This guide covers Node.js server applications. For mobile, see the React Native guide. For browser applications, see the Web guide.
@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.
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-nodejsbinding - An ES module project (
"type": "module"inpackage.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
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:
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 withunlock():
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.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.
@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-standardtransfer() method recognizes an RGB invoice, decodes it, and builds the native send request for a fungible amount:
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
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. Onmainnet, 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.
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.