Power user guidelines

This page will guide through an interaction with RGB smart contracts from a command-line, giving a power user perspective on what the system can do. It is a "baseline guide", abstracted from a specifics of particular wallet or GUI implementations, which may be not updated to the latest RGB version.

  • Using contracts

    First, we'd like to explore how one can add an existing RGB contracts and interact with a current RGB contract state, getting data about owned assets, supply and other information.

    Read more

  • Transfer state

    Second, we will figure out how users can interact with each other in context of a specific RGB smart contract, including how they can do a transfer of assets or other forms of RGB contract state.

    Read more

  • Issue a contract

    Finally, we will demonstrate how to issue a new RGB contracts (including creating assets), which can then be imported by other users. But think twice before producing another token :)

    Read more

This section assumes you have rgb command-line tool already installed. If not, please refer to the installation guidelines.

Using contracts

A contract is distributed as a package, named contract consignment.

Consignment is a term in RGB denoting a package of client-side-validated data passed between peers. Consignments may be of two different types: contract consignments, which distribute public contract information from a contract issuer to users, and transfer consignments, which are used for doing state transfers between contract users. In this chapter we will address the first type of consignments, leaving the second for a next chapter.

RGB stores all data required for its operations in a storage called stash. Since RGB is not a blockchain-based smart contracts, the stash is not replicated to other peer machines and usually keeps the data which nobody else than you know or have access to (at least to some of those data). Thus, losing stash means loosing your assets and contract state, and it has to be backed up with the same effort as a seed phrase or wallet descriptor for a complex wallet setup.

To import a contract into your stash one first needs to get a contract consignment from a contract issuer. A contract consignment is either a binary file – or an ASCII/Base64-armoded text (and example can be found it the "issuing contract" section).

$ rgb import contract.rgb

To list contracts which are part of the stash you need to run rgb commands with no arguments provided (or rgb info as an alternative to this)

$ rgb

Which should output something like

Schemata:
---------
marina-karl-basic-4h3xkAmiRdQs2HwQmnFVqoj5DG3NhGkJRpNZXjNrJT2N: RGB20

Interfaces:
---------
RGB20 complex-field-union-DbwzvSu4BZU81jEpE9FVZ3xjcyuTKWWy2gmdnaxtACrS

Contracts:
---------
rgb:BasilYellowGrand0BgHH3yYaCUvaw5Tc8KfrVB1aWN4vBvCXCuMfK98N3o6Z

Here you see your imported contract id, plus a schema, used by this contract which implements RGB20 interface. Now, you can read the state of the contract through this interface:

$ rgb state BasilYellowGrand0BgHH3yYaCUvaw5Tc8KfrVB1aWN4vBvCXCuMfK98N3o6Z RGB20
Global state:
Nominal:=(ticker=("TEST"), name=("Test asset"), details=~, precision=8)

Owned state:
  (amount=100000000000000, owner=913d9a55efd7748ee89b577328a8f22189432c04275a106c4915cd1dac543562:0, witness=~)

Here you see that the contract has both global state, representing the information about RGB20 token, and an owned state – certain amount of that token assigned to a UTXO.

State transfers

In most of the cases interaction between contract participants happens through invoicing: if Alice wants Bob to do something with the contract state he owns (for instance, send some of the tokens to Alice), she constructs an invoice which contains instructions for Bob on the action he is asked to perform.

Hereinafter we will call Alice, who issues an invoice, a beneficiary, and Bob, who executes the invoice, an actor. We say invoice executing instead of paying the invoice, since invoice may not contain a payment and carry some other form of action (key revocation, casting a vote etc).

Creating an invoice

In RGB, invoicing is much more general than just an invoice for a certain amount of tokens. In fact, you can pack any request for any contract operation, under any possible schema and interface in form of invoice: revoking identity, voting in DAO, performing secondary asset issuance, creating NFT engraving and so on, so on.

To construct an invoice one have to run the following command:

$ rgb invoice $CONTRACT -i $INTERFACE -a $ACTION $STATE $SEAL

Here:

  • $CONTRACT should be a contract id under which the interaction happens
  • $INTERFACE is human-readable interface name which should be used for interacting the contract by both parties, beneficiary and actor. It may be skipped, if the contract schema implements just a single interface.
  • $ACTION is the name of the operation which should be performed by the actor. If it is skipped, it defaults to an operation which declared in the used interface as "default".
  • $STATE provides an information about the state, which should be transferred to the beneficiary single-use-seal defined in the $SEAL parameter. The state mast match state type for the given action, for instance, for a transfer of a fungible token it must be an integer specifying amount of smallest token denominations to be transferred.
  • $SEAL is a definition of a single-use-seal owned by beneficiary; it can be either a UTXO on beneficiary's wallet, or an address. If an address is used then the actor will use it to construct an UTXO in his witness transaction, and this UTXO will be seen and in control of the beneficiary.

An example of the command using RGB20 interface to request a token transfer:

alice$ CONTRACT=DirectDetectEqual0EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW

alice$ MY_UTXO=4960acc21c175c551af84114541eace09c14d3a1bb184809f7b80916f57f9ef8:1

alice$ rgb invoice $CONTRACT -i RGB20 100 $MY_UTXO

The result of this commands would be an invoice printed to STDOUT:

rgb:DirectDetectEqual0EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW
/RGB20/100@6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve

To learn more about invoices please refer to RGB FAQ Website

Performing transfer

To perform a state transfer Bob has to receive an invoice from Alice. We assume that Bob has some command-line wallet tool, which is able to construct, sign and publish normal bitcoin transactions (we will represent this tool with a wallet command).

At the first stage, Bob constructs PSBT file, which must spend outputs containing sufficient amount of RGB assets, plus an output to store a change. We assume that Bob saves PSBT to tx.psbt file.

Now, Bob can pay Alice's invoice (which he saved to $INVOICE variable) with the following command:

bob$ rgb transfer tx.psbt $INVOICE consignment.rgb

The result transfer consignment will be stored to consignment.rgb file in a binary form. Bob should send this file to Alice by some third-party means - this can be an e-mail, some file server – or one of existing RGB-related protocols, like RGB-RPC, Storm (no Lightning network) or something else.

Upon receiving the consignment Alice verifies and accepts it to her local RGB stash (which keeps information about all Alice contracts and owned state) with the following command:

alice$ rgb accept consignment.rgb

If the consignment was invalid, the command will fail and list all problems the consignment had. Otherwise, the command should succeed with a single warning – that the terminal witness transaction is not yet mined. This is due to the fact that Bob hasn't yet published his transaction yet, since he is waiting on Alice approval that she is happy with the transfer.

Upon adding transfer consignment to the stash command will return a signature over the consignment, which Alice can send back to Bob as a form of payslip.

Bob can now check Alice's signature, sign and publish his transaction:

bob$ rgb check <sig> && wallet sign --publish tx.psbt

Alice's RGB wallet will see the witness transaction mined, after which the new state will appear in her user interface.

Issuing contract

To issue a contract you need to write a contract declaration file. Contract declaration can be done in multiple languages, including Rust, YAML, TOML, JSON and future Contractum. Here we will stick with a YAML format as most human-readable:

interface: RGB20

