Schedule Token Payment

Initialise the Bundler Instance and Account API Instance.

Make sure you have the tokens you want to schedule in your SC Wallet Address.

import { BigNumber } from "ethers";
import { encodeFunctionData, parseUnits } from "viem";

const abi = [
  // Read-Only Functions
  "function balanceOf(address owner) view returns (uint256)",
  "function decimals() view returns (uint8)",
  "function symbol() view returns (string)",
  // Authenticated Functions
  "function transfer(address to, uint amount) returns (bool)",
  // Events
  "event Transfer(address indexed from, address indexed to, uint amount)",

const data = encodeFunctionData({
  args: [recipientAddress, parseUnits(transferAmount.toString(), token.decimals)],
  functionName: "transfer",

const unsignedUserOp = await walletAPI.createUnsignedUserOp({
  target: token.address,
  maxFeePerGas: BigNumber.from("90000000000"), // average value for the token transfer
  maxPriorityFeePerGas: BigNumber.from("1500000000"), // average value for the token transfer
  gasLimit: BigNumber.from("2000320"), // average value for the token transfer
  value: 0n,

const newUserOp: any = {
  sender: await unsignedUserOp.sender,
  nonce: await unsignedUserOp.nonce,
  initCode: await unsignedUserOp.initCode,
  callData: await unsignedUserOp.callData,
  callGasLimit: await unsignedUserOp.callGasLimit,
  verificationGasLimit: await unsignedUserOp.verificationGasLimit,
  preVerificationGas: await unsignedUserOp.preVerificationGas,
  maxFeePerGas: await unsignedUserOp.maxFeePerGas,
  maxPriorityFeePerGas: await unsignedUserOp.maxPriorityFeePerGas,
  paymasterAndData: await unsignedUserOp.paymasterAndData,
  signature: await unsignedUserOp.signature,

const key = await bundler.getValidNonceKey(newUserOp);
const nonce = await walletAPI.getNonce(key);
newUserOp.nonce = nonce;

const signedUserOp = await walletAPI.signUserOp(newUserOp);

const advancedOp = {
  advancedUserOperation: {
    executionTimeWindow: {
      executionWindowStart: epochTimeofScheduledTime,
      executionWindowEnd: epochTimeofScheduledTimeWindowEnd,

const userOpHash = await bundler.sendUserOpToBundler(advancedOp);

Last updated