Skip to main content
Glama

build_userop

Constructs unsigned ERC-4337 UserOperations from transaction requests for smart account wallets, enabling gas and paymaster field completion before signing.

Instructions

Build an unsigned ERC-4337 UserOperation from a transaction request. Returns sender, nonce, callData, buildId. Platform fills gas/paymaster fields before signing.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
wallet_idYesSmart Account wallet ID (UUID).
typeYesTransaction type.
toNoRecipient address.
amountNoAmount in smallest units (wei). Example: "1000000000000000000" = 1 ETH, "1000000" = 1 USDC
tokenNoToken contract address (for TOKEN_TRANSFER/APPROVE).
contractNoContract address (for CONTRACT_CALL).
methodNoContract method name (for CONTRACT_CALL).
abiNoContract ABI (for CONTRACT_CALL).
argsNoContract method args (for CONTRACT_CALL).
callsNoBatch calls (for BATCH type).
networkYesEVM network (e.g., "ethereum-sepolia").

Implementation Reference

  • The handler function for the `build_userop` tool which constructs a POST request to the `/v1/wallets/:id/userop/build` endpoint.
        async (args) => {
          const request: Record<string, unknown> = { type: args.type };
          if (args.to) request.to = args.to;
          if (args.amount) request.amount = args.amount;
          if (args.token) request.token = args.token;
          if (args.contract) request.contract = args.contract;
          if (args.method) request.method = args.method;
          if (args.abi) request.abi = args.abi;
          if (args.args) request.args = args.args;
          if (args.calls) request.calls = args.calls;
          const body = { request, network: args.network };
          const result = await apiClient.post(
            `/v1/wallets/${args.wallet_id}/userop/build`,
            body,
          );
          return toToolResult(result);
        },
      );
    }
  • Input schema validation for the `build_userop` tool using Zod.
    {
      wallet_id: z.string().describe('Smart Account wallet ID (UUID).'),
      type: z.enum(['TRANSFER', 'TOKEN_TRANSFER', 'CONTRACT_CALL', 'APPROVE', 'BATCH']).describe('Transaction type.'),
      to: z.string().optional().describe('Recipient address.'),
      amount: z.string().optional().describe('Amount in smallest units (wei). Example: "1000000000000000000" = 1 ETH, "1000000" = 1 USDC'),
      token: z.string().optional().describe('Token contract address (for TOKEN_TRANSFER/APPROVE).'),
      contract: z.string().optional().describe('Contract address (for CONTRACT_CALL).'),
      method: z.string().optional().describe('Contract method name (for CONTRACT_CALL).'),
      abi: z.array(z.unknown()).optional().describe('Contract ABI (for CONTRACT_CALL).'),
      args: z.array(z.unknown()).optional().describe('Contract method args (for CONTRACT_CALL).'),
      calls: z.array(z.object({ to: z.string(), amount: z.string().optional().describe('Amount in smallest units (wei)'), data: z.string().optional() })).optional().describe('Batch calls (for BATCH type).'),
      network: z.string().describe('EVM network (e.g., "ethereum-sepolia").'),
    },
  • Registration function `registerBuildUserop` for the `build_userop` tool.
    export function registerBuildUserop(
      server: McpServer,
      apiClient: ApiClient,
      walletContext?: WalletContext,
    ): void {
      server.tool(
        'build_userop',
        withWalletPrefix(
          'Build an unsigned ERC-4337 UserOperation from a transaction request. Returns sender, nonce, callData, buildId. Platform fills gas/paymaster fields before signing.',
          walletContext?.walletName,
        ),
        {
          wallet_id: z.string().describe('Smart Account wallet ID (UUID).'),
          type: z.enum(['TRANSFER', 'TOKEN_TRANSFER', 'CONTRACT_CALL', 'APPROVE', 'BATCH']).describe('Transaction type.'),
          to: z.string().optional().describe('Recipient address.'),
          amount: z.string().optional().describe('Amount in smallest units (wei). Example: "1000000000000000000" = 1 ETH, "1000000" = 1 USDC'),
          token: z.string().optional().describe('Token contract address (for TOKEN_TRANSFER/APPROVE).'),
          contract: z.string().optional().describe('Contract address (for CONTRACT_CALL).'),
          method: z.string().optional().describe('Contract method name (for CONTRACT_CALL).'),
          abi: z.array(z.unknown()).optional().describe('Contract ABI (for CONTRACT_CALL).'),
          args: z.array(z.unknown()).optional().describe('Contract method args (for CONTRACT_CALL).'),
          calls: z.array(z.object({ to: z.string(), amount: z.string().optional().describe('Amount in smallest units (wei)'), data: z.string().optional() })).optional().describe('Batch calls (for BATCH type).'),
          network: z.string().describe('EVM network (e.g., "ethereum-sepolia").'),
        },
        async (args) => {
          const request: Record<string, unknown> = { type: args.type };
          if (args.to) request.to = args.to;
          if (args.amount) request.amount = args.amount;
          if (args.token) request.token = args.token;
          if (args.contract) request.contract = args.contract;
          if (args.method) request.method = args.method;
          if (args.abi) request.abi = args.abi;
          if (args.args) request.args = args.args;
          if (args.calls) request.calls = args.calls;
          const body = { request, network: args.network };
          const result = await apiClient.post(
            `/v1/wallets/${args.wallet_id}/userop/build`,
            body,
          );
          return toToolResult(result);
        },
      );
    }

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/minhoyoo-iotrust/WAIaaS'

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