๐Ÿ—๏ธ TronLib Architecture

September 7, 2025 ยท View on GitHub

This document provides a comprehensive overview of TronLib's architecture, design principles, and component interactions. It's designed to be read after completing the Quick Start Guide and serves as a deep dive into how the library is structured.

๐Ÿ“š Learning Path

  1. Quick Start Guide - Basic usage
  2. Architecture Overview (this document) - Understanding the design
  3. Package Documentation - Detailed API references
  4. API Reference - Complete function documentation
  5. Examples - Real-world implementations

๐ŸŽฏ Design Principles

1. High-Level Abstractions ๐Ÿš€

TronLib prioritizes developer experience by providing high-level, domain-specific APIs that abstract away blockchain complexity while maintaining access to lower-level functionality when needed.

2. Modular Architecture ๐Ÿงฉ

Each package has a single responsibility and well-defined interfaces, making the library easy to understand, test, and extend.

3. Type Safety ๐Ÿ”’

Strong typing throughout the library prevents common errors, especially around address handling and numeric conversions.

4. Performance โšก

Connection pooling, caching of immutable data, and efficient gRPC communication ensure optimal performance.

๐Ÿ“‹ Component Overview

graph TB
    App[Your Application] --> Client[client]
    
    Client --> Account[account]
    Client --> TRC20[trc20]
    Client --> SmartContract[smartcontract]
    Client --> Resources[resources]
    Client --> Voting[voting]
    Client --> TRC10[trc10]
    Client --> Network[network]
    
    Account --> Types[types]
    TRC20 --> Types
    SmartContract --> Types
    
    Client --> Signer[signer]
    Account --> Utils[utils]
    TRC20 --> Utils
    SmartContract --> Utils
    
    TRC20 --> EventDecoder[eventdecoder]
    SmartContract --> EventDecoder
    
    Client --> LowLevel[client/lowlevel]
    
    subgraph "Core Foundation"
        Types
        Utils
        Signer
        EventDecoder
    end
    
    subgraph "High-Level Managers"
        Account
        TRC20
        SmartContract
        Resources
        Voting
        TRC10
        Network
    end
    
    subgraph "Transport Layer"
        Client
        LowLevel
    end

๐Ÿ”ง Core Components

๐ŸŒ Client Package (pkg/client)

Role: Central communication hub with TRON nodes

Key Features:

  • gRPC connection management with pooling
  • Automatic retry and timeout handling
  • Transaction signing and broadcasting
  • Simulation capabilities
  • Manager factory methods

Connection Management:

// Connection pool configuration
cli, err := client.NewClient("grpc://grpc.trongrid.io:50051",
    client.WithPool(5, 10),           // 5 initial, 10 max connections
    client.WithTimeout(30*time.Second)) // Default timeout

Manager Access Pattern:

accountMgr := cli.Account()          // Account operations
trc20Mgr, _ := cli.TRC20(tokenAddr)   // TRC20 operations
contractMgr := cli.SmartContract()   // Contract operations

๐Ÿท๏ธ Types Package (pkg/types)

Role: Fundamental types and constants

Core Types:

  • Address: Multi-format address handling (Base58, hex, EVM)
  • Transaction: Transaction wrapper with extensions
  • Error types and constants

Address Handling:

// Flexible address creation
addr1, _ := types.NewAddress("TxxxBase58Address")           // Base58
addr2, _ := types.NewAddressFromHex("41xxxxxxxxxxxxxxxx")   // TRON hex
addr3, _ := types.NewAddressFromBytes(addressBytes)        // Raw bytes

// Multiple output formats
base58 := addr.String()        // Base58 (default)
tronHex := addr.Hex()         // 41-prefixed hex
evmHex := addr.HexEVM()       // 0x-prefixed hex
bytes := addr.Bytes()         // 21-byte slice

๐Ÿ” Signer Package (pkg/signer)

Role: Key management and cryptographic signing operations.

Key Features:

  • Signer Interface: Defines the contract for signing data (e.g., transaction hashes, message hashes).
  • SignTx Function: A package-level utility for comprehensive transaction signing, including hashing and attaching signatures.
  • SignMessageV2 Function: A package-level utility for signing arbitrary messages using TIP-191 format (v2).
  • PrivateKeySigner: An implementation of the Signer interface for signing with a raw private key.
  • HDWalletSigner: An implementation of the Signer interface for HD wallet-based signing.
// Example: Using SignTx with a PrivateKeySigner
pk, _ := signer.NewPrivateKeySigner("0x<hex-privkey>")
tx := &core.Transaction{} // Your unsigned transaction
err := signer.SignTx(pk, tx)
// Handle error and broadcast

๐Ÿ› ๏ธ Utils Package (pkg/utils)

Role: ABI encoding/decoding and type conversion utilities

Core Functionality:

  • ABI method encoding
  • Event signature generation
  • Type marshaling/unmarshaling
  • Data validation
// ABI processing
processor := utils.NewABIProcessor(abiObject)
encoded, _ := processor.EncodeMethod("transfer", 
    []string{"address", "uint256"}, 
    recipient, amount)

๐ŸŽฏ High-Level Managers

๐Ÿ’ฐ Account Manager (pkg/account)

Purpose: Account operations and TRX transfers

Key Operations:

  • Balance queries
  • Account information retrieval
  • TRX transfers
  • Account resource management
am := client.Account()

// Query operations
balance, _ := am.GetBalance(ctx, address)
account, _ := am.GetAccount(ctx, address)

// Transfer operations
tx, _ := am.TransferTRX(ctx, from, to, amount)

๐Ÿช™ TRC20 Manager (pkg/trc20)

Purpose: TRC20 token operations with decimal handling

Key Features:

  • Automatic decimal conversion
  • Immutable property caching (name, symbol, decimals)
  • Standard TRC20 operations
  • Precision arithmetic using shopspring/decimal
trc20Mgr, _ := trc20.NewManager(client, tokenAddress)

// Cached properties (fetched once)
name, _ := trc20Mgr.Name(ctx)
symbol, _ := trc20Mgr.Symbol(ctx) 
decimals, _ := trc20Mgr.Decimals(ctx)

// Operations with decimal precision
amount := decimal.NewFromFloat(12.34)
_, tx, _ := trc20Mgr.Transfer(ctx, from, to, amount)

๐Ÿ“œ Smart Contract Manager (pkg/smartcontract)

Purpose: Contract deployment and interaction

Two-Level API:

  1. Manager: Deployment and administrative operations
  2. Instance: Bound contract interaction
// Manager for deployment
mgr := client.SmartContracts()
contractAddr, _ := mgr.Deploy(ctx, owner, "MyContract", abi, bytecode, value, feeLimit, consumeUserResourcePercent, constructorParams...)

// Instance for interaction  
instance, _ := smartcontract.NewInstance(client, contractAddr, abi)
tx, _ := instance.Invoke(ctx, caller, value, "methodName", param1, param2)

๐ŸŽญ Event Decoder (pkg/eventdecoder)

Purpose: Transaction log decoding with built-in event support

Key Features:

  • Built-in TRC20 event signatures
  • Runtime ABI registration
  • Structured event output
  • Graceful fallback for unknown events
// Built-in TRC20 events work automatically
event, _ := eventdecoder.DecodeLog(topics, data)

// Register custom events
eventdecoder.RegisterABIJSON(customABI)

// Structured output
fmt.Printf("Event: %s\n", event.EventName)
for _, param := range event.Parameters {
    fmt.Printf("  %s (%s): %v\n", param.Name, param.Type, param.Value)
}

๐Ÿ”„ Typical Workflows

1. Simple TRX Transfer Flow

