> ## Documentation Index
> Fetch the complete documentation index at: https://docs.utexo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js Quickstart

> Send your first USDT on Bitcoin transfer from a Node.js server application using @utexo/rgb-sdk.

<Info>
  This guide covers Node.js server-side usage. For mobile (iOS/Android) see the [React Native guide](/getting-started/quickstart/react-native), and for browser apps see the [Web guide](/getting-started/quickstart/web). For concepts shared across all guides, see the [Quickstart Overview](/getting-started/quickstart/overview).
</Info>

## Prerequisites

* **Node.js v18 or later** — [Download here](https://nodejs.org/)
* **A testnet BTC balance** for transaction fees (see [Quickstart Overview](/getting-started/quickstart/overview#common-prerequisites) for faucet links)
* **Basic familiarity with async/await JavaScript**

<Warning>
  This guide uses **testnet**. Never use mainnet keys or real funds while following this tutorial. Testnet assets have no monetary value.
</Warning>

## Step 1: Install the SDK

```bash theme={null}
npm install @utexo/rgb-sdk
```

The `@utexo/rgb-sdk` package is **Node.js only** and is not browser-compatible. It requires access to the file system and native crypto modules. For browser environments use `@utexo/rgb-sdk-web`; for iOS and Android use `@utexo/rgb-sdk-rn`.

## Step 2: Generate Wallet Keys

Start by generating a BIP-39 mnemonic. This 12-word seed phrase is the only way to recover your wallet — store it securely before proceeding.

```javascript theme={null}
const { generateKeys } = require('@utexo/rgb-sdk');

const keys = await generateKeys('testnet');
console.log('Mnemonic:', keys.mnemonic); // Store this securely — never share it
console.log('Pubkey:', keys.xpub);
```

**Back up your mnemonic immediately.** If you lose it, your wallet and any assets it holds cannot be recovered. Never commit mnemonics to source control.

## Step 3: Initialise the Wallet

Create and initialise a `UTEXOWallet` instance using your mnemonic. Initialisation connects to the default RGB transport and Bitcoin indexer endpoints for testnet.

```javascript theme={null}
const { UTEXOWallet } = require('@utexo/rgb-sdk');

const wallet = new UTEXOWallet(keys.mnemonic, {
  network: 'testnet'
});
await wallet.initialize();
console.log('Wallet initialised successfully');
```

`initialize()` performs the initial sync with the Bitcoin indexer and RGB transport layer. This may take a few seconds on first run.

## Step 4: Get a Deposit Address

Get your wallet's Bitcoin deposit address. You will use this to receive testnet BTC from a faucet — a small BTC balance is required to pay RGB transaction fees.

```javascript theme={null}
const address = await wallet.getAddress();
console.log('Deposit address:', address);
```

Send testnet BTC to this address using one of the faucets listed in the [Quickstart Overview](/getting-started/quickstart/overview#common-prerequisites). Wait for at least 1 confirmation before continuing. A few thousand satoshis is enough to cover fees for this tutorial.

## Step 5: Create UTXOs

RGB asset state must be anchored to Bitcoin UTXOs. Before you can receive any RGB asset, your wallet needs dedicated UTXOs created for this purpose.

```javascript theme={null}
// num: number of UTXOs to create
// size: size of each UTXO in satoshis
await wallet.createUtxos({ num: 5, size: 1000 });
await wallet.refreshWallet();
console.log('UTXOs created and wallet synced');
```

**Parameter reference:**

| Parameter | Type     | Description                                                                                   |
| --------- | -------- | --------------------------------------------------------------------------------------------- |
| `num`     | `number` | Number of UTXOs to create. `5` is recommended for a new wallet.                               |
| `size`    | `number` | Size of each UTXO in **satoshis**. `1000` satoshis per UTXO is the minimum recommended value. |

`refreshWallet()` syncs the wallet's local state with the Bitcoin chain. Always call it after any on-chain operation before querying balances or generating invoices.

## Step 6: Get the USDT on Bitcoin Asset ID

Before generating an invoice, you need the **asset ID** of the USDT on Bitcoin token on testnet. This ID uniquely identifies the asset contract in the RGB protocol.

```javascript theme={null}
// List known assets to find the USDT asset ID
const assets = await wallet.listAssets();
console.log('Available assets:', JSON.stringify(assets, null, 2));

// The USDT asset ID will look like:
// "rgb:2dkSTbr-jFhznbPmo-TQafzswCN-av2UEe9m2-LnFCMMG9-M9vByXo"
const usdtAssetId = assets.find(a => a.ticker === 'USDT')?.id;
console.log('USDT Asset ID:', usdtAssetId);
```

If no assets appear, your wallet may not yet have been assigned any RGB assets. You can also obtain the canonical testnet USDT asset ID from the [SDK Reference](/sdk/utexo-sdk) or by asking in the [Utexo Discord](https://discord.gg/utexo).

## Step 7: Generate an RGB Invoice (Receiver Side)

The receiver generates a blinded invoice to share with the sender. The blinded invoice hides the receiver's UTXO from the sender while still allowing the transfer to be verified client-side.

```javascript theme={null}
// Run this on the RECEIVER's wallet
const receiveData = await wallet.blindReceive({
  assetId: usdtAssetId,   // RGB asset ID from Step 6
  amount: 100,             // Amount in asset base units (1 USDT = 1 unit)
  minConfirmations: 1,     // Minimum Bitcoin confirmations before the transfer is accepted
  durationSeconds: 3600    // Invoice expiry: 3600 seconds = 1 hour
});
console.log('RGB Invoice:', receiveData.invoice);
// Share receiveData.invoice with the sender
```

**Parameter reference:**

| Parameter          | Type     | Description                                                                           |
| ------------------ | -------- | ------------------------------------------------------------------------------------- |
| `assetId`          | `string` | The RGB asset contract ID. See Step 6.                                                |
| `amount`           | `number` | Amount to receive in **asset base units**. For USDT on Bitcoin, 1 unit = 1 USDT.      |
| `minConfirmations` | `number` | Minimum Bitcoin confirmations required before accepting the transfer.                 |
| `durationSeconds`  | `number` | Invoice validity window in seconds. Invoice is rejected by the receiver after expiry. |

Invoices expire after `durationSeconds`. The sender must complete the transfer before the invoice expires, otherwise a new invoice is required.

## Step 8: Send an RGB Asset (Sender Side)

The sender uses the invoice from Step 7 to transfer the asset. The sender must already hold a balance of the RGB asset being transferred.

```javascript theme={null}
// Run this on the SENDER's wallet (must hold USDT on Bitcoin balance)
const sendResult = await wallet.send({
  invoice: receiveData.invoice, // Invoice string from Step 7
  assetId: usdtAssetId,         // Must match the asset ID in the invoice
  amount: 100                   // Must match the amount in the invoice
});
console.log('Transfer TXID:', sendResult.txid);
console.log('Transfer status:', sendResult.status);

// Sync both wallets after the transfer
await wallet.refreshWallet();        // Sender
await receiverWallet.refreshWallet(); // Receiver (run on receiver's side)
```

The `send()` call constructs the RGB state transition, attaches it to a Bitcoin transaction, and broadcasts it. The RGB transport layer (`rpcs://`) is used to communicate the state transition to the receiver.

The `amount` and `assetId` in the `send()` call must exactly match those in the invoice. Mismatches will cause the transfer to be rejected by the receiver's client-side validator.

## Step 9: Verify the Transfer

After both wallets have called `refreshWallet()`, check the balances to confirm the transfer completed successfully.

```javascript theme={null}
// Check receiver's balance
const receiverAssets = await receiverWallet.listAssets();
console.log('Receiver assets:', JSON.stringify(receiverAssets, null, 2));

// Check sender's remaining BTC balance
const senderBtcBalance = await wallet.getBtcBalance();
console.log('Sender BTC balance (satoshis):', senderBtcBalance);
```

Expected result: the receiver's asset list shows a balance of `100` for the USDT asset. If the transfer is still pending confirmation, call `refreshWallet()` again after the next Bitcoin block. RGB transfers require Bitcoin confirmation to finalise. On testnet, a new block typically arrives every 1–10 minutes.

## Troubleshooting

| Issue                                | Likely cause                     | Fix                                                                          |
| ------------------------------------ | -------------------------------- | ---------------------------------------------------------------------------- |
| `initialize()` hangs or times out    | No network connection to indexer | Check your internet connection and firewall settings                         |
| `createUtxos()` fails                | Insufficient BTC balance         | Fund your wallet with more testnet BTC from a faucet                         |
| Invoice rejected                     | Invoice has expired              | Generate a new invoice and retry                                             |
| `send()` fails with validation error | `amount` or `assetId` mismatch   | Confirm the send parameters exactly match the invoice                        |
| Balance not updated after send       | Wallet not synced                | Call `refreshWallet()` on both sender and receiver wallets                   |
| Asset ID not found                   | Asset not yet in wallet          | Check `listAssets()` or obtain the canonical asset ID from the SDK reference |

If you encounter an issue not listed here, join the [Utexo Discord](https://discord.gg/utexo) for community support.

## Next Steps

* [SDK Reference](/sdk/utexo-sdk) — Full method reference for `UTEXOWallet`, including Lightning channel management and backup
* [Architecture](/getting-started/architecture) — Understand how Bitcoin, Lightning, and RGB fit together
* [Glossary](/getting-started/glossary) — Definitions for RGB, PSBT, blinded invoice, UTXO, and other key terms
