Skip to content

Viem integration

The recommended integration uses createBundlerClient and the SDK's Viem paymaster adapter.

ts
import {createPublicClient, defineChain, http} from "viem";
import {createBundlerClient} from "viem/account-abstraction";
import {
  createInkPublicPaymasterClient,
  createInkViemPaymaster,
  INK_PUBLIC_PAYMASTER,
} from "@hellomoon/ink-paymaster";

const ink = defineChain({
  id: INK_PUBLIC_PAYMASTER.chainId,
  name: INK_PUBLIC_PAYMASTER.chainName,
  nativeCurrency: {name: "Ether", symbol: "ETH", decimals: 18},
  rpcUrls: {default: {http: ["https://rpc-qnd.inkonchain.com"]}},
});

const publicClient = createPublicClient({chain: ink, transport: http()});
const service = createInkPublicPaymasterClient();
const bundlerClient = createBundlerClient({
  account,
  chain: ink,
  client: publicClient,
  transport: http(service.bundlerUrl),
  paymaster: createInkViemPaymaster(service),
  paymasterContext: {
    maxTokenCost: 100_000n,
    idempotencyKey: "checkout-order-123",
  },
});

Where callData comes from

When you pass calls to sendUserOperation, Viem invokes the smart account's encodeCalls implementation. This produces the account-specific callData; it does not come from the paymaster.

ts
const hash = await bundlerClient.sendUserOperation({
  calls: [{to: destination, value: 0n, data: transferCalldata}],
});

This matters because different accounts expose different execution ABIs. A SimpleAccount might encode execute(target, value, data), while another account may encode a batch executor.

Choosing maxTokenCost

maxTokenCost is the maximum USDC amount the quote may precharge, in six-decimal base units. It is not necessarily the final cost: unused precharge becomes refund credit after settlement.

Choose a ceiling high enough for the operation's estimated gas, but keep it bounded to the amount your application is prepared to reimburse. The SDK rejects zero and negative values.

Idempotency

Use one stable idempotency key for all network retries of the same logical UserOperation. Use a new key after changing the sender, nonce, account call, or reimbursement ceiling. Keys must contain 8–128 letters, numbers, dots, underscores, colons, or hyphens.

Public prepaid USDC paymaster for Ink Mainnet