node-red-contrib-bdk 0.0.1

Node-RED nodes for Bitcoin Development Kit (BDK) integration with wallet configuration nodes

npm install node-red-contrib-bdk

node-red-contrib-bdk

Node-RED nodes for Bitcoin Development Kit (BDK) integration.

Installation

npm install node-red-contrib-bdk

Configuration

Wallet Configuration Nodes

This package uses Wallet Configuration Nodes (similar to the Twitter node pattern) to manage wallet settings. Create wallet configuration nodes once and reuse them across multiple nodes.

Creating a Wallet Configuration

  1. Add a BDK Wallet configuration node to your flow
  2. Configure the wallet settings:
    • Name: A friendly name for this wallet configuration
    • Network: Select mainnet, testnet, signet, or regtest
    • Bitcoin Descriptor: Optional watch-only wallet descriptor
    • Account Index: BIP44 account index (default: 0)
    • Mnemonic: Optional BIP39 mnemonic phrase (stored securely in credentials)
    • Client Type: Choose esplora (HTTP - recommended) or electrum (TCP)
    • Server Provider: Choose blockstream or mempool.space
    • Electrum URL: Optional Electrum server URL (only used when Client Type is electrum)
    • Stop Gap: Number of consecutive unused addresses before stopping scan (default: 10)

Note: Either descriptor or mnemonic must be provided. If both are provided, descriptor takes precedence. If only mnemonic is provided, the descriptor will be automatically generated.

Using Wallet Configurations in Nodes

All BDK nodes allow you to select a wallet configuration:

  1. Open any BDK node (e.g., Generate Address, Sync, Get Balance)
  2. In the node configuration, select the wallet from the Wallet dropdown
  3. The node will use that wallet's configuration

Important: Wallet instances are cached, so sync state (transactions, balance, UTXOs) persists across all nodes using the same wallet configuration.

Optional: Global Defaults (settings.js)

You can optionally set global defaults in Node-RED's settings.js file. These defaults are used as fallbacks when creating wallet configurations:

module.exports = {
  // ... other Node-RED settings ...
  
  bdk: {
    networkType: 'testnet',        // Default network
    clientType: 'esplora',         // Default client type
    electrumUrl: '',               // Default Electrum URL
    stopGap: 10                    // Default stop gap
  }
};

Note: These are only defaults. Each wallet configuration node can override these values.

Nodes

All nodes require selecting a wallet configuration node:

Core Wallet Operations

  • bdk-wallet: Wallet configuration node (create this first)
  • bdk-generate-address: Generate a new Bitcoin address for the wallet
  • bdk-get-balance: Get the current wallet balance
  • bdk-get-descriptor: Get the wallet descriptor
  • bdk-sync: Synchronize wallet with blockchain
  • bdk-list-transactions: List all transactions in the wallet
  • bdk-get-utxos: Get all unspent transaction outputs (UTXOs)

Transaction Operations

  • bdk-create-transaction: Create an unsigned PSBT (Partially Signed Bitcoin Transaction)
  • bdk-sign-psbt: Sign a PSBT using the mnemonic from the wallet configuration
  • bdk-finalize-psbt: Finalize a signed PSBT into a broadcastable transaction
  • bdk-decode-psbt: Decode a PSBT and return detailed information
  • bdk-broadcast: Broadcast a finalized transaction to the Bitcoin network

Usage Examples

Basic Flow: Generate Address and Check Balance

  1. Create a BDK Wallet configuration node:

    • Set Network to testnet
    • Enter your mnemonic (or descriptor)
    • Name it "My Test Wallet"
  2. Add a Generate Address node:

    • Select "My Test Wallet" from the Wallet dropdown
    • Configure address index and chain (external/internal)
  3. Add a Get Balance node:

    • Select the same "My Test Wallet" from the Wallet dropdown
    • Connect it to receive messages
  4. Add a Sync node:

    • Select "My Test Wallet" from the Wallet dropdown
    • This will sync the wallet with the blockchain before checking balance

Transaction Flow: Create, Sign, and Broadcast

  1. Create a BDK Wallet configuration node with a mnemonic (required for signing)

  2. Create Transaction node:

    • Select your wallet
    • Input: msg.payload.recipient (address) and msg.payload.amount (in satoshis)
  3. Sign PSBT node:

    • Select the same wallet (must have mnemonic configured)
    • Input: msg.payload.psbt from Create Transaction node
  4. Finalize PSBT node:

    • Select the same wallet
    • Input: msg.payload.psbt from Sign PSBT node
  5. Broadcast node:

    • Select the same wallet
    • Input: msg.payload.hex or msg.payload.psbt from Finalize PSBT node

Input/Output Format

Generate Address

Input: Any message (address index and chain can be overridden via msg.payload.index and msg.payload.chain)

Output:

{
  address: "bc1...",
  index: 0,
  chain: "external",
  scriptPubkey: "..."
}

Get Balance

Input: Any message

Output:

{
  total: "1000000",        // Total balance in satoshis (string)
  spendable: "1000000",    // Spendable balance (currently same as total)
  unconfirmed: "0",        // Unconfirmed balance (currently not calculated)
  confirmed: "1000000",    // Confirmed balance (currently same as total)
  balanceString: "1000000 sats"
}

Note: Balance is calculated from UTXOs using wallet.list_unspent(). Confirmed/unconfirmed distinction is not yet implemented - all UTXOs are currently counted as confirmed.

Sync

Input: Any message

Output:

{
  synced: true,
  transactions: 5,        // Number of transactions found
  balance: "1000000"      // Total balance in satoshis (string)
}

Note: Sync uses wallet.start_full_scan() and EsploraClient.full_scan() to synchronize the wallet with the blockchain. The stopGap parameter (default: 10) determines how many consecutive unused addresses to scan before stopping. Balance is calculated from UTXOs after syncing.

List Transactions

Input: Any message

Output:

{
  transactions: [
    {
      txid: "...",
      received: 1000000,  // bigint or number
      sent: 500000,      // bigint or number
      fee: "1000",       // string or null
      confirmationTime: {
        height: 123456,
        timestamp: 1234567890
      } // null if unconfirmed
    }
  ],
  count: 1
}

Note: Transactions are retrieved using wallet.listTransactions(false). The confirmationTime field will be null for unconfirmed transactions. To check if a transaction is confirmed, verify that confirmationTime is not null.

Get UTXOs

Input: Any message

Output:

{
  utxos: [
    {
      outpoint: "txid:vout",
      txid: "...",
      vout: 0,
      value: "1000000",        // Value in satoshis (string)
      scriptPubkey: "...",     // Hex-encoded script pubkey
      confirmationTime: null  // Not available directly on UTXO
    }
  ],
  count: 1
}

Note: UTXOs are retrieved using wallet.list_unspent(). Confirmation status is not available directly on the UTXO object. To check if a UTXO is confirmed, use the transaction ID (txid) with the List Transactions node to get the transaction's confirmation status.

Create Transaction

Input:

{
  recipient: "bc1...",  // or address
  amount: "1000000",     // in satoshis
  feeRate: 1.0          // optional, sat/vB (default: 1.0)
}

Output:

{
  psbt: "cHNidP8...",
  message: "PSBT created. Use sign-psbt action to sign it."
}

Sign PSBT

Input:

{
  psbt: "cHNidP8..."  // or psbtString
}

Output:

{
  psbt: "cHNidP8...",
  signed: true,
  message: "PSBT signed. Use finalize-psbt and broadcast actions to complete."
}

Finalize PSBT

Input:

{
  psbt: "cHNidP8..."  // or psbtString
}

Output:

{
  txid: "...",
  hex: "01000000...",
  psbt: "cHNidP8...",
  finalized: true
}

Broadcast

Input:

{
  hex: "01000000...",     // or transaction
  psbt: "cHNidP8..."      // or psbtString (will be finalized if hex not provided)
}

Output:

{
  txid: "...",
  broadcast: true
}

Network Configuration

Testnet (Default)

  • Network: testnet
  • Esplora URL: https://blockstream.info/testnet/api
  • Use for testing and development

Mainnet

  • Network: mainnet
  • Esplora URL: https://blockstream.info/api
  • Use for production with real funds

Signet

  • Network: signet
  • Esplora URL: https://mempool.space/signet/api
  • Use for testing with a controlled network

Regtest

  • Network: regtest
  • URL: http://localhost:3000/api
  • Use for local development with a local Bitcoin node

Security Notes

  1. Mnemonic Storage: Mnemonics are stored securely in Node-RED's credential system and are never exposed in flow files.

  2. Multiple Wallets: You can create multiple wallet configuration nodes for different wallets or networks. Each wallet maintains its own cached state.

  3. Wallet State Persistence: Wallet instances are cached, so sync state (transactions, balance, UTXOs) persists across all nodes using the same wallet configuration. This means:

    • Sync once, use balance/transactions in multiple nodes
    • State is shared across nodes using the same wallet config
    • State persists until Node-RED restarts or wallet config is updated
  4. Never Commit Secrets: Never commit wallet configurations with real mnemonics to version control. Use Node-RED's credential system (which stores credentials separately from flow files).

Troubleshooting

"BDK Wallet configuration not selected"

  • Make sure you've created a BDK Wallet configuration node
  • Select the wallet in the node's configuration dialog

"Sync failed: endpoint not found" or "Sync failed: fetch failed"

  • Check that the Esplora server is accessible
  • Verify the network type matches the URL (testnet vs signet vs mainnet)
  • Ensure the wallet descriptor/mnemonic is valid
  • In standalone Node.js environments, WASM fetch may have limitations - sync works best in Node-RED environment

"Mnemonic required to sign PSBT"

  • Make sure the selected wallet configuration has a mnemonic set
  • Mnemonics are stored in credentials, so check the wallet config node's credentials

Wallet state not updating

  • Run the Sync node to update wallet state
  • Wallet state is cached per wallet configuration
  • Multiple nodes using the same wallet config share the same state

Transactions always showing as unconfirmed

  • Make sure you've run the Sync node to update wallet state
  • Confirmation status is determined by the confirmationTime field in transaction objects
  • If confirmationTime is null, the transaction is unconfirmed
  • Check that the Esplora server is properly synced with the blockchain
  • Transactions use wallet.listTransactions(false) which returns transactions with confirmationTime populated for confirmed transactions

"Cannot find module '@bitcoindevkit/bdk-wallet-node'"

  • Run npm install in the package directory
  • If using Node-RED, also install in Node-RED's global node_modules: cd ~/.node-red && npm install @bitcoindevkit/bdk-wallet-node

Transactions always showing as unconfirmed

  • Make sure you've run the Sync node to update wallet state
  • Confirmation status is determined by confirmationTime field in transaction objects
  • If confirmationTime is null, the transaction is unconfirmed
  • Check that the Esplora server is properly synced with the blockchain

"Cannot find module '@bitcoindevkit/bdk-wallet-node'"

  • Run npm install in the package directory
  • If using Node-RED, also install in Node-RED's global node_modules: cd ~/.node-red && npm install @bitcoindevkit/bdk-wallet-node

License

See LICENSE file for details.

Node Info

Version: 0.0.1
Updated 3 days ago
Rating: not yet rated

Categories

Actions

Rate:

Downloads

80 in the last week

Nodes

  • bdk-wallet
  • bdk-generate-address
  • bdk-get-balance
  • bdk-sync
  • bdk-list-transactions
  • bdk-get-utxos
  • bdk-create-transaction
  • bdk-sign-psbt
  • bdk-finalize-psbt
  • bdk-decode-psbt
  • bdk-broadcast
  • bdk-get-descriptor

Keywords

  • node-red
  • bitcoin
  • bdk
  • wallet

Maintainers