diff --git a/content/program/rust/contract.md b/content/program/rust/contract.md index 2559002..fcc0e68 100644 --- a/content/program/rust/contract.md +++ b/content/program/rust/contract.md @@ -5,36 +5,121 @@ title = "Writing simple contract" anchor = "basics" +++ +Firstly, using cargo to create a new project: `cargo new rgb20-token`, and enter +it: `cd rgb20-token`. Then create a directory to store the contract file. You may +name it whatever you like, here we set it to `contracts`: `mkdir contracts`. +See source codes at [RGB20-Token](https://github.com/oneforalone/rgb20-usdt). + +Here is the complete project file tree: +``` +➜ rgb20-token git:(main) ✗ tree . +. +├── Cargo.lock +├── Cargo.toml +├── contracts +└── src + └── main.rs + +3 directories, 3 files +``` + +Secondly, we add some libs in `Cargo.toml` file: + +```toml +[denpendencies] +amplify = "4.0.1" +strict_encoding = "2.5.0" +strict_types = "1.6.1" +bp-core = "0.10.9" +rgb-std = { version = "0.10.8", features = ["serde", "fs"] } +serde = "1.0.152" +serde_json = "1.0.93" +rgb-schemata = "0.10.0" +``` + +Then, in `src/main.rs`, write following codes: + ```rust - let nominal = Nominal::new("TEST", "Test asset", Precision::CentiMicro); - let contract_text = ContractText::default(); - let beneficiary = Outpoint::new( - Txid::from_hex("623554ac1dcd15496c105a27042c438921f2a82873579be88e74d7ef559a3d91").unwrap(), - 0 - ); - - let contract = ContractBuilder::with( - rgb20(), - schema(), - iface_impl() - ).expect("schema fails to implement RGB20 interface") +use rgbstd::interface::{rgb20, ContractBuilder}; - .set_chain(Chain::Testnet3) +use std::convert::Infallible; +use std::fs; - .add_global_state("Nominal", nominal) - .expect("invalid nominal") +use amplify::hex::FromHex; +use bp::{Chain, Outpoint, Tx, Txid}; +use rgb_schemata::{nia_rgb20, nia_schema}; +use rgbstd::containers::BindleContent; +use rgbstd::contract::WitnessOrd; +use rgbstd::resolvers::ResolveHeight; +use rgbstd::stl::{ + Amount, ContractData, DivisibleAssetSpec, Precision, RicardianContract, Timestamp, +}; +use rgbstd::validation::{ResolveTx, TxResolverError}; +use strict_encoding::StrictDumb; - .add_global_state("ContractText", contract_text) - .expect("invalid contract text") +struct DumbResolver; - .add_fungible_state("Assets", beneficiary, 1_000_000_0000_0000) - .expect("invalid asset amount") +impl ResolveTx for DumbResolver { + fn resolve_tx(&self, _txid: Txid) -> Result { + Ok(Tx::strict_dumb()) + } +} + +impl ResolveHeight for DumbResolver { + type Error = Infallible; + fn resolve_height(&mut self, _txid: Txid) -> Result { + Ok(WitnessOrd::OffChain) + } +} + +#[rustfmt::skip] +fn main() { + let name = "Token"; // name of token + let decimal = Precision::CentiMicro; // Decimal: 8 + let desc = "RGB Token"; // token description + let spec = DivisibleAssetSpec::with("RGB20", name, decimal, Some(desc)).unwrap(); + let terms = RicardianContract::default(); + let contract_data = ContractData { terms, media: None }; + let created = Timestamp::now(); + let txid = "9fef7f1c9cd1dd6b9ac5c0a050103ad874346d4fdb7bcf954de2dfe64dd2ce05"; + // token owner address in utxo + let beneficiary = Outpoint::new(Txid::from_hex(txid).unwrap(), 0); + const ISSUE: u64 = 1_000_000_000; + + let contract = ContractBuilder::with(rgb20(), nia_schema(), nia_rgb20()) + .expect("schema fails to implement RGB20 interface") + .set_chain(Chain::Testnet3) + .add_global_state("spec", spec) + .expect("invalid nominal") + .add_global_state("created", created) + .expect("invalid creation date") + .add_global_state("issuedSupply", Amount::from(ISSUE)) + .expect("invalid issued supply") + .add_global_state("data", contract_data) + .expect("invalid contract text") + .add_fungible_state("assetOwner", beneficiary, ISSUE) + .expect("invalid asset amount") .issue_contract() .expect("contract doesn't fit schema requirements"); let contract_id = contract.contract_id(); + debug_assert_eq!(contract_id, contract.contract_id()); let bindle = contract.bindle(); - bindle.save("examples/rgb20-simplest.contract.rgb").expect("unable to save contract"); + eprintln!("{bindle}"); + bindle.save("contracts/rgb20-token.contract.rgb") + .expect("unable to save contract"); + fs::write("contracts/rgb20-token.contract.rgba", bindle.to_string()) + .expect("unable to save contract"); +} + ``` + +Save it, and execute `cargo run`, after that, contract file would save in +`contracts` directory. You can specify your own token name, decimal, +description, beneficiary and supply by modifing corresponding variable's value, +as well as contracts saving fold. + +Now, you can import the contract with `rgb import` command: +`rgb import contracts/rgb20-token.contract.rgb`.