Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 19, 2026

The existing "privy" wallet provider (Privy EOA + Safe smart account) is renamed to "safe". A new "privy" provider is added that creates only a Privy EOA without Safe deployment. x402 skills now validate and reject "safe" mode since Safe's contract-based transactions are incompatible with x402's direct signing requirements.

Changes

Wallet Provider Enum

  • "privy""safe" (Privy EOA + Safe smart account, supports spending limits)
  • New "privy" (Privy EOA only, no Safe, direct signing)

Agent Wallet Creation (core/agent.py)

  • "safe" mode: Creates Privy wallet → deploys Safe → uses Safe address as evm_wallet_address
  • "privy" mode: Creates Privy wallet → uses Privy address directly as evm_wallet_address

User Wallet Creation (core/user.py)

  • Added mode parameter to create_user_server_wallet() supporting both "safe" and "privy"

x402 Skills (skills/x402/base.py)

def _validate_wallet_provider(self) -> None:
    if agent.wallet_provider == "safe":
        raise ValueError(
            "x402 operations are not supported with 'safe' wallet provider. "
            "Safe wallets use smart contract transactions which are incompatible "
            "with x402 direct signing requirements."
        )

Client Adapters (clients/__init__.py)

  • Updated get_wallet_provider() and get_wallet_signer() to handle both "safe" and "privy"

Tests

  • Updated test fixtures from wallet_provider="privy" to wallet_provider="safe"
Original prompt

现在的 wallet provider 枚举中,我们需要把 privy 改成 safe。这只是一个名字变动。另外,在这种 safe 模式下,x402 skill 请直接抛出异常,我们已经证明这种模式不支持 x402 交互。

然后,我们新增一个 privy,这个 privy 只创建 privy wallet,和现在的流程类似,只是不再创建 safe wallet。直接使用 privy wallet 填写到 evm_wallet_address 字段。user server wallet 也用同样的规则。

这个任务不需要考虑历史数据,即使是 safe wallet 模式目前还无生产数据。


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits January 19, 2026 05:42
Co-authored-by: hyacinthus <488292+hyacinthus@users.noreply.github.com>
…iders

Co-authored-by: hyacinthus <488292+hyacinthus@users.noreply.github.com>
Copilot AI changed the title [WIP] Rename privy to safe in wallet provider enum Refactor wallet provider enum: rename privy→safe, add new privy-only mode Jan 19, 2026
Copilot AI requested a review from hyacinthus January 19, 2026 05:47
@hyacinthus hyacinthus marked this pull request as ready for review January 19, 2026 13:42
Copilot AI review requested due to automatic review settings January 19, 2026 13:42
@hyacinthus hyacinthus merged commit 680b54e into main Jan 19, 2026
5 of 6 checks passed
@hyacinthus hyacinthus deleted the copilot/update-wallet-provider-enum branch January 19, 2026 13:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the wallet provider enumeration to clarify the distinction between Privy EOA-only wallets and Privy+Safe smart account wallets. The existing "privy" provider (which created a Privy EOA with a Safe smart account) is renamed to "safe", and a new "privy" provider is introduced that creates only a Privy EOA without deploying a Safe contract. Additionally, x402 skills now validate and reject "safe" mode since Safe's contract-based transactions are incompatible with x402's direct signing requirements.

Changes:

  • Wallet provider enum updated: "privy" renamed to "safe", new "privy" mode added for EOA-only wallets
  • Agent and user wallet creation logic modified to support both "safe" (Privy+Safe) and "privy" (EOA-only) modes
  • x402 skills now validate and reject "safe" wallet provider due to incompatibility with direct signing

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
intentkit/models/agent.py Updated wallet_provider enum to include "safe" and "privy", updated comments to reflect spending limits are for "safe" mode
frontend/src/types/agent.ts Updated TypeScript type definition to include "safe" in wallet_provider union type
intentkit/core/agent.py Renamed "privy" mode to "safe" for Safe wallet creation, added new "privy" mode for EOA-only wallet creation, updated spending limit sync logic
intentkit/core/user.py Added mode parameter to support both "safe" and "privy" wallet creation for user server wallets
intentkit/clients/init.py Updated wallet provider and signer adapters to handle both "safe" and "privy" modes
intentkit/skills/x402/base.py Added validation to reject "safe" wallet provider since Safe transactions are incompatible with x402 direct signing
intentkit/skills/onchain.py Updated is_onchain_capable to include both "safe" and "privy" as valid on-chain providers
tests/skills/test_unified_wallet.py Updated test from "privy" to "safe" provider
tests/core/test_privy_spending_limit_sync.py Updated tests from "privy" to "safe" provider
tests/core/test_privy_owner_validation.py Updated test from "privy" to "safe" provider
Comments suppressed due to low confidence (2)

intentkit/models/agent.py:832

  • This import of module re is redundant, as it was previously imported on line 6.
        import re

