Skip to main content

Account Abstraction SDK

Introduction

Shiba’s account abstraction implementation allows for transaction batching, sponsored transactions and paying for gas fees out of the user’s balance. This SDK provides a simple interface to interact with the Account Abstraction service.

Audience

Developers.

Installation

Prerequisites

  1. Node.js
  2. npm

Installing the SDK

To install the SDK, you can clone the repository and install the dependencies. Once this gets published to npm, you can install it using npm, till then you can follow the below steps:

  1. Clone the repository
git clone https://github.com/shibaone/account-abstraction-sdk.git
  1. Navigate to the project directory
cd account-abstraction-sdk
  1. Install the dependencies
npm install
  1. Build the project
npm run build
  1. Install yalc to publish it locally
npm install -g yalc
  1. Publish the package locally
yalc publish
  1. Now go to your project and install this package in your project
yalc add shib-account-abstraction-sdk@1.0.0
  1. Link the package
yalc link shib-account-abstraction-sdk@1.0.0
  1. Now you can use this package in your project
npm install shib-account-abstraction-sdk

Getting Started

The Account Abstraction SDK has implemented the Shib4337 class underneath the hood. The Shib4337 class provides an interface to interact with Ethereum's Account Abstraction (EIP-4337) functionality. It allows developers to create and manage smart contract wallets (Safes), handle meta-transactions, and integrate with bundlers and paymasters.

Methods

Class Overview

The Shib4337 class is designed to:

  • Initialize and manage a smart contract wallet (Safe) using Account Abstraction.
  • Queue meta-transactions to be executed.
  • Create user operations (UserOperation) compatible with EIP-4337.
  • Interact with bundler services to send user operations.
  • Integrate with paymaster services for gas sponsorship.

Constructor

constructor(options: Safe4337Options)

Description

Creates an instance of the Shib4337 class.

info

This constructor is typically called internally by the init static method and not directly by developers.

Parameters

  • options: Safe4337Options: Configuration options for initializing the Shib4337 instance.

    interface Safe4337Options {
    chainId: number;
    safeAddress: string;
    initCode: string;
    bundlerClient: ethers.JsonRpcProvider;
    publicClient: ethers.JsonRpcProvider;
    bundlerUrl: string;
    paymasterOptions?: PaymasterOptions;
    entryPointAddress: string;
    safe4337ModuleAddress: string;
    }
    parameterrequired/optionaltypedescription
    chainIdRequirednumberBlockchain network identifier.
    safeAddressRequiredstringContract address of the Safe (smart contract wallet).
    initCodeRequiredstringInitialization code that is used to deploy a new Safe if it doesn’t already exist.
    bundlerClientRequiredethers.JsonRpcProviderA JSON RPC provider specifically for interacting with the bundler.
    publicClientRequiredethers.JsonRpcProviderA standard JSON RPC provider that enables general communication with the Ethereum network.
    bundlerUrlRequiredstringA URL that specifies the endpoint for the bundler service.
    paymasterOptionsOptionalPaymasterOptionsPaymaster configuration. For more information, head to its documentation page.
    entryPointAddressRequiredstringThe address of the EntryPoint contract
    safe4337ModuleAddressRequiredstringThe address of the Safe4337 module contract

Example

note

Not typically used directly; use Shib4337.init() instead.


Static Methods

init

static init(initOptions: Safe4337InitOptions): Shib4337

Description

Initializes a new instance of the Shib4337 class. It sets up the necessary configurations, including chain IDs, contract addresses, and clients for interacting with the blockchain and bundler services.

  • If safeAddress is provided, it uses the existing Safe.
  • If safeAddress is not provided, it calculates the predicted Safe address based on the owners, threshold, and salt nonce.

Parameters

  • initOptions: Safe4337InitOptions: Initialization parameters.

    interface Safe4337InitOptions {
    chainId: number;
    signer: ethers.Signer;
    options: {
    safeAddress?: string;
    owners?: string[ ];
    threshold?: number;
    saltNonce?: string;
    };
    bundlerUrl: string;
    rpcUrl?: string;
    customContracts?: {
    safe4337ModuleAddress?: string;
    entryPointAddress?: string;
    };
    paymasterOptions?: PaymasterOptions;
    }
    parameterrequired/optionaltypedescription
    chainIdRequirednumberBlockchain network identifier.
    signerRequiredethers.SignerAn account with the ability to sign transactions.
    optionsRequiredConfiguration settings for the Safe smart contract wallet.
    safeAddressOptionalstringContract address of the Safe (smart contract wallet).
    ownersOptionalstring[ ]Array of addresses that will act as owners of the Safe.
    thresholdOptionalnumberDefines the minimum number of owner approvals required for transactions.
    saltNonceOptionalstringUnique value (salt) used for deploying a new Safe instance if no existing safeAddress is provided.
    bundlerUrlRequiredstringA URL that specifies the endpoint for the bundler service.
    rpcUrlOptionalstringURL for the JSON-RPC endpoint to connect to the network.
    customContractsOptionalAn object containing custom contract addresses for specific components in the EIP-4337 setup.
    safe4337ModuleAddressOptionalstringAddress of a custom Safe4337 module.
    entryPointAddressOptionalstringAddress of a custom Entry Point contract.
    paymasterOptionsOptionalPaymasterOptionsPaymaster configuration. For more information, head to its documentation page.

