Skip to content

Commit

Permalink
add create_token method and fixed tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhiGuang committed Oct 30, 2019
1 parent 7291a7c commit c647c3c
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 63 deletions.
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

SRML-based Substrate node for ERC-721 Non-Fungible Token Standard implementation

# Building
# Prepare

Install Rust:

Expand All @@ -16,6 +16,24 @@ Install required tools:
./scripts/init.sh
```


# Test

Test nftrml module:

```bash
cargo test -p nftrml-nft
```

Test all crates:

```bash
cargo test --all
```


# Building

Build all native code:

```bash
Expand Down Expand Up @@ -60,3 +78,20 @@ cargo run -- \
```

Additional CLI usage options are available and may be shown by running `cargo run -- --help`.

# Client

Use [Polkadot/Substrate Portal](https://polkadot.js.org) to test the node.


Additional types as a JSON file:

```js
{
"TokenId": "u64",
"TokenLinkedItem": {
"prev": "Option<u64>",
"next": "Option<u64>"
}
}
```
233 changes: 171 additions & 62 deletions nftrml/nft/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/// https://github.com/paritytech/substrate/blob/master/srml/example/src/lib.rs
use rstd::prelude::*;
use support::{decl_module, decl_storage, decl_event, Parameter, StorageMap,
use support::{decl_module, decl_storage, decl_event, Parameter, StorageMap, StorageValue,
dispatch::Result, ensure, traits::Currency
};
use sr_primitives::{
Expand Down Expand Up @@ -54,9 +54,9 @@ decl_storage! {

//#region ERC-721 metadata extension

pub Symbol get(symbol) config(): Vec<u8>;
pub Symbol get(symbol) config(): Vec<u8>;

pub Name get(name) config(): Vec<u8>;
pub Name get(name) config(): Vec<u8>;

pub TokenURI get(token_uri): map T::TokenId => Vec<u8>;

Expand Down Expand Up @@ -132,7 +132,7 @@ decl_module! {
Self::deposit_event(RawEvent::ApprovalForAll(sender, to, approved));
}

// transfer
/// transfer token
#[weight = SimpleDispatchInfo::FixedNormal(1_000_000)]
fn transfer_from(origin, from: T::AccountId, to: T::AccountId, token_id: T::TokenId) {
let sender = ensure_signed(origin)?;
Expand All @@ -142,7 +142,7 @@ decl_module! {
Self::deposit_event(RawEvent::Transfer(from, to, token_id));
}

// safe transfer
// safe transfer token
#[weight = SimpleDispatchInfo::FixedNormal(1_000_000)]
fn safe_transfer_from(origin, from: T::AccountId, to: T::AccountId, token_id: T::TokenId) {

Expand All @@ -152,6 +152,13 @@ decl_module! {

Self::deposit_event(RawEvent::Transfer(from, to, token_id));
}

/// create token for your self, maybe for test
fn create_token(origin) {
let sender = ensure_signed(origin)?;

Self::do_create_token(&sender)?;
}
}
}

Expand Down Expand Up @@ -223,6 +230,22 @@ impl<T: Trait> Module<T> {
<TokenToApproval<T>>::remove(token_id);
Ok(())
}

fn do_create_token(owner: &T::AccountId) -> Result {
let token_id = Self::total_supply();
if token_id == T::TokenId::max_value() {
return Err("TokenId overflow");
}
let balance =Self::balance_of(owner);

<TokenToOwner<T>>::insert(token_id, owner);
<OwnerCount<T>>::insert(owner, balance + 1.into());
<TotalSupply<T>>::put(token_id + 1.into());

<OwnerToTokenList<T>>::append(owner, token_id);

Ok(())
}
}

/// impl NFTCurrency Module
Expand Down Expand Up @@ -414,8 +437,41 @@ mod tests {
t.into()
}


#[test]
fn token_to_approval_can_approve() {
fn should_create_token() {
with_externalities(&mut new_test_ext(), || {
let owner = 1;
let origin = Origin::signed(owner);

let old_total_supply = NftModule::total_supply();
let old_balance = NftModule::balance_of(owner);

assert_eq!(OwnerToTokenTest::get(&(owner, Some(0))), None);

assert_ok!(NftModule::create_token(origin.clone()));

let new_total_supply = NftModule::total_supply();
let new_balance = NftModule::balance_of(owner);

assert_eq!(old_total_supply + 1, new_total_supply);
assert_eq!(old_balance + 1, new_balance);
assert_eq!(NftModule::owner_of(old_total_supply), owner);

assert_eq!(OwnerToTokenTest::get(&(owner, None)), Some(TokenLinkedItem::<Test> {
prev: Some(0),
next: Some(0),
}));

assert_eq!(OwnerToTokenTest::get(&(owner, Some(0))), Some(TokenLinkedItem::<Test> {
prev: None,
next: None,
}));
});
}

#[test]
fn should_approve() {
with_externalities(&mut new_test_ext(), || {
let owner = 1;
let origin = Origin::signed(owner);
Expand All @@ -439,7 +495,7 @@ mod tests {
}

#[test]
fn owner_to_operator_can_set_approval_for_all() {
fn should_set_approval_for_all() {
with_externalities(&mut new_test_ext(), || {
let owner = 1;
let origin = Origin::signed(owner);
Expand All @@ -452,6 +508,114 @@ mod tests {
});
}



#[test]
fn should_transfer_from() {
with_externalities(&mut new_test_ext(), || {
{
let from1 = 1;
let to1 = 2;
let token_id1 = 1;

OwnerToTokenList::<Test>::append(&from1, token_id1);
<TokenToOwner<Test>>::insert(token_id1, from1);
<OwnerCount<Test>>::insert(from1, 1);

let old_from_balance = NftModule::balance_of(from1);
let old_to_balance = NftModule::balance_of(to1);

assert_ok!(NftModule::transfer_from(Origin::signed(from1), from1, to1, token_id1));

assert_eq!(NftModule::owner_of(token_id1), to1);

let new_from_balance = NftModule::balance_of(from1);
let new_to_balance = NftModule::balance_of(to1);

assert_eq!(old_from_balance - 1, new_from_balance);
assert_eq!(old_to_balance + 1, new_to_balance);
}

{
let from2 = 3;
let to2 = 4;
let token_id2 = 2;
let token_approve_account = 5;

OwnerToTokenList::<Test>::append(&from2, token_id2);
<TokenToOwner<Test>>::insert(token_id2, from2);
<OwnerCount<Test>>::insert(from2, 1);
<TokenToApproval<Test>>::insert(token_id2, token_approve_account);

let old_from_balance = NftModule::balance_of(from2);
let old_to_balance = NftModule::balance_of(to2);

assert_ok!(NftModule::transfer_from(Origin::signed(token_approve_account), from2, to2, token_id2));

assert_eq!(NftModule::owner_of(token_id2), to2);

let new_from_balance = NftModule::balance_of(from2);
let new_to_balance = NftModule::balance_of(to2);

assert_eq!(old_from_balance - 1, new_from_balance);
assert_eq!(old_to_balance + 1, new_to_balance);
}

{
let from3 = 6;
let to3 = 7;
let token_id3 = 3;
let account_approve_account = 8;
OwnerToTokenList::<Test>::append(&from3, token_id3);
<TokenToOwner<Test>>::insert(token_id3, from3);
<OwnerCount<Test>>::insert(from3, 1);

let old_from_balance = NftModule::balance_of(from3);
let old_to_balance = NftModule::balance_of(to3);

<OwnerToOperator<Test>>::insert((from3, account_approve_account), true);
assert_ok!(NftModule::transfer_from(Origin::signed(account_approve_account), from3, to3, token_id3));

assert_eq!(NftModule::owner_of(token_id3), to3);

let new_from_balance = NftModule::balance_of(from3);
let new_to_balance = NftModule::balance_of(to3);

assert_eq!(old_from_balance - 1, new_from_balance);
assert_eq!(old_to_balance + 1, new_to_balance);
}
});
}

#[test]
fn should_safe_transfer_from() {
with_externalities(&mut new_test_ext(), || {
let from = 9;
let origin = Origin::signed(from);
let to = 10;
let token_id = 4;

OwnerToTokenList::<Test>::append(&from, token_id);
<TokenToOwner<Test>>::insert(token_id, from);
<OwnerCount<Test>>::insert(from, 1);
assert_eq!(Balances::free_balance(to), 20);


let old_from_balance = NftModule::balance_of(from);
let old_to_balance = NftModule::balance_of(to);

assert_ok!(NftModule::safe_transfer_from(origin, from, to, token_id));

assert_eq!(NftModule::owner_of(token_id), to);

let new_from_balance = NftModule::balance_of(from);
let new_to_balance = NftModule::balance_of(to);

assert_eq!(old_from_balance - 1, new_from_balance);
assert_eq!(old_to_balance + 1, new_to_balance);
});
}

#[test]
fn owned_to_token_can_append_values() {
with_externalities(&mut new_test_ext(), || {
Expand Down Expand Up @@ -565,59 +729,4 @@ mod tests {
});
}


#[test]
fn owne_to_token_can_transfer_from() {
with_externalities(&mut new_test_ext(), || {
{
let from1 = 1;
let to1 = 2;
let token_id1 = 1;
OwnerToTokenList::<Test>::append(&from1, token_id1);
<TokenToOwner<Test>>::insert(token_id1, from1);
<OwnerCount<Test>>::insert(from1, 1);
assert_ok!(NftModule::transfer_from(Origin::signed(from1), from1, to1, token_id1));
}

{
let from2 = 3;
let to2 = 4;
let token_id2 = 2;
let token_approve_account = 5;
OwnerToTokenList::<Test>::append(&from2, token_id2);
<TokenToOwner<Test>>::insert(token_id2, from2);
<OwnerCount<Test>>::insert(from2, 1);
<TokenToApproval<Test>>::insert(token_id2, token_approve_account);
assert_ok!(NftModule::transfer_from(Origin::signed(token_approve_account), from2, to2, token_id2));
}

{
let from3 = 6;
let to3 = 7;
let token_id3 = 3;
let account_approve_account = 8;
OwnerToTokenList::<Test>::append(&from3, token_id3);
<TokenToOwner<Test>>::insert(token_id3, from3);
<OwnerCount<Test>>::insert(from3, 1);
<OwnerToOperator<Test>>::insert((from3, account_approve_account), true);
assert_ok!(NftModule::transfer_from(Origin::signed(account_approve_account), from3, to3, token_id3));
}
});
}

#[test]
fn owne_to_token_can_safe_transfer_from() {
with_externalities(&mut new_test_ext(), || {
let from = 9;
let origin = Origin::signed(from);
let to = 10;
let token_id = 4;

OwnerToTokenList::<Test>::append(&from, token_id);
<TokenToOwner<Test>>::insert(token_id, from);
<OwnerCount<Test>>::insert(from, 1);
assert_eq!(Balances::free_balance(to), 20);
assert_ok!(NftModule::safe_transfer_from(origin, from, to, token_id));
});
}
}

0 comments on commit c647c3c

Please sign in to comment.