# @hsuite/helpers - Utility Library

> 🛠️ **Comprehensive utility library for Hedera Hashgraph development and market data integration**

Essential helper functions for offline transaction handling, cryptocurrency price fetching via CoinGecko API, and enhanced logging capabilities within the Smart Node ecosystem.

***

## Table of Contents

* [Quick Start](#quick-start)
* [Architecture](#architecture)
* [API Reference](#api-reference)
* [Guides](#guides)
* [Examples](#examples)
* [Integration](#integration)

***

## Quick Start

### Installation

```bash
npm install @hsuite/helpers
```

### Basic Usage

```typescript
import { CoingeckoHelper, LoggerHelper, HashgraphOfflineTransactionHelper } from '@hsuite/helpers';

// Enhanced logging
const logger = new LoggerHelper('MyService');
logger.log('Service started');

// CoinGecko integration
const coingecko = new CoingeckoHelper(httpService);
const btcData = await coingecko.fetchTokenMarkets('bitcoin');

// Offline transactions
const txHelper = new HashgraphOfflineTransactionHelper(config, client, network);
const nodes = await txHelper.getHederaNodes();
```

***

## Architecture

### Core Utilities

#### 📊 **Market Data Integration**

* **`CoingeckoHelper`** - CoinGecko API integration for cryptocurrency market data
* **Enhanced Error Handling** - Robust data formatting and error management
* **Rate Limiting** - Built-in API rate limiting and retry logic

#### 📝 **Enhanced Logging**

* **`LoggerHelper`** - Advanced logging with global and instance-level control
* **Flexible Control** - Enable/disable logging at global or service level
* **NestJS Integration** - Extends NestJS Logger with enhanced functionality

#### ⚡ **Offline Transactions**

* **`HashgraphOfflineTransactionHelper`** - Hedera transaction utilities for offline workflows
* **Node Discovery** - Automatic network node discovery and selection
* **Multi-Service Integration** - Works with ClientService and NetworkService

### Module Structure

```
src/
├── commons/                     # Common utility functions
├── hashgraph/                   # Hedera Hashgraph specific utilities
│   └── offline-transaction.helper.ts # Offline transaction management
├── index.ts                    # Public API exports
└── interfaces/                 # TypeScript interfaces
```

***

## API Reference

### CoingeckoHelper

**Constructor**: `new CoingeckoHelper(httpService: HttpService)`

#### Methods

**`fetchTokenMarkets(coinId: string): Promise<TokenMarketData>`**

* Retrieves comprehensive market data for a specific cryptocurrency
* **Parameters**: `coinId` - CoinGecko coin identifier (e.g., 'bitcoin', 'hedera-hashgraph')
* **Returns**: Formatted object with price, volume, supply, and metadata
* **Throws**: `Error` if API request fails or invalid response

```typescript
interface TokenMarketData {
  symbol: string;              // Token symbol (e.g., 'btc')
  name: string;                // Full token name (e.g., 'Bitcoin')
  icon: string;                // Icon URL
  price: number;               // Current USD price
  volume: number;              // 24h trading volume
  high_24h: number;            // 24h high price
  low_24h: number;             // 24h low price
  price_change_24h: number;    // 24h price change
  total_supply: number;        // Total token supply
  circulating_supply: number;  // Circulating supply
  last_updated: string;        // Last update timestamp
}
```

### LoggerHelper

**Constructor**: `new LoggerHelper(context: string)`

#### Static Methods

**`setGlobalLoggingEnabled(enabled: boolean): void`**

* Controls logging globally across all LoggerHelper instances
* **Parameters**: `enabled` - Whether to enable global logging

#### Instance Methods

**`setLoggingEnabled(enabled: boolean): void`**

* Controls logging for specific instance
* **Parameters**: `enabled` - Whether to enable instance logging

**Standard Logging Methods:**

* **`log(message: string, ...optionalParams: any[]): void`**
* **`error(message: string, trace?: string, ...optionalParams: any[]): void`**
* **`warn(message: string, ...optionalParams: any[]): void`**
* **`debug(message: string, ...optionalParams: any[]): void`**
* **`verbose(message: string, ...optionalParams: any[]): void`**

### HashgraphOfflineTransactionHelper

**Constructor**: `new HashgraphOfflineTransactionHelper(configService, clientService, networkService)`

#### Methods

**`getHederaNodes(): Promise<AccountId[]>`**

* Fetches all available Hedera network nodes
* **Returns**: Array of AccountId objects representing network nodes
* **Throws**: `Error` if network discovery fails

**`getRandomHederaNode(): Promise<AccountId>`**

* Returns a randomly selected Hedera network node
* **Returns**: Single AccountId for load balancing
* **Throws**: `Error` if no nodes available

***

## Guides

### Market Data Integration Guide

Learn how to integrate CoinGecko API for real-time cryptocurrency market data. Set up token price monitoring, market cap tracking, and historical data analysis for your applications.

### Enhanced Logging Guide

Set up advanced logging with global and instance-level control. Configure logging levels, structured logging patterns, and debug controls for production environments.

### Offline Transaction Guide

Handle Hedera Hashgraph transactions for offline workflows and node management. Implement transaction queuing, node selection, and load balancing strategies.

***

## Examples

### CoinGecko Market Data Integration

```typescript
import { Injectable } from '@nestjs/common';
import { CoingeckoHelper } from '@hsuite/helpers';
import { HttpService } from '@nestjs/axios';

@Injectable()
export class TokenService {
  private coingecko: CoingeckoHelper;

  constructor(private httpService: HttpService) {
    this.coingecko = new CoingeckoHelper(httpService);
  }

  async getBitcoinData() {
    try {
      const btcData = await this.coingecko.fetchTokenMarkets('bitcoin');
      
      return {
        symbol: btcData.symbol,        // 'btc'
        name: btcData.name,            // 'Bitcoin'
        price: btcData.price,          // Current USD price
        volume: btcData.volume,        // 24h trading volume
        high24h: btcData.high_24h,     // 24h high
        low24h: btcData.low_24h,       // 24h low
        priceChange: btcData.price_change_24h,
        totalSupply: btcData.total_supply,
        circulatingSupply: btcData.circulating_supply,
        lastUpdated: btcData.last_updated
      };
    } catch (error) {
      console.error('Failed to fetch Bitcoin data:', error);
      throw error;
    }
  }

  async getHederaData() {
    const hbarData = await this.coingecko.fetchTokenMarkets('hedera-hashgraph');
    return {
      price: hbarData.price,
      marketCap: hbarData.price * hbarData.circulating_supply,
      volume24h: hbarData.volume
    };
  }

  async getMultipleTokens() {
    const tokens = ['bitcoin', 'ethereum', 'hedera-hashgraph'];
    const results = await Promise.all(
      tokens.map(token => this.coingecko.fetchTokenMarkets(token))
    );
    
    return results.map(data => ({
      symbol: data.symbol,
      price: data.price,
      change24h: data.price_change_24h
    }));
  }
}
```

### Enhanced Logging Patterns

```typescript
import { Injectable } from '@nestjs/common';
import { LoggerHelper } from '@hsuite/helpers';

@Injectable()
export class MyService {
  private logger = new LoggerHelper(MyService.name);

  async performOperation() {
    // Standard logging
    this.logger.log('Starting operation');
    
    try {
      this.logger.debug('Operation in progress');
      
      const result = await this.processData();
      
      this.logger.log('Operation completed successfully', { 
        result,
        duration: '123ms'
      });
      
      return result;
    } catch (error) {
      this.logger.error('Operation failed', error.stack);
      throw error;
    }
  }

  // Global logging control
  disableAllLogging() {
    LoggerHelper.setGlobalLoggingEnabled(false);
    this.logger.log('This will not appear');
  }

  // Instance-level logging control
  muteThisService() {
    this.logger.setLoggingEnabled(false);
    this.logger.log('This will not appear');
  }

  // Conditional logging
  conditionalLogging(isDebugMode: boolean) {
    this.logger.setLoggingEnabled(isDebugMode);
    this.logger.debug('Debug information'); // Only shows if enabled
  }

  private async processData() {
    this.logger.verbose('Processing data in detail');
    // Simulate processing
    await new Promise(resolve => setTimeout(resolve, 100));
    return { processed: true };
  }
}
```

### Offline Transaction Management

```typescript
import { Injectable } from '@nestjs/common';
import { HashgraphOfflineTransactionHelper } from '@hsuite/helpers';
import { SmartConfigService } from '@hsuite/smart-config';
import { ClientService } from '@hsuite/client';
import { NetworkService } from '@hsuite/mirrors';

@Injectable()
export class TransactionService {
  private helper: HashgraphOfflineTransactionHelper;

  constructor(
    private configService: SmartConfigService,
    private clientService: ClientService,
    private networkService: NetworkService
  ) {
    this.helper = new HashgraphOfflineTransactionHelper(
      configService,
      clientService,
      networkService
    );
  }

  async prepareOfflineTransaction() {
    try {
      // Get all available Hedera nodes
      const allNodes = await this.helper.getHederaNodes();
      console.log(`Found ${allNodes.length} nodes`);

      // Get a random node for transaction submission
      const randomNode = await this.helper.getRandomHederaNode();
      console.log(`Selected node: ${randomNode.toString()}`);

      return { 
        allNodes, 
        selectedNode: randomNode,
        nodeCount: allNodes.length
      };
    } catch (error) {
      console.error('Failed to prepare offline transaction:', error);
      throw error;
    }
  }

  async loadBalanceTransactions() {
    // Use multiple nodes for load balancing
    const tasks = [];
    for (let i = 0; i < 5; i++) {
      tasks.push(this.helper.getRandomHederaNode());
    }
    
    const selectedNodes = await Promise.all(tasks);
    
    return selectedNodes.map((node, index) => ({
      taskId: index + 1,
      assignedNode: node.toString()
    }));
  }

  async monitorNetworkHealth() {
    try {
      const nodes = await this.helper.getHederaNodes();
      
      return {
        totalNodes: nodes.length,
        status: nodes.length > 0 ? 'healthy' : 'unhealthy',
        nodes: nodes.slice(0, 5).map(node => node.toString()) // Show first 5
      };
    } catch (error) {
      return {
        totalNodes: 0,
        status: 'error',
        error: error.message
      };
    }
  }
}
```

***

## Integration

### Required Dependencies

```json
{
  "@hashgraph/sdk": "^2.62.0",
  "@hsuite/hashgraph-types": "^2.0.3",
  "@hsuite/smart-config": "^2.1.1",
  "@nestjs/axios": "^3.0.2"
}
```

### Environment Variables

```env
# CoinGecko Configuration
COINGECKO_API_KEY=your-coingecko-pro-api-key

# Hedera Configuration (for offline transactions)
HEDERA_NETWORK=testnet
HEDERA_ACCOUNT_ID=0.0.123456
HEDERA_PRIVATE_KEY=302e020100300506032b657004220420...

# Logging Configuration (optional)
LOG_LEVEL=debug
GLOBAL_LOGGING_ENABLED=true
```

### Module Integration

```typescript
import { HttpModule } from '@nestjs/axios';
import { CoingeckoHelper, LoggerHelper } from '@hsuite/helpers';

@Module({
  imports: [HttpModule],
  providers: [
    CoingeckoHelper,
    {
      provide: 'APP_LOGGER',
      useFactory: () => new LoggerHelper('AppModule')
    }
  ],
  exports: [CoingeckoHelper, 'APP_LOGGER']
})
export class UtilitiesModule {}
```

***

**💡 Best Practices**:

* Use LoggerHelper for consistent logging across your application
* Cache CoinGecko API responses to avoid rate limiting
* Handle offline transaction errors gracefully with proper retry logic

## **⚠️ Rate Limits**: CoinGecko API has rate limits. Consider implementing caching for production use.

<p align="center">Built with ❤️ by the HSuite Team<br>Copyright © 2025 HSuite. All rights reserved.</p>
