difftreelog
Merge branch 'develop' into release/v2.0.0
in: master
34 files changed
Dockerfilediffbeforeafterboth--- a/Dockerfile
+++ b/Dockerfile
@@ -1,9 +1,9 @@
# ===== BUILD ======
-FROM phusion/baseimage:0.10.2 as builder
+FROM phusion/baseimage:18.04-1.0.0 as builder
LABEL maintainer="gz@usetech.com"
-ENV WASM_TOOLCHAIN=nightly-2020-10-01
+ENV WASM_TOOLCHAIN=nightly-2021-01-27
ARG PROFILE=release
@@ -37,7 +37,7 @@
# ===== RUN ======
-FROM phusion/baseimage:0.10.2
+FROM phusion/baseimage:18.04-1.0.0
ARG PROFILE=release
COPY --from=builder /nft_parachain/target/$PROFILE/nft /usr/local/bin
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -54,6 +54,7 @@
mod default_weights;
pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;
+pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;
pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;
pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;
@@ -71,8 +72,7 @@
NFT,
// decimal points
Fungible(DecimalPoints),
- // decimal points
- ReFungible(DecimalPoints),
+ ReFungible,
}
impl Default for CollectionMode {
@@ -87,7 +87,7 @@
CollectionMode::Invalid => 0,
CollectionMode::NFT => 1,
CollectionMode::Fungible(_) => 2,
- CollectionMode::ReFungible(_) => 3,
+ CollectionMode::ReFungible => 3,
}
}
}
@@ -185,6 +185,8 @@
// Timeouts for item types in passed blocks
pub sponsor_transfer_timeout: u32,
+ pub owner_can_transfer: bool,
+ pub owner_can_destroy: bool,
}
impl Default for CollectionLimits {
@@ -193,7 +195,10 @@
account_token_ownership_limit: 10_000_000,
token_limit: u32::max_value(),
sponsored_data_size: u32::max_value(),
- sponsor_transfer_timeout: 14400 }
+ sponsor_transfer_timeout: 14400,
+ owner_can_transfer: true,
+ owner_can_destroy: true
+ }
}
}
@@ -266,6 +271,7 @@
pub struct CreateReFungibleData {
pub const_data: Vec<u8>,
pub variable_data: Vec<u8>,
+ pub pieces: u128,
}
#[derive(Encode, Decode, Debug, Clone, PartialEq)]
@@ -377,7 +383,9 @@
/// Collection limit bounds per collection exceeded
CollectionLimitBoundsExceeded,
/// Schema data size limit bound exceeded
- SchemaDataLimitExceeded
+ SchemaDataLimitExceeded,
+ /// Maximum refungibility exceeded
+ WrongRefungiblePieces
}
}
@@ -548,7 +556,6 @@
let decimal_points = match mode {
CollectionMode::Fungible(points) => points,
- CollectionMode::ReFungible(points) => points,
_ => 0
};
@@ -590,7 +597,7 @@
sponsor_confirmed: false,
variable_on_chain_schema: Vec::new(),
const_on_chain_schema: Vec::new(),
- limits: CollectionLimits::default(),
+ limits: CollectionLimits::default()
};
// Add new collection to map
@@ -933,7 +940,7 @@
Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;
Self::validate_create_item_args(&target_collection, &data)?;
- Self::create_item_no_validation(collection_id, &target_collection, owner, data)?;
+ Self::create_item_no_validation(collection_id, owner, data)?;
Ok(())
}
@@ -973,7 +980,7 @@
Self::validate_create_item_args(&target_collection, data)?;
}
for data in &items_data {
- Self::create_item_no_validation(collection_id, &target_collection, owner.clone(), data.clone())?;
+ Self::create_item_no_validation(collection_id, owner.clone(), data.clone())?;
}
Ok(())
@@ -1012,7 +1019,7 @@
{
CollectionMode::NFT => Self::burn_nft_item(collection_id, item_id)?,
CollectionMode::Fungible(_) => Self::burn_fungible_item(&sender, collection_id, value)?,
- CollectionMode::ReFungible(_) => Self::burn_refungible_item(collection_id, item_id, &sender)?,
+ CollectionMode::ReFungible => Self::burn_refungible_item(collection_id, item_id, &sender)?,
_ => ()
};
@@ -1154,7 +1161,7 @@
{
CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, from, recipient)?,
CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, value, &from, &recipient)?,
- CollectionMode::ReFungible(_) => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?,
+ CollectionMode::ReFungible => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?,
_ => ()
};
@@ -1211,7 +1218,7 @@
match target_collection.mode
{
CollectionMode::NFT => Self::set_nft_variable_data(collection_id, item_id, data)?,
- CollectionMode::ReFungible(_) => Self::set_re_fungible_variable_data(collection_id, item_id, data)?,
+ CollectionMode::ReFungible => Self::set_re_fungible_variable_data(collection_id, item_id, data)?,
CollectionMode::Fungible(_) => fail!(Error::<T>::CantStoreMetadataInFungibleTokens),
_ => fail!(Error::<T>::UnexpectedCollectionType)
};
@@ -1551,7 +1558,7 @@
{
CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, sender.clone(), recipient)?,
CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, value, &sender, &recipient)?,
- CollectionMode::ReFungible(_) => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?,
+ CollectionMode::ReFungible => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?,
_ => ()
};
@@ -1603,12 +1610,16 @@
fail!(Error::<T>::NotFungibleDataUsedToMintFungibleCollectionToken);
}
},
- CollectionMode::ReFungible(_) => {
+ CollectionMode::ReFungible => {
if let CreateItemData::ReFungible(data) = data {
// check sizes
ensure!(ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, Error::<T>::TokenConstDataLimitExceeded);
ensure!(ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, Error::<T>::TokenVariableDataLimitExceeded);
+
+ // Check refungibility limits
+ ensure!(data.pieces <= MAX_REFUNGIBLE_PIECES, Error::<T>::WrongRefungiblePieces);
+ ensure!(data.pieces > 0, Error::<T>::WrongRefungiblePieces);
} else {
fail!(Error::<T>::NotReFungibleDataUsedToMintReFungibleCollectionToken);
}
@@ -1619,7 +1630,7 @@
Ok(())
}
- fn create_item_no_validation(collection_id: CollectionId, collection: &CollectionType<T::AccountId>, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
+ fn create_item_no_validation(collection_id: CollectionId, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
match data
{
CreateItemData::NFT(data) => {
@@ -1636,8 +1647,7 @@
},
CreateItemData::ReFungible(data) => {
let mut owner_list = Vec::new();
- let value = (10 as u128).pow(collection.decimal_points as u32);
- owner_list.push(Ownership {owner: owner.clone(), fraction: value});
+ owner_list.push(Ownership {owner: owner.clone(), fraction: data.pieces});
let item = ReFungibleItemType {
owner: owner_list,
@@ -1866,7 +1876,7 @@
CollectionMode::Fungible(_) => {
<FungibleItemList<T>>::contains_key(collection_id, &subject)
}
- CollectionMode::ReFungible(_) => {
+ CollectionMode::ReFungible => {
<ReFungibleItemList<T>>::get(collection_id, item_id)
.owner
.iter()
@@ -1895,7 +1905,7 @@
{
CollectionMode::NFT => <NftItemList<T>>::contains_key(collection_id, item_id),
CollectionMode::Fungible(_) => <FungibleItemList<T>>::contains_key(collection_id, owner),
- CollectionMode::ReFungible(_) => <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
+ CollectionMode::ReFungible => <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
_ => false
};
@@ -2421,7 +2431,7 @@
sponsored
}
- CollectionMode::ReFungible(_) => {
+ CollectionMode::ReFungible => {
// get correct limit
let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
pallets/nft/src/tests.rsdiffbeforeafterboth--- a/pallets/nft/src/tests.rs
+++ b/pallets/nft/src/tests.rs
@@ -35,7 +35,7 @@
}
fn default_re_fungible_data () -> CreateReFungibleData {
- CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] }
+ CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1], pieces: 1023 }
}
fn create_test_collection_for_owner(mode: &CollectionMode, owner: u64, id: CollectionId) -> CollectionId {
@@ -114,26 +114,6 @@
}
#[test]
-fn create_re_fungible_collection_fails_with_large_decimal_numbers() {
- new_test_ext().execute_with(|| {
- default_limits();
-
- let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
- let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
- let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
-
- let origin1 = Origin::signed(1);
- assert_noop!(TemplateModule::create_collection(
- origin1,
- col_name1,
- col_desc1,
- token_prefix1,
- CollectionMode::ReFungible(MAX_DECIMAL_POINTS + 1)
- ), Error::<Test>::CollectionDecimalPointLimitExceeded);
- });
-}
-
-#[test]
fn create_nft_item() {
new_test_ext().execute_with(|| {
default_limits();
@@ -176,7 +156,7 @@
fn create_refungible_item() {
new_test_ext().execute_with(|| {
default_limits();
- let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);
+ let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
let data = default_re_fungible_data();
create_test_item(collection_id, &data.clone().into());
@@ -192,7 +172,7 @@
TemplateModule::refungible_item_id(collection_id, 1).owner[0],
Ownership {
owner: 1,
- fraction: 1000
+ fraction: 1023
}
);
});
@@ -203,7 +183,7 @@
new_test_ext().execute_with(|| {
default_limits();
- create_test_collection(&CollectionMode::ReFungible(3), 1);
+ create_test_collection(&CollectionMode::ReFungible, 1);
let origin1 = Origin::signed(1);
@@ -224,7 +204,7 @@
item.owner[0],
Ownership {
owner: 1,
- fraction: 1000
+ fraction: 1023
}
);
}
@@ -312,7 +292,7 @@
new_test_ext().execute_with(|| {
default_limits();
- let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);
+ let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
let data = default_re_fungible_data();
create_test_item(collection_id, &data.clone().into());
@@ -331,23 +311,23 @@
TemplateModule::refungible_item_id(collection_id, 1).owner[0],
Ownership {
owner: 1,
- fraction: 1000
+ fraction: 1023
}
);
- assert_eq!(TemplateModule::balance_count(1, 1), 1000);
+ assert_eq!(TemplateModule::balance_count(1, 1), 1023);
assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
// change owner scenario
- assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000));
+ assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1023));
assert_eq!(
TemplateModule::refungible_item_id(1, 1).owner[0],
Ownership {
owner: 2,
- fraction: 1000
+ fraction: 1023
}
);
assert_eq!(TemplateModule::balance_count(1, 1), 0);
- assert_eq!(TemplateModule::balance_count(1, 2), 1000);
+ assert_eq!(TemplateModule::balance_count(1, 2), 1023);
// assert_eq!(TemplateModule::address_tokens(1, 1), []);
assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
@@ -357,7 +337,7 @@
TemplateModule::refungible_item_id(1, 1).owner[0],
Ownership {
owner: 2,
- fraction: 500
+ fraction: 523
}
);
assert_eq!(
@@ -367,7 +347,7 @@
fraction: 500
}
);
- assert_eq!(TemplateModule::balance_count(1, 2), 500);
+ assert_eq!(TemplateModule::balance_count(1, 2), 523);
assert_eq!(TemplateModule::balance_count(1, 3), 500);
assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
@@ -378,7 +358,7 @@
TemplateModule::refungible_item_id(1, 1).owner[0],
Ownership {
owner: 2,
- fraction: 300
+ fraction: 323
}
);
assert_eq!(
@@ -388,7 +368,7 @@
fraction: 700
}
);
- assert_eq!(TemplateModule::balance_count(1, 2), 300);
+ assert_eq!(TemplateModule::balance_count(1, 2), 323);
assert_eq!(TemplateModule::balance_count(1, 3), 700);
assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
@@ -517,7 +497,7 @@
new_test_ext().execute_with(|| {
default_limits();
- let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);
+ let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
let origin1 = Origin::signed(1);
let origin2 = Origin::signed(2);
@@ -525,7 +505,7 @@
let data = default_re_fungible_data();
create_test_item(collection_id, &data.into());
- assert_eq!(TemplateModule::balance_count(1, 1), 1000);
+ assert_eq!(TemplateModule::balance_count(1, 1), 1023);
assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
assert_ok!(TemplateModule::set_mint_permission(
@@ -543,8 +523,8 @@
assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));
// do approve
- assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1000));
- assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1000);
+ assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1023));
+ assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1023);
assert_ok!(TemplateModule::transfer_from(
origin2.clone(),
@@ -554,14 +534,14 @@
1,
100
));
- assert_eq!(TemplateModule::balance_count(1, 1), 900);
+ assert_eq!(TemplateModule::balance_count(1, 1), 923);
assert_eq!(TemplateModule::balance_count(1, 3), 100);
assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
assert_eq!(
TemplateModule::approved(1, (1, 1, 2)),
- 900
+ 923
);
});
}
@@ -717,7 +697,7 @@
new_test_ext().execute_with(|| {
default_limits();
- let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);
+ let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
let origin1 = Origin::signed(1);
assert_ok!(TemplateModule::set_mint_permission(
@@ -738,12 +718,12 @@
create_test_item(collection_id, &data.into());
// check balance (collection with id = 1, user id = 2)
- assert_eq!(TemplateModule::balance_count(1, 1), 1000);
+ assert_eq!(TemplateModule::balance_count(1, 1), 1023);
// burn item
- assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1000));
+ assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1023));
assert_noop!(
- TemplateModule::burn_item(origin1.clone(), 1, 1, 1000),
+ TemplateModule::burn_item(origin1.clone(), 1, 1, 1023),
Error::<Test>::TokenNotFound
);
@@ -807,7 +787,7 @@
let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);
let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);
- let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible(3), 3);
+ let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3);
// check balance before
assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0);
@@ -826,7 +806,7 @@
// check balance (collection with id = 1, user id = 1)
assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1);
assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 5);
- assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 1000);
+ assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 1023);
assert_eq!(TemplateModule::nft_item_id(nft_collection_id, 1).owner, 1);
assert_eq!(TemplateModule::fungible_item_id(fungible_collection_id, 1).value, 5);
assert_eq!(TemplateModule::refungible_item_id(re_fungible_collection_id, 1).owner[0].owner, 1);
@@ -1905,7 +1885,7 @@
new_test_ext().execute_with(|| {
default_limits();
- let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);
+ let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
let origin1 = Origin::signed(1);
@@ -1982,7 +1962,7 @@
}));
- let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);
+ let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
let origin1 = Origin::signed(1);
runtime_types.jsondiffbeforeafterboth--- a/runtime_types.json
+++ b/runtime_types.json
@@ -1,27 +1,4 @@
{
- "Schedule": {
- "version": "u32",
- "put_code_per_byte_cost": "Gas",
- "grow_mem_cost": "Gas",
- "regular_op_cost": "Gas",
- "return_data_per_byte_cost": "Gas",
- "event_data_per_byte_cost": "Gas",
- "event_per_topic_cost": "Gas",
- "event_base_cost": "Gas",
- "call_base_cost": "Gas",
- "instantiate_base_cost": "Gas",
- "dispatch_base_cost": "Gas",
- "sandbox_data_read_cost": "Gas",
- "sandbox_data_write_cost": "Gas",
- "transfer_cost": "Gas",
- "instantiate_cost": "Gas",
- "max_event_topics": "u32",
- "max_stack_height": "u32",
- "max_memory_pages": "u32",
- "max_table_size": "u32",
- "enable_println": "bool",
- "max_subject_len": "u32"
- },
"AccessMode": {
"_enum": [
"Normal",
@@ -34,7 +11,7 @@
"Invalid": null,
"NFT": null,
"Fungible": "DecimalPoints",
- "ReFungible": "DecimalPoints"
+ "ReFungible": null
}
},
"Ownership": {
@@ -84,7 +61,8 @@
},
"CreateReFungibleData": {
"const_data": "Vec<u8>",
- "variable_data": "Vec<u8>"
+ "variable_data": "Vec<u8>",
+ "pieces": "u128"
},
"CreateItemData": {
"_enum": {
@@ -117,15 +95,8 @@
"AccountTokenOwnershipLimit": "u32",
"SponsoredMintSize": "u32",
"TokenLimit": "u32",
- "SponsorTimeout": "u32"
- },
- "AccountInfo": "AccountInfoWithProviders",
- "AccountInfoWithProviders": {
- "nonce": "Index",
- "consumers": "RefCount",
- "providers": "RefCount",
- "data": "AccountData"
+ "SponsorTimeout": "u32",
+ "OwnerCanTransfer": "bool",
+ "OwnerCanDestroy": "bool"
}
-
- }
-
\ No newline at end of file
+}
\ No newline at end of file
tests/src/addCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -1,4 +1,9 @@
-import { ApiPromise } from '@polkadot/api';
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { ApiPromise } from '@polkadot/api';
import BN from 'bn.js';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
@@ -98,7 +103,7 @@
});
});
- it('Add an admin to a collection that has reached the maximum number of admins limit', async () => {
+ it.only('Add an admin to a collection that has reached the maximum number of admins limit', async () => {
await usingApi(async (api: ApiPromise) => {
const Alice = privateKey('//Alice');
const accounts = [
@@ -112,18 +117,18 @@
];
const collectionId = await createCollectionExpectSuccess();
- const chainLimit = await api.query.nft.chainLimit() as unknown as { collections_admins_limit: BN };
- const chainLimitNumber = chainLimit.collections_admins_limit.toNumber();
- expect(chainLimitNumber).to.be.equal(5);
+ const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN };
+ const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber();
+ expect(chainAdminLimit).to.be.equal(5);
- for (let i = 0; i < chainLimitNumber; i++) {
+ for (let i = 0; i < chainAdminLimit; i++) {
const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, accounts[i]);
await submitTransactionAsync(Alice, changeAdminTx);
const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
expect(adminListAfterAddAdmin).to.be.contains(accounts[i]);
}
- const tx = api.tx.nft.addCollectionAdmin(collectionId, accounts[chainLimitNumber]);
+ const tx = api.tx.nft.addCollectionAdmin(collectionId, accounts[chainAdminLimit]);
await expect(submitTransactionExpectFailAsync(Alice, tx)).to.be.rejected;
});
});
tests/src/addToContractWhiteList.test.tsdiffbeforeafterboth--- a/tests/src/addToContractWhiteList.test.ts
+++ b/tests/src/addToContractWhiteList.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import chai from "chai";
import chaiAsPromised from 'chai-as-promised';
import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
tests/src/addToWhiteList.test.tsdiffbeforeafterboth--- a/tests/src/addToWhiteList.test.ts
+++ b/tests/src/addToWhiteList.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { IKeyringPair } from '@polkadot/types/types';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
tests/src/approve.test.tsdiffbeforeafterboth--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -34,7 +34,7 @@
await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob);
// reFungible
const reFungibleCollectionId =
- await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob);
});
@@ -56,7 +56,7 @@
await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 0);
// reFungible
const reFungibleCollectionId =
- await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob, 1);
await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob, 0);
@@ -95,7 +95,7 @@
await approveExpectFail(fungibleCollectionId, 1, Alice, Bob);
// reFungible
const reFungibleCollectionId =
- await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await destroyCollectionExpectSuccess(reFungibleCollectionId);
await approveExpectFail(reFungibleCollectionId, 1, Alice, Bob);
});
@@ -113,7 +113,7 @@
await approveExpectFail(fungibleCollectionId, 2, Alice, Bob);
// reFungible
const reFungibleCollectionId =
- await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await approveExpectFail(reFungibleCollectionId, 2, Alice, Bob);
});
});
@@ -132,7 +132,7 @@
await approveExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice);
// reFungible
const reFungibleCollectionId =
- await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, Bob, Alice);
});
tests/src/burnItem.test.tsdiffbeforeafterboth--- a/tests/src/burnItem.test.ts
+++ b/tests/src/burnItem.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
import { Keyring } from "@polkadot/api";
import { IKeyringPair } from "@polkadot/types/types";
@@ -70,7 +75,7 @@
});
it('Burn item in ReFungible collection', async () => {
const createMode = 'ReFungible';
- const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 2 }});
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode }});
const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
await usingApi(async (api) => {
@@ -91,7 +96,7 @@
it('Burn owned portion of item in ReFungible collection', async () => {
const createMode = 'ReFungible';
- const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 2 }});
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
await usingApi(async (api) => {
@@ -107,7 +112,7 @@
const tx = api.tx.nft.burnItem(collectionId, tokenId, 0);
const events2 = await submitTransactionAsync(bob, tx);
const result2 = getGenericResult(events2);
-
+
// Get balances
const balance: any = (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON();
// console.log(balance);
tests/src/change-collection-owner.test.tsdiffbeforeafterboth--- a/tests/src/change-collection-owner.test.ts
+++ b/tests/src/change-collection-owner.test.ts
@@ -1,4 +1,9 @@
-import chai from 'chai';
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import privateKey from './substrate/privateKey';
import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
tests/src/confirmSponsorship.test.tsdiffbeforeafterboth--- a/tests/src/confirmSponsorship.test.ts
+++ b/tests/src/confirmSponsorship.test.ts
@@ -115,7 +115,7 @@
});
it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0 }});
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
@@ -247,7 +247,7 @@
});
it('ReFungible: Sponsoring is rate limited', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0 }});
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
tests/src/contracts.test.tsdiffbeforeafterboth--- a/tests/src/contracts.test.ts
+++ b/tests/src/contracts.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import chai from "chai";
import chaiAsPromised from 'chai-as-promised';
import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
tests/src/createCollection.test.tsdiffbeforeafterboth--- a/tests/src/createCollection.test.ts
+++ b/tests/src/createCollection.test.ts
@@ -28,7 +28,7 @@
await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
});
it('Create new ReFungible collection', async () => {
- await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
});
});
tests/src/createItem.test.tsdiffbeforeafterboth--- a/tests/src/createItem.test.ts
+++ b/tests/src/createItem.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { default as usingApi } from './substrate/substrate-api';
import { Keyring } from "@polkadot/api";
import { IKeyringPair } from "@polkadot/types/types";
@@ -28,7 +33,7 @@
});
it('Create new item in ReFungible collection', async () => {
const createMode = 'ReFungible';
- const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
+ const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
await createItemExpectSuccess(alice, newCollectionID, createMode);
});
});
tests/src/createMultipleItems.test.tsdiffbeforeafterboth--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -56,14 +56,14 @@
it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {
await usingApi(async (api: ApiPromise) => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
const Alice = privateKey('//Alice');
const args = [
- { Refungible: ['0x31', '0x31'] },
- { Refungible: ['0x32', '0x32'] },
- { Refungible: ['0x33', '0x33'] },
+ {refungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},
+ {refungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
+ {refungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
];
const createMultipleItemsTx = await api.tx.nft
.createMultipleItems(collectionId, Alice.address, args);
@@ -137,7 +137,7 @@
// ReFungible
const collectionIdReFungible =
- await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const argsReFungible = [
{ ReFungible: ['1'.repeat(2049), '1'.repeat(2049)] },
{ ReFungible: ['2'.repeat(2049), '2'.repeat(2049)] },
tests/src/destroyCollection.test.tsdiffbeforeafterboth--- a/tests/src/destroyCollection.test.ts
+++ b/tests/src/destroyCollection.test.ts
@@ -1,12 +1,14 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
-import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api";
-import { createCollectionExpectSuccess, createCollectionExpectFailure, destroyCollectionExpectSuccess, destroyCollectionExpectFailure } from "./util/helpers";
-import type { AccountId, EventRecord } from '@polkadot/types/interfaces';
-import privateKey from './substrate/privateKey';
+import { default as usingApi } from "./substrate/substrate-api";
+import { createCollectionExpectSuccess, destroyCollectionExpectSuccess, destroyCollectionExpectFailure } from "./util/helpers";
chai.use(chaiAsPromised);
-const expect = chai.expect;
describe('integration test: ext. destroyCollection():', () => {
it('NFT collection can be destroyed', async () => {
@@ -18,7 +20,7 @@
await destroyCollectionExpectSuccess(collectionId);
});
it('ReFungible collection can be destroyed', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await destroyCollectionExpectSuccess(collectionId);
});
});
tests/src/enableContractSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/enableContractSponsoring.test.ts
+++ b/tests/src/enableContractSponsoring.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { IKeyringPair } from '@polkadot/types/types';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -1,5 +1,9 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { ApiPromise } from '@polkadot/api';
-import BN from 'bn.js';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import privateKey from './substrate/privateKey';
tests/src/removeFromContractWhiteList.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/removeFromContractWhiteList.test.ts
@@ -0,0 +1,72 @@
+import privateKey from "./substrate/privateKey";
+import usingApi from "./substrate/substrate-api";
+import { deployFlipper, toggleFlipValueExpectFailure, toggleFlipValueExpectSuccess } from "./util/contracthelpers";
+import { addToContractWhiteListExpectSuccess, isWhitelistedInContract, removeFromContractWhiteListExpectFailure, removeFromContractWhiteListExpectSuccess, toggleContractWhitelistExpectSuccess } from "./util/helpers";
+import { IKeyringPair } from '@polkadot/types/types';
+import { expect } from "chai";
+
+describe('Integration Test removeFromContractWhiteList', () => {
+ let bob: IKeyringPair;
+
+ before(() => {
+ bob = privateKey('//Bob');
+ });
+
+ it('user is no longer whitelisted after removal', async () => {
+ await usingApi(async (api) => {
+ const [flipper, deployer] = await deployFlipper(api);
+
+ await addToContractWhiteListExpectSuccess(deployer, flipper.address, bob.address);
+ await removeFromContractWhiteListExpectSuccess(deployer, flipper.address, bob.address);
+
+ expect(await isWhitelistedInContract(flipper.address, bob.address)).to.be.false;
+ });
+ });
+
+ it('user can\'t execute contract after removal', async () => {
+ await usingApi(async (api) => {
+ const [flipper, deployer] = await deployFlipper(api);
+ await toggleContractWhitelistExpectSuccess(deployer, flipper.address, true);
+
+ await addToContractWhiteListExpectSuccess(deployer, flipper.address, bob.address);
+ await toggleFlipValueExpectSuccess(bob, flipper);
+
+ await removeFromContractWhiteListExpectSuccess(deployer, flipper.address, bob.address);
+ await toggleFlipValueExpectFailure(bob, flipper);
+ });
+ });
+
+ it('can be called twice', async () => {
+ await usingApi(async (api) => {
+ const [flipper, deployer] = await deployFlipper(api);
+
+ await addToContractWhiteListExpectSuccess(deployer, flipper.address, bob.address);
+ await removeFromContractWhiteListExpectSuccess(deployer, flipper.address, bob.address);
+ await removeFromContractWhiteListExpectSuccess(deployer, flipper.address, bob.address);
+ });
+ });
+});
+
+describe('Negative Integration Test removeFromContractWhiteList', () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+
+ before(() => {
+ alice = privateKey('//Alice');
+ bob = privateKey('//Bob');
+ });
+
+ it('fails when called with non-contract address', async () => {
+ await usingApi(async () => {
+ await removeFromContractWhiteListExpectFailure(alice, alice.address, bob.address);
+ });
+ });
+
+ it('fails when executed by non owner', async () => {
+ await usingApi(async (api) => {
+ const [flipper, _] = await deployFlipper(api);
+
+ await removeFromContractWhiteListExpectFailure(alice, flipper.address, bob.address);
+ });
+ });
+});
tests/src/removeFromWhiteList.test.tsdiffbeforeafterboth--- a/tests/src/removeFromWhiteList.test.ts
+++ b/tests/src/removeFromWhiteList.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { default as usingApi } from './substrate/substrate-api';
tests/src/setCollectionLimits.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionLimits.test.ts
+++ b/tests/src/setCollectionLimits.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
// https://unique-network.readthedocs.io/en/latest/jsapi.html#setchainlimits
import { ApiPromise, Keyring } from '@polkadot/api';
import { IKeyringPair } from '@polkadot/types/types';
tests/src/setCollectionSponsor.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionSponsor.test.ts
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -9,7 +9,6 @@
import { createCollectionExpectSuccess, setCollectionSponsorExpectSuccess, destroyCollectionExpectSuccess, setCollectionSponsorExpectFailure } from "./util/helpers";
import { Keyring } from "@polkadot/api";
import { IKeyringPair } from "@polkadot/types/types";
-import type { AccountId } from '@polkadot/types/interfaces';
chai.use(chaiAsPromised);
const expect = chai.expect;
@@ -34,7 +33,7 @@
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
});
it('Set ReFungible collection sponsor', async () => {
- const collectionId = await createCollectionExpectSuccess({ mode: {type: 'ReFungible', decimalPoints: 0} });
+ const collectionId = await createCollectionExpectSuccess({ mode: {type: 'ReFungible'} });
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
});
tests/src/setConstOnChainSchema.test.tsdiffbeforeafterboth--- a/tests/src/setConstOnChainSchema.test.ts
+++ b/tests/src/setConstOnChainSchema.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { Keyring } from '@polkadot/api';
import { IKeyringPair } from '@polkadot/types/types';
import chai from 'chai';
tests/src/setContractSponsoringRateLimit.test.tsdiffbeforeafterboth--- a/tests/src/setContractSponsoringRateLimit.test.ts
+++ b/tests/src/setContractSponsoringRateLimit.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { IKeyringPair } from '@polkadot/types/types';
import privateKey from './substrate/privateKey';
import usingApi from './substrate/substrate-api';
tests/src/setMintPermission.test.tsdiffbeforeafterboth--- a/tests/src/setMintPermission.test.ts
+++ b/tests/src/setMintPermission.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { IKeyringPair } from '@polkadot/types/types';
import privateKey from './substrate/privateKey';
import usingApi from './substrate/substrate-api';
tests/src/setPublicAccessMode.test.tsdiffbeforeafterboth--- a/tests/src/setPublicAccessMode.test.ts
+++ b/tests/src/setPublicAccessMode.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
// https://unique-network.readthedocs.io/en/latest/jsapi.html#setschemaversion
import { ApiPromise, Keyring } from '@polkadot/api';
import { IKeyringPair } from '@polkadot/types/types';
tests/src/setSchemaVersion.test.tsdiffbeforeafterboth--- a/tests/src/setSchemaVersion.test.ts
+++ b/tests/src/setSchemaVersion.test.ts
@@ -1,7 +1,11 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
// https://unique-network.readthedocs.io/en/latest/jsapi.html#setschemaversion
import { ApiPromise, Keyring } from '@polkadot/api';
import { IKeyringPair } from '@polkadot/types/types';
-import BN from 'bn.js';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import usingApi, {submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';
tests/src/setVariableMetaData.test.tsdiffbeforeafterboth--- a/tests/src/setVariableMetaData.test.ts
+++ b/tests/src/setVariableMetaData.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { IKeyringPair } from '@polkadot/types/types';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
tests/src/setVariableOnChainSchema.test.tsdiffbeforeafterboth--- a/tests/src/setVariableOnChainSchema.test.ts
+++ b/tests/src/setVariableOnChainSchema.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import { Keyring } from '@polkadot/api';
import { IKeyringPair } from '@polkadot/types/types';
import chai from 'chai';
tests/src/toggleContractWhiteList.test.tsdiffbeforeafterboth--- a/tests/src/toggleContractWhiteList.test.ts
+++ b/tests/src/toggleContractWhiteList.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import chai from "chai";
import chaiAsPromised from 'chai-as-promised';
import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
tests/src/transfer.test.tsdiffbeforeafterboth--- a/tests/src/transfer.test.ts
+++ b/tests/src/transfer.test.ts
@@ -63,7 +63,7 @@
});
});
- it('Create collection, balance transfers and check balance', async () => {
+ it('User can transfer owned token', async () => {
await usingApi(async (api) => {
const Alice = privateKey('//Alice');
const Bob = privateKey('//Bob');
@@ -77,10 +77,10 @@
await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible');
// reFungible
const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
await transferExpectSuccess(reFungibleCollectionId,
- newReFungibleTokenId, Alice, Bob, 1, 'ReFungible');
+ newReFungibleTokenId, Alice, Bob, 100, 'ReFungible');
});
});
});
@@ -119,7 +119,7 @@
await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible');
// reFungible
const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
await destroyCollectionExpectSuccess(reFungibleCollectionId);
await transferExpectFail(reFungibleCollectionId,
@@ -134,7 +134,7 @@
await transferExpectFail(fungibleCollectionId, 2, Alice, Bob, 1, 'Fungible');
// reFungible
const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await transferExpectFail(reFungibleCollectionId,
2, Alice, Bob, 1, 'ReFungible');
});
@@ -151,7 +151,7 @@
await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible');
// reFungible
const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, 1);
await transferExpectFail(reFungibleCollectionId,
@@ -168,7 +168,7 @@
await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Charlie, Bob, 1, 'Fungible');
// reFungible
const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
await transferExpectFail(reFungibleCollectionId,
newReFungibleTokenId, Charlie, Bob, 1, 'ReFungible');
tests/src/transferFrom.test.tsdiffbeforeafterboth--- a/tests/src/transferFrom.test.ts
+++ b/tests/src/transferFrom.test.ts
@@ -25,7 +25,7 @@
await usingApi(async (api: ApiPromise) => {
const Alice = privateKey('//Alice');
const Bob = privateKey('//Bob');
- const Charlie = privateKey('//CHARLIE');
+ const Charlie = privateKey('//Charlie');
// nft
const nftCollectionId = await createCollectionExpectSuccess();
const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
@@ -40,11 +40,11 @@
await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 1, 'Fungible');
// reFungible
const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
- await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob);
+ await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob, 100);
await transferFromExpectSuccess(reFungibleCollectionId,
- newReFungibleTokenId, Bob, Alice, Charlie, 1, 'ReFungible');
+ newReFungibleTokenId, Bob, Alice, Charlie, 100, 'ReFungible');
});
});
});
@@ -54,7 +54,7 @@
await usingApi(async (api: ApiPromise) => {
const Alice = privateKey('//Alice');
const Bob = privateKey('//Bob');
- const Charlie = privateKey('//CHARLIE');
+ const Charlie = privateKey('//Charlie');
// nft
const nftCollectionCount = await api.query.nft.createdCollectionCount() as unknown as number;
await approveExpectFail(nftCollectionCount + 1, 1, Alice, Bob);
@@ -96,7 +96,7 @@
await usingApi(async (api: ApiPromise) => {
const Alice = privateKey('//Alice');
const Bob = privateKey('//Bob');
- const Charlie = privateKey('//CHARLIE');
+ const Charlie = privateKey('//Charlie');
// nft
const nftCollectionId = await createCollectionExpectSuccess();
const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
@@ -109,7 +109,7 @@
await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 1);
// reFungible
const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
await transferFromExpectFail(reFungibleCollectionId,
newReFungibleTokenId, Bob, Alice, Charlie, 1);
@@ -120,7 +120,7 @@
await usingApi(async (api: ApiPromise) => {
const Alice = privateKey('//Alice');
const Bob = privateKey('//Bob');
- const Charlie = privateKey('//CHARLIE');
+ const Charlie = privateKey('//Charlie');
// nft
const nftCollectionId = await createCollectionExpectSuccess();
const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
@@ -135,7 +135,7 @@
await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 2);
// reFungible
const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob);
await transferFromExpectFail(reFungibleCollectionId,
@@ -147,8 +147,8 @@
await usingApi(async (api: ApiPromise) => {
const Alice = privateKey('//Alice');
const Bob = privateKey('//Bob');
- const Charlie = privateKey('//CHARLIE');
- const Dave = privateKey('//DAVE');
+ const Charlie = privateKey('//Charlie');
+ const Dave = privateKey('//Dave');
// nft
const nftCollectionId = await createCollectionExpectSuccess();
const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
@@ -174,7 +174,7 @@
}
// reFungible
const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
try {
await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, Dave, Bob);
tests/src/types.tsdiffbeforeafterboth--- a/tests/src/types.ts
+++ b/tests/src/types.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
import BN from 'bn.js';
export interface ICollectionInterface {
tests/src/util/helpers.tsdiffbeforeafterboth1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56import { ApiPromise, Keyring } from '@polkadot/api';7import { Enum, Struct } from '@polkadot/types/codec';8import type { AccountId, EventRecord } from '@polkadot/types/interfaces';9import { u128 } from '@polkadot/types/primitive';10import { IKeyringPair } from '@polkadot/types/types';11import { BigNumber } from 'bignumber.js';12import BN from 'bn.js';13import chai from 'chai';14import chaiAsPromised from 'chai-as-promised';15import { alicesPublicKey, nullPublicKey } from '../accounts';16import privateKey from '../substrate/privateKey';17import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from '../substrate/substrate-api';18import { ICollectionInterface } from '../types';19import { hexToStr, strToUTF16, utf16ToStr } from './util';2021chai.use(chaiAsPromised);22const expect = chai.expect;2324type GenericResult = {25 success: boolean,26};2728interface CreateCollectionResult {29 success: boolean;30 collectionId: number;31}3233interface CreateItemResult {34 success: boolean;35 collectionId: number;36 itemId: number;37}3839interface IReFungibleOwner {40 Fraction: BN;41 Owner: number[];42}4344interface ITokenDataType {45 Owner: number[];46 ConstData: number[];47 VariableData: number[];48}4950interface IFungibleTokenDataType {51 Value: BN;52}5354export interface IReFungibleTokenDataType {55 Owner: IReFungibleOwner[];56 ConstData: number[];57 VariableData: number[];58}5960export function getGenericResult(events: EventRecord[]): GenericResult {61 const result: GenericResult = {62 success: false,63 };64 events.forEach(({ phase, event: { data, method, section } }) => {65 // console.log(` ${phase}: ${section}.${method}:: ${data}`);66 if (method === 'ExtrinsicSuccess') {67 result.success = true;68 }69 });70 return result;71}7273export function getCreateCollectionResult(events: EventRecord[]): CreateCollectionResult {74 let success = false;75 let collectionId: number = 0;76 events.forEach(({ phase, event: { data, method, section } }) => {77 // console.log(` ${phase}: ${section}.${method}:: ${data}`);78 if (method == 'ExtrinsicSuccess') {79 success = true;80 } else if ((section == 'nft') && (method == 'Created')) {81 collectionId = parseInt(data[0].toString());82 }83 });84 const result: CreateCollectionResult = {85 success,86 collectionId,87 };88 return result;89}9091export function getCreateItemResult(events: EventRecord[]): CreateItemResult {92 let success = false;93 let collectionId: number = 0;94 let itemId: number = 0;95 events.forEach(({ phase, event: { data, method, section } }) => {96 // console.log(` ${phase}: ${section}.${method}:: ${data}`);97 if (method == 'ExtrinsicSuccess') {98 success = true;99 } else if ((section == 'nft') && (method == 'ItemCreated')) {100 collectionId = parseInt(data[0].toString());101 itemId = parseInt(data[1].toString());102 }103 });104 const result: CreateItemResult = {105 success,106 collectionId,107 itemId,108 };109 return result;110}111112interface Invalid {113 type: 'Invalid';114}115116interface Nft {117 type: 'NFT';118}119120interface Fungible {121 type: 'Fungible';122 decimalPoints: number;123}124125interface ReFungible {126 type: 'ReFungible';127 decimalPoints: number;128}129130interface Nft {131 type: 'NFT'132}133134interface Fungible {135 type: 'Fungible',136 decimalPoints: number137}138139interface ReFungible {140 type: 'ReFungible',141 decimalPoints: number142}143144type CollectionMode = Nft | Fungible | ReFungible | Invalid;145146export type CreateCollectionParams = {147 mode: CollectionMode,148 name: string,149 description: string,150 tokenPrefix: string,151};152153const defaultCreateCollectionParams: CreateCollectionParams = {154 description: 'description',155 mode: { type: 'NFT' },156 name: 'name',157 tokenPrefix: 'prefix',158}159160export async function createCollectionExpectSuccess(params: Partial<CreateCollectionParams> = {}): Promise<number> {161 const {name, description, mode, tokenPrefix } = {...defaultCreateCollectionParams, ...params};162163 let collectionId: number = 0;164 await usingApi(async (api) => {165 // Get number of collections before the transaction166 const AcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString(), 10);167168 // Run the CreateCollection transaction169 const alicePrivateKey = privateKey('//Alice');170171 let modeprm = {};172 if (mode.type === 'NFT') {173 modeprm = {nft: null};174 } else if (mode.type === 'Fungible') {175 modeprm = {fungible: mode.decimalPoints};176 } else if (mode.type === 'ReFungible') {177 modeprm = {refungible: mode.decimalPoints};178 } else if (mode.type === 'Invalid') {179 modeprm = {invalid: null};180 }181182 const tx = api.tx.nft.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm);183 const events = await submitTransactionAsync(alicePrivateKey, tx);184 const result = getCreateCollectionResult(events);185186 // Get number of collections after the transaction187 const BcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString(), 10);188189 // Get the collection190 const collection: any = (await api.query.nft.collection(result.collectionId)).toJSON();191192 // What to expect193 // tslint:disable-next-line:no-unused-expression194 expect(result.success).to.be.true;195 expect(result.collectionId).to.be.equal(BcollectionCount);196 // tslint:disable-next-line:no-unused-expression197 expect(collection).to.be.not.null;198 expect(BcollectionCount).to.be.equal(AcollectionCount + 1, 'Error: NFT collection NOT created.');199 expect(collection.Owner).to.be.equal(alicesPublicKey);200 expect(utf16ToStr(collection.Name)).to.be.equal(name);201 expect(utf16ToStr(collection.Description)).to.be.equal(description);202 expect(hexToStr(collection.TokenPrefix)).to.be.equal(tokenPrefix);203204 collectionId = result.collectionId;205 });206207 return collectionId;208}209210export async function createCollectionExpectFailure(params: Partial<CreateCollectionParams> = {}) {211 const {name, description, mode, tokenPrefix } = {...defaultCreateCollectionParams, ...params};212213 let modeprm = {};214 if (mode.type === 'NFT') {215 modeprm = {nft: null};216 } else if (mode.type === 'Fungible') {217 modeprm = {fungible: mode.decimalPoints};218 } else if (mode.type === 'ReFungible') {219 modeprm = {refungible: mode.decimalPoints};220 } else if (mode.type === 'Invalid') {221 modeprm = {invalid: null};222 }223224 await usingApi(async (api) => {225 // Get number of collections before the transaction226 const AcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString());227228 // Run the CreateCollection transaction229 const alicePrivateKey = privateKey('//Alice');230 const tx = api.tx.nft.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm);231 const events = await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;232 const result = getCreateCollectionResult(events);233234 // Get number of collections after the transaction235 const BcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString());236237 // What to expect238 // tslint:disable-next-line:no-unused-expression239 expect(result.success).to.be.false;240 expect(BcollectionCount).to.be.equal(AcollectionCount, 'Error: Collection with incorrect data created.');241 });242}243244export async function findUnusedAddress(api: ApiPromise): Promise<IKeyringPair> {245 let bal = new BigNumber(0);246 let unused;247 do {248 const randomSeed = 'seed' + Math.floor(Math.random() * Math.floor(10000));249 const keyring = new Keyring({ type: 'sr25519' });250 unused = keyring.addFromUri(`//${randomSeed}`);251 bal = new BigNumber((await api.query.system.account(unused.address)).data.free.toString());252 } while (bal.toFixed() != '0');253 return unused;254}255256export async function findNotExistingCollection(api: ApiPromise): Promise<number> {257 const totalNumber = parseInt((await api.query.nft.createdCollectionCount()).toString(), 10) as unknown as number;258 const newCollection: number = totalNumber + 1;259 return newCollection;260}261262function getDestroyResult(events: EventRecord[]): boolean {263 let success: boolean = false;264 events.forEach(({ phase, event: { data, method, section } }) => {265 // console.log(` ${phase}: ${section}.${method}:: ${data}`);266 if (method == 'ExtrinsicSuccess') {267 success = true;268 }269 });270 return success;271}272273export async function destroyCollectionExpectFailure(collectionId: number, senderSeed: string = '//Alice') {274 await usingApi(async (api) => {275 // Run the DestroyCollection transaction276 const alicePrivateKey = privateKey(senderSeed);277 const tx = api.tx.nft.destroyCollection(collectionId);278 await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;279 });280}281282export async function destroyCollectionExpectSuccess(collectionId: number, senderSeed: string = '//Alice') {283 await usingApi(async (api) => {284 // Run the DestroyCollection transaction285 const alicePrivateKey = privateKey(senderSeed);286 const tx = api.tx.nft.destroyCollection(collectionId);287 const events = await submitTransactionAsync(alicePrivateKey, tx);288 const result = getDestroyResult(events);289290 // Get the collection291 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();292293 // What to expect294 expect(result).to.be.true;295 expect(collection).to.be.not.null;296 expect(collection.Owner).to.be.equal(nullPublicKey);297 });298}299300export async function setCollectionSponsorExpectSuccess(collectionId: number, sponsor: string) {301 await usingApi(async (api) => {302303 // Run the transaction304 const alicePrivateKey = privateKey('//Alice');305 const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);306 const events = await submitTransactionAsync(alicePrivateKey, tx);307 const result = getGenericResult(events);308309 // Get the collection310 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();311312 // What to expect313 expect(result.success).to.be.true;314 expect(collection.Sponsor.toString()).to.be.equal(sponsor.toString());315 expect(collection.SponsorConfirmed).to.be.false;316 });317}318319export async function removeCollectionSponsorExpectSuccess(collectionId: number) {320 await usingApi(async (api) => {321322 // Run the transaction323 const alicePrivateKey = privateKey('//Alice');324 const tx = api.tx.nft.removeCollectionSponsor(collectionId);325 const events = await submitTransactionAsync(alicePrivateKey, tx);326 const result = getGenericResult(events);327328 // Get the collection329 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();330331 // What to expect332 expect(result.success).to.be.true;333 expect(collection.Sponsor).to.be.equal(nullPublicKey);334 expect(collection.SponsorConfirmed).to.be.false;335 });336}337338export async function removeCollectionSponsorExpectFailure(collectionId: number) {339 await usingApi(async (api) => {340341 // Run the transaction342 const alicePrivateKey = privateKey('//Alice');343 const tx = api.tx.nft.removeCollectionSponsor(collectionId);344 await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;345 });346}347348export async function setCollectionSponsorExpectFailure(collectionId: number, sponsor: string, senderSeed: string = '//Alice') {349 await usingApi(async (api) => {350351 // Run the transaction352 const alicePrivateKey = privateKey(senderSeed);353 const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);354 await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;355 });356}357358export async function confirmSponsorshipExpectSuccess(collectionId: number, senderSeed: string = '//Alice') {359 await usingApi(async (api) => {360361 // Run the transaction362 const sender = privateKey(senderSeed);363 const tx = api.tx.nft.confirmSponsorship(collectionId);364 const events = await submitTransactionAsync(sender, tx);365 const result = getGenericResult(events);366367 // Get the collection368 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();369370 // What to expect371 expect(result.success).to.be.true;372 expect(collection.Sponsor).to.be.equal(sender.address);373 expect(collection.SponsorConfirmed).to.be.true;374 });375}376377export async function confirmSponsorshipExpectFailure(collectionId: number, senderSeed: string = '//Alice') {378 await usingApi(async (api) => {379380 // Run the transaction381 const sender = privateKey(senderSeed);382 const tx = api.tx.nft.confirmSponsorship(collectionId);383 await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;384 });385}386387export async function enableContractSponsoringExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, enable: boolean) {388 await usingApi(async (api) => {389 const tx = api.tx.nft.enableContractSponsoring(contractAddress, enable);390 const events = await submitTransactionAsync(sender, tx);391 const result = getGenericResult(events);392393 expect(result.success).to.be.true;394 });395}396397export async function enableContractSponsoringExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, enable: boolean) {398 await usingApi(async (api) => {399 const tx = api.tx.nft.enableContractSponsoring(contractAddress, enable);400 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;401 const result = getGenericResult(events);402403 expect(result.success).to.be.false;404 });405}406407export async function setContractSponsoringRateLimitExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {408 await usingApi(async (api) => {409 const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);410 const events = await submitTransactionAsync(sender, tx);411 const result = getGenericResult(events);412413 expect(result.success).to.be.true;414 });415}416417export async function setContractSponsoringRateLimitExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {418 await usingApi(async (api) => {419 const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);420 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;421 const result = getGenericResult(events);422423 expect(result.success).to.be.false;424 });425}426427export async function setVariableMetaDataExpectSuccess(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {428 await usingApi(async (api) => {429 const tx = api.tx.nft.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));430 const events = await submitTransactionAsync(sender, tx);431 const result = getGenericResult(events);432433 expect(result.success).to.be.true;434 });435}436437export async function setVariableMetaDataExpectFailure(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {438 await usingApi(async (api) => {439 const tx = api.tx.nft.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));440 await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;441 });442}443444export interface CreateFungibleData extends Struct {445 readonly value: u128;446}447448export interface CreateReFungibleData extends Struct {}449export interface CreateNftData extends Struct {}450451export interface CreateItemData extends Enum {452 NFT: CreateNftData;453 Fungible: CreateFungibleData;454 ReFungible: CreateReFungibleData;455}456457export async function burnItemExpectSuccess(owner: IKeyringPair, collectionId: number, tokenId: number, value = 0) {458 await usingApi(async (api) => {459 const tx = api.tx.nft.burnItem(collectionId, tokenId, value);460 const events = await submitTransactionAsync(owner, tx);461 const result = getGenericResult(events);462 // Get the item463 const item: any = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON();464 // What to expect465 // tslint:disable-next-line:no-unused-expression466 expect(result.success).to.be.true;467 // tslint:disable-next-line:no-unused-expression468 expect(item).to.be.not.null;469 expect(item.Owner).to.be.equal(nullPublicKey);470 });471}472473export async function474approveExpectSuccess(collectionId: number,475 tokenId: number, owner: IKeyringPair, approved: IKeyringPair, amount: number = 1) {476 await usingApi(async (api: ApiPromise) => {477 const allowanceBefore =478 await api.query.nft.allowances(collectionId, [tokenId, owner.address, approved.address]) as unknown as BN;479 const approveNftTx = await api.tx.nft.approve(approved.address, collectionId, tokenId, amount);480 const events = await submitTransactionAsync(owner, approveNftTx);481 const result = getCreateItemResult(events);482 // tslint:disable-next-line:no-unused-expression483 expect(result.success).to.be.true;484 const allowanceAfter =485 await api.query.nft.allowances(collectionId, [tokenId, owner.address, approved.address]) as unknown as BN;486 expect(allowanceAfter.toNumber() - allowanceBefore.toNumber()).to.be.equal(amount);487 });488}489490export async function491transferFromExpectSuccess(collectionId: number,492 tokenId: number,493 accountApproved: IKeyringPair,494 accountFrom: IKeyringPair,495 accountTo: IKeyringPair,496 value: number = 1,497 type: string = 'NFT') {498 await usingApi(async (api: ApiPromise) => {499 let balanceBefore = new BN(0);500 if (type === 'Fungible') {501 balanceBefore = await api.query.nft.balance(collectionId, accountTo.address) as unknown as BN;502 }503 const transferFromTx = await api.tx.nft.transferFrom(504 accountFrom.address, accountTo.address, collectionId, tokenId, value);505 const events = await submitTransactionAsync(accountApproved, transferFromTx);506 const result = getCreateItemResult(events);507 // tslint:disable-next-line:no-unused-expression508 expect(result.success).to.be.true;509 if (type === 'NFT') {510 const nftItemData = await api.query.nft.nftItemList(collectionId, tokenId) as unknown as ITokenDataType;511 expect(nftItemData.Owner.toString()).to.be.equal(accountTo.address);512 }513 if (type === 'Fungible') {514 const balanceAfter = await api.query.nft.balance(collectionId, accountTo.address) as unknown as BN;515 expect(balanceAfter.sub(balanceBefore).toNumber()).to.be.equal(value);516 }517 if (type === 'ReFungible') {518 const nftItemData =519 await api.query.nft.reFungibleItemList(collectionId, tokenId) as unknown as IReFungibleTokenDataType;520 expect(nftItemData.Owner[0].Owner.toString()).to.be.equal(accountTo.address);521 expect(nftItemData.Owner[0].Fraction.toNumber()).to.be.equal(value);522 }523 });524}525526export async function527transferFromExpectFail(collectionId: number,528 tokenId: number,529 accountApproved: IKeyringPair,530 accountFrom: IKeyringPair,531 accountTo: IKeyringPair,532 value: number = 1) {533 await usingApi(async (api: ApiPromise) => {534 const transferFromTx = await api.tx.nft.transferFrom(535 accountFrom.address, accountTo.address, collectionId, tokenId, value);536 const events = await expect(submitTransactionExpectFailAsync(accountApproved, transferFromTx)).to.be.rejected;537 const result = getCreateCollectionResult(events);538 // tslint:disable-next-line:no-unused-expression539 expect(result.success).to.be.false;540 });541}542543export async function544transferExpectSuccess(collectionId: number,545 tokenId: number,546 sender: IKeyringPair,547 recipient: IKeyringPair,548 value: number = 1,549 type: string = 'NFT') {550 await usingApi(async (api: ApiPromise) => {551 let balanceBefore = new BN(0);552 if (type === 'Fungible') {553 balanceBefore = await api.query.nft.balance(collectionId, recipient.address) as unknown as BN;554 }555 const transferTx = await api.tx.nft.transfer(recipient.address, collectionId, tokenId, value);556 const events = await submitTransactionAsync(sender, transferTx);557 const result = getCreateItemResult(events);558 // tslint:disable-next-line:no-unused-expression559 expect(result.success).to.be.true;560 if (type === 'NFT') {561 const nftItemData = await api.query.nft.nftItemList(collectionId, tokenId) as unknown as ITokenDataType;562 expect(nftItemData.Owner.toString()).to.be.equal(recipient.address);563 }564 if (type === 'Fungible') {565 const balanceAfter = await api.query.nft.balance(collectionId, recipient.address) as unknown as BN;566 expect(balanceAfter.sub(balanceBefore).toNumber()).to.be.equal(value);567 }568 if (type === 'ReFungible') {569 const nftItemData =570 await api.query.nft.reFungibleItemList(collectionId, tokenId) as unknown as IReFungibleTokenDataType;571 expect(nftItemData.Owner[0].Owner.toString()).to.be.equal(recipient.address);572 expect(nftItemData.Owner[0].Fraction.toNumber()).to.be.equal(value);573 }574 });575}576577export async function578transferExpectFail(collectionId: number,579 tokenId: number,580 sender: IKeyringPair,581 recipient: IKeyringPair,582 value: number = 1,583 type: string = 'NFT') {584 await usingApi(async (api: ApiPromise) => {585 const transferTx = await api.tx.nft.transfer(recipient.address, collectionId, tokenId, value);586 const events = await expect(submitTransactionExpectFailAsync(sender, transferTx)).to.be.rejected;587 if (events && Array.isArray(events)) {588 const result = getCreateCollectionResult(events);589 // tslint:disable-next-line:no-unused-expression590 expect(result.success).to.be.false;591 }592 });593}594595export async function596approveExpectFail(collectionId: number,597 tokenId: number, owner: IKeyringPair, approved: IKeyringPair, amount: number = 1) {598 await usingApi(async (api: ApiPromise) => {599 const approveNftTx = await api.tx.nft.approve(approved.address, collectionId, tokenId, amount);600 const events = await expect(submitTransactionExpectFailAsync(owner, approveNftTx)).to.be.rejected;601 const result = getCreateCollectionResult(events);602 // tslint:disable-next-line:no-unused-expression603 expect(result.success).to.be.false;604 });605}606607export async function createItemExpectSuccess(608 sender: IKeyringPair, collectionId: number, createMode: string, owner: string = '') {609 let newItemId: number = 0;610 await usingApi(async (api) => {611 const AItemCount = parseInt((await api.query.nft.itemListIndex(collectionId)).toString(), 10);612 const Aitem: any = (await api.query.nft.fungibleItemList(collectionId, owner)).toJSON();613 const AItemBalance = new BigNumber(Aitem.Value);614615 if (owner === '') {616 owner = sender.address;617 }618619 let tx;620 if (createMode === 'Fungible') {621 const createData = {fungible: {value: 10}};622 tx = api.tx.nft.createItem(collectionId, owner, createData);623 } else {624 tx = api.tx.nft.createItem(collectionId, owner, createMode);625 }626 const events = await submitTransactionAsync(sender, tx);627 const result = getCreateItemResult(events);628629 const BItemCount = parseInt((await api.query.nft.itemListIndex(collectionId)).toString(), 10);630 const Bitem: any = (await api.query.nft.fungibleItemList(collectionId, owner)).toJSON();631 const BItemBalance = new BigNumber(Bitem.Value);632633 // What to expect634 // tslint:disable-next-line:no-unused-expression635 expect(result.success).to.be.true;636 if (createMode === 'Fungible') {637 expect(BItemBalance.minus(AItemBalance).toNumber()).to.be.equal(10);638 } else {639 expect(BItemCount).to.be.equal(AItemCount + 1);640 }641 expect(collectionId).to.be.equal(result.collectionId);642 expect(BItemCount).to.be.equal(result.itemId);643 newItemId = result.itemId;644 });645 return newItemId;646}647648export async function createItemExpectFailure(649 sender: IKeyringPair, collectionId: number, createMode: string, owner: string = sender.address) {650 await usingApi(async (api) => {651 const tx = api.tx.nft.createItem(collectionId, owner, createMode);652 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;653 const result = getCreateItemResult(events);654655 expect(result.success).to.be.false;656 });657}658659export async function setPublicAccessModeExpectSuccess(660 sender: IKeyringPair, collectionId: number,661 accessMode: 'Normal' | 'WhiteList',662) {663 await usingApi(async (api) => {664665 // Run the transaction666 const tx = api.tx.nft.setPublicAccessMode(collectionId, accessMode);667 const events = await submitTransactionAsync(sender, tx);668 const result = getGenericResult(events);669670 // Get the collection671 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();672673 // What to expect674 // tslint:disable-next-line:no-unused-expression675 expect(result.success).to.be.true;676 expect(collection.Access).to.be.equal(accessMode);677 });678}679680export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {681 await setPublicAccessModeExpectSuccess(sender, collectionId, 'WhiteList');682}683684export async function disableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {685 await setPublicAccessModeExpectSuccess(sender, collectionId, 'Normal');686}687688export async function setMintPermissionExpectSuccess(sender: IKeyringPair, collectionId: number, enabled: boolean) {689 await usingApi(async (api) => {690691 // Run the transaction692 const tx = api.tx.nft.setMintPermission(collectionId, enabled);693 const events = await submitTransactionAsync(sender, tx);694 const result = getGenericResult(events);695696 // Get the collection697 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();698699 // What to expect700 // tslint:disable-next-line:no-unused-expression701 expect(result.success).to.be.true;702 expect(collection.MintMode).to.be.equal(enabled);703 });704}705706export async function enablePublicMintingExpectSuccess(sender: IKeyringPair, collectionId: number) {707 await setMintPermissionExpectSuccess(sender, collectionId, true);708}709710export async function setMintPermissionExpectFailure(sender: IKeyringPair, collectionId: number, enabled: boolean) {711 await usingApi(async (api) => {712 // Run the transaction713 const tx = api.tx.nft.setMintPermission(collectionId, enabled);714 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;715 const result = getCreateCollectionResult(events);716 // tslint:disable-next-line:no-unused-expression717 expect(result.success).to.be.false;718 });719}720721export async function isWhitelisted(collectionId: number, address: string) {722 let whitelisted: boolean = false;723 await usingApi(async (api) => {724 whitelisted = (await api.query.nft.whiteList(collectionId, address)).toJSON() as unknown as boolean;725 });726 return whitelisted;727}728729export async function addToWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {730 await usingApi(async (api) => {731732 const whiteListedBefore = (await api.query.nft.whiteList(collectionId, address)).toJSON();733734 // Run the transaction735 const tx = api.tx.nft.addToWhiteList(collectionId, address);736 const events = await submitTransactionAsync(sender, tx);737 const result = getGenericResult(events);738739 const whiteListedAfter = (await api.query.nft.whiteList(collectionId, address)).toJSON();740741 // What to expect742 // tslint:disable-next-line:no-unused-expression743 expect(result.success).to.be.true;744 // tslint:disable-next-line: no-unused-expression745 expect(whiteListedBefore).to.be.false;746 // tslint:disable-next-line: no-unused-expression747 expect(whiteListedAfter).to.be.true;748 });749}750751export async function removeFromWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {752 await usingApi(async (api) => {753 // Run the transaction754 const tx = api.tx.nft.removeFromWhiteList(collectionId, address);755 const events = await submitTransactionAsync(sender, tx);756 const result = getGenericResult(events);757758 // What to expect759 // tslint:disable-next-line:no-unused-expression760 expect(result.success).to.be.true;761 });762}763764export async function removeFromWhiteListExpectFailure(sender: IKeyringPair, collectionId: number, address: string) {765 await usingApi(async (api) => {766 // Run the transaction767 const tx = api.tx.nft.removeFromWhiteList(collectionId, address);768 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;769 const result = getGenericResult(events);770771 // What to expect772 // tslint:disable-next-line:no-unused-expression773 expect(result.success).to.be.false;774 });775}776777export const getDetailedCollectionInfo = async (api: ApiPromise, collectionId: number)778 : Promise<ICollectionInterface | null> => {779 return await api.query.nft.collection(collectionId) as unknown as ICollectionInterface;780};781782export const getCreatedCollectionCount = async (api: ApiPromise): Promise<number> => {783 // set global object - collectionsCount784 return (await api.query.nft.createdCollectionCount() as unknown as BN).toNumber();785};1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56import { ApiPromise, Keyring } from '@polkadot/api';7import { Enum, Struct } from '@polkadot/types/codec';8import type { AccountId, EventRecord } from '@polkadot/types/interfaces';9import { u128 } from '@polkadot/types/primitive';10import { IKeyringPair } from '@polkadot/types/types';11import { BigNumber } from 'bignumber.js';12import BN from 'bn.js';13import chai from 'chai';14import chaiAsPromised from 'chai-as-promised';15import { alicesPublicKey, nullPublicKey } from '../accounts';16import privateKey from '../substrate/privateKey';17import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from '../substrate/substrate-api';18import { ICollectionInterface } from '../types';19import { hexToStr, strToUTF16, utf16ToStr } from './util';2021chai.use(chaiAsPromised);22const expect = chai.expect;2324type GenericResult = {25 success: boolean,26};2728interface CreateCollectionResult {29 success: boolean;30 collectionId: number;31}3233interface CreateItemResult {34 success: boolean;35 collectionId: number;36 itemId: number;37}3839interface IReFungibleOwner {40 Fraction: BN;41 Owner: number[];42}4344interface ITokenDataType {45 Owner: number[];46 ConstData: number[];47 VariableData: number[];48}4950interface IFungibleTokenDataType {51 Value: BN;52}5354export interface IReFungibleTokenDataType {55 Owner: IReFungibleOwner[];56 ConstData: number[];57 VariableData: number[];58}5960export function getGenericResult(events: EventRecord[]): GenericResult {61 const result: GenericResult = {62 success: false,63 };64 events.forEach(({ phase, event: { data, method, section } }) => {65 // console.log(` ${phase}: ${section}.${method}:: ${data}`);66 if (method === 'ExtrinsicSuccess') {67 result.success = true;68 }69 });70 return result;71}7273export function getCreateCollectionResult(events: EventRecord[]): CreateCollectionResult {74 let success = false;75 let collectionId: number = 0;76 events.forEach(({ phase, event: { data, method, section } }) => {77 // console.log(` ${phase}: ${section}.${method}:: ${data}`);78 if (method == 'ExtrinsicSuccess') {79 success = true;80 } else if ((section == 'nft') && (method == 'Created')) {81 collectionId = parseInt(data[0].toString());82 }83 });84 const result: CreateCollectionResult = {85 success,86 collectionId,87 };88 return result;89}9091export function getCreateItemResult(events: EventRecord[]): CreateItemResult {92 let success = false;93 let collectionId: number = 0;94 let itemId: number = 0;95 events.forEach(({ phase, event: { data, method, section } }) => {96 // console.log(` ${phase}: ${section}.${method}:: ${data}`);97 if (method == 'ExtrinsicSuccess') {98 success = true;99 } else if ((section == 'nft') && (method == 'ItemCreated')) {100 collectionId = parseInt(data[0].toString());101 itemId = parseInt(data[1].toString());102 }103 });104 const result: CreateItemResult = {105 success,106 collectionId,107 itemId,108 };109 return result;110}111112interface Invalid {113 type: 'Invalid';114}115116interface Nft {117 type: 'NFT';118}119120interface Fungible {121 type: 'Fungible';122 decimalPoints: number;123}124125interface ReFungible {126 type: 'ReFungible';127}128129type CollectionMode = Nft | Fungible | ReFungible | Invalid;130131export type CreateCollectionParams = {132 mode: CollectionMode,133 name: string,134 description: string,135 tokenPrefix: string,136};137138const defaultCreateCollectionParams: CreateCollectionParams = {139 description: 'description',140 mode: { type: 'NFT' },141 name: 'name',142 tokenPrefix: 'prefix',143}144145export async function createCollectionExpectSuccess(params: Partial<CreateCollectionParams> = {}): Promise<number> {146 const {name, description, mode, tokenPrefix } = {...defaultCreateCollectionParams, ...params};147148 let collectionId: number = 0;149 await usingApi(async (api) => {150 // Get number of collections before the transaction151 const AcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString(), 10);152153 // Run the CreateCollection transaction154 const alicePrivateKey = privateKey('//Alice');155156 let modeprm = {};157 if (mode.type === 'NFT') {158 modeprm = {nft: null};159 } else if (mode.type === 'Fungible') {160 modeprm = {fungible: mode.decimalPoints};161 } else if (mode.type === 'ReFungible') {162 modeprm = {refungible: null};163 } else if (mode.type === 'Invalid') {164 modeprm = {invalid: null};165 }166167 const tx = api.tx.nft.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm);168 const events = await submitTransactionAsync(alicePrivateKey, tx);169 const result = getCreateCollectionResult(events);170171 // Get number of collections after the transaction172 const BcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString(), 10);173174 // Get the collection175 const collection: any = (await api.query.nft.collection(result.collectionId)).toJSON();176177 // What to expect178 // tslint:disable-next-line:no-unused-expression179 expect(result.success).to.be.true;180 expect(result.collectionId).to.be.equal(BcollectionCount);181 // tslint:disable-next-line:no-unused-expression182 expect(collection).to.be.not.null;183 expect(BcollectionCount).to.be.equal(AcollectionCount + 1, 'Error: NFT collection NOT created.');184 expect(collection.Owner).to.be.equal(alicesPublicKey);185 expect(utf16ToStr(collection.Name)).to.be.equal(name);186 expect(utf16ToStr(collection.Description)).to.be.equal(description);187 expect(hexToStr(collection.TokenPrefix)).to.be.equal(tokenPrefix);188189 collectionId = result.collectionId;190 });191192 return collectionId;193}194195export async function createCollectionExpectFailure(params: Partial<CreateCollectionParams> = {}) {196 const {name, description, mode, tokenPrefix } = {...defaultCreateCollectionParams, ...params};197198 let modeprm = {};199 if (mode.type === 'NFT') {200 modeprm = {nft: null};201 } else if (mode.type === 'Fungible') {202 modeprm = {fungible: mode.decimalPoints};203 } else if (mode.type === 'ReFungible') {204 modeprm = {refungible: null};205 } else if (mode.type === 'Invalid') {206 modeprm = {invalid: null};207 }208209 await usingApi(async (api) => {210 // Get number of collections before the transaction211 const AcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString());212213 // Run the CreateCollection transaction214 const alicePrivateKey = privateKey('//Alice');215 const tx = api.tx.nft.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm);216 const events = await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;217 const result = getCreateCollectionResult(events);218219 // Get number of collections after the transaction220 const BcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString());221222 // What to expect223 // tslint:disable-next-line:no-unused-expression224 expect(result.success).to.be.false;225 expect(BcollectionCount).to.be.equal(AcollectionCount, 'Error: Collection with incorrect data created.');226 });227}228229export async function findUnusedAddress(api: ApiPromise): Promise<IKeyringPair> {230 let bal = new BigNumber(0);231 let unused;232 do {233 const randomSeed = 'seed' + Math.floor(Math.random() * Math.floor(10000));234 const keyring = new Keyring({ type: 'sr25519' });235 unused = keyring.addFromUri(`//${randomSeed}`);236 bal = new BigNumber((await api.query.system.account(unused.address)).data.free.toString());237 } while (bal.toFixed() != '0');238 return unused;239}240241export async function findNotExistingCollection(api: ApiPromise): Promise<number> {242 const totalNumber = parseInt((await api.query.nft.createdCollectionCount()).toString(), 10) as unknown as number;243 const newCollection: number = totalNumber + 1;244 return newCollection;245}246247function getDestroyResult(events: EventRecord[]): boolean {248 let success: boolean = false;249 events.forEach(({ phase, event: { data, method, section } }) => {250 // console.log(` ${phase}: ${section}.${method}:: ${data}`);251 if (method == 'ExtrinsicSuccess') {252 success = true;253 }254 });255 return success;256}257258export async function destroyCollectionExpectFailure(collectionId: number, senderSeed: string = '//Alice') {259 await usingApi(async (api) => {260 // Run the DestroyCollection transaction261 const alicePrivateKey = privateKey(senderSeed);262 const tx = api.tx.nft.destroyCollection(collectionId);263 await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;264 });265}266267export async function destroyCollectionExpectSuccess(collectionId: number, senderSeed: string = '//Alice') {268 await usingApi(async (api) => {269 // Run the DestroyCollection transaction270 const alicePrivateKey = privateKey(senderSeed);271 const tx = api.tx.nft.destroyCollection(collectionId);272 const events = await submitTransactionAsync(alicePrivateKey, tx);273 const result = getDestroyResult(events);274275 // Get the collection276 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();277278 // What to expect279 expect(result).to.be.true;280 expect(collection).to.be.not.null;281 expect(collection.Owner).to.be.equal(nullPublicKey);282 });283}284285export async function setCollectionSponsorExpectSuccess(collectionId: number, sponsor: string) {286 await usingApi(async (api) => {287288 // Run the transaction289 const alicePrivateKey = privateKey('//Alice');290 const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);291 const events = await submitTransactionAsync(alicePrivateKey, tx);292 const result = getGenericResult(events);293294 // Get the collection295 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();296297 // What to expect298 expect(result.success).to.be.true;299 expect(collection.Sponsor.toString()).to.be.equal(sponsor.toString());300 expect(collection.SponsorConfirmed).to.be.false;301 });302}303304export async function removeCollectionSponsorExpectSuccess(collectionId: number) {305 await usingApi(async (api) => {306307 // Run the transaction308 const alicePrivateKey = privateKey('//Alice');309 const tx = api.tx.nft.removeCollectionSponsor(collectionId);310 const events = await submitTransactionAsync(alicePrivateKey, tx);311 const result = getGenericResult(events);312313 // Get the collection314 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();315316 // What to expect317 expect(result.success).to.be.true;318 expect(collection.Sponsor).to.be.equal(nullPublicKey);319 expect(collection.SponsorConfirmed).to.be.false;320 });321}322323export async function removeCollectionSponsorExpectFailure(collectionId: number) {324 await usingApi(async (api) => {325326 // Run the transaction327 const alicePrivateKey = privateKey('//Alice');328 const tx = api.tx.nft.removeCollectionSponsor(collectionId);329 await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;330 });331}332333export async function setCollectionSponsorExpectFailure(collectionId: number, sponsor: string, senderSeed: string = '//Alice') {334 await usingApi(async (api) => {335336 // Run the transaction337 const alicePrivateKey = privateKey(senderSeed);338 const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);339 await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;340 });341}342343export async function confirmSponsorshipExpectSuccess(collectionId: number, senderSeed: string = '//Alice') {344 await usingApi(async (api) => {345346 // Run the transaction347 const sender = privateKey(senderSeed);348 const tx = api.tx.nft.confirmSponsorship(collectionId);349 const events = await submitTransactionAsync(sender, tx);350 const result = getGenericResult(events);351352 // Get the collection353 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();354355 // What to expect356 expect(result.success).to.be.true;357 expect(collection.Sponsor).to.be.equal(sender.address);358 expect(collection.SponsorConfirmed).to.be.true;359 });360}361362export async function confirmSponsorshipExpectFailure(collectionId: number, senderSeed: string = '//Alice') {363 await usingApi(async (api) => {364365 // Run the transaction366 const sender = privateKey(senderSeed);367 const tx = api.tx.nft.confirmSponsorship(collectionId);368 await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;369 });370}371372export async function enableContractSponsoringExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, enable: boolean) {373 await usingApi(async (api) => {374 const tx = api.tx.nft.enableContractSponsoring(contractAddress, enable);375 const events = await submitTransactionAsync(sender, tx);376 const result = getGenericResult(events);377378 expect(result.success).to.be.true;379 });380}381382export async function enableContractSponsoringExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, enable: boolean) {383 await usingApi(async (api) => {384 const tx = api.tx.nft.enableContractSponsoring(contractAddress, enable);385 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;386 const result = getGenericResult(events);387388 expect(result.success).to.be.false;389 });390}391392export async function setContractSponsoringRateLimitExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {393 await usingApi(async (api) => {394 const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);395 const events = await submitTransactionAsync(sender, tx);396 const result = getGenericResult(events);397398 expect(result.success).to.be.true;399 });400}401402export async function setContractSponsoringRateLimitExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {403 await usingApi(async (api) => {404 const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);405 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;406 const result = getGenericResult(events);407408 expect(result.success).to.be.false;409 });410}411412export async function toggleContractWhitelistExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, enabled: boolean) {413 await usingApi(async (api) => {414 const tx = api.tx.nft.toggleContractWhiteList(contractAddress, true);415 const events = await submitTransactionAsync(sender, tx);416 const result = getGenericResult(events);417418 expect(result.success).to.be.true;419 });420}421422export async function isWhitelistedInContract(contractAddress: AccountId | string, user: string) {423 let whitelisted: boolean = false;424 await usingApi(async (api) => {425 whitelisted = (await api.query.nft.contractWhiteList(contractAddress, user)).toJSON() as boolean;426 });427 return whitelisted;428}429430export async function addToContractWhiteListExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, user: string) {431 await usingApi(async (api) => {432 const tx = api.tx.nft.addToContractWhiteList(contractAddress, user);433 const events = await submitTransactionAsync(sender, tx);434 const result = getGenericResult(events);435436 expect(result.success).to.be.true;437 });438}439440export async function removeFromContractWhiteListExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, user: string) {441 await usingApi(async (api) => {442 const tx = api.tx.nft.removeFromContractWhiteList(contractAddress, user);443 const events = await submitTransactionAsync(sender, tx);444 const result = getGenericResult(events);445446 expect(result.success).to.be.true;447 });448}449450export async function removeFromContractWhiteListExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, user: string) {451 await usingApi(async (api) => {452 const tx = api.tx.nft.removeFromContractWhiteList(contractAddress, user);453 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;454 const result = getGenericResult(events);455456 expect(result.success).to.be.false;457 });458}459460export async function setVariableMetaDataExpectSuccess(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {461 await usingApi(async (api) => {462 const tx = api.tx.nft.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));463 const events = await submitTransactionAsync(sender, tx);464 const result = getGenericResult(events);465466 expect(result.success).to.be.true;467 });468}469470export async function setVariableMetaDataExpectFailure(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {471 await usingApi(async (api) => {472 const tx = api.tx.nft.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));473 await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;474 });475}476477export interface CreateFungibleData extends Struct {478 readonly value: u128;479}480481export interface CreateReFungibleData extends Struct {}482export interface CreateNftData extends Struct {}483484export interface CreateItemData extends Enum {485 NFT: CreateNftData;486 Fungible: CreateFungibleData;487 ReFungible: CreateReFungibleData;488}489490export async function burnItemExpectSuccess(owner: IKeyringPair, collectionId: number, tokenId: number, value = 0) {491 await usingApi(async (api) => {492 const tx = api.tx.nft.burnItem(collectionId, tokenId, value);493 const events = await submitTransactionAsync(owner, tx);494 const result = getGenericResult(events);495 // Get the item496 const item: any = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON();497 // What to expect498 // tslint:disable-next-line:no-unused-expression499 expect(result.success).to.be.true;500 // tslint:disable-next-line:no-unused-expression501 expect(item).to.be.not.null;502 expect(item.Owner).to.be.equal(nullPublicKey);503 });504}505506export async function507approveExpectSuccess(collectionId: number,508 tokenId: number, owner: IKeyringPair, approved: IKeyringPair, amount: number = 1) {509 await usingApi(async (api: ApiPromise) => {510 const allowanceBefore =511 await api.query.nft.allowances(collectionId, [tokenId, owner.address, approved.address]) as unknown as BN;512 const approveNftTx = await api.tx.nft.approve(approved.address, collectionId, tokenId, amount);513 const events = await submitTransactionAsync(owner, approveNftTx);514 const result = getCreateItemResult(events);515 // tslint:disable-next-line:no-unused-expression516 expect(result.success).to.be.true;517 const allowanceAfter =518 await api.query.nft.allowances(collectionId, [tokenId, owner.address, approved.address]) as unknown as BN;519 expect(allowanceAfter.toNumber() - allowanceBefore.toNumber()).to.be.equal(amount);520 });521}522523export async function524transferFromExpectSuccess(collectionId: number,525 tokenId: number,526 accountApproved: IKeyringPair,527 accountFrom: IKeyringPair,528 accountTo: IKeyringPair,529 value: number = 1,530 type: string = 'NFT') {531 await usingApi(async (api: ApiPromise) => {532 let balanceBefore = new BN(0);533 if (type === 'Fungible') {534 balanceBefore = await api.query.nft.balance(collectionId, accountTo.address) as unknown as BN;535 }536 const transferFromTx = await api.tx.nft.transferFrom(537 accountFrom.address, accountTo.address, collectionId, tokenId, value);538 const events = await submitTransactionAsync(accountApproved, transferFromTx);539 const result = getCreateItemResult(events);540 // tslint:disable-next-line:no-unused-expression541 expect(result.success).to.be.true;542 if (type === 'NFT') {543 const nftItemData = await api.query.nft.nftItemList(collectionId, tokenId) as unknown as ITokenDataType;544 expect(nftItemData.Owner.toString()).to.be.equal(accountTo.address);545 }546 if (type === 'Fungible') {547 const balanceAfter = await api.query.nft.balance(collectionId, accountTo.address) as unknown as BN;548 expect(balanceAfter.sub(balanceBefore).toNumber()).to.be.equal(value);549 }550 if (type === 'ReFungible') {551 const nftItemData =552 await api.query.nft.reFungibleItemList(collectionId, tokenId) as unknown as IReFungibleTokenDataType;553 expect(nftItemData.Owner[0].Owner.toString()).to.be.equal(accountTo.address);554 expect(nftItemData.Owner[0].Fraction.toNumber()).to.be.equal(value);555 }556 });557}558559export async function560transferFromExpectFail(collectionId: number,561 tokenId: number,562 accountApproved: IKeyringPair,563 accountFrom: IKeyringPair,564 accountTo: IKeyringPair,565 value: number = 1) {566 await usingApi(async (api: ApiPromise) => {567 const transferFromTx = await api.tx.nft.transferFrom(568 accountFrom.address, accountTo.address, collectionId, tokenId, value);569 const events = await expect(submitTransactionExpectFailAsync(accountApproved, transferFromTx)).to.be.rejected;570 const result = getCreateCollectionResult(events);571 // tslint:disable-next-line:no-unused-expression572 expect(result.success).to.be.false;573 });574}575576export async function577transferExpectSuccess(collectionId: number,578 tokenId: number,579 sender: IKeyringPair,580 recipient: IKeyringPair,581 value: number = 1,582 type: string = 'NFT') {583 await usingApi(async (api: ApiPromise) => {584 let balanceBefore = new BN(0);585 if (type === 'Fungible') {586 balanceBefore = await api.query.nft.balance(collectionId, recipient.address) as unknown as BN;587 }588 const transferTx = await api.tx.nft.transfer(recipient.address, collectionId, tokenId, value);589 const events = await submitTransactionAsync(sender, transferTx);590 const result = getCreateItemResult(events);591 // tslint:disable-next-line:no-unused-expression592 expect(result.success).to.be.true;593 if (type === 'NFT') {594 const nftItemData = await api.query.nft.nftItemList(collectionId, tokenId) as unknown as ITokenDataType;595 expect(nftItemData.Owner.toString()).to.be.equal(recipient.address);596 }597 if (type === 'Fungible') {598 const balanceAfter = await api.query.nft.balance(collectionId, recipient.address) as unknown as BN;599 expect(balanceAfter.sub(balanceBefore).toNumber()).to.be.equal(value);600 }601 if (type === 'ReFungible') {602 const nftItemData =603 await api.query.nft.reFungibleItemList(collectionId, tokenId) as unknown as IReFungibleTokenDataType;604 expect(nftItemData.Owner[0].Owner.toString()).to.be.equal(recipient.address);605 expect(nftItemData.Owner[0].Fraction.toNumber()).to.be.equal(value);606 }607 });608}609610export async function611transferExpectFail(collectionId: number,612 tokenId: number,613 sender: IKeyringPair,614 recipient: IKeyringPair,615 value: number = 1,616 type: string = 'NFT') {617 await usingApi(async (api: ApiPromise) => {618 const transferTx = await api.tx.nft.transfer(recipient.address, collectionId, tokenId, value);619 const events = await expect(submitTransactionExpectFailAsync(sender, transferTx)).to.be.rejected;620 if (events && Array.isArray(events)) {621 const result = getCreateCollectionResult(events);622 // tslint:disable-next-line:no-unused-expression623 expect(result.success).to.be.false;624 }625 });626}627628export async function629approveExpectFail(collectionId: number,630 tokenId: number, owner: IKeyringPair, approved: IKeyringPair, amount: number = 1) {631 await usingApi(async (api: ApiPromise) => {632 const approveNftTx = await api.tx.nft.approve(approved.address, collectionId, tokenId, amount);633 const events = await expect(submitTransactionExpectFailAsync(owner, approveNftTx)).to.be.rejected;634 const result = getCreateCollectionResult(events);635 // tslint:disable-next-line:no-unused-expression636 expect(result.success).to.be.false;637 });638}639640export async function createItemExpectSuccess(641 sender: IKeyringPair, collectionId: number, createMode: string, owner: string = '') {642 let newItemId: number = 0;643 await usingApi(async (api) => {644 const AItemCount = parseInt((await api.query.nft.itemListIndex(collectionId)).toString(), 10);645 const Aitem: any = (await api.query.nft.fungibleItemList(collectionId, owner)).toJSON();646 const AItemBalance = new BigNumber(Aitem.Value);647648 if (owner === '') {649 owner = sender.address;650 }651652 let tx;653 if (createMode === 'Fungible') {654 const createData = {fungible: {value: 10}};655 tx = api.tx.nft.createItem(collectionId, owner, createData);656 } else if (createMode === 'ReFungible') {657 const createData = {refungible: {const_data: [], variable_data: [], pieces: 100}};658 tx = api.tx.nft.createItem(collectionId, owner, createData);659 } else {660 tx = api.tx.nft.createItem(collectionId, owner, createMode);661 }662 const events = await submitTransactionAsync(sender, tx);663 const result = getCreateItemResult(events);664665 const BItemCount = parseInt((await api.query.nft.itemListIndex(collectionId)).toString(), 10);666 const Bitem: any = (await api.query.nft.fungibleItemList(collectionId, owner)).toJSON();667 const BItemBalance = new BigNumber(Bitem.Value);668669 // What to expect670 // tslint:disable-next-line:no-unused-expression671 expect(result.success).to.be.true;672 if (createMode === 'Fungible') {673 expect(BItemBalance.minus(AItemBalance).toNumber()).to.be.equal(10);674 } else {675 expect(BItemCount).to.be.equal(AItemCount + 1);676 }677 expect(collectionId).to.be.equal(result.collectionId);678 expect(BItemCount).to.be.equal(result.itemId);679 newItemId = result.itemId;680 });681 return newItemId;682}683684export async function createItemExpectFailure(685 sender: IKeyringPair, collectionId: number, createMode: string, owner: string = sender.address) {686 await usingApi(async (api) => {687 const tx = api.tx.nft.createItem(collectionId, owner, createMode);688 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;689 const result = getCreateItemResult(events);690691 expect(result.success).to.be.false;692 });693}694695export async function setPublicAccessModeExpectSuccess(696 sender: IKeyringPair, collectionId: number,697 accessMode: 'Normal' | 'WhiteList',698) {699 await usingApi(async (api) => {700701 // Run the transaction702 const tx = api.tx.nft.setPublicAccessMode(collectionId, accessMode);703 const events = await submitTransactionAsync(sender, tx);704 const result = getGenericResult(events);705706 // Get the collection707 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();708709 // What to expect710 // tslint:disable-next-line:no-unused-expression711 expect(result.success).to.be.true;712 expect(collection.Access).to.be.equal(accessMode);713 });714}715716export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {717 await setPublicAccessModeExpectSuccess(sender, collectionId, 'WhiteList');718}719720export async function disableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {721 await setPublicAccessModeExpectSuccess(sender, collectionId, 'Normal');722}723724export async function setMintPermissionExpectSuccess(sender: IKeyringPair, collectionId: number, enabled: boolean) {725 await usingApi(async (api) => {726727 // Run the transaction728 const tx = api.tx.nft.setMintPermission(collectionId, enabled);729 const events = await submitTransactionAsync(sender, tx);730 const result = getGenericResult(events);731732 // Get the collection733 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();734735 // What to expect736 // tslint:disable-next-line:no-unused-expression737 expect(result.success).to.be.true;738 expect(collection.MintMode).to.be.equal(enabled);739 });740}741742export async function enablePublicMintingExpectSuccess(sender: IKeyringPair, collectionId: number) {743 await setMintPermissionExpectSuccess(sender, collectionId, true);744}745746export async function setMintPermissionExpectFailure(sender: IKeyringPair, collectionId: number, enabled: boolean) {747 await usingApi(async (api) => {748 // Run the transaction749 const tx = api.tx.nft.setMintPermission(collectionId, enabled);750 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;751 const result = getCreateCollectionResult(events);752 // tslint:disable-next-line:no-unused-expression753 expect(result.success).to.be.false;754 });755}756757export async function isWhitelisted(collectionId: number, address: string) {758 let whitelisted: boolean = false;759 await usingApi(async (api) => {760 whitelisted = (await api.query.nft.whiteList(collectionId, address)).toJSON() as unknown as boolean;761 });762 return whitelisted;763}764765export async function addToWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {766 await usingApi(async (api) => {767768 const whiteListedBefore = (await api.query.nft.whiteList(collectionId, address)).toJSON();769770 // Run the transaction771 const tx = api.tx.nft.addToWhiteList(collectionId, address);772 const events = await submitTransactionAsync(sender, tx);773 const result = getGenericResult(events);774775 const whiteListedAfter = (await api.query.nft.whiteList(collectionId, address)).toJSON();776777 // What to expect778 // tslint:disable-next-line:no-unused-expression779 expect(result.success).to.be.true;780 // tslint:disable-next-line: no-unused-expression781 expect(whiteListedBefore).to.be.false;782 // tslint:disable-next-line: no-unused-expression783 expect(whiteListedAfter).to.be.true;784 });785}786787export async function removeFromWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {788 await usingApi(async (api) => {789 // Run the transaction790 const tx = api.tx.nft.removeFromWhiteList(collectionId, address);791 const events = await submitTransactionAsync(sender, tx);792 const result = getGenericResult(events);793794 // What to expect795 // tslint:disable-next-line:no-unused-expression796 expect(result.success).to.be.true;797 });798}799800export async function removeFromWhiteListExpectFailure(sender: IKeyringPair, collectionId: number, address: string) {801 await usingApi(async (api) => {802 // Run the transaction803 const tx = api.tx.nft.removeFromWhiteList(collectionId, address);804 const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;805 const result = getGenericResult(events);806807 // What to expect808 // tslint:disable-next-line:no-unused-expression809 expect(result.success).to.be.false;810 });811}812813export const getDetailedCollectionInfo = async (api: ApiPromise, collectionId: number)814 : Promise<ICollectionInterface | null> => {815 return await api.query.nft.collection(collectionId) as unknown as ICollectionInterface;816};817818export const getCreatedCollectionCount = async (api: ApiPromise): Promise<number> => {819 // set global object - collectionsCount820 return (await api.query.nft.createdCollectionCount() as unknown as BN).toNumber();821};