Safe Account V2
Safe Account V2 uses the original Safe Singleton and adds ERC-4337 functionality using a module/fallback handler.
The V2 contracts, known as the SafeAccountV0_2_0
class in AbstractionKit, supports EntryPoint v0.6.
Import
import { SafeAccountV0_2_0 as SafeAccount } from "abstractionkit";
How to use
Initialize a new Safe Account and calculate its address:
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31"; // Safe owner pub address
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.
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);
key | type | description | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
owners[] |
| Pass the owner(s) address(es) of the account. It can be a single owner account, a multi-sig, or a WebAuthn | ||||||||||||||||||||||||||||||||||||
initCodeOverrides? |
| Override values to change the initialization default values |
key | type | description |
---|---|---|
ECDSASignature | string | ECDSA signature represented as a string |
key | type | description |
---|---|---|
authenticatorData | ArrayBuffer | Binary data returned by the authenticator during the Webauthn process |
clientDataFields | string | Fields associated with the client's Webauthn request data |
rs | [bigint, bigint] | Array of two bigints representing the 'r' and 's' values of the signature |
key | type | description |
---|---|---|
SafeAccount class | SafeAccountV0_2_0 | An instance of the Safe V2 Account and the initialization parameters |
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://api.candide.dev/bundler/version/network/YOUR_API_KEY";
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);
key | type | description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
userOperation | UserOperationV6 | userOperation to sign | |||||||||
privateKeys | string[] | private keys of owners/signers | |||||||||
chainId | bigint | target chain id | |||||||||
overrides? |
| overrides for the default values |
key | type | description |
---|---|---|
sender | string | The account making the operation |
nonce | string | Anti-replay parameter (see “Semi-abstracted Nonce Support” ) |
initCode | string | The initCode of the account (needed if and only if the account is not yet on-chain and needs to be created) |
callData | string | The data to pass to the sender during the main execution call |
callGasLimit | bigint | The amount of gas to allocate the main execution call |
verificationGasLimit | bigint | The amount of gas to allocate for the verification step |
preVerificationGas | bigint | The amount of gas to pay for to compensate the bundler for pre-verification execution and calldata |
maxFeePerGas | bigint | Maximum fee per gas (similar to EIP-1559 max_fee_per_gas) |
maxPriorityFeePerGas | bigint | Maximum priority fee per gas (similar to EIP-1559 max_priority_fee_per_gas) |
paymasterAndData | string | Address of paymaster sponsoring the transaction, followed by extra data to send to the paymaster (empty for self-sponsored transaction). Revolves to '0x' if not using a paymaster, and a paymasterDummyData when estimating gas |
signature | string | The signature for the userOperation. It is the data passed into the account along with the nonce during the verification step. Resolves to '0x' when the user did not provide their signature yet |
key | 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);
key | type | description |
---|---|---|
userOperation | UserOperationV6 | userOperation to send |
bundlerRpc | string | bundler rpc to send userOperation |
key | type | description |
---|---|---|
sender | string | The account making the operation |
nonce | string | Anti-replay parameter (see “Semi-abstracted Nonce Support” ) |
initCode | string | The initCode of the account (needed if and only if the account is not yet on-chain and needs to be created) |
callData | string | The data to pass to the sender during the main execution call |
callGasLimit | bigint | The amount of gas to allocate the main execution call |
verificationGasLimit | bigint | The amount of gas to allocate for the verification step |
preVerificationGas | bigint | The amount of gas to pay for to compensate the bundler for pre-verification execution and calldata |
maxFeePerGas | bigint | Maximum fee per gas (similar to EIP-1559 max_fee_per_gas) |
maxPriorityFeePerGas | bigint | Maximum priority fee per gas (similar to EIP-1559 max_priority_fee_per_gas) |
paymasterAndData | string | Address of paymaster sponsoring the transaction, followed by extra data to send to the paymaster (empty for self-sponsored transaction). Revolves to '0x' if not using a paymaster, and a paymasterDummyData when estimating gas |
signature | string | The signature for the userOperation. It is the data passed into the account along with the nonce during the verification step. Resolves to '0x' when the user did not provide their signature yet |
key | type | description |
---|---|---|
userOperationHash | string | The hash over the userOp (except signature), entryPoint and chainId |
bundler | Bundler | The Bundler class |
entrypointAddress | string | The entrypoint address where the useroperation got executed |
included() | Promise<UserOperationReceiptResult | BundlerJsonRpcError> | Waits for the user operation to be included onchain and returns the user operation receipt on success, or the bundler error on failture |
key | type | description |
---|---|---|
code | number | Bundler RPC error code |
message | string | Bundler RPC error message description |
key | type | description | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOpHash | string | The hash of the user operation. | |||||||||||||||||||||||||||||||||
entryPoint | string | The address of the entry point contract that processed the operation. | |||||||||||||||||||||||||||||||||
sender | string | The address of the sender of the user operation. | |||||||||||||||||||||||||||||||||
nonce | bigint | The nonce of the user operation. | |||||||||||||||||||||||||||||||||
paymaster | string | The address of the paymaster that paid for the gas of the user operation. | |||||||||||||||||||||||||||||||||
actualGasCost | bigint | The actual gas cost incurred for executing the user operation. | |||||||||||||||||||||||||||||||||
actualGasUsed | bigint | The actual amount of gas used for the user operation. | |||||||||||||||||||||||||||||||||
success | boolean | Indicates whether the user operation was successful. | |||||||||||||||||||||||||||||||||
logs | string | The logs produced during the execution of the user operation. | |||||||||||||||||||||||||||||||||
receipt |
| The detailed receipt of the user operation. |
Example Response
sendUserOperationResponse: {
userOperationHash: '0x61b3e2c57ad7ad1ae788f0ac84c79b28aab8aeaf872be173cadc72ab8b3d4418',
bundler: { rpcUrl: 'https://api.candide.dev/bundler/version/network/YOUR_API_KEY' },
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
Advanced Methods
The Advanced methods offer fine control and customization, catering to developers who require detailed configurations for their specific requirements.
createAccountAddress
Calculates the Account address from the initial owners
Usage
In this example, we initiate a single owner account.
- example.ts
- Param Types
- Return Type
import { SafeAccount } from "abstractionkit";
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const safeAddress = SafeAccount.createAccountAddress(
[ownerPublicAddress],
);
console.log("Account address (sender): " + safeAddress);
key | type | description | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
owners[] |
| Pass the owner(s) address(es) of the account. It can be a single owner account, a multi-sig, or a WebAuthn | ||||||||||||||||||||||||||||||||||||
initCodeOverrides |
| Override values to change the initialization default values |
key | type | description |
---|---|---|
ECDSASignature | string | ECDSA signature represented as a string |
key | type | description |
---|---|---|
authenticatorData | ArrayBuffer | Binary data returned by the authenticator during the Webauthn process |
clientDataFields | string | Fields associated with the client's Webauthn request data |
rs | [bigint, bigint] | Array of two bigints representing the 'r' and 's' values of the signature |
key | type | description |
---|---|---|
Smart Account Address | string | Smart Account Address |
Example Response
Account address(sender) : 0x1a02592A3484c2077d2E5D24482497F85e1980C6
Source code
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);
key | type | description | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
owners[] |
| Pass the owner(s) address(es) of the account. It can be a single owner account, a multi-sig, or a WebAuthn | ||||||||||||||||||||||||||||||||||||
initCodeOverrides? |
| Override values to change the initialization default values |
key | type | description |
---|---|---|
ECDSASignature | string | ECDSA signature represented as a string |
key | type | description |
---|---|---|
authenticatorData | ArrayBuffer | Binary data returned by the authenticator during the Webauthn process |
clientDataFields | string | Fields associated with the client's Webauthn request data |
rs | [bigint, bigint] | Array of two bigints representing the 'r' and 's' values of the signature |
key | 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
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 { SafeAccountV0_2_0 as SafeAccount } from "abstractionkit";
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
let [accountAddress, initCode] = SafeAccount.createAccountAddressAndInitCode(
[ownerPublicAddress],
);
console.log("Account address (sender): " + accountAddress);
console.log("initCode: ", initCode);
key | type | description | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
owners[] |
| Pass the owner(s) address(es) of the account. It can be a single owner account, a multi-sig, or a WebAuthn | ||||||||||||||||||||||||||||||||||||
initCodeOverrides? |
| Override values to change the initialization default values |
key | type | description |
---|---|---|
ECDSASignature | string | ECDSA signature represented as a string |
key | type | description |
---|---|---|
authenticatorData | ArrayBuffer | Binary data returned by the authenticator during the Webauthn process |
clientDataFields | string | Fields associated with the client's Webauthn request data |
rs | [bigint, bigint] | Array of two bigints representing the 'r' and 's' values of the signature |
key | type | description |
---|---|---|
account address | string | The Safe Account Address |
initcode | string | The initCode field in the userOperation |
Example Response
Account address(sender) : 0x1a02592A3484c2077d2E5D24482497F85e1980C6
initCode: 0x...
Source code
createAccountAddressAndInitCode
createInitializerCallData
Creates the initilizer calldata
Usage
- Example
- Param Types
- Return Types
import { SafeAccountV0_3_0 as SafeAccount } from "abstractionkit";
const initializeCallData = SafeAccount.createInitializerCallData(
[ownerPublicAddress], // owners
1, //threshold
);
console.log("initializeCallData: " + initializeCallData);
key | type | description | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
owners[] |
| Pass the owner(s) address(es) of the account. It can be a single owner account, a multi-sig, or a WebAuthn | |||||||||||||||||||||
threshold | number | Pass the owner(s) address(es) of the account. It can be a single owner account, a multi-sig, or a WebAuthn | |||||||||||||||||||||
overrides? |
| Override values to change the initialization default values |
key | type | description |
---|---|---|
ECDSASignature | string | ECDSA signature represented as a string |
key | type | description |
---|---|---|
authenticatorData | ArrayBuffer | Binary data returned by the authenticator during the Webauthn process |
clientDataFields | string | Fields associated with the client's Webauthn request data |
rs | [bigint, bigint] | Array of two bigints representing the 'r' and 's' values of the signature |
key | type | description |
---|---|---|
calldata | string | The initializer calldata |
Example Response
initializeCallData: 0xb63e800d000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b47000000000000000000000000000000000000000000000000000000000000014000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c2260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bdbc5fbc9ca8c3f514d073ec3de840ac84fc6d3100000000000000000000000000000000000000000000000000000000000000648d0dc49f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22600000000000000000000000000000000000000000000000000000000
Source
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);
key | type | description | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
metaTransaction |
| The MetaTransaction to create calldata for | |||||||||||||||||||||
safeModuleExecutorFunctionSelector |
| Safe has two executor functions executeUserOpWithErrorString and executeUserOp |
key | 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 = SafeAccount.createAccountCallDataBatchTransactions([tx1, tx2]);
console.log("callData: " + callData);
key | type | description | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
metaTransaction[] |
| The MetaTransaction to create calldata for | |||||||||||||||||||||
safeModuleExecutorFunctionSelector |
| Safe has two executor functions executeUserOpWithErrorString and executeUserOp |
key | type | description |
---|---|---|
callData | string | CallData to be includes in the user operation to send a single transaction |
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,
UserOperationV6
} from "abstractionkit";
const bundlerRPC = "https://api.candide.dev/bundler/version/network/YOUR_API_KEY";
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const smartAccount = SafeAccount.initializeNewAccount([ownerPublicAddress])
// Use createUserOperation() to help you construct the userOp below
let userOperation: UserOperationV6 = smartAccount.createUserOperation(..);
const [preVerificationGas, verificationGasLimit, callGasLimit] = await estimateUserOperationGas(userOperation, bundlerRPC);
key | type | description | |||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOperation | UserOperationV6 | userOperation to send | |||||||||||||||||||||||||||||||||||||||||||||||||||
bundlerRpc | string | bundler rpc to send userOperation | |||||||||||||||||||||||||||||||||||||||||||||||||||
overrides? |
| overrides for the default values |
key | type | description |
---|---|---|
sender | string | The account making the operation |
nonce | string | Anti-replay parameter (see “Semi-abstracted Nonce Support” ) |
initCode | string | The initCode of the account (needed if and only if the account is not yet on-chain and needs to be created) |
callData | string | The data to pass to the sender during the main execution call |
callGasLimit | bigint | The amount of gas to allocate the main execution call |
verificationGasLimit | bigint | The amount of gas to allocate for the verification step |
preVerificationGas | bigint | The amount of gas to pay for to compensate the bundler for pre-verification execution and calldata |
maxFeePerGas | bigint | Maximum fee per gas (similar to EIP-1559 max_fee_per_gas) |
maxPriorityFeePerGas | bigint | Maximum priority fee per gas (similar to EIP-1559 max_priority_fee_per_gas) |
paymasterAndData | string | Address of paymaster sponsoring the transaction, followed by extra data to send to the paymaster (empty for self-sponsored transaction). Revolves to '0x' if not using a paymaster, and a paymasterDummyData when estimating gas |
signature | string | The signature for the userOperation. It is the data passed into the account along with the nonce during the verification step. Resolves to '0x' when the user did not provide their signature yet |
key | type | description |
---|---|---|
ECDSASignature | string | ECDSA signature represented as a string |
key | type | description |
---|---|---|
authenticatorData | ArrayBuffer | Binary data returned by the authenticator during the Webauthn process |
clientDataFields | string | Fields associated with the client's Webauthn request data |
rs | [bigint, bigint] | Array of two bigints representing the 'r' and 's' values of the signature |
Paramater | Type | Description |
---|---|---|
gas estimates | Promise<[bigint, bigint, bigint]> | Returns the gas estimates of preVerificationGas, verificationGasLimit, callGasLimit |
Example Response
[ 46840n, 64545n, 102761n ]
Source code
getUserOperationEip712Hash
Create a userOperation eip712 hash
Usage
- example
- Param Types
- Return Types
console.log("Hello world");
key | type | description | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOperation |
| UserOperation to hash | ||||||||||||||||||||||||||||||||||||
chainId | bigint | target chain id | ||||||||||||||||||||||||||||||||||||
overrides? |
| Overrides for the default values |
key | type | description |
---|---|---|
userOperation | string | userOperation hash |
Source
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, EIP712_SAFE_OPERATION_V6_TYPE } 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 = EIP712_SAFE_OPERATION_V6_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, EIP712_SAFE_OPERATION_V6_TYPE } 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 = EIP712_SAFE_OPERATION_V6_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;
key | type | description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
signersAddresses | string[] | Provide dummy signatures for the operation | |||||||||
signatures | string[] | Provide dummy signatures for the operation | |||||||||
overrides? |
| overrides for the default values |
key | type | description |
---|---|---|
signature | string | The EIP-712 Signature |
Example Response
0x0000000000000000000000006da39f6f7b0d2c0035084d3c313350697b3167ff591a84bf0b4bb4741224b5d226682ec306544c091e2b6535042c900b459282edfe98e393d552963ca8db11731c
Source code
formatEip712SignaturesToUseroperationSignature
isModuleEnabled
Checks if a specified module is enabled for a given Safe account. This function returns a boolean indicating the module's status.
- Param Types
- Return Types
key | type | description |
---|---|---|
nodeRpcUrl | string | The JSON-RPC API url for the target chain. |
moduleAddress | string | The module address to check if enabled. |
key | type | description |
---|---|---|
isEnabled | boolean | Indicates whether the specified module is enabled. |
createAddOwnerWithThresholdMetaTransactions
Creates a meta-transaction to add a new owner to the Safe account with a specified threshold. This function returns an object containing the meta-transaction details, including the target address, encoded data, and transaction value.
- Param Types
- Return Types
key | type | description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
newOwner |
| The public address of the new owner to be added | ||||||||||||||||||
threshold | number | The new threshold value for owner confirmations. | ||||||||||||||||||
overrides |
| Optional Overrides for the default values used in the transaction. |
key | type | description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Promise<MetaTransaction[]> |
| The meta-transaction object for adding a new owner with the specified threshold. |
createSwapOwnerMetaTransactions
Creates a meta-transaction to swap an owner in the Safe account. If a new owner verifier is not already deployed, it will deploy one and fetch the previous owner automatically. This function returns a promise that resolves to a list of meta-transactions containing the necessary details for the swap and deployment.
- Param Types
- Return Types
key | type | description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
nodeRpcUrl | string | The JSON-RPC API URL for the target chain to fetch the previous owner. | ||||||||||||||||||
newOwner |
| The public address of the new owner to be added. | ||||||||||||||||||
oldOwner | Signer | The public address of the owner to be replaced. | ||||||||||||||||||
overrides |
| Overrides for the default values used in the transaction. |
key | type | description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MetaTransaction[] |
| A promise that resolves to a list of meta-transactions for swapping the specified owner and deploying the verifier if necessary. |
createRemoveOwnerMetaTransaction
Creates a meta-transaction to remove an owner from the Safe account, fetching the previous owner if not provided. This function returns a promise that resolves to a meta-transaction object containing the necessary details for the removal.
- Param Types
- Return Types
key | type | description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
nodeRpcUrl | string | The JSON-RPC API URL for the target chain to fetch the previous owner. | ||||||||||||||||||
ownerToDelete |
| The public address of the owner to be deleted. | ||||||||||||||||||
threshold | number | The new threshold value for owner confirmations after removal. | ||||||||||||||||||
overrides |
| Optional Overrides for the default values used in the transaction. |
key | type | description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MetaTransaction |
| A promise that resolves to the meta-transaction object for removing the specified owner. |