zerodev

package module
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 23, 2025 License: Apache-2.0 Imports: 19 Imported by: 1

README

go-zerodev

Basic Go SDK for executing transactions with zerodev paymaster and bundler

Limitations

  • Only entrypoint 0.7 is supported
  • AA wallet has to be already deployed, the SDK does not support walled deployment at this point
  • Only single call is supported

Usage

Default sender and signer
package main

import (
	"fmt"
	"math/big"

	"github.com/DIMO-Network/go-zerodev"
	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/crypto"
)

func main() {
	// Create config for zerodev client with default sender and its signer
	clientConfig := zerodev.ClientConfig{
		AccountAddress:     common.HexToAddress("YOUR_AA_WALLET_ADDRESS"),
		AccountPK:          <YOUR_AA_WALLET_PK>,
		EntryPointVersion:  zerodev.EntryPointVersion07,
		RpcURL:             <RPC_URL>,
		PaymasterURL:       <PAYMASTER_URL>,
		BundlerURL:         <BUNDLER_URL>,
		ChainID:            <CHAIN_ID>,
	}

	// Create a client
	client, _ := zerodev.NewClient(&clientConfig)
	defer client.Close()

	// Prepare call data
	zeroAddress := common.HexToAddress(zerodev.AddressZero)
	encodedCall, _ := zerodev.EncodeExecuteCall(&ethereum.CallMsg{
		To:    &zeroAddress,
		Value: big.NewInt(0),
		Data:  common.FromHex("0x"),
	})

	// Execute the call as user operation
	result, _ := client.SendUserOperation(encodedCall, false)
    
	// Get transaction hash
	fmt.Println(hexutil.Encode(result.UserOperationHash))
}
Custom sender and signer
package main

import (
	"fmt"
	"math/big"

	"github.com/DIMO-Network/go-zerodev"
	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/crypto"
)

func main() {
	// Create config for zerodev client with default sender and its signer
	clientConfig := zerodev.ClientConfig{
		AccountAddress:     common.HexToAddress("YOUR_AA_WALLET_ADDRESS"),
		AccountPK:          <YOUR_AA_WALLET_PK>,
		EntryPointVersion:  zerodev.EntryPointVersion07,
		RpcURL:             <RPC_URL>,
		PaymasterURL:       <PAYMASTER_URL>,
		BundlerURL:         <BUNDLER_URL>,
		ChainID:            <CHAIN_ID>,
	}

	// Create a client
	client, _ := zerodev.NewClient(&clientConfig)
	defer client.Close()

	// Prepare call data
	zeroAddress := common.HexToAddress(zerodev.AddressZero)
	encodedCall, _ := zerodev.EncodeExecuteCall(&ethereum.CallMsg{
		To:    &zeroAddress,
		Value: big.NewInt(0),
		Data:  common.FromHex("0x"),
	})

	customAASender := common.HexToAddress("CUSTOM_AA_WALLET_ADDRESS")

	// Retrieve user operation with custom sender and its hash for signing
	opToSign, opHash, err := client.GetUserOperationAndHashToSign(&customAASender, encodedCall)
	if err != nil {
		panic(err)
	}

	// Sign the hash using any signing method valid for this custom sender, e.g. PK
	customSigner, err := client.GetSmartAccountSigner(<CUSTOM_AA_WALLET>, <CUSTOM_AA_WALLET_ECDSA_PK>)
	if err != nil {
		panic(err)
	}
	
	customSignerSignature, err := customSigner.SignUserOpertionHash(*opHash)
	if err != nil {
		panic(err)
	}
	
	// Add signature to user operation
	opToSign.Signature = customSignerSignature

	// Send signed user operation
	result, err := client.SendSignedUserOperation(opToSign, false)
	if err != nil {
		panic(err)
	}

	fmt.Println(hexutil.Encode(result.UserOperationHash))
}

Documentation

Index

Constants

View Source
const (
	ChainPolygon     = int64(137)
	ChainPolygonAmoy = int64(80_002)
)

ChainPolygon Polygon ChainID ChainPolygonAmoy Polygon Amoy Testnet ChainID

View Source
const (
	AddressZero = "0x0000000000000000000000000000000000000000"
)

Addresses

View Source
const (
	EntryPointVersion07 = "0.7"
)
View Source
const (
	SignatureDummy = "" /* 132-byte string literal not displayed */
)

SignatureDummy Signature used in interaction with paymaster to calculate fees

Variables

This section is empty.

Functions

func EncodeExecuteCall

func EncodeExecuteCall(msg *ethereum.CallMsg) (*[]byte, error)

Types

type BundlerClient

type BundlerClient struct {
	Client     types.RPCClient
	EntryPoint Entrypoint
	ChainID    *big.Int
}

func NewBundlerClient

