Skip to content

mayerdev/tatum-sdk-go

Repository files navigation

tatum-sdk-go

Go SDK for the Tatum API — blockchain infrastructure for developers.

Repositories

Platform URL
GitLab (primary) https://gitlab.com/mayerdev/tatum-sdk-go
GitHub (mirror) https://github.com/mayerdev/tatum-sdk-go
Codeberg (mirror) https://codeberg.org/mayerdev/tatum-sdk-go

Go module path: gitlab.com/mayerdev/tatum-sdk-go

Installation

go get gitlab.com/mayerdev/tatum-sdk-go

Quick Start

import (
    tatum "gitlab.com/mayerdev/tatum-sdk-go"
    "gitlab.com/mayerdev/tatum-sdk-go/chain"
)

client, err := tatum.NewClient("your-api-key")
if err != nil {
    log.Fatal(err)
}

Services

Keygen (offline)

HD wallet generation, address and private key derivation — fully offline, no API calls.

import (
    "gitlab.com/mayerdev/tatum-sdk-go/chain"
    "gitlab.com/mayerdev/tatum-sdk-go/keygen"
)

Generate wallet — returns a 24-word mnemonic and xpub:

w, err := keygen.GenerateWallet(chain.Ethereum)
// w.Mnemonic — "word1 word2 ... word24"
// w.XPub     — "xpub6Ev..."

Derive address from xpub and index:

addr, err := keygen.DeriveAddress(w.XPub, 0, chain.Ethereum)

Derive private key from mnemonic and index (EVM → 0x-prefixed hex, UTXO → WIF):

privKey, err := keygen.DerivePrivateKey(w.Mnemonic, 0, chain.Ethereum)

Supported networks:

Network Chain Address format Key format
Ethereum chain.Ethereum 0x... 0x... hex
Polygon chain.Polygon 0x... 0x... hex
BNB Smart Chain chain.BNBSmartChain 0x... 0x... hex
Avalanche chain.Avalanche 0x... 0x... hex
Arbitrum chain.Arbitrum 0x... 0x... hex
Optimism chain.Optimism 0x... 0x... hex
Base chain.Base 0x... 0x... hex
zkSync chain.ZkSync 0x... 0x... hex
Linea chain.Linea 0x... 0x... hex
Scroll chain.Scroll 0x... 0x... hex
Blast chain.Blast 0x... 0x... hex
Fantom chain.Fantom 0x... 0x... hex
Cronos chain.Cronos 0x... 0x... hex
Celo chain.Celo 0x... 0x... hex
Gnosis chain.Gnosis 0x... 0x... hex
Harmony chain.Harmony 0x... 0x... hex
Aurora chain.Aurora 0x... 0x... hex
Heco chain.Heco 0x... 0x... hex
KuCoin chain.KuCoin 0x... 0x... hex
Klaytn chain.Klaytn 0x... 0x... hex
Palm chain.Palm 0x... 0x... hex
Ethereum Classic chain.EthereumClassic 0x... 0x... hex
VeChain chain.VeChain 0x... 0x... hex
Hedera chain.Hedera 0x... 0x... hex
Chiliz chain.Chiliz 0x... 0x... hex
Theta chain.Theta 0x... 0x... hex
Tron chain.Tron T... 0x... hex
Bitcoin chain.Bitcoin 1... WIF
Litecoin chain.Litecoin L... WIF
Dogecoin chain.Dogecoin D... WIF
Bitcoin Cash chain.BitcoinCash 1... WIF
Dash chain.Dash X... WIF
ZCash chain.ZCash t1... WIF
Solana chain.Solana base58 pubkey (see note) hex
XRP chain.XRP r... 0x... hex
chains := []chain.Chain{
    chain.Ethereum, chain.Polygon, chain.BNBSmartChain, chain.Avalanche,
    chain.Arbitrum, chain.Optimism, chain.Base, chain.ZkSync,
    chain.Linea, chain.Scroll, chain.Blast, chain.Fantom,
    chain.Cronos, chain.Celo, chain.Gnosis, chain.Harmony,
    chain.Aurora, chain.Heco, chain.KuCoin, chain.Klaytn,
    chain.Palm, chain.EthereumClassic, chain.VeChain, chain.Hedera,
    chain.Chiliz, chain.Theta, chain.Tron,
    chain.Bitcoin, chain.Litecoin, chain.Dogecoin, chain.BitcoinCash,
    chain.Dash, chain.ZCash,
    chain.Solana, chain.XRP,
}

for _, c := range chains {
    w, err := keygen.GenerateWallet(c)
    if err != nil {
        log.Fatal(err)
    }
    addr, err := keygen.DeriveAddress(w.XPub, 0, c)
    if err != nil {
        log.Fatal(err)
    }
    privKey, err := keygen.DerivePrivateKey(w.Mnemonic, 0, c)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("chain=%s\n  mnemonic=%s\n  xpub=%s\n  address=%s\n  privkey=%s\n\n",
        c, w.Mnemonic, w.XPub, addr, privKey)
}

Solana multi-address derivation: Because SLIP-0010 with ed25519 only supports hardened child derivation, public-key child derivation is cryptographically impossible for Solana. As a result, DeriveAddress(xpub, index, chain.Solana) only works for index == 0 (it returns the xpub itself). For index > 0 it returns keygen.ErrSolanaPublicDerivation. To derive multiple Solana addresses, use DerivePrivateKey with the desired index and then convert with SolanaAddressFromPrivKey:

privKey, err := keygen.DerivePrivateKey(w.Mnemonic, 5, chain.Solana)
addr, err := keygen.SolanaAddressFromPrivKey(privKey)

Unsupported networks return keygen.ErrUnsupportedChain:

_, err := keygen.GenerateWallet(chain.Cardano)
if errors.Is(err, keygen.ErrUnsupportedChain) {
    // handle unsupported chain
}

WalletGen (API-based)

Generate wallets and derive addresses/keys via Tatum's REST API (server-side, 17 chains).

Generate wallet:

w, err := client.WalletGen.GenerateWallet(ctx, chain.Ethereum)
// w.Mnemonic — "word1 word2 ... word24"
// w.XPub     — "xpub6Ev..."

// For Solana: w.Address, w.PrivateKey
// For Algorand: w.Address, w.Secret

Derive address from xpub and index:

addr, err := client.WalletGen.DeriveAddress(ctx, chain.Bitcoin, xpub, 0)

Derive private key from mnemonic and index:

key, err := client.WalletGen.DerivePrivateKey(ctx, chain.Ethereum, mnemonic, 0)
if errors.Is(err, walletgen.ErrNotSupported) {
    // chain does not support this operation
}

Supported chains and operations:

Chain GenerateWallet DeriveAddress DerivePrivateKey
chain.Bitcoin
chain.BitcoinCash
chain.Dogecoin
chain.Litecoin
chain.Ethereum
chain.BNBSmartChain
chain.Polygon
chain.Klaytn
chain.KuCoin
chain.VeChain
chain.Harmony
chain.Tron
chain.XDC
chain.Solana
chain.Algorand
chain.Flow
chain.EGLD

Flow address derivation: Flow uses a different API path for address derivation (/v3/flow/pubkey/{xpub}/{index} instead of the standard /v3/{chain}/address/{xpub}/{index}). DeriveAddress handles this automatically. The wallet response for Flow contains w.Address (the public key / address). DerivePrivateKey returns the privateKey field from the API response.

Wallet

items, err := client.Wallet.GetPortfolio(ctx, wallet.PortfolioRequest{
    Addresses: []string{"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"},
    Chain:     "ethereum",
})

balance, err := client.Wallet.GetBalanceByTime(ctx, wallet.BalanceByTimeRequest{
    Address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    Chain:   "ethereum",
    Time:    1700000000,
})

utxos, err := client.Wallet.GetUTXOs(ctx, wallet.UTXORequest{
    Address: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
    Chain:   "bitcoin",
})

Transactions

txs, err := client.Transactions.GetHistory(ctx, transactions.HistoryRequest{
    Address:  "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    Chain:    "ethereum",
    PageSize: 10,
})

tx, err := client.Transactions.GetByHash(ctx, transactions.ByHashRequest{
    Hash:  "0xabc123...",
    Chain: "ethereum",
})

Blockchain

block, err := client.Blockchain.GetCurrentBlock(ctx, blockchain.CurrentBlockRequest{
    Chain: "ethereum",
})

balance, err := client.Blockchain.GetNativeBalance(ctx, blockchain.NativeBalanceRequest{
    Address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    Chain:   "ethereum",
})

NFT

meta, err := client.NFT.GetMetadata(ctx, nft.MetadataRequest{
    TokenID:  "1",
    Contract: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
    Chain:    "ethereum",
})

tokens, err := client.NFT.GetCollectionTokens(ctx, nft.CollectionTokensRequest{
    Collection: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
    Chain:      "ethereum",
    PageSize:   20,
})

Token

transfers, err := client.Token.GetTransfers(ctx, token.TransfersRequest{
    Address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    Chain:   "ethereum",
})

rate, err := client.Token.GetExchangeRates(ctx, token.ExchangeRatesRequest{
    Contract: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
    Chain:    "ethereum",
})

Prices

rate, err := client.Prices.GetRate(ctx, prices.RateRequest{
    Currency: "BTC",
    BasePair: "USD",
})

candles, err := client.Prices.GetOHLCV(ctx, prices.OHLCVRequest{
    Currency: "ETH",
    BasePair: "USD",
    From:     1700000000,
    To:       1700086400,
})

Staking

assets, err := client.Staking.GetStakedAssets(ctx, staking.StakedAssetsRequest{
    Address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    Chain:   "ethereum",
})

validators, err := client.Staking.GetValidators(ctx, staking.ValidatorsRequest{
    Chain: "ethereum",
})

