# @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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hsuite.network/developers/libs/helpers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
