{"id":13560693,"url":"https://github.com/RGB-Tools/rgb-sandbox","last_synced_at":"2025-04-03T16:30:59.646Z","repository":{"id":44456381,"uuid":"511831589","full_name":"RGB-Tools/rgb-sandbox","owner":"RGB-Tools","description":null,"archived":false,"fork":false,"pushed_at":"2024-04-17T09:52:29.000Z","size":56,"stargazers_count":20,"open_issues_count":1,"forks_count":11,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-04T12:39:56.859Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RGB-Tools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-08T09:05:52.000Z","updated_at":"2024-04-13T08:04:41.000Z","dependencies_parsed_at":"2023-02-14T15:46:45.920Z","dependency_job_id":"48f6e003-e23a-460b-84b7-e0d9ec30bd3f","html_url":"https://github.com/RGB-Tools/rgb-sandbox","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RGB-Tools%2Frgb-sandbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RGB-Tools%2Frgb-sandbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RGB-Tools%2Frgb-sandbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RGB-Tools%2Frgb-sandbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RGB-Tools","download_url":"https://codeload.github.com/RGB-Tools/rgb-sandbox/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247036923,"owners_count":20873048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T13:00:48.736Z","updated_at":"2025-04-03T16:30:59.372Z","avatar_url":"https://github.com/RGB-Tools.png","language":"Shell","funding_links":[],"categories":["Guides","Awesome RGB(Really Good Bitcoin)"],"sub_categories":["Main RGB Standards","Code Repositories"],"readme":"RGB Sandbox\n===\n\n## Introduction\nThis is an RGB sandbox and demo based on RGB version 0.10.\nIt is based on the original rgb-node demo by [St333p] (version 0.1), [grunch]'s\n[guide] and previous rgb-node sandbox versions.\n\nThe underlying Bitcoin network is `regtest`.\n\nRGB is operated via the [rgb-contracts] crate. [BDK] is used for walleting.\n\nThis sandbox can help explore RGB features in a self-contained environment\nor can be used as a demo of the main RGB functionalities for fungible assets.\n\nTwo versions of the demo are available:\n- an automated one\n- a manual one\n\nThe automated version is meant to provide a quick and easy way to see an RGB\ntoken be created and transferred. The manual version is meant to provide a\nhands-on experience with an RGB token and gives step-by-step instructions on\nhow to operate all the required components.\n\nCommands are to be executed in a bash shell. Example output is provided to\nallow following the links between the steps. Actual output when executing the\nprocedure will be different each time.\n\n## Setup\nClone the repository, including (shallow) submodules:\n```sh\ngit clone https://github.com/RGB-Tools/rgb-sandbox --recurse-submodules --shallow-submodules\n```\n\nThe default setup assumes the user and group IDs are `1000`. If that's not the\ncase, the `MYUID` and `MYGID` environment variables  in the\n`docker-compose.yml` file need to be updated accordingly.\n\nThe automated demo does not require any other setup steps.\n\nThe manual version requires handling of data directories and services, see the\n[dedicated section](#data-and-service-management) for instructions.\n\nBoth versions will leave `bdk-cli` and `rgb-contracts` installed, in the\nrespective directories under the project root. These directories can be safely\nremoved to start from scratch, doing so will just require the rust crates to be\nre-installed on the next run.\n\n### Requirements\n- [git]\n- [cargo]\n- [docker]\n- [docker compose]\n- sqlite3 development library (e.g. `libsqlite3-dev` on Debian-like systems)\n\n## Sandbox exploration\nThe services started with docker compose simulate a small network with a\nbitcoin node and an explorer. These can be used to support testing and\nexploring the basic functionality of an RGB ecosystem.\n\nCheck out the manual demo below to get started with example commands. Refer to\neach command's help documentation for additional information.\n\n## Automated demo\nTo check out the automated demo, run:\n```sh\nbash demo.sh\n```\n\nThe automated script will install the required rust crates, create empty\nservice data directories, start the required services, prepare the wallets,\nissue assets, execute a series of asset transfers, then stop the services and\nremove the data directories.\n\nFor more verbose output during the automated demo, add the `-v` option (`bash\ndemo.sh -v`), which shows the commands being run and additional\ninformation (including output from additional inspection commands).\n\n## Manual demo recording\n\nFollowing the manual demo and executing all the required steps is a rather long\nand error-prone process.\n\nTo ease the task of following the steps, a recording of the manual demo\nexecution is available:\n[![demo](https://asciinema.org/a/603883.svg)](https://asciinema.org/a/603883?autoplay=1)\n\n## Manual demo\n\nNote: this has not yet been updated to the 0.10 version.\n\nThe manual demo shows how to issue an asset and transfer some to a recipient.\n\nAt the beginning of the demo, some shell command aliases and common variables\nneed to be set, then a series of steps are briefly described and illustrated\nwith example shell commands.\n\nDuring each step, commands either use literal values, ones that the user needs\nto fill in, or variables. Some variables (uppercase) are the ones set at the\nbeginning of the demo, others (lowercase) need to be set based on the output of\nthe commands as they are run.\n\nValues that need to be filled in with command output follow the command\ninvocation that produces the required output and the example value is\nellipsized (`...`), meaning the instruction should not be copied verbatim and\nthe value should instead be replaced with the actual output received while\nfollowing the steps.\n\n### Data and service management\nCreate data directories and start the required services in Docker containers:\n```sh\n# create data directories\nmkdir data{0,1,core,index}\n\n# start services (first time docker images need to be downloaded...)\ndocker compose up -d\n```\n\nTo get a list of the running services you can run:\n```sh\ndocker compose ps\n```\n\nTo get their respective logs you can run, for instance:\n```sh\ndocker compose logs bitcoind\n```\n\nOnce finished and in order to clean up containers and data to start the demo\nfrom scratch, run:\n```sh\n# stop services and remove containers\ndocker compose down\n\n# remove data directories\nrm -fr data{0,1,core,index}\n```\n\n### Premise\nThe rgb-contracts CLI tool does not handle wallet-related functionality, it\nperforms RGB-specific tasks over data that is provided by an external wallet,\nsuch as BDK. In particular, in order to demonstrate a basic workflow with\nissuance and transfer, from the bitcoin wallets we will need:\n- an *outpoint_issue* to which the issuer will allocate the new asset\n- an *outpoint_receive* where the recipient will receive the asset transfer\n- an *addr_change* where the sender will receive the bitcoin and asset change\n- a partially signed bitcoin transaction (PSBT) to anchor the transfer\n\n### bdk-cli installation\nWallets will be handled with BDK. We install its CLI to the `bdk-cli` directory\ninside the project directory:\n```sh\ncargo install bdk-cli --version \"0.27.1\" --root \"./bdk-cli\" --features electrum --locked\n```\n\n### rgb-contracts installation\nRGB functionality will be handled with `rgb-contracts`. We install its CLI to\nthe `rgb-contracts` directory inside the project directory:\n```sh\ncargo install rgb-contracts --version \"0.10.0-rc.5\" --root \"./rgb-contracts\" --all-features --locked\n```\n\n### Demo\n#### Initial setup\nWe setup aliases to ease CLI calls:\n```sh\nalias bcli=\"docker compose exec -u blits bitcoind bitcoin-cli -regtest\"\nalias bdk=\"bdk-cli/bin/bdk-cli\"\nalias rgb0=\"rgb-contracts/bin/rgb -n regtest -d data0\"\nalias rgb1=\"rgb-contracts/bin/rgb -n regtest -d data1\"\n```\n\nWe set some environment variables:\n```sh\nCLOSING_METHOD=\"opret1st\"\nDERIVE_PATH=\"m/86'/1'/0'/9\"\nDESC_TYPE=\"wpkh\"\nELECTRUM=\"localhost:50001\"\nELECTRUM_DOCKER=\"electrs:50001\"\nCONSIGNMENT=\"consignment.rgb\"\nPSBT=\"tx.psbt\"\nIFACE=\"RGB20\"\n```\n\nWe prepare the Bitcoin wallets using Bitcoin Core and BDK:\n```sh\n# Bitcoin Core wallet\nbcli createwallet miner\nbcli -generate 103\n\n# if there are any bdk wallets from previous runs, they need to be removed\nrm -fr ~/.bdk-bitcoin/{issuer,receiver}\n\n# issuer/sender BDK wallet\nbdk key generate\n# example output:\n# {\n#   \"fingerprint\": \"a83fc09c\",\n#   \"mnemonic\": \"frozen nest frown retire wolf clinic tent know culture mad season whip impulse adjust hand change stomach meat wreck brick foam broken start reform\",\n#   \"xprv\": \"tprv8ZgxMBicQKsPey8NKMEpFemmWPMtYb4znAKtWVKr48Q1uDvemxT3RRW5m6NpToMoiVYSwVS16xKkeMueVhxnUsE7X7TpgzzxLSg7jBS1ma2\"\n# }\n\nxprv_0=\"tprv8Zgx...\"\n\nbdk key derive -p \"$DERIVE_PATH\" -x \"$xprv_0\"\n# example output:\n# {\n#   \"xprv\": \"[a83fc09c/86'/1'/0'/9]tprv8iqTQS7ksLhSaJNCfach4uTD6NJtoypuYnSEM5no1Km6YkCt8ciaYxtNL8pR68KU8a7GDSMhRTsrjaH7QR5bsx2e4287tjBa7SdFGyStGPR/*\",\n#   \"xpub\": \"[a83fc09c/86'/1'/0'/9]tpubDFXVYrA11iP7TmPzZEHHUK7KfPppyK1p8631dbq6RbZVPETem1YAjTWEWK6xkwQpJpcvcX6vGZ8xoK6yLE7CcRnm4514mhHGfJ1UNLHVxXG/*\"\n# }\n\nxprv_der_0=\"[a83fc09c/86'/1'/0'/9]tprv8iqT...\"\nxpub_der_0=\"[a83fc09c/86'/1'/0'/9]tpubDFXV...\"\n\n# receiver BDK wallet\nbdk key generate\n# example output:\n# {\n#   \"fingerprint\": \"2976d70f\",\n#   \"mnemonic\": \"kick detail chronic crime unusual nut legal viable limb elegant always tent envelope betray comfort human famous boat garment shallow hunt brass mind bomb\",\n#   \"xprv\": \"tprv8ZgxMBicQKsPdorFhbmRFNu9tWMy2xxLLRYvxE5bpSvhymTpUmHdgaZiXN3ndATpSRTyyaxpnve3xYwhdoUhW1DwCW85MW9KwuJzV2xX6gV\"\n# }\n\nxprv_1=\"tprv8Zgx...\"\n\nbdk key derive -p \"$DERIVE_PATH\" -x \"$xprv_1\"\n# example output:\n# {\n#   \"xprv\": \"[2976d70f/86'/1'/0'/9]tprv8j496FRBryAmENLx7h66pKcgtet1o7fJN5yv4jVvZ8cpcDVTWajqqmyNFmrv9buLR7UkhqFKuvshcZQxdzfCgN1Qg1m5UcHLA5PRumTBvv7/*\",\n#   \"xpub\": \"[2976d70f/86'/1'/0'/9]tpubDFkBEfTS1LrS7qNk1LkhDjGoTgPwxSrCwPahMFYDyQRDShkE8yZS2GbERvepZ9mNAK5R4ejNmDoFFv1EHZ8QgJwqkXFmn6C1spUa6VUwr1x/*\"\n# }\n\nxprv_der_1=\"[2976d70f/86'/1'/0'/9]tprv8j49...\"\nxpub_der_1=\"[2976d70f/86'/1'/0'/9]tpubDFkB...\"\n\n# generate addresses\nbdk -n regtest wallet -w issuer -d \"$DESC_TYPE($xpub_der_0)\" get_new_address\n# example output:\n# {\n#   \"address\": \"bcrt1q67z8nmswgvs38n64yl80plsejcs6vt867c2y22\"\n# }\n\naddr_issue=\"bcrt1q67...\"\n\nbdk -n regtest wallet -w issuer -d \"$DESC_TYPE($xpub_der_0)\" get_new_address\n# example output:\n# {\n#   \"address\": \"bcrt1qr36fkwcvaqkg4v5e2hdh9x4vrxhqysf6wk4hcn\"\n# }\n\naddr_change=\"bcrt1qr3...\"\n\nbdk -n regtest wallet -w receiver -d \"$DESC_TYPE($xpub_der_1)\" get_new_address\n# example output:\n# {\n#   \"address\": \"bcrt1q87w6s0anaugzksgmq9adwcgw9wyt6ekj7u8qc6\"\n# }\n\naddr_receive=\"bcrt1q87...\"\n\n# fund wallets\nbcli -rpcwallet=miner sendtoaddress \"$addr_issue\" 1\nbcli -rpcwallet=miner sendtoaddress \"$addr_receive\" 1\nbcli -rpcwallet=miner -generate 1\n\n# sync wallets\nbdk -n regtest wallet -w issuer -d \"$DESC_TYPE($xpub_der_0)\" -s \"$ELECTRUM\" sync\nbdk -n regtest wallet -w receiver -d \"$DESC_TYPE($xpub_der_1)\" -s \"$ELECTRUM\" sync\n\n# list wallet unspents and gather the outpoints\nbdk -n regtest wallet -w issuer -d \"$DESC_TYPE($xpub_der_0)\" list_unspent\n# example output:\n# [\n#   {\n#     \"is_spent\": false,\n#     \"keychain\": \"External\",\n#     \"outpoint\": \"6f6343401fc57c3f6a30043c61023e62311ee2b5d321823843af9cbcbfb2ac7e:1\",\n#     \"txout\": {\n#       \"script_pubkey\": \"0014d78479ee0e432113cf5527cef0fe199621a62cfa\",\n#       \"value\": 100000000\n#     }\n#   }\n# ]\n\noutpoint_issue=\"6f6...c7e:1\"\n\nbdk -n regtest wallet -w receiver -d \"$DESC_TYPE($xpub_der_1)\" list_unspent\n# example output:\n# [\n#   {\n#     \"is_spent\": false,\n#     \"keychain\": \"External\",\n#     \"outpoint\": \"bbc274a1f145552a6f22cab912c9b1903fb30333128b3b0f22212f2aa87772e2:0\",\n#     \"txout\": {\n#       \"script_pubkey\": \"00143f9da83fb3ef102b411b017ad7610e2b88bd66d2\",\n#       \"value\": 100000000\n#     }\n#   }\n# ]\n\noutpoint_receive=\"bbc...2e2:0\"\n```\n\nWe setup the RGB clients, importing schema and interface implementation:\n```sh\n# 1st client\nrgb0 import rgb-schemata/schemata/NonInflatableAssets.rgb\n# example output:\n# Stock file not found, creating default stock\n# Wallet file not found, creating new wallet list\n# Schema urn:lnp-bp:sc:BEiLYE-am9WhTW1-oK8cpvw4-FEMtzMrf-mKocuGZn-qWK6YF#ginger-parking-nirvana imported to the stash\n\nrgb0 import rgb-schemata/schemata/NonInflatableAssets-RGB20.rgb\n# example output:\n# Implementation urn:lnp-bp:im:9EUGHC-wpuiyrQE-NdPBVyiv-VX4sVRBs-9yKfteug-HtqnGb#titanic-easy-citizen of interface urn:lnp-bp:if:48hc4i-m9JRcYQA-uUSzwFCK-VNEa9eZf-nhepU8QJ-pqosXS#laptop-domingo-cool for schema urn:lnp-bp:sc:BEiLYE-am9WhTW1-oK8cpvw4-FEMtzMrf-mKocuGZn-qWK6YF#ginger-parking-nirvana imported to the stash\n\n# 2nd client (same output as 1st client)\nrgb1 import rgb-schemata/schemata/NonInflatableAssets.rgb\nrgb1 import rgb-schemata/schemata/NonInflatableAssets-RGB20.rgb\n```\n\nWe retrieve the schema ID and set it as environment variable:\n```sh\nrgb0 schemata\n# example output:\n# urn:lnp-bp:sc:BEiLYE-am9WhTW1-oK8cpvw4-FEMtzMrf-mKocuGZn-qWK6YF#ginger-parking-nirvana RGB20\n\nschema=\"urn:lnp-bp:sc:BEiLYE-am...ing-nirvana\"\n```\n\n#### Asset issuance\nTo issue an asset, we first need to prepare a contract definition file, then\nuse it to actually carry out the issuance.\n\nTo prepare the contract file, we copy the provided template and modify the copy\nto set the required data:\n- issued supply\n- created timestamp\n- closing method\n- issuance txid and vout\n\nWe do this with a single command (which reads the template file, modifies the\ngiven properties and writes the result to the contract definition file):\n```sh\nsed \\\n  -e \"s/issued_supply/1000/\" \\\n  -e \"s/created_timestamp/$(date +%s)/\" \\\n  -e \"s/closing_method/$CLOSING_METHOD/\" \\\n  -e \"s/txid:vout/$outpoint_issue/\" \\\n  contracts/usdt.yaml.template \u003e contracts/usdt.yaml\n```\n\nTo actually issue the asset, run:\n```sh\nrgb0 issue \"$schema\" \"$IFACE\" contracts/usdt.yaml\n# example output:\n# A new contract rgb:2Q7p6zS-JUCTP8pMJ-7fk8QBjYp-ngvHnJiuw-9jh8PPuvy-scKUUkd is issued and added to the stash.\n# Use `export` command to export the contract.\n\ncontract_id=\"rgb:2Q7...Ukd\"\n```\nThis will create a new genesis that includes the asset metadata and the\nallocation of the initial amount to `outpoint_issue`.\n\nYou can list known contracts:\n```sh\nrgb0 contracts\n# example output:\n# rgb:2Q7p6zS-JUCTP8pMJ-7fk8QBjYp-ngvHnJiuw-9jh8PPuvy-scKUUkd\n```\n\nYou can show the current known state for the contract:\n```sh\nrgb0 state \"$contract_id\" \"$IFACE\"\n# example output:\n# Global:\n#   spec := (naming=(ticker=(\"USDT\"), name=(\"USD Tether\"), details=~), precision=0)\n#   data := (terms=(\"demo RGB20 asset\"), media=~)\n#   issuedSupply := (1000)\n#   created := (1691496693)\n#\n# Owned:\n#   assetOwner:\n#     amount=1000, utxo=6f6343401fc57c3f6a30043c61023e62311ee2b5d321823843af9cbcbfb2ac7e:1, witness=~ # owner unknown\n```\n\n#### Transfer\n\n##### Receiver: generate invoice\nIn order to receive assets, the receiver needs to provide an invoice to the\nsender. The receiver generates an invoice providing the amount to be received\n(here `100`) and the outpoint where the assets should be allocated:\n```sh\nrgb1 invoice \"$contract_id\" \"$IFACE\" 100 \"$CLOSING_METHOD:$outpoint_receive\"\n# example output:\n# rgb:2Q7p6zS-JUCTP8pMJ-7fk8QBjYp-ngvHnJiuw-9jh8PPuvy-scKUUkd/RGB20/100+utxob:ZCTkvDN-mrwDXLSkx-1PKfHuaGH-R7cLf79Rg-YfSUGYn6i-YAS4Ts\n\ninvoice=\"rgb:2Q7...Ukd/RGB20/100+utxob:ZCT...4Ts\"\n```\nNote: this will blind the given outpoint and the invoice will contain a blinded\nUTXO in place of the original outpoint (see the `utxob:` part of the invoice).\n\n##### Sender: initiate asset transfer\nTo send assets, the sender needs to create a consignment and commit to it into\na bitcoin transaction. We need to create a PSBT and then modify it to include\nthe commitment.\n\nWe create the PSBT, using `outpoint_issue` as input and `addr_change` for the\nchange (RGB and BTC):\n```sh\nbdk -n regtest wallet -w issuer -d \"$DESC_TYPE($xpub_der_0)\" create_tx \\\n  -f 5 --send_all --utxos \"$outpoint_issue\" --to \"$addr_change:0\" \\\n  --add_string opret\n# example output:\n# {\n#   \"details\": {\n#     \"confirmation_time\": null,\n#     \"fee\": 630,\n#     \"received\": 99999370,\n#     \"sent\": 100000000,\n#     \"transaction\": null,\n#     \"txid\": \"26a1250ec087138e663cb7be52e13b18758e0257d9aba79d3f6eb0b0516763dd\"\n#   },\n#   \"psbt\": \"cHNidP8BAGIBAAAAAX6ssr+8nK9DOIIh07XiHjFiPgJhPAQwaj98xR9AQ2NvAQAAAAD+////Aore9QUAAAAAFgAUHHSbOwzoLIqymVXbcpqsGa4CQToAAAAAAAAAAAdqBW9wcmV0aAAAAAABAN4CAAAAAAEB9PcBuZVCyKTgMO50SVrsjfqdlVTABBB3cMtZaGXMN2MAAAAAAP3///8C/AUQJAEAAAAWABRhzatgiLp38YKt+2na/iB6/Y2MnADh9QUAAAAAFgAU14R57g5DIRPPVSfO8P4ZliGmLPoCRzBEAiAdCmZ/hSk/rZr+G+SGo/Lx8O8ZpAjIihTYcF983h796wIgHnKVCPwfmTIn+EPl8pDXbzHRTVnAn5jBRDCaMYS1SeMBIQPkcWZ9eqvZKlG1QK4t4vplBvahq6fHGp/lezPo9+pznWcAAAABAR8A4fUFAAAAABYAFNeEee4OQyETz1UnzvD+GZYhpiz6IgYClNhrjr91okI1jPK4r97icFId4fmZHKPciyYh7UBuX+MYqD/AnFYAAIABAACAAAAAgAkAAAAAAAAAACICAquWbk66NttJRZuWBIjM4NIbB1bT0/pH5VKyViGyey5TGKg/wJxWAACAAQAAgAAAAIAJAAAAAQAAAAAA\"\n# }\n\necho \"cHN...AAA\" | base64 -d \u003e \"data0/$PSBT\"\n```\n\nWe then modify the PSBT to set the commitment host:\n```sh\nrgb0 set-host --method \"$CLOSING_METHOD\" \"data0/$PSBT\"\n# PSBT file 'data0/tx.psbt' is updated with opret1st host now set.\n```\n\nWe create the transfer, providing the PSBT and the invoice. This generates the\nconsignment:\n```sh\nrgb0 transfer --method \"$CLOSING_METHOD\" \"data0/$PSBT\" \"$invoice\" \"data0/$CONSIGNMENT\"\n# example output:\n# Transfer is created and saved into 'data0/consignment.rgb'.\n# PSBT file 'data0/tx.psbt' is updated with all required commitments and ready to be signed.\n# Stash data are updated.\n```\n\nThe consignment can be inspected, but since the output is very long it's best\nto send the output to a file:\n```sh\nrgb0 inspect \"data0/$CONSIGNMENT\" \u003e consignment.inspect\n```\nTo view the result, open the `consignment.inspect` file with a text editor.\n\n##### Consignment exchange\nFor the purpose of this demo, copying the file over to the receiving node's\ndata directory is sufficient:\n```sh\ncp data{0,1}/\"$CONSIGNMENT\"\n```\n\nIn real-world scenarios, consignments are exchanged either via [RGB HTTP\nJSON-RPC] (e.g. using an [RGB proxy]) or other consignment exchange services.\n\n##### Receiver: validate transfer\nBefore a transfer can be safely accepted, it needs to be validated:\n```sh\nrgb1 validate \"data1/$CONSIGNMENT\"\n# example output:\n# Consignment has non-mined terminal(s)\n# Non-mined terminals:\n# - f17d544c0ac161f758d379c4366e6ede8f394da9633671908738b415ae5c8fb4\n# Validation warnings:\n# - terminal witness transaction f17d544c0ac161f758d379c4366e6ede8f394da9633671908738b415ae5c8fb4 is not yet mined.\n```\n\nAt this point it's normal that validation reports a warning about the witness\ntransaction not been mined, as the sender has not broadcast it yet. The sender\nis waiting for approval from the receiver.\n\nOnce validation has passed, the receiver can approve the transfer. For this\ndemo let's just assume it happened, in a real-world scenario an [RGB proxy]\nwould be typically used for this as well.\n\n##### Sender: sign and broadcast transaction\nWith the receiver's approval of the transfer, the transaction can be signed and\nbroadcast:\n```sh\nbdk -n regtest wallet -w issuer -d \"$DESC_TYPE($xprv_der_0)\" \\\n  sign --psbt $(cat data0/$PSBT | base64 | tr -d '\\r\\n')\n# example output:\n# {\n#   \"is_finalized\": true,\n#   \"psbt\": \"cHNidP8BAH0BAAAAAX6ssr+8nK9DOIIh07XiHjFiPgJhPAQwaj98xR9AQ2NvAQAAAAD+////Aore9QUAAAAAFgAUHHSbOwzoLIqymVXbcpqsGa4CQToAAAAAAAAAACJqILJNu5OPAn29xMK30LPyEYF8BQzo4m4kMqdwQOf+vFMvaAAAACb8A1JHQgGzGylFw6I59wDVj85LlfJSDWRSj1ETsk8raL8NsrHYvNYAALgv5W39fUCA+5Wg2rcfqnBDyRzss7SzfYf8Km8dWDCRECcAAAABuC/lbf19QID7laDatx+qcEPJHOyztLN9h/wqbx1YMJGgDwAAAAGgDwECAAMAAAAAAAAPvcNrn//UdwiEAwAAAAAAAB1R+iZ9g65EZQH+yo6U6Rd5BR49w6kNrogl9GhgX2lPAkkbzeRxlHm2NcOArOXeqIFc56HypcJNjYqcpHODx2ySCGQAAAAAAAAAU/umctyJSLYssZtL73I+o2LndtWGDjf0niWCCTgYfVgAAAEA3gIAAAAAAQH09wG5lULIpOAw7nRJWuyN+p2VVMAEEHdwy1loZcw3YwAAAAAA/f///wL8BRAkAQAAABYAFGHNq2CIunfxgq37adr+IHr9jYycAOH1BQAAAAAWABTXhHnuDkMhE89VJ87w/hmWIaYs+gJHMEQCIB0KZn+FKT+tmv4b5Iaj8vHw7xmkCMiKFNhwX3zeHv3rAiAecpUI/B+ZMif4Q+XykNdvMdFNWcCfmMFEMJoxhLVJ4wEhA+RxZn16q9kqUbVAri3i+mUG9qGrp8can+V7M+j36nOdZwAAAAEBHwDh9QUAAAAAFgAU14R57g5DIRPPVSfO8P4ZliGmLPoiBgKU2GuOv3WiQjWM8riv3uJwUh3h+Zkco9yLJiHtQG5f4xioP8CcVgAAgAEAAIAAAACACQAAAAAAAAABBwABCGsCRzBEAiAJopaRrp3rkRwyFThM4feKs1/LrqP3oLj/4mxEWEX8NgIgWTtPIDgl2pOHAQHcW8Y8L3+kwPYbUfe5IHgE7Q49dpwBIQKU2GuOv3WiQjWM8riv3uJwUh3h+Zkco9yLJiHtQG5f4yb8A1JHQgO4L+Vt/X1AgPuVoNq3H6pwQ8kc7LO0s32H/CpvHVgwkSCzGylFw6I59wDVj85LlfJSDWRSj1ETsk8raL8NsrHYvAAiAgKrlm5OujbbSUWblgSIzODSGwdW09P6R+VSslYhsnsuUxioP8CcVgAAgAEAAIAAAACACQAAAAEAAAAAKfwGTE5QQlA0ALgv5W39fUCA+5Wg2rcfqnBDyRzss7SzfYf8Km8dWDCRIAjJeTBvKvCk+LhBj7FQmWMaz10SJxpnP3PjjR0/gGtNCfwGTE5QQlA0AQhTJmpjuc0zTwj8BU9QUkVUAAAI/AVPUFJFVAEgsk27k48Cfb3EwrfQs/IRgXwFDOjibiQyp3BA5/68Uy8A\"\n# }\n\npsbt_signed=\"cHN...y8A\"\n\nbdk -n regtest wallet -w issuer -d \"$DESC_TYPE($xpub_der_0)\" -s \"$ELECTRUM\" \\\n    broadcast --psbt \"$psbt_signed\"\n# example output:\n# {\n#   \"txid\": \"f17d544c0ac161f758d379c4366e6ede8f394da9633671908738b415ae5c8fb4\"\n# }\n```\n\n##### Transaction confirmation\nNow the transaction has been broadcast, let's confirm it:\n```sh\nbcli -rpcwallet=miner -generate 1\n```\nIn real-world scenarios the parties wait for the transaction to be included in\na block.\n\n##### Receiver: accept transfer\nOnce the transaction has been confirmed, the receiver can accept the transfer,\nwhich is required to complete the transfer and update the contract state:\n```sh\nrgb1 accept \"data1/$CONSIGNMENT\"\n# example output:\n# Consignment is valid\n#\n# Transfer accepted into the stash\n```\nNote that accepting a transfer first validates its consignment.\n\nLet's see the updated contract state, from the receiver's point of view:\n```sh\nrgb1 state \"$contract_id\" \"$IFACE\"\n# example output:\n# Global:\n#   spec := (naming=(ticker=(\"USDT\"), name=(\"USD Tether\"), details=~), precision=0)\n#   data := (terms=(\"demo RGB20 asset\"), media=~)\n#   issuedSupply := (1000)\n#   created := (1691496693)\n#\n# Owned:\n#   assetOwner:\n#     amount=900, utxo=f17d544c0ac161f758d379c4366e6ede8f394da9633671908738b415ae5c8fb4:0, witness=f17d544c0ac161f758d379c4366e6ede8f394da9633671908738b415ae5c8fb4 # owner unknown\n#     amount=100, utxo=bbc274a1f145552a6f22cab912c9b1903fb30333128b3b0f22212f2aa87772e2:0, witness=f17d544c0ac161f758d379c4366e6ede8f394da9633671908738b415ae5c8fb4 # owner unknown\n#     amount=1000, utxo=6f6343401fc57c3f6a30043c61023e62311ee2b5d321823843af9cbcbfb2ac7e:1, witness=~ # owner unknown\n```\nThe allocations for the original issuance and the transfer can be seen. The\nreceiver can recognize its allocation from the `utxo`, which corresponds to the\n`outpoint_receive` provided to generate the invoice.\n\n##### Sender: accept transfer\nThe sender doesn't need to explicitly accept the transfer, as it's automatically\naccepted when creating it.\n\nThe contract state already reflects the updated situation:\n```sh\nrgb0 state \"$contract_id\" \"$IFACE\"\n# example output:\n# Global:\n#   spec := (naming=(ticker=(\"USDT\"), name=(\"USD Tether\"), details=~), precision=0)\n#   data := (terms=(\"demo RGB20 asset\"), media=~)\n#   issuedSupply := (1000)\n#   created := (1691496693)\n#\n# Owned:\n#   assetOwner:\n#     amount=900, utxo=f17d544c0ac161f758d379c4366e6ede8f394da9633671908738b415ae5c8fb4:0, witness=f17d544c0ac161f758d379c4366e6ede8f394da9633671908738b415ae5c8fb4 # owner unknown\n#     amount=1000, utxo=6f6343401fc57c3f6a30043c61023e62311ee2b5d321823843af9cbcbfb2ac7e:1, witness=~ # owner unknown\n```\n\nSince the `outpoint_receive` was blinded during invoice generation, the payer\nhas no information on where the asset was allocated by the transfer, so the\nreceiver's allocation is not visible in the contract state on the sender's\nside.\n\n\n[BDK]: https://github.com/bitcoindevkit/bdk-cli\n[RGB HTTP JSON-RPC]: https://github.com/RGB-Tools/rgb-http-json-rpc\n[RGB proxy]: https://github.com/RGB-Tools/rgb-proxy-server\n[St333p]: https://github.com/St333p\n[cargo]: https://github.com/rust-lang/cargo\n[docker compose]: https://docs.docker.com/compose/install/\n[docker]: https://docs.docker.com/get-docker/\n[git]: https://git-scm.com/downloads\n[grunch]: https://github.com/grunch\n[guide]: https://grunch.dev/blog/rgbnode-tutorial/\n[rgb-contracts]: https://github.com/RGB-WG/rgb\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRGB-Tools%2Frgb-sandbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRGB-Tools%2Frgb-sandbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRGB-Tools%2Frgb-sandbox/lists"}