For TypeScript users: Copy the utilities below directly into your project. Not using TypeScript? Implement your own version following the same logic shown in the code.
Show Click to view signing utilities code
Copy
Ask AI
import { Address, createWalletClient, Hex, http, OneOf, publicActions, SignTypedDataParameters,} from "viem";import { privateKeyToAccount } from "viem/accounts";import { base } from "viem/chains";/** * Types for different signable payloads. */// Payload for EIP-712 permit signature (excluding the account field)type SignablePermitPayload = Omit<SignTypedDataParameters, "account">;// Payload for simple message signing (raw hex message)type SignableSimplePayload = { message: { raw: Hex; };};// Payload for on-chain transaction signingtype SignableOnChainPayload = | { data: Hex; to: Address; gasLimit?: bigint; value: bigint; } | { data: Hex; to: Address; gasLimit?: bigint; value?: bigint | undefined; } | { data: Hex; to: Address; gasLimit?: bigint; value: bigint; };/** * Example EOA account and wallet client setup. * Replace the private key with a real one for production use. */const eoaAccount = privateKeyToAccount("0x"); // ⚠️ Replace with your private keyconst walletClient = createWalletClient({ account: eoaAccount, chain: base, transport: http(), // ⚠️ Use private paid RPC for production}).extend(publicActions);/** * Signs a simple quote payload (raw message). * * @param signablePayload - The payload containing the raw message to sign. * @returns The signature as a Hex string. * * @example * const signature = await signSimpleQuoteSignablePayload({ * message: { raw: "0x68656c6c6f" } * }); */const signSimpleQuoteSignablePayload = async ( signablePayload: SignableSimplePayload): Promise<Hex> => { const signature = await eoaAccount.signMessage(signablePayload); return signature;};/** * Signs a permit quote payload (EIP-712 typed data). * * @param signablePayload - The EIP-712 payload to sign. * @returns The signature as a Hex string. * * @example * const signature = await signPermitQuoteSignablePayload({ * domain: { ... }, * types: { ... }, * primaryType: "Permit", * message: { ... } * }); */const signPermitQuoteSignablePayload = async ( signablePayload: SignablePermitPayload): Promise<Hex> => { const signature = await walletClient.signTypedData({ ...signablePayload, account: eoaAccount, }); return signature;};/** * Signs an on-chain quote payload (transaction). * * @param signablePayload - The transaction payload to send. * @returns The transaction hash as a Hex string. * * @example * const txHash = await signOnChainQuoteSignablePayload({ * to: "0x...", * data: "0x...", * value: 0n * }); */const signOnChainQuoteSignablePayload = async ( signablePayload: SignableOnChainPayload): Promise<Hex> => { const hash = await walletClient.sendTransaction(signablePayload); // Wait for 5 confirmations before returning the hash await walletClient.waitForTransactionReceipt({ hash, confirmations: 5 }); return hash;};/** * Union type for all supported payloads to sign. */type PayloadToSign = OneOf< | { quoteType: "simple"; signablePayload: SignableSimplePayload; } | { quoteType: "permit"; signablePayload: SignablePermitPayload; } | { quoteType: "onchain"; signablePayload: SignableOnChainPayload; }>;/** * Signs a quote payload based on its type. * * @param payloadToSign - The payload and its type. * @returns The signature or transaction hash as a Hex string. * * @example * // Simple message * const sig = await signQuoteSignablePayload({ * quoteType: "simple", * signablePayload: { message: { raw: "0x68656c6c6f" } } * }); * * // Permit (EIP-712) * const sig = await signQuoteSignablePayload({ * quoteType: "permit", * signablePayload: { domain: {...}, types: {...}, primaryType: "...", message: {...} } * }); * * // On-chain transaction * const txHash = await signQuoteSignablePayload({ * quoteType: "onchain", * signablePayload: { to: "0x...", data: "0x...", value: 0n } * }); */const signQuoteSignablePayload = async ( payloadToSign: PayloadToSign): Promise<Hex> => { const { quoteType, signablePayload } = payloadToSign; let signature: Hex = "0x"; switch (quoteType) { case "simple": signature = await signSimpleQuoteSignablePayload(signablePayload); break; case "permit": signature = await signPermitQuoteSignablePayload(signablePayload); break; case "onchain": signature = await signOnChainQuoteSignablePayload(signablePayload); break; default: throw new Error("Unsupported quote type, can't sign the payload"); } return signature;};
For EOA mode, the API cleverly embeds the supertransaction hash into your signatures. This creates a cryptographic link between funding and execution, enabling single-signature cross-chain operations.For Permit: The supertx hash replaces the deadline field