> ## 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.

# Quickstart

> Send your first USDT on Bitcoin transfer in under 15 minutes.

<Warning>
  This page documents the archived `@utexo/rgb-sdk` package. New Node.js integrations should use [`@utexo/wdk-rgb-lightning`](/sdk/wdk-rgb-lightning). For browsers see the [Web Quickstart](/getting-started/quickstart/web); for iOS and Android see the [React Native Quickstart](/getting-started/quickstart/react-native).
</Warning>

## What You Will Build

This guide walks you through the full Utexo SDK integration flow: installing the SDK, generating and initializing a wallet, funding it with testnet BTC, creating UTXOs to anchor RGB state, generating an RGB invoice and completing your first USDT on Bitcoin transfer.

By the end of this guide you will have:

* A working `UTEXOWallet` instance connected to testnet
* A funded wallet with UTXOs ready to receive RGB assets
* Successfully sent and verified a USDT on Bitcoin transfer

<Info>
  **Estimated time:** 15 minutes, not counting testnet faucet confirmation time (usually 1–5 minutes, but can vary).
</Info>

## How RGB Transfers Work

Before writing any code, it helps to understand the flow:

1. The **receiver** generates a blinded invoice tied to one of their UTXOs
2. The **sender** calls `.send()` with that invoice — the RGB state transition is constructed and broadcast
3. Both wallets call `.refreshWallet()` to sync the latest on-chain state
4. The receiver's balance updates to reflect the new asset allocation

All asset state is validated client-side. Neither party needs to trust a third party — the Bitcoin UTXO provides the settlement anchor.

<Info>
  New to RGB or UTXOs? See the [Glossary](/getting-started/glossary) for definitions, and [Architecture](/getting-started/architecture) for how Bitcoin, Lightning, and RGB fit together.
</Info>

## Prerequisites

Before you start, make sure you have the following:

* **Node.js v18 or later** — [Download here](https://nodejs.org/)
* **A testnet BTC balance** for transaction fees. Get testnet BTC from the Utexo Telegram faucet bot [@Utexo\_RLN\_bot](https://t.me/Utexo_RLN_bot) — send `/getbtc` followed by your Bitcoin address.
* **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>

## Network Endpoints (Testnet)

The SDK connects to the following endpoints by default on testnet. No configuration is needed to follow this guide.

| Service | Endpoint |
| - | - |
| RGB Transport | `rpcs://rgb-proxy.utexo.com/json-rpc` |
| Bitcoin Indexer | `https://esplora-api.utexo.com` |

For mainnet endpoint configuration, see the [wdk-rgb-lightning Reference](/sdk/wdk-rgb-lightning).

## Step 1: Install the SDK

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

<Warning>
  The Utexo SDK is **Node.js only** and is not browser-compatible. It requires access to the file system and native crypto modules.
</Warning>

## 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);
```

<Warning>
  **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.
</Warning>

## Step 3: Initialize the Wallet

Create and initialize a `UTEXOWallet` instance using your mnemonic. Initialization 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 initialized 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 the Telegram faucet bot — 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 `/getbtc` with this address to [@Utexo\_RLN\_bot](https://t.me/Utexo_RLN_bot) (see [Prerequisites](#prerequisites)). Wait for at least 1 confirmation before continuing.

<Info>
  You only need a small amount — a few thousand satoshis is enough to cover fees for this tutorial.
</Info>

## 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. |

<Info>
  `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.
</Info>

## Step 6: Get the RGB USDT Asset ID

Before generating an invoice, you need the **asset ID** of the RGB USDT 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);
```

<Info>
  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 [wdk-rgb-lightning Reference](/sdk/wdk-rgb-lightning) or by asking in the [Utexo Discord](https://discord.gg/utexo).
</Info>

## 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 for RGB USDT)
  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 RGB USDT, 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. |

<Warning>
  Invoices expire after `durationSeconds`. The sender must complete the transfer before the invoice expires, otherwise the sender will need a new invoice.
</Warning>

## 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 RGB USDT 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)
```

<Info>
  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.
</Info>

<Warning>
  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.
</Warning>

## 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.

<Info>
  RGB transfers require Bitcoin confirmation to finalize. On testnet, a new block typically arrives every 1–10 minutes.
</Info>

## 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 via `/getbtc` on [@Utexo\_RLN\_bot](https://t.me/Utexo_RLN_bot) |
| 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 |

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

## Next Steps

* [wdk-rgb-lightning Reference](/sdk/wdk-rgb-lightning) — Current Node.js / Bare module for RGB Lightning
* [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


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.