Skip to main content

Paymaster

A CandidePaymaster is a class interacts with Candide's ERC-4337 Paymaster API.

Supports:

  • Gas sponsorship through Gas Policies
  • ERC-20 Token Sponsorship
  • Multi-EntryPoins at v0.6 and v0.7

Usage

Import

import { CandidePaymaster } from "abstractionkit";

How to use

Initialize a Paymaster with your RPC url. Get an API key from the dashboard.

paymaster.ts
import { CandidePaymaster } from "abstractionkit";

const paymasterRpc = "https://api.candide.dev/paymaster/$version/$network/$apikey";
const paymaster: CandidePaymaster = new CandidePaymaster(paymasterRPC);

Then you can consume Paymaster methods:

const supportedEntryPoints = await paymaster.getSupportedEntrypoints();

Methods

createSponsorPaymasterUserOperation

Returns the paymaster data if the the userOperation has a Gas Policy. Otherwise it returns an error message. Supports two types of Gas Policies:

  • Public Gas Policies: These are gas policies provided by third parties, which do not require a sponsorship policy ID.
  • Private Gas Policies: These require a sponsorship policy ID and can be used if no public gas policy matches the user operation.

Usage

example.ts
import { CandidePaymaster } from "abstractionkit";

const paymasterRpc = "https://api.candide.dev/paymaster/$version/$network/$apikey";
const paymaster: CandidePaymaster = new CandidePaymaster(paymasterRPC);
const sponsorshipPolicyId = '1234';

// Use createUserOperation() to help you construct a userOp
const userOperation = smartAccount.createUserOperation(..)

const [sponsoredUserOperation, sponsorMetadata] =
await paymaster.createSponsorPaymasterUserOperation(
userOperation,
bundlerUrl,
sponsorshipPolicyId, // optional
);

Source code

createSponsorPaymasterUserOperation

createTokenPaymasterUserOperation

Estimates gas limits and returns the user operation with the paymaster data for ERC-20 Token sponsorship.

Usage

import { SafeAccountV0_3_0 as SafeAccount, CandidePaymaster } from "abstractionkit";

const paymasterRPC="https://api.candide.dev/paymaster/$version/$network/$apikey";
const erc20TokenAddress = "0xFa5854FBf9964330d761961F46565AB7326e5a3b"; // CTT test token
const bundlerRPC = "https://sepolia.voltaire.candidewallet.com/rpc";

const ownerPublicAddress = "0x2Ef844456580b6e1E22e1D584EBbC2467D9298B2"
const smartAccount = SafeAccount.initializeNewAccount([ownerPublicAddress])

// Use createUserOperation() to help you construct a userOp
let userOperation = smartAccount.createUserOperation(..);

const paymaster: CandidePaymaster = new CandidePaymaster(paymasterRPC);

userOperation = await paymaster.createTokenPaymasterUserOperation(
smartAccount,
userOperation,
erc20TokenAddress,
bundlerRPC,
);
Details
{
sender: '0xb8741a449d50ed0dcfe395287f85be152884c8d9',
nonce: 10n,
initCode: '0x',
callData: '0x541d63c800000000000000000000000038869bf66a61cf6bdb996a6ae40d5853fd43b52600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e48d80ff0a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000018b009a7af758ae5d7b6aae84fe4c5ba67c041dfe5336000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246a627842000000000000000000000000b8741a449d50ed0dcfe395287f85be152884c8d9009a7af758ae5d7b6aae84fe4c5ba67c041dfe5336000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246a627842000000000000000000000000b8741a449d50ed0dcfe395287f85be152884c8d900fa5854fbf9964330d761961f46565ab7326e5a3b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000003fe285dcd76bcce4ac92d38a6f2f8e964041e02000000000000000000000000000000000000000000000000000a1d1b51fe47c5c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
callGasLimit: 116807n,
verificationGasLimit: 75441n,
preVerificationGas: 50444n,
maxFeePerGas: 66195658616n,
maxPriorityFeePerGas: 120000n,
paymasterAndData: '0x3fE285DcD76BCcE4Ac92d38A6F2F8E964041e020Fa5854FBf9964330d761961F46565AB7326e5a3b00000065bcd7fc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de84cb0d94beb10a4658077bd4ad19f4fdf94425ec730f342b8115d9907f6072f40bcea6a95bce74c29b84a7d4ee9fa67f4efb39e25a2e39a2ecb110b9a0af6b6a9589bfef7ec431b',
signature: '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
}

Source code

createTokenPaymasterUserOperation

calculateUserOperationErc20TokenMaxGasCost

Calculates the maximum gas cost in ERC-20 tokens for a given userOperation

Usage

import { CandidePaymaster } from "abstractionkit";

const erc20TokenAddress = "0xFa5854FBf9964330d761961F46565AB7326e5a3b"; // CTT test token
// Use createUserOperation() to help you construct a userOp
const userOperation = smartAccount.createUserOperation(..)

const paymasterRPC="https://api.candide.dev/paymaster/$version/$network/$apikey";
const paymaster: CandidePaymaster = new CandidePaymaster(paymasterRPC);

const cost = await paymaster.calculateUserOperationErc20TokenMaxGasCost(
userOperation,
erc20TokenAddress,
);
Details
3391931975665260

Source code

calculateUserOperationErc20TokenMaxGasCost

Advanced Methods

getPaymasterMetaData

Returns the metadata associated with the Paymaster, along with dummyPaymasterAndData useful for gas estimates

Usage

example.ts
import { CandidePaymaster, SafeAccountV0_3_0 as SafeAccount } from "abstractionkit";

const paymasterRPC="https://api.candide.dev/paymaster/$version/$network/$apikey";
const paymaster: CandidePaymaster = new CandidePaymaster(paymasterRPC);

const paymasterResult = await paymaster.getPaymasterMetaData(SafeAccount.DEFAULT_ENTRYPOINT_ADDRESS);
Example Response
{
name: 'CANDIDE Paymaster',
description: 'CANDIDE Paymaster a fast, secure and feature-rich 4337 Paymaster',
icons: [],
address: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
sponsoredEventTopic: '0xa050a122b4c0e369e3385eb6b7cccd8019638b2764de67bec0af99130ddf8471',
dummyPaymasterAndData: {
paymaster: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
paymasterVerificationGasLimit: '0xffff',
paymasterPostOpGasLimit: '0xffff',
paymasterData: '0x00010000000000ffff000000000000000000000000000000000000000000000000000000000000ffff010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011c'
}
}

source code

getPaymasterMetaData

getSupportedEntrypoints

Returns the supported Entrypoints by the paymaster

Usage

example.ts
import { CandidePaymaster } from "abstractionkit";

const paymasterRPC="https://api.candide.dev/paymaster/$version/$network/$apikey";
const paymaster: CandidePaymaster = new CandidePaymaster(paymasterRPC);

const paymasterResult = await paymaster.getSupportedEntrypoints();
Example Response
[
'0x0000000071727De22E5E9d8BAf0edAc6f37da032',
'0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789'
]

source code

getSupportedEntrypoints

isSupportedERC20Token

Checks if a particular ERC-20 token is accepted as gas payment by the paymaster. Returns a boolean

Usage

example.ts
import { CandidePaymaster } from "abstractionkit";

const paymasterRPC="https://api.candide.dev/paymaster/$version/$network/$apikey";
const paymaster: CandidePaymaster = new CandidePaymaster(paymasterRPC);

const erc20TokenAddress = "0xFa5854FBf9964330d761961F46565AB7326e5a3b"; // CTT on sepolia testnet

const isSupported = await paymaster.isSupportedERC20Token(erc20TokenAddress);
Example Response
true

Source

isSupportedERC20Token

getSupportedERC20TokenData

Returns the token data given an erc20 address

Usage

example.ts
import { CandidePaymaster } from "abstractionkit";

const paymasterRpc = "https://api.candide.dev/paymaster/$version/$network/$apikey";

const erc20TokenAddress = "0xFa5854FBf9964330d761961F46565AB7326e5a3b";
const paymaster: CandidePaymaster = new CandidePaymaster(paymasterRPC);
const erc20TokenData = await paymaster.getSupportedERC20TokenData(erc20TokenAddress);
Example Response
{
name: 'Candide Test Token',
symbol: 'CTT',
address: '0xFa5854FBf9964330d761961F46565AB7326e5a3b',
decimal: 18,
fee: 0n,
exchangeRate: 1001219705870085130n
}

Source code

getSupportedERC20TokenData

createPaymasterUserOperation

Estimates gas limits and set paymaster data. Returns a complete userOperation and the sponsor metadata if defined

Usage

import { CandidePaymaster } from "abstractionkit";

const bundlerRPC = "https://sepolia.voltaire.candidewallet.com/rpc";
const paymasterRpc = "https://api.candide.dev/paymaster/$version/$network/$apikey";

const paymaster: CandidePaymaster = new CandidePaymaster(paymasterRPC);

// Use createUserOperation() to help you construct a userOp
const userOperation = smartAccount.createUserOperation(..)

const [sponsoredUserOp, sponsorMetadata] = paymaster.createPaymasterUserOperation(userOperation, bundlerRPC);

console.log(sponsoredUserOp);
console.log(sponsorMetadata);
Example Response
{
sender: '0xb5ba83cd38f6d7302fda5c0213aaa1483f8ec6f5',
nonce: 0n,
callData: '0x541d63c800000000000000000000000038869bf66a61cf6bdb996a6ae40d5853fd43b52600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001448d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f2009a7af758ae5d7b6aae84fe4c5ba67c041dfe5336000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246a627842000000000000000000000000b5ba83cd38f6d7302fda5c0213aaa1483f8ec6f5009a7af758ae5d7b6aae84fe4c5ba67c041dfe5336000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246a627842000000000000000000000000b5ba83cd38f6d7302fda5c0213aaa1483f8ec6f5000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
callGasLimit: 126318n,
verificationGasLimit: 895372n,
preVerificationGas: 59404n,
maxFeePerGas: 22056449241n,
maxPriorityFeePerGas: 21053883366n,
signature: '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000041ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
factory: '0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67',
factoryData: '0x1688f0b900000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c7620000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4b63e800d000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b47000000000000000000000000000000000000000000000000000000000000014000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008e35fa6431ac9e2680991d7822df3df47b1f6a1000000000000000000000000000000000000000000000000000000000000000648d0dc49f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c2260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
paymaster: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
paymasterVerificationGasLimit: 100000n,
paymasterPostOpGasLimit: 45000n,
paymasterData: '0x0200000066ec5650b403073db5c06bf3aa8171b902d0efc451d1ae1ac8f6c832fe24eb6407805d2506d0f34ebb9637864d9612b7f9eee7293e1d8a6d9d9d0cc90b621abbfc448e981c'
}
{
name: 'Candide',
description: 'Developers from across the globe use Candide Atelier to build on Safe Accounts and tap into a network of third-party gas sponsorship to ultimately supercharge their user growth',
url: 'https://candide.dev',
icons: [ 'https://docs.candide.dev/img/logo-dark.png' ]
}

Source code

createPaymasterUserOperation