func NewBundlerClient(rpcClient types.RPCClient, entrypoint Entrypoint, chainID *big.Int) (*BundlerClient, error)

func (*BundlerClient) GetChainID

func (b *BundlerClient) GetChainID() *big.Int

func (*BundlerClient) GetEntryPoint

func (b *BundlerClient) GetEntryPoint() Entrypoint

func (*BundlerClient) GetUserOperationGasPrice

func (b *BundlerClient) GetUserOperationGasPrice() (*GetUserOperationGasPriceResponse, error)

func (*BundlerClient) GetUserOperationReceipt added in v0.4.0

func (b *BundlerClient) GetUserOperationReceipt(hash []byte, pollingDelaySeconds int, pollingRetries int) (*UserOperationReceipt, error)

func (*BundlerClient) SendUserOperation

func (b *BundlerClient) SendUserOperation(op *UserOperation) ([]byte, error)

type Client

type Client struct {
	Signer          types.AccountSigner
	EntryPoint      Entrypoint
	PaymasterClient *PaymasterClient
	BundlerClient   *BundlerClient
	ChainID         *big.Int
	RpcClients      struct {
		Network   *rpc.Client
		Paymaster *rpc.Client
		Bundler   *rpc.Client
	}
	ReceiptPollingDelay   int
	ReceiptPollingRetries int
}

func NewClient

func NewClient(config *ClientConfig) (*Client, error)

func (*Client) Close

func (c *Client) Close()

func (*Client) GetSmartAccountSigner added in v0.3.0

func (c *Client) GetSmartAccountSigner(address common.Address, pk *ecdsa.PrivateKey) (types.AccountSigner, error)

func (*Client) GetUserOperationAndHashToSign added in v0.2.0

func (c *Client) GetUserOperationAndHashToSign(sender common.Address, callData *[]byte) (*UserOperation, *common.Hash, error)

GetUserOperationAndHashToSign creates a UserOperation based on the sender and callData, computes its hash and returns both. Allows to create UserOperation with custom sender and then customize the signing process. After adding signature to the returned UserOperation, it can be sent by SendSignedUserOperation

func (*Client) GetUserOperationReceipt added in v0.4.0

func (c *Client) GetUserOperationReceipt(result *UserOperationResult) (*UserOperationReceipt, error)

func (*Client) SendSignedUserOperation added in v0.2.0

func (c *Client) SendSignedUserOperation(signedOp *UserOperation, waitForReceipt bool) (*UserOperationResult, error)

SendSignedUserOperation sends a pre-signed user operation to the bundler. Allows to create UserOperation with different sender and this sender's signature

func (*Client) SendUserOperation

func (c *Client) SendUserOperation(callData *[]byte, waitForReceipt bool) (*UserOperationResult, error)

SendUserOperation creates and sends a signed user operation using the provided call data. Sender of the user operation is the client's Sender and the signer is SenderSigner

type ClientConfig

type ClientConfig struct {
	AccountAddress             common.Address
	AccountPK                  *ecdsa.PrivateKey
	EntryPointVersion          string
	RpcURL                     *url.URL
	PaymasterURL               *url.URL
	BundlerURL                 *url.URL
	ChainID                    *big.Int
	ReceiptPollingDelaySeconds int
	ReceiptPollingRetries      int
}

type Entrypoint

type Entrypoint interface {
	GetAddress() common.Address
	GetNonce(account common.Address) (*big.Int, error)
	GetUserOperationHash(op *UserOperation) (*common.Hash, error)
	PackUserOperation(op *UserOperation) ([]byte, error)
}

type EntrypointClient07

type EntrypointClient07 struct {
	Client  types.RPCClient
	Address common.Address
	Abi     *abi.ABI
	ChainID *big.Int
}

func NewEntrypoint07

func NewEntrypoint07(rpcClient types.RPCClient, chainID *big.Int) (*EntrypointClient07, error)

NewEntrypoint07 creates a new EntrypointClient07 instance.

func (*EntrypointClient07) GetAddress

func (e *EntrypointClient07) GetAddress() common.Address

func (*EntrypointClient07) GetNonce

func (e *EntrypointClient07) GetNonce(account common.Address) (*big.Int, error)

GetNonce retrieves the nonce of a specific account.

func (*EntrypointClient07) GetUserOperationHash

func (e *EntrypointClient07) GetUserOperationHash(op *UserOperation) (*common.Hash, error)

GetUserOperationHash calculates the hash of a UserOperation.

func (*EntrypointClient07) PackUserOperation

func (*EntrypointClient07) PackUserOperation(op *UserOperation) ([]byte, error)

PackUserOperation creates a packed representation of a UserOperation compliant with Entrypoint 0.7

type GasPriceSpecification

