{"id":51654684,"url":"https://github.com/fireblocks/stacks-fireblocks-sdk","last_synced_at":"2026-07-14T08:03:52.120Z","repository":{"id":346362365,"uuid":"1102382298","full_name":"fireblocks/stacks-fireblocks-sdk","owner":"fireblocks","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-22T09:20:22.000Z","size":402,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T11:13:27.079Z","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-11-23T11:10:11.000Z","updated_at":"2026-06-11T11:37:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/fireblocks/stacks-fireblocks-sdk","commit_stats":null,"previous_names":["fireblocks/stacks-fireblocks-sdk"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fireblocks/stacks-fireblocks-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fstacks-fireblocks-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fstacks-fireblocks-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fstacks-fireblocks-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fstacks-fireblocks-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fireblocks","download_url":"https://codeload.github.com/fireblocks/stacks-fireblocks-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fireblocks%2Fstacks-fireblocks-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:51.563Z","updated_at":"2026-07-14T08:03:52.105Z","avatar_url":"https://github.com/fireblocks.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stacks Fireblocks SDK\n\nA stateless SDK and REST API server for interacting with Fireblocks and the Stacks Network, enabling secure operations on Stacks using Fireblocks services.\n\nThe SDK Typedocs can be found here:\nhttps://fireblocks.github.io/stacks-fireblocks-sdk/\n\n---\n\n## ⚡ Project Overview\n\n**Stacks Fireblocks SDK** lets you securely execute Stacks transactions using Fireblocks vaults and raw signing.\nIt's designed to simplify integration with Fireblocks for secure Stacks transactions.\n\n### **Two Usage Modes**\n\n| Mode | Use Case | How |\n|------|----------|-----|\n| **TypeScript SDK** | Import into your Node.js application | `import { StacksSDK } from \"stacks-fireblocks-sdk\"` |\n| **REST API Server** | Dockerized service for non-TS environments | `docker-compose up` or `node dist/server.js` |\n\n### **Prerequisites**\n\n- Fireblocks workspace with raw signing enabled.\n- Fireblocks API key and secret key file.\n- Node.js v18+\n- Docker and Docker Compose (for REST API server mode).\n\n---\n\n## 🚀 Features\n\n- **Secure Stacks Transactions**: All transactions are Fireblocks-signed and submitted to Stacks.\n- **Fireblocks raw signing support**\n- **Native STX transfers**: Send STX with optional gross transactions (fee deduction from recipient)\n- **Fungible token transfers**: Support for SIP-010 token transfers (sBTC, USDC, etc.)\n- **Nonce management**: Optional nonce override on every transaction method; query confirmed on-chain nonce via `getAccountNonce()`\n- **Replace-by-fee**: Replace a stuck pending STX transaction with a higher-fee one using the same nonce\n- **Stacking functionality**:\n  - Solo stacking \n  - Pool delegation and stacking\n  - Delegation management (delegate, revoke, allow contract caller)\n  - Account status and eligibility checking\n- **Transaction monitoring**: Real-time transaction status polling with error code mapping\n- **REST API mode**: Easily integrate through HTTP requests.\n- **Vault pooling**: Efficient per-vault instance management.\n\n---\n\n## 📦 Installation\n\n### **Option 1: TypeScript SDK (for Node.js applications)**\n\nInstall the package in your project:\n\n```bash\nnpm install stacks-fireblocks-sdk\n```\n\nImport and use in your code:\n\n```typescript\nimport { StacksSDK, FireblocksConfig } from \"stacks-fireblocks-sdk\";\n\nconst config: FireblocksConfig = {\n  apiKey: process.env.FIREBLOCKS_API_KEY!,\n  apiSecret: fs.readFileSync(process.env.FIREBLOCKS_SECRET_KEY_PATH!, \"utf8\"),\n  testnet: true,\n};\n\nconst sdk = await StacksSDK.create(\"YOUR_VAULT_ID\", config);\n```\n\n\u003e **Note:** Importing the SDK does NOT start a server. The SDK is a pure library.\n\n### **Option 2: REST API Server (Docker)**\n\nFor non-TypeScript environments, run the SDK as a dockerized REST API service:\n\n```bash\ngit clone https://github.com/fireblocks/stacks-fireblocks-sdk\ncd stacks-fireblocks-sdk\ncp .env.example .env\n# Make sure your Fireblocks secret key is in ./secrets/fireblocks_secret.key\ndocker-compose up --build        # Dev Mode\ndocker-compose -f docker-compose.yml up --build  # Prod Mode\n```\n\n\u003e API will run on port `3000` by default. Change via `PORT` in `.env`.\n\n### **Option 3: Local Development**\n\n```bash\ngit clone https://github.com/fireblocks/stacks-fireblocks-sdk\ncd stacks-fireblocks-sdk\nnpm install\ncp .env.example .env\n```\n\nEdit `.env` to include your API key, private key path, and Stacks network config.\n\n```bash\nnpm run dev    # Start REST API server with hot reload\nnpm run build  # Build for production\n```\n\n---\n\n## ⚙️ Configuration\n\nEnvironment variables (via `.env`) control SDK behavior:\n\n| Variable                   | Required | Default                               | Description                             |\n| -------------------------- | -------- | ------------------------------------- | --------------------------------------- |\n| FIREBLOCKS_API_KEY         | Yes      | —                                     | Your Fireblocks API key                 |\n| FIREBLOCKS_SECRET_KEY_PATH | Yes      | —                                     | Path to your Fireblocks secret key file |\n| FIREBLOCKS_BASE_PATH       | No       | BasePath.US from \"@fireblocks/ts-sdk\" | Base URL of the Fireblocks API          |\n| NETWORK                    | No       | MAINNET                               | Stacks mainnet or testnet               |\n| PORT                       | No       | 3000                                  | Port to run the REST API server         |\n\n### Sample `.env`:\n\n```dotenv\nFIREBLOCKS_BASE_PATH=https://api.fireblocks.io/v1\nFIREBLOCKS_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\nFIREBLOCKS_SECRET_KEY_PATH=./secrets/fireblocks_secret.key\nSTACKS_NETWORK=TESTNET\nPORT=3000\n```\n\nNote: Setting STACKS_NETWORK to anything other than TESTNET (or testnet) will set the network as mainnet.\n\n\u003e 🔒 Never commit your `.env` file or secret key to source control.\n\n---\n\n## 🔑 Secret Key Setup (Docker)\n\n1. Place your Fireblocks private key at:\n\n```\n./secrets/fireblocks_secret.key\n```\n\n2. Your `.env` should reference this file **relative to the project root**:\n\n```dotenv\nFIREBLOCKS_SECRET_KEY_PATH=./secrets/fireblocks_secret.key\n```\n\n3. Docker Compose mounts this file automatically:\n\n```yaml\nvolumes:\n  - ./secrets/fireblocks_secret.key:/app/secrets/fireblocks_secret.key:ro\n```\n\n---\n\n## 📖 SDK Usage Examples\n\n### **Initialize the SDK**\n\n```typescript\nimport { StacksSDK, FireblocksConfig } from \"stacks-fireblocks-sdk\";\nimport fs from \"fs\";\n\nconst fireblocksConfig: FireblocksConfig = {\n  apiKey: process.env.FIREBLOCKS_API_KEY!,\n  apiSecret: fs.readFileSync(process.env.FIREBLOCKS_SECRET_KEY_PATH!, \"utf8\"),\n  testnet: true, // or false for mainnet\n};\n\nconst sdk = await StacksSDK.create(\"YOUR_VAULT_ID\", fireblocksConfig);\n```\n\n### **Get Account Information**\n\n```typescript\n// Get Stacks address\nconst address = sdk.getAddress();\nconsole.log(\"Stacks Address:\", address);\n\n// Get public key\nconst publicKey = sdk.getPublicKey();\nconsole.log(\"Public Key:\", publicKey);\n\n// Get BTC rewards address (for stacking)\nconst btcAddress = sdk.getBtcRewardsAddress();\nconsole.log(\"BTC Rewards Address:\", btcAddress);\n```\n\n### **Check Balance**\n\n```typescript\n// Get native STX balance\nconst balanceResponse = await sdk.getBalance();\nif (balanceResponse.success) {\n  console.log(\"STX Balance:\", balanceResponse.balance);\n}\n\n// Get fungible token balances\nconst ftBalances = await sdk.getFtBalances();\nif (ftBalances.success) {\n  ftBalances.data?.forEach((token) =\u003e {\n    console.log(`${token.token}: ${token.balance}`);\n  });\n}\n```\n\n### **Transfer STX**\n\n```typescript\n// Basic STX transfer\nconst transferResponse = await sdk.createNativeTransaction(\n  \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\", // recipient\n  10.5, // amount in STX\n  false, // grossTransaction (if true, fee is deducted from amount)\n  \"Payment for services\", // optional note\n);\n\nif (transferResponse.success) {\n  console.log(\"Transaction Hash:\", transferResponse.txHash);\n}\n\n// Gross transaction (fee deducted from recipient)\nconst grossTransfer = await sdk.createNativeTransaction(\n  \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\",\n  10.5,\n  true, // fee will be deducted from the 10.5 STX\n);\n\n// With explicit nonce and fee override\nconst transfer = await sdk.createNativeTransaction(\n  \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\",\n  10.5,\n  false,\n  undefined, // note\n  7,    // nonce override (integer)\n  0.01, // fee in STX (overrides auto-estimation)\n);\n```\n\n### **Transfer Fungible Tokens**\n\n```typescript\nimport { TokenType } from \"stacks-fireblocks-sdk\";\n\n// Transfer sBTC (built-in token)\nconst ftTransfer = await sdk.createFTTransaction(\n  \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\",\n  0.1, // amount in token units\n  TokenType.sBTC,\n);\n\nif (ftTransfer.success) {\n  console.log(\"Transaction Hash:\", ftTransfer.txHash);\n}\n\n// Transfer custom SIP-010 token\n// Note: tokenAssetName is the name from define-fungible-token (may differ from contract name)\nconst customTransfer = await sdk.createFTTransaction(\n  \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\",\n  100, // amount in token units\n  TokenType.CUSTOM,\n  \"SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9\", // contract address\n  \"my-token\", // contract name\n  \"my-token-asset\", // asset name (from define-fungible-token)\n);\n```\n\n\u003e **Finding the asset name:** For custom tokens, the `tokenAssetName` is found in the contract's source code in the `define-fungible-token` declaration. View the contract on a block explorer (e.g., explorer.hiro.so) and look for `(define-fungible-token \u003casset-name\u003e)`. This may differ from the contract name - for example, USDCx contract (`usdcx`) defines its token as `usdcx-token`.\n\n### **Check Account Status**\n\n```typescript\nconst status = await sdk.checkStatus();\n\nif (status.success) {\n  console.log(\"Balance Information:\");\n  console.log(\"  Total STX:\", status.data?.balance.stx_total);\n  console.log(\"  Locked STX:\", status.data?.balance.stx_locked);\n  console.log(\"  Unlock Height:\", status.data?.balance.burnchain_unlock_height);\n\n  console.log(\"\\nDelegation Status:\");\n  console.log(\"  Is Delegated:\", status.data?.delegation.is_delegated);\n  console.log(\"  Delegated To:\", status.data?.delegation.delegated_to);\n  console.log(\"  Amount:\", status.data?.delegation.amount_delegated);\n}\n```\n\n### **Solo Stacking**\n\nSolo stacking requires you to provide a signer key and signature. You can use any valid `secp256k1` key pair for your signer.\n\n**Generate signer signature:**\nUse the [Stacks Signature Generation Tool](https://signature.stacking.tools/) to generate your signer signature with the following parameters:\n- **Function**: \"stack-stx\"\n- **Max Amount**: Maximum STX amount to authorize, equal or more to what you'll stack\n- **Lock period**: Number of cycles (1-12)\n- **Auth ID**: Random integer for replay protection, must be the same one used to generate the signature\n- **Reward cycle**: Current reward cycle\n- **PoX address**: Your BTC rewards address\n- If you plan to run your own signer to earn full rewards, use your signer's public key here\n- If using a hosted signer service, use their public key and signature\n\n```typescript\n// Stack 150,000 STX for 6 cycles\nconst stackResponse = await sdk.stackSolo(\n  \"02778d476704afa...\", // Signer public key\n  \"1997445c32fc172f...\", // Signer signature\n  150000, // amount in STX\n  6, // lock period in cycles (1-12)\n  \"1772114443795\", // authId (same as used to generate signature)\n);\n\nif (stackResponse.success) {\n  console.log(\"Stacking Transaction Hash:\", stackResponse.txHash);\n  console.log(\"BTC rewards will be sent to:\", sdk.getBtcRewardsAddress());\n} else {\n  console.error(\"Stacking failed:\", stackResponse.error);\n}\n```\n\n### **Pool Stacking**\n\n```typescript\n// Delegate to a stacking pool\nconst delegateResponse = await sdk.delegateToPool(\n  \"SP21YTSM60CAY6D011EZVEVNKXVW8FVZE198XEFFP\", // pool address\n  \"stacking-pool-v1\", // pool contract name\n  50000, // amount to delegate\n  12, // lock period in cycles\n);\n\n// Allow a pool to lock your STX\nconst allowCallerResponse = await sdk.allowContractCaller(\n  \"SP21YTSM60CAY6D011EZVEVNKXVW8FVZE198XEFFP\",\n  \"stacking-pool-v1\",\n);\n\n// Revoke delegation\nconst revokeResponse = await sdk.revokeDelegation();\n```\n\n### **Nonce Management**\n\n```typescript\n// Returns confirmed nonce, pending tx count, and the next safe nonce to use.\n// nextAvailable is gap-aware: if pending nonces are [5, 6, 9], it returns 7\n// (the first gap) rather than 10, so your tx confirms as soon as possible.\nconst nonceResponse = await sdk.getAccountNonce();\nif (nonceResponse.success) {\n  console.log(\"Confirmed nonce:\", nonceResponse.confirmedNonce);\n  console.log(\"Pending txs:    \", nonceResponse.pendingTxCount);\n  console.log(\"Use this nonce: \", nonceResponse.nextAvailable);\n}\n```\n\nAll transaction methods (`createNativeTransaction`, `createFTTransaction`, `delegateToPool`, `allowContractCaller`, `revokeDelegation`, `stackSolo`, `increaseStackedAmount`, `extendStackingPeriod`) accept an optional `nonce?: number` parameter as their last argument. When omitted, the SDK automatically uses `nextAvailable` from `getAccountNonce()` — the same gap-aware value the nonce endpoint returns — so auto-nonce and manual nonce are always consistent.\n\n### **Replace a Stuck Transaction**\n\nIf a transaction is stuck in the mempool due to a low fee, you can replace it by submitting a new transaction with the same nonce and a higher fee. Both native STX transfers and contract calls (PoX operations, etc.) are supported.\n\n```typescript\n// Replace any pending transaction visible to the Hiro indexer.\n// The original tx is looked up automatically — same nonce, same args, higher fee.\nconst replacement = await sdk.replaceTransaction(\n  \"0xabc123...\", // original tx ID\n  0.01,          // new fee in STX (must be ≥ RBF_MIN_FEE_MULTIPLIER × original fee)\n);\n\n// For token_transfer only: optionally change recipient or amount\nconst replacement = await sdk.replaceTransaction(\n  \"0xabc123...\",\n  0.01,\n  \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\", // newRecipient\n  10.5,  // newAmount in STX\n);\n\n// Replace a future-nonce STX transfer not visible to the Hiro indexer.\n// nonceOverride bypasses the indexer lookup. Only STX transfers are supported\n// on this path since contract call args cannot be inferred.\nconst replacement = await sdk.replaceTransaction(\n  \"0xabc123...\",\n  0.01,\n  \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\", // newRecipient (required)\n  10.5,  // newAmount in STX (required)\n  7,     // nonceOverride\n);\n\nif (replacement.success) {\n  console.log(\"Replacement tx hash:\", replacement.txHash);\n}\n```\n\n\u003e The minimum fee bump is controlled by `RBF_MIN_FEE_MULTIPLIER` in `constants.ts` (default `1.25`). The fee check only applies on the lookup path where the original fee is known.\n\n### **Transaction Status Monitoring**\n\n```typescript\n// Get transaction status with error code mapping\nconst txStatus = await sdk.getTxStatusById(\"0xabcd1234...\");\n\nif (txStatus.success) {\n  console.log(\"Status:\", txStatus.data?.tx_status);\n\n  if (txStatus.data?.tx_status !== \"success\") {\n    console.log(\"Error:\", txStatus.data?.tx_error);\n    console.log(\"Error Code:\", txStatus.data?.tx_result?.repr);\n  }\n}\n```\n\n### **Transaction History**\n\n```typescript\n// Get transaction history (cached)\nconst history = await sdk.getTransactionHistory(true);\n\n// Get fresh transaction history with pagination\nconst freshHistory = await sdk.getTransactionHistory(\n  false, // don't use cache\n  50, // limit\n  0, // offset\n);\n\nhistory.forEach((tx) =\u003e {\n  console.log(`${tx.transaction_hash}: ${tx.tx_type} - ${tx.tx_status}`);\n});\n```\n\n---\n\n## 🛠️ API Reference\n\n### **Account Information Endpoints**\n\n| Method | Route                               | Description                                                                |\n| ------ | ----------------------------------- | -------------------------------------------------------------------------- |\n| GET    | `/api/:vaultId/address`             | Fetch the Stacks address associated with the given vault                   |\n| GET    | `/api/:vaultId/publicKey`           | Retrieve the public key for the vault account                              |\n| GET    | `/api/:vaultId/btc-rewards-address` | Get the BTC rewards address associated with the given vault (for stacking) |\n| GET    | `/api/:vaultId/nonce`               | Get confirmed nonce, pending tx count, and next available nonce (gap-aware) |\n\n### **Balance Endpoints**\n\n| Method | Route                       | Description                                   |\n| ------ | --------------------------- | --------------------------------------------- |\n| GET    | `/api/:vaultId/balance`     | Get the native STX balance                    |\n| GET    | `/api/:vaultId/ft-balances` | Get all fungible token balances for the vault |\n\n### **Transaction Endpoints**\n\n| Method | Route                                   | Description                                                                  |\n| ------ | --------------------------------------- | ---------------------------------------------------------------------------- |\n| GET    | `/api/:vaultId/transactions`            | List recent transactions for this vault                                      |\n| GET    | `/api/transactions/:txId`               | Get detailed transaction status with error code mapping                      |\n| POST   | `/api/:vaultId/transfer`                | Transfer STX or Fungible Tokens to another address                           |\n| POST   | `/api/:vaultId/replace-transaction`     | Replace a stuck pending STX transaction with a higher-fee one (same nonce)   |\n\n`/transfer` accepts optional `nonce` (integer) and `fee` (STX, for STX transfers only) body fields to override the auto-estimated values.\n\n`/replace-transaction` body fields:\n\n| Field           | Type    | Required | Description                                                                  |\n| --------------- | ------- | -------- | ---------------------------------------------------------------------------- |\n| `originalTxId`  | string  | Yes      | Transaction ID of the pending transaction to replace                         |\n| `newFee`        | number  | Yes      | New fee in STX — must be higher than the original                            |\n| `newRecipient`  | string  | No       | New recipient address. Defaults to the original recipient                    |\n| `newAmount`     | number  | No       | New transfer amount in STX. Defaults to the original amount                  |\n| `nonceOverride` | integer | No       | Nonce to use directly, bypassing the Hiro indexer lookup. Required when the original tx is a future-nonce tx not visible in the explorer. When set, `newRecipient` and `newAmount` are also required. |\n\n### **Stacking Endpoints**\n\n| Method | Route                                               | Description                                          |\n| ------ | --------------------------------------------------- | ---------------------------------------------------- |\n| GET    | `/api/:vaultId/check-status`                        | Check account stacking status and delegation info    |\n| GET    | `/api/poxInfo`                                      | Fetch current PoX info from blockchain               |\n| POST   | `/api/:vaultId/stacking/solo`                       | Solo stack STX                                       |\n| POST   | `/api/:vaultId/stacking/solo/increase`              | Increase the STX amount of an existing solo position |\n| POST   | `/api/:vaultId/stacking/solo/extend`                | Extend the lock period of an existing solo position  |\n| POST   | `/api/:vaultId/stacking/pool/delegate`              | Delegate amount of STX to a stacking pool            |\n| POST   | `/api/:vaultId/stacking/pool/allow-contract-caller` | Allow a pool contract to lock your STX               |\n| POST   | `/api/:vaultId/revoke-delegation`                   | Revoke any active STX delegation                     |\n\n### **Utility Endpoints**\n\n| Method | Route          | Description                           |\n| ------ | -------------- | ------------------------------------- |\n| GET    | `/api/metrics` | Prometheus-compatible service metrics |\n\n---\n\n- **\\* IMPORTANT NOTE \\*\\***: Transactions could sometimes pass at blockchain level but fail at smart contract level,\n  in this case a {success: true, txid: \u003cVALID-TX-ID\u003e} 200 response will be returned to user, please double check\n  the success of the transaction by polling the txid status with the `/api/:vaultId/transactions/:txId` endpoint.\n\n## 🎯 Stacking Guide\n\n### **Solo Stacking Requirements**\n\n1. **Minimum Amount**: Must meet the dynamic minimum threshold (request will fail otherwise)\n2. **Lock Period**: 1-12 reward cycles (each cycle ≈ 2 weeks)\n3. **No Active Delegation**: Account must not be delegated to an address\n4. **Timing**: Submit during reward phase (with more than 10 blocks away from prepare phase)\n\n### **Reward Cycle Timeline**\n\n- Each cycle is approximately 2,100 Bitcoin blocks (~2 weeks)\n- **Reward Phase**: ~2,000 blocks - safe to submit stacking requests\n- **Prepare Phase**: ~100 blocks - risky window before next cycle\n- SDK automatically checks timing safety before stacking\n\n### **Bitcoin Rewards**\n\n- Rewards are paid directly to your BTC address each cycle\n- Amount: `Expected ≈(Your STX / Total Stacked) × Total BTC from Miners`\n\n### **Pool Stacking vs Solo Stacking**\n\n**Pool Stacking:**\n\n- ✅ Lower minimum (pool operators set their own minimum)\n- ✅ No signer infrastructure required\n- ✅ Pool handles all technical operations\n- ❌ Pool takes a commission\n- ❌ Less control over reward address\n\n- Note: For pool stacking, delegate the amount you want to stack to the pool and allow the pool contract as contract-caller to lock your STX,\n  the pool will handle the rest and lock STX when ready and distirbute rewards at the end of locking period.\n\n**Solo Stacking:**\n\n- ✅ Keep all rewards (no commission)\n- ✅ Full control over reward address\n- ✅ Higher rewards for large holders\n- ❌ Must meet higher minimum threshold (typically 90,000+ STX)\n\n---\n\n## 📊 REST API Examples (cURL)\n\n### **Get Account Address**\n\n```bash\ncurl -X 'GET' \\\n  'http://localhost:3000/api/123/address' \\\n  -H 'accept: application/json'\n```\n\n### **Check Balance**\n\n```bash\ncurl -X 'GET' \\\n  'http://localhost:3000/api/123/balance' \\\n  -H 'accept: application/json'\n```\n\n### **Transfer STX**\n\n```bash\ncurl -X 'POST' \\\n  'http://localhost:3000/api/123/transfer' \\\n  -H 'accept: application/json' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n  \"recipientAddress\": \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\",\n  \"amount\": 100.5,\n  \"assetType\": \"STX\",\n  \"grossTransaction\": false,\n  \"note\": \"Payment for services\"\n}'\n```\n\n### **Transfer Custom SIP-010 Token**\n\n```bash\ncurl -X 'POST' \\\n  'http://localhost:3000/api/123/transfer' \\\n  -H 'accept: application/json' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n  \"recipientAddress\": \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\",\n  \"amount\": 100,\n  \"assetType\": \"Custom\",\n  \"tokenContractAddress\": \"SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9\",\n  \"tokenContractName\": \"my-token\",\n  \"tokenAssetName\": \"my-token-asset\"\n}'\n```\n\n\u003e **Note:** `tokenAssetName` is the name from the contract's `define-fungible-token` declaration, which may differ from `tokenContractName`.\n\n### **Get Account Nonce**\n\n```bash\ncurl http://localhost:3000/api/123/nonce\n# → {\n#     \"success\": true,\n#     \"confirmedNonce\": 5,\n#     \"pendingTxCount\": 2,\n#     \"nextAvailable\": 7\n#   }\n```\n\n### **Transfer STX with Nonce Override**\n\n```bash\ncurl -X POST http://localhost:3000/api/123/transfer \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"recipientAddress\": \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\",\n    \"amount\": 10.5,\n    \"assetType\": \"STX\",\n    \"nonce\": 7,\n    \"fee\": 0.01\n  }'\n```\n\n### **Replace a Stuck Transaction**\n\n```bash\ncurl -X POST http://localhost:3000/api/123/replace-transaction \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"originalTxId\": \"0xabc123...\",\n    \"newFee\": 0.01\n  }'\n```\n\nFor a future-nonce transaction not visible in the explorer, provide `nonceOverride` with the exact nonce, plus `newRecipient` and `newAmount`:\n\n```bash\ncurl -X POST http://localhost:3000/api/123/replace-transaction \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"originalTxId\": \"0xabc123...\",\n    \"newFee\": 0.01,\n    \"newRecipient\": \"ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG\",\n    \"newAmount\": 10.5,\n    \"nonceOverride\": 7\n  }'\n```\n\n### **Solo Stack STX**\n```bash\ncurl -X 'POST' \\\n  'http://localhost:3000/api/123/stacking/solo' \\\n  -H 'accept: application/json' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n  \"signerKey\": \"02778d476704afa540ac01438f62c371dc387\",\n  \"signerSig65Hex\": \"1997445c32fc1720b202995f656396b50c355\",\n  \"amount\": 6520000,\n  \"lockPeriod\": 1,\n  \"authId\": \"1\"\n}'\n```\n\n### **Check Stacking Status**\n\n```bash\ncurl -X 'GET' \\\n  'http://localhost:3000/api/123/status' \\\n  -H 'accept: application/json'\n```\n\n### **Get Transaction Status**\n\n```bash\ncurl -X 'GET' \\\n  'http://localhost:3000/api/123/tx/0xabcd1234...' \\\n  -H 'accept: application/json'\n```\n\n---\n\n## 📄 Development\n\n### Run locally with hot reload\n\n```bash\nnpm run dev\n```\n\n### Run tests\n\n```bash\nnpm test\n```\n\n### Build for production\n\n```bash\nnpm run build\n```\n\n---\n\n## 🔗 API Documentation\n\nSwagger UI API Documentation will be available at http://localhost:3000/api-docs after running the project.\n\n---\n\n## 🚪 Security\n\n- Never commit your `.env` or secrets.\n- Use secrets management in production.\n- Fireblocks raw signing provides secure transaction signing without exposing private keys.\n- All transactions are signed within Fireblocks secure infrastructure.\n\n---\n\n## 🌐 Network Information\n\n### Mainnet\n\n- **Network**: Stacks Mainnet\n- **API**: `https://api.hiro.so`\n- **PoX Contract**: `SP000000000000000000002Q6VF78.pox-4`\n\n### Testnet\n\n- **Network**: Stacks Testnet\n- **API**: `https://api.testnet.hiro.so`\n- **PoX Contract**: `ST000000000000000000002AMW42H.pox-4`\n\n---\n\n## 📚 Additional Resources\n\n- [Stacks Documentation](https://docs.stacks.co)\n- [Fireblocks Documentation](https://developers.fireblocks.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffireblocks%2Fstacks-fireblocks-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffireblocks%2Fstacks-fireblocks-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffireblocks%2Fstacks-fireblocks-sdk/lists"}