Skip to main content
This guide covers Node.js server applications. For mobile, see the React Native guide. For browser applications, see the Web guide.
This guide uses @utexo/wdk-rgb-lightning, the current Node.js / Bare module for RGB and RGB-over-Lightning. It runs an rgb-lightning-node (LDK + rgb-lib) node in-process behind WDK’s wallet-manager/account contract. The mnemonic stays in the WDK secret manager; channel-state cryptography runs in-process through a VLS signer.
@utexo/wdk-rgb-lightning is a pre-1.0 beta. This guide was checked against 0.2.0-beta.5 with @utexo/rgb-lightning-node-nodejs 0.2.0-beta.5 (RLN v0.17.0-beta.3). 0.2.0-beta.5 requires the native binding at exactly the same version. APIs may change between releases — check the installed package’s index.d.ts before upgrading.
The archived @utexo/rgb-sdk package (UTEXOWallet, initialize(), send()) is no longer used for new Node.js integrations. Do not mix its method names into WDK code.

Prerequisites

  • Node.js 18 or later, on a platform supported by the prebuilt @utexo/rgb-lightning-node-nodejs binding
  • An ES module project ("type": "module" in package.json), since the package ships as pure ESM
  • Signet BTC for transaction fees, from a public signet faucet
  • A separately initialized sender wallet that already holds the RGB asset for an end-to-end transfer
  • Secure server-side storage for the mnemonic and a persistent, access-controlled data directory
This guide uses the public Bitcoin signet, the network of the Mint staging environment. Never use mainnet keys or real funds while following this guide.

Step 1: Install the SDK

@utexo/rgb-lightning-node-nodejs is the native binding for Node.js. It is an optional peer dependency, so install it explicitly. Its postinstall downloads a prebuilt native artifact; no Rust toolchain is required. On Node.js, import '@utexo/wdk-rgb-lightning' resolves to the Node entry point and wires this binding automatically. For Bare / React Native worklets, install @utexo/rgb-lightning-node-bare instead.

Step 2: Generate a Seed Phrase

WalletManagerRgbLightning extends WDK’s WalletManager, so the standard seed helpers are available:
Store the mnemonic securely. Do not log it in production or commit it to source control. Re-using the same mnemonic and dataDir reproduces the same Lightning node identity across restarts.

Step 3: Create the Wallet and Unlock the Node

Construct the manager with the seed and config, get the single account, then bring the node online with unlock():
network and dataDir are required at construction. unlock() takes the node’s chain backend in ldk_chain_sync (TransactionSync with an Esplora or Electrum indexer, or BlockSync with bitcoind RPC), the RGB indexer_url, and the RGB transport proxy_endpoint. Sender and receiver must use the same network and an RGB proxy that both can reach. Failures throw a typed UnlockError.
To receive USDT on Bitcoin (BFA asset schema) minted by the Utexo Mint, also pass eth_rpc_url: an Ethereum JSON-RPC endpoint for the chain with the bridge contract (Arbitrum One for the Mint). The node uses it to validate the bridge events behind the asset. Without it the node keeps its non-BFA behavior.
Give every wallet its own dataDir. rgb-lib takes an exclusive lock on a wallet directory, and the sender and receiver in this guide are separate nodes. A mnemonic is necessary for key recovery, but it does not replace a backup of the RGB and channel state in dataDir — see VSS backup in the reference.

Step 4: Fund the Wallet

getAddress() throws AccountLockedError before unlock(). It returns a stable address; call rotateAddress() when you need a new one. Send signet BTC to this address and wait for confirmation before creating RGB UTXOs. Signet blocks arrive about every 10 minutes.

Step 5: Create RGB UTXOs

RGB allocations live on dedicated (“colored”) UTXOs. createUtxos() takes RLN’s native request:

Step 6: Resolve the Asset From the Sender

listAssets() forwards RLN’s response, grouped by schema, with the snake_case asset_id field. USDT on Bitcoin from the Utexo Mint uses the BFA schema, so it is in the bfa array. Other test assets are in nia, cfa, ifa, or uda.
A new receiver wallet will not list an asset it has never received. Resolve the ID and precision from the funded sender or an authoritative asset registry. For issuing assets, use @utexo/wdk-wallet-rgb.

Step 7: Create a Receive Invoice

Run this on the receiver wallet created above. min_confirmations and witness are required; witness: false creates a blinded invoice.
assignment_amount is an integer in asset base units. One displayed unit equals 10 ** precision base units; it is not always equal to 1.

Step 8: Send From the Funded Wallet

The WDK-standard transfer() method recognizes an RGB invoice, decodes it, and builds the native send request for a fungible amount:
For RGB invoices, hash is the anchoring Bitcoin txid. transfer() also routes BOLT11 invoices, Lightning node pubkeys, and BTC addresses. For non-fungible, multi-recipient, or witness sends, call sendRgbAsset() with a full recipient_groups request built from decodeRgbInvoice() — see the reference. The sender must be a separately created and unlocked WalletAccountRgbLightning with its own dataDir, sufficient signet BTC, and a spendable asset balance.

Step 9: Refresh and Verify

A transfer can remain pending while its consignment is delivered and its Bitcoin anchor reaches the required confirmation count. Use listTransfers(assetId) to inspect its status.

Step 10: Shut Down

manager.dispose() shuts down the native node and wipes retained seed material. Call it on every manager before the process exits.

Lightning Payments

The same account exposes channels and BOLT11 payments on signet, testnet and regtest. On mainnet, Lightning methods throw LightningDisabledError (code: 'LIGHTNING_DISABLED_ON_MAINNET') before any network call; on-chain RGB methods keep working. A payment needs a connected peer and an open channel with enough liquidity — unlocking the node does not create either.
For RGB-over-Lightning, pass asset_id / asset_amount when opening the channel and creating the invoice. RGB-routed HTLCs have a minimum of 3,000,000 msat. To receive through the Utexo LSP instead of managing channels yourself, configure lspBaseUrl and use account.createLsp() — see the wdk-rgb-lightning reference.

Troubleshooting

Implementation References

Next Steps