Skip to main content
Glama

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
NameRequiredDescriptionDefault
wallet_idYesWallet ID
tokenYesERC-20 token contract address
spenderYesContract address to approve as spender
amountYesAmount to approve in human-readable format (e.g. "1000"), or "max" for unlimited
chain_idYesChain ID
decimalsNoToken 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,
        });
      },
    );
  • 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)'),
    },
  • 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,
      });
    },
  • 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');
    }
  • 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');
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hifriendbot/agentwallet-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server