Safe Account V3
Safe Account V3 uses the original Safe Singleton and adds ERC-4337 functionality using a module/fallback handler.
The V3 contracts, known as the SafeAccountV0_3_0
class in AbstractionKit, supports EntryPoint v0.7.
Import
import { SafeAccountV0_3_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_3_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_3_0 | An instance of the Safe V3 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: '0xd785bb8a95a6a08ace0aa2e54aee5cf04694b1db',
nonce: 19n,
callData: '0x541d63c80000000000000000000000009a7af758ae5d7b6aae84fe4c5ba67c041dfe533600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246a627842000000000000000000000000d785bb8a95a6a08ace0aa2e54aee5cf04694b1db00000000000000000000000000000000000000000000000000000000',
callGasLimit: 58588n,
verificationGasLimit: 94374n,
preVerificationGas: 45628n,
maxFeePerGas: 148180551200n,
maxPriorityFeePerGas: 161327244n,
signature: '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000041ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
factory: null,
factoryData: null,
paymaster: null,
paymasterVerificationGasLimit: null,
paymasterPostOpGasLimit: null,
paymasterData: null
}
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,
);
userOperation.signature = signature;
console.log(signature);
key | type | description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
userOperation | UserOperationV7 | 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” ) |
factory | string | account factory, only for new accounts |
factoryData | string | data for account factory (only if account factory exists) |
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 | Extra gas to pay the bunder |
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) |
paymaster | string | Address of paymaster contract, (or empty, if account pays for itself) |
paymasterVerificationGasLimit | string | The amount of gas to allocate for the paymaster post-operation code |
paymasterPostOpGasLimit | string | The amount of gas to allocate for the paymaster post-operation code |
paymasterData | string | Data for paymaster (only if paymaster exists) |
signature | string | Data passed into the account to verify authorization |
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 | UserOperationV7 | 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” ) |
factory | string | account factory, only for new accounts |
factoryData | string | data for account factory (only if account factory exists) |
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 | Extra gas to pay the bunder |
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) |
paymaster | string | Address of paymaster contract, (or empty, if account pays for itself) |
paymasterVerificationGasLimit | string | The amount of gas to allocate for the paymaster post-operation code |
paymasterPostOpGasLimit | string | The amount of gas to allocate for the paymaster post-operation code |
paymasterData | string | Data for paymaster (only if paymaster exists) |
signature | string | Data passed into the account to verify authorization |
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: '0x0000000071727De22E5E9d8BAf0edAc6f37da032'
}
Useroperation sent. Waiting to be included...
receipt: {
userOpHash: '0x395ddb51c0b76fd72796878d1008c8c9af897e944092bbc741b0a8def1a29984',
entryPoint: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
sender: '0xd785bb8a95a6a08ace0aa2e54aee5cf04694b1db',
nonce: 19n,
paymaster: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
actualGasCost: 16706333689468320n,
actualGasUsed: 185340n,
success: true,
logs: '[{"address":"0x0000000071727de22e5e9d8baf0edac6f37da032","topics":["0x49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f","0x395ddb51c0b76fd72796878d1008c8c9af897e944092bbc741b0a8def1a29984","0x000000000000000000000000d785bb8a95a6a08ace0aa2e54aee5cf04694b1db","0x0000000000000000000000008b1f6cb5d062aa2ce8d581942bbb960420d875ba"],"data":"0x00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000003b5a526d0f55a0000000000000000000000000000000000000000000000000000000000002d3fc","blockNumber":"0x65e483","transactionHash":"0xdf4f976eb8148d14ded74c3f1b21666250be9ae836aa42fb97a3e5ba23f6bf8e","transactionIndex":"0x5d","blockHash":"0x0f306649579021da8b4447bdfcf24b050bacc162ddb756c1d003ab2dd7a0ad9f","logIndex":"0x79","removed":false}]',
receipt: {
blockHash: '0x0f306649579021da8b4447bdfcf24b050bacc162ddb756c1d003ab2dd7a0ad9f',
blockNumber: 6677635n,
from: '0x3cfdc212769c890907bce93d3d8c2c53de6a7a89',
cumulativeGasUsed: 10239342n,
gasUsed: 175887n,
logs: '[{"address":"0x0000000071727de22e5e9d8baf0edac6f37da032","topics":["0xbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972"],"data":"0x","blockNumber":"0x65e483","transactionHash":"0xdf4f976eb8148d14ded74c3f1b21666250be9ae836aa42fb97a3e5ba23f6bf8e","transactionIndex":"0x5d","blockHash":"0x0f306649579021da8b4447bdfcf24b050bacc162ddb756c1d003ab2dd7a0ad9f","logIndex":"0x74","removed":false},{"address":"0xd785bb8a95a6a08ace0aa2e54aee5cf04694b1db","topics":["0xb648d3644f584ed1c2232d53c46d87e693586486ad0d1175f8656013110b714e"],"data":"0x00000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c2260000000000000000000000009a7af758ae5d7b6aae84fe4c5ba67c041dfe5336000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246a627842000000000000000000000000d785bb8a95a6a08ace0aa2e54aee5cf04694b1db00000000000000000000000000000000000000000000000000000000","blockNumber":"0x65e483","transactionHash":"0xdf4f976eb8148d14ded74c3f1b21666250be9ae836aa42fb97a3e5ba23f6bf8e","transactionIndex":"0x5d","blockHash":"0x0f306649579021da8b4447bdfcf24b050bacc162ddb756c1d003ab2dd7a0ad9f","logIndex":"0x75","removed":false},{"address":"0x9a7af758ae5d7b6aae84fe4c5ba67c041dfe5336","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000d785bb8a95a6a08ace0aa2e54aee5cf04694b1db","0x0000000000000000000000000000000000000000000000000000000000000508"],"data":"0x","blockNumber":"0x65e483","transactionHash":"0xdf4f976eb8148d14ded74c3f1b21666250be9ae836aa42fb97a3e5ba23f6bf8e","transactionIndex":"0x5d","blockHash":"0x0f306649579021da8b4447bdfcf24b050bacc162ddb756c1d003ab2dd7a0ad9f","logIndex":"0x76","removed":false},{"address":"0xd785bb8a95a6a08ace0aa2e54aee5cf04694b1db","topics":["0x6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb8","0x00000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c226"],"data":"0x","blockNumber":"0x65e483","transactionHash":"0xdf4f976eb8148d14ded74c3f1b21666250be9ae836aa42fb97a3e5ba23f6bf8e","transactionIndex":"0x5d","blockHash":"0x0f306649579021da8b4447bdfcf24b050bacc162ddb756c1d003ab2dd7a0ad9f","logIndex":"0x77","removed":false},{"address":"0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba","topics":["0xa050a122b4c0e369e3385eb6b7cccd8019638b2764de67bec0af99130ddf8471","0x395ddb51c0b76fd72796878d1008c8c9af897e944092bbc741b0a8def1a29984","0x000000000000000000000000d785bb8a95a6a08ace0aa2e54aee5cf04694b1db","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x65e483","transactionHash":"0xdf4f976eb8148d14ded74c3f1b21666250be9ae836aa42fb97a3e5ba23f6bf8e","transactionIndex":"0x5d","blockHash":"0x0f306649579021da8b4447bdfcf24b050bacc162ddb756c1d003ab2dd7a0ad9f","logIndex":"0x78","removed":false},{"address":"0x0000000071727de22e5e9d8baf0edac6f37da032","topics":["0x49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f","0x395ddb51c0b76fd72796878d1008c8c9af897e944092bbc741b0a8def1a29984","0x000000000000000000000000d785bb8a95a6a08ace0aa2e54aee5cf04694b1db","0x0000000000000000000000008b1f6cb5d062aa2ce8d581942bbb960420d875ba"],"data":"0x00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000003b5a526d0f55a0000000000000000000000000000000000000000000000000000000000002d3fc","blockNumber":"0x65e483","transactionHash":"0xdf4f976eb8148d14ded74c3f1b21666250be9ae836aa42fb97a3e5ba23f6bf8e","transactionIndex":"0x5d","blockHash":"0x0f306649579021da8b4447bdfcf24b050bacc162ddb756c1d003ab2dd7a0ad9f","logIndex":"0x79","removed":false}]',
logsBloom: '0x0000000000111000000010000000000000200000000000000000000002000000000800040000020000000001000040000000000000000000800002000000000020000000020000000000000c000000000040000010000000000000000000000000000000020800000000000000000800000000000000200000000010000000000000000020100000000000000800000020000000000000008000000004000000000040100000000800400080000000000200000040000000000002000000000000000002000000400001000000000000000000000020000000100000000020000000200000000000000200000000000200000000000000000000000010000000',
transactionHash: '0xdf4f976eb8148d14ded74c3f1b21666250be9ae836aa42fb97a3e5ba23f6bf8e',
transactionIndex: 93n,
effectiveGasPrice: 50000149713n
}
}
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
createFactoryAddressAndData
Create an account factory address and factory data
Usage
In this example, we initiate a single owner account.
- example.ts
- Param Types
- Return Type
import { SafeAccountV0_3_0 as SafeAccount } from "abstractionkit";
const ownerPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
let [factoryAddress, factoryData] = SafeAccount.createFactoryAddressAndData(
[ownerPublicAddress],
);
console.log("factoryAddress: " + factoryAddress);
console.log("factoryData: ", factoryData);
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 |
---|---|---|
factory address | string | The Safe factory address |
factory data | string | The factory data |
Example Response
factoryAddress: 0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67
factoryData: 0x1688f0b900000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c7620000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4b63e800d000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b47000000000000000000000000000000000000000000000000000000000000014000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c2260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000bdbc5fbc9ca8c3f514d073ec3de840ac84fc6d3100000000000000000000000000000000000000000000000000000000000000648d0dc49f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c2260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Source code
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_3_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_3_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_3_0 as SafeAccount,
UserOperationV7
} 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
const userOperation:UserOperationV7 = {..}
const [preVerificationGas, verificationGasLimit, callGasLimit] = await estimateUserOperationGas(userOperation, bundlerRPC);
key | type | description | |||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOperation | UserOperationV7 | 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” ) |
factory | string | account factory, only for new accounts |
factoryData | string | data for account factory (only if account factory exists) |
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 | Extra gas to pay the bunder |
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) |
paymaster | string | Address of paymaster contract, (or empty, if account pays for itself) |
paymasterVerificationGasLimit | string | The amount of gas to allocate for the paymaster post-operation code |
paymasterPostOpGasLimit | string | The amount of gas to allocate for the paymaster post-operation code |
paymasterData | string | Data for paymaster (only if paymaster exists) |
signature | string | Data passed into the account to verify authorization |
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
import {
SafeAccountV0_3_0 as SafeAccount,
UserOperationV7
} from "abstractionkit";
const userOperation: UserOperationV7 = smartAccount.createUserOperation(..)
const userOpEip712Hash = SafeAccount.getUserOperationEip712Hash(userOperation, chainId);
console.log(userOpEip712Hash);
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 |
Example Response
0xec030c825b12b398c10f1b552004e43ec753fdf001e1c1daa1ceffe4f7ff5056
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_3_0 as SafeAccount, EIP712_SAFE_OPERATION_V7_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_V7_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_3_0 as SafeAccount, EIP712_SAFE_OPERATION_V7_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_V7_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. |