Skip to main content

Quick Start

Applies to both RGB lines

There are two separate walkthroughs, one per line. Their files, invoices and wallets can't be mixed. See Two RGB lines.

Both walkthroughs issue a fungible asset and send part of it to a second wallet. Each follows its project's own demo: rgb-sandbox for Line B, and examples/demo.sh for Line A. Output shown as real output came from running the pinned binary offline on 2026-10-19. Steps that need a node or an indexer weren't run here. Their output is quoted from the upstream README, or left out.

You need the CLI for your line installed first: see Installation.

Before you move real value
  • Send the consignment and get it accepted before you broadcast. If the witness transaction is published and the recipient never gets the consignment, the assets are gone.
  • Let only the RGB tool spend the RGB wallet's coins. A Bitcoin-only wallet that spends a UTXO holding RGB state destroys that state.
  • Back up the RGB data directory, not just the seed. A seed alone doesn't recover assets.

Line B: regtest with rgb-cmd 0.11.1​

This is the manual demo from the rgb-sandbox README, run with rgb-cmd 0.11.1. The sandbox itself pins 0.11.1-rc.6. rgb-cmd does the RGB work, and bp-wallet (bp, bp-hot) holds the keys and signs. For apps, rgb-lib wraps all of this in one library.

1. Start regtest and set up​

git clone https://github.com/rgb-protocol/rgb-sandbox --recurse-submodules --shallow-submodules
cd rgb-sandbox
docker compose --profile electrum up -d
cargo install bp-wallet --version 0.11.1-alpha.2 --root ./bp-wallet --features=cli,hot
cargo install --locked rgb-cmd --version 0.11.1 --root ./rgb-cmd
export PATH="$PWD/rgb-cmd/bin:$PWD/bp-wallet/bin:$PATH"
export LNPBP_NETWORK=regtest
alias bcli="docker compose exec -u blits bitcoind bitcoin-cli -regtest"
bcli createwallet miner
bcli -generate 103

The issuer's data lives in data0 and the recipient's in data1. Every rgb command below passes -d (data directory), -w (wallet name) and --electrum=localhost:50001 (the sandbox's indexer; the = is required).

2. Create keys and RGB wallets​

mkdir wallets
export SEED_PASSWORD="seed test password"
bp-hot seed wallets/0.seed
bp-hot derive -N -s bip86 wallets/0.seed wallets/0.derive
# copy the "Account:" value it prints, e.g. [598d26fe/86h/1h/0h]tpubDCwK...4FLe
descriptor_0="<account_0>/<0;1;9>/*"
rgb -d data0 --electrum=localhost:50001 create --wpkh "$descriptor_0" issuer

Repeat with wallets/1.seed, descriptor_1, -d data1 and the name rcpt1 for the recipient.

3. Import the NIA schema​

The sandbox ships the compiled schemas from rgb-schemas as a submodule:

rgb -d data0 -w issuer import rgb-schemas/schemata/NonInflatableAsset.rgb
rgb -d data1 -w rcpt1 import rgb-schemas/schemata/NonInflatableAsset.rgb

Real output:

Unable to find or parse config file; using config defaults
Importing kit rgb:kit:qxyONQWD-WY7Sha7-wzsRSMW-MaNI6PI-T74uzx9-sBzUztg:
- schema NonInflatableAsset RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus
- script library alu:q~CZ0ovt-UN9eBlc-VMn86mz-Kfd3ywu-f7~9jTB-k6A8tiY#japan-nylon-center
- strict types: 35 definitions
Kit is imported

The schema ID is rgb:sch:RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus. rgb schemata prints it again.

4. Fund both wallets​

rgb -d data0 -w issuer --electrum=localhost:50001 address -k 9
rgb -d data1 -w rcpt1 --electrum=localhost:50001 address -k 9
bcli -rpcwallet=miner sendtoaddress "<addr_issue>" 1
bcli -rpcwallet=miner sendtoaddress "<addr_receive>" 1
bcli -rpcwallet=miner -generate 1
rgb -d data0 -w issuer --electrum=localhost:50001 utxos --sync
rgb -d data1 -w rcpt1 --electrum=localhost:50001 utxos --sync

Note one outpoint (txid:vout) from each wallet: outpoint_issue for the issuer and outpoint_receive for the recipient.

5. Issue​

Write demo.yaml. This is the sandbox's contracts/usdt.yaml.template with a neutral ticker, and with the schema ID and issue outpoint filled in:

schema: rgb:sch:RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus

globals:
spec:
ticker: DEMO
name: Demo Asset
details: ~
precision: 0
terms:
text: demo NIA asset
media: ~
issuedSupply: 1000

assignments:
assetOwner:
seal: <outpoint_issue>
amount: 1000
rgb -d data0 -w issuer issue "ssi:issuer" demo.yaml
rgb -d data0 -w issuer contracts

Real output (the contract ID differs on every run, because genesis seals are blinded with random values):

A new contract rgb:7Wf1Rne9-BQWvPlL-P50XBTB-D1sZQlF-Wn7eRYV-3_wZZg8 is issued and added to the stash.
Use `export` command to export the contract.

rgb:7Wf1Rne9-BQWvPlL-P50XBTB-D1sZQlF-Wn7eRYV-3_wZZg8 BitcoinRegtest 2026-10-19 rgb:sch:RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus
Developer: ssi:issuer

rgb -d data0 -w issuer --electrum=localhost:50001 state "$contract_id" shows the 1000 units on outpoint_issue.

6. Recipient: create an invoice​

rgb -d data1 -w rcpt1 --electrum=localhost:50001 invoice --amount 100 "$contract_id"

Example output, from the sandbox README:

rgb:Tk3d0h5w-8v4XYCg-7e~Sc0o-Lu6rp~X-~Jt7VHS-jqgzFD8/~/BF/bcrt:utxob:MSLQCKkW-w6caphB-12do1nJ-HNfgxvv-WE3zOOC-s8yZyHq-Ihoa5

The utxob: part is the recipient's outpoint, blinded so that the payer never learns it. Use the long option --amount: in 0.11.1, invoice gives the short flag -a to three different options.

7. Sender: transfer​

rgb -d data0 -w issuer --electrum=localhost:50001 transfer "$invoice" data0/consignment.rgb data0/tx.psbt

This writes the consignment and a PSBT that already commits to it. The default fee is 400 sats (--fee).

8. Recipient: validate, and only then broadcast​

Send data0/consignment.rgb to the recipient. The sandbox just copies it. Real deployments use an RGB proxy.

cp data0/consignment.rgb data1/
rgb -d data1 -w rcpt1 --electrum=localhost:50001 validate data1/consignment.rgb

Once the recipient approves, the sender signs, finalizes and publishes:

bp-hot sign -N data0/tx.psbt wallets/0.derive
rgb -d data0 -w issuer --electrum=localhost:50001 finalize -p data0/tx.psbt data0/tx.tx
bcli -rpcwallet=miner -generate 1

9. Recipient: accept​

rgb -d data1 -w rcpt1 --electrum=localhost:50001 utxos --sync
rgb -d data1 -w rcpt1 --electrum=localhost:50001 accept data1/consignment.rgb
rgb -d data1 -w rcpt1 --electrum=localhost:50001 state "$contract_id"

accept prints Transfer accepted into the stash (from cli/src/command.rs). The recipient's state now shows 100 units, and the sender's shows 900 units of change. To clean up, run docker compose --profile electrum down -v and rm -fr data0 data1 wallets.

Next steps​