Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions lumera/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Lumera Client

A Go client for interacting with the Lumera blockchain.

## Features

- Connect to Lumera nodes via gRPC
- Interact with all Lumera modules:
- Action module - manage and query action data
- SuperNode module - interact with supernodes
- Transaction module - broadcast and query transactions
- Node module - query node status and blockchain info
- Configurable connection options
- Clean, modular API design with clear separation of interfaces and implementations

## Installation

```bash
go get github.com/LumeraProtocol/lumera-client
```

## Quick Start

```go
package main

import (
"context"
"fmt"
"log"

"github.com/LumeraProtocol/lumera-client/client"
)

func main() {
// Create a context
ctx := context.Background()

// Initialize the client with options
lumeraClient, err := client.NewClient(
ctx,
client.WithGRPCAddr("localhost:9090"),
client.WithChainID("lumera-mainnet"),
client.WithTimeout(30),
)
if err != nil {
log.Fatalf("Failed to create Lumera client: %v", err)
}
defer lumeraClient.Close()

// Get the latest block height
latestBlock, err := lumeraClient.Node().GetLatestBlock(ctx)
if err != nil {
log.Fatalf("Failed to get latest block: %v", err)
}

fmt.Printf("Latest block height: %d\n", latestBlock.Block.Header.Height)
}
```

## Examples

The repository includes example applications demonstrating how to use the client:

- **Basic Example**: Shows simple queries and interactions with the Lumera blockchain
- **Advanced Example**: Demonstrates a complete transaction flow with error handling and retries

To run the examples:

```bash
# Build and run the basic example
make run-basic

# Build and run the advanced example
make run-advanced
```

## Project Structure

```
lumera-client/
│ # Core client package
│ interface.go # Client interface definitions
│ client.go # Client implementation
│ config.go # Configuration types
│ options.go # Option functions
│ connection.go # Connection handling
├── modules/ # Module-specific packages
│ ├── action/ # Action module
│ ├── node/ # Node module
│ ├── supernode/ # SuperNode module
│ └── tx/ # Transaction module
└── examples/ # Example applications
└── main.go # Basic usage example

```

## Module Documentation

### Action Module

The Action module allows you to interact with Lumera actions, which are the core data processing units in the Lumera blockchain.

```go
// Get action by ID
action, err := client.Action().GetAction(ctx, "action-id-123")

// Calculate fee for action with specific data size
fee, err := client.Action().GetActionFee(ctx, "1024") // 1KB data
```

### Node Module

The Node module provides information about the blockchain and node status.

```go
// Get latest block
block, err := client.Node().GetLatestBlock(ctx)

// Get specific block by height
block, err := client.Node().GetBlockByHeight(ctx, 1000)

// Get node information
nodeInfo, err := client.Node().GetNodeInfo(ctx)
```

### SuperNode Module

The SuperNode module allows you to interact with Lumera supernodes.

```go
// Get top supernodes for a specific block
topNodes, err := client.SuperNode().GetTopSuperNodesForBlock(ctx, 1000)

// Get specific supernode by address
node, err := client.SuperNode().GetSuperNode(ctx, "validator-address")
```

### Transaction Module

The Transaction module handles transaction broadcasting and querying.

```go
// Broadcast a signed transaction
resp, err := client.Tx().BroadcastTx(ctx, txBytes, sdktx.BroadcastMode_BROADCAST_MODE_SYNC)

// Simulate a transaction
sim, err := client.Tx().SimulateTx(ctx, txBytes)

// Get transaction by hash
tx, err := client.Tx().GetTx(ctx, "tx-hash")
```

98 changes: 98 additions & 0 deletions lumera/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package lumera

import (
"context"

"github.com/LumeraProtocol/supernode/pkg/lumera/modules/action"
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/node"
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/supernode"
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/tx"
)

// lumeraClient implements the Client interface
type lumeraClient struct {
cfg *Config
actionMod action.Module
supernodeMod supernode.Module
txMod tx.Module
nodeMod node.Module
conn Connection
}

