Skip to main content

Send a transaction

Basic payment​

import { parseEther } from "viem";

const hash = await walletClient.sendTransaction({
account,
chain: walletClient.chain,
to: recipient,
value: parseEther("1.50"), // native USDC: 18 decimals
});

Calling your contract​

const hash = await walletClient.writeContract({
account,
chain: walletClient.chain,
address: CONTRACT,
abi,
functionName: "pay",
args: [orderId],
value: parseEther("1.50"),
});

What happens​

  1. CrackPay checks the call against your app's listing. If it is not allowed, the call rejects with 4100 and the user sees nothing.
  2. CrackPay shows the user the amount and where it goes.
  3. The user approves with their passkey.
  4. CrackPay sends it with gas sponsored and waits for it to land.
  5. The promise resolves with the transaction hash. The payment is final.

Request fields​

FieldBehaviour
toRequired. No contract creation. The zero address is refused.
dataOptional
valueOptional. Native USDC, 18 decimals.
gas, gasPrice, maxFeePerGas, maxPriorityFeePerGas, nonceIgnored

One call per transaction. There is no batching.

Tokens​

For EURC, or any contract that pulls tokens with transferFrom, send two transactions and await each:

import { tokens } from "@crackpay/miniapp-sdk";
import { erc20Abi, parseUnits } from "viem";

const amount = parseUnits("5", tokens.EURC.decimals);

await walletClient.writeContract({
account,
chain: walletClient.chain,
address: tokens.EURC.address,
abi: erc20Abi,
functionName: "approve",
args: [CONTRACT, amount], // the exact amount, never unlimited
});

await walletClient.writeContract({
account,
chain: walletClient.chain,
address: CONTRACT,
abi,
functionName: "payWithToken",
args: [tokens.EURC.address, amount],
});

What a listed app may call​

CallListed appTest app
A contract in its listingAllowedAllowed
Any other contract or addressRefused, 4100Allowed
approve on a listed token, spender in the listingAllowedAllowed
approve to any other spenderRefused, 4100Allowed
transfer or transferFrom on a tokenRefused, 4100Allowed

Move tokens through your own contract, never with a direct token transfer.

Gas​

CrackPay sponsors every transaction. Do not estimate gas, set fee fields, or keep a gas reserve in the user's balance.

:::note While Circle's sponsorship is paused When Circle Gas Station is unavailable, CrackPay falls back to the user's account paying its own fee, about a cent in USDC, and shows it in the confirmation. Your app still sets nothing. A payment of the user's entire balance can then fail for lack of the fee; CrackPay checks this before the passkey prompt. :::

Errors​

See Error codes. Treat 4001 as a cancel.