Skip to content

refrakts/sparkscan-api-go

Repository files navigation

sparkscan-api-go

CI Go Reference

Go client library for the Sparkscan API (v3.4.0) -- an explorer for Spark wallets on Bitcoin.

  • Fully generated from the OpenAPI spec using ogen -- update the spec and run go generate
  • All 19 endpoints covered across v1 and v2 APIs (transactions, addresses, tokens, historical data, stats)
  • Pagination iterators using Go 1.23+ iter.Seq2 for both offset-based (v1) and cursor-based (v2) endpoints
  • Functional options for API key auth, custom HTTP clients, and timeouts

Install

go get github.com/refrakts/sparkscan-api-go

Requires Go 1.25+.

Quick start

package main

import (
    "context"
    "fmt"
    "log"

    sparkscan "github.com/refrakts/sparkscan-api-go"
    "github.com/refrakts/sparkscan-api-go/ogen"
)

func main() {
    client, err := sparkscan.NewClient("https://api.sparkscan.io")
    if err != nil {
        log.Fatal(err)
    }

    stats, err := client.GetV2StatsSummary(context.Background(), ogen.GetV2StatsSummaryParams{
        Network: ogen.GetV2StatsSummaryNetworkMAINNET,
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Active accounts: %d\n", stats.ActiveAccounts)
    fmt.Printf("TVL: $%.2f\n", stats.TotalValueLockedUsd)
    fmt.Printf("BTC price: $%.2f\n", stats.CurrentBtcPriceUsd)
}

Usage

Client options

client, err := sparkscan.NewClient("https://api.sparkscan.io",
    sparkscan.WithAPIKey("your-api-key"),
    sparkscan.WithHTTPClient(customClient),
    sparkscan.WithTimeout(10 * time.Second),
)

Fetching transactions

// Latest transactions
txs, err := client.GetV1TxLatest(ctx, ogen.GetV1TxLatestParams{
    Limit: ogen.NewOptInt(10),
})

// Single transaction by ID
tx, err := client.GetV1TxByTxid(ctx, ogen.GetV1TxByTxidParams{
    Txid: "abc123...",
})

Address operations

// Address summary
info, err := client.GetV1AddressByAddress(ctx, ogen.GetV1AddressByAddressParams{
    Address: "sp1...",
})

// Token holdings
tokens, err := client.GetV1AddressByAddressTokens(ctx, ogen.GetV1AddressByAddressTokensParams{
    Address: "sp1...",
})

Pagination

Paginated endpoints have List* methods returning iter.Seq2 iterators that handle page fetching automatically:

// Offset-based (v1) -- iterates all pages
params := ogen.GetV1AddressByAddressTransactionsParams{Address: "sp1..."}
for tx, err := range client.ListV1AddressByAddressTransactions(ctx, params) {
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(tx.ID, tx.Type)
}

// Cursor-based (v2) -- iterates all pages
params := ogen.GetV2TokensListParams{Network: ogen.GetV2TokensListNetworkMAINNET}
for token, err := range client.ListV2TokensList(ctx, params) {
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(token.Name)
}

For single-page access, use the non-List variant (e.g. GetV1AddressByAddressTransactions) which returns the raw paginated response including metadata.

Token lookup

result, err := client.GetV1TokensByIdentifier(ctx, ogen.GetV1TokensByIdentifierParams{
    Identifier: "token-id",
})

// Response is a union: single detail or search results
if detail, ok := result.GetGetV1TokensByIdentifierOK0(); ok {
    fmt.Printf("%s: supply %s\n", detail.Metadata.Name, detail.TotalSupply)
}

Historical data

params := ogen.GetV2HistoricalSatsBalancesByAddressParams{
    Address: "sp1...",
    Network: ogen.GetV2HistoricalSatsBalancesByAddressNetworkMAINNET,
}
for point, err := range client.ListV2HistoricalSatsBalancesByAddress(ctx, params) {
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("t=%d balance=%s\n", point.T, point.B)
}

Error handling

API errors are returned as *sparkscan.APIError:

tx, err := client.GetV1TxByTxid(ctx, params)
if err != nil {
    var apiErr *sparkscan.APIError
    if errors.As(err, &apiErr) {
        fmt.Printf("API error %d: %s\n", apiErr.StatusCode, apiErr.Message)
    }
}

Raw client access

For advanced use cases, access the underlying ogen client directly:

raw := client.Raw()
// Call ogen methods with full response type switching

API coverage

All v1 and v2 endpoints are supported:

Domain Endpoints
Transactions GetV1TxLatest, GetV1TxByTxid, GetV2TxLatest, GetV2TxByTxid
Addresses GetV1AddressByAddress, GetV1AddressByAddressTransactions, GetV1AddressByAddressTokens, GetV2AddressByAddressTransactions
Tokens GetV1TokensByIdentifier, GetV1TokensByIdentifierHolders, GetV1TokensByIdentifierTransactions, PostV1TokensMetadataBatch, PostV1TokensIssuerLookup, GetV2TokensList
Historical GetV2HistoricalSatsBalancesByAddress, GetV2HistoricalTokensBalancesByAddressByTokenIdentifier, GetV2HistoricalNetWorthByAddress
Stats GetV2StatsSummary, GetV2StatsTpv

Paginated endpoints also have List* iterator variants.

Development

Regenerating

Everything regenerates from the OpenAPI spec:

go generate ./...

This runs three steps:

  1. cmd/normalize-spec -- pre-processes the spec to fix ogen-incompatible patterns (anyOf unions, invalid types, merges multi-object variants)
  2. ogen -- generates the raw Go client and types in ogen/
  3. cmd/generate-wrapper -- generates wrapper_gen.go with error-handling methods and pagination iterators

All generated code is checked in so consumers can go get without running generation.

Project structure

client.go                  Hand-written: NewClient, options, auth, error types
options.go                 Hand-written: WithAPIKey, WithHTTPClient, WithTimeout
pagination.go              Hand-written: PaginateOffset, PaginateCursor helpers
wrapper_gen.go             Generated: endpoint methods + List* iterators
ogen/                      Generated: raw ogen client, types, JSON codecs
api/schema.json            Upstream OpenAPI spec (input)
cmd/normalize-spec/        Schema pre-processor
cmd/generate-wrapper/      Wrapper code generator

License

MIT

About

Go client library for the Sparkscan API — a Spark wallet explorer on Bitcoin

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages