{"id":13561069,"url":"https://github.com/bitlightlabs/bitlight-rgb20-contract","last_synced_at":"2025-04-03T16:31:56.885Z","repository":{"id":228058104,"uuid":"773032181","full_name":"bitlightlabs/bitlight-rgb20-contract","owner":"bitlightlabs","description":"RGB20 Contract Demo based on RGB v0.11.0-beta.5","archived":false,"fork":false,"pushed_at":"2024-04-14T18:47:00.000Z","size":103,"stargazers_count":12,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-04-24T05:07:37.283Z","etag":null,"topics":["contract","rgb20"],"latest_commit_sha":null,"homepage":"https://bitlightlabs.com","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bitlightlabs.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":"2024-03-16T14:59:16.000Z","updated_at":"2024-06-13T08:58:33.060Z","dependencies_parsed_at":"2024-06-13T08:58:10.976Z","dependency_job_id":"e7d83fc4-a57f-4bb8-a9b5-365278aabd49","html_url":"https://github.com/bitlightlabs/bitlight-rgb20-contract","commit_stats":null,"previous_names":["bitlightlabs/bitlight-rgb20-contract"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitlightlabs%2Fbitlight-rgb20-contract","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitlightlabs%2Fbitlight-rgb20-contract/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitlightlabs%2Fbitlight-rgb20-contract/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitlightlabs%2Fbitlight-rgb20-contract/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitlightlabs","download_url":"https://codeload.github.com/bitlightlabs/bitlight-rgb20-contract/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247037077,"owners_count":20873092,"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":["contract","rgb20"],"created_at":"2024-08-01T13:00:52.207Z","updated_at":"2025-04-03T16:31:51.877Z","avatar_url":"https://github.com/bitlightlabs.png","language":"Rust","funding_links":[],"categories":["Token and NFTs Example"],"sub_categories":["Main RGB Standards"],"readme":"# RGB20 Demo based on RGB v0.11\n\n## Pre-request\n\nTo complete the demo, you need to set up the following toolchains:\n\n1. [Git][git]\n2. [Rust][rust]\n3. [RGB-CLI][rgb-cli]\n4. [Bitcoin Local Env][bitlight-local-env-public]\n\n[git]: https://git-scm.com/\n\n[rust]: https://www.rust-lang.org/tools/install\n\n[rgb-cli]: https://github.com/RGB-WG/rgb\n\n[bitlight-local-env-public]: https://github.com/bitlightlabs/bitlight-local-env-public/\n\n### RGB-CLI\n\nFirst, clone it from GitHub:\n\n```bash\ngit clone https://github.com/RGB-WG/rgb.git\n```\n\nThen, build it, copy the binary to `~/.cargo/bin/`:\n\n```\ncd rgb\ncargo build --package rgb-wallet --bin rgb --release \ncp target/release/rgb ~/.cargo/bin/\n```\n\n### Bitcoin Local Env\n\nRun `make up` to start the development environment\n\n```bash\ngit clone https://github.com/bitlightlabs/bitlight-local-env-public/\nmake up\n```\n\nWrite down Alice's xprv and Bitcoin address.\n\n```\nmake alice-cli\n```\n\n```text\nNetwork             :  regtest\nWallet Name         :  alice\nRoot XPRV           :  tprv8ZgxMBicQKsPeHzjP5LTL818LxwHbJNLZRa98Qdnn7M98fW15365cB1Sz9QZvYufASRKH6JEPhfpxVuFTKMHxDcEAVboqKuZdMmxzKVhMnW\nFixed XPUB          :  [5183a8d8/86'/1'/0']tpubDDtdVYn7LWnWNUXADgoLGu48aLH4dZ17hYfRfV9rjB7QQK3BrphnrSV6pGAeyfyiAM7DmXPJgRzGoBdwWvRoFdJoMVpWfmM9FCk8ojVhbMS/\u003c0;1;9;10\u003e/*\nBitcoin Address     :  bcrt1pn0s2pajhsw38fnpgcj79w3kr3c0r89y3xyekjt8qaudje70g4shs20nwfx\n```\n\nWrite down Bob's xprv and Bitcoin address.\n\n```\nmake bob-cli\n```\n\n```text\nNetwork             :  regtest\nWallet Name         :  bob\nRoot XPRV           :  tprv8ZgxMBicQKsPeEP6QyHbs7W2pfW5FJisXLcX93h2AnH5Kx8fuhKz7FYm4kw46SUgXJd3zUKwNoTqxtpLw7vmtLeFUGJb6XSeom45hQjeXxJ\nFixed XPUB          :  [3abb3cbb/86'/1'/0']tpubDDeBXqUqyVcbe75SbHAPNXMojntFu5C8KTUEhnyQc74Bty6h8XxqmCavPBMd1fqQQAAYDdp6MAAcN4e2eJQFH3v4txc89s8wvHg98QSUrdL/\u003c0;1;9;10\u003e/*\nBitcoin Address     :  bcrt1plphl407vyfpml2thhypzuqk232256njnaw4zhtmyrrku66pqn9usx4x59h\n```\n\nget satoshis faucet for alice and bob\n\n```\nmake core-cli\nload_wallet\n# alice\nsend bcrt1pn0s2pajhsw38fnpgcj79w3kr3c0r89y3xyekjt8qaudje70g4shs20nwfx 1\nsend bcrt1plphl407vyfpml2thhypzuqk232256njnaw4zhtmyrrku66pqn9usx4x59h 1\nsend bcrt1pr3rupmav8a7av7dqfyvynu2wk02lduggnh9ln4ndze9aqvuv9y3sklwrss 1\n# bob\nsend bcrt1p9yjaffzhuh9p7d9gnwfunxssngesk25tz7rudu4v69dl6e7w7qhq5x43k5 1\nmint 1 \n```\n\n## Create and Import Contract\n\nTo create a RGB20 contract, just clone this repo to you local machine. Then\ncompile and run it.\n\n```bash\n$ git clone https://github.com/bitlightlabs/bitlight-rgb20-contract\n$ cd bitlight-rgb20-contract\n```\n\nedit main.rs, change the beneficiary to alice's address\n\n```rust\n    let beneficiary_txid =\n        Txid::from_hex(\"d6afd1233f2c3a7228ae2f07d64b2091db0d66f2e8ef169cf01217617f51b8fb\").unwrap();\n    let beneficiary = Outpoint::new(beneficiary_txid, 1);\n```\n\nExport ESPLORA_SERVER env for esplora-api endpoint:\n\n```bash\n$ export LNPBP_NETWORK=regtest\n$ export ESPLORA_SERVER=\"http://esplora-api.bitlight-local-env.orb.local:3000\"\n```\n\n_note:  a locally running bitlight-local-env-esplora-**api** docker container instance should export **ESPLORA_SERVER**\nvalue:_\n\n```bash\n$ export ESPLORA_SERVER=\"http://localhost:3002\"\t\n```\n\n_and locally running bitlight-local-env-esplora (server / non-api) docker container client constructor parameter\nin [examples/broadcast-tx.rs](examples/broadcast-tx.rs) set to:_\n\n```rust\n    esplora_client::Builder::new(\"http://localhost:5002\")\t\n```\n\n```bash\n$ make run\n\nThe issued contract data:\n{\"ticker\":\"TEST\",\"name\":\"Test asset\",\"details\":null,\"precision\":\"centiMicro\"}\namount=adMhBHaQ, owner=bc:tapret1st:311ec7d43f0f33cda5a0c515a737b5e0bbce3896e6eb32e67db0e868a58f4150:1, witness=~\ntotalSupply=adMhBHaQ\n\nContracts are available in the test directory\n---------------------------------\n./test:\n-rw-r--r--  1 bitlight  staff  21364 Mar 15 19:57 rgb20-simplest.rgb\n-rw-r--r--  1 bitlight  staff  27456 Mar 15 19:57 rgb20-simplest.rgba\n---------------------------------\n```\n\nNow, we are creating a RGB20 #TEST contract, which stores in `test` folder.\n\nBefore importing contracts, let's import our wallets to rgb.\n\nExport ESPLORA_SERVER env for esplora-api endpoint:\n\n```bash\nexport LNPBP_NETWORK=regtest\nexport ESPLORA_SERVER=\"http://esplora-api.bitlight-local-env.orb.local:3000\"\n```\n\nCreate rgb wallet container for Alice:\n\n```bash\n$ rgb -d .alice create default --tapret-key-only \u003calice-fixed-xpub-descriptor\u003e\n$ rgb -d .alice create default --tapret-key-only \"[5183a8d8/86'/1'/0']tpubDDtdVYn7LWnWNUXADgoLGu48aLH4dZ17hYfRfV9rjB7QQK3BrphnrSV6pGAeyfyiAM7DmXPJgRzGoBdwWvRoFdJoMVpWfmM9FCk8ojVhbMS/\u003c0;1;9;10\u003e/*\"\n\nLoading descriptor from command-line argument ... success\nSyncing keychain 0 ........... keychain 1 .......... keychain 9 .......... keychain 10 .......... success\nSaving the wallet as 'default' ... success\n\n$ rgb -d .alice utxos\n\nHeight\t   Amount, ṩ\tOutpoint\nbcrt1pn0s2pajhsw38fnpgcj79w3kr3c0r89y3xyekjt8qaudje70g4shs20nwfx\t\u00260/0\n102\t   100000000\td6afd1233f2c3a7228ae2f07d64b2091db0d66f2e8ef169cf01217617f51b8fb:1\n\nLoading descriptor from wallet default ... success\n\nWallet total balance: 100000000 ṩ\n\n```\n\nCreate rgb wallet container for Bob:\n\n```bash\n$ rgb -d .bob create default --tapret-key-only \u003cbob-fixed-xpub-descriptor\u003e\n\nLoading descriptor from command-line argument ... success\nSyncing keychain 0 ........... keychain 1 .......... keychain 9 .......... keychain 10 .......... success\nSaving the wallet as 'default' ... success\n\n$ rgb -d .bob utxos\n\nHeight\t   Amount, ṩ\tOutpoint\nbcrt1plphl407vyfpml2thhypzuqk232256njnaw4zhtmyrrku66pqn9usx4x59h\t\u00260/0\n102\t   100000000\t389bf4b8c31d5dca7e36cffc361a8a020916cb242015e816ccacfa5312be564c:0\n\nLoading descriptor from wallet default ... success\n\nWallet total balance: 100000000 ṩ\n\n```\n\nImport contract for Alice\n\n```\n$ rgb -d .alice import test/rgb20-simplest.rgb\n\nImporting consignment rgb:csg:D6$4UcFP-6siMEPG-z5WedGG-!gfynub-7vIFN93-KGneAc4#parking-agent-parody:\n- validating the contract rgb:2TglHDbZ-!ntHfLf-yLEEFpM-o!sLGAz-Bw84b8m-hXRuSW0 ... success\nConsignment is imported\n```\n\nAfter that, we can inspect contracts state with `rgb state` command.\n\nget the state of the contract for Alice\n\n```bash\n$ rgb -d .alice contracts\nrgb:2TglHDbZ-!ntHfLf-yLEEFpM-o!sLGAz-Bw84b8m-hXRuSW0\tbitcoin            \t2024-06-13\trgb:sch:KzMZV9bO7gFhox97!klj0FonG2ZKnjuOIg2tFChu$YA#lucas-episode-silicon\n  Developer: ssi:anonymous\n$ export RGB20_CONTRACT=\"rgb:2TglHDbZ-!ntHfLf-yLEEFpM-o!sLGAz-Bw84b8m-hXRuSW0\"\n```\n\n_note:  special characters (such as \"**$**\") in RGB20_CONTRACT environment variable will need escaping, i.e.,_\n\n```bash\n$ export RGB20_CONTRACT=\"rgb:vi09buwx-VuXsvVi-VBA9Htw-sL5Vf81-22oM0V1-pxpGi\\$c\"\n                                                                           ↑\t\n```\n\n```bash\n# rgb -d \u003cDATA_DIR\u003e state \u003cCONTRACT_ID\u003e \u003cIFACE\u003e\n$ rgb -d .alice state $RGB20_CONTRACT RGB20Fixed\n\nGlobal:\n  spec := (ticker=(\"TEST\"), name=(\"Test asset\"), details=~, precision=8)\n  terms := (text=(\"\"), media=~)\n  issuedSupply := (100000000000)\n\nOwned:\n  assetOwner:\n    value=adMhBHaQ, utxo=bc:tapret1st:311ec7d43f0f33cda5a0c515a737b5e0bbce3896e6eb32e67db0e868a58f4150:1, witness=~\n```\n\nPrint operation history for Alice\n\n```\n$ rgb -d .alice history $RGB20_CONTRACT\n\nLoading descriptor from wallet default ... success\nOperation\tValue\tSeal\tWitness\nissued\tadMhBHaQ\tbc:tapret1st:311ec7d43f0f33cda5a0c515a737b5e0bbce3896e6eb32e67db0e868a58f4150:1\t~\n```\n\nImport contract For Bob:\n\n```bash\n$ rgb -d .bob import test/rgb20-simplest.rgb\n$ rgb -d .bob contracts\n$ rgb -d .bob state $RGB20_CONTRACT RGB20Fixed\n\nGlobal:\n  spec := (ticker=(\"TEST\"), name=(\"Test asset\"), details=~, precision=8)\n  terms := (text=(\"\"), media=~)\n  issuedSupply := (100000000000)\n\nOwned:\n  assetOwner:\n```\n\nNow we have successfully created an rgb20 token, and the owner\nis `bc:tapret1st:311ec7d43f0f33cda5a0c515a737b5e0bbce3896e6eb32e67db0e868a58f4150:1`, which belongs to Alice.\n\n## Transfer\n\nThere are about five steps in a complete transfer:\n\n1. Create an invoice\n2. Construct a PSBT\n3. Make a transfer\n4. Accept the transfer\n5. Sign the PSBT and broadcast it\n\n### Create an invoice\n\nTo receive 1,000 #Test, Bob needs to create an invoice and send it to Alice.\n\n```bash\n$ rgb -d .bob invoice $RGB20_CONTRACT RGB20Fixed 2000\nrgb:2TglHDbZ-!ntHfLf-yLEEFpM-o!sLGAz-Bw84b8m-hXRuSW0/RGB20Fixed/TadF+bcrt:utxob:4HhkKFP6-92o3r0C-EUCK1DI-k0hamBB-CU9xauX-GhjVSHs-IRESQ\n```\n\n### Make a transfer\n\n```bash\n$ rgb -d .alice transfer \\\n    rgb:2TglHDbZ-!ntHfLf-yLEEFpM-o!sLGAz-Bw84b8m-hXRuSW0/RGB20Fixed/TadF+bcrt:utxob:4HhkKFP6-92o3r0C-EUCK1DI-k0hamBB-CU9xauX-GhjVSHs-IRESQ \\\n    transfer.consignment alice.psbt\n```\n\nThe consignment is saved in the `transfer.consignment` file, and needs to be sent to Bob, who is waiting to accept it.\n\n### Accept transfer\n\nAfter receiving the `transfer.consignment` file, Bob could validate it before accepting.\n\n```bash\n$ rgb -d .bob validate transfer.consignment\nThe provided consignment is valid\n```\n\nBob accepts the consignment:\n\n```bash\n$ rgb -d .bob accept -f transfer.consignment\nTransfer accepted into the stash\n```\n\n### Sign psbt and broadcast it\n\n#### Sign psbt\n\nLet's inspect the psbt file:\n\n```bash\n$ hal psbt decode --regtest alice.psbt\n```\n\n```json\n{\n  \"unsigned_tx\": {\n    \"txid\": \"0fd2b9f690428f751aa381c82cadf52b50ced63616802fe0803cb983d5ac3e1a\",\n    \"wtxid\": \"0fd2b9f690428f751aa381c82cadf52b50ced63616802fe0803cb983d5ac3e1a\",\n    \"size\": 137,\n    \"weight\": 548,\n    \"vsize\": 137,\n    \"version\": 2,\n    \"locktime\": 0,\n    \"inputs\": [\n      {\n        \"prevout\": \"d6afd1233f2c3a7228ae2f07d64b2091db0d66f2e8ef169cf01217617f51b8fb:1\",\n        \"txid\": \"d6afd1233f2c3a7228ae2f07d64b2091db0d66f2e8ef169cf01217617f51b8fb\",\n        \"vout\": 1,\n        \"script_sig\": {\n          \"hex\": \"\",\n          \"asm\": \"\"\n        },\n        \"sequence\": 0,\n        \"witness\": null\n      }\n    ],\n    \"outputs\": [\n      {\n        \"value\": 99997600,\n        \"script_pub_key\": {\n          \"hex\": \"51209aa1750ffc777b77b7a5e92202e75980072afbec58d51c5130d5857445c8ab20\",\n          \"asm\": \"OP_PUSHNUM_1 OP_PUSHBYTES_32 9aa1750ffc777b77b7a5e92202e75980072afbec58d51c5130d5857445c8ab20\",\n          \"type\": \"unknown\",\n          \"address\": \"bcrt1pn2sh2rluwaah0da9ay3q9e6esqrj47lvtr23c5fs6kzhg3wg4vsqldfds2\"\n        }\n      },\n      {\n        \"value\": 2000,\n        \"script_pub_key\": {\n          \"hex\": \"51202925d4a457e5ca1f34a89b93c99a109a330b2a8b1787c6f2acd15bfd67cef02e\",\n          \"asm\": \"OP_PUSHNUM_1 OP_PUSHBYTES_32 2925d4a457e5ca1f34a89b93c99a109a330b2a8b1787c6f2acd15bfd67cef02e\",\n          \"type\": \"unknown\",\n          \"address\": \"bcrt1p9yjaffzhuh9p7d9gnwfunxssngesk25tz7rudu4v69dl6e7w7qhq5x43k5\"\n        }\n      }\n    ],\n    \"total_output_value\": 99999600\n  },\n  \"inputs\": [\n    {\n      \"witness_utxo\": {\n        \"value\": 100000000,\n        \"script_pub_key\": {\n          \"hex\": \"51209be0a0f65783a274cc28c4bc5746c38e1e3394913133692ce0ef1b2cf9e8ac2f\",\n          \"asm\": \"OP_PUSHNUM_1 OP_PUSHBYTES_32 9be0a0f65783a274cc28c4bc5746c38e1e3394913133692ce0ef1b2cf9e8ac2f\",\n          \"type\": \"unknown\",\n          \"address\": \"bcrt1pn0s2pajhsw38fnpgcj79w3kr3c0r89y3xyekjt8qaudje70g4shs20nwfx\"\n        }\n      }\n    }\n  ],\n  \"outputs\": [\n    {},\n    {}\n  ]\n}\n```\n\nNow, it's Alice's turn to sign the PSBT file and broadcast it.\n\nSign the PSBT with sparrow, hal, or bdk-cli.\n\n```shell\n$ bdk-cli -n regtest wallet --descriptor \"tr(tprv8ZgxMBicQKsPeHzjP5LTL818LxwHbJNLZRa98Qdnn7M98fW15365cB1Sz9QZvYufASRKH6JEPhfpxVuFTKMHxDcEAVboqKuZdMmxzKVhMnW/86'/1'/0'/0/*)\" \\ \nsign --psbt $(cat alice.psbt | base64 | tr -d '\\r\\n') | jq -r '.psbt' | base64 --decode \u003e alice.psbt.signed\n\n$ hal psbt finalize alice.psbt.signed\n0200000000010184cc73022f7b19317eb3490f10ef7f0...27921857420c21461a205c5b60ca54c00000000\n```\n\nSet the signed PSBT hex encoding string to SOME_TX in examples/broadcast-tx.rs\n\nAfter broadcasting, mine 1 block.\n\n```\ncargo run --example broadcast-tx\n```\n\n```\ncd \u003cbitlight-local-env-public\u003e\nmake core-cli\nmint 1\n```\n\nAt that time, Bob and Alice would get different outputs with `rgb state` and `rgb validate`.\n\n### Check Alice and Bob's RGB state\n\nFor Alice:\n\n```bash\n$ rgb -d .alice state $RGB20_CONTRACT RGB20Fixed --sync\n\nGlobal:\n  spec := (ticker=(\"TEST\"), name=(\"Test asset\"), details=~, precision=8)\n  terms := (text=(\"\"), media=~)\n  issuedSupply := (100000000000)\n\nOwned:\n  assetOwner:\n    value=99999998000, utxo=bc:tapret1st:ff66b39da83f310fb75db3336c9cf509dfd68ecfb7ea67fa556b5160eafe3a9f:0, witness=bc:ff66b39da83f310fb75db3336c9cf509dfd68ecfb7ea67fa556b5160eafe3a9f\n```\n\n```bash\n$ rgb -d .alice history $RGB20_CONTRACT\n\n```\n\nFor Bob:\n\n```bash\n$ rgb -d .bob state $RGB20_CONTRACT RGB20Fixed --sync\n\nGlobal:\n  spec := (ticker=(\"TEST\"), name=(\"Test asset\"), details=~, precision=8)\n  terms := (text=(\"\"), media=~)\n  issuedSupply := (100000000000)\n\nOwned:\n  assetOwner:\n    value=2000, utxo=bc:tapret1st:04099eb216c8ac6c1767de0c7b6076b2dcabf63583ece8e6f9ccfd6c4cd4a95f:0, witness=bc:ff66b39da83f310fb75db3336c9cf509dfd68ecfb7ea67fa556b5160eafe3a9f\n```\n\n```bash\n$ rgb -d .bob history $RGB20_CONTRACT\n\nLoading descriptor from wallet default ... success\nOperation\tValue\tSeal\tWitness\nreceived\tTadF\tbc:tapret1st:04099eb216c8ac6c1767de0c7b6076b2dcabf63583ece8e6f9ccfd6c4cd4a95f:0\tbc:8d6f2936ef1bb39728821e1af97b950b6941de64450e6fabaec20c8cb0f970a9 (105@1726911117)\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitlightlabs%2Fbitlight-rgb20-contract","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitlightlabs%2Fbitlight-rgb20-contract","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitlightlabs%2Fbitlight-rgb20-contract/lists"}