Skip to content

LumeraProtocol/sdk-go

Repository files navigation

Lumera Go SDK

Official Go SDK for the Lumera Protocol - a next-generation blockchain platform for AI and decentralized storage.

Features

  • 🔗 Unified APIs — Single interface unifying Lumera gRPC, SuperNode SDK, and SnApi
  • 📦 Type-Safe — Full Go type definitions for all Lumera modules
  • 🚀 High-Level API — Simple methods for complex operations
  • 🔐 Secure — Built on Cosmos SDK's proven cryptography
  • 📝 Well-Documented — Comprehensive examples and documentation

Unified APIs

This SDK unifies three distinct Lumera interfaces behind one easy client:

Installation

go get github.com/LumeraProtocol/sdk-go

Quick Start

package main

import (
    "context"
    "log"
    
    "github.com/cosmos/cosmos-sdk/crypto/keyring"
    lumerasdk "github.com/LumeraProtocol/sdk-go/client"
)

func main() {
    ctx := context.Background()
    
    // Initialize keyring (for queries-only flows, any key name/address placeholders are fine)
    kr, err := keyring.New("lumera", "test", "/tmp", nil)
    if err != nil {
        log.Fatal(err)
    }
    
    // Create client
    client, err := lumerasdk.New(ctx, lumerasdk.Config{
        ChainID:      "lumera-testnet-2",
        GRPCEndpoint: "localhost:9090",
        RPCEndpoint:  "http://localhost:26657",
        Address:      "lumera1abc...",
        KeyName:      "my-key",
    }, kr, lumerasdk.WithLogger(zap.NewExample()))
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
    
    // Query an action via Lumera gRPC API
    action, err := client.Blockchain.Action.GetAction(ctx, "action-123")
    if err != nil {
        log.Fatal(err)
    }
    
    log.Printf("Action: %+v", action)
}

Note: For Cascade file operations (SuperNode SDK + SnApi), see:

ICA Cascade Flow (Upload/Download)

If you need to register Cascade actions via an interchain account (ICS-27) while still using the SDK for metadata, uploads, and downloads, the high-level flow is:

  1. Resolve the controller-chain owner address and ensure the ICA host address is registered.
  2. Fund the ICA host address on Lumera so it can pay fees.
  3. Initialize cascade.Client with ICAOwnerKeyName and ICAOwnerHRP to allow controller-chain download signatures.
  4. Build and submit MsgRequestAction over ICA, then use the returned action ID for the supernode upload.
  5. Download with a controller-chain signer (or let the client derive it).
  6. After the action is DONE, send MsgApproveAction over ICA and wait for APPROVED.

Minimal wiring (controller-chain submit helpers are application-specific):

// setup cascade client with ICA owner config
cascadeClient, err := cascade.New(ctx, cascade.Config{
    ChainID:         lumeraChainID,
    GRPCAddr:        lumeraGRPC,
    Address:         lumeraAddr,  // host chain address
    KeyName:         lumeraKeyName,
    ICAOwnerKeyName: simdKeyName, // controller chain key name
    ICAOwnerHRP:     "cosmos",    // controller chain address HRP
    Timeout:         30 * time.Second,
}, kr)

// send function submits ICA MsgRequestAction and returns action id
sendFunc := func(ctx context.Context, msg *actiontypes.MsgRequestAction, _ []byte, _ string, _ *cascade.UploadOptions) (*types.ActionResult, error) {
    actionIDs, err := sendICARequestTx(ctx, []*actiontypes.MsgRequestAction{msg})
    if err != nil {
        return nil, err
    }
    return &types.ActionResult{ActionID: actionIDs[0]}, nil
}

res, err := cascadeClient.Upload(ctx, icaAddr, nil, filePath,
    cascade.WithICACreatorAddress(icaAddr),
    cascade.WithAppPubkey(simdPubkey),
    cascade.WithICASendFunc(sendFunc),
)

// download using controller address for signature (optional override)
_, err = cascadeClient.Download(ctx, res.ActionID, downloadDir, cascade.WithDownloadSignerAddress(ownerAddr))

// approve via ICA when action is DONE
approveMsg, _ := cascade.CreateApproveActionMessage(ctx, res.ActionID, cascade.WithApproveCreator(icaAddr))
_ = sendICAApproveTx(ctx, []*actiontypes.MsgApproveAction{approveMsg})

Notes:

  • WithICASendFunc is required when using WithICACreatorAddress and/or WithAppPubkey.
  • Some chains enforce app_pubkey for ICA creators; set it to the controller-chain key pubkey.
  • The full end-to-end test lives in ../lumera/devnet/tests/hermes/ibc_hermes_ica_test.go (TestICACascadeFlow).
  • Devnet test link: lumera/devnet/tests/hermes/ibc_hermes_ica_test.go

Sending ICA RequestAction (helpers + CLI)

