Safe Account
The SafeAccount
uses the original Safe Singleton and adds ERC-4337 functionality using a fallback handler module. The V2 contracts have been developed by the Safe Team, has been audited by Open Zeppelin & Ackee Blockchain. To learn more about the contracts and audits, visit Safe's github.
Import
import { SafeAccountV0_2_0 as SafeAccount } from "abstractionkit";
How to use
Initialize a new Safe Account and calculate its address:
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const smartAccount = SafeAccount.initializeNewAccount([ownerPublicAddress]);
const accountAddress = smartAccount.accountAddress;
Methods
The Essentials methods provides all necessary functionalities with support for overrides, offering a streamlined approach.
The Advanced methods offer fine control and customization, catering to developers who require detailed configurations for their specific requirements.
initializeNewAccount
Initilizes a new SafeAccount class given a list of owners of public address(es). Only need to be called on the first transaction when the account has not been deployed yet.
Usage
In this example, we initiate a single owner account.
- example.ts
- Param Types
- Return Type
import { SafeAccountV0_2_0 as SafeAccount } from "abstractionkit";
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const smartAccount = SafeAccount.initializeNewAccount([ownerPublicAddress]);
console.log("Account address (sender): " + smartAccount.accountAddress);
Param Name | Param Type | Description | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
owners | string[] | The public key address(es) of the owner(s) of the account. | |||||||||||||||||||||
InitCode Overrides | InitCodeOverrides object. (optional)
| InitCodeOverrides allows you to override the default paramaters |
Param Name | Param Type | Description |
---|---|---|
SafeAccount class | SafeAccountV0_2_0 | Creates an instance of the SafeAccount with its associated version |
Example Response
Account address(sender) : 0x1a02592A3484c2077d2E5D24482497F85e1980C6
Source code
createUserOperation
This method determines the nonce, fetch the gas prices, estimate gas limits and return a useroperation to be signed. You can override any of these values using the overrides parameter.
Usage
This example mints the same NFT twice in a single useroperation
- example.ts
- Param Types
- Return Type
import { MetaTransaction } from "abstractionkit";
const jsonRpcNodeProvider = "https://rpc2.sepolia.org";
const bundlerUrl = "https://sepolia.voltaire.candidewallet.com/rpc";
const transaction: MetaTransaction = {
to: "0xD9de104e3386d9A45a61BcE269c43E48B534e4E7", // NFT contract address
value: 0n,
data: "0x1249c58b", // mint()
}
let userOperation = await smartAccount.createUserOperation(
[transaction, transaction], // batch transactions to mint 2 NFTs
jsonRpcNodeProvider,
bundlerUrl,
)
console.log(userOperation);
Param Name | Param Type | Description | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Transactions | MetaTransaction[]
| MetaTransaction is the type of a transaction to construct a Safe operation | |||||||||||||||||||||||||||
Provider RPC | string | The node URL. It is used to fetch the current nonce and fetch gas prices | |||||||||||||||||||||||||||
Bundler URL | string | The Bundler URL. It is used to fetch the gas limits | |||||||||||||||||||||||||||
Overrides | CreateUserOperationOverrides, optional object
| CreateUserOperationOverrides allows you to override any of the default paramaters for the user operation |
Param Name | Param Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
UserOperation | Promise<UserOperation | JsonRpcError | BundlerJsonRpcError> UserOperation object
|
| BundlerJsonRpcError object
| Returns a useroperation on success, or the rpc / bundler error on failure. |
Example Response
{
sender: '0x44e3cb9acd92ab055d3251994352bb8fe0e20879',
nonce: 1n,
initCode: '0x',
callData: '0x541d63c800000000000000000000000038869bf66a61cf6bdb996a6ae40d5853fd43b52600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001048d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000b200d9de104e3386d9a45a61bce269c43e48b534e4e7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041249c58b00d9de104e3386d9a45a61bce269c43e48b534e4e7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041249c58b000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
callGasLimit: 95085n,
verificationGasLimit: 62187n,
preVerificationGas: 46156n,
maxFeePerGas: 1625933544n,
maxPriorityFeePerGas: 1200000000n,
paymasterAndData: '0x',
signature: '0x00000000000000000000000041c6297bd9573e8d979a272db4f6576a98f639a7e6874055a627769401dc46d01143551ccaa473364ace4340ec395c546dccb725e1eac2639ecef443d229f0071b'
}
Source code
signUserOperation
This method takes a userOperation, the private keys of the owner of the account, and the chainId and returns the signature field.
- example.ts
- Param Types
- Return Type
const chainId = BigInt("11155111"); // sepolia chain ID
const privateKey = "0x4cad764980d84fc6684ca839cae2c78be5432e292fa98416e11687ceb9096a03";
const userOperation = {..}
const signature = smartAccount.signUserOperation(
userOperation,
[privateKey],
chainId,
);
console.log(signature);
Param Name | Param Type | Description | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
UserOperation | UserOperation object
| ERC-4337's higher-layer pseudo-transaction | ||||||||||||||||||||||||||||||||||||
Private keys | string[] | The private keys of the owners of the account | ||||||||||||||||||||||||||||||||||||
Chain ID | bigint | The Chain ID where the userOperation will be executed |
Param Name | Param Type | Description |
---|---|---|
Signature field | string | UserOperation Signature with the data passed into the account along with the nonce during the verification step |
Example Response
0x00000000000000000000000041c6297bd9573e8d979a272db4f6576a98f639a7e6874055a627769401dc46d01143551ccaa473364ace4340ec395c546dccb725e1eac2639ecef443d229f0071b
Source code
sendUserOperation
This method sends the userop to the bundler to be executed onchain. It returns a promise SendUseroperationResponse
object to confirm the on-chain inclusion of the userop
- example.ts
- Param Types
- Return Type
const sendUserOperationResponse = await smartAccount.sendUserOperation(userOperation, bundlerUrl)
console.log("sendUserOperationResponse: ". sendUserOperationResponse);
console.log("Useroperation sent. Waiting to be included...");
const receipt = await sendUserOperationResponse.included()
console.log("receipt: ", receipt);
Param Name | Param Type | Description | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
User Operation | UserOperation object
| ERC-4337's higher-layer pseudo-transaction | ||||||||||||||||||||||||||||||||||||
Bundler URL | string | The Bundler URL. It is used here to submit the useroperation |
Param Name | Param Type | Description | |||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Bundler receipt result | Promise<SendUseroperationResponse | BundlerJsonRpcError> SendUseroperationResponse class
|
| Returns SendUseroperationResponse with an async function .included() that returns the receipt on success, or error on failture. |
Example Response
sendUserOperationResponse: {
userOperationHash: '0x61b3e2c57ad7ad1ae788f0ac84c79b28aab8aeaf872be173cadc72ab8b3d4418',
bundler: { rpcUrl: 'https://sepolia.voltaire.candidewallet.com/rpc' },
entrypointAddress: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789'
}
Useroperation sent. Waiting to be included...
receipt: {
userOpHash: '0x61b3e2c57ad7ad1ae788f0ac84c79b28aab8aeaf872be173cadc72ab8b3d4418',
entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789',
sender: '0x44e3cb9acd92ab055d3251994352bb8fe0e20879',
nonce: '0x2',
paymaster: '0x0000000000000000000000000000000000000000',
actualGasCost: 261844423573004,
actualGasUsed: 185893,
success: true,
logs: '[{"address":"0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789","blockHash":"0xba4e1221571d457b4a01db81be6c3ca8e1dcf0117c2c383425e8379853345a69","blockNumber":"0x4e4d65","data":"0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000ee2567da7e0c000000000000000000000000000000000000000000000000000000000002d625","logIndex":"0x140","removed":false,"topics":["0x49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f","0x61b3e2c57ad7ad1ae788f0ac84c79b28aab8aeaf872be173cadc72ab8b3d4418","0x00000000000000000000000044e3cb9acd92ab055d3251994352bb8fe0e20879","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":"0x00289aec83e4f8a109e2026e9e7f9a122bcf66116b1fc9c48099d668eec49f25","transactionIndex":"0xc5"}]',
receipt: {
blockHash: '0xba4e1221571d457b4a01db81be6c3ca8e1dcf0117c2c383425e8379853345a69',
blockNumber: '0x4e4d65',
from: '0x3cfdc212769c890907bce93d3d8c2c53de6a7a89',
cumulativeGasUsed: '0x1c3ffde',
gasUsed: '0x2dbfd',
logs: '[{"address":"0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789","blockHash":"0xba4e1221571d457b4a01db81be6c3ca8e1dcf0117c2c383425e8379853345a69","blockNumber":"0x4e4d65","data":"0x00000000000000000000000000000000000000000000000000013cd7ed43f8b8","logIndex":"0x13a","removed":false,"topics":["0x2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4","0x00000000000000000000000044e3cb9acd92ab055d3251994352bb8fe0e20879"],"transactionHash":"0x00289aec83e4f8a109e2026e9e7f9a122bcf66116b1fc9c48099d668eec49f25","transactionIndex":"0xc5"},{"address":"0x44e3cb9acd92ab055d3251994352bb8fe0e20879","blockHash":"0xba4e1221571d457b4a01db81be6c3ca8e1dcf0117c2c383425e8379853345a69","blockNumber":"0x4e4d65","data":"0x","logIndex":"0x13b","removed":false,"topics":["0x6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb8","0x000000000000000000000000d556564bacf6feac2e26ff70695f8250cea8c29e"],"transactionHash":"0x00289aec83e4f8a109e2026e9e7f9a122bcf66116b1fc9c48099d668eec49f25","transactionIndex":"0xc5"},{"address":"0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789","blockHash":"0xba4e1221571d457b4a01db81be6c3ca8e1dcf0117c2c383425e8379853345a69","blockNumber":"0x4e4d65","data":"0x","logIndex":"0x13c","removed":false,"topics":["0xbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972"],"transactionHash":"0x00289aec83e4f8a109e2026e9e7f9a122bcf66116b1fc9c48099d668eec49f25","transactionIndex":"0xc5"},{"address":"0xd9de104e3386d9a45a61bce269c43e48b534e4e7","blockHash":"0xba4e1221571d457b4a01db81be6c3ca8e1dcf0117c2c383425e8379853345a69","blockNumber":"0x4e4d65","data":"0x","logIndex":"0x13d","removed":false,"topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000044e3cb9acd92ab055d3251994352bb8fe0e20879","0x0000000000000000000000000000000000000000000000000000000000000023"],"transactionHash":"0x00289aec83e4f8a109e2026e9e7f9a122bcf66116b1fc9c48099d668eec49f25","transactionIndex":"0xc5"},{"address":"0xd9de104e3386d9a45a61bce269c43e48b534e4e7","blockHash":"0xba4e1221571d457b4a01db81be6c3ca8e1dcf0117c2c383425e8379853345a69","blockNumber":"0x4e4d65","data":"0x","logIndex":"0x13e","removed":false,"topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x00000000000000000000000044e3cb9acd92ab055d3251994352bb8fe0e20879","0x0000000000000000000000000000000000000000000000000000000000000024"],"transactionHash":"0x00289aec83e4f8a109e2026e9e7f9a122bcf66116b1fc9c48099d668eec49f25","transactionIndex":"0xc5"},{"address":"0x44e3cb9acd92ab055d3251994352bb8fe0e20879","blockHash":"0xba4e1221571d457b4a01db81be6c3ca8e1dcf0117c2c383425e8379853345a69","blockNumber":"0x4e4d65","data":"0x","logIndex":"0x13f","removed":false,"topics":["0x6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb8","0x000000000000000000000000d556564bacf6feac2e26ff70695f8250cea8c29e"],"transactionHash":"0x00289aec83e4f8a109e2026e9e7f9a122bcf66116b1fc9c48099d668eec49f25","transactionIndex":"0xc5"},{"address":"0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789","blockHash":"0xba4e1221571d457b4a01db81be6c3ca8e1dcf0117c2c383425e8379853345a69","blockNumber":"0x4e4d65","data":"0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000ee2567da7e0c000000000000000000000000000000000000000000000000000000000002d625","logIndex":"0x140","removed":false,"topics":["0x49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f","0x61b3e2c57ad7ad1ae788f0ac84c79b28aab8aeaf872be173cadc72ab8b3d4418","0x00000000000000000000000044e3cb9acd92ab055d3251994352bb8fe0e20879","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":"0x00289aec83e4f8a109e2026e9e7f9a122bcf66116b1fc9c48099d668eec49f25","transactionIndex":"0xc5"}]',
logsBloom: '0x000000000000100000000000000000000000000000000000000000000000000000080000000000000022080100000000001000000000008000000200000020000000000000020000000000080000000008100000000000000000000000002000020000000a0800000000000000000800000000000000000000000014000200000000000000000000000000000008000040000000000200000000000000000000000000000002000000400000400000000200000000000000000002200008000000000002000000000001000008000000000000000000080800000000000020000040000000000000000000000000000200000000000000000100000000000000',
transactionHash: '0x00289aec83e4f8a109e2026e9e7f9a122bcf66116b1fc9c48099d668eec49f25',
transactionIndex: '0xc5',
effectiveGasPrice: '0xc6e9e20'
}
}
Source code
createAccountAddressAndInitCode
Calculates the Safe address and the initCode needed to deploy the account onchain
Usage
In this example, we initiate a single owner account.
- example.ts
- Param Types
- Return Type
import { SafeAccount } from "abstractionkit";
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
let [accountAddress, initCode] = SafeAccount.createAccountAddressAndInitCode(
[ownerPublicAddress],
);
console.log("Account address (sender): " + accountAddress);
console.log("initCode: ", initCode);
Param Name | Param Type | Description | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
owners | string[] | The public key address(es) of the owner(s) of the account. | |||||||||||||||||||||
InitCodeOverrides | Optional object
| InitCodeOverrides allows you to override the default paramaters |
Param Name | Param Type | Description |
---|---|---|
[sender,initCode] | [string,BytesLike] | Returns an array that includes the sender (account address) and the factory generator function callData for the initCode |
Example Response
Account address(sender) : 0x1a02592A3484c2077d2E5D24482497F85e1980C6
initCode: 0x...
Source code
createAccountAddressAndInitCode
createInitCode
Calculates the intCode needed to deploy the account onchain
Usage
In this example, we initiate a single owner account.
- example.ts
- Param Types
- Return Type
import { SafeAccount } from "abstractionkit";
const owner1PublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const owner2PublicAddress = "0x4991A5360e5da9BAF62fF644d89F46268e5159eA";
const initCode = SafeAccount.createInitCode([ownerPublicAddress, owner2PublicAddress], 2);
console.log("initCode: ", initCode);
Param Name | Param Type | Description |
---|---|---|
owners | string[] | Pass the owner(s) address(es) of the account. It can be a single owner account or a multi-owner accounts (multi-sig) |
threshold | number | The minimum number of owners needed to approve a transaction. Default to 1 |
c2nonce | bigint | To generate different sender addresses from the same owners. Default to 0 |
singletonAddress | string | Safe contract singleton address |
safeAccountFactoryAddress | string | Safe Factory address |
safe4337ModuleAddress | string | Safe 4337 module address |
addModuleLibAddress | string | addModuleLib address |
Param Name | Param Type | Description |
---|---|---|
initCode | string | The initCode of the account, only needed if the account is not yet on-chain and needs to be created |
Example Response
initCode: 0x...
Source code
createAccountCallDataSingleTransaction
Encode calldata for a single MetaTransaction to be executed by Safe account
Usage
In this example, we make a transfer of 1 wei to a random address.
- example.ts
- Param Types
- Return Type
import { SafeAccountV0_2_0 as SafeAccount } from "abstractionkit";
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const smartAccount = SafeAccount.initializeNewAccount([ownerPublicAddress]);
const callData = smartAccount.createAccountCallDataSingleTransaction({
to: "0x1a02592A3484c2077d2E5D24482497F85e1980C6",
value: 1,
data: "0x",
});
console.log("callData: " + callData);
Param Name | Param Type | Description | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MetaTransaction | Object
| MetaTransaction is the type of a transaction to construct a Gnosis Safe operation |
Param Name | Param Type | Description |
---|---|---|
callData | string | CallData to be includes in the user operation to send a single transaction |
Example Response
callData : 0xf34308ef000000000000000000000000b4fbf271143f4fbf7b91a5ded31805e42b2208d6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Source code
createAccountCallDataSingleTransaction
createAccountCallDataBatchTransactions
Encode calldata for a list of MetaTransactions to be executed by Safe account
Usage
In this example, we make a transfer to 2 different random addresses, 1 wei each.
- example.ts
- Param Types
- Return Type
import {
SafeAccountV0_2_0 as SafeAccount,
MetaTransaction,
} from "abstractionkit";
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const smartAccount = SafeAccount.initializeNewAccount([ownerPublicAddress]);
const tx1: MetaTransaction = {
to: "0x1a02592A3484c2077d2E5D24482497F85e1980C6",
value: 1,
data: "0x",
};
const tx2: MetaTransaction = {
to: "0x3fe285dcd76bcce4ac92d38a6f2f8e964041e020",
value: 1,
data: "0x",
};
const callData = smartAccount.createAccountCallDataBatchTransactions([tx1, tx2]);
console.log("callData: " + callData);
Param Name | Param Type | Description | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MetaTransaction[] | Object[]
| MetaTransaction is the type of a transaction to construct a Gnosis Safe operation | |||||||||||||||
Multisend Contract Address | string (optional) | Defaults to the multisend contract address by Safe |
Param Name | Param Type | Description |
---|---|---|
callData | string | Calldata to be included in the user operation to send a batch of transactions |
Example Response
callData : 0xf34308ef000000000000000000000000b4fbf271143f4fbf7b91a5ded31805e42b2208d6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Source code
createAccountCallDataBatchTransactions
estimateUserOperationGas
Estimate gas limits for a userOperation
Usage
- example.ts
- Param Types
- Response Type
import {
SafeAccountV0_2_0 as SafeAccount,
UserOperation
} from "abstractionkit";
const bundlerRPC = "https://sepolia.voltaire.candidewallet.com/rpc";
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const smartAccount = SafeAccount.initializeNewAccount([ownerPublicAddress])
// Use createUserOperation() to help you construct the userOp below
let userOperation = {
sender: '0xb8741a449d50ed0dcfe395287f85be152884c8d9',
nonce: 10n,
initCode: '0x',
callData: '0x541d63c800000000000000000000000038869bf66a61cf6bdb996a6ae40d5853fd43b52600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001448d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f2009a7af758ae5d7b6aae84fe4c5ba67c041dfe5336000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246a627842000000000000000000000000b8741a449d50ed0dcfe395287f85be152884c8d9009a7af758ae5d7b6aae84fe4c5ba67c041dfe5336000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246a627842000000000000000000000000b8741a449d50ed0dcfe395287f85be152884c8d9000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
callGasLimit: 0n,
verificationGasLimit: 0n,
preVerificationGas: 0n,
maxFeePerGas: 66195658616n,
maxPriorityFeePerGas: 120000n,
paymasterAndData: '0x',
signature: '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
}
const [preVerificationGas, verificationGasLimit, callGasLimit] = await estimateUserOperationGas(userOperation, bundlerRPC);
Paramater | Type | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOperation |
| ||||||||||||||||||||||||||||||||||||
Bundler URL |
| ||||||||||||||||||||||||||||||||||||
Number of Signers |
| ||||||||||||||||||||||||||||||||||||
StateOverrideSet |
|
Paramater | Type | Description |
---|---|---|
userOperation | Promise<[bigint, bigint, bigint]> | Returns the gas estimates of preVerificationGas, verificationGasLimit, callGasLimit |
Example Response
[ 46840n, 64545n, 102761n ]
Source code
formatEip712SignaturesToUseroperationSignature
A static method to format a list of eip712 signatures to a userOperation signature.
Usage
- ethers example
- viem example
- Param Types
- Response Type
import { SafeAccountV0_2_0 as SafeAccount } from "abstractionkit";
import { Wallet } from "ethers";
const ownerPublicAddress = process.env.PUBLIC_ADDRESS as string;
const smartAccount = SafeAccount.initializeNewAccount([ownerPublicAddress]);
let userOperation = ... // Use createUserOperation() to help you construct the userOp below
const domain = {
chainId: process.env.CHAIN_ID,
verifyingContract: smartAccount.safe4337ModuleAddress,
};
const types = SafeAccount.EIP712_SAFE_OPERATION_TYPE;
// formate according to EIP712 Safe Operation Type
const { sender, ...userOp } = userOperation;
const safeUserOperation = {
...userOp,
safe: userOperation.sender,
validUntil: BigInt(0),
validAfter: BigInt(0),
entryPoint: smartAccount.entrypointAddress,
};
const ownerPrivateKey = process.env.PRIVATE_KEY as string;
const signer = new Wallet(ownerPrivateKey);
const signature = await signer.signTypedData(domain, types, safeUserOperation);
const formatedSig = SafeAccount.formatEip712SignaturesToUseroperationSignature([ownerPublicAddress], [signature]);
userOperation.signature = formatedSig;
import { SafeAccountV0_2_0 as SafeAccount } from "abstractionkit";
import { privateKeyToAccount } from "viem";
const ownerPublicAddress = process.env.PUBLIC_ADDRESS as string;
const smartAccount = SafeAccount.initializeNewAccount([ownerPublicAddress]);
let userOperation = ... // Use createUserOperation() to help you construct the userOp below
const domain = {
chainId: process.env.CHAIN_ID,
verifyingContract: smartAccount.safe4337ModuleAddress,
};
const types = SafeAccount.EIP712_SAFE_OPERATION_TYPE;
// formate according to EIP712 Safe Operation Type
const { sender, ...userOp } = userOperation;
const safeUserOperation = {
...userOp,
safe: userOperation.sender,
validUntil: BigInt(0),
validAfter: BigInt(0),
entryPoint: smartAccount.entrypointAddress,
};
const ownerPrivateKey = process.env.PRIVATE_KEY as string;
const signer = privateKeyToAccount(ownerPrivateKey);
const signature = await signer.signTypedData({
domain,
types,
primaryType: 'SafeOp',
message: safeUserOperation,
});
const formatedSig = SafeAccount.formatEip712SignaturesToUseroperationSignature([ownerPublicAddress], [signature]);
userOperation.signature = formatedSig;
Paramater | Type | Description |
---|---|---|
Signers Addresses | string[] | signers public addresses |
Signatures | string[] | List of eip712 signatures |
validAfter | bigint | timestamp the signature will be valid after |
validUntil | bigint | timestamp the signature will be valid until |
Paramater | Type | Description |
---|---|---|
Signature | string | A userOperation signature |
Example Response
0x0000000000000000000000006da39f6f7b0d2c0035084d3c313350697b3167ff591a84bf0b4bb4741224b5d226682ec306544c091e2b6535042c900b459282edfe98e393d552963ca8db11731c