Skip to content

Commit 48f9376

Browse files
committed
fix permill issues in the calls when the spawning method when a new frunique is been created
update test to handle the new data add new helper functions to create a frunique
1 parent 327f6a4 commit 48f9376

File tree

5 files changed

+43
-15
lines changed

5 files changed

+43
-15
lines changed

pallets/fruniques/README.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
### **FR**actional **Uniques**
33
> This is WIP - just being spec'd out
44
5-
This pallet is being developed **tightly coupled** to both [`pallet_assets`](https://paritytech.github.io/substrate/latest/pallet_assets/) and [`pallet_uniques`](https://paritytech.github.io/substrate/latest/pallet_uniques/index.html). These are the default [Statemine](https://github.com/paritytech/cumulus/tree/master/polkadot-parachains/statemine) pallets for fungible and non-fungible tokens.
5+
This pallet is being developed **tightly coupled** to both [`pallet_assets`](https://paritytech.github.io/substrate/latest/pallet_assets/) and [`pallet_uniques`](https://paritytech.github.io/substrate/latest/pallet_uniques/index.html). These are the default [Statemine](https://github.com/paritytech/cumulus/tree/master/polkadot-parachains/statemine) pallets for fungible and non-fungible tokens.
66

77
A Frunique is a type of Non-Fungible Token (NFT)
88

@@ -19,20 +19,20 @@ This pallet provides functionality that allows NFT holders to mint a fungible to
1919

2020
The non-fungible token is created and minted using the Statemine `pallet_uniques`.
2121

22-
The fungible token is created and minted using the Statemine `pallet_assets`.
22+
The fungible token is created and minted using the Statemine `pallet_assets`.
2323

2424
The NFT/Unique can be unlocked and released if and only if a single origin holds all of the corresponding fungible token.
2525

2626
![basket-of-fungibles](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/hashed-io/hashed-substrate/main/docs/fungible-basket-frunique.iuml)
2727

2828
## NFT <--> NFTs
29-
An NFT as a trie of NFTs.
29+
An NFT as a trie of NFTs.
3030

3131
### Use cases
3232
#### Tax credit marketplace
3333
A credit is a single NFT, with an `amount`, state of redemption, expiration year, and other metadata. However, that owner can sell less than the `amount`, in which case the newly created credit NFT has all of the same associated data. The sum of the children `amount` values must be equal to the parent.
3434

35-
To support this, we'll create a `AggregatedFrunique` type that enforces the aggregation rules.
35+
To support this, we'll create a `AggregatedFrunique` type that enforces the aggregation rules.
3636

3737
#### Cannabis compliance
3838
For the NY state cannabis compliance program, all yield from all plants must be tracked. This aligns to a very similar data structure as above. Each mother plant is an NFT, each clone as an NFT, each package of flower an NFT, etc. Auditing a specific item is fairly easy via traversing all of its ancestors and descendants through to the harvest and dispensary.
@@ -58,7 +58,7 @@ yarn install
5858
```bash
5959
yarn run:api tx.fruniques.create 1 1 1 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY 1 100 --seed "//Alice"
6060
```
61-
## Check NFT
61+
## Check NFT
6262
```bash
6363
yarn run:api query.uniques.class 1
6464
yarn run:api query.uniques.asset 1 1
@@ -71,9 +71,16 @@ yarn run:api query.assets.asset 1
7171
yarn run:api query.assets.account 1 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
7272
```
7373

74+
## Tests of the pallet
75+
76+
To run the test you simply run the following command
77+
```bash
78+
cargo test --package pallet-fruniques
79+
```
80+
7481
# Similar Projects
7582
### [Fractional Art](https://fractional.art/)
76-
83+
7784
### [Detailed Process Explainer with screenshots](https://medium.com/fractional-art/how-to-use-fractional-to-fractionalize-nfts-84da1a465b6d)
7885

7986
License: MIT

pallets/fruniques/src/functions.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ impl<T: Config> Pallet<T> {
3030
u32::from_ne_bytes(input.try_into().unwrap())
3131
}
3232

33+
pub fn percent_to_permill(input: u8) -> Permill {
34+
Permill::from_percent(input as u32)
35+
}
36+
3337
pub fn bytes_to_string(input: Vec<u8>) -> String {
3438
let mut s = String::default();
3539
for x in input {
@@ -196,7 +200,6 @@ impl<T: Config> Pallet<T> {
196200
collection: T::CollectionId,
197201
item: T::ItemId,
198202
owner: <T::Lookup as sp_runtime::traits::StaticLookup>::Source,
199-
_numeric_value: Option<Permill>,
200203
attributes: Option<Vec<(BoundedVec<u8, T::KeyLimit>, BoundedVec<u8, T::ValueLimit>)>>,
201204
) -> DispatchResult {
202205

pallets/fruniques/src/lib.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,15 +224,13 @@ pub mod pallet {
224224
///
225225
/// ### Parameters needed in order to divide a unique:
226226
/// - `class_id`: The type of NFT that the function will create, categorized by numbers.
227-
/// - `numeric_value`: The value of the NFT that the function will create.
228227
/// - `parent_info`: Information of the parent NFT and a flag to indicate the child would inherit their attributes.
229228
/// - `attributes`: Generates a list of attributes for the new NFT.
230229
///
231230
#[pallet::weight(10_000 + T::DbWeight::get().writes(4))]
232231
pub fn spawn(
233232
origin: OriginFor<T>,
234233
class_id: CollectionId,
235-
numeric_value: Option<Permill>,
236234
parent_info: Option<HierarchicalInfo>,
237235
attributes: Option<Vec<(BoundedVec<u8, T::KeyLimit>, BoundedVec<u8, T::ValueLimit>)>>,
238236
) -> DispatchResult {
@@ -250,7 +248,6 @@ pub mod pallet {
250248
class_id,
251249
instance_id,
252250
account_id,
253-
numeric_value,
254251
attributes,
255252
)?;
256253

@@ -273,7 +270,7 @@ pub mod pallet {
273270
collection_id: class_id,
274271
child_id: instance_id,
275272
is_hierarchical: parent_info.1,
276-
weight: numeric_value.unwrap()
273+
weight: Self::percent_to_permill(parent_info.2),
277274
};
278275

279276
<FruniqueChild<T>>::insert(class_id, instance_id, Some(child_info));

pallets/fruniques/src/tests.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use crate::{mock::*, Error};
2+
use core::convert::TryFrom;
3+
use codec::{Encode};
24

35
use frame_support::{assert_noop, assert_ok, BoundedVec};
46
use sp_runtime::Permill;
@@ -34,7 +36,18 @@ impl ExtBuilder {
3436
}
3537

3638
fn dummy_description() -> BoundedVec<u8, StringLimit> {
37-
bvec![b'a'; 10]
39+
BoundedVec::<u8, StringLimit>::try_from(b"dummy description".to_vec()).unwrap()
40+
}
41+
42+
fn dummy_attributes() -> Vec<(BoundedVec<u8, KeyLimit>, BoundedVec<u8, ValueLimit>)> {
43+
vec![(
44+
BoundedVec::<u8, KeyLimit>::try_from(b"dummy key".encode()).expect("Error on encoding key to BoundedVec"),
45+
BoundedVec::<u8, ValueLimit>::try_from(b"dummy value".encode()).expect("Error on encoding value to BoundedVec"),
46+
)]
47+
}
48+
49+
fn dummy_value() -> Permill {
50+
Permill::from_percent(50)
3851
}
3952

4053
#[test]
@@ -47,10 +60,17 @@ fn create_collection_works() {
4760
#[test]
4861
fn spawn_extrinsic_works() {
4962
ExtBuilder::default().build().execute_with(|| {
50-
assert_noop!(Fruniques::spawn(Origin::signed(1), 0, None, None, None), Error::<Test>::CollectionNotFound);
63+
// A collection must be created before spawning an NFT
64+
assert_noop!(Fruniques::spawn(Origin::signed(1), 0, None, None), Error::<Test>::CollectionNotFound);
5165

5266
assert_ok!(Fruniques::create_collection(Origin::signed(1), Some(dummy_description())));
53-
assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, None, None));
67+
// A NFT can be created with empty data
68+
assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, None));
69+
// A NFT can be created with attributes
70+
assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, Some(dummy_attributes())));
71+
// A NFT can be hierarchical
72+
assert_ok!(Fruniques::spawn(Origin::signed(1), 0, Some((0, false, 10)), None));
73+
5474
})
5575
}
5676

pallets/fruniques/src/types.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ pub type StringLimit<T> = BoundedVec<u8, <T as pallet_uniques::Config>::StringLi
1616
pub type CollectionId = u32;
1717
pub type ItemId = u32;
1818

19-
pub type HierarchicalInfo = (ItemId, bool);
19+
// (ParentId, Heirarchical)
20+
pub type HierarchicalInfo = (ItemId, bool, u8);
2021

2122
#[derive(CloneNoBound, Encode, Decode, RuntimeDebugNoBound, Default, TypeInfo, MaxEncodedLen)]
2223
pub struct ChildInfo {

0 commit comments

Comments
 (0)