# Go SDK (/get-started/sdks/server-side/go)

> For the complete documentation index, see [llms.txt](/llms.txt)



The ZeroDev Go SDK is part of the [Omni SDK](https://github.com/zerodevapp/zerodev-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.

<Callout type="info">
  The Go binding is currently in alpha.
</Callout>

## Install [#install]

```bash
go get github.com/zerodevapp/zerodev-omni-sdk/bindings/go
```

Then import:

```go
import "github.com/zerodevapp/zerodev-omni-sdk/bindings/go/aa"
```

Requires Go 1.21+ with CGo enabled (the default on the supported platforms).

## Setup [#setup]

```go
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, nil)
if err != nil { panic(err) }
defer account.Close()
```

`aa.GenerateSigner()` is useful for demos when you don't need to reuse a key. It requires a working OS CSPRNG; on hardened sandboxes where `getrandom(2)` is blocked the call returns an error rather than producing a weak key, so production paths in those environments should pass a real key via `aa.LocalSigner(pk)`.

## Example — sponsored UserOp [#example--sponsored-userop]

```go
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, nil)
    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 [#custom-signers]

Pass callbacks for any signing backend (Privy, HSM, MPC, custom keystore):

```go
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-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.

```go
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`.

## Next steps [#next-steps]

* [Runnable example: gasless-transfer-7702/go](https://github.com/zerodevapp/zerodev-omni-sdk/tree/main/examples/gasless-transfer-7702/go)
* [Omni SDK source](https://github.com/zerodevapp/zerodev-omni-sdk)
* [Create a Smart Account](/onboarding/create-a-smart-account)
* [Bundler & Paymaster RPCs](/api-and-toolings/infrastructure/rpcs)
