Skip to content
Skip to content

Agent Wallet Management

Balchemy provides two distinct wallet models depending on which product surface you are using. Studio users connect and manage their own wallets. Hub external agents receive a Balchemy-managed custodial wallet created automatically during onboarding.

What you'll learn

  • The difference between Studio wallets and Hub custodial wallets
  • How to fund, check, and withdraw from an agent custodial wallet
  • Supported chains and token approvals (ERC-20 approve / revoke)
  • Security model for custodial key storage

Studio wallets vs Hub custodial wallets

StudioHub (custodial)
Who controls the keysThe user — keys never leave their walletBalchemy — AES-256-GCM encrypted on server
CreationUser connects an existing walletAuto-created during agent onboarding
FundingUser deposits to their own walletOperator or external sender deposits to the agent address
ChainsSolana + EVM (user-choice)Solana + EVM / Base (chain ID 8453)
WithdrawalsUser signs from their walletRequires manage scope + step-up token
VisibilityIn Studio wallets pageIn Hub agent detail page (/hub/agents/[agentId])

The right wallet model depends on who initiates trades. Studio wallets are for human operators running personal bots. Hub custodial wallets are for autonomous agents operating on behalf of an operator without needing the operator to sign every transaction.


Quick start

Complete these steps to get an agent wallet funded and ready to trade.

1. Discover the agent

Onboard the agent at /hub/agents/new. The success screen returns the custodial wallet address alongside the MCP API key and endpoint.

2. Copy the wallet address

The custodial wallet address is displayed on the discovery success screen and on the agent detail page under Principal > Funding Wallet. Copy it from either location.

3. Fund the wallet

Send SOL or ETH to the address from any external source. There is no minimum deposit enforced by the platform; the trading engine's pre-trade checks will block orders that exceed available balance.

4. Verify the balance

Check current balances from the Hub Dashboard wallet card or via the API:

curl https://api.balchemy.ai/api/nest/agents/wallet/balance \
  -H "Authorization: Bearer YOUR_JWT"

5. Execute trades

Once funded, the agent can call trading tools through MCP. Balance is debited automatically when orders execute.


Checking the wallet balance

The Hub Dashboard shows a compact wallet card with SOL and EVM/Base balances. Balances update on each page load. You can also fetch them programmatically:

# Using the agent JWT
curl https://api.balchemy.ai/api/nest/agents/wallet/balance \
  -H "Authorization: Bearer YOUR_AGENT_JWT"

The response shape:

{
  "sol": "2.451",
  "evm": "0.018"
}

Both values are string-formatted to avoid floating-point precision issues in JSON.


Funding the wallet

Send funds directly to the agent's custodial wallet address. Balchemy does not impose any restrictions on who can send funds to the address — it is a standard on-chain address.

ChainTokenNotes
SolanaSOLNative; used for gas and as collateral
SolanaSPL tokensUSDC, USDT, and other supported mints
EVM / BaseETHNative; used for gas
EVM / BaseERC-20USDC and other approved tokens

ERC-20 tokens on EVM require a token approval before they can be used in trades. See the Token Approvals section below.


Withdrawals

Withdrawals move funds from the agent's custodial wallet to any external address. They require manage scope and an active step-up token. Withdrawals are available from:

  • The Agent Wallet card on /hub (quick withdrawal for the global agent wallet)
  • The Agent Detail page at /hub/agents/[agentId] (per-agent withdrawal actions under the wallet section)

Withdraw via API

# Solana withdrawal
curl -X POST https://api.balchemy.ai/api/nest/agents/wallet/withdraw/solana \
  -H "Authorization: Bearer YOUR_MANAGE_SCOPED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "toAddress": "YOUR_SOLANA_WALLET_ADDRESS",
    "amount": "1.5"
  }'
 
# EVM withdrawal
curl -X POST https://api.balchemy.ai/api/nest/agents/wallet/withdraw/evm \
  -H "Authorization: Bearer YOUR_MANAGE_SCOPED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "toAddress": "0xYOUR_EVM_ADDRESS",
    "amount": "0.01"
  }'

Both endpoints require a valid destination address for the respective chain. Solana addresses are base58-encoded public keys; EVM addresses are 0x-prefixed hex strings.


Token approvals (EVM)

Before an EVM agent can trade an ERC-20 token, it must have an active approval for that token mint with the trading router. Approvals are managed through wallet tools.

Check existing approvals

curl https://api.balchemy.ai/api/nest/bots/BOTID/trading/wallet/approvals?wallet_index=0 \
  -H "Authorization: Bearer YOUR_TRADE_SCOPED_KEY"

Approve a token

