approve_token
Authorize smart contracts to transfer your ERC-20 tokens for DeFi interactions like trading or lending. Specify exact amounts or grant unlimited approval.
Instructions
Approve a spender contract to transfer ERC-20 tokens on your behalf. Required before interacting with any DeFi protocol (DEXs, lending, etc.). Use amount "max" for unlimited approval, or specify an exact amount.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| wallet_id | Yes | Wallet ID | |
| token | Yes | ERC-20 token contract address | |
| spender | Yes | Contract address to approve as spender | |
| amount | Yes | Amount to approve in human-readable format (e.g. "1000"), or "max" for unlimited | |
| chain_id | Yes | Chain ID | |
| decimals | No | Token decimals (6 for USDC, 18 for most tokens) |
Implementation Reference
- src/index.ts:677-717 (registration)Registration of the 'approve_token' tool using server.tool() with the tool name, description, zod schema for input validation, and async handler function
server.tool( 'approve_token', 'Approve a spender contract to transfer ERC-20 tokens on your behalf. ' + 'Required before interacting with any DeFi protocol (DEXs, lending, etc.). ' + 'Use amount "max" for unlimited approval, or specify an exact amount.', { wallet_id: z.number().int().describe('Wallet ID'), token: z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe('ERC-20 token contract address'), spender: z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe('Contract address to approve as spender'), amount: z.string().describe('Amount to approve in human-readable format (e.g. "1000"), or "max" for unlimited'), chain_id: z.number().int().describe('Chain ID'), decimals: z.number().int().default(18).describe('Token decimals (6 for USDC, 18 for most tokens)'), }, async ({ wallet_id, token, spender, amount, chain_id, decimals }) => { if (isSolanaChain(chain_id)) { throw new Error('approve_token is not supported on Solana. Solana SPL tokens do not use ERC-20 style approvals.'); } // approve(address spender, uint256 amount) — selector: 0x095ea7b3 let rawAmount: string; if (amount.toLowerCase() === 'max') { rawAmount = (BigInt(2) ** BigInt(256) - BigInt(1)).toString(); } else { rawAmount = parseUnits(amount, decimals); } const calldata = '0x095ea7b3' + padAddress(spender) + encodeUint256(rawAmount); const result = await api(`/wallets/${wallet_id}/send`, 'POST', { to: token, value: '0', data: calldata, chain_id, }); return jsonResponse({ ...(result as Record<string, unknown>), token, spender, amount: amount.toLowerCase() === 'max' ? 'unlimited' : amount, }); }, ); - src/index.ts:682-689 (schema)Zod schema definition for approve_token inputs: wallet_id, token (ERC-20 address), spender (contract address), amount (human-readable or 'max'), chain_id, and decimals
{ wallet_id: z.number().int().describe('Wallet ID'), token: z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe('ERC-20 token contract address'), spender: z.string().regex(/^0x[a-fA-F0-9]{40}$/).describe('Contract address to approve as spender'), amount: z.string().describe('Amount to approve in human-readable format (e.g. "1000"), or "max" for unlimited'), chain_id: z.number().int().describe('Chain ID'), decimals: z.number().int().default(18).describe('Token decimals (6 for USDC, 18 for most tokens)'), }, - src/index.ts:690-716 (handler)Handler function for approve_token: validates chain (not Solana), converts amount to raw units (handling 'max' for unlimited approval), builds ERC-20 approve(address,uint256) calldata with selector 0x095ea7b3, sends transaction via API, and returns result
async ({ wallet_id, token, spender, amount, chain_id, decimals }) => { if (isSolanaChain(chain_id)) { throw new Error('approve_token is not supported on Solana. Solana SPL tokens do not use ERC-20 style approvals.'); } // approve(address spender, uint256 amount) — selector: 0x095ea7b3 let rawAmount: string; if (amount.toLowerCase() === 'max') { rawAmount = (BigInt(2) ** BigInt(256) - BigInt(1)).toString(); } else { rawAmount = parseUnits(amount, decimals); } const calldata = '0x095ea7b3' + padAddress(spender) + encodeUint256(rawAmount); const result = await api(`/wallets/${wallet_id}/send`, 'POST', { to: token, value: '0', data: calldata, chain_id, }); return jsonResponse({ ...(result as Record<string, unknown>), token, spender, amount: amount.toLowerCase() === 'max' ? 'unlimited' : amount, }); }, - src/index.ts:218-220 (helper)padAddress helper function that pads an address to 32 bytes (64 hex chars) for ABI encoding, used in approve_token calldata construction
function padAddress(address: string): string { return address.slice(2).toLowerCase().padStart(64, '0'); } - src/index.ts:225-228 (helper)encodeUint256 helper function that encodes a uint256 as 32 bytes hex (64 chars), used in approve_token calldata construction
function encodeUint256(value: string): string { const hex = BigInt(value).toString(16); return hex.padStart(64, '0'); }