Go SDK

The Omne Go SDK delivers high-performance blockchain integration for Go applications. Built for scalability, concurrency, and production-grade reliability.

Installation

Go Module Installation

# Initialize Go module (if not already done) go mod init your-project # Install Omne Go SDK go get github.com/omne-foundation/omne-go-sdk # Install specific version go get github.com/omne-foundation/omne-go-sdk@v1.2.3 # Update dependencies go mod tidy

Requirements

go.modgo
module your-project go 1.19 require ( github.com/omne-foundation/omne-go-sdk v1.2.3 github.com/gorilla/websocket v1.5.0 // Auto-installed github.com/btcsuite/btcd v0.23.0 // Auto-installed golang.org/x/crypto v0.10.0 // Auto-installed )

Go Version Support

The SDK requires Go 1.19 or later for optimal performance and access to the latest language features. We recommend using the latest stable Go version.

Quick Start

Basic Setup

package main import ( "context" "fmt" "log" "time" "github.com/omne-foundation/omne-go-sdk/client" "github.com/omne-foundation/omne-go-sdk/types" ) func main() { // Initialize client config := &client.Config{ Network: types.TestNet, Endpoint: "https://testnet-rpc.omne.foundation", Timeout: 30 * time.Second, } omneClient, err := client.NewOmneClient(config) if err != nil { log.Fatal("Failed to create client:", err) } defer omneClient.Close() // Check connection ctx := context.Background() status, err := omneClient.GetNetworkStatus(ctx) if err != nil { log.Fatal("Failed to get network status:", err) } fmt.Printf("Connected to: %s\n", status.NetworkID) fmt.Printf("Latest block: %d\n", status.LatestBlock) }

Account Management

package main import ( "fmt" "log" "github.com/omne-foundation/omne-go-sdk/account" "github.com/omne-foundation/omne-go-sdk/wallet" ) func main() { // Generate new account acc, err := account.Generate() if err != nil { log.Fatal("Failed to generate account:", err) } fmt.Printf("Address: %s\n", acc.Address()) fmt.Printf("Public key: %s\n", acc.PublicKey()) // Import from private key privateKey := "your-private-key-hex" importedAcc, err := account.FromPrivateKey(privateKey) if err != nil { log.Fatal("Failed to import account:", err) } // Create wallet for multiple accounts w := wallet.New() w.AddAccount(acc) w.AddAccount(importedAcc) // Get account by address foundAcc, exists := w.GetAccount("omne1...") if exists { fmt.Printf("Found account: %s\n", foundAcc.Address()) } // Save/load wallet (encrypted) err = w.SaveToFile("wallet.json", "secure-password") if err != nil { log.Fatal("Failed to save wallet:", err) } loadedWallet, err := wallet.LoadFromFile("wallet.json", "secure-password") if err != nil { log.Fatal("Failed to load wallet:", err) } }

Core Features

🚀 High Performance

  • • Zero-copy operations
  • • Optimized serialization
  • • Connection pooling
  • • Efficient memory usage

⚡ Concurrency

  • • Goroutine-safe
  • • Context support
  • • Channel-based streams
  • • Worker pool patterns

🛡️ Type Safety

  • • Strong typing
  • • Compile-time checks
  • • Interface definitions
  • • Generic support

🔧 Production Ready

  • • Comprehensive logging
  • • Metrics collection
  • • Health checks
  • • Graceful shutdown

Working with Transactions

Simple Transfer

package main import ( "context" "fmt" "log" "github.com/omne-foundation/omne-go-sdk/client" "github.com/omne-foundation/omne-go-sdk/types" "github.com/omne-foundation/omne-go-sdk/transactions" ) func sendTransfer(client *client.OmneClient, account *account.Account) error { ctx := context.Background() // Create transfer transaction tx := &transactions.TransferTx{ FromAddress: account.Address(), ToAddress: "omne1recipient-address", Amount: "1000000", // 1 OMNE in micro-OMNE Fee: "auto", // Auto fee estimation Memo: "Payment for services", } // Sign transaction signedTx, err := account.Sign(tx) if err != nil { return fmt.Errorf("failed to sign transaction: %w", err) } // Broadcast to network result, err := client.Broadcast(ctx, signedTx) if err != nil { return fmt.Errorf("failed to broadcast transaction: %w", err) } fmt.Printf("Transaction hash: %s\n", result.Hash) // Wait for confirmation receipt, err := client.WaitForTransaction(ctx, result.Hash) if err != nil { return fmt.Errorf("failed to wait for transaction: %w", err) } fmt.Printf("Confirmed in block: %d\n", receipt.BlockNumber) return nil }

Concurrent Processing

package main import ( "context" "fmt" "sync" "github.com/omne-foundation/omne-go-sdk/transactions" ) type PaymentRequest struct { ToAddress string Amount string Memo string } func processBatchPayments( client *client.OmneClient, account *account.Account, payments []PaymentRequest, ) error { ctx := context.Background() // Use worker pool for concurrent processing const numWorkers = 10 paymentChan := make(chan PaymentRequest, len(payments)) resultChan := make(chan error, len(payments)) // Start workers var wg sync.WaitGroup for i := 0; i < numWorkers; i++ { wg.Add(1) go func() { defer wg.Done() for payment := range paymentChan { tx := &transactions.TransferTx{ FromAddress: account.Address(), ToAddress: payment.ToAddress, Amount: payment.Amount, Fee: "auto", Memo: payment.Memo, } signedTx, err := account.Sign(tx) if err != nil { resultChan <- err continue } result, err := client.Broadcast(ctx, signedTx) if err != nil { resultChan <- err continue } fmt.Printf("Sent payment: %s\n", result.Hash) resultChan <- nil } }() } // Send payments to workers for _, payment := range payments { paymentChan <- payment } close(paymentChan) // Wait for workers to finish go func() { wg.Wait() close(resultChan) }() // Collect results var errors []error for err := range resultChan { if err != nil { errors = append(errors, err) } } if len(errors) > 0 { return fmt.Errorf("some payments failed: %v", errors) } return nil }

Transaction Monitoring

// Monitor transaction status func monitorTransaction(client *client.OmneClient, txHash string) { ctx := context.Background() tx, err := client.GetTransaction(ctx, txHash) if err != nil { log.Printf("Failed to get transaction: %v", err) return } fmt.Printf("Status: %s\n", tx.Status) fmt.Printf("Block: %d\n", tx.BlockNumber) fmt.Printf("Confirmations: %d\n", tx.Confirmations) fmt.Printf("Gas used: %d\n", tx.GasUsed) if tx.Status == "failed" { fmt.Printf("Error: %s\n", tx.Error) } } // Subscribe to account transactions func subscribeToTransactions(client *client.OmneClient, address string) { ctx := context.Background() txChan, err := client.SubscribeTransactions(ctx, address) if err != nil { log.Fatal("Failed to subscribe to transactions:", err) } for tx := range txChan { fmt.Printf("New transaction: %s\n", tx.Hash) fmt.Printf("Amount: %s\n", tx.Amount) fmt.Printf("Direction: %s\n", tx.Direction) // "in" or "out" } }

Smart Contracts

Contract Deployment

package main import ( "context" "fmt" "github.com/omne-foundation/omne-go-sdk/contracts" ) func deployContract( client *client.OmneClient, account *account.Account, ) (*contracts.Contract, error) { ctx := context.Background() // Load contract from files contract, err := contracts.LoadFromFiles( "contract.wasm", // Bytecode file "contract.json", // ABI file ) if err != nil { return nil, fmt.Errorf("failed to load contract: %w", err) } // Set constructor arguments constructorArgs := []interface{}{ "initial_value", 1000, } // Deploy contract deployment, err := contract.Deploy(ctx, account, constructorArgs) if err != nil { return nil, fmt.Errorf("failed to deploy contract: %w", err) } fmt.Printf("Contract deployed at: %s\n", deployment.Address) return contract, nil }

Contract Interaction

// Connect to existing contract func interactWithContract(client *client.OmneClient, account *account.Account) error { ctx := context.Background() contract, err := contracts.NewContract( "omne1contract-address", contractABI, ) if err != nil { return fmt.Errorf("failed to create contract instance: %w", err) } // Read contract state (free) balance, err := contract.Call(ctx, "GetBalance", []interface{}{ "omne1user-address", }) if err != nil { return fmt.Errorf("failed to call contract: %w", err) } fmt.Printf("Balance: %v\n", balance) // Write contract state (requires transaction) result, err := contract.Execute(ctx, account, "Transfer", []interface{}{ "omne1recipient", "1000000", }, &contracts.ExecuteOptions{ Fee: "auto", }) if err != nil { return fmt.Errorf("failed to execute contract: %w", err) } fmt.Printf("Transaction hash: %s\n", result.Hash) return nil }

Event Listening

// Listen to contract events func listenToEvents(contract *contracts.Contract, account *account.Account) { ctx := context.Background() // Listen to all Transfer events eventChan, err := contract.SubscribeEvents(ctx, "Transfer", nil) if err != nil { log.Fatal("Failed to subscribe to events:", err) } for event := range eventChan { fmt.Printf("Transfer event:\n") fmt.Printf("From: %s\n", event.Data["from"]) fmt.Printf("To: %s\n", event.Data["to"]) fmt.Printf("Amount: %s\n", event.Data["amount"]) } } // Listen with filters func listenToMyTransfers(contract *contracts.Contract, account *account.Account) { ctx := context.Background() // Filter for transfers to our account filters := map[string]interface{}{ "to": account.Address(), } eventChan, err := contract.SubscribeEvents(ctx, "Transfer", filters) if err != nil { log.Fatal("Failed to subscribe to filtered events:", err) } for event := range eventChan { fmt.Printf("Received transfer: %s OMNE\n", event.Data["amount"]) } }

Context & Cancellation

Timeout Handling

package main import ( "context" "fmt" "time" ) func operationWithTimeout(client *client.OmneClient) error { // Create context with timeout ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() // Operation will be cancelled after 10 seconds status, err := client.GetNetworkStatus(ctx) if err != nil { if ctx.Err() == context.DeadlineExceeded { return fmt.Errorf("operation timed out") } return fmt.Errorf("operation failed: %w", err) } fmt.Printf("Network status: %v\n", status) return nil } func cancellableOperation(client *client.OmneClient) error { ctx, cancel := context.WithCancel(context.Background()) // Cancel operation after 5 seconds go func() { time.Sleep(5 * time.Second) cancel() }() // This operation can be cancelled balance, err := client.GetBalance(ctx, "omne1address") if err != nil { if ctx.Err() == context.Canceled { return fmt.Errorf("operation was cancelled") } return fmt.Errorf("operation failed: %w", err) } fmt.Printf("Balance: %s\n", balance.Amount) return nil }

Graceful Shutdown

package main import ( "context" "fmt" "os" "os/signal" "sync" "syscall" "time" ) func gracefulService(client *client.OmneClient) { // Create context for graceful shutdown ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Handle shutdown signals sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) var wg sync.WaitGroup // Start monitoring goroutine wg.Add(1) go func() { defer wg.Done() txChan, err := client.SubscribeNewTransactions(ctx) if err != nil { fmt.Printf("Failed to subscribe to transactions: %v\n", err) return } for { select { case tx := <-txChan: fmt.Printf("New transaction: %s\n", tx.Hash) case <-ctx.Done(): fmt.Println("Stopping transaction monitoring...") return } } }() // Wait for shutdown signal <-sigChan fmt.Println("Received shutdown signal...") // Cancel context to stop all operations cancel() // Wait for all goroutines to finish with timeout done := make(chan struct{}) go func() { wg.Wait() close(done) }() select { case <-done: fmt.Println("All goroutines stopped gracefully") case <-time.After(10 * time.Second): fmt.Println("Timeout waiting for goroutines to stop") } // Close client connection client.Close() fmt.Println("Shutdown complete") }

Error Handling

Error Types

package main import ( "errors" "fmt" "github.com/omne-foundation/omne-go-sdk/errors" ) func handleErrors(client *client.OmneClient, account *account.Account) { ctx := context.Background() _, err := client.Transfer(ctx, &transactions.TransferTx{ FromAddress: account.Address(), ToAddress: "invalid-address", Amount: "1000000", }) if err != nil { // Check specific error types var validationErr *errors.ValidationError var networkErr *errors.NetworkError var txErr *errors.TransactionError switch { case errors.As(err, &validationErr): fmt.Printf("Validation failed: %s\n", validationErr.Message) fmt.Printf("Field: %s\n", validationErr.Field) fmt.Printf("Value: %v\n", validationErr.Value) case errors.As(err, &networkErr): fmt.Printf("Network error: %s\n", networkErr.Message) fmt.Printf("Status code: %d\n", networkErr.StatusCode) fmt.Printf("Retryable: %t\n", networkErr.Retryable) case errors.As(err, &txErr): fmt.Printf("Transaction failed: %s\n", txErr.Message) fmt.Printf("Code: %d\n", txErr.Code) fmt.Printf("Gas used: %d\n", txErr.GasUsed) default: fmt.Printf("Unknown error: %v\n", err) } } }

Retry Logic

package main import ( "context" "fmt" "time" "github.com/omne-foundation/omne-go-sdk/errors" ) func retryWithBackoff( ctx context.Context, operation func() error, maxRetries int, baseDelay time.Duration, ) error { var lastErr error for attempt := 0; attempt <= maxRetries; attempt++ { if err := operation(); err != nil { lastErr = err // Check if error is retryable var networkErr *errors.NetworkError if errors.As(err, &networkErr) && networkErr.Retryable { if attempt < maxRetries { delay := baseDelay * time.Duration(1<<attempt) // Exponential backoff select { case <-time.After(delay): continue case <-ctx.Done(): return ctx.Err() } } } return err } return nil } return lastErr } // Usage example func reliableTransfer(client *client.OmneClient, account *account.Account) error { return retryWithBackoff( context.Background(), func() error { _, err := client.Transfer(context.Background(), &transactions.TransferTx{ FromAddress: account.Address(), ToAddress: "omne1recipient", Amount: "1000000", }) return err }, 3, // max retries 1*time.Second, // base delay ) }

Testing

Mock Client

package main import ( "context" "testing" "github.com/omne-foundation/omne-go-sdk/testing" "github.com/omne-foundation/omne-go-sdk/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestTransfer(t *testing.T) { // Create mock client mockClient := testing.NewMockOmneClient() // Set up mock responses mockClient.MockBalance("omne1test-address", &types.Balance{ Amount: "1000000", Denom: "uomne", }) mockClient.MockTransactionResult(&types.TransactionResult{ Hash: "0x123...", Status: "success", }) // Test transfer account := testing.GenerateMockAccount() result, err := mockClient.Transfer(context.Background(), &transactions.TransferTx{ FromAddress: account.Address(), ToAddress: "omne1recipient", Amount: "500000", }) require.NoError(t, err) assert.Equal(t, "0x123...", result.Hash) assert.Equal(t, "success", result.Status) } func TestBalanceCheck(t *testing.T) { mockClient := testing.NewMockOmneClient() expectedBalance := &types.Balance{ Amount: "1000000", Denom: "uomne", } mockClient.MockBalance("omne1test-address", expectedBalance) balance, err := mockClient.GetBalance(context.Background(), "omne1test-address") require.NoError(t, err) assert.Equal(t, expectedBalance.Amount, balance.Amount) assert.Equal(t, expectedBalance.Denom, balance.Denom) }

Integration Tests

package main import ( "context" "os" "testing" "time" "github.com/omne-foundation/omne-go-sdk/client" "github.com/omne-foundation/omne-go-sdk/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestIntegration(t *testing.T) { // Skip integration tests in short mode if testing.Short() { t.Skip("Skipping integration test in short mode") } // Set up test client config := &client.Config{ Network: types.TestNet, Endpoint: os.Getenv("OMNE_TESTNET_ENDPOINT"), Timeout: 30 * time.Second, } omneClient, err := client.NewOmneClient(config) require.NoError(t, err) defer omneClient.Close() ctx := context.Background() t.Run("NetworkConnection", func(t *testing.T) { status, err := omneClient.GetNetworkStatus(ctx) require.NoError(t, err) assert.Contains(t, status.NetworkID, "omne-testnet") assert.Greater(t, status.LatestBlock, uint64(0)) }) t.Run("AccountBalance", func(t *testing.T) { testAddress := os.Getenv("OMNE_TEST_ADDRESS") if testAddress == "" { t.Skip("OMNE_TEST_ADDRESS not set") } balance, err := omneClient.GetBalance(ctx, testAddress) require.NoError(t, err) assert.Equal(t, "uomne", balance.Denom) assert.GreaterOrEqual(t, balance.Amount, "0") }) t.Run("SmallTransfer", func(t *testing.T) { testPrivateKey := os.Getenv("OMNE_TEST_PRIVATE_KEY") if testPrivateKey == "" { t.Skip("OMNE_TEST_PRIVATE_KEY not set") } account, err := account.FromPrivateKey(testPrivateKey) require.NoError(t, err) // Small test transfer result, err := omneClient.Transfer(ctx, &transactions.TransferTx{ FromAddress: account.Address(), ToAddress: "omne1testrecipient", Amount: "1000", // 0.001 OMNE }) require.NoError(t, err) assert.NotEmpty(t, result.Hash) receipt, err := omneClient.WaitForTransaction(ctx, result.Hash) require.NoError(t, err) assert.Equal(t, "success", receipt.Status) }) }

Advanced Configuration

Client Configuration

package main import ( "time" "github.com/omne-foundation/omne-go-sdk/client" "github.com/omne-foundation/omne-go-sdk/types" ) func main() { config := &client.Config{ // Network settings Network: types.MainNet, Endpoint: "https://rpc.omne.foundation", // Request settings Timeout: 30 * time.Second, MaxRetries: 3, RetryDelay: 1 * time.Second, // WebSocket settings WSEndpoint: "wss://ws.omne.foundation", WSReconnect: true, WSReconnectDelay: 5 * time.Second, // Fee settings DefaultFee: "1000", FeeMultiplier: 1.2, // Gas settings DefaultGas: 200000, GasMultiplier: 1.5, // Connection pool settings MaxIdleConns: 10, MaxConnsPerHost: 100, IdleConnTimeout: 90 * time.Second, // TLS settings InsecureSkipVerify: false, // Custom HTTP headers Headers: map[string]string{ "User-Agent": "MyApp/1.0.0", "X-Custom-Header": "value", }, // Logging LogLevel: "info", Logger: customLogger, } client, err := client.NewOmneClient(config) if err != nil { log.Fatal("Failed to create client:", err) } defer client.Close() }

Custom Network

// Define custom network customNetwork := &types.Network{ NetworkID: "omne-devnet-1", ChainID: "omne-devnet", RPCEndpoint: "http://localhost:26657", WSEndpoint: "ws://localhost:26657/websocket", AddressPrefix: "omne", CoinType: 118, GasPrice: "0.001", FeeDenom: "uomne", } config := &client.Config{ Network: customNetwork, Endpoint: customNetwork.RPCEndpoint, } client, err := client.NewOmneClient(config)

Next Steps

API Reference

Complete Go API documentation with all packages and functions.

View API docs →

Examples

Go examples and implementation patterns.

Browse examples →

GitHub

Source code, issues, and contributions welcome.

View on GitHub →