AbstractionKit v0.3.3

Paymaster methods now return a named-field object instead of a tuple or raw UserOperation, and they surface the token quote the paymaster actually applied. CandidePaymasterContext is back as its own argument. A new skipGasEstimation flag lets createUserOperation bypass the bundler round trip when the paymaster is the source of truth for gas.
Paymaster methods return objects, with a token quote
Three paymaster methods changed return shape. All now return { userOperation, tokenQuote? | sponsorMetadata? }:
CandidePaymaster.createSponsorPaymasterUserOperationreturns{ userOperation, sponsorMetadata? }.CandidePaymaster.createTokenPaymasterUserOperationreturns{ userOperation, tokenQuote? }.Erc7677Paymaster.createPaymasterUserOperationreturns{ userOperation, tokenQuote? }.
The new TokenQuote type is exported from the package root:
type TokenQuote = {
token: string // ERC-20 token contract address used to pay gas
exchangeRate: bigint // scaled by 10^18 (1 ETH expressed in the token's smallest unit)
tokenCost: bigint // maximum token cost for this UserOperation
}
The exchange rate and max token cost were previously computed internally and discarded. Consumers had to fetch them again with fetchTokenPaymasterExchangeRate and calculateUserOperationErc20TokenMaxGasCost to show the user the charge. Now both are surfaced from a single call:
const { userOperation, tokenQuote } = await paymaster.createTokenPaymasterUserOperation(
smartAccount, userOp, usdcAddress, bundlerRpc,
)
console.log(`User will pay up to ${tokenQuote.tokenCost} of USDC`)
tokenQuote is absent on sponsored flows and on the signingPhase: "finalize" path (no gas estimation, so nothing to recompute).
Migration:
// Before
const [sponsoredOp, sponsorMetadata] = await paymaster.createSponsorPaymasterUserOperation(...)
const tokenOp = await paymaster.createTokenPaymasterUserOperation(...)
const userOp = await erc7677.createPaymasterUserOperation(...)
// After
const { userOperation: sponsoredOp, sponsorMetadata } = await paymaster.createSponsorPaymasterUserOperation(...)
const { userOperation: tokenOp, tokenQuote } = await paymaster.createTokenPaymasterUserOperation(...)
const { userOperation, tokenQuote } = await erc7677.createPaymasterUserOperation(...)
CandidePaymasterContext is its own argument again
We tried folding CandidePaymasterContext into overrides.context in v0.3.0. It read worse than expected, especially with the two-phase signingPhase flow, so context is a dedicated argument again: it's the second-to-last positional on both createSponsorPaymasterUserOperation and createTokenPaymasterUserOperation, with overrides last.
// Before (0.3.0–0.3.2)
await paymaster.createSponsorPaymasterUserOperation(
smartAccount, userOp, bundlerRpc, sponsorshipPolicyId,
{ context: { signingPhase: "commit" }, preVerificationGasPercentageMultiplier: 20 },
)
// After (0.3.3)
await paymaster.createSponsorPaymasterUserOperation(
smartAccount, userOp, bundlerRpc, sponsorshipPolicyId,
{ signingPhase: "commit" }, // context
{ preVerificationGasPercentageMultiplier: 20 }, // overrides
)
For createTokenPaymasterUserOperation, context.token is always derived from the tokenAddress argument, so pass undefined for context unless you need another field like signingPhase.
skipGasEstimation on createUserOperation
CreateUserOperationOverrides (Safe accounts, Simple7702Account, and Calibur7702Account) now takes a skipGasEstimation?: boolean flag. When set, the SDK skips the bundler's eth_estimateUserOperationGas call; gas limits fall back to any overrides you pass, or 0n.
const userOp = await smartAccount.createUserOperation(
[tx], nodeUrl, bundlerUrl,
{ skipGasEstimation: true },
)
The returned UserOperation is always populated with a dummy signature, whether or not estimation ran. Previously the signature stayed "0x" when all three gas fields were overridden, which broke downstream paymaster calls that require a valid placeholder signature.
Useful when gas estimation is run separately: a paymaster sponsorship call that returns its own gas limits, or an ERC-7677 provider that estimates as part of pm_getPaymasterStubData.
Also in this release
CandidePaymasternow parses sponsor info per ERC-7677. The paymaster returns sponsor info undersponsor: { name, icon? }(singularicon) per ERC-7677. The previous code read a non-standardsponsorMetadatakey and always returnedundefined, so sponsor logos rendered as a broken<img>. The raw response is now normalized into the publicSponsorMetadatashape ({ name, description, url, icons[] }).SponsorInfotype exported from the package root. Represents the raw ERC-7677{ name, icon? }shape, for consumers who want to work with the pre-normalization response.
Start building
Upgrade with yarn add abstractionkit@0.3.3. If you hit anything, find us on Discord.