curl -X POST https://api.balchemy.ai/api/nest/bots/BOTID/trading/wallet/approve \
  -H "Authorization: Bearer YOUR_TRADE_SCOPED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "approval": {
      "walletIndex": 0,
      "tokenAddress": "0xUSERS_TOKEN_CONTRACT",
      "amount": "1000000000"
    }
  }'

Revoke a token approval

curl -X POST https://api.balchemy.ai/api/nest/bots/BOTID/trading/wallet/revoke \
  -H "Authorization: Bearer YOUR_TRADE_SCOPED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "revoke": {
      "walletIndex": 0,
      "tokenAddress": "0xUSERS_TOKEN_CONTRACT"
    }
  }'

Revoking an approval prevents the trading engine from using that token in future swaps. Existing open orders for that token will fail if they settle after revocation.


Default order profile

Each agent can have a default order profile that pre-fills trade parameters when no explicit values are provided. The profile stores amount, unit, slippage, stop-loss, and take-profit targets.

Get the current profile

curl https://api.balchemy.ai/api/nest/bots/BOTID/trading/wallet/order-profile \
  -H "Authorization: Bearer YOUR_READ_SCOPED_KEY"

Update the profile

curl -X PATCH https://api.balchemy.ai/api/nest/bots/BOTID/trading/wallet/order-profile \
  -H "Authorization: Bearer YOUR_TRADE_SCOPED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 10,
    "amountUnit": "USDC",
    "slippageBps": 50,
    "stopLossPercent": 5,
    "autoApprove": true
  }'

Default order profile fields

FieldTypeRequiredDescription
amountnumberYesTrade size in the selected unit
amountUnit"SOL" | "USDC" | "USD"NoDefault: "SOL"
slippageBpsnumberNoSlippage tolerance in basis points
networkFeeLamportsnumberNoSolana priority fee in lamports
trailingStopPercentnumberNoTrailing stop percentage
stopLossPercentnumberNoHard stop-loss percentage
takeProfitTargetsarrayNoArray of { percent, portion } targets
dcaLegsarrayNoDCA schedule legs
autoApprovebooleanNoSkip confirmation for trade orders
maxLossPercentnumberNoMaximum allowed loss before halt
maxPositionSizenumberNoMaximum single position size
namestringNoHuman-readable profile name

Security model

Custodial wallet keys are stored using AES-256-GCM encryption with a data encryption key (DEK) envelope. The DEK is encrypted by a key encryption key (KEK) held either in a local secure store or in AWS KMS, depending on the deployment environment.

Key security properties:

  • Private keys are never transmitted to clients or logged
  • All wallet mutations go through the authorized execution layer — no direct key access from controllers
  • Trading operations go through pre-trade security checks before any on-chain transaction
  • Withdrawals require manage scope, which requires claim + step-up authentication
  • The step-up token is valid for 5 minutes from issuance

The custodial model is designed for agents that need to operate autonomously without requiring a human to sign each trade. If you need non-custodial trading with a user-controlled wallet, use Studio instead.


Wallet tool reference

The wallet category exposes 14 tools through MCP. All read-only tools require read scope; mutation tools require trade scope; withdrawal configuration requires manage scope.

Tool nameScopeDescription
trading_wallet_listreadList all connected wallets
trading_wallet_defaultreadGet the current default wallet
trading_wallet_verification_messagereadGenerate a wallet connect verification message
trading_wallet_connecttradeConnect a wallet via signature verification
trading_wallet_platform_delegatereadGet the platform delegate public key
trading_wallet_set_defaulttradeSet a wallet as default by index
trading_wallet_approvalsreadList token approvals for a wallet
trading_wallet_has_approvalreadCheck if a specific token is approved
trading_wallet_approve_tokentradeApprove a token for trading
trading_wallet_revoke_tokentradeRevoke a token approval
trading_wallet_custodial_getreadGet custodial wallet info and address
trading_wallet_custodial_ensuretradeEnsure the custodial wallet exists
trading_wallet_default_order_profile_getreadGet the default order profile
trading_wallet_default_order_profile_updatetradeUpdate the default order profile

Error handling

ErrorCauseResolution
403 Forbidden — manage scope requiredAttempting a withdrawal without manage scopeClaim the agent and use a manage-scoped key
403 Forbidden — step-up requiredmanage action without a valid step-up tokenIssue a step-up token from the agent detail control plane at /hub/agents/[agentId]
400 — amount is requiredMissing amount field in order profile updateInclude a numeric amount in the request body
400 — wallet_index and token_mint requiredMissing fields for approval checkProvide both wallet_index (number) and token_mint (string)
404 — custodial wallet not readyBackend still preparing the walletWait 30–60 seconds and retry
Insufficient balanceTrade size exceeds available balanceFund the wallet or reduce the trade size

Connection lost. Retrying...