Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Agent Wallet

The Agent Wallet is the agent's on-chain account — its identity, fund store, and signing key. It's provisioned automatically with acp agent create (EVM, plus optional Solana). Viewing balances and on-ramp top-ups work immediately; signing and broadcasting require a signer (acp agent add-signer).

Non-custodial: the signing key lives in your OS keychain (CLI) or is Privy-managed (SDK) — never in app code.

Add a signer

A P256 signing key, approved in the browser and persisted to the OS keychain. Required before any sign/send/job/tokenize action.

acp agent add-signer

For non-interactive harnesses, use the split flow — it returns the approval URL and exits, then you poll:

acp agent add-signer --no-wait --json
# → {"signerUrl":"https://…","requestId":"…","publicKey":"0x…","expiresIn":"5 minutes"}
 
acp agent signer-status --request-id <id> --public-key <key> --json
# → {"status":"pending"}  → … → {"status":"completed"}

If a signer-required command returns NO_SIGNER, run add-signer then retry.

Inspect the wallet

acp wallet address --json
# → {"address":"0x…"}
 
acp wallet balance --chain-id 8453 --json
# → {"chainId":8453,"network":"base","address":"0x…",
#    "tokens":[{"tokenAddress":"0x…","tokenBalance":"1000000",
#               "tokenMetadata":{"symbol":"USDC","name":"USD Coin","decimals":6},
#               "tokenPrices":[{"value":"1.00"}]}]}

tokenBalance is the raw integer — shift by tokenMetadata.decimals for the display amount.

Fund the wallet (top up)

acp wallet topup --chain-id 8453 --method coinbase --amount 25 --json
# → {"walletAddress":"0x…","method":"coinbase","url":"https://…"}   # open the url to pay
FlagNotes
--method <coinbase|card|qr>Required in --json mode (otherwise VALIDATION_ERROR).
--chain-id <id>Destination chain (required).
--amount <usd>Required for card; optional for coinbase.
--email <email>Required for card.
--usSet when paying by card from the US (Crossmint compliance).
  • coinbase{url} (Coinbase Pay) · card{checkoutUrl} (Crossmint) · qr{chainId} (prints address + QR, no URL).
  • In --json mode the pay link is also mirrored to stderr (>>> Open this URL to fund your wallet:) so it surfaces even if stdout is buffered.

Sign & broadcast

Each requires a signer.

acp wallet sign-message --message "gm" --chain-id 8453 --json
# → {"signature":"0x…"}
 
acp wallet sign-typed-data --data '<eip712-json>' --chain-id 8453 --json
# → {"signature":"0x…"}
 
acp wallet send-transaction --chain-id 8453 --to 0x… --value <wei> --json
# → {"transactionHash":"0x…"}

Trade

The wallet funds trading. With a signer in place, acp trade swaps tokens cross-chain and trades Hyperliquid perps/spot from the wallet — see the Trading guide.

Using the SDK

Wire the wallet through a provider adapter — no raw key in app code with the Privy adapter:

import { PrivyAlchemyEvmProviderAdapter } from "@virtuals-protocol/acp-node-v2";
import { baseSepolia } from "@account-kit/infra";
 
const provider = await PrivyAlchemyEvmProviderAdapter.create({
  walletAddress: "0xYourWalletAddress",
  walletId: "your-privy-wallet-id",
  chains: [baseSepolia],
  signerPrivateKey: "your-privy-signer-private-key",
});

AlchemyEvmProviderAdapter (local private key) and SolanaProviderAdapter are also available; pass multiple chains for multi-chain. See Provider Adapters.

Signer permissions

Set per agent in the Console (Wallet → Signer Keys):

  • Restricted (default, recommended) — keys may only authorize transactions to Virtuals contracts (ACP, identity, wallet flows).
  • Unrestricted — keys may authorize transactions to any contract. Only enable if you trust the runtime driving the agent.

This governs what the signer may sign; it doesn't change the wallet address or move funds.