sequenceDiagram
    participant App as Application
    participant Client as Client
    participant AM as AccountManager
    participant SignerImpl as Signer (Implementation)
    participant SignTxFunc as signer.SignTx
    participant Node as TRON Node
    
    App->>Client: NewClient(endpoint)
    App->>SignerImpl: NewPrivateKeySigner(key)
    App->>AM: TransferTRX(from, to, amount)
    AM->>Node: Build transaction via gRPC
    AM-->>App: Return unsigned transaction (tx)
    App->>SignTxFunc: SignTx(signerImpl, tx)
    SignTxFunc->>SignerImpl: Sign(hash)
    SignerImpl-->>SignTxFunc: signature
    SignTxFunc-->>App: Return signed transaction
    App->>Client: Broadcast(signedTx)
    Client->>Node: Broadcast signed transaction
    Client-->>App: Return broadcast result

2. TRC20 Transfer Flow

sequenceDiagram
    participant App as Application
    participant Client as Client
    participant TRC20 as TRC20Manager
    participant SC as SmartContract
    participant Utils as Utils
    participant Node as TRON Node
    
    App->>TRC20: NewManager(client, tokenAddr)
    TRC20->>Node: Query token metadata (cached)
    App->>TRC20: Transfer(from, to, amount)
    TRC20->>Utils: Encode transfer method call
    TRC20->>SC: Build contract invocation
    SC->>Node: Create transaction via gRPC
    SC-->>App: Return unsigned transaction
    Note over App: Sign and broadcast as usual

3. Event Decoding Flow

sequenceDiagram
    participant App as Application
    participant Client as Client
    participant ED as EventDecoder
    participant Cache as Signature Cache
    
    App->>Client: GetTransactionInfo(txid)
    Client-->>App: Transaction with logs
    App->>ED: DecodeLog(topics, data)
    ED->>Cache: Lookup event signature
    alt Signature found
        ED->>ED: Decode using cached ABI
        ED-->>App: Structured event
    else Unknown signature
        ED-->>App: Fallback event with raw data
    end

๐Ÿ”ง Configuration and Customization

Client Configuration

cli, err := client.NewClient(endpoint,
    // Connection pool settings
    client.WithPool(initialConns, maxConns),
    
    // Default timeout for operations
    client.WithTimeout(duration),
    
    // Custom gRPC dial options
    client.WithDialOptions(grpc.WithKeepaliveParams(...)),
)

Broadcast Options

opts := client.DefaultBroadcastOptions()
opts.FeeLimit = 100_000_000              // Maximum energy cost in SUN
opts.WaitForReceipt = true               // Wait for on-chain confirmation
opts.WaitTimeout = 20 * time.Second      // Receipt wait timeout
opts.PollInterval = 500 * time.Millisecond // Polling frequency

Event Decoder Customization

// Register custom contract ABIs
eventdecoder.RegisterABIJSON(abiJSON)
eventdecoder.RegisterABIObject(abiObject)

// Built-in events (automatically available):
// - Transfer(address,address,uint256)
// - Approval(address,address,uint256)

๐Ÿš€ Performance Considerations

Connection Pooling

  • Client maintains a pool of gRPC connections
  • Pool size configurable based on application needs
  • Automatic connection management and health checking

Caching Strategy

  • TRC20 Manager: Caches immutable properties (name, symbol, decimals)
  • Event Decoder: Caches event signatures and ABI fragments
  • Address Types: Lazy conversion between formats

Decimal Precision

  • Uses shopspring/decimal for precise arithmetic
  • Automatic conversion between human-readable and on-chain formats
  • Prevents floating-point precision issues common in financial applications

๐Ÿ”’ Security Best Practices

Key Management

// โœ… Good: Store keys securely
key := os.Getenv("PRIVATE_KEY")  // From environment
signer, _ := signer.NewPrivateKeySigner(key)

// โŒ Bad: Hardcode keys in source
signer, _ := signer.NewPrivateKeySigner("abc123...")

Transaction Validation

// โœ… Good: Simulate before broadcasting
simResult, _ := client.Simulate(ctx, tx)
if simResult.Success {
    result, _ := client.SignAndBroadcast(ctx, tx, opts, signer)
}

// โœ… Good: Set appropriate fee limits
opts.FeeLimit = 50_000_000  // Reasonable limit for TRC20 transfer

Address Validation

// โœ… Good: Validate addresses
addr, err := types.NewAddress(addressString)
if err != nil {
    return fmt.Errorf("invalid address: %w", err)
}

// โœ… Good: Use typed addresses throughout
func transfer(from, to *types.Address, amount decimal.Decimal) error {
    // ...
}

๐Ÿ”„ Extension Points

Custom Managers

Create custom managers following the established patterns:

type CustomManager struct {
    client client.Client
}

func NewCustomManager(cli client.Client) *CustomManager {
    return &CustomManager{client: cli}
}

func (m *CustomManager) CustomOperation(ctx context.Context, params...) error {
    // Use client.lowlevel or other packages as needed
}

Custom Event Decoders

Extend event decoding capabilities:

// Register custom ABI at startup
func init() {
    eventdecoder.RegisterABIJSON(myContractABI)
}

This architecture enables TronLib to provide both simplicity for common use cases and flexibility for advanced scenarios, while maintaining high performance and type safety throughout the stack.

๐ŸŽ›๏ธ Advanced Architecture and Internal Design

Key Architectural Principles

  • Separation of Concerns: Each package has a single responsibility, making the codebase maintainable and testable.
  • Abstraction: Interfaces are used to abstract implementation details, enabling easy testing and extensibility.
  • Resource Management: Connection pooling and proper cleanup ensure efficient resource utilization.
  • Error Handling: Consistent error handling with sentinel errors for better error categorization.
  • Type Safety: Strong typing with custom types for addresses, transactions, and other domain objects.

Design Patterns Used

Client-Manager Pattern

The SDK uses a central Client that acts as a gateway to specialized managers for different blockchain functionalities:

  • Account Management (account.Manager) - TRX transfers, account information
  • Smart Contracts (smartcontract.Manager) - Contract deployment and management
  • TRC20 Tokens (trc20.Manager) - TRC20 token standard implementation
  • Network Operations (network.Manager) - Node and network information
  • Resource Management (resources.Manager) - Bandwidth and energy management
  • TRC10 Tokens (trc10.Manager) - TRC10 token standard implementation
  • Voting (voting.Manager) - Voting and witness operations

The client provides factory methods to access these managers:

accountMgr := client.Account()
contractMgr := client.SmartContract()
trc20Mgr := client.TRC20(tokenAddress)

Connection Pooling

The client package implements a connection pool for efficient gRPC connection management:

  • Reuses connections to reduce overhead
  • Manages connection lifecycle with proper cleanup
  • Supports configurable pool sizes with WithPool(initConnections, maxConnections)
  • Implements lazy connection creation on first use

Functional Options Pattern

The SDK uses functional options for flexible configuration:

client, err := client.NewClient("grpc://node:50051", 
    client.WithTimeout(30*time.Second),
    client.WithPool(5, 10))

Interface-Based Design

Key components use interfaces for loose coupling:

  • signer.Signer interface for transaction signing
  • lowlevel.ConnProvider for connection abstraction
  • contractClient interface for smart contract operations

Builder Pattern

Transaction building uses a fluent builder pattern:

builder := types.NewTransactionBuilder()
tx := builder.WithRefBlock(hash, num).WithContract(type, params).Build()

Factory Pattern

Smart contract instances are created using factory methods:

// Create contract instance with ABI from network
contract, err := smartcontract.NewInstance(client, contractAddress)

// Create contract instance with provided ABI
contract, err := smartcontract.NewInstance(client, contractAddress, abiString)

Wrapper Pattern

The SDK wraps gRPC calls with validation and error handling:

// Low-level call wrapper with validation
result, err := lowlevel.Call(connProvider, ctx, "operation", func(client api.WalletClient, ctx context.Context) (*core.Account, error) {
    return client.GetAccount(ctx, req)
})

Data Flow Patterns

Request-Response Flow

sequenceDiagram
    participant App as Application
    participant Client as Client
    participant Pool as Connection Pool
    participant GRPC as gRPC Server
    participant Manager as Manager
    
    App->>Client: Call method (e.g., GetAccount)
    Client->>Manager: Create manager instance
    Manager->>Client: Get connection from pool
    Client->>Pool: GetConnection()
    Pool->>GRPC: Establish connection if needed
    Pool-->>Client: Return connection
    Client->>Manager: Pass connection
    Manager->>GRPC: Execute gRPC call
    GRPC-->>Manager: Return response
    Manager-->>Client: Process and validate
    Client-->>App: Return result

Transaction Signing and Broadcasting Flow

sequenceDiagram
    participant App as Application
    participant Client as Client
    participant Signer as Signer
    participant Broadcaster as Client.SignAndBroadcast
    participant SignTx as signer.SignTx
    participant GRPC as gRPC Server
    
    App->>Client: Create transaction
    Client->>App: Return unsigned transaction
    App->>Broadcaster: SignAndBroadcast(tx, opts, signer)
    Broadcaster->>SignTx: SignTx(signer, tx)
    SignTx->>Signer: Sign(hash)
    Signer-->>SignTx: signature
    SignTx-->>Broadcaster: signedTx
    Broadcaster->>GRPC: BroadcastTransaction(signedTx)
    GRPC-->>Broadcaster: Result
    Broadcaster-->>App: Return broadcast result

Smart Contract Interaction Flow

sequenceDiagram
    participant App as Application
    participant Client as Client
    participant Contract as Contract Instance
    participant ABIProc as ABI Processor
    participant SignTx as signer.SignTx
    participant SignerImpl as Signer (Implementation)
    participant GRPC as gRPC Server
    
    App->>Client: Create contract instance
    Client->>Contract: NewInstance()
    Contract->>ABIProc: NewABIProcessor()
    
    App->>Contract: Call constant method
    Contract->>ABIProc: Encode method call
    ABIProc-->>Contract: Return encoded data
    Contract->>GRPC: TriggerConstantContract
    GRPC-->>Contract: Return result
    Contract->>ABIProc: Decode result
    ABIProc-->>Contract: Return decoded data
    Contract-->>App: Return result
    
    App->>Contract: Invoke state-changing method
    Contract->>ABIProc: Encode method call
    ABIProc-->>Contract: Return encoded data
    Contract->>App: Return unsigned transaction (tx)
    App->>SignTx: SignTx(signerImpl, tx)
    SignTx->>SignerImpl: Sign(hash)
    SignerImpl-->>SignTx: signature
    SignTx-->>App: Return signed transaction
    App->>Client: Broadcast(signedTx)
    Client->>GRPC: BroadcastTransaction
    GRPC-->>Client: Return result
    Client-->>App: Return BroadcastResult

Package Structure and Responsibilities

Core Packages

PackageResponsibility
pkg/clientMain client implementation, connection pooling, broadcasting, and manager accessors
pkg/accountAccount-related operations (balance, transfers, account information)
pkg/smartcontractSmart contract deployment, interaction, contract instances, and ABI processing
pkg/trc20TRC20 token standard implementation with decimal handling
pkg/signerTransaction signing implementations (private key, hardware wallets planned)
pkg/typesShared types, address handling, error definitions, and constants
pkg/networkNetwork information and node status operations
pkg/resourcesBandwidth and energy resource management (freezing, unfreezing)
pkg/trc10TRC10 token standard implementation
pkg/votingVoting and witness-related operations
pkg/eventdecoderSmart contract event decoding and signature registry
pkg/utilsUtility functions for ABI encoding/decoding, validation, and conversion

Low-Level Packages

PackageResponsibility
pkg/client/lowlevelLow-level gRPC call wrappers and utilities
pb/apiGenerated gRPC API protobuf definitions
pb/coreGenerated core TRON protobuf definitions

Package Dependencies

The package dependency structure follows a layered approach:

Application Layer
    โ†“
pkg/client (entry point)
    โ†“
Business Logic Layer:
pkg/account, pkg/smartcontract, pkg/trc20,
pkg/network, pkg/resources, pkg/trc10, pkg/voting
    โ†“
Utility Layer:
pkg/signer, pkg/types, pkg/eventdecoder, pkg/utils
    โ†“
Low-Level Layer:
pkg/client/lowlevel
    โ†“
Protocol Layer:
pb/api, pb/core

Each package in the business logic layer depends on:

  1. pkg/client/lowlevel for gRPC wrappers
  2. pkg/types for shared types and errors
  3. Their specific utility packages (e.g., pkg/smartcontract uses pkg/utils for ABI processing)

Key Interfaces and Implementations

Signer Interface

type Signer interface {
    Address() *types.Address
    PublicKey() *ecdsa.PublicKey
    Sign(hash []byte) ([]byte, error)
}

Implementation: PrivateKeySigner and HDWalletSigner in pkg/signer

The Signer interface defines a contract for signing a cryptographic hash, making it highly flexible for various signing mechanisms (e.g., private keys, hardware wallets, cloud KMS). Transaction-specific handling (like hashing and signature attachment) is managed by the signer.SignTx utility function.

Connection Provider Interface

type ConnProvider interface {
    GetConnection(ctx context.Context) (*grpc.ClientConn, error)
    ReturnConnection(conn *grpc.ClientConn)
    GetTimeout() time.Duration
}

Implementation: Client in pkg/client

The ConnProvider interface abstracts connection management, allowing different implementations for testing, load balancing, or custom connection strategies.

Contract Client Interface

type contractClient interface {
    lowlevel.ConnProvider
}

Implementation: Used by smartcontract.Instance

This interface ensures that contract instances can work with any connection provider that implements the basic connection functionality.

Manager Interface Pattern

Each manager follows a consistent pattern:

type Manager struct {
    conn lowlevel.ConnProvider
}

func NewManager(conn lowlevel.ConnProvider) *Manager {
    return &Manager{conn: conn}
}

This pattern ensures all managers have consistent construction and dependency injection.

Extension Points and Customization

Custom Signers

Developers can implement the signer.Signer interface to support different signing mechanisms:

  • Hardware wallets (Ledger, Trezor)
  • Multi-signature schemes
  • External signing services (HSM, cloud KMS)
  • Custom key derivation schemes

Example implementation:

type CustomSigner struct {
    // ... fields relevant to your custom signer
}

// Implement the signer.Signer interface
func (s *CustomSigner) Address() *types.Address { /* ... */ }
func (s *CustomSigner) PublicKey() *ecdsa.PublicKey { /* ... */ }
func (s *CustomSigner) Sign(hash []byte) ([]byte, error) { /* ... */ }

// Example usage with your custom signer
// customSigner := &CustomSigner{...}
// tx := &core.Transaction{} // Your unsigned transaction
// err := signer.SignTx(customSigner, tx)
// // ...

Custom Connection Providers

The ConnProvider interface allows for custom connection management:

  • Load balancing across multiple nodes
  • Custom authentication mechanisms
  • Proxy support with custom headers
  • Circuit breaker patterns for resilience
  • Custom retry logic and timeout handling

Custom ABI Processing

The utils.ABIProcessor can be extended for custom ABI handling:

  • Custom type encoding/decoding for specialized contracts
  • Specialized parameter validation for domain-specific contracts
  • Custom method signature handling for non-standard contracts

Event Decoding Extensions

The eventdecoder package can be extended with:

  • Custom event signature registries for private networks
  • Specialized parameter formatting for custom types
  • Custom event filtering and processing logic

Custom Error Handling

The SDK uses sentinel errors that can be extended:

  • Custom error types for domain-specific errors
  • Enhanced error wrapping with additional context
  • Custom error reporting and logging mechanisms

Custom Address Handling

The types.Address type can be extended with:

  • Custom address validation for private networks
  • Additional address formatting options
  • Custom address derivation schemes