clawallex_pay
Process payments using USDC by generating virtual cards for online checkouts, with options for wallet-based or on-chain self-custody transactions.
Instructions
Pay for a product or service using USDC. Creates a single-use flash virtual card (card_type=100), deducts from wallet balance, returns card details for checkout.
Mode A (mode_code=100, default): wallet balance → flash card. Immediate settlement. Mode B (mode_code=200): for callers with self-custody wallets — signing is performed by the caller. x402 on-chain two-stage flow: Stage 1 (Quote): POST with mode_code=200, chain_code, token_code. The 402 response is EXPECTED — it is a quote, NOT an error. Returns: card_order_id, client_request_id, x402_reference_id, payee_address, asset_address, final_card_amount, issue_fee_amount, fx_fee_amount, fee_amount, payable_amount. Agent signs: construct and sign an EIP-3009 transferWithAuthorization using your own wallet/signing library. Stage 2 requires the resulting signature and your wallet address (authorization.from). authorization fields: from=your wallet address, to=payee_address, value=maxAmountRequired, validAfter/validBefore=unix seconds validity window, nonce=random 32-byte hex (unique per auth). Stage 2 (Settle): POST again with SAME client_request_id + signed x402 data: - payment_requirements.payTo MUST equal payee_address from Stage 1 - payment_requirements.asset MUST equal asset_address from Stage 1 - payment_requirements.maxAmountRequired MUST equal payable_amount × 10^decimals (USDC = 6 decimals, e.g. '207.59' → '207590000') - payment_requirements.extra.referenceId MUST equal x402_reference_id from Stage 1 - extra.card_amount MUST equal amount, extra.paid_amount MUST equal amount + fee_amount - If settle is rejected, order stays pending_payment — fix params and retry with same client_request_id.
Fee structure: fee_amount = issue_fee_amount + fx_fee_amount. total_amount = amount + fee_amount.
Example (Mode A): clawallex_pay({ amount: 50, description: 'OpenAI API credits' })
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | Card face amount in USD | |
| description | Yes | What this payment is for | |
| mode_code | No | 100=wallet (default), 200=x402 on-chain | |
| tx_limit | No | Per-transaction limit in USD (optional, default 100.0000) | |
| allowed_mcc | No | MCC whitelist, comma-separated (optional, e.g. '5734,5815') | |
| blocked_mcc | No | MCC blacklist, comma-separated (optional, e.g. '7995') | |
| client_request_id | No | UUID idempotency key (<=64 chars). Mode B Stage 2: MUST reuse from Stage 1. | |
| chain_code | No | Chain code for Mode B Stage 1 (e.g. 'ETH') | |
| token_code | No | Token code for Mode B Stage 1 (e.g. 'USDC') | |
| extra | No | Mode B Stage 2 (required): { card_amount, paid_amount } | |
| x402_reference_id | No | x402 reference ID. Card creation Stage 1: optional (server generates if omitted). Stage 2: use value from 402 response. Refill Mode B: required, serves as idempotency key. | |
| x402_version | No | x402 version (Mode B Stage 2, required) | |
| payment_payload | No | x402 payment payload (Mode B Stage 2, required) | |
| payment_requirements | No | x402 payment requirements (Mode B Stage 2, required) | |
| payer_address | No | Payer wallet address (optional, final value from verify) |
Implementation Reference
- src/tools/payment.ts:50-101 (handler)The handler for the 'clawallex_pay' tool, which processes payments and card creation requests, including Mode A (wallet) and Mode B (x402) flows.
async (params) => { try { const modeCode = params.mode_code ?? 100; if (modeCode === 200) { const hasX402 = params.x402_version !== undefined || params.payment_payload !== undefined || params.payment_requirements !== undefined; if (hasX402) { const missing: string[] = []; if (params.x402_version === undefined) missing.push("x402_version"); if (params.payment_payload === undefined) missing.push("payment_payload"); if (params.payment_requirements === undefined) missing.push("payment_requirements"); if (params.extra === undefined) missing.push("extra (must include card_amount and paid_amount)"); if (missing.length > 0) { return { content: [{ type: "text" as const, text: `Mode B Stage 2 missing required fields: ${missing.join(", ")}.` }], isError: true as const }; } } else { if (!params.chain_code || !params.token_code) { return { content: [{ type: "text" as const, text: "Mode B Stage 1 requires chain_code and token_code." }], isError: true as const }; } } } const body: Record<string, unknown> = { mode_code: modeCode, card_type: 100, amount: params.amount.toFixed(4), client_request_id: params.client_request_id ?? randomUUID(), }; if (params.tx_limit) body.tx_limit = params.tx_limit; if (params.allowed_mcc) body.allowed_mcc = params.allowed_mcc; if (params.blocked_mcc) body.blocked_mcc = params.blocked_mcc; if (params.chain_code) body.chain_code = params.chain_code; if (params.token_code) body.token_code = params.token_code; if (params.x402_reference_id !== undefined) body.x402_reference_id = params.x402_reference_id; if (params.x402_version !== undefined) body.x402_version = params.x402_version; if (params.payment_payload !== undefined) body.payment_payload = params.payment_payload; if (params.payment_requirements !== undefined) body.payment_requirements = params.payment_requirements; if (params.extra !== undefined) body.extra = params.extra; if (params.payer_address !== undefined) body.payer_address = params.payer_address; const result = await client.post<unknown>("/payment/card-orders", body); return toolOk({ ...(result as Record<string, unknown>), _hint: `Card created for: ${params.description}. Use get_card_details to retrieve card number for checkout.`, }); } catch (err) { if (err instanceof ClawallexApiError && err.statusCode === 402 && err.details) { return formatX402Quote(err.details as Record<string, unknown>); } return toolError(err); } }, ); - src/tools/payment.ts:37-49 (schema)Zod schema definition for the inputs to the 'clawallex_pay' tool.
{ amount: z.number().describe("Card face amount in USD"), description: z.string().describe("What this payment is for"), mode_code: z.number().int().describe("100=wallet (default), 200=x402 on-chain").optional(), tx_limit: z.string().describe("Per-transaction limit in USD (optional, default 100.0000)").optional(), allowed_mcc: z.string().describe("MCC whitelist, comma-separated (optional, e.g. '5734,5815')").optional(), blocked_mcc: z.string().describe("MCC blacklist, comma-separated (optional, e.g. '7995')").optional(), client_request_id: z.string().max(64).describe("UUID idempotency key (<=64 chars). Mode B Stage 2: MUST reuse from Stage 1.").optional(), chain_code: z.string().describe("Chain code for Mode B Stage 1 (e.g. 'ETH')").optional(), token_code: z.string().describe("Token code for Mode B Stage 1 (e.g. 'USDC')").optional(), extra: z.record(z.unknown()).describe("Mode B Stage 2 (required): { card_amount, paid_amount }").optional(), ...x402Fields, }, - src/tools/payment.ts:9-10 (registration)Registration of the 'clawallex_pay' tool in the McpServer.
server.tool( "clawallex_pay",