type GasPriceSpecification struct {
	MaxPriorityFeePerGas *big.Int `json:"maxPriorityFeePerGas"`
	MaxFeePerGas         *big.Int `json:"maxFeePerGas"`
}

func (*GasPriceSpecification) UnmarshalJSON

func (g *GasPriceSpecification) UnmarshalJSON(b []byte) error

type GasPriceSpecificationHex

type GasPriceSpecificationHex struct {
	MaxPriorityFeePerGas string `json:"maxPriorityFeePerGas"`
	MaxFeePerGas         string `json:"maxFeePerGas"`
}

type GetUserOperationGasPriceResponse

type GetUserOperationGasPriceResponse struct {
	Slow     *GasPriceSpecification `json:"slow"`
	Standard *GasPriceSpecification `json:"standard"`
	Fast     *GasPriceSpecification `json:"fast"`
}

type GetUserOperationReceiptResponse added in v0.4.0

type GetUserOperationReceiptResponse struct {
	UserOpHash    *hexutil.Bytes       `json:"userOpHash"`
	Entrypoint    common.Address       `json:"entrypoint"`
	Sender        common.Address       `json:"sender"`
	Nonce         *hexutil.Bytes       `json:"nonce"`
	Paymaster     common.Address       `json:"paymaster"`
	ActualGasUsed *hexutil.Big         `json:"actualGasUsed"`
	ActualGasCost *hexutil.Big         `json:"actualGasCost"`
	Success       bool                 `json:"success"`
	Logs          []ethtypes.Log       `json:"logs"`
	Receipt       UserOperationReceipt `json:"receipt"`
}

type PaymasterClient

type PaymasterClient struct {
	Client     types.RPCClient
	EntryPoint Entrypoint
	ChainID    *big.Int
}

func NewPaymasterClient

func NewPaymasterClient(rpcClient types.RPCClient, entrypoint Entrypoint, chainID *big.Int) (*PaymasterClient, error)

func (*PaymasterClient) GetChainID

func (p *PaymasterClient) GetChainID() *big.Int

func (*PaymasterClient) GetEntryPoint

func (p *PaymasterClient) GetEntryPoint() Entrypoint

func (*PaymasterClient) SponsorUserOperation

func (p *PaymasterClient) SponsorUserOperation(op *UserOperation) (*SponsorUserOperationResponse, error)

type PrivateKeySigner

type PrivateKeySigner struct {
	PrivateKey *ecdsa.PrivateKey
	Address    common.Address
}

func NewPrivateKeySigner

func NewPrivateKeySigner(privateKey *ecdsa.PrivateKey) (*PrivateKeySigner, error)

func (*PrivateKeySigner) GetAddress added in v0.3.0

func (s *PrivateKeySigner) GetAddress() common.Address

func (*PrivateKeySigner) SignHash

func (s *PrivateKeySigner) SignHash(hash common.Hash) ([]byte, error)

func (*PrivateKeySigner) SignMessage

func (s *PrivateKeySigner) SignMessage(message []byte) ([]byte, error)

func (*PrivateKeySigner) SignTypedData

func (s *PrivateKeySigner) SignTypedData(typedData *signer.TypedData) ([]byte, error)

func (*PrivateKeySigner) SignUserOperationHash added in v0.3.0

func (s *PrivateKeySigner) SignUserOperationHash(hash common.Hash) ([]byte, error)

type SendUserOperationRequest

type SendUserOperationRequest struct {
	ChainID           *uint64         `json:"chainId"`
	Operation         *UserOperation  `json:"userOp"`
	EntryPointAddress *common.Address `json:"entryPointAddress"`
	GasToken          *common.Address `json:"gasToken,omitempty"`
	ShouldOverrideFee bool            `json:"shouldOverrideFee"`
	ShouldConsume     bool            `json:"shouldConsume"`
}

type SendUserOperationResponse

type SendUserOperationResponse struct {
	TxHash *hexutil.Bytes `json:"txHash"`
}

type SponsorUserOperationRequest

type SponsorUserOperationRequest struct {
	ChainID           *big.Int       `json:"chainId"`
	Operation         *UserOperation `json:"userOp"`
	EntryPointAddress common.Address `json:"entryPointAddress"`
	ShouldOverrideFee bool           `json:"shouldOverrideFee"`
	ShouldConsume     bool           `json:"shouldConsume"`
}

type SponsorUserOperationResponse

type SponsorUserOperationResponse struct {
	CallGasLimit                  *big.Int `json:"callGasLimit"`
	PaymasterVerificationGasLimit *big.Int `json:"paymasterVerificationGasLimit"`
	PaymasterPostOpGasLimit       *big.Int `json:"paymasterPostOpGasLimit"`
	VerificationGasLimit          *big.Int `json:"verificationGasLimit"`
	MaxPriorityFeePerGas          *big.Int `json:"maxPriorityFeePerGas"`
	Paymaster                     []byte   `json:"paymaster"`
	MaxFeePerGas                  *big.Int `json:"maxFeePerGas"`
	PaymasterData                 []byte   `json:"paymasterData"`
	PreVerificationGas            *big.Int `json:"preVerificationGas"`
}