Returns

  • Shib4337: An instance of the Shib4337 class.

Example

import { Shib4337 } from './Shib4337';
import { ethers } from 'ethers';

const provider = new ethers.JsonRpcProvider('<https://rpc-url>');
const signer = new ethers.Wallet(PRIVATE_KEY, provider);

const shibAAservice = Shib4337.init({
chainId: 109, // Shibarium
signer,
options: {
owners: [signer.address],
threshold: 1,
saltNonce: '0',
},
bundlerUrl: '<https://bundler-url>',
paymasterOptions: {
paymasterUrl: '<https://paymaster-url>',
isSponsored: true,
},
});

Instance Methods

getSupportedEntryPoints

async getSupportedEntryPoints(): Promise<string[]>

Description

Fetches the list of supported entry point contract addresses from the bundler service.

Returns

  • Promise<string[]>: An array of entry point contract addresses.

Example

const entryPoints = await shibAAservice.getSupportedEntryPoints();
console.log('Supported Entry Points:', entryPoints);

getWalletAddress

async getWalletAddress(): Promise<string>

Description

Retrieves the smart contract wallet (Safe) address associated with the Shib4337 instance.

Returns

  • Promise<string>: The wallet address.

Example

const walletAddress = await shibAAservice.getWalletAddress();
console.log('Wallet Address:', walletAddress);

addTransaction

async addTransaction(transaction: MetaTransactionData): Promise<MetaTransactionData[]>

Description

Adds a transaction to the internal transaction queue. These transactions can later be batched and executed together.

Parameters

  • transaction: MetaTransactionData: The transaction data to add to the queue.

    interface MetaTransactionData {
    to: string;
    value: string | number | bigint;
    data: string;
    operation?: OperationType;
    }
    parameterrequired/optionaltypedescription
    toRequiredstringThe address of the recipient (contract or wallet) that will receive the transaction.
    valueRequiredstring, number or bigintThe amount of tokens to be sent with the transaction.
    dataRequiredstringThe calldata to be sent along with the transaction, typically used to interact with smart contracts. For example, it could contain function signatures and parameters.
    operationOptionalOperationTypeSpecifies the type of operation to be performed. The default operation is usually CALL, but it may also support DELEGATECALL or other types, depending on the setup.

Returns

  • Promise<MetaTransactionData[]>: The updated list of transactions in the queue.

Example

await shibAAservice.addTransaction({
to: '0xRecipientAddress',
value: ethers.parseEther('0.1').toString(),
data: '0x',
operation: OperationType.Call,
});

getTransactions

async getTransactions(): Promise<MetaTransactionData[]>

Description

Retrieves the list of transactions currently in the internal queue.

Returns

  • Promise<MetaTransactionData[]>: The list of queued transactions.

Example

const transactions = await shibAAservice.getTransactions();
console.log('Queued Transactions:', transactions);

createTransaction

async createTransaction(props: Safe4337CreateTransactionProps): Promise<UserOperation>

Description

Creates a user operation (UserOperation) that can be sent to the bundler for execution. It handles the encoding of transactions, estimation of gas, and integration with paymasters.