intentkit/models/agent.py:1987

  • This import of module hashlib is redundant, as it was previously imported on line 3.
        import hashlib

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +107 to +159
if current_wallet_provider in ("safe", "privy") and old_limit != new_limit:
agent_data = await AgentData.get(agent.id)
if agent_data.privy_wallet_data:
from intentkit.clients.privy import create_privy_safe_wallet

try:
privy_wallet_data = json.loads(agent_data.privy_wallet_data)
except json.JSONDecodeError:
privy_wallet_data = {}

existing_privy_wallet_id = privy_wallet_data.get("privy_wallet_id")
existing_privy_wallet_address = privy_wallet_data.get(
"privy_wallet_address"
)

if existing_privy_wallet_id and existing_privy_wallet_address:
rpc_url: str | None = None
network_id = (
agent.network_id
or privy_wallet_data.get("network_id")
or "base-mainnet"
)
if config.chain_provider:
try:
chain_config = config.chain_provider.get_chain_config(
network_id
)
rpc_url = chain_config.rpc_url
except Exception as e:
logger.warning(
f"Failed to get RPC URL from chain provider: {e}"
)

wallet_data = await create_privy_safe_wallet(
agent_id=agent.id,
network_id=network_id,
rpc_url=rpc_url,
weekly_spending_limit_usdc=agent.weekly_spending_limit
if agent.weekly_spending_limit is not None
else 0.0,
existing_privy_wallet_id=existing_privy_wallet_id,
existing_privy_wallet_address=existing_privy_wallet_address,
)
agent_data = await AgentData.patch(
agent.id,
{
"evm_wallet_address": wallet_data["smart_wallet_address"],
"privy_wallet_data": json.dumps(wallet_data),
},
# Only safe mode supports spending limits
if current_wallet_provider == "safe":
from intentkit.clients.privy import create_privy_safe_wallet

try:
privy_wallet_data = json.loads(agent_data.privy_wallet_data)
except json.JSONDecodeError:
privy_wallet_data = {}

existing_privy_wallet_id = privy_wallet_data.get("privy_wallet_id")
existing_privy_wallet_address = privy_wallet_data.get(
"privy_wallet_address"
)
return agent_data

if existing_privy_wallet_id and existing_privy_wallet_address:
rpc_url: str | None = None
network_id = (
agent.network_id
or privy_wallet_data.get("network_id")
or "base-mainnet"
)
if config.chain_provider:
try:
chain_config = config.chain_provider.get_chain_config(
network_id
)
rpc_url = chain_config.rpc_url
except Exception as e:
logger.warning(
f"Failed to get RPC URL from chain provider: {e}"
)

wallet_data = await create_privy_safe_wallet(
agent_id=agent.id,
network_id=network_id,
rpc_url=rpc_url,
weekly_spending_limit_usdc=agent.weekly_spending_limit
if agent.weekly_spending_limit is not None
else 0.0,
existing_privy_wallet_id=existing_privy_wallet_id,
existing_privy_wallet_address=existing_privy_wallet_address,
)
agent_data = await AgentData.patch(
agent.id,
{
"evm_wallet_address": wallet_data["smart_wallet_address"],
"privy_wallet_data": json.dumps(wallet_data),
},
)
return agent_data
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spending limit sync logic at line 107 checks if the wallet provider is "safe" or "privy" and if the spending limit changed. However, it only processes spending limit updates for "safe" mode (line 111). This means that when a user with a "privy" wallet (new privy-only mode) tries to change their spending limit, the code will enter the if block at line 107, but then skip the actual update logic since current_wallet_provider != "safe".

This behavior might be intentional (since privy-only mode doesn't support spending limits according to the PR description). However, it would be better to either:

  1. Not enter this code path at all for privy mode (change line 107 to only check for "safe")
  2. Add an explicit check/warning that spending limits are not supported for privy-only mode

Copilot uses AI. Check for mistakes.
raise ValueError(
"x402 operations are not supported with 'safe' wallet provider. "
"Safe wallets use smart contract transactions which are incompatible "
"with x402 direct signing requirements. Please use 'privy' or 'cdp' wallet provider instead."
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message suggests using 'privy' or 'cdp' wallet provider as alternatives to 'safe'. However, in the context of x402 operations, only the new "privy" mode (privy-only, no Safe) is actually compatible with x402's direct signing requirements. The suggestion to use "cdp" is appropriate, but the message could be clearer that "privy" here refers to the privy-only mode, not the old privy+Safe mode (which is now called "safe").

Suggested change
"with x402 direct signing requirements. Please use 'privy' or 'cdp' wallet provider instead."
"with x402 direct signing requirements. Please use the privy-only "
"wallet provider ('privy', without Safe) or 'cdp' instead; the old "
"Privy+Safe configuration is now called 'safe' and remains unsupported."

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants