Asset and Balance Features

This document provides a comprehensive overview of the Asset and Balance features in the RCoinX backend system. These features work together to manage cryptocurrency assets, user balances, and wallet functionality.

Table of Contents

  1. Database Structure
  2. Database Relations
  3. Asset Feature
  4. Balance Feature
  5. API Documentation
  6. Frontend Integration Guide

Database Structure

Asset Module Tables

1. Assets Table (assets)

The main table for storing cryptocurrency and token information.
FieldTypeDescriptionExample
iduintPrimary key, auto-increment1
symbolvarchar(20)Unique asset symbol”BTC”, “ETH”, “USDT”
namevarchar(100)Full asset name”Bitcoin”, “Ethereum”
typevarchar(20)Asset type (coin/token)“coin”, “token”
decimalsintNumber of decimal places8, 18
kyc_requiredboolWhether KYC is requiredfalse
websitevarchar(255)Asset website URLhttps://bitcoin.org
metadatajsonAdditional asset metadata{"description": "..."}
icon_file_iduintReference to icon file1
is_activeboolWhether asset is activetrue
is_evmboolWhether asset is EVM compatiblefalse
is_fungibleboolWhether asset is fungibletrue
created_attimestampCreation timestamp”2023-01-01T12:00:00Z”
updated_attimestampLast update timestamp”2023-01-01T12:00:00Z”
deleted_attimestampSoft delete timestampnull

2. Chains Table (chains)

Stores blockchain network information.
FieldTypeDescriptionExample
iduintPrimary key1
namevarchar(100)Chain name”Ethereum”, “Bitcoin”
symbolvarchar(20)Chain symbol”ETH”, “BTC”
typevarchar(20)Chain type”evm”, “bitcoin”, “solana”
descriptiontextChain description”A decentralized platform…”
website_urlvarchar(255)Chain websitehttps://ethereum.org
is_activeboolWhether chain is activetrue
supports_smart_contractsboolSmart contract supporttrue
consensus_mechanismvarchar(50)Consensus mechanism”Proof of Stake”
block_timeintBlock time in seconds12
created_attimestampCreation timestamp”2023-01-01T12:00:00Z”
updated_attimestampLast update timestamp”2023-01-01T12:00:00Z”
deleted_attimestampSoft delete timestampnull

3. Networks Table (networks)

Stores specific network configurations for chains.
FieldTypeDescriptionExample
iduintPrimary key1
namevarchar(100)Network name”Ethereum Mainnet”
chain_iduintReference to chain1
network_idvarchar(50)Network identifier”1”
is_activeboolWhether network is activetrue
is_testnetboolWhether it’s a testnetfalse
created_attimestampCreation timestamp”2023-01-01T12:00:00Z”
updated_attimestampLast update timestamp”2023-01-01T12:00:00Z”
deleted_attimestampSoft delete timestampnull

4. Token Standards Table (token_standards)

Stores token standard information (ERC-20, BEP-20, etc.).
FieldTypeDescriptionExample
iduintPrimary key1
codevarchar(100)Standard code”ERC-20”, “BEP-20”
descriptiontextStandard description”Fungible token standard”
created_attimestampCreation timestamp”2023-01-01T12:00:00Z”
updated_attimestampLast update timestamp”2023-01-01T12:00:00Z”
deleted_attimestampSoft delete timestampnull

5. Asset Networks Table (asset_networks)

Junction table linking assets to networks with token standards.
FieldTypeDescriptionExample
iduintPrimary key1
asset_iduintReference to asset1
token_standard_iduintReference to token standard1
network_iduintReference to network1
is_activeboolWhether configuration is activetrue
created_attimestampCreation timestamp”2023-01-01T12:00:00Z”
updated_attimestampLast update timestamp”2023-01-01T12:00:00Z”
deleted_attimestampSoft delete timestampnull

Balance Module Tables

1. Balances Table (balances)

Stores user balance information for each asset.
FieldTypeDescriptionExample
iduintPrimary key1
user_iduintReference to user1
asset_iduintReference to asset1
balancedecimal(20,8)Total balance1000.00000000
availabledecimal(20,8)Available balance950.00000000
lockeddecimal(20,8)Locked balance50.00000000
is_activeboolWhether balance is activetrue
created_attimestampCreation timestamp”2023-01-01T12:00:00Z”
updated_attimestampLast update timestamp”2023-01-01T12:00:00Z”
deleted_attimestampSoft delete timestampnull

2. Balance Wallets Table (balance_wallets)

Stores wallet information for user balances.
FieldTypeDescriptionExample
iduintPrimary key1
balance_iduintReference to balance1
wallet_addressvarchar(255)Wallet address”0x1234…”
private_keytextEncrypted private key”encrypted_key”
public_keytextPublic key”public_key_data”
asset_network_iduintReference to asset network1
mnemonictextWallet mnemonic”word1 word2…”
derivation_pathvarchar(255)Derivation path”m/44’/60’/0’/0/0”
is_activeboolWhether wallet is activetrue
created_attimestampCreation timestamp”2023-01-01T12:00:00Z”
updated_attimestampLast update timestamp”2023-01-01T12:00:00Z”
deleted_attimestampSoft delete timestampnull

3. Transactions Table (transactions)

Stores transaction history for wallets.
FieldTypeDescriptionExample
iduintPrimary key1
wallet_iduintReference to balance wallet1
hashvarchar(255)Transaction hash”0xabc123…”
fromvarchar(255)From address”0x1234…”
tovarchar(255)To address”0x5678…”
valuevarchar(255)Transaction value”1000000000000000000”
assetvarchar(255)Asset symbol”ETH”
block_numuint64Block number12345678
timestamptimestampTransaction timestamp”2023-01-01T12:00:00Z”
statusvarchar(50)Transaction status”confirmed”
confirmationsintNumber of confirmations12
network_feevarchar(255)Network fee”21000000000000000”
error_messagetextError message if failednull
created_attimestampCreation timestamp”2023-01-01T12:00:00Z”
updated_attimestampLast update timestamp”2023-01-01T12:00:00Z”
deleted_attimestampSoft delete timestampnull

Database Relations

Asset Module Relations

Balance Module Relations

Cross-Module Relations

The Asset and Balance modules are connected through:
  1. Assets → Balances: Each balance is associated with a specific asset
  2. Asset Networks → Balance Wallets: Each wallet is created for a specific asset-network combination
  3. Users → Balances: Each balance belongs to a specific user

Asset Feature

Overview

The Asset feature manages cryptocurrency and token information, including:
  • Asset Management: CRUD operations for cryptocurrencies and tokens
  • Network Configuration: Support for multiple blockchain networks
  • Token Standards: Support for various token standards (ERC-20, BEP-20, etc.)
  • Chain Management: Support for different blockchain types (EVM, Bitcoin, Solana, etc.)

Key Features

1. Asset Types

  • Coins: Native cryptocurrencies (BTC, ETH, etc.)
  • Tokens: Smart contract-based tokens (USDT, USDC, etc.)

2. Multi-Chain Support

  • EVM Chains: Ethereum, BSC, Polygon, etc.
  • Bitcoin-like: Bitcoin, Litecoin, etc.
  • Solana: Solana ecosystem
  • Cosmos: Cosmos SDK chains

3. Token Standards

  • ERC-20: Ethereum fungible tokens
  • BEP-20: BSC fungible tokens
  • SPL: Solana program library tokens
  • Custom: Platform-specific standards

Business Logic

Asset Creation Flow

  1. Create asset with basic information (symbol, name, type)
  2. Configure asset networks for supported chains
  3. Set token standards for each network
  4. Activate asset for trading

Asset Network Configuration

  1. Select chain and network
  2. Choose appropriate token standard
  3. Configure network-specific parameters
  4. Enable/disable network support

Balance Feature

Overview

The Balance feature manages user cryptocurrency balances and wallets, including:
  • Balance Management: Track user balances for each asset
  • Wallet Generation: Create wallets for different networks
  • Transaction Tracking: Monitor incoming and outgoing transactions
  • Balance Operations: Lock/unlock funds, transfers

Key Features

1. Balance Types

  • Total Balance: Complete balance amount
  • Available Balance: Amount available for transactions
  • Locked Balance: Amount locked in pending operations

2. Wallet Management

  • Multi-Network Wallets: Generate wallets for different networks
  • HD Wallet Support: Hierarchical deterministic wallet generation
  • Private Key Management: Secure storage of private keys
  • Address Generation: Generate unique addresses for each network

3. Transaction Monitoring

  • Real-time Updates: Monitor blockchain for new transactions
  • Status Tracking: Track transaction confirmation status
  • Fee Calculation: Calculate and track network fees
  • Error Handling: Handle failed transactions

Business Logic

Balance Creation Flow

  1. User requests balance for specific asset
  2. System creates balance record with zero amounts
  3. Generate wallet for primary network
  4. Set up transaction monitoring

Wallet Generation Flow

  1. User requests wallet for specific asset-network
  2. Check if balance exists, create if needed
  3. Generate HD wallet with unique derivation path
  4. Store wallet information securely
  5. Set up blockchain monitoring

Transaction Processing Flow

  1. Monitor blockchain for incoming transactions
  2. Update balance when transaction confirms
  3. Track transaction status and confirmations
  4. Handle failed or stuck transactions

API Documentation

Asset API Endpoints

Public Endpoints (No Authentication Required)

Get Assets
GET /client/assets
Query Parameters:
  • page (int, optional): Page number (default: 1)
  • page_size (int, optional): Page size (default: 10, max: 100)
  • search (string, optional): Search term for symbol/name
  • asset_type (string, optional): Filter by type (“coin” or “token”)
Response:
{
  "code": 200,
  "message": "Success",
  "data": {
    "assets": [
      {
        "id": 1,
        "symbol": "BTC",
        "name": "Bitcoin",
        "type": "coin",
        "decimals": 8,
        "kyc_required": false,
        "website": "https://bitcoin.org",
        "metadata": "{}",
        "icon_file_id": 1,
        "is_active": true,
        "is_evm": false,
        "is_fungible": true,
        "created_at": "2023-01-01T12:00:00Z",
        "updated_at": "2023-01-01T12:00:00Z"
      }
    ],
    "count": 1
  }
}
Get Asset by ID
GET /client/assets/{id}
Path Parameters:
  • id (int, required): Asset ID
Response:
{
  "code": 200,
  "message": "Success",
  "data": {
    "id": 1,
    "symbol": "BTC",
    "name": "Bitcoin",
    "type": "coin",
    "decimals": 8,
    "kyc_required": false,
    "website": "https://bitcoin.org",
    "metadata": "{}",
    "icon_file_id": 1,
    "is_active": true,
    "is_evm": false,
    "is_fungible": true,
    "created_at": "2023-01-01T12:00:00Z",
    "updated_at": "2023-01-01T12:00:00Z"
  }
}
Get Asset by Symbol
GET /client/assets/symbol/{symbol}
Path Parameters:
  • symbol (string, required): Asset symbol (e.g., “BTC”, “ETH”)
Response: Same as Get Asset by ID
Get Networks
GET /client/networks
Query Parameters:
  • page (int, optional): Page number (default: 1)
  • page_size (int, optional): Page size (default: 10, max: 100)
  • search (string, optional): Search term for network name
Response:
{
  "code": 200,
  "message": "Success",
  "data": {
    "networks": [
      {
        "id": 1,
        "name": "Ethereum Mainnet",
        "chain_id": 1,
        "chain": {
          "id": 1,
          "name": "Ethereum",
          "symbol": "ETH",
          "type": "evm"
        },
        "network_id": "1",
        "is_active": true,
        "is_testnet": false,
        "created_at": "2023-01-01T12:00:00Z",
        "updated_at": "2023-01-01T12:00:00Z"
      }
    ],
    "count": 1
  }
}
Get All Networks
GET /client/networks/all
Response:
{
  "code": 200,
  "message": "Success",
  "data": [
    {
      "id": 1,
      "name": "Ethereum Mainnet",
      "chain_id": 1,
      "chain": {
        "id": 1,
        "name": "Ethereum",
        "symbol": "ETH",
        "type": "evm"
      },
      "network_id": "1",
      "is_active": true,
      "is_testnet": false,
      "created_at": "2023-01-01T12:00:00Z",
      "updated_at": "2023-01-01T12:00:00Z"
    }
  ]
}
Get Network by ID
GET /client/networks/{id}
Path Parameters:
  • id (int, required): Network ID
Response: Same as network object in Get Networks

Balance API Endpoints

Authenticated Endpoints (Bearer Token Required)

Get User Balances
GET /client/balances
Authorization: Bearer {token}
Response:
{
  "code": 200,
  "message": "Success",
  "data": [
    {
      "id": 1,
      "user_id": 1,
      "asset_id": 1,
      "asset": {
        "id": 1,
        "symbol": "BTC",
        "name": "Bitcoin",
        "type": "coin",
        "decimals": 8
      },
      "balance": "1.00000000",
      "available": "0.95000000",
      "locked": "0.05000000",
      "is_active": true,
      "created_at": "2023-01-01T12:00:00Z",
      "updated_at": "2023-01-01T12:00:00Z"
    }
  ]
}
Get Balance by ID
GET /client/balances/{id}
Authorization: Bearer {token}
Path Parameters:
  • id (int, required): Balance ID
Response:
{
  "code": 200,
  "message": "Success",
  "data": {
    "id": 1,
    "user_id": 1,
    "asset_id": 1,
    "asset": {
      "id": 1,
      "symbol": "BTC",
      "name": "Bitcoin",
      "type": "coin",
      "decimals": 8
    },
    "balance": "1.00000000",
    "available": "0.95000000",
    "locked": "0.05000000",
    "is_active": true,
    "created_at": "2023-01-01T12:00:00Z",
    "updated_at": "2023-01-01T12:00:00Z"
  }
}
Get Balance by Asset
GET /client/balances/asset/{asset_id}
Authorization: Bearer {token}
Path Parameters:
  • asset_id (int, required): Asset ID
Response: Same as Get Balance by ID
Generate Wallet for Balance
POST /client/balances/generate-wallet?asset_network_id={asset_network_id}
Authorization: Bearer {token}
Query Parameters:
  • asset_network_id (int, required): Asset Network ID
Response:
{
  "code": 200,
  "message": "Wallet generated successfully",
  "data": {
    "wallet_id": 1,
    "wallet_address": "0x1234567890abcdef1234567890abcdef12345678",
    "public_key": "public_key_data",
    "network": "Ethereum Mainnet",
    "derivation_path": "m/44'/60'/0'/0/0",
    "chain_id": "1",
    "asset_network_id": 1,
    "balance_id": 1,
    "balance": {
      "id": 1,
      "user_id": 1,
      "asset_id": 1,
      "balance": "0.00000000",
      "available": "0.00000000",
      "locked": "0.00000000",
      "is_active": true
    },
    "is_active": true,
    "created_at": "2023-01-01T12:00:00Z"
  }
}
Get User Wallets
GET /client/wallets
Authorization: Bearer {token}
Response:
{
  "code": 200,
  "message": "Success",
  "data": [
    {
      "id": 1,
      "balance_id": 1,
      "balance": {
        "id": 1,
        "user_id": 1,
        "asset_id": 1,
        "asset": {
          "id": 1,
          "symbol": "BTC",
          "name": "Bitcoin"
        }
      },
      "wallet_address": "0x1234567890abcdef1234567890abcdef12345678",
      "public_key": "public_key_data",
      "asset_network": {
        "id": 1,
        "asset": {
          "id": 1,
          "symbol": "ETH",
          "name": "Ethereum"
        },
        "network": {
          "id": 1,
          "name": "Ethereum Mainnet"
        }
      },
      "derivation_path": "m/44'/60'/0'/0/0",
      "is_active": true,
      "created_at": "2023-01-01T12:00:00Z",
      "updated_at": "2023-01-01T12:00:00Z"
    }
  ]
}
Get Wallet by ID
GET /client/wallets/{id}
Authorization: Bearer {token}
Path Parameters:
  • id (int, required): Wallet ID
Response: Same as wallet object in Get User Wallets
Get Wallets by Balance
GET /client/wallets/balance/{balance_id}
Authorization: Bearer {token}
Path Parameters:
  • balance_id (int, required): Balance ID
Response: Same as Get User Wallets

Error Responses

All endpoints return standardized error responses:
{
  "code": 400,
  "message": "Bad Request",
  "error": "Invalid request parameters"
}
Common HTTP Status Codes:
  • 200: Success
  • 400: Bad Request
  • 401: Unauthorized (missing or invalid token)
  • 403: Forbidden (insufficient permissions)
  • 404: Not Found
  • 422: Unprocessable Entity (validation errors)
  • 500: Internal Server Error

Frontend Integration Guide

Authentication

All balance and wallet endpoints require authentication. Include the Bearer token in the Authorization header:
const headers = {
  'Authorization': `Bearer ${token}`,
  'Content-Type': 'application/json'
};

Asset Management

Fetching Assets

// Get all assets with pagination
const fetchAssets = async (page = 1, pageSize = 10, search = '', assetType = '') => {
  const params = new URLSearchParams({
    page: page.toString(),
    page_size: pageSize.toString(),
    ...(search && { search }),
    ...(assetType && { asset_type: assetType })
  });
  
  const response = await fetch(`/client/assets?${params}`, {
    headers: { 'Content-Type': 'application/json' }
  });
  
  return response.json();
};

// Get asset by symbol
const fetchAssetBySymbol = async (symbol) => {
  const response = await fetch(`/client/assets/symbol/${symbol}`, {
    headers: { 'Content-Type': 'application/json' }
  });
  
  return response.json();
};

Asset Selection Component

import React, { useState, useEffect } from 'react';

const AssetSelector = ({ onAssetSelect, selectedAsset }) => {
  const [assets, setAssets] = useState([]);
  const [loading, setLoading] = useState(false);
  const [search, setSearch] = useState('');

  useEffect(() => {
    fetchAssets();
  }, [search]);

  const fetchAssets = async () => {
    setLoading(true);
    try {
      const response = await fetchAssets(1, 50, search);
      if (response.code === 200) {
        setAssets(response.data.assets);
      }
    } catch (error) {
      console.error('Error fetching assets:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="asset-selector">
      <input
        type="text"
        placeholder="Search assets..."
        value={search}
        onChange={(e) => setSearch(e.target.value)}
      />
      {loading ? (
        <div>Loading...</div>
      ) : (
        <div className="asset-list">
          {assets.map(asset => (
            <div
              key={asset.id}
              className={`asset-item ${selectedAsset?.id === asset.id ? 'selected' : ''}`}
              onClick={() => onAssetSelect(asset)}
            >
              <span className="symbol">{asset.symbol}</span>
              <span className="name">{asset.name}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

Balance Management

Fetching User Balances

// Get all user balances
const fetchUserBalances = async (token) => {
  const response = await fetch('/client/balances', {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });
  
  return response.json();
};

// Get balance for specific asset
const fetchBalanceByAsset = async (assetId, token) => {
  const response = await fetch(`/client/balances/asset/${assetId}`, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });
  
  return response.json();
};

Balance Display Component

import React, { useState, useEffect } from 'react';

const BalanceDisplay = ({ token }) => {
  const [balances, setBalances] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    fetchBalances();
  }, [token]);

  const fetchBalances = async () => {
    setLoading(true);
    try {
      const response = await fetchUserBalances(token);
      if (response.code === 200) {
        setBalances(response.data);
      }
    } catch (error) {
      console.error('Error fetching balances:', error);
    } finally {
      setLoading(false);
    }
  };

  const formatBalance = (balance, decimals) => {
    return parseFloat(balance).toFixed(decimals);
  };

  return (
    <div className="balance-display">
      <h3>Your Balances</h3>
      {loading ? (
        <div>Loading balances...</div>
      ) : (
        <div className="balance-list">
          {balances.map(balance => (
            <div key={balance.id} className="balance-item">
              <div className="asset-info">
                <span className="symbol">{balance.asset.symbol}</span>
                <span className="name">{balance.asset.name}</span>
              </div>
              <div className="balance-amounts">
                <div className="total">
                  Total: {formatBalance(balance.balance, balance.asset.decimals)}
                </div>
                <div className="available">
                  Available: {formatBalance(balance.available, balance.asset.decimals)}
                </div>
                {parseFloat(balance.locked) > 0 && (
                  <div className="locked">
                    Locked: {formatBalance(balance.locked, balance.asset.decimals)}
                  </div>
                )}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

Wallet Management

Generating Wallets

// Generate wallet for specific asset network
const generateWallet = async (assetNetworkId, token) => {
  const response = await fetch(`/client/balances/generate-wallet?asset_network_id=${assetNetworkId}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });
  
  return response.json();
};

// Get user wallets
const fetchUserWallets = async (token) => {
  const response = await fetch('/client/wallets', {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });
  
  return response.json();
};

Wallet Generation Component

import React, { useState } from 'react';

const WalletGenerator = ({ assetNetwork, token, onWalletGenerated }) => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  const handleGenerateWallet = async () => {
    setLoading(true);
    setError('');
    
    try {
      const response = await generateWallet(assetNetwork.id, token);
      if (response.code === 200) {
        onWalletGenerated(response.data);
      } else {
        setError(response.message || 'Failed to generate wallet');
      }
    } catch (err) {
      setError('Network error occurred');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="wallet-generator">
      <h4>Generate Wallet for {assetNetwork.asset.symbol}</h4>
      <p>Network: {assetNetwork.network.name}</p>
      
      {error && <div className="error">{error}</div>}
      
      <button 
        onClick={handleGenerateWallet} 
        disabled={loading}
        className="generate-btn"
      >
        {loading ? 'Generating...' : 'Generate Wallet'}
      </button>
    </div>
  );
};

Wallet Display Component

import React, { useState, useEffect } from 'react';

const WalletDisplay = ({ token }) => {
  const [wallets, setWallets] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    fetchWallets();
  }, [token]);

  const fetchWallets = async () => {
    setLoading(true);
    try {
      const response = await fetchUserWallets(token);
      if (response.code === 200) {
        setWallets(response.data);
      }
    } catch (error) {
      console.error('Error fetching wallets:', error);
    } finally {
      setLoading(false);
    }
  };

  const copyToClipboard = (text) => {
    navigator.clipboard.writeText(text);
    // Show success message
  };

  return (
    <div className="wallet-display">
      <h3>Your Wallets</h3>
      {loading ? (
        <div>Loading wallets...</div>
      ) : (
        <div className="wallet-list">
          {wallets.map(wallet => (
            <div key={wallet.id} className="wallet-item">
              <div className="wallet-info">
                <div className="asset">
                  {wallet.balance.asset.symbol} - {wallet.asset_network.network.name}
                </div>
                <div className="address">
                  <span>{wallet.wallet_address}</span>
                  <button onClick={() => copyToClipboard(wallet.wallet_address)}>
                    Copy
                  </button>
                </div>
                <div className="derivation">
                  Path: {wallet.derivation_path}
                </div>
              </div>
              <div className="wallet-status">
                {wallet.is_active ? 'Active' : 'Inactive'}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

Network Management

Fetching Networks

// Get all networks
const fetchNetworks = async () => {
  const response = await fetch('/client/networks/all', {
    headers: { 'Content-Type': 'application/json' }
  });
  
  return response.json();
};

// Get networks with pagination
const fetchNetworksPaginated = async (page = 1, pageSize = 10, search = '') => {
  const params = new URLSearchParams({
    page: page.toString(),
    page_size: pageSize.toString(),
    ...(search && { search })
  });
  
  const response = await fetch(`/client/networks?${params}`, {
    headers: { 'Content-Type': 'application/json' }
  });
  
  return response.json();
};

Network Selection Component

import React, { useState, useEffect } from 'react';

const NetworkSelector = ({ onNetworkSelect, selectedNetwork }) => {
  const [networks, setNetworks] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    fetchNetworks();
  }, []);

  const fetchNetworks = async () => {
    setLoading(true);
    try {
      const response = await fetchNetworks();
      if (response.code === 200) {
        setNetworks(response.data);
      }
    } catch (error) {
      console.error('Error fetching networks:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="network-selector">
      <h4>Select Network</h4>
      {loading ? (
        <div>Loading networks...</div>
      ) : (
        <div className="network-list">
          {networks.map(network => (
            <div
              key={network.id}
              className={`network-item ${selectedNetwork?.id === network.id ? 'selected' : ''}`}
              onClick={() => onNetworkSelect(network)}
            >
              <div className="network-name">{network.name}</div>
              <div className="chain-info">
                {network.chain.name} ({network.chain.symbol})
              </div>
              <div className="network-type">
                {network.is_testnet ? 'Testnet' : 'Mainnet'}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

Error Handling

Global Error Handler

const handleApiError = (error, response) => {
  if (response) {
    switch (response.code) {
      case 401:
        // Redirect to login
        window.location.href = '/login';
        break;
      case 403:
        // Show access denied message
        showError('Access denied. You do not have permission to perform this action.');
        break;
      case 404:
        // Show not found message
        showError('The requested resource was not found.');
        break;
      case 422:
        // Show validation errors
        showError(response.error || 'Validation error occurred.');
        break;
      case 500:
        // Show server error message
        showError('A server error occurred. Please try again later.');
        break;
      default:
        showError(response.message || 'An unexpected error occurred.');
    }
  } else {
    showError('Network error occurred. Please check your connection.');
  }
};

const showError = (message) => {
  // Implement your error display logic
  console.error(message);
  // Could use toast notifications, modals, etc.
};

API Wrapper with Error Handling

const apiCall = async (url, options = {}) => {
  try {
    const response = await fetch(url, {
      headers: {
        'Content-Type': 'application/json',
        ...options.headers
      },
      ...options
    });
    
    const data = await response.json();
    
    if (data.code >= 400) {
      handleApiError(null, data);
      throw new Error(data.message || 'API Error');
    }
    
    return data;
  } catch (error) {
    if (error.name === 'TypeError') {
      // Network error
      handleApiError(error, null);
    }
    throw error;
  }
};

Best Practices

1. State Management

  • Use React Context or Redux for global state management
  • Cache API responses to reduce unnecessary requests
  • Implement optimistic updates for better UX

2. Security

  • Never store sensitive data (private keys, tokens) in localStorage
  • Use secure HTTP-only cookies for authentication when possible
  • Implement proper token refresh logic

3. Performance

  • Implement pagination for large data sets
  • Use debouncing for search inputs
  • Lazy load components and data when possible

4. User Experience

  • Show loading states for all async operations
  • Provide clear error messages
  • Implement retry mechanisms for failed requests
  • Use skeleton loaders for better perceived performance

5. Data Validation

  • Validate data on both client and server side
  • Implement proper form validation
  • Handle edge cases gracefully
This comprehensive guide should help frontend developers integrate with the Asset and Balance features effectively. The API is designed to be RESTful and follows standard HTTP conventions for easy integration with any frontend framework.