The SDK includes small helpers to assemble ICS-27 packets and decode acknowledgements in ica:

  • PackRequestForICA: packs MsgRequestAction into google.protobuf.Any bytes.
  • BuildICAPacketData: wraps one or more Any messages into InterchainAccountPacketData for EXECUTE_TX.
  • BuildMsgSendTx: builds controller-side MsgSendTx if you submit the tx programmatically.
  • ExtractRequestActionIDsFromAck / ExtractRequestActionIDsFromTxMsgData: pull action IDs out of acknowledgements.
  • ParseTxHashJSON, ExtractPacketInfoFromTxJSON, DecodePacketAcknowledgementJSON: CLI-friendly helpers for tx hash, packet info, and ack decoding.

Build a packet JSON file (used by the CLI) from a MsgRequestAction:

msg, _, _ := cascadeClient.CreateRequestActionMessage(ctx, icaAddr, filePath, &cascade.UploadOptions{
    ICACreatorAddress: icaAddr,
    AppPubkey:         simdPubkey,
})

anyBz, _ := ica.PackRequestForICA(msg)
var any codectypes.Any
_ = gogoproto.Unmarshal(anyBz, &any)

packet, _ := ica.BuildICAPacketData([]*codectypes.Any{&any})
packetJSON, _ := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()).MarshalJSON(&packet)
_ = os.WriteFile("ica-packet.json", packetJSON, 0o600)

Send the packet on the controller chain (example simd CLI):

simd tx interchain-accounts controller send-tx <connection-id> ica-packet.json \
  --from <controller-key> \
  --chain-id <controller-chain-id> \
  --gas auto \
  --gas-adjustment 1.3 \
  --broadcast-mode sync \
  --output json \
  --yes

Once you have the IBC acknowledgement bytes (from relayer output or packet-ack query), decode action IDs:

ids, err := ica.ExtractRequestActionIDsFromAck(ackBytes)

If you already have sdk.TxMsgData (for example, from an ack you decoded yourself), use:

ids := ica.ExtractRequestActionIDsFromTxMsgData(msgData)

Packet/ack CLI helpers (controller chain):

# tx response -> packet identifiers
simd q tx <tx-hash> --output json
# packet ack query uses port/channel/sequence from send_packet event
simd q ibc channel packet-ack <port> <channel> <sequence> --output json
txHash, _ := ica.ParseTxHashJSON(txJSON)
packetInfo, _ := ica.ExtractPacketInfoFromTxJSON(txQueryJSON)
ackBytes, _ := ica.DecodePacketAcknowledgementJSON(ackQueryJSON)
ids, _ := ica.ExtractRequestActionIDsFromAck(ackBytes)
_ = txHash
_ = packetInfo

Crypto Helpers (pkg/crypto)

Common helpers:

  • DefaultKeyringParams / NewKeyring for consistent keyring setup.
  • LoadKeyringFromMnemonic / ImportKeyFromMnemonic for mnemonic-based flows.
  • AddressFromKey to derive HRP-specific addresses without mutating global config.
  • NewDefaultTxConfig and SignTxWithKeyring for signing with Cosmos SDK builders.
import (
    "github.com/LumeraProtocol/sdk-go/constants"
    sdkcrypto "github.com/LumeraProtocol/sdk-go/pkg/crypto"
)

kr, _ := sdkcrypto.NewKeyring(sdkcrypto.DefaultKeyringParams())
addr, _ := sdkcrypto.AddressFromKey(kr, "alice", constants.LumeraAccountHRP)
_ = addr

Multi-Account Usage

Reuse the same configuration and transports for multiple local accounts via the client factory:

import (
    "context"

    "github.com/cosmos/cosmos-sdk/crypto/keyring"
    lumerasdk "github.com/LumeraProtocol/sdk-go/client"
    "github.com/LumeraProtocol/sdk-go/constants"
    sdkcrypto "github.com/LumeraProtocol/sdk-go/pkg/crypto"
)

kr, _ := keyring.New("lumera", "os", "~/.lumera", nil)
factory, err := lumerasdk.NewFactory(lumerasdk.Config{
    ChainID:      "lumera-testnet-2",
    GRPCEndpoint: "localhost:9090",
    RPCEndpoint:  "http://localhost:26657",
}, kr)

aliceAddr, _ := sdkcrypto.AddressFromKey(kr, "alice", constants.LumeraAccountHRP)
bobAddr, _ := sdkcrypto.AddressFromKey(kr, "bob", constants.LumeraAccountHRP)

alice, _ := factory.WithSigner(ctx, aliceAddr, "alice")
bob, _ := factory.WithSigner(ctx, bobAddr, "bob")
defer alice.Close()
defer bob.Close()

// Upload or query with different signers using the same underlying connections
_, _ = alice.Blockchain.Action.GetAction(ctx, "some-action-id")
_, _ = bob.Blockchain.Action.GetAction(ctx, "another-action-id")

See examples/multi-account for a runnable sample.

Examples

See the examples directory for complete working examples:

Documentation

Development

# Clone the repository
git clone https://github.com/LumeraProtocol/sdk-go.git
cd sdk-go

# Install dependencies
go mod download

# Run tests
make test

# Run linters
make lint

# Build examples
make examples

Contributing

Contributions are welcome! Please read our Contributing Guide for details.

License

Apache 2.0 - see LICENSE file for details.

Links

About

Official Go SDK for Lumera Protocol

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •