Skip to main content

Utilities

A set of utilities for ERC-4337 Account Abstraction to help you with your development.

UserOperation utils​

createUserOperationHash​

Computes the hash of a UserOperation, which is used as the unique identifier for the operation on-chain.

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

const userOpHash = createUserOperationHash(
userOperation,
"0x0000000071727De22E5E9d8BAf0edAc6f37da032",
11155111n
);

Source code​

createUserOperationHash

createPackedUserOperationV6​

Encodes a UserOperationV6 into its packed ABI representation, suitable for hashing or on-chain verification.

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

const packed = createPackedUserOperationV6(userOperationV6);

Source code​

createPackedUserOperationV6

createPackedUserOperationV7​

Encodes a UserOperationV7 into its packed ABI representation, suitable for hashing or on-chain verification.

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

const packed = createPackedUserOperationV7(userOperationV7);

Source code​

createPackedUserOperationV7

fetchAccountNonce​

Fetches the current nonce for a smart account from the EntryPoint. Accepts an optional key parameter (default 0) that enables parallel nonce channels, allowing multiple independent UserOperations to be submitted concurrently.

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

const nonce = await fetchAccountNonce(
"https://ethereum-sepolia-rpc.publicnode.com",
"0x0000000071727De22E5E9d8BAf0edAc6f37da032",
"0xYourSmartAccountAddress"
);

Source code​

fetchAccountNonce

calculateUserOperationMaxGasCost​

Calculates the maximum possible gas cost (in wei) for a UserOperation based on its gas limits and fee parameters.

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

const maxCost = calculateUserOperationMaxGasCost(userOperation);

Source code​

calculateUserOperationMaxGasCost

JsonRpcNode​

JsonRpcNode wraps common Ethereum node calls behind the same Transport abstraction used by Bundler and Paymaster services. Use it for node reads instead of the removed top-level URL helpers fetchGasPrice, getBalanceOf, getDepositInfo, and getDelegatedAddress.

example.ts
import { GasOption, JsonRpcNode } from "abstractionkit";

const node = new JsonRpcNode("https://ethereum-sepolia-rpc.publicnode.com");

const [maxFeePerGas, maxPriorityFeePerGas] = await node.getFeeData(GasOption.Medium);
const deposit = await node.getEntryPointDeposit(
"0xYourAccountAddress",
"0x0000000071727De22E5E9d8BAf0edAc6f37da032",
);
const depositInfo = await node.getEntryPointDepositInfo(
"0xYourAccountAddress",
"0x0000000071727De22E5E9d8BAf0edAc6f37da032",
);
const delegatee = await node.getDelegatedAddress("0xYourEOAAddress");

Methods​

  • chainId()
  • blockNumber()
  • getCode(address)
  • call(transaction)
  • getTransactionCount(address)
  • getFeeData(gasOption?)
  • getDelegatedAddress(eoaAddress)
  • getEntryPointNonce(entryPoint, account, key?)
  • getEntryPointDeposit(address, entryPoint)
  • getEntryPointDepositInfo(address, entryPoint)
  • request(args, options?)

Source code​

JsonRpcNode

getBalanceOf​

Deprecated in v0.3.8. Use JsonRpcNode#getEntryPointDeposit instead.

migration.ts
import { JsonRpcNode } from "abstractionkit";

const node = new JsonRpcNode("https://ethereum-sepolia-rpc.publicnode.com");
const balance = await node.getEntryPointDeposit(
"0xYourAccountAddress",
"0x0000000071727De22E5E9d8BAf0edAc6f37da032",
);

getDepositInfo​

Deprecated in v0.3.8. Use JsonRpcNode#getEntryPointDepositInfo instead.

migration.ts
import { JsonRpcNode } from "abstractionkit";

const node = new JsonRpcNode("https://ethereum-sepolia-rpc.publicnode.com");
const info = await node.getEntryPointDepositInfo(
"0xYourAccountAddress",
"0x0000000071727De22E5E9d8BAf0edAc6f37da032",
);

getStorageAt​

Reads the 32-byte storage word at a given slot via eth_getStorageAt.

example.ts
import { JsonRpcNode, SAFE_FALLBACK_HANDLER_STORAGE_SLOT } from "abstractionkit";

const node = new JsonRpcNode("https://ethereum-sepolia-rpc.publicnode.com");
const word = await node.getStorageAt(
"0xYourAccountAddress",
SAFE_FALLBACK_HANDLER_STORAGE_SLOT,
);

Source code​

getStorageAt

Simulation utils​

Simulates a UserOperation via the EntryPoint's handleOps on Tenderly and returns a shareable dashboard link.

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

const { simulation, simulationShareLink } =
await simulateUserOperationWithTenderlyAndCreateShareLink(
"my-account",
"my-project",
"my-access-key",
11155111n,
"0x0000000071727De22E5E9d8BAf0edAc6f37da032",
userOperation
);

Source code​

simulateUserOperationWithTenderlyAndCreateShareLink

Simulates UserOperation callData with Tenderly and returns shareable links. Unlike simulateUserOperationWithTenderlyAndCreateShareLink, this simulates the inner call data rather than the full EntryPoint handleOps flow.

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

const { simulation, callDataSimulationShareLink } =
await simulateUserOperationCallDataWithTenderlyAndCreateShareLink(
"my-account",
"my-project",
"my-access-key",
11155111n,
"0x0000000071727De22E5E9d8BAf0edAc6f37da032",
userOperation
);

Source code​

simulateUserOperationCallDataWithTenderlyAndCreateShareLink

Simulates sender callData directly with Tenderly and returns shareable links. Useful for simulating the execution of callData from a specific sender address without wrapping it in a full UserOperation.

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

const { simulation, callDataSimulationShareLink } =
await simulateSenderCallDataWithTenderlyAndCreateShareLink(
"my-account",
"my-project",
"my-access-key",
11155111n,
"0x0000000071727De22E5E9d8BAf0edAc6f37da032",
"0xSenderAddress",
"0xCallData"
);

Source code​

simulateSenderCallDataWithTenderlyAndCreateShareLink

Multicall utils​

encodeMultiSendCallData​

Encodes an array of MetaTransactions into a single callData payload for the MultiSend contract.

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

const callData = encodeMultiSendCallData([
{
to: "0xTokenAddress",
value: 0n,
data: "0xTransferCallData",
operation: 0,
},
{
to: "0xAnotherContract",
value: 0n,
data: "0xAnotherCallData",
operation: 0,
},
]);

Source code​

encodeMultiSendCallData

decodeMultiSendCallData​

Decodes encoded MultiSend callData back into a readable representation.

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

const decoded = decodeMultiSendCallData(encodedCallData);

Source code​

decodeMultiSendCallData

Generic Ethereum utils​

fetchGasPrice​

Deprecated in v0.3.8. Use JsonRpcNode#getFeeData instead.

migration.ts
import { GasOption, JsonRpcNode } from "abstractionkit";

const node = new JsonRpcNode("https://ethereum-sepolia-rpc.publicnode.com");
const [maxFeePerGas, maxPriorityFeePerGas] = await node.getFeeData(GasOption.Medium);

createCallData​

Encodes a function call into ABI-encoded call data by combining a function selector with its encoded parameters.

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

const callData = createCallData(
"0xa9059cbb", // transfer(address,uint256) selector
["address", "uint256"],
["0xRecipientAddress", 1000000n]
);

Source code​

createCallData

getFunctionSelector​

Computes the 4-byte function selector from a Solidity function signature string.

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

const selector = getFunctionSelector("transfer(address,uint256)");
// Returns "0xa9059cbb"

Source code​

getFunctionSelector

sendJsonRpcRequest​

Sends a JSON-RPC request to the given URL. Accepts optional headers (defaults to {"Content-Type": "application/json"}) and an optional paramsKeyName for non-standard JSON-RPC endpoints.

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

const result = await sendJsonRpcRequest(
"https://ethereum-sepolia-rpc.publicnode.com",
"eth_blockNumber",
[]
);

Source code​

sendJsonRpcRequest

sendEthCallRequest​

Deprecated in v0.3.8. Use JsonRpcNode#call instead.

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

const node = new JsonRpcNode("https://ethereum-sepolia-rpc.publicnode.com");
const result = await node.call({
to: "0xContractAddress",
data: "0xCallData",
});

Source code​

JsonRpcNode.call

sendEthGetCodeRequest​

Deprecated in v0.3.8. Use JsonRpcNode#getCode instead.

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

const node = new JsonRpcNode("https://ethereum-sepolia-rpc.publicnode.com");
const code = await node.getCode("0xContractAddress");

Source code​

JsonRpcNode.getCode

getDelegatedAddress​

Deprecated in v0.3.8. Use JsonRpcNode#getDelegatedAddress instead.

migration.ts
import { JsonRpcNode } from "abstractionkit";

const node = new JsonRpcNode("https://ethereum-sepolia-rpc.publicnode.com");
const delegatee = await node.getDelegatedAddress("0xYourEOAAddress");

if (delegatee) {
console.log("Delegated to:", delegatee);
} else {
console.log("Not delegated");
}

Error and revert decoding​

decodeUserOperationRevertReason​

Reads the EntryPoint's UserOperationRevertReason log directly from a mined receipt and returns the decoded reason, with no extra RPC call. The result is matched to the receipt's userOpHash, so a multi-op bundle returns the right entry. The reason is an Error string, a Panic code, or empty when the inner call left no revert data (usually out-of-gas).

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

const receipt = await response.included();
const revert = decodeUserOperationRevertReason(receipt);

if (revert.reverted) {
console.log(revert.errorMessage ?? revert.panicCode ?? "out of gas");
}

Source code​

decodeUserOperationRevertReason

parseAaCode​

Parses an EntryPoint AAxx revert code (e.g. AA21) out of an error message, so you can branch on a stable contract-defined code instead of matching message text. When a UserOperation fails, AbstractionKit also surfaces this code directly on AbstractionKitError.aaCode, so most callers can read error.aaCode without calling parseAaCode themselves.

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

try {
await smartAccount.sendUserOperation(userOperation, bundlerUrl);
} catch (error) {
// Read the code straight off the error...
if (error.aaCode === "AA21") {
// account did not pay the prefund
}
// ...or parse it from any message string
const code = parseAaCode(error.message);
}

Source code​

parseAaCode

EIP-7702 Utilities​

createAndSignEip7702DelegationAuthorization​

Creates and signs an EIP-7702 delegation authorization, allowing an EOA to delegate its code to a specified contract address. Accepts either a hex-encoded private key string for synchronous signing, or an async signer callback (hash: string) => Promise<string> for use with viem, ethers Signers, hardware wallets, or MPC signers.

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

// With a private key (synchronous)
const authorization = createAndSignEip7702DelegationAuthorization(
11155111n,
"0xDelegateeContractAddress",
0n,
"0xYourPrivateKey"
);

// With an async signer callback
const authorization = await createAndSignEip7702DelegationAuthorization(
11155111n,
"0xDelegateeContractAddress",
0n,
async (hash) => {
// Sign the hash using your preferred method
return await wallet.signMessage(hash);
}
);

Source code​

createAndSignEip7702DelegationAuthorization

createRevokeDelegationAuthorization​

Creates a signed authorization that revokes an existing EIP-7702 delegation by setting the delegatee address to the zero address, restoring the EOA to a normal account.

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

const revokeAuth = createRevokeDelegationAuthorization(
11155111n,
0n,
"0xYourPrivateKey"
);

Source code​

createRevokeDelegationAuthorization

createEip7702DelegationAuthorizationHash​

Computes the keccak256 hash of an EIP-7702 delegation authorization using the MAGIC prefix (0x05) as defined in the EIP-7702 spec. Useful when signing the authorization externally.

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

const hash = createEip7702DelegationAuthorizationHash(
11155111n,
"0xDelegateeContractAddress",
0n
);

Source code​

createEip7702DelegationAuthorizationHash

createAndSignEip7702RawTransaction​

Creates and signs a raw EIP-7702 (set-code, type 0x04) transaction with an authorization list. The transaction is RLP-encoded and includes the type prefix, ready for eth_sendRawTransaction.

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

const rawTx = createAndSignEip7702RawTransaction(
11155111n, // chainId
0n, // nonce
2000000000n, // maxPriorityFeePerGas
20000000000n, // maxFeePerGas
21000n, // gasLimit
"0xDestination", // destination
0n, // value
"0x", // data
[], // accessList
[authorization], // authorizationList
"0xYourPrivateKey"
);

Source code​

createAndSignEip7702RawTransaction

createEip7702TransactionHash​

Computes the keccak256 hash of an EIP-7702 transaction for signing purposes, using the type 0x04 prefix and RLP encoding.

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

const txHash = createEip7702TransactionHash(
11155111n, // chainId
0n, // nonce
2000000000n, // maxPriorityFeePerGas
20000000000n, // maxFeePerGas
21000n, // gasLimit
"0xDestination", // destination
0n, // value
"0x", // data
[], // accessList
[authorization] // authorizationList
);

Source code​

createEip7702TransactionHash