DeFi

events, err := client.DeFi.GetEvents(ctx, defi.EventsRequest{
    Contract: "0xUniswapV3Pool...",
    Chain:    "ethereum",
})

latest, err := client.DeFi.GetLatestBlock(ctx, defi.LatestBlockRequest{
    Chain: "ethereum",
})

Fees

gas, err := client.Fees.EstimateGas(ctx, fees.EstimateGasRequest{
    Chain: "ethereum",
    From:  "0xSender",
    To:    "0xReceiver",
    Value: "1000000000000000000",
})

fee, err := client.Fees.GetBlockchainFee(ctx, fees.BlockchainFeeRequest{
    Chain: "ethereum",
})

Name Service

resolved, err := client.NameService.Resolve(ctx, nameservice.ResolveRequest{
    Name:  "vitalik.eth",
    Chain: "ethereum",
})

Security

check, err := client.Security.CheckAddress(ctx, security.CheckAddressRequest{
    Address: "0xSomeAddress",
    Chain:   "ethereum",
})
if check.Malicious {
    log.Println("address flagged as malicious:", check.Tags)
}

Notifications

Subscribe / unsubscribe:

sub, err := client.Notifications.Create(ctx, notifications.CreateRequest{
    Type:    "ADDRESS_TRANSACTION",
    Address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    Chain:   "ethereum",
    URL:     "https://your-webhook.example.com/hook",
})

list, err := client.Notifications.List(ctx, notifications.ListRequest{PageSize: 10})

err = client.Notifications.Cancel(ctx, notifications.CancelRequest{ID: sub.ID})

HMAC webhook authentication:

Enable HMAC signing so every webhook from Tatum contains an x-payload-hash header:

err = client.Notifications.EnableHMAC(ctx, notifications.EnableHMACRequest{
    HMACSecret: "c354b83b-d31b-4dda-9bab-d6a67715a1ed",
})

err = client.Notifications.DisableHMAC(ctx)

Parsing and verifying incoming webhooks:

import "gitlab.com/mayerdev/tatum-sdk-go/notifications"

// In your HTTP handler:
body, _ := io.ReadAll(r.Body)
xPayloadHash := r.Header.Get("x-payload-hash")

payload, valid, err := notifications.ParseAndVerifyWebhook(body, xPayloadHash, "your-hmac-secret")
if err != nil {
    http.Error(w, "bad request", http.StatusBadRequest)
    return
}
if !valid {
    http.Error(w, "invalid signature", http.StatusUnauthorized)
    return
}

fmt.Println(payload.Chain, payload.Address, payload.Amount, payload.TxID)

Pass an empty string as hmacSecret to skip signature verification and only parse the payload.

WebhookPayload fields:

Field Type Description
Address string Subscribed address
Amount string Transfer amount
CounterAddress string Counterpart address
Asset string Asset symbol
BlockNumber int64 Block number
TxID string Transaction hash
Type string "native" or "token"
TokenID *string Token ID (nullable)
ContractAddress string Token contract address
Chain string Blockchain identifier
SubscriptionType string e.g. "ADDRESS_EVENT"

RPC Gateway

result, err := client.RPC.Call(ctx, chain.Ethereum, chain.Mainnet, "eth_blockNumber", nil)

result, err := client.RPC.Call(ctx, chain.Ethereum, chain.Mainnet, "eth_getBalance", []any{
    "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "latest",
})

Supported chains:

chain.Ethereum, chain.Bitcoin, chain.Polygon, chain.BNBSmartChain,
chain.Solana, chain.Avalanche, chain.Tron, chain.Optimism,
chain.Arbitrum, chain.Base, chain.ZkSync, chain.Linea,
// ... and 35+ more

Error Handling

_, err := client.Wallet.GetPortfolio(ctx, req)
if err != nil {
    if tatum.IsNotFound(err) {
        // 404
    }
    if tatum.IsRateLimit(err) {
        // 429 — SDK automatically retries with exponential backoff
    }
    var apiErr *tatum.APIError
    if errors.As(err, &apiErr) {
        fmt.Println(apiErr.StatusCode, apiErr.ErrorCode, apiErr.Message)
    }
}

The client automatically retries on 429, 502, 503, 504 responses using exponential backoff.

Pagination

txs, err := client.Transactions.GetHistory(ctx, transactions.HistoryRequest{
    Address:  "0x...",
    Chain:    "ethereum",
    PageSize: 50,
    Cursor:   "",
})

Pass the cursor from the previous response to fetch the next page.

Client Options

client, err := tatum.NewClient("your-api-key",
    tatum.WithBaseURL("https://api.tatum.io"),
    tatum.WithTimeout(15*time.Second),
    tatum.WithRetries(5),
    tatum.WithUserAgent("my-app/1.0"),
    tatum.WithRPCBaseURL("https://%s-%s.gateway.tatum.io/"),
)

Requirements

License

MIT