Skip to content

Commit 9827b5f

Browse files
authored
Refactor lumera client (#23)
* Refactor lumera client * remove go mod
1 parent d54e4ea commit 9827b5f

27 files changed

+731
-838
lines changed

lumera/Readme.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Lumera Client
2+
3+
A Go client for interacting with the Lumera blockchain.
4+
5+
## Features
6+
7+
- Connect to Lumera nodes via gRPC
8+
- Interact with all Lumera modules:
9+
- Action module - manage and query action data
10+
- SuperNode module - interact with supernodes
11+
- Transaction module - broadcast and query transactions
12+
- Node module - query node status and blockchain info
13+
- Configurable connection options
14+
- Clean, modular API design with clear separation of interfaces and implementations
15+
16+
## Installation
17+
18+
```bash
19+
go get github.com/LumeraProtocol/lumera-client
20+
```
21+
22+
## Quick Start
23+
24+
```go
25+
package main
26+
27+
import (
28+
"context"
29+
"fmt"
30+
"log"
31+
32+
"github.com/LumeraProtocol/lumera-client/client"
33+
)
34+
35+
func main() {
36+
// Create a context
37+
ctx := context.Background()
38+
39+
// Initialize the client with options
40+
lumeraClient, err := client.NewClient(
41+
ctx,
42+
client.WithGRPCAddr("localhost:9090"),
43+
client.WithChainID("lumera-mainnet"),
44+
client.WithTimeout(30),
45+
)
46+
if err != nil {
47+
log.Fatalf("Failed to create Lumera client: %v", err)
48+
}
49+
defer lumeraClient.Close()
50+
51+
// Get the latest block height
52+
latestBlock, err := lumeraClient.Node().GetLatestBlock(ctx)
53+
if err != nil {
54+
log.Fatalf("Failed to get latest block: %v", err)
55+
}
56+
57+
fmt.Printf("Latest block height: %d\n", latestBlock.Block.Header.Height)
58+
}
59+
```
60+
61+
## Examples
62+
63+
The repository includes example applications demonstrating how to use the client:
64+
65+
- **Basic Example**: Shows simple queries and interactions with the Lumera blockchain
66+
- **Advanced Example**: Demonstrates a complete transaction flow with error handling and retries
67+
68+
To run the examples:
69+
70+
```bash
71+
# Build and run the basic example
72+
make run-basic
73+
74+
# Build and run the advanced example
75+
make run-advanced
76+
```
77+
78+
## Project Structure
79+
80+
```
81+
lumera-client/
82+
│ # Core client package
83+
│ interface.go # Client interface definitions
84+
│ client.go # Client implementation
85+
│ config.go # Configuration types
86+
│ options.go # Option functions
87+
│ connection.go # Connection handling
88+
├── modules/ # Module-specific packages
89+
│ ├── action/ # Action module
90+
│ ├── node/ # Node module
91+
│ ├── supernode/ # SuperNode module
92+
│ └── tx/ # Transaction module
93+
└── examples/ # Example applications
94+
└── main.go # Basic usage example
95+
96+
```
97+
98+
## Module Documentation
99+
100+
### Action Module
101+
102+
The Action module allows you to interact with Lumera actions, which are the core data processing units in the Lumera blockchain.
103+
104+
```go
105+
// Get action by ID
106+
action, err := client.Action().GetAction(ctx, "action-id-123")
107+
108+
// Calculate fee for action with specific data size
109+
fee, err := client.Action().GetActionFee(ctx, "1024") // 1KB data
110+
```
111+
112+
### Node Module
113+
114+
The Node module provides information about the blockchain and node status.
115+
116+
```go
117+
// Get latest block
118+
block, err := client.Node().GetLatestBlock(ctx)
119+
120+
// Get specific block by height
121+
block, err := client.Node().GetBlockByHeight(ctx, 1000)
122+
123+
// Get node information
124+
nodeInfo, err := client.Node().GetNodeInfo(ctx)
125+
```
126+
127+
### SuperNode Module
128+
129+
The SuperNode module allows you to interact with Lumera supernodes.
130+
131+
```go
132+
// Get top supernodes for a specific block
133+
topNodes, err := client.SuperNode().GetTopSuperNodesForBlock(ctx, 1000)
134+
135+
// Get specific supernode by address
136+
node, err := client.SuperNode().GetSuperNode(ctx, "validator-address")
137+
```
138+
139+
### Transaction Module
140+
141+
The Transaction module handles transaction broadcasting and querying.
142+
143+
```go
144+
// Broadcast a signed transaction
145+
resp, err := client.Tx().BroadcastTx(ctx, txBytes, sdktx.BroadcastMode_BROADCAST_MODE_SYNC)
146+
147+
// Simulate a transaction
148+
sim, err := client.Tx().SimulateTx(ctx, txBytes)
149+
150+
// Get transaction by hash
151+
tx, err := client.Tx().GetTx(ctx, "tx-hash")
152+
```
153+

lumera/client.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package lumera
2+
3+
import (
4+
"context"
5+
6+
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/action"
7+
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/node"
8+
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/supernode"
9+
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/tx"
10+
)
11+
12+
// lumeraClient implements the Client interface
13+
type lumeraClient struct {
14+
cfg *Config
15+
actionMod action.Module
16+
supernodeMod supernode.Module
17+
txMod tx.Module
18+
nodeMod node.Module
19+
conn Connection
20+
}
21+
22+
// newClient creates a new Lumera client with provided options
23+
func newClient(ctx context.Context, opts ...Option) (Client, error) {
24+
cfg := DefaultConfig()
25+
26+
// Apply all options
27+
for _, opt := range opts {
28+
opt(cfg)
29+
}
30+
31+
// Create a single gRPC connection to be shared by all modules
32+
conn, err := newGRPCConnection(ctx, cfg.GRPCAddr)
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
// Initialize all module clients with the shared connection
38+
actionModule, err := action.NewModule(conn.GetConn())
39+
if err != nil {
40+
conn.Close()
41+
return nil, err
42+
}
43+
44+
supernodeModule, err := supernode.NewModule(conn.GetConn())
45+
if err != nil {
46+
conn.Close()
47+
return nil, err
48+
}
49+
50+
txModule, err := tx.NewModule(conn.GetConn())
51+
if err != nil {
52+
conn.Close()
53+
return nil, err
54+
}
55+
56+
nodeModule, err := node.NewModule(conn.GetConn())
57+
if err != nil {
58+
conn.Close()
59+
return nil, err
60+
}
61+
62+
return &lumeraClient{
63+
cfg: cfg,
64+
actionMod: actionModule,
65+
supernodeMod: supernodeModule,
66+
txMod: txModule,
67+
nodeMod: nodeModule,
68+
conn: conn,
69+
}, nil
70+
}
71+
72+
// Action returns the Action module client
73+
func (c *lumeraClient) Action() action.Module {
74+
return c.actionMod
75+
}
76+
77+
// SuperNode returns the SuperNode module client
78+
func (c *lumeraClient) SuperNode() supernode.Module {
79+
return c.supernodeMod
80+
}
81+
82+
// Tx returns the Transaction module client
83+
func (c *lumeraClient) Tx() tx.Module {
84+
return c.txMod
85+
}
86+
87+
// Node returns the Node module client
88+
func (c *lumeraClient) Node() node.Module {
89+
return c.nodeMod
90+
}
91+
92+
// Close closes all connections
93+
func (c *lumeraClient) Close() error {
94+
if c.conn != nil {
95+
return c.conn.Close()
96+
}
97+
return nil
98+
}

lumera/config.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package lumera
2+
3+
// Config holds all the configuration needed for the client
4+
type Config struct {
5+
// GRPCAddr is the gRPC endpoint address
6+
GRPCAddr string
7+
8+
// ChainID is the ID of the chain
9+
ChainID string
10+
11+
// Timeout is the default request timeout in seconds
12+
Timeout int
13+
}
14+
15+
// DefaultConfig returns a default configuration
16+
func DefaultConfig() *Config {
17+
return &Config{
18+
GRPCAddr: "localhost:9090",
19+
ChainID: "lumera",
20+
Timeout: 10,
21+
}
22+
}

lumera/connection.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package lumera
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
"google.golang.org/grpc"
9+
"google.golang.org/grpc/credentials/insecure"
10+
)
11+
12+
// Connection defines the interface for a client connection
13+
type Connection interface {
14+
Close() error
15+
GetConn() *grpc.ClientConn
16+
}
17+
18+
// grpcConnection wraps a gRPC connection
19+
type grpcConnection struct {
20+
conn *grpc.ClientConn
21+
}
22+
23+
// newGRPCConnection creates a new gRPC connection
24+
func newGRPCConnection(ctx context.Context, addr string) (Connection, error) {
25+
dialCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
26+
defer cancel()
27+
28+
// Note: Cosmos SDK doesn't support TLS for gRPC so we use insecure credentials
29+
conn, err := grpc.DialContext(
30+
dialCtx,
31+
addr,
32+
grpc.WithTransportCredentials(insecure.NewCredentials()),
33+
grpc.WithBlock(),
34+
)
35+
if err != nil {
36+
return nil, fmt.Errorf("failed to connect to gRPC server: %w", err)
37+
}
38+
39+
return &grpcConnection{
40+
conn: conn,
41+
}, nil
42+
}
43+
44+
// Close closes the gRPC connection
45+
func (c *grpcConnection) Close() error {
46+
if c.conn != nil {
47+
return c.conn.Close()
48+
}
49+
return nil
50+
}
51+
52+
// GetConn returns the underlying gRPC connection
53+
func (c *grpcConnection) GetConn() *grpc.ClientConn {
54+
return c.conn
55+
}

lumera/interface.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package lumera
2+
3+
import (
4+
"context"
5+
6+
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/action"
7+
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/node"
8+
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/supernode"
9+
"github.com/LumeraProtocol/supernode/pkg/lumera/modules/tx"
10+
)
11+
12+
// Client defines the main interface for interacting with Lumera blockchain
13+
type Client interface {
14+
// Module accessors
15+
Action() action.Module
16+
SuperNode() supernode.Module
17+
Tx() tx.Module
18+
Node() node.Module
19+
20+
Close() error
21+
}
22+
23+
// NewClient creates a new Lumera client with provided options
24+
func NewClient(ctx context.Context, opts ...Option) (Client, error) {
25+
return newClient(ctx, opts...)
26+
}

0 commit comments

Comments
 (0)