Go SDK
The ZeroDev Go SDK is part of the Omni SDK — a single Zig core shipped with first-class bindings for Go, Swift, Kotlin, Rust, Python, and C. The module bundles precompiled static libraries for darwin/linux × arm64/amd64, so go get works without a Zig toolchain. It supports smart-account creation, signing, sponsored transactions, and EIP-7702 delegation on any EVM chain.
Install
go get github.com/zerodevapp/zerodev-omni-sdk/bindings/goThen import:
import "github.com/zerodevapp/zerodev-omni-sdk/bindings/go/aa"Requires Go 1.21+ with CGo enabled (the default on the supported platforms).
Setup
import "github.com/zerodevapp/zerodev-omni-sdk/bindings/go/aa"
ctx, err := aa.NewContext(
projectID,
"", // RPC URL (empty → derive from project_id)
"", // Bundler URL (empty → derive from project_id)
11155111, // Sepolia
aa.GasZeroDev,
aa.PaymasterZeroDev,
)
if err != nil { panic(err) }
defer ctx.Close()
signer, err := aa.LocalSigner(privateKey)
if err != nil { panic(err) }
defer signer.Close()
account, err := ctx.NewAccount(signer, aa.KernelV3_3, 0)
if err != nil { panic(err) }
defer account.Close()aa.GenerateSigner() is useful for demos when you don't need to reuse a key.
Example — sponsored UserOp
package main
import (
"fmt"
"os"
"github.com/zerodevapp/zerodev-omni-sdk/bindings/go/aa"
)
func main() {
projectID := os.Getenv("ZERODEV_PROJECT_ID")
ctx, _ := aa.NewContext(projectID, "", "", 11155111,
aa.GasZeroDev, aa.PaymasterZeroDev)
defer ctx.Close()
signer, _ := aa.LocalSigner(privateKey)
defer signer.Close()
account, _ := ctx.NewAccount(signer, aa.KernelV3_3, 0)
defer account.Close()
recipient := [20]byte{ /* ... */ }
hash, _ := account.SendUserOp([]aa.Call{{Target: recipient}})
receipt, _ := account.WaitForUserOperationReceipt(hash, 60_000, 2_000)
fmt.Println("Success:", receipt.Success)
fmt.Println("Tx:", receipt.Receipt["transactionHash"])
}Custom signers
Pass callbacks for any signing backend (Privy, HSM, MPC, custom keystore):
signer, _ := aa.CustomSigner(aa.SignerFuncs{
SignHash: func(hash [32]byte) ([65]byte, error) { /* ... */ },
SignMessage: func(msg []byte) ([65]byte, error) { /* ... */ },
SignTypedDataHash: func(hash [32]byte) ([65]byte, error) { /* ... */ },
GetAddress: func() [20]byte { /* ... */ },
// Optional — omit to let the SDK hash the auth tuple and call SignHash.
SignAuthorization: func(chainID uint64, address [20]byte, nonce uint64) (aa.Authorization, error) {
/* ... */
},
})EIP-7702 delegation
EIP-7702 lets an EOA delegate its code to a Kernel contract so its address is the smart-account address — no CREATE2, no init code, no index. The SDK signs an authorization tuple on the first UserOp and attaches it via the eip7702Auth field; subsequent ops skip the auth once delegation is installed on-chain.
signer, _ := aa.GenerateSigner() // fresh EOA
defer signer.Close()
account, _ := ctx.NewAccount7702(signer, aa.KernelV3_3)
defer account.Close()
addr, _ := account.GetAddress() // == signer's EOA address
hash, _ := account.SendUserOp([]aa.Call{{Target: addr}})Custom signers can populate SignerFuncs.SignAuthorization to sign EIP-7702 tuples natively. Leave it nil and the SDK falls back to hashing the tuple and calling SignHash.