Skip to main content
Glama

sign_userop

Sign a completed UserOperation with gas and paymaster fields to authorize blockchain transactions from smart accounts, returning a signed operation with signature and transaction ID for tracking.

Instructions

Sign a completed UserOperation (with gas/paymaster fields). Returns signed UserOperation with signature and txId for tracking.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
wallet_idYesSmart Account wallet ID (UUID).
build_idYesBuild ID from build_userop response.
senderYesSmart Account address (0x hex).
nonceYesAccount nonce (0x hex).
call_dataYesEncoded call data (0x hex).
call_gas_limitYesGas limit for call execution (0x hex).
verification_gas_limitYesGas limit for verification (0x hex).
pre_verification_gasYesPre-verification gas (0x hex).
max_fee_per_gasYesMax fee per gas (0x hex).
max_priority_fee_per_gasYesMax priority fee per gas (0x hex).
signatureNoPlaceholder signature (0x hex). Default: 0x.
factoryNoFactory address for undeployed accounts.
factory_dataNoFactory data for undeployed accounts.
paymasterNoPaymaster address.
paymaster_dataNoPaymaster data.
paymaster_verification_gas_limitNoPaymaster verification gas limit.
paymaster_post_op_gas_limitNoPaymaster post-op gas limit.

Implementation Reference

  • Tool registration and handler implementation for sign_userop.
    export function registerSignUserop(
      server: McpServer,
      apiClient: ApiClient,
      walletContext?: WalletContext,
    ): void {
      server.tool(
        'sign_userop',
        withWalletPrefix(
          'Sign a completed UserOperation (with gas/paymaster fields). Returns signed UserOperation with signature and txId for tracking.',
          walletContext?.walletName,
        ),
        {
          wallet_id: z.string().describe('Smart Account wallet ID (UUID).'),
          build_id: z.string().describe('Build ID from build_userop response.'),
          sender: z.string().describe('Smart Account address (0x hex).'),
          nonce: z.string().describe('Account nonce (0x hex).'),
          call_data: z.string().describe('Encoded call data (0x hex).'),
          call_gas_limit: z.string().describe('Gas limit for call execution (0x hex).'),
          verification_gas_limit: z.string().describe('Gas limit for verification (0x hex).'),
          pre_verification_gas: z.string().describe('Pre-verification gas (0x hex).'),
          max_fee_per_gas: z.string().describe('Max fee per gas (0x hex).'),
          max_priority_fee_per_gas: z.string().describe('Max priority fee per gas (0x hex).'),
          signature: z.string().optional().describe('Placeholder signature (0x hex). Default: 0x.'),
          factory: z.string().optional().describe('Factory address for undeployed accounts.'),
          factory_data: z.string().optional().describe('Factory data for undeployed accounts.'),
          paymaster: z.string().optional().describe('Paymaster address.'),
          paymaster_data: z.string().optional().describe('Paymaster data.'),
          paymaster_verification_gas_limit: z.string().optional().describe('Paymaster verification gas limit.'),
          paymaster_post_op_gas_limit: z.string().optional().describe('Paymaster post-op gas limit.'),
        },
        async (args) => {
          const userOperation: Record<string, unknown> = {
            sender: args.sender,
            nonce: args.nonce,
            callData: args.call_data,
            callGasLimit: args.call_gas_limit,
            verificationGasLimit: args.verification_gas_limit,
            preVerificationGas: args.pre_verification_gas,
            maxFeePerGas: args.max_fee_per_gas,
            maxPriorityFeePerGas: args.max_priority_fee_per_gas,
            signature: args.signature ?? '0x',
          };
          if (args.factory) userOperation.factory = args.factory;
          if (args.factory_data) userOperation.factoryData = args.factory_data;
          if (args.paymaster) userOperation.paymaster = args.paymaster;
          if (args.paymaster_data) userOperation.paymasterData = args.paymaster_data;
          if (args.paymaster_verification_gas_limit) userOperation.paymasterVerificationGasLimit = args.paymaster_verification_gas_limit;
          if (args.paymaster_post_op_gas_limit) userOperation.paymasterPostOpGasLimit = args.paymaster_post_op_gas_limit;
          const body = { buildId: args.build_id, userOperation };
          const result = await apiClient.post(
            `/v1/wallets/${args.wallet_id}/userop/sign`,
            body,
          );
          return toToolResult(result);
        },
      );
    }
  • Handler logic for sign_userop tool which maps arguments to a request body and sends it to the API.
    async (args) => {
      const userOperation: Record<string, unknown> = {
        sender: args.sender,
        nonce: args.nonce,
        callData: args.call_data,
        callGasLimit: args.call_gas_limit,
        verificationGasLimit: args.verification_gas_limit,
        preVerificationGas: args.pre_verification_gas,
        maxFeePerGas: args.max_fee_per_gas,
        maxPriorityFeePerGas: args.max_priority_fee_per_gas,
        signature: args.signature ?? '0x',
      };
      if (args.factory) userOperation.factory = args.factory;
      if (args.factory_data) userOperation.factoryData = args.factory_data;
      if (args.paymaster) userOperation.paymaster = args.paymaster;
      if (args.paymaster_data) userOperation.paymasterData = args.paymaster_data;
      if (args.paymaster_verification_gas_limit) userOperation.paymasterVerificationGasLimit = args.paymaster_verification_gas_limit;
      if (args.paymaster_post_op_gas_limit) userOperation.paymasterPostOpGasLimit = args.paymaster_post_op_gas_limit;
      const body = { buildId: args.build_id, userOperation };
      const result = await apiClient.post(
        `/v1/wallets/${args.wallet_id}/userop/sign`,
        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