// newClient creates a new Lumera client with provided options
func newClient(ctx context.Context, opts ...Option) (Client, error) {
cfg := DefaultConfig()

// Apply all options
for _, opt := range opts {
opt(cfg)
}

// Create a single gRPC connection to be shared by all modules
conn, err := newGRPCConnection(ctx, cfg.GRPCAddr)
if err != nil {
return nil, err
}

// Initialize all module clients with the shared connection
actionModule, err := action.NewModule(conn.GetConn())
if err != nil {
conn.Close()
return nil, err
}

supernodeModule, err := supernode.NewModule(conn.GetConn())
if err != nil {
conn.Close()
return nil, err
}

txModule, err := tx.NewModule(conn.GetConn())
if err != nil {
conn.Close()
return nil, err
}

nodeModule, err := node.NewModule(conn.GetConn())
if err != nil {
conn.Close()
return nil, err
}

return &lumeraClient{
cfg: cfg,
actionMod: actionModule,
supernodeMod: supernodeModule,
txMod: txModule,
nodeMod: nodeModule,
conn: conn,
}, nil
}

// Action returns the Action module client
func (c *lumeraClient) Action() action.Module {
return c.actionMod
}

// SuperNode returns the SuperNode module client
func (c *lumeraClient) SuperNode() supernode.Module {
return c.supernodeMod
}

// Tx returns the Transaction module client
func (c *lumeraClient) Tx() tx.Module {
return c.txMod
}

// Node returns the Node module client
func (c *lumeraClient) Node() node.Module {
return c.nodeMod
}

// Close closes all connections
func (c *lumeraClient) Close() error {
if c.conn != nil {
return c.conn.Close()
}
return nil
}
22 changes: 22 additions & 0 deletions lumera/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package lumera

// Config holds all the configuration needed for the client
type Config struct {
// GRPCAddr is the gRPC endpoint address
GRPCAddr string

// ChainID is the ID of the chain
ChainID string

// Timeout is the default request timeout in seconds
Timeout int
}

// DefaultConfig returns a default configuration
func DefaultConfig() *Config {
return &Config{
GRPCAddr: "localhost:9090",
ChainID: "lumera",
Timeout: 10,
}
}
55 changes: 55 additions & 0 deletions lumera/connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package lumera

import (
"context"
"fmt"
"time"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)

// Connection defines the interface for a client connection
type Connection interface {
Close() error
GetConn() *grpc.ClientConn
}

// grpcConnection wraps a gRPC connection
type grpcConnection struct {
conn *grpc.ClientConn
}

// newGRPCConnection creates a new gRPC connection
func newGRPCConnection(ctx context.Context, addr string) (Connection, error) {
dialCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()

// Note: Cosmos SDK doesn't support TLS for gRPC so we use insecure credentials
conn, err := grpc.DialContext(
dialCtx,
addr,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(),
)
if err != nil {
return nil, fmt.Errorf("failed to connect to gRPC server: %w", err)
}

return &grpcConnection{
conn: conn,
}, nil
}

// Close closes the gRPC connection
func (c *grpcConnection) Close() error {
if c.conn != nil {
return c.conn.Close()
}
return nil
}

// GetConn returns the underlying gRPC connection
func (c *grpcConnection) GetConn() *grpc.ClientConn {
return c.conn
}
26 changes: 26 additions & 0 deletions lumera/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package lumera

import (
"context"

"github.com/LumeraProtocol/supernode/pkg/lumera/modules/action"
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/node"
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/supernode"
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/tx"
)

// Client defines the main interface for interacting with Lumera blockchain
type Client interface {
// Module accessors
Action() action.Module
SuperNode() supernode.Module
Tx() tx.Module
Node() node.Module

Close() error
}

// NewClient creates a new Lumera client with provided options
func NewClient(ctx context.Context, opts ...Option) (Client, error) {
return newClient(ctx, opts...)
}
Loading