Parameters

  • props: Safe4337CreateTransactionProps

    interface Safe4337CreateTransactionProps {
    transactions?: MetaTransactionData[];
    options?: Safe4337CreateTransactionOptions;
    }
    parameterrequired/optionaltypedescription
    transactionsOptionalstringAn array of transactions to include. If not provided, uses the queued transactions.
    optionsOptionalstringAdditional options for transaction creation.
    interface Safe4337CreateTransactionOptions {
    type?: PaymasterType;
    amountToApprove?: BigNumberish;
    validUntil?: number;
    validAfter?: number;
    feeEstimator?: Function;
    paymasterAndData?: string;
    }
    parameterrequired/optionaltypedescription
    typeOptionalPaymasterTypeThe PaymasterType. Check Paymaster page.
    amountToApproveOptionalBigNumberishThe amount (in the blockchain's native currency, like ETH) to be approved for spending by the smart contract.
    validUntilOptionalnumberA timestamp representing the time until which the transaction remains valid.
    validAfterOptionalnumberA timestamp indicating the time from which the transaction becomes valid.
    feeEstimatorOptionalFunctionA function that estimates the transaction fees.
    paymasterAndDataOptionalstringEncoded data that contains information about the paymaster to be used and any additional parameters required by the paymaster.

Returns

  • Promise<UserOperation>: The constructed user operation ready to be sent to the bundler.

Example

const userOp = await shibAAservice.createTransaction({
options: {
type: PaymasterType.VerifyingPaymaster,
},
});

executeTransaction

async executeTransaction(props: Safe4337ExecuteTransactionProps): Promise<SendExecuteTransactionResponse>

Description

Executes the user operation by sending it to the bundler service. It handles the signing of the operation and waits for the transaction to be mined.

Parameters

  • props: Safe4337ExecuteTransactionProps

    interface Safe4337ExecuteTransactionProps {
    userOp: UserOperation;
    signer: ethers.Signer;
    }
    parameterrequired/optionaltypedescription
    userOpRequiredUserOperationThe user operation to execute.
    signerRequiredethers.SignerThe signer used to sign the transaction

Description

Executes the user operation by sending it to the bundler service. It handles the signing of the operation and waits for the transaction to be mined.

Returns

  • Promise<SendExecuteTransactionResponse>

    interface SendExecuteTransactionResponse {
    userOpHash: string;
    wait: () => Promise<UserOperationWithPayload>;
    }

Example

const executeResponse = await shibAAservice.executeTransaction({
userOp,
signer,
});

const userOpHash = executeResponse.userOpHash;
const receipt = await executeResponse.wait();
console.log('Transaction Receipt:', receipt);

getUserOpsByHash

async getUserOpsByHash(userOpHash: string): Promise<UserOperationWithPayload>

Description

Fetches the details of a user operation from the bundler service using its hash.

Parameters

parameterrequired/optionaltypedescription
userOpHashstringThe hash of the user operation.

Returns

  • Promise<UserOperationWithPayload>: The user operation details.

Example

const userOpDetails = await shibAAservice.getUserOpsByHash(userOpHash);
console.log('User Operation Details:', userOpDetails);

Examples

Initializing the Shib4337 Instance

import { Shib4337 } from 'shib-account-abstraction-sdk';
import { ethers } from 'ethers';

const provider = new ethers.JsonRpcProvider('<https://rpc-url>');
const signer = new ethers.Wallet(PRIVATE_KEY, provider);

const shibAAservice = Shib4337.init({
chainId: 157, // Puppynet
signer,
options: {
owners: [signer.address],
threshold: 1,
saltNonce: '0',
},
bundlerUrl: '<https://bundler-url>',
paymasterOptions: {
paymasterUrl: '<https://paymaster-url>',
isSponsored: true,
},
});

Adding and Executing Transactions

// Add a transaction to the queue
await shibAAservice.addTransaction({
to: '0xRecipientAddress',
value: ethers.parseEther('0.1').toString(),
data: '0x',
operation: OperationType.Call,
});

// Create a user operation
const userOp = await shibAAservice.createTransaction({
options: {
type: PaymasterType.VerifyingPaymaster,
},
});

// Execute the transaction
const executeResponse = await shibAAservice.executeTransaction({
userOp,
signer,
});

const userOpHash = executeResponse.userOpHash;
const receipt = await executeResponse.wait();
console.log('Transaction Receipt:', receipt);

Error Handling

Bundler Errors

ERC-4337 error responses have this format:


{
"jsonrpc": "2.0",
"id": 1
"error": {
code,
message
}
}

Below are the common error codes specified by the protocol.

Many of these errors will also be accompanied by an additional error message from the EntryPoint.

CodeDescription
-32521Transaction reverted (or will revert) during execution phase.
-32602Invalid UserOperation struct/fields.
-32500Transaction rejected by entryPoint's simulateValidation, during account creation or validation.
-32501Transaction rejected by paymaster's validatePaymasterUserOp.
-32502Transaction rejected because of opcode validation.
-32503UserOperation out of time-range: either account or paymaster returned a time-range, and it is already expired (or will expire soon).
-32504Transaction rejected because paymaster (or signature aggregator) is throttled/banned.
-32505Transaction rejected because paymaster (or signature aggregator) stake or unstake-delay is too low.
-32506Transaction rejected because account specified unsupported signature aggregator.
-32507Either validateUserOp or validatePaymasterUserOp returned an invalid signature check.

EntryPoint Errors

Bundler error codes often are accompanied by an additional AAxx code provided by the EntryPoint to give additional guidance.

  • AA1x error codes relate to creating an account
  • AA2x error codes relate to the sender of the user operation
  • AA3x error codes relate to paymasters
  • AA4x error codes relate to verification generally
  • AA5x errors relate to actions after the user operation was executed

Additional Methods and Functionality

The Shib4337 class includes several advanced features:

  • Paymaster Integration: Supports various paymaster types for gas sponsorship.
  • Gas Estimation: Estimates gas requirements for user operations.
  • Transaction Batching: Allows batching multiple transactions into a single operation.
  • Error Handling: Provides informative error messages for troubleshooting.