{"id":51654694,"url":"https://github.com/fireblocks/cardano-raw-sdk","last_synced_at":"2026-07-14T08:03:57.187Z","repository":{"id":351336384,"uuid":"1113626660","full_name":"fireblocks/cardano-raw-sdk","owner":"fireblocks","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-09T13:39:55.000Z","size":1910,"stargazers_count":2,"open_issues_count":1,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T15:23:33.796Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fireblocks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-10T08:37:06.000Z","updated_at":"2026-05-07T09:06:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"c3080e52-6c93-4be8-9216-ece98d6e7ed6","html_url":"https://github.com/fireblocks/cardano-raw-sdk","commit_stats":null,"previous_names":["fireblocks/cardano-raw-sdk"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fireblocks/cardano-raw-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fcardano-raw-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fcardano-raw-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fcardano-raw-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fcardano-raw-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fireblocks","download_url":"https://codeload.github.com/fireblocks/cardano-raw-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fcardano-raw-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35451878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-14T02:00:06.603Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-14T08:03:56.272Z","updated_at":"2026-07-14T08:03:57.177Z","avatar_url":"https://github.com/fireblocks.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cardano Raw SDK\n\nA TypeScript SDK for managing Cardano token transfers through Fireblocks, with integrated Iagon API services for balance queries, transaction history, and token operations.\n\n## Features\n\n- 🔐 **Fireblocks Integration**: Secure vault account management and transaction signing\n- 🏦 **Balance Queries**: Check balances by address, credential, or stake key\n- 💸 **Token Transfers**: Execute Cardano token transfers with automatic UTXO selection\n  - Native ADA transfers\n  - Single token (CNT) transfers\n  - Multi-token transfers (multiple tokens in one transaction)\n  - Address-to-address transfers\n  - Vault-to-vault transfers for seamless internal operations\n- 💰 **Fee Estimation**: Accurate fee calculation for ADA, single-token, and multi-token transfers\n- 🔧 **UTxO Management**: Consolidate fragmented UTxOs to optimize wallet efficiency\n- 🗳️ **Governance Operations**: Full Conway-era governance support\n  - Register as a DRep (Delegated Representative)\n  - Cast votes on governance actions\n  - Delegate voting power to DReps\n- 🏊 **Staking Operations**: Complete staking lifecycle management\n  - Register/deregister stake keys\n  - Delegate to stake pools\n  - Withdraw rewards\n- 📊 **Transaction History**: Retrieve basic and detailed transaction history with pagination\n- 🏊 **Pool Information**: Query stake pool metadata, delegators, and blocks\n- 🔄 **Connection Pooling**: Efficient SDK instance management with automatic cleanup\n- 🌐 **Multi-Network Support**: Works with Cardano mainnet, preprod, and preview networks\n- 🚀 **REST API Server**: Optional Express server for HTTP-based operations\n- 🐳 **Docker Support**: Easy deployment with Docker and Docker Compose\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Usage Methods](#usage-methods)\n  - [Method 1: TypeScript SDK](#method-1-typescript-sdk)\n  - [Method 2: REST API Service](#method-2-rest-api-service)\n- [Configuration](#configuration)\n- [API Documentation](#api-documentation)\n- [Examples](#examples)\n- [Development](#development)\n\n## Installation\n\n### Prerequisites\n\n- Node.js 18+ (for SDK usage)\n- Docker \u0026 Docker Compose (for API service deployment)\n- Fireblocks API credentials\n- Iagon API key (required for balance queries, transaction history, and transfers)\n\n### Install as a TypeScript Package\n\n**Install from GitHub** (for use as a dependency in your project):\n\n```bash\n# Install directly from GitHub\nnpm install github:fireblocks/cardano-raw-sdk\n\n# Or install a specific branch/tag\nnpm install github:fireblocks/cardano-raw-sdk#main\nnpm install github:fireblocks/cardano-raw-sdk#v1.0.0\n```\n\n**Or clone for development**:\n\n```bash\ngit clone https://github.com/fireblocks/cardano-raw-sdk.git\ncd cardano-raw-sdk\nnpm install\nnpm run build\n```\n\n## Usage Methods\n\n### Method 1: TypeScript SDK\n\nUse the SDK directly in your TypeScript/JavaScript application.\n\n#### Basic Setup\n\n```typescript\nimport { FireblocksCardanoRawSDK } from \"cardano-raw-sdk\";\nimport { Networks, SupportedAssets } from \"cardano-raw-sdk/types\";\nimport { BasePath } from \"@fireblocks/ts-sdk\";\n\n// Initialize the SDK\nconst sdk = await FireblocksCardanoRawSDK.createInstance({\n  fireblocksConfig: {\n    apiKey: \"your-fireblocks-api-key\",\n    secretKey: \"your-fireblocks-secret-key\",\n    basePath: BasePath.US,\n  },\n  vaultAccountId: \"your-vault-account-id\",\n  network: Networks.MAINNET,\n  iagonApiKey: \"your-iagon-api-key\",\n});\n```\n\n#### Get Balance\n\n```typescript\n// Get balance by address\nconst balance = await sdk.getBalanceByAddress({\n  index: 0,\n  groupByPolicy: false,\n});\n\nconsole.log(\"Balance:\", balance);\n\n// Get balance by stake key\nconst stakeBalance = await sdk.getBalanceByStakeKey({\n  stakeKey: \"stake1u8a9qstrmj...\",\n  groupByPolicy: true,\n});\n```\n\n#### Transfer Native ADA\n\nTransfer ADA without any tokens:\n\n```typescript\nconst result = await sdk.transferAda({\n  index: 0, // Source address index\n  recipientAddress: \"addr1qxy...\",\n  adaAmount: 5000000, // 5 ADA in lovelace\n});\n\nconsole.log(\"Transaction Hash:\", result.txHash);\nconsole.log(\"Sender Address:\", result.senderAddress);\nconsole.log(\"Fee:\", result.fee.ada, \"ADA\");\n```\n\n#### Transfer Single Token (CNT)\n\nThe SDK supports two transfer modes:\n\n**1. Transfer to a Cardano Address**\n\n```typescript\nconst transferResult = await sdk.transfer({\n  index: 0,\n  recipientAddress: \"addr1qxy...\",\n  tokenPolicyId: \"f0ff48bbb7bbe9d5...\",\n  tokenName: \"4e49...\",\n  requiredTokenAmount: 1000000,\n});\n\nconsole.log(\"Transaction Hash:\", transferResult.txHash);\nconsole.log(\"Sender Address:\", transferResult.senderAddress);\nconsole.log(\"Fee:\", transferResult.fee.ada, \"ADA\"); // e.g., \"0.170000 ADA\"\nconsole.log(\"Fee (lovelace):\", transferResult.fee.lovelace); // e.g., \"170000\"\n```\n\n**2. Vault-to-Vault Transfer**\n\n```typescript\nconst transferResult = await sdk.transfer({\n  index: 0, // Source address index\n  recipientVaultAccountId: \"1\", // Destination vault account\n  recipientIndex: 0, // Destination address index (optional, defaults to 0)\n  tokenPolicyId: \"f0ff48bbb7bbe9d5...\",\n  tokenName: \"4e49...\",\n  requiredTokenAmount: 1000000,\n});\n\nconsole.log(\"Transaction Hash:\", transferResult.txHash);\nconsole.log(\"Sender Address:\", transferResult.senderAddress);\nconsole.log(\"Fee:\", transferResult.fee.ada, \"ADA\"); // e.g., \"0.170000 ADA\"\n```\n\n**Note**: You must provide exactly one of `recipientAddress` or `recipientVaultAccountId`, not both.\n\n#### Transfer Multiple Tokens\n\nTransfer multiple different tokens in a single transaction:\n\n```typescript\nconst result = await sdk.transferMultipleTokens({\n  index: 0,\n  recipientAddress: \"addr1qxy...\",\n  tokens: [\n    {\n      policyId: \"f0ff48bbb7bbe9d5...\",\n      assetName: \"4e4654\",\n      amount: 1000000,\n    },\n    {\n      policyId: \"a1b2c3d4e5f6...\",\n      assetName: \"544f4b454e\",\n      amount: 500000,\n    },\n  ],\n  includeAda: true, // Optional: include extra ADA in the transfer\n  adaAmount: 2000000, // 2 ADA in lovelace (required if includeAda is true)\n});\n\nconsole.log(\"Transaction Hash:\", result.txHash);\nconsole.log(\"Fee:\", result.fee.ada, \"ADA\");\n```\n\n**Estimate multi-token transfer fee:**\n\n```typescript\nconst feeEstimate = await sdk.estimateMultiTokenTransactionFee({\n  index: 0,\n  recipientAddress: \"addr1qxy...\",\n  tokens: [\n    { policyId: \"f0ff48bbb...\", assetName: \"4e4654\", amount: 1000000 },\n    { policyId: \"a1b2c3d4e5f6...\", assetName: \"544f4b454e\", amount: 500000 },\n  ],\n});\n\nconsole.log(\"Estimated Fee:\", feeEstimate.fee.ada, \"ADA\");\n```\n\n#### Consolidate UTxOs\n\nConsolidate fragmented UTxOs to optimize your wallet:\n\n```typescript\nconst result = await sdk.consolidateUtxos({\n  index: 0,\n  targetAddress: \"addr1qxy...\", // Optional: defaults to source address\n});\n\nconsole.log(\"Transaction Hash:\", result.txHash);\nconsole.log(\"Consolidated\", result.inputCount, \"UTxOs\");\nconsole.log(\"Fee:\", result.fee.ada, \"ADA\");\n```\n\n#### Transaction History\n\n```typescript\n// Get basic transaction history\nconst history = await sdk.getTransactionHistory({\n  index: 0,\n  limit: 10,\n  offset: 0,\n  fromSlot: 100000,\n});\n\n// Get detailed transaction history with inputs/outputs\nconst detailedHistory = await sdk.getDetailedTxHistory({\n  index: 0,\n  limit: 10,\n  offset: 0,\n});\n\n// Get transaction details by hash\nconst txDetails = await sdk.getTransactionDetails(\"6c9e6d70a0ce7ca5d...\");\n```\n\n#### Asset Information\n\n```typescript\n// Get detailed asset information including metadata and decimals\nconst assetInfo = await sdk.getAssetInfo(\n  \"f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a\", // Policy ID\n  \"4e4654\" // Asset name (hex)\n);\n\nconsole.log(\"Token Name:\", assetInfo.data.metadata?.name);\nconsole.log(\"Ticker:\", assetInfo.data.metadata?.ticker);\nconsole.log(\"Decimals:\", assetInfo.data.metadata?.decimals);\nconsole.log(\"Total Supply:\", assetInfo.data.total_supply);\nconsole.log(\"Logo:\", assetInfo.data.metadata?.logo);\n\n// Use decimals to format token amounts correctly\nconst rawAmount = 1000000;\nconst decimals = assetInfo.data.metadata?.decimals || 0;\nconst formattedAmount = rawAmount / Math.pow(10, decimals);\nconsole.log(`Amount: ${formattedAmount} ${assetInfo.data.metadata?.ticker}`);\n```\n\n#### Governance Operations\n\n**Register as a DRep (Delegated Representative)**\n\n```typescript\nconst result = await sdk.registerAsDRep({\n  vaultAccountId: \"your-vault-id\",\n  index: 0,\n  anchor: {\n    url: \"https://example.com/drep-metadata.json\",\n    dataHash: \"abc123...\", // Blake2b-256 hash of the metadata\n  },\n});\n\nconsole.log(\"Transaction Hash:\", result.txHash);\nconsole.log(\"DRep ID:\", result.drepId);\n// Note: Requires 500 ADA deposit\n```\n\n**Cast a Governance Vote (as a DRep)**\n\n```typescript\nconst result = await sdk.castGovernanceVote({\n  vaultAccountId: \"your-vault-id\",\n  index: 0,\n  governanceActionTxHash: \"abc123...\",\n  governanceActionIndex: 0,\n  vote: \"yes\", // \"yes\", \"no\", or \"abstain\"\n});\n\nconsole.log(\"Transaction Hash:\", result.txHash);\n```\n\n**Delegate Voting Power to a DRep**\n\n```typescript\nconst result = await sdk.delegateToDRep({\n  vaultAccountId: \"your-vault-id\",\n  index: 0,\n  drepId: \"drep1...\", // DRep credential or key hash\n});\n\nconsole.log(\"Transaction Hash:\", result.txHash);\n```\n\n#### Pool Information\n\n```typescript\n// Get pool metadata (name, ticker, description)\nconst metadata = await sdk.getPoolMetadata(\"pool1...\");\nconsole.log(\"Pool Name:\", metadata.data.name);\nconsole.log(\"Ticker:\", metadata.data.ticker);\n\n// Get pool delegators summary\nconst delegators = await sdk.getPoolDelegators(\"pool1...\");\nconsole.log(\"Total Delegators:\", delegators.data.total_count);\nconsole.log(\"Active Stake:\", delegators.data.active_stake);\n\n// Get detailed delegator list with pagination\nconst delegatorList = await sdk.getPoolDelegatorsList(\"pool1...\", 10, 0);\n\n// Get blocks produced by pool\nconst blocks = await sdk.getPoolBlocks(\"pool1...\");\nconsole.log(\"Total Blocks:\", blocks.data.length);\n```\n\n#### Vault Account Operations\n\n```typescript\n// Get vault account addresses\nconst addresses = await sdk.getVaultAccountAddresses();\n\n// Get public key (change index, address index)\nconst publicKey = await sdk.getPublicKey(0, 0);\n```\n\n#### Graceful Shutdown\n\n```typescript\n// Clean up resources when done\nawait sdk.shutdown();\n```\n\n### Method 2: REST API Service\n\nRun the SDK as a REST API service using Docker or Node.js directly.\n\n#### Quick Start with Docker\n\n1. **Clone the repository**:\n\n   ```bash\n   git clone https://github.com/fireblocks/cardano-raw-sdk.git\n   cd cardano-raw-sdk\n   ```\n\n2. **Configure environment variables**:\n\n   ```bash\n   cp .env.example .env\n   # Edit .env with your credentials\n   ```\n\n3. **Start the service**:\n\n   ```bash\n   docker-compose up -d\n   ```\n\n4. **Access the API**:\n   - API Base URL: `http://localhost:8000/api`\n   - Swagger Documentation: `http://localhost:8000/api-docs`\n   - Health Check: `http://localhost:8000/health`\n\n#### API Endpoints\n\n##### Balance Operations\n\n```bash\n# Get balance by address\nGET /api/balance/address/:vaultAccountId?assetId=ADA\u0026index=0\u0026groupByPolicy=false\n\n# Get balance by credential\nGET /api/balance/credential/:vaultAccountId/:credential?groupByPolicy=false\n\n# Get balance by stake key\nGET /api/balance/stake-key/:vaultAccountId/:stakeKey?groupByPolicy=false\n```\n\n##### Webhook Operations\n\n**Setup in Fireblocks Console:**\n\n1. Go to **Fireblocks Console → Settings → Webhooks**\n2. Add webhook URL: `https://your-domain.com/api/webhook`\n3. Select events: `TRANSACTION_CREATED`, `TRANSACTION_STATUS_UPDATED`, etc.\n4. Fireblocks will automatically sign webhooks with both JWKS and legacy signatures\n\n**Important:** Ensure your server's `FIREBLOCKS_BASE_PATH` environment variable matches your Fireblocks workspace:\n\n- US workspace: `https://api.fireblocks.io` (default)\n- EU workspace: `https://api.eu1.fireblocks.io`\n- EU2 workspace: `https://api.eu2.fireblocks.io`\n- Sandbox: `https://sandbox-api.fireblocks.io`\n\n**Endpoint:**\n\n```bash\n# Enrich Fireblocks webhook with automatic signature verification\nPOST /api/webhook\nContent-Type: application/json\nHeaders:\n  - fireblocks-webhook-signature: \u003cJWT signature\u003e (added by Fireblocks)\n  - fireblocks-signature: \u003cLegacy signature\u003e (added by Fireblocks)\n\nBody:\n{\n  \"eventType\": \"transaction.created\",\n  \"data\": { ... }\n}\n\n# Response (enriched with CNT data):\n{\n  \"eventType\": \"transaction.created\",\n  \"data\": {\n    ...\n    \"cardanoTokensData\": {\n      \"tx_hash\": \"...\",\n      \"inputs\": [...],\n      \"outputs\": [...]\n    }\n  }\n}\n```\n\n**Security:** The endpoint automatically verifies webhook signatures using:\n\n- **JWKS** (modern, automatic key rotation) - tries first\n- **Legacy RSA-SHA512** (static keys) - fallback\n- Verification environment is automatically determined from `FIREBLOCKS_BASE_PATH` config\n\nInvalid signatures are rejected with 401 error.\n\n##### Transaction Operations\n\n```bash\n# Get transaction details by hash\nGET /api/tx/hash/:hash\n\n# Get asset information (metadata, decimals, supply)\nGET /api/assets/:policyId/:assetName\n\n# Get transaction history\nGET /api/tx/history/:vaultAccountId?index=0\u0026limit=10\u0026offset=0\u0026fromSlot=100000\n\n# Get detailed transaction history\nGET /api/tx/address/:vaultAccountId?index=0\u0026limit=10\u0026offset=0\n```\n\n##### Transfer Operations\n\n**ADA Transfers**\n\n```bash\n# Transfer native ADA\nPOST /api/transfers/ada\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"your-vault-id\",\n  \"recipientAddress\": \"addr1qxy...\",\n  \"adaAmount\": 5000000,\n  \"index\": 0\n}\n\n# Estimate ADA transfer fee\nPOST /api/fee-estimate/ada\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"your-vault-id\",\n  \"recipientAddress\": \"addr1qxy...\",\n  \"adaAmount\": 5000000,\n  \"index\": 0\n}\n```\n\n**Single Token (CNT) Transfers**\n\n```bash\n# Execute transfer (to address)\nPOST /api/transfers\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"your-vault-id\",\n  \"recipientAddress\": \"addr1qxy...\",\n  \"tokenPolicyId\": \"f0ff48bbb7bbe9d5...\",\n  \"tokenName\": \"4e49...\",\n  \"requiredTokenAmount\": 1000000,\n  \"index\": 0\n}\n\n# Response:\n{\n  \"txHash\": \"a1b2c3d4e5f6...\",\n  \"senderAddress\": \"addr1qxy...\",\n  \"tokenName\": \"4e49...\",\n  \"fee\": {\n    \"lovelace\": \"170000\",\n    \"ada\": \"0.170000\"\n  }\n}\n\n# Execute transfer (vault-to-vault)\nPOST /api/transfers\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"0\",\n  \"recipientVaultAccountId\": \"1\",\n  \"recipientIndex\": 0,\n  \"tokenPolicyId\": \"f0ff48bbb7bbe9d5...\",\n  \"tokenName\": \"4e49...\",\n  \"requiredTokenAmount\": 1000000,\n  \"index\": 0\n}\n```\n\n**Multi-Token Transfers**\n\n```bash\n# Transfer multiple tokens in one transaction\nPOST /api/transfers/tokens\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"your-vault-id\",\n  \"recipientAddress\": \"addr1qxy...\",\n  \"tokens\": [\n    {\n      \"policyId\": \"f0ff48bbb7bbe9d5...\",\n      \"assetName\": \"4e4654\",\n      \"amount\": 1000000\n    },\n    {\n      \"policyId\": \"a1b2c3d4e5f6...\",\n      \"assetName\": \"544f4b454e\",\n      \"amount\": 500000\n    }\n  ],\n  \"includeAda\": true,\n  \"adaAmount\": 2000000,\n  \"index\": 0\n}\n\n# Estimate multi-token transfer fee\nPOST /api/fee-estimate/tokens\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"your-vault-id\",\n  \"recipientAddress\": \"addr1qxy...\",\n  \"tokens\": [\n    { \"policyId\": \"f0ff48bbb...\", \"assetName\": \"4e4654\", \"amount\": 1000000 }\n  ],\n  \"index\": 0\n}\n```\n\n**UTxO Consolidation**\n\n```bash\n# Consolidate fragmented UTxOs\nPOST /api/utxos/consolidate\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"your-vault-id\",\n  \"index\": 0,\n  \"targetAddress\": \"addr1qxy...\" // Optional\n}\n\n# Response:\n{\n  \"txHash\": \"a1b2c3d4e5f6...\",\n  \"inputCount\": 15,\n  \"fee\": {\n    \"lovelace\": \"200000\",\n    \"ada\": \"0.200000\"\n  }\n}\n```\n\n##### Governance Operations\n\n```bash\n# Register as a DRep (requires 500 ADA deposit)\nPOST /api/governance/register-drep\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"your-vault-id\",\n  \"index\": 0,\n  \"anchor\": {\n    \"url\": \"https://example.com/drep-metadata.json\",\n    \"dataHash\": \"abc123...\"\n  }\n}\n\n# Cast a governance vote (as a DRep)\nPOST /api/governance/vote\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"your-vault-id\",\n  \"index\": 0,\n  \"governanceActionTxHash\": \"abc123...\",\n  \"governanceActionIndex\": 0,\n  \"vote\": \"yes\"\n}\n\n# Delegate voting power to a DRep\nPOST /api/governance/delegate-drep\nContent-Type: application/json\n\n{\n  \"vaultAccountId\": \"your-vault-id\",\n  \"index\": 0,\n  \"drepId\": \"drep1...\"\n}\n```\n\n##### Pool Information\n\n```bash\n# Get pool metadata (name, ticker, description)\nGET /api/pools/:poolId/metadata\n\n# Get pool delegators summary\nGET /api/pools/:poolId/delegators?limit=10\u0026offset=0\n\n# Get detailed delegator list\nGET /api/pools/:poolId/delegators/list?limit=10\u0026offset=0\n\n# Get blocks produced by pool\nGET /api/pools/:poolId/blocks\n```\n\n##### Example cURL Commands\n\n```bash\n# Get balance\ncurl http://localhost:8000/api/balance/address/vault-123?assetId=ADA\u0026index=0\n\n# Get transaction history\ncurl http://localhost:8000/api/tx/history/vault-123?limit=5\n\n# Get asset information\ncurl http://localhost:8000/api/assets/f0ff48bbb7bbe9d5.../4e4654\n\n# Transfer native ADA\ncurl -X POST http://localhost:8000/api/transfers/ada \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"vaultAccountId\": \"vault-123\",\n    \"recipientAddress\": \"addr1qxy...\",\n    \"adaAmount\": 5000000,\n    \"index\": 0\n  }'\n\n# Estimate ADA transfer fee\ncurl -X POST http://localhost:8000/api/fee-estimate/ada \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"vaultAccountId\": \"vault-123\",\n    \"recipientAddress\": \"addr1qxy...\",\n    \"adaAmount\": 5000000,\n    \"index\": 0\n  }'\n\n# Execute CNT transfer (to address)\ncurl -X POST http://localhost:8000/api/transfers \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"vaultAccountId\": \"vault-123\",\n    \"recipientAddress\": \"addr1qxy...\",\n    \"tokenPolicyId\": \"f0ff48bbb...\",\n    \"tokenName\": \"4e49...\",\n    \"requiredTokenAmount\": 1000000\n  }'\n# Response: {\"txHash\":\"a1b2c3d4...\",\"senderAddress\":\"addr1qxy...\",\"tokenName\":\"4e49...\",\"fee\":{\"lovelace\":\"170000\",\"ada\":\"0.170000\"}}\n\n# Execute CNT transfer (vault-to-vault)\ncurl -X POST http://localhost:8000/api/transfers \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"vaultAccountId\": \"0\",\n    \"recipientVaultAccountId\": \"1\",\n    \"tokenPolicyId\": \"f0ff48bbb...\",\n    \"tokenName\": \"4e49...\",\n    \"requiredTokenAmount\": 1000000\n  }'\n\n# Transfer multiple tokens\ncurl -X POST http://localhost:8000/api/transfers/tokens \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"vaultAccountId\": \"vault-123\",\n    \"recipientAddress\": \"addr1qxy...\",\n    \"tokens\": [\n      {\"policyId\": \"f0ff48bbb...\", \"assetName\": \"4e4654\", \"amount\": 1000000},\n      {\"policyId\": \"a1b2c3d4e5f6...\", \"assetName\": \"544f4b454e\", \"amount\": 500000}\n    ],\n    \"includeAda\": true,\n    \"adaAmount\": 2000000\n  }'\n\n# Consolidate UTxOs\ncurl -X POST http://localhost:8000/api/utxos/consolidate \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"vaultAccountId\": \"vault-123\",\n    \"index\": 0\n  }'\n\n# Register as DRep\ncurl -X POST http://localhost:8000/api/governance/register-drep \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"vaultAccountId\": \"vault-123\",\n    \"index\": 0,\n    \"anchor\": {\n      \"url\": \"https://example.com/drep-metadata.json\",\n      \"dataHash\": \"abc123...\"\n    }\n  }'\n\n# Cast governance vote\ncurl -X POST http://localhost:8000/api/governance/vote \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"vaultAccountId\": \"vault-123\",\n    \"index\": 0,\n    \"governanceActionTxHash\": \"abc123...\",\n    \"governanceActionIndex\": 0,\n    \"vote\": \"yes\"\n  }'\n\n# Delegate to DRep\ncurl -X POST http://localhost:8000/api/governance/delegate-drep \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"vaultAccountId\": \"vault-123\",\n    \"index\": 0,\n    \"drepId\": \"drep1...\"\n  }'\n\n# Get pool metadata\ncurl http://localhost:8000/api/pools/pool1.../metadata\n\n# Get pool delegators\ncurl http://localhost:8000/api/pools/pool1.../delegators?limit=10\n\n# Get pool blocks\ncurl http://localhost:8000/api/pools/pool1.../blocks\n```\n\n## Configuration\n\n### Environment Variables\n\nCopy `.env.example` to `.env` and fill in your values:\n\n```bash\ncp .env.example .env\n```\n\n| Variable                              | Required | Default                     | Description                                                    |\n| ------------------------------------- | -------- | --------------------------- | -------------------------------------------------------------- |\n| `PORT`                                | No       | `8000`                      | HTTP server port                                               |\n| `NODE_ENV`                            | No       | `production`                | Set to `development` only when using self-signed certs locally |\n| `FIREBLOCKS_API_USER_KEY`             | Yes      | -                           | Fireblocks API key UUID                                        |\n| `FIREBLOCKS_API_USER_SECRET_KEY_PATH` | Yes      | -                           | Absolute path to the Fireblocks RSA secret key file            |\n| `FIREBLOCKS_BASE_PATH`                | No       | `https://api.fireblocks.io` | Fireblocks workspace URL - also controls webhook JWKS region   |\n| `IAGON_API_KEY`                       | Yes      | -                           | Iagon API key for blockchain data queries                      |\n| `CARDANO_NETWORK`                     | No       | `mainnet`                   | `mainnet` or `preprod`                                         |\n\n**Fireblocks base path options:**\n\n- US (default): `https://api.fireblocks.io`\n\n### Fireblocks Secret Key\n\nThe SDK supports three ways to provide your Fireblocks RSA private key:\n\n#### Option 1: File Path (Recommended for local development)\n\n```bash\n# Create a secure directory\nmkdir -p ~/.fireblocks\n\n# Save your secret key\ncat \u003e ~/.fireblocks/secret.key \u003c\u003c 'EOF'\n-----BEGIN PRIVATE KEY-----\nMIIJQgIBADANBgkqhki...\n-----END PRIVATE KEY-----\nEOF\n\n# Set proper permissions\nchmod 600 ~/.fireblocks/secret.key\n\n# Set environment variable\nexport FIREBLOCKS_API_USER_SECRET_KEY_PATH=/home/user/.fireblocks/secret.key\n```\n\n#### Option 2: Direct PEM Content (CI/CD environments)\n\n```bash\n# Set the key content directly (with newlines)\nexport FIREBLOCKS_API_USER_SECRET_KEY=\"-----BEGIN PRIVATE KEY-----\nMIIJQgIBADANBgkqhki...\n-----END PRIVATE KEY-----\"\n```\n\n#### Option 3: Base64 Encoded (Recommended for CI/CD secrets)\n\n```bash\n# Encode your key file to base64 (single line, easy to store as secret)\ncat ~/.fireblocks/secret.key | base64 -w 0 \u003e key.b64\n\n# Set the base64-encoded content\nexport FIREBLOCKS_API_USER_SECRET_KEY=$(cat key.b64)\n```\n\n**Priority:** If both `FIREBLOCKS_API_USER_SECRET_KEY` and `FIREBLOCKS_API_USER_SECRET_KEY_PATH` are set, the direct key content takes precedence.\n\n## API Documentation\n\n### Swagger UI\n\nWhen running the API service, interactive API documentation is available at:\n\n```\nhttp://localhost:8000/api-docs\n```\n\n### TypeDoc Documentation\n\nGenerate TypeScript documentation:\n\n```bash\nnpm run docs\n```\n\nView the generated documentation by opening `docs/index.html` in your browser.\n\n## Examples\n\n### Example 1: Transfer Tokens with SDK\n\n```typescript\nimport { FireblocksCardanoRawSDK } from \"cardano-raw-sdk\";\nimport { Networks, SupportedAssets } from \"cardano-raw-sdk/types\";\nimport { BasePath } from \"@fireblocks/ts-sdk\";\n\nasync function transferTokens() {\n  const sdk = await FireblocksCardanoRawSDK.createInstance({\n    fireblocksConfig: {\n      apiKey: process.env.FIREBLOCKS_API_KEY!,\n      secretKey: process.env.FIREBLOCKS_SECRET_KEY!,\n      basePath: BasePath.US,\n    },\n    vaultAccountId: \"vault-123\",\n    network: Networks.MAINNET,\n    iagonApiKey: process.env.IAGON_API_KEY!,\n  });\n\n  try {\n    const result = await sdk.transfer({\n      recipientAddress: \"addr1qxy...\",\n      tokenPolicyId: \"f0ff48bbb7bbe9d5...\",\n      tokenName: \"4e49...\",\n      requiredTokenAmount: 1000000,\n    });\n\n    console.log(\"Transfer successful!\");\n    console.log(\"Transaction Hash:\", result.txHash);\n    console.log(\"Sender Address:\", result.senderAddress);\n    console.log(\"Transaction Fee:\", result.fee.ada, \"ADA\");\n    console.log(\"View on Cardanoscan:\", `https://cardanoscan.io/transaction/${result.txHash}`);\n  } catch (error) {\n    console.error(\"Transfer failed:\", error);\n  } finally {\n    await sdk.shutdown();\n  }\n}\n\ntransferTokens();\n```\n\n### Example 2: SDK Manager with Connection Pooling\n\n```typescript\nimport { SdkManager } from \"cardano-raw-sdk/pool\";\nimport { FireblocksCardanoRawSDK } from \"cardano-raw-sdk\";\nimport { Networks } from \"cardano-raw-sdk/types\";\nimport { BasePath } from \"@fireblocks/ts-sdk\";\n\nconst manager = new SdkManager(\n  {\n    apiKey: process.env.FIREBLOCKS_API_KEY!,\n    secretKey: process.env.FIREBLOCKS_SECRET_KEY!,\n    basePath: BasePath.US,\n  },\n  Networks.MAINNET,\n  {\n    maxPoolSize: 50,\n    idleTimeoutMs: 20 * 60 * 1000,\n  },\n  async (vaultAccountId, fireblocksConfig, network) =\u003e\n    FireblocksCardanoRawSDK.createInstance({\n      fireblocksConfig,\n      vaultAccountId,\n      network,\n    })\n);\n\n// Get SDK for a vault account (automatically pooled)\nconst sdk1 = await manager.getSdk(\"vault-123\");\nconst balance1 = await sdk1.getBalanceByAddress({ index: 0 });\n\n// Reuses the same SDK instance\nconst sdk2 = await manager.getSdk(\"vault-123\");\nconst balance2 = await sdk2.getBalanceByAddress({ index: 0 });\n\n// Release SDK back to pool when done\nmanager.releaseSdk(\"vault-123\");\n\n// Get pool metrics\nconst metrics = manager.getMetrics();\nconsole.log(\"Pool Metrics:\", metrics);\n\n// Shutdown when done\nawait manager.shutdown();\n```\n\n### Example 3: API Client in JavaScript\n\n```javascript\nconst axios = require(\"axios\");\n\nconst API_BASE_URL = \"http://localhost:8000/api\";\n\nasync function getBalanceAndTransfer() {\n  try {\n    // Get balance\n    const balanceResponse = await axios.get(`${API_BASE_URL}/balance/address/vault-123`, {\n      params: {\n        assetId: \"ADA\",\n        index: 0,\n        groupByPolicy: true,\n      },\n    });\n    console.log(\"Balance:\", balanceResponse.data);\n\n    // Execute transfer\n    const transferResponse = await axios.post(`${API_BASE_URL}/transfers`, {\n      vaultAccountId: \"vault-123\",\n      recipientAddress: \"addr1qxy...\",\n      tokenPolicyId: \"f0ff48bbb7bbe9d5...\",\n      tokenName: \"4e49...\",\n      requiredTokenAmount: 1000000,\n    });\n    console.log(\"Transfer Result:\", transferResponse.data);\n    console.log(\"Transaction Hash:\", transferResponse.data.txHash);\n    console.log(\"Fee:\", transferResponse.data.fee.ada, \"ADA\");\n  } catch (error) {\n    console.error(\"Error:\", error.response?.data || error.message);\n  }\n}\n\ngetBalanceAndTransfer();\n```\n\n### Example 4: Using Cache for Performance\n\n```typescript\nimport { FireblocksCardanoRawSDK } from \"cardano-raw-sdk\";\nimport { Networks, SupportedAssets } from \"cardano-raw-sdk/types\";\nimport { BasePath } from \"@fireblocks/ts-sdk\";\n\nasync function demonstrateCaching() {\n  const sdk = await FireblocksCardanoRawSDK.createInstance({\n    fireblocksConfig: {\n      apiKey: process.env.FIREBLOCKS_API_KEY!,\n      secretKey: process.env.FIREBLOCKS_SECRET_KEY!,\n      basePath: BasePath.US,\n    },\n    vaultAccountId: \"vault-123\",\n    network: Networks.MAINNET,\n    iagonApiKey: process.env.IAGON_API_KEY!,\n  });\n\n  // Check cache statistics\n  const stats = sdk.getCacheStats();\n  console.log(`Cache stats: ${stats.addressCount} addresses, ${stats.publicKeyCount} public keys`);\n\n  // Multiple operations benefit from caching\n  const balance1 = await sdk.getBalanceByAddress({ index: 0 });\n  const balance2 = await sdk.getBalanceByAddress({ index: 0 });\n  // Second balance check uses cached address - no Fireblocks API call!\n\n  // Clear cache if needed\n  sdk.clearCache();\n\n  await sdk.shutdown();\n}\n\ndemonstrateCaching();\n```\n\n### Example 5: Transfer Native ADA\n\n```typescript\nimport { FireblocksCardanoRawSDK } from \"cardano-raw-sdk\";\nimport { Networks } from \"cardano-raw-sdk/types\";\nimport { BasePath } from \"@fireblocks/ts-sdk\";\n\nasync function transferAda() {\n  const sdk = await FireblocksCardanoRawSDK.createInstance({\n    fireblocksConfig: {\n      apiKey: process.env.FIREBLOCKS_API_KEY!,\n      secretKey: process.env.FIREBLOCKS_SECRET_KEY!,\n      basePath: BasePath.US,\n    },\n    vaultAccountId: \"vault-123\",\n    network: Networks.MAINNET,\n    iagonApiKey: process.env.IAGON_API_KEY!,\n  });\n\n  try {\n    // Estimate fee first\n    const feeEstimate = await sdk.estimateAdaTransactionFee({\n      index: 0,\n      recipientAddress: \"addr1qxy...\",\n      adaAmount: 5000000, // 5 ADA\n    });\n    console.log(\"Estimated Fee:\", feeEstimate.fee.ada, \"ADA\");\n\n    // Execute transfer\n    const result = await sdk.transferAda({\n      index: 0,\n      recipientAddress: \"addr1qxy...\",\n      adaAmount: 5000000,\n    });\n\n    console.log(\"ADA Transfer successful!\");\n    console.log(\"Transaction Hash:\", result.txHash);\n    console.log(\"Actual Fee:\", result.fee.ada, \"ADA\");\n  } catch (error) {\n    console.error(\"Transfer failed:\", error);\n  } finally {\n    await sdk.shutdown();\n  }\n}\n\ntransferAda();\n```\n\n### Example 6: Multi-Token Transfer\n\n```typescript\nimport { FireblocksCardanoRawSDK } from \"cardano-raw-sdk\";\nimport { Networks } from \"cardano-raw-sdk/types\";\nimport { BasePath } from \"@fireblocks/ts-sdk\";\n\nasync function transferMultipleTokens() {\n  const sdk = await FireblocksCardanoRawSDK.createInstance({\n    fireblocksConfig: {\n      apiKey: process.env.FIREBLOCKS_API_KEY!,\n      secretKey: process.env.FIREBLOCKS_SECRET_KEY!,\n      basePath: BasePath.US,\n    },\n    vaultAccountId: \"vault-123\",\n    network: Networks.MAINNET,\n    iagonApiKey: process.env.IAGON_API_KEY!,\n  });\n\n  try {\n    const result = await sdk.transferMultipleTokens({\n      index: 0,\n      recipientAddress: \"addr1qxy...\",\n      tokens: [\n        {\n          policyId: \"f0ff48bbb7bbe9d5...\",\n          assetName: \"4e4654\",\n          amount: 1000000,\n        },\n        {\n          policyId: \"a1b2c3d4e5f6...\",\n          assetName: \"544f4b454e\",\n          amount: 500000,\n        },\n      ],\n      includeAda: true,\n      adaAmount: 2000000, // Also send 2 ADA\n    });\n\n    console.log(\"Multi-token transfer successful!\");\n    console.log(\"Transaction Hash:\", result.txHash);\n    console.log(\"Fee:\", result.fee.ada, \"ADA\");\n  } catch (error) {\n    console.error(\"Transfer failed:\", error);\n  } finally {\n    await sdk.shutdown();\n  }\n}\n\ntransferMultipleTokens();\n```\n\n### Example 7: UTxO Consolidation\n\n```typescript\nimport { FireblocksCardanoRawSDK } from \"cardano-raw-sdk\";\nimport { Networks } from \"cardano-raw-sdk/types\";\nimport { BasePath } from \"@fireblocks/ts-sdk\";\n\nasync function consolidateUtxos() {\n  const sdk = await FireblocksCardanoRawSDK.createInstance({\n    fireblocksConfig: {\n      apiKey: process.env.FIREBLOCKS_API_KEY!,\n      secretKey: process.env.FIREBLOCKS_SECRET_KEY!,\n      basePath: BasePath.US,\n    },\n    vaultAccountId: \"vault-123\",\n    network: Networks.MAINNET,\n    iagonApiKey: process.env.IAGON_API_KEY!,\n  });\n\n  try {\n    const result = await sdk.consolidateUtxos({\n      index: 0,\n      // targetAddress: \"addr1qxy...\" // Optional: defaults to source address\n    });\n\n    console.log(\"UTxO consolidation successful!\");\n    console.log(\"Transaction Hash:\", result.txHash);\n    console.log(\"Consolidated\", result.inputCount, \"UTxOs\");\n    console.log(\"Fee:\", result.fee.ada, \"ADA\");\n  } catch (error) {\n    console.error(\"Consolidation failed:\", error);\n  } finally {\n    await sdk.shutdown();\n  }\n}\n\nconsolidateUtxos();\n```\n\n### Example 8: Governance Operations\n\n```typescript\nimport { FireblocksCardanoRawSDK } from \"cardano-raw-sdk\";\nimport { Networks } from \"cardano-raw-sdk/types\";\nimport { BasePath } from \"@fireblocks/ts-sdk\";\n\nasync function participateInGovernance() {\n  const sdk = await FireblocksCardanoRawSDK.createInstance({\n    fireblocksConfig: {\n      apiKey: process.env.FIREBLOCKS_API_KEY!,\n      secretKey: process.env.FIREBLOCKS_SECRET_KEY!,\n      basePath: BasePath.US,\n    },\n    vaultAccountId: \"vault-123\",\n    network: Networks.MAINNET,\n    iagonApiKey: process.env.IAGON_API_KEY!,\n  });\n\n  try {\n    // Register as a DRep (requires 500 ADA deposit)\n    const drepResult = await sdk.registerAsDRep({\n      vaultAccountId: \"vault-123\",\n      index: 0,\n      anchor: {\n        url: \"https://example.com/drep-metadata.json\",\n        dataHash: \"abc123...\",\n      },\n    });\n    console.log(\"Registered as DRep:\", drepResult.drepId);\n    console.log(\"Transaction Hash:\", drepResult.txHash);\n\n    // Cast a vote on a governance action\n    const voteResult = await sdk.castGovernanceVote({\n      vaultAccountId: \"vault-123\",\n      index: 0,\n      governanceActionTxHash: \"abc123...\",\n      governanceActionIndex: 0,\n      vote: \"yes\", // or \"no\" or \"abstain\"\n    });\n    console.log(\"Vote cast! TX Hash:\", voteResult.txHash);\n\n    // Delegate voting power to another DRep\n    const delegateResult = await sdk.delegateToDRep({\n      vaultAccountId: \"vault-123\",\n      index: 0,\n      drepId: \"drep1...\",\n    });\n    console.log(\"Delegated to DRep! TX Hash:\", delegateResult.txHash);\n  } catch (error) {\n    console.error(\"Governance operation failed:\", error);\n  } finally {\n    await sdk.shutdown();\n  }\n}\n\nparticipateInGovernance();\n```\n\n## Development\n\n### Setup Development Environment\n\n```bash\n# Install dependencies\nnpm install\n\n# Build the project\nnpm run build\n\n# Run in development mode with hot reload\nnpm run dev\n\n# Generate documentation\nnpm run docs\n```\n\n### Project Structure\n\n```\ncardano-raw-sdk/\n├── src/\n│   ├── FireblocksCardanoRawSDK.ts       # Main SDK class\n│   ├── pool/\n│   │   └── sdkManager.ts         # Connection pooling manager\n│   ├── services/\n│   │   ├── fireblocks.service.ts # Fireblocks integration\n│   │   └── iagon.api.service.ts  # Iagon API client\n│   ├── api/\n│   │   ├── router.ts             # Express routes\n│   │   └── controllers/\n│   │       └── controller.ts     # API controllers\n│   ├── types/                    # TypeScript type definitions\n│   ├── utils/                    # Utility functions\n│   └── server.ts                 # Express server setup\n├── docs/                         # Generated documentation\n├── Dockerfile                    # Docker configuration\n├── docker-compose.yml            # Docker Compose setup\n├── package.json\n├── tsconfig.json\n└── README.md\n```\n\n### Docker Deployment\n\n#### Build Docker Image\n\n```bash\ndocker build -t cardano-raw-sdk:latest .\n```\n\n#### Run with Docker Compose\n\n```bash\n# Start services\ndocker-compose up -d\n\n# View logs\ndocker-compose logs -f\n\n# Stop services\ndocker-compose down\n\n# Restart services\ndocker-compose restart\n```\n\n#### Docker Compose Configuration\n\n```yaml\nversion: \"3.8\"\n\nservices:\n  fireblocks-sdk:\n    build: .\n    ports:\n      - \"8000:8000\"\n    environment:\n      - PORT=8000\n      - CARDANO_NETWORK=mainnet\n      - POOL_MAX_SIZE=100\n    env_file:\n      - .env\n    volumes:\n      - ./fireblocks_secret.key:/app/fireblocks_secret.key:ro\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8000/health\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n```\n\n## Advanced Features\n\n### Intelligent Caching\n\nThe SDK implements automatic caching to minimize Fireblocks API calls:\n\n- **Address Caching**: Vault account addresses are cached by index\n- **Public Key Caching**: Public keys are cached per asset/change/address combination\n- **Automatic Cache Management**: Caches are cleared on SDK shutdown\n- **Manual Cache Control**: Use `clearCache()` and `getCacheStats()` methods\n\n```typescript\n// Check cache statistics\nconst stats = sdk.getCacheStats();\nconsole.log(\"Cached addresses:\", stats.addressCount);\nconsole.log(\"Cached public keys:\", stats.publicKeyCount);\n\n// Clear cache manually if needed\nsdk.clearCache();\n```\n\n**Benefits:**\n\n- Reduces API calls to Fireblocks by up to 90%\n- Faster response times for repeated operations\n- Lower costs and improved rate limit compliance\n- Automatic per-vault-account isolation via SDK pooling\n\n### Connection Pooling\n\nThe SDK Manager implements intelligent connection pooling:\n\n- **LRU Eviction**: Automatically removes least-recently-used idle connections\n- **Automatic Cleanup**: Periodically removes idle connections\n- **Per-Vault Instances**: Each vault account gets its own SDK instance\n- **Metrics**: Track pool usage and performance\n\n### Error Handling\n\n```typescript\ntry {\n  const result = await sdk.transfer({ ... });\n} catch (error) {\n  if (error.code === 'INSUFFICIENT_BALANCE') {\n    console.error('Insufficient balance:', error.details);\n  } else if (error instanceof SdkApiError) {\n    console.error('API Error:', error.statusCode, error.message);\n  } else {\n    console.error('Unexpected error:', error);\n  }\n}\n```\n\n### Network Support\n\n- **Mainnet**: Production Cardano network (use `Networks.MAINNET`)\n- **Preprod**: Pre-production testnet (use `Networks.PREPROD`)\n- **Preview**: Preview testnet (not currently supported)\n\n### Advanced SDK Methods\n\nThe SDK provides additional methods for advanced use cases:\n\n```typescript\n// Access internal services for advanced operations\nconst fireblocksService = sdk.getFireblocksService();\nconst iagonApiService = sdk.getIagonApiService();\n\n// Cache management\nsdk.clearCache(); // Clear all cached addresses and public keys\nconst stats = sdk.getCacheStats(); // Get cache statistics\n\n// Graceful shutdown\nawait sdk.shutdown(); // Clean up resources and clear cache\n```\n\n## Troubleshooting\n\n### Common Issues\n\n1. **\"SDK factory not initialized\" error**\n   - Ensure you're passing the SDK factory function to SdkManager constructor\n   - Check that FireblocksCardanoRawSDK.createInstance is properly imported\n\n2. **\"Insufficient balance\" error**\n   - Ensure sufficient ADA for transaction fees (minimum ~1.2 ADA)\n   - Verify token balance is sufficient for the transfer amount\n\n3. **Docker container fails to start**\n   - Check that the secret key path is correct and file is readable\n   - Verify all required environment variables are set\n   - Check Docker logs: `docker-compose logs -f`\n\n## Security Considerations\n\n- ⚠️ Never commit `.env` files or secret keys to version control\n- ⚠️ Store Fireblocks secret keys in secure locations with restricted permissions\n- ⚠️ Enable Fireblocks transaction approval policies for production\n\n## License\n\n[MIT License](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffireblocks%2Fcardano-raw-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffireblocks%2Fcardano-raw-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffireblocks%2Fcardano-raw-sdk/lists"}