func (*SponsorUserOperationResponse) MarshalJSON

func (r *SponsorUserOperationResponse) MarshalJSON() ([]byte, error)

func (*SponsorUserOperationResponse) UnmarshalJSON

func (r *SponsorUserOperationResponse) UnmarshalJSON(b []byte) error

type SponsorUserOperationResponseHex

type SponsorUserOperationResponseHex struct {
	CallGasLimit                  string `json:"callGasLimit"`
	PaymasterVerificationGasLimit string `json:"paymasterVerificationGasLimit"`
	PaymasterPostOpGasLimit       string `json:"paymasterPostOpGasLimit"`
	VerificationGasLimit          string `json:"verificationGasLimit"`
	MaxPriorityFeePerGas          string `json:"maxPriorityFeePerGas"`
	Paymaster                     string `json:"paymaster"`
	MaxFeePerGas                  string `json:"maxFeePerGas"`
	PaymasterData                 string `json:"paymasterData"`
	PreVerificationGas            string `json:"preVerificationGas"`
}

type UserOperation

type UserOperation struct {
	Sender                        common.Address `json:"sender"`
	Nonce                         *big.Int       `json:"nonce"`
	CallData                      []byte         `json:"callData"`
	CallGasLimit                  *big.Int       `json:"callGasLimit,omitempty"`
	VerificationGasLimit          *big.Int       `json:"verificationGasLimit,omitempty"`
	PreVerificationGas            *big.Int       `json:"preVerificationGas,omitempty"`
	MaxFeePerGas                  *big.Int       `json:"maxFeePerGas"`
	MaxPriorityFeePerGas          *big.Int       `json:"maxPriorityFeePerGas"`
	Paymaster                     []byte         `json:"paymaster,omitempty"`
	PaymasterData                 []byte         `json:"paymasterData,omitempty"`
	PaymasterVerificationGasLimit *big.Int       `json:"paymasterVerificationGasLimit,omitempty"`
	PaymasterPostOpGasLimit       *big.Int       `json:"paymasterPostOpGasLimit,omitempty"`
	Signature                     []byte         `json:"signature,omitempty"`
}

func (*UserOperation) MarshalJSON

func (op *UserOperation) MarshalJSON() ([]byte, error)

func (*UserOperation) UnmarshalJSON added in v0.4.2

func (op *UserOperation) UnmarshalJSON(b []byte) error

type UserOperationHex

type UserOperationHex struct {
	Sender                        string `json:"sender"`
	Nonce                         string `json:"nonce"`
	CallData                      string `json:"callData"`
	CallGasLimit                  string `json:"callGasLimit,omitempty"`
	VerificationGasLimit          string `json:"verificationGasLimit,omitempty"`
	PreVerificationGas            string `json:"preVerificationGas,omitempty"`
	MaxFeePerGas                  string `json:"maxFeePerGas"`
	MaxPriorityFeePerGas          string `json:"maxPriorityFeePerGas"`
	Paymaster                     string `json:"paymaster,omitempty"`
	PaymasterData                 string `json:"paymasterData,omitempty"`
	PaymasterVerificationGasLimit string `json:"paymasterVerificationGasLimit,omitempty"`
	PaymasterPostOpGasLimit       string `json:"paymasterPostOpGasLimit,omitempty"`
	Signature                     string `json:"signature,omitempty"`
}

type UserOperationReceipt added in v0.4.0

type UserOperationReceipt struct {
	TransactionHash   *hexutil.Bytes  `json:"transactionHash"`
	TransactionIndex  *hexutil.Big    `json:"transactionIndex"`
	BlockHash         *hexutil.Bytes  `json:"blockHash"`
	BlockNumber       *hexutil.Big    `json:"blockNumber"`
	From              common.Address  `json:"from"`
	To                common.Address  `json:"to"`
	CumulativeGasUsed *hexutil.Big    `json:"cumulativeGasUsed"`
	GasUsed           *hexutil.Big    `json:"gasUsed"`
	ContractAddress   *common.Address `json:"contractAddress"`
	Logs              []ethtypes.Log  `json:"logs"`
	LogsBloom         *hexutil.Bytes  `json:"logsBloom"`
	Status            *hexutil.Uint   `json:"status"`
	EffectiveGasPrice *hexutil.Big    `json:"effectiveGasPrice"`
}

type UserOperationResult

type UserOperationResult struct {
	UserOperationHash []byte                `json:"userOperationHash"`
	Receipt           *UserOperationReceipt `json:"receipt,omitempty"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL