Skip to content

Commit

Permalink
add CFA schema + merge terms with media
Browse files Browse the repository at this point in the history
  • Loading branch information
zoedberg committed Jun 29, 2023
1 parent 124157d commit d9c39b0
Show file tree
Hide file tree
Showing 30 changed files with 884 additions and 390 deletions.
21 changes: 11 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ readme = "README.md"

[dependencies]
amplify = "4.0.0"
strict_encoding = "2.2.0"
strict_types = "1.2.0"
strict_encoding = "2.3.0"
strict_types = "1.3.0"
aluvm = "0.10.2"
bp-core = "0.10.3"
bp-core = "0.10.4"
rgb-std = { version = "0.10.2", features = ["serde", "fs"] }
serde = "1.0.152"
serde_json = "1.0.93"
sha2 = "0.10.7"

[features]
all=[]
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
[![Apache-2 licensed](https://img.shields.io/crates/l/rgb-schemata)](./LICENSE)

This repository provides rust source code and compiled versions of RGB
contract schemata recommended for the use by contract developers.
contract schemata recommended for the use by contract developers.

RGB is confidential & scalable client-validated smart contracts for Bitcoin &
Lightning. To learn more about RGB please check [RGB blueprint][Blueprint] and
Expand All @@ -24,14 +24,16 @@ This repository provides the following RGB schemata:

* __Non-inflatable assets (NIA)__, implementing RGB20 interface.
This is the simplest form of a fungible asset/token, which doesn't provide
such features as secondary issue, ability to change asset name and
such features as secondary issue, ability to change asset name and
parameters, ability to burn or replace the asset.

* __Unique digital asset (UDA)__, implementing RGB21 interface.
This is the simplest form of an NFT, which has one issuance of a single
non-fungible and non-fractionable token with a representative attached
This is the simplest form of an NFT, which has one issuance of a single
non-fungible and non-fractionable token with a representative attached
media file and a preview.

* __Collectible fungible assets (CFA)__, implementing RGB25 interface.
This is the simplest form of collectible fungible assets

## Library

Expand Down
Binary file modified examples/rgb20-simplest.contract.rgb
Binary file not shown.
25 changes: 15 additions & 10 deletions examples/rgb20-token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use amplify::hex::FromHex;
use bp::{Chain, Outpoint, Tx, Txid};
use rgb_schemata::{nia_rgb20, nia_schema};
use rgbstd::containers::BindleContent;
use rgbstd::interface::rgb20::Amount;
use rgbstd::interface::{rgb20, ContractBuilder, FungibleAllocation, Rgb20};
use rgbstd::persistence::{Inventory, Stock};
use rgbstd::resolvers::ResolveHeight;
use rgbstd::stl::{DivisibleAssetSpec, Precision, RicardianContract, Timestamp};
use rgbstd::stl::{
Amount, ContractData, DivisibleAssetSpec, Precision, RicardianContract, Timestamp,
};
use rgbstd::validation::{ResolveTx, TxResolverError};
use strict_encoding::StrictDumb;

Expand All @@ -27,14 +28,18 @@ impl ResolveHeight for DumbResolver {
fn main() {
let spec = DivisibleAssetSpec::new("TEST", "Test asset", Precision::CentiMicro);
let terms = RicardianContract::default();
let contract_data = ContractData {
terms,
media: None,
};
let created = Timestamp::default();
let beneficiary = Outpoint::new(
Txid::from_hex("623554ac1dcd15496c105a27042c438921f2a82873579be88e74d7ef559a3d91").unwrap(),
Txid::from_hex("623554ac1dcd15496c105a27042c438921f2a82873579be88e74d7ef559a3d91").unwrap(),
0
);

const ISSUE: u64 = 1_000_000_0000_0000;
const ISSUE: u64 = 1_000_000_000_000;

let contract = ContractBuilder::with(
rgb20(),
nia_schema(),
Expand All @@ -50,11 +55,11 @@ fn main() {

.add_global_state("issuedSupply", Amount::from(ISSUE))
.expect("invalid issued supply")
.add_global_state("terms", terms)

.add_global_state("data", contract_data)
.expect("invalid contract text")

.add_fungible_state("beneficiary", beneficiary, ISSUE)
.add_fungible_state("assetOwner", beneficiary, ISSUE)
.expect("invalid asset amount")

.issue_contract()
Expand Down Expand Up @@ -85,9 +90,9 @@ fn main() {
// Reading contract state through the interface from the stock:
let contract = stock.contract_iface(contract_id, rgb20().iface_id()).unwrap();
let contract = Rgb20::from(contract);
let allocations = contract.fungible("beneficiary", &None).unwrap();
let allocations = contract.fungible("assetOwner", &None).unwrap();
eprintln!("{}", serde_json::to_string(&contract.spec()).unwrap());

for FungibleAllocation { owner, witness, value } in allocations {
eprintln!("amount={value}, owner={owner}, witness={witness}");
}
Expand Down
Binary file modified examples/rgb21-simplest.contract.rgb
Binary file not shown.
8 changes: 4 additions & 4 deletions examples/rgb21-token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ fn main() {
let terms = RicardianContract::default();
let created = Timestamp::default();
let beneficiary = Outpoint::new(
Txid::from_hex("623554ac1dcd15496c105a27042c438921f2a82873579be88e74d7ef559a3d91").unwrap(),
Txid::from_hex("623554ac1dcd15496c105a27042c438921f2a82873579be88e74d7ef559a3d91").unwrap(),
0
);

let fraction = OwnedFraction::from_inner(1);
let index = TokenIndex::from_inner(2);

let preview = EmbeddedMedia {
ty: stl::MediaType::with("text/*"),
data: SmallBlob::try_from_iter(vec![0, 0]).expect("invalid data"),
ty: stl::MediaType::with("text/*"),
data: SmallBlob::try_from_iter(vec![0, 0]).expect("invalid data"),
};

let token_data = TokenData { index, preview: Some(preview), ..Default::default() };
Expand All @@ -65,7 +65,7 @@ fn main() {
.add_global_state("terms", terms)
.expect("invalid contract text")

.add_data_state("beneficiary", beneficiary, allocation)
.add_data_state("assetOwner", beneficiary, allocation)
.expect("invalid asset blob")

.issue_contract()
Expand Down
Binary file added examples/rgb25-simplest.contract.rgb
Binary file not shown.
117 changes: 117 additions & 0 deletions examples/rgb25-token.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use std::convert::Infallible;

use amplify::hex::FromHex;
use bp::{Chain, Outpoint, Tx, Txid};
use rgb_schemata::{cfa_rgb25, cfa_schema};
use rgbstd::containers::BindleContent;
use rgbstd::interface::{rgb25, ContractBuilder, FungibleAllocation};
use rgbstd::persistence::{Inventory, Stock};
use rgbstd::resolvers::ResolveHeight;
use rgbstd::stl::{
Amount, Attachment, ContractData, Details, MediaType, Name, Precision, RicardianContract,
Timestamp,
};
use rgbstd::validation::{ResolveTx, TxResolverError};
use sha2::{Digest, Sha256};
use strict_encoding::StrictDumb;

struct DumbResolver;

impl ResolveTx for DumbResolver {
fn resolve_tx(&self, _txid: Txid) -> Result<Tx, TxResolverError> { Ok(Tx::strict_dumb()) }
}

impl ResolveHeight for DumbResolver {
type Error = Infallible;
fn resolve_height(&mut self, _txid: Txid) -> Result<u32, Self::Error> { Ok(0) }
}

#[rustfmt::skip]
fn main() {
let name = Name::try_from("Test asset").unwrap();
let details = Details::try_from("details with ℧nicode characters").unwrap();
let precision = Precision::CentiMicro;
let terms = RicardianContract::default();
let file_bytes = std::fs::read("README.md").unwrap();
let mut hasher = Sha256::new();
hasher.update(file_bytes);
let file_hash = hasher.finalize();
let media = Some(Attachment {
ty: MediaType::with("text/*"),
digest: file_hash.into(),
});
let contract_data = ContractData {
terms,
media,
};
let created = Timestamp::default();
let beneficiary = Outpoint::new(
Txid::from_hex("623554ac1dcd15496c105a27042c438921f2a82873579be88e74d7ef559a3d91").unwrap(),
0
);

const ISSUE: u64 = 1_000_000_000_000;

let contract = ContractBuilder::with(
rgb25(),
cfa_schema(),
cfa_rgb25()
).expect("schema fails to implement RGB25 interface")

.set_chain(Chain::Testnet3)
.add_global_state("name", name)
.expect("invalid name")

.add_global_state("details", details)
.expect("invalid details")

.add_global_state("precision", precision)
.expect("invalid precision")

.add_global_state("created", created)
.expect("invalid created")

.add_global_state("issuedSupply", Amount::from(ISSUE))
.expect("invalid issuedSupply")

.add_global_state("data", contract_data)
.expect("invalid contract data")

.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();
eprintln!("{bindle}");
bindle.save("examples/rgb25-simplest.contract.rgb").expect("unable to save contract");

// Let's create some stock - an in-memory stash and inventory around it:
let mut stock = Stock::default();
stock.import_iface(rgb25()).unwrap();
stock.import_schema(cfa_schema()).unwrap();
stock.import_iface_impl(cfa_rgb25()).unwrap();

// Noe we verify our contract consignment and add it to the stock
let verified_contract = match bindle.unbindle().validate(&mut DumbResolver) {
Ok(consignment) => consignment,
Err(consignment) => {
panic!("can't produce valid consignment. Report: {}", consignment.validation_status().expect("status always present upon validation"));
}
};
stock.import_contract(verified_contract, &mut DumbResolver).unwrap();

// Reading contract state through the interface from the stock:
let contract = stock.contract_iface(contract_id, rgb25().iface_id()).unwrap();
let name = contract.global("name").unwrap();
let allocations = contract.fungible("assetOwner", &None).unwrap();
eprintln!("{}", Name::from_strict_val_unchecked(&name[0]));

for FungibleAllocation { owner, witness, value } in allocations {
eprintln!("(amount={value}, owner={owner}, witness={witness})");
}
}
Binary file modified interfaces/RGB20.rgb
Binary file not shown.
50 changes: 25 additions & 25 deletions interfaces/RGB20.rgba
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
-----BEGIN RGB INTERFACE-----
Id: BR2fhPEKPtsjoEz2PDpBV4o24HCjvD1Dk4nHnaRx94fQ
Id: 4CXiewut3xPYxYusN3PhwjawdLnMhZw7hpiVSJUcCHaU
Name: RGB20

AAVSR0IyMAYMYnVybmVkU3VwcGx5AYiMWGVjOvE7lbfNGo2K8trB3BQLl3JR2dTa
88dRHI6EAAEHY3JlYXRlZAFZbno6DqNlnhAw8YtNZaO5E+5YUAf8914Lts3BacHA
OwEADGlzc3VlZFN1cHBseQGIjFhlYzrxO5W3zRqNivLawdwUC5dyUdnU2vPHURyO
hAEBDnJlcGxhY2VkU3VwcGx5AYiMWGVjOvE7lbfNGo2K8trB3BQLl3JR2dTa88dR
HI6EAAEEc3BlYwGZYk235CaSmVSTLt/I0melUpcCKTzVq8BWTm8iWzP68QEABXRl
cm1zARjLlG8Sk88YDp143MZbxZtHL//+rfv1jbGYzIMo9ksBAQAFCmFzc2V0T3du
ZXICAAABCWJ1cm5FcG9jaAEBAAAJYnVyblJpZ2h0AQEAARJpbmZsYXRpb25BbGxv
d2FuY2UCAQABC3VwZGF0ZVJpZ2h0AQEAAAABRnusgTmx9RP9N7MedEWdhgqy9nAz
2prUcubaPR/zinsEB2NyZWF0ZWQAAQABAAxpc3N1ZWRTdXBwbHkAAQABAARzcGVj
AAEAAQAFdGVybXMAAQABAAQKYXNzZXRPd25lcgAAAP//CWJ1cm5FcG9jaAAAAAEA
EmluZmxhdGlvbkFsbG93YW5jZQAAAP//C3VwZGF0ZVJpZ2h0AAAAAQAAAwEDBAYE
QnVybgEBMY7KoHKHC9lSMKlRWmqqFJgrrJ4/sV6iUo6wQFInp6EBDGJ1cm5lZFN1
cHBseQABAAEAAQR1c2VkAQlidXJuUmlnaHQBAAEAAQZmdXR1cmUBCWJ1cm5SaWdo
dAAAAQAAAwEDBQAFSXNzdWUBAUZ7rIE5sfUT/TezHnRFnYYKsvZwM9qa1HLm2j0f
84p7AQxpc3N1ZWRTdXBwbHkAAQABAAEEdXNlZAESaW5mbGF0aW9uQWxsb3dhbmNl
AQD//wILYmVuZWZpY2lhcnkBCmFzc2V0T3duZXIAAP//BmZ1dHVyZQESaW5mbGF0
aW9uQWxsb3dhbmNlAAD//wAEAQMEBgELYmVuZWZpY2lhcnkJT3BlbkVwb2NoAQAA
AQR1c2VkAQlidXJuRXBvY2gBAAEAAglidXJuUmlnaHQAAQABAARuZXh0AQlidXJu
RXBvY2gAAAEAAAABCWJ1cm5SaWdodAZSZW5hbWUBAAEDbmV3AQRzcGVjAQABAAEE
dXNlZAELdXBkYXRlUmlnaHQBAAEAAQZmdXR1cmUBC3VwZGF0ZVJpZ2h0AAABAAAA
AQZmdXR1cmUHUmVwbGFjZQEBMY7KoHKHC9lSMKlRWmqqFJgrrJ4/sV6iUo6wQFIn
p6EBDnJlcGxhY2VkU3VwcGx5AAEAAQABBHVzZWQBCWJ1cm5SaWdodAEAAQACC2Jl
bmVmaWNpYXJ5AQphc3NldE93bmVyAAD//wZmdXR1cmUBCWJ1cm5SaWdodAAAAQAA
BAECAwUBC2JlbmVmaWNpYXJ5CFRyYW5zZmVyAAAAAQhwcmV2aW91cwEKYXNzZXRP
d25lcgEA//8BC2JlbmVmaWNpYXJ5AQphc3NldE93bmVyAQD//wABAgELYmVuZWZp
Y2lhcnkAoYeej1a91v2MoyO5TzngYGQ6ppo5IZGU1gxMinx7AcgBCFRyYW5zZmVy
OwEABGRhdGEBHUILZdBBGlIYHYsC89qDqplVfYLTs7sHm15bzCA8M+MBAAxpc3N1
ZWRTdXBwbHkBiIxYZWM68TuVt80ajYry2sHcFAuXclHZ1Nrzx1EcjoQBAQ5yZXBs
YWNlZFN1cHBseQGIjFhlYzrxO5W3zRqNivLawdwUC5dyUdnU2vPHURyOhAABBHNw
ZWMBmWJNt+QmkplUky7fyNJnpVKXAik81avAVk5vIlsz+vEBAAUKYXNzZXRPd25l
cgIAAAEJYnVybkVwb2NoAQEAAAlidXJuUmlnaHQBAQABEmluZmxhdGlvbkFsbG93
YW5jZQIBAAELdXBkYXRlUmlnaHQBAQAAAAFGe6yBObH1E/03sx50RZ2GCrL2cDPa
mtRy5to9H/OKewQHY3JlYXRlZAABAAEABGRhdGEAAQABAAxpc3N1ZWRTdXBwbHkA
AQABAARzcGVjAAEAAQAECmFzc2V0T3duZXIAAAD//wlidXJuRXBvY2gAAAABABJp
bmZsYXRpb25BbGxvd2FuY2UAAAD//wt1cGRhdGVSaWdodAAAAAEAAAMBAwQGBEJ1
cm4BATGOyqByhwvZUjCpUVpqqhSYK6yeP7FeolKOsEBSJ6ehAQxidXJuZWRTdXBw
bHkAAQABAAEEdXNlZAEJYnVyblJpZ2h0AQABAAEGZnV0dXJlAQlidXJuUmlnaHQA
AAEAAAMBAwUABUlzc3VlAQFGe6yBObH1E/03sx50RZ2GCrL2cDPamtRy5to9H/OK
ewEMaXNzdWVkU3VwcGx5AAEAAQABBHVzZWQBEmluZmxhdGlvbkFsbG93YW5jZQEA
//8CC2JlbmVmaWNpYXJ5AQphc3NldE93bmVyAAD//wZmdXR1cmUBEmluZmxhdGlv
bkFsbG93YW5jZQAA//8ABAEDBAYBC2JlbmVmaWNpYXJ5CU9wZW5FcG9jaAEAAAEE
dXNlZAEJYnVybkVwb2NoAQABAAIJYnVyblJpZ2h0AAEAAQAEbmV4dAEJYnVybkVw
b2NoAAABAAAAAQlidXJuUmlnaHQGUmVuYW1lAQABA25ldwEEc3BlYwEAAQABBHVz
ZWQBC3VwZGF0ZVJpZ2h0AQABAAEGZnV0dXJlAQt1cGRhdGVSaWdodAAAAQAAAAEG
ZnV0dXJlB1JlcGxhY2UBATGOyqByhwvZUjCpUVpqqhSYK6yeP7FeolKOsEBSJ6eh
AQ5yZXBsYWNlZFN1cHBseQABAAEAAQR1c2VkAQlidXJuUmlnaHQBAAEAAgtiZW5l
ZmljaWFyeQEKYXNzZXRPd25lcgAA//8GZnV0dXJlAQlidXJuUmlnaHQAAAEAAAQB
AgMFAQtiZW5lZmljaWFyeQhUcmFuc2ZlcgAAAAEIcHJldmlvdXMBCmFzc2V0T3du
ZXIBAP//AQtiZW5lZmljaWFyeQEKYXNzZXRPd25lcgEA//8AAQIBC2JlbmVmaWNp
YXJ5AKGHno9Wvdb9jKMjuU854GBkOqaaOSGRlNYMTIp8ewHIAQhUcmFuc2Zlcg==


-----END RGB INTERFACE-----
Binary file added interfaces/RGB25.rgb
Binary file not shown.
Loading

0 comments on commit d9c39b0

Please sign in to comment.