globals:
  Nominal:
    ticker: TEST
    name: Test asset
    details: ~
    precision: 8
  ContractText: >
    SUBJECT TO, AND WITHOUT IN ANY WAY LIMITING, THE REPRESENTATIONS AND WARRANTIES OF ANY SELLER 
    EXPRESSLY SET FORTH IN THIS AGREEMENT OR ANY OTHER EXPRESS OBLIGATION OF SELLERS PURSUANT TO THE
    TERMS HEREOF, AND ACKNOWLEDGING THE PRIOR USE OF THE PROPERTY AND PURCHASER’S OPPORTUNITY 
    TO INSPECT THE PROPERTY, PURCHASER AGREES TO PURCHASE THE PROPERTY “AS IS”, “WHERE IS”, 
    WITH ALL FAULTS AND CONDITIONS THEREON. ANY WRITTEN OR ORAL INFORMATION, REPORTS, STATEMENTS, 
    DOCUMENTS OR RECORDS CONCERNING THE PROPERTY PROVIDED OR MADE AVAILABLE TO PURCHASER, ITS AGENTS
    OR CONSTITUENTS BY ANY SELLER, ANY SELLER’S AGENTS, EMPLOYEES OR THIRD PARTIES REPRESENTING OR
    PURPORTING TO REPRESENT ANY SELLER, SHALL NOT BE REPRESENTATIONS OR WARRANTIES, UNLESS
    SPECIFICALLY SET FORTH HEREIN. IN PURCHASING THE PROPERTY OR TAKING OTHER ACTION HEREUNDER,
    PURCHASER HAS NOT AND SHALL NOT RELY ON ANY SUCH DISCLOSURES, BUT RATHER, PURCHASER SHALL RELY
    ONLY ON PURCHASER’S OWN INSPECTION OF THE PROPERTY AND THE REPRESENTATIONS AND WARRANTIES 
    HEREIN. PURCHASER ACKNOWLEDGES THAT THE PURCHASE PRICE REFLECTS AND TAKES INTO ACCOUNT THAT THE
    PROPERTY IS BEING SOLD “AS IS”.

assignments:
  Assets:
    seal: tapret1st:01d46e52c4bdb51931a0eae83e958c78bdef9cac2057b36d55370410edafdd42:0
    amount: 100000000000000

As you can see, contract definition consists of:

  • specification of the interface used for constructing the contract and parsing provided state
  • global state – in this case specifying token nominal information and giving legal contract test
  • assignments, which assign owned state (issued asset amount) to a single-use-seals, which are bitcoin UTXO prefixed with a type of seals (tapret 1st output).

You compile the contract with the command

$ rgb issue 4h3xkAmiRdQs2HwQmnFVqoj5DG3NhGkJRpNZXjNrJT2N RGB20 examples/rgb20-demo.yaml

Here, we use a default schema for RGB20 assets, which is provided with RGB itself, but one may develop a custom schema as described in programming RGB part of this website. We also specify an interface (RGB20) and provide a YAML file to which we have saved our contract.

The issued contract was added to the stash. You may see it by running

$ rgb info
Schemata:
---------
marina-karl-basic-4h3xkAmiRdQs2HwQmnFVqoj5DG3NhGkJRpNZXjNrJT2N: RGB20 

Interfaces:
---------
RGB20 complex-field-union-DbwzvSu4BZU81jEpE9FVZ3xjcyuTKWWy2gmdnaxtACrS

Contracts:
---------
rgb:BasilYellowGrand0BgHH3yYaCUvaw5Tc8KfrVB1aWN4vBvCXCuMfK98N3o6Z

To distribute contract to other users you have to export it in a form of contract consignment. This consignment may be a binary file - or ASCII/Base64 armored text, such that it can be sent via messengers or by an e-mail (or even put into a dynamic QR code).

$ rgb export -a BasilYellowGrand0BgHH3yYaCUvaw5Tc8KfrVB1aWN4vBvCXCuMfK98N3o6Z

We provide an -a option before the contract id to use ASCII armoring. If we do not provide a file name as a last argument, the contract is exported to the standard output of the terminal:

----- BEGIN RGB CONTRACT -----
Id: BgHH3yYaCUvaw5Tc8KfrVB1aWN4vBvCXCuMfK98N3o6Z
Checksum: basil-yellow-grand

AQAAAAACAAAqtIS1DeMje22cf/4RnKx+xPCNaqxfFqvWGhpQNPOrpAEAAQDw06ivRjpjzvxKOiEt
SfSRNwdqeH5viPmGMD0IY93KMAEAAQAAAQgAxr3uYkgVMfD14HWM2mhgU8BQxPxK0SGaXFuOW/3B
trECAAABAAEAAQABAAEAAQAAAQD//wAAAQAAxr3uYkgVMfD14HWM2mhgU8BQxPxK0SGaXFuOW/3B
trEAAQAAAQD//wEAAAEA//8ADwAAIoM2c5ybCMor86xCND2RseewiCxZlc49r51r9H/TA0UBC1JH
QkNvbnRyYWN0DENvbnRyYWN0TmFtZQUB5YDcz29OYj8l60N4tNmXBXNso2tmZhosAPikieRyt6sq
tIS1DeMje22cf/4RnKx+xPCNaqxfFqvWGhpQNPOrpAELUkdCQ29udHJhY3QHTm9taW5hbAYEBnRp
Y2tlcpLnXKh6DUXvMZ3Zc5AtjaLSaC5MfiPfR5v+e+hCmDUGBG5hbWUigzZznJsIyivzrEI0PZGx
57CILFmVzj2vnWv0f9MDRQdkZXRhaWxzNlYTwDFDkvlzaxCwNmRv+WzqeIWhnBnyDfvUtmQDTkoJ
cHJlY2lzaW9uykNH38AFMQoa5Vkrfdbz6TZF5SMTBfvpku8zziza4x42VhPAMUOS+XNrELA2ZG/5
bOp4haGcGfIN+9S2ZANOSgAEAgAEbm9uZca97mJIFTHw9eB1jNpoYFPAUMT8StEhmlxbjlv9wbax
AQRzb21l0KC6y1ZHRS3FNas6lTWmmaVfqG/yORKXGb8uUARjlBQ+VY/6Dww4withvk0RC4k2lNUc
U0xwbzSK8xMlHskDNgAIYc2QPfO0+7TYKNNcU/l24/gdyeEYILKqdmYeTSiiVRAAAAAAAAAAAP//
AAAAAAAARG+7cbgnA35t9/gdg4KINl4VK6TcQG1qQ5INyYpsbyUACGHNkD3ztPu02CjTXFP5duP4
HcnhGCCyqnZmHk0oolUQKAAAAAAAAAD/AAAAAAAAAFV37iE4le7TpKToItt89gePS14g13JwujwQ
v4lzxs1LAANgA18zMiADXzMzIQNfMzQiA18zNSMDXzM2JANfMzclA18zOCYDXzM5JwNfNDAoA180
MSkDXzQyKgNfNDMrA180NCwDXzQ1LQNfNDYuA180Ny8DXzQ4MANfNDkxA181MDIDXzUxMwNfNTI0
A181MzUDXzU0NgNfNTU3A181NjgDXzU3OQNfNTg6A181OTsDXzYwPANfNjE9A182Mj4DXzYzPwNf
NjRAA182NUEDXzY2QgNfNjdDA182OEQDXzY5RQNfNzBGA183MUcDXzcySANfNzNJA183NEoDXzc1
SwNfNzZMA183N00DXzc4TgNfNzlPA184MFADXzgxUQNfODJSA184M1MDXzg0VANfODVVA184NlYD
Xzg3VwNfODhYA184OVkDXzkwWgNfOTFbA185MlwDXzkzXQNfOTReA185NV8DXzk2YANfOTdhA185
OGIDXzk5YwRfMTAwZARfMTAxZQRfMTAyZgRfMTAzZwRfMTA0aARfMTA1aQRfMTA2agRfMTA3awRf
MTA4bARfMTA5bQRfMTEwbgRfMTExbwRfMTEycARfMTEzcQRfMTE0cgRfMTE1cwRfMTE2dARfMTE3
dQRfMTE4dgRfMTE5dwRfMTIweARfMTIxeQRfMTIyegRfMTIzewRfMTI0fARfMTI1fQRfMTI2fgRf
MTI3f1zQw8DbZ34iXVDAzVWjj9KnnTop1iXjT3jf1hZsPLgGAAhVd+4hOJXu06Sk6CLbfPYHj0te
INdycLo8EL+Jc8bNSwEAAAAAAAAACAAAAAAAAABhzZA987T7tNgo01xT+Xbj+B3J4Rggsqp2Zh5N
KKJVEAABb8aWNwahCDQgGejxadp+9IqPQ8ioGIMkRvPuF6i1ObwBC1JHQkNvbnRyYWN0D0NvbnRy
YWN0RGV0YWlscwUBRG+7cbgnA35t9/gdg4KINl4VK6TcQG1qQ5INyYpsbyWS51yoeg1F7zGd2XOQ
LY2i0mguTH4j30eb/nvoQpg1BgELUkdCQ29udHJhY3QGVGlja2VyBQFc0MPA22d+Il1QwM1Vo4/S
p506KdYl409439YWbDy4Bsa97mJIFTHw9eB1jNpoYFPAUMT8StEhmlxbjlv9wbaxAAAAykNH38AF
MQoa5Vkrfdbz6TZF5SMTBfvpku8zziza4x4BC1JHQkNvbnRyYWN0CVByZWNpc2lvbgMRC2luZGl2
aXNpYmxlAARkZWNpAQVjZW50aQIFbWlsbGkDBW1pY3JvBglkZWNpTWljcm8HCmNlbnRpTWljcm8I
BG5hbm8JCGRlY2lOYW5vCgljZW50aU5hbm8LBHBpY28MCGRlY2lQaWNvDQljZW50aVBpY28OBWZl
bXRvDwlkZWNpRmVtdG8QCmNlbnRpRmVtdG8RBGF0dG8S0KC6y1ZHRS3FNas6lTWmmaVfqG/yORKX
Gb8uUARjlBQABQFvxpY3BqEINCAZ6PFp2n70io9DyKgYgyRG8+4XqLU5vOWA3M9vTmI/JetDeLTZ
lwVzbKNrZmYaLAD4pInkcrerAAhhzZA987T7tNgo01xT+Xbj+B3J4Rggsqp2Zh5NKKJVEAUAAAAA
AAAAKAAAAAAAAADw06ivRjpjzvxKOiEtSfSRNwdqeH5viPmGMD0IY93KMAELUkdCQ29udHJhY3QM
Q29udHJhY3RUZXh0BQE+VY/6Dww4withvk0RC4k2lNUcU0xwbzSK8xMlHskDNgABDieh3fpTsCEB
UDTfigOMqoQNnWUf0itqpviSlmrfVn4MAANSR0IDANAAAAAAAAEABAAADieh3fpTsCEBUDTfigOM
qoQNnWUf0itqpviSlmrfVn4AAAGWwcTJa9GZ/1ploGCamFxyZysjojs4MmiJQPGX4wL3AQVSR0Iy
MAIMQ29udHJhY3RUZXh0AfDTqK9GOmPO/Eo6IS1J9JE3B2p4fm+I+YYwPQhj3cowAQdOb21pbmFs
ASq0hLUN4yN7bZx//hGcrH7E8I1qrF8Wq9YaGlA086ukAQEGQXNzZXRzAAIAAAIMQ29udHJhY3RU
ZXh0AQABAAdOb21pbmFsAQABAAEGQXNzZXRzAQD//wABCFRyYW5zZmVyAAABBkFzc2V0cwEA//8B
BkFzc2V0cwEA//8AAQZBc3NldHMAAQhUcmFuc2ZlcjbVpCrKcaQDIWfTc4Sl6JvDFJkaRvimk4G0
iH28yGhPlsHEyWvRmf9aZaBgmphccmcrI6I7ODJoiUDxl+MC9wECAAAHTm9taW5hbAEADENvbnRy
YWN0VGV4dAEAAAZBc3NldHMAAQAACFRyYW5zZmVyAAAAADbVpCrKcaQDIWfTc4Sl6JvDFJkaRvim
k4G0iH28yGhPgwAAAgAAAQASAARURVNUClRlc3QgYXNzZXQACAEAAQACAAAAAQAAAQEAAwFiNVSs
Hc0VSWwQWicELEOJIfKoKHNXm+iOdNfvVZo9kQAAAAA9qe0Y5e3D8QgAQHoQ81oAAHvqdgO4GMt1
N/GyBwEZNIJHD4eLef1tItTO/SxpB6mwAAAAAAAAAAAAAAAAAAA=

----- END RGB CONTRACT -----