difftreelog
Merge branch 'develop' into feature/NFTPAR-243_enableContractSponsoring
in: master
12 files changed
.devcontainer/Dockerfilediffbeforeafterboth--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,14 @@
+FROM mcr.microsoft.com/vscode/devcontainers/rust:0-1
+
+RUN apt-get update && export DEBIAN_FRONTEND=noninteractive && \
+ apt-get -y install --no-install-recommends libssl-dev pkg-config libclang-dev clang
+
+USER vscode
+
+RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash && \
+ export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" && \
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
+ nvm install v12.20.1 && \
+ rustup toolchain install nightly-2020-10-01 && \
+ rustup default nightly-2020-10-01 && \
+ rustup target add wasm32-unknown-unknown
\ No newline at end of file
.devcontainer/devcontainer.jsondiffbeforeafterboth--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,18 @@
+{
+ "name": "Rust",
+ "build": {
+ "dockerfile": "Dockerfile"
+ },
+ "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
+ "settings": {
+ "terminal.integrated.shell.linux": "/bin/bash",
+ "lldb.executable": "/usr/bin/lldb",
+ "files.watcherExclude": {
+ "**/target/**": true
+ }
+ },
+ "extensions": [
+ "matklad.rust-analyzer"
+ ],
+ "remoteUser": "vscode"
+}
README.mddiffbeforeafterboth--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@
```bash
rustup toolchain install 1.49.0
-rustup toolchain install nightly-2020-10-01
+rustup toolchain install nightly-2020-01-27
rustup default nightly-2021-01-27
```
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -1122,8 +1122,8 @@
// Check approval
let mut approval: u128 = 0;
- if <Allowances<T>>::contains_key(collection_id, (item_id, &from, &recipient)) {
- approval = <Allowances<T>>::get(collection_id, (item_id, &from, &recipient));
+ if <Allowances<T>>::contains_key(collection_id, (item_id, &from, &sender)) {
+ approval = <Allowances<T>>::get(collection_id, (item_id, &from, &sender));
ensure!(approval >= value, Error::<T>::TokenValueNotEnough);
appoved_transfer = true;
}
@@ -1144,10 +1144,10 @@
// Reduce approval by transferred amount or remove if remaining approval drops to 0
if approval.checked_sub(value).unwrap_or(0) > 0 {
- <Allowances<T>>::insert(collection_id, (item_id, &from, &recipient), approval - value);
+ <Allowances<T>>::insert(collection_id, (item_id, &from, &sender), approval - value);
}
else {
- <Allowances<T>>::remove(collection_id, (item_id, &from, &recipient));
+ <Allowances<T>>::remove(collection_id, (item_id, &from, &sender));
}
match target_collection.mode
tests/README.mddiffbeforeafterboth--- a/tests/README.md
+++ b/tests/README.md
@@ -2,8 +2,8 @@
## How to run
-1. Run `npm install`.
+1. Run `yarn install`.
2. Setup a test node. You can do it using `docker-compose up -d` in parent directory.
3. Optional step - configure tests with env variables or by editing [configuration file](src/config.ts).
-4. Run `npm test`.
+4. Run `yarn test`.
tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -25,8 +25,10 @@
"testSetVariableMetaData": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetaData.test.ts",
"testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",
"testRemoveCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionAdmin.test.ts",
+ "testRemoveFromWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/removeFromWhiteList.test.ts",
"testConnection": "mocha --timeout 9999999 -r ts-node/register ./**/connection.test.ts",
"testCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",
+ "testCreateMultipleItems": "mocha --timeout 9999999 -r ts-node/register ./**/createMultipleItems.test.ts",
"testApprove": "mocha --timeout 9999999 -r ts-node/register ./**/approve.test.ts",
"testTransferFrom": "mocha --timeout 9999999 -r ts-node/register ./**/transferFrom.test.ts",
"testCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",
@@ -35,7 +37,8 @@
"testTransfer": "mocha --timeout 9999999 -r ts-node/register ./**/transfer.test.ts",
"testBurnItem": "mocha --timeout 9999999 -r ts-node/register ./**/burnItem.test.ts",
"testCreditFeesToTreasury": "mocha --timeout 9999999 -r ts-node/register ./**/creditFeesToTreasury.test.ts",
- "testEnableContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/enableContractSponsoring.test.ts"
+ "testEnableContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/enableContractSponsoring.test.ts",
+ "testSetContractSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setContractSponsoringRateLimit.test.ts"
},
"author": "",
"license": "SEE LICENSE IN ../LICENSE",
tests/src/createMultipleItems.test.tsdiffbeforeafterboth3// file 'LICENSE', which is part of this source code package.3// file 'LICENSE', which is part of this source code package.4//4//56import { assert } from 'chai';5import { ApiPromise } from '@polkadot/api';6import BN from 'bn.js';7import chai from 'chai';7import { alicesPublicKey } from './accounts';8import chaiAsPromised from 'chai-as-promised';8import privateKey from './substrate/privateKey';9import privateKey from './substrate/privateKey';9import usingApi from './substrate/substrate-api';10import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';10import waitNewBlocks from './substrate/wait-new-blocks';11import {1112 createCollectionExpectSuccess,13 destroyCollectionExpectSuccess,14 IReFungibleTokenDataType,15} from './util/helpers';1617chai.use(chaiAsPromised);12const idCollection = 12;18const expect = chai.expect;1920interface ITokenDataType {21 Owner: number[];22 ConstData: number[];23 VariableData: number[];24}2526describe('Integration Test createMultipleItems(collection_id, owner, items_data):', () => {27 it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {28 await usingApi(async (api: ApiPromise) => {29 const collectionId = await createCollectionExpectSuccess();30 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;31 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);32 const Alice = privateKey('//Alice');33 const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }];34 const createMultipleItemsTx = await api.tx.nft35 .createMultipleItems(collectionId, Alice.address, args);36 await submitTransactionAsync(Alice, createMultipleItemsTx);37 const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;38 expect(itemsListIndexAfter.toNumber()).to.be.equal(3);39 const token1Data = await api.query.nft.nftItemList(collectionId, 1) as unknown as ITokenDataType;40 const token2Data = await api.query.nft.nftItemList(collectionId, 2) as unknown as ITokenDataType;41 const token3Data = await api.query.nft.nftItemList(collectionId, 3) as unknown as ITokenDataType;4243 expect(token1Data.Owner.toString()).to.be.equal(Alice.address);44 expect(token2Data.Owner.toString()).to.be.equal(Alice.address);45 expect(token3Data.Owner.toString()).to.be.equal(Alice.address);4647 expect(token1Data.ConstData.toString()).to.be.equal('0x31');48 expect(token2Data.ConstData.toString()).to.be.equal('0x32');49 expect(token3Data.ConstData.toString()).to.be.equal('0x33');5051 expect(token1Data.VariableData.toString()).to.be.equal('0x31');52 expect(token2Data.VariableData.toString()).to.be.equal('0x32');53 expect(token3Data.VariableData.toString()).to.be.equal('0x33');54 });55 });5657 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {58 await usingApi(async (api: ApiPromise) => {59 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});60 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;61 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);62 const Alice = privateKey('//Alice');63 const args = [64 { Refungible: ['0x31', '0x31'] },65 { Refungible: ['0x32', '0x32'] },66 { Refungible: ['0x33', '0x33'] },67 ];68 const createMultipleItemsTx = await api.tx.nft69 .createMultipleItems(collectionId, Alice.address, args);70 await submitTransactionAsync(Alice, createMultipleItemsTx);71 const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;72 expect(itemsListIndexAfter.toNumber()).to.be.equal(3);73 const token1Data = await api.query.nft.reFungibleItemList(collectionId, 1) as unknown as IReFungibleTokenDataType;74 const token2Data = await api.query.nft.reFungibleItemList(collectionId, 2) as unknown as IReFungibleTokenDataType;75 const token3Data = await api.query.nft.reFungibleItemList(collectionId, 3) as unknown as IReFungibleTokenDataType;7677 expect(token1Data.Owner[0].Owner.toString()).to.be.equal(Alice.address);78 expect(token1Data.Owner[0].Fraction.toNumber()).to.be.equal(1);7980 expect(token2Data.Owner[0].Owner.toString()).to.be.equal(Alice.address);81 expect(token2Data.Owner[0].Fraction.toNumber()).to.be.equal(1);8283 expect(token3Data.Owner[0].Owner.toString()).to.be.equal(Alice.address);84 expect(token3Data.Owner[0].Fraction.toNumber()).to.be.equal(1);8586 expect(token1Data.ConstData.toString()).to.be.equal('0x31');87 expect(token2Data.ConstData.toString()).to.be.equal('0x32');88 expect(token3Data.ConstData.toString()).to.be.equal('0x33');8990 expect(token1Data.VariableData.toString()).to.be.equal('0x31');91 expect(token2Data.VariableData.toString()).to.be.equal('0x32');92 expect(token3Data.VariableData.toString()).to.be.equal('0x33');93 });94 });95});139614describe.skip('integration test: ext. createMultipleItems():', () => {97describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {15 it('Create two NFT tokens in active NFT collection', async () => {98 it('Create token with not existing type', async () => {16 await usingApi(async (api) => {99 await usingApi(async (api: ApiPromise) => {17 const AitemListIndex = await api.query.nft.itemListIndex(idCollection);100 const collectionId = await createCollectionExpectSuccess();18 console.log(`itemListIndex count (before): ${AitemListIndex}`);101 const Alice = privateKey('//Alice');102 try {19 const args = ['NFT', 'NFT'];103 const args = [{ invalid: null }, { invalid: null }, { invalid: null }];20 const alicePrivateKey = privateKey('//Alice');21 const createMultipleItems = await api.tx.nft104 const createMultipleItemsTx = await api.tx.nft22 .createMultipleItems(idCollection, alicesPublicKey, args)105 .createMultipleItems(collectionId, Alice.address, args);23 .signAndSend(alicePrivateKey);24 // tslint:disable-next-line: no-unused-expression25 assert.exists(createMultipleItems, 'createMultipleItems is neither `null` or `undefined`');26 console.log(`Ext. createMultipleItems submitted with hash: ${createMultipleItems}`);27 await waitNewBlocks(api);28 const BitemListIndex = await api.query.nft.itemListIndex(idCollection);106 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;29 console.log(`itemListIndex count (after): ${BitemListIndex}`);30 if (BitemListIndex === AitemListIndex) { assert.fail('Corret token not added in collection!'); }107 } catch (e) {108 // tslint:disable-next-line:no-unused-expression109 expect(e).to.be.exist;110 }31 });111 });32 });112 });11333 it('(!negative test!) Create two Fungible tokens in active NFT collection', async () => {114 it('Create token in not existing collection', async () => {34 await usingApi(async (api) => {115 await usingApi(async (api: ApiPromise) => {35 const AitemListIndex = await api.query.nft.itemListIndex(idCollection);116 const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;36 console.log(`itemListIndex count (before): ${AitemListIndex}`);37 const args = ['Fungible', 'Fungible'];38 const alicePrivateKey = privateKey('//Alice');117 const Alice = privateKey('//Alice');39 const createMultipleItems = await api.tx.nft118 const createMultipleItemsTx = await api.tx.nft40 .createMultipleItems(idCollection, alicesPublicKey, args)119 .createMultipleItems(collectionId, Alice.address, ['NFT', 'NFT', 'NFT']);41 .signAndSend(alicePrivateKey);42 // tslint:disable-next-line: no-unused-expression43 assert.exists(createMultipleItems, 'createMultipleItems is neither `null` or `undefined`');44 console.log(`Ext. createMultipleItems submitted with hash: ${createMultipleItems}`);45 await waitNewBlocks(api);46 const BitemListIndex = await api.query.nft.itemListIndex(idCollection);120 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;47 console.log(`itemListIndex count (after): ${BitemListIndex}`);48 if (BitemListIndex > AitemListIndex) { assert.fail('Incorrect token added in collection!'); }49 });121 });50 });122 });12351 it('(!negative test!) Create two ReFungible tokens in active NFT collection', async () => {124 it('Create NFT and Re-fungible tokens that has reached the maximum data limit', async () => {52 await usingApi(async (api) => {125 await usingApi(async (api: ApiPromise) => {126 // NFT53 const AitemListIndex = await api.query.nft.itemListIndex(idCollection);127 const collectionId = await createCollectionExpectSuccess();54 console.log(`itemListIndex count (before): ${AitemListIndex}`);55 const args = ['ReFungible', 'ReFungible'];128 const Alice = privateKey('//Alice');56 const alicePrivateKey = privateKey('//Alice');129 const args = [130 { nft: ['A'.repeat(2049), 'A'.repeat(2049)] },131 { nft: ['B'.repeat(2049), 'B'.repeat(2049)] },132 { nft: ['C'.repeat(2049), 'C'.repeat(2049)] },133 ];57 const createMultipleItems = await api.tx.nft134 const createMultipleItemsTx = await api.tx.nft58 .createMultipleItems(idCollection, alicesPublicKey, args)135 .createMultipleItems(collectionId, Alice.address, args);59 .signAndSend(alicePrivateKey);60 // tslint:disable-next-line: no-unused-expression61 assert.exists(createMultipleItems, 'createMultipleItems is neither `null` or `undefined`');136 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;137138 // ReFungible139 const collectionIdReFungible =62 console.log(`Ext. createMultipleItems submitted with hash: ${createMultipleItems}`);140 await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});141 const argsReFungible = [63 await waitNewBlocks(api);142 { ReFungible: ['1'.repeat(2049), '1'.repeat(2049)] },143 { ReFungible: ['2'.repeat(2049), '2'.repeat(2049)] },144 { ReFungible: ['3'.repeat(2049), '3'.repeat(2049)] },145 ];64 const BitemListIndex = await api.query.nft.itemListIndex(idCollection);146 const createMultipleItemsTxFungible = await api.tx.nft65 console.log(`itemListIndex count (after): ${BitemListIndex}`);147 .createMultipleItems(collectionIdReFungible, Alice.address, argsReFungible);66 if (BitemListIndex > AitemListIndex) { assert.fail('Incorrect token added in collection!'); }148 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTxFungible)).to.be.rejected;67 });149 });68 });150 });151152 it('Create tokens with different types', async () => {153 await usingApi(async (api: ApiPromise) => {154 const collectionId = await createCollectionExpectSuccess();155 const Alice = privateKey('//Alice');156 const createMultipleItemsTx = await api.tx.nft157 .createMultipleItems(collectionId, Alice.address, ['NFT', 'Fungible', 'ReFungible']);158 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;159 // garbage collection :-D160 await destroyCollectionExpectSuccess(collectionId);161 });162 });163164 it('Create tokens with different data limits <> maximum data limit', async () => {165 await usingApi(async (api: ApiPromise) => {166 const collectionId = await createCollectionExpectSuccess();167 const Alice = privateKey('//Alice');168 const args = [169 { nft: ['A', 'A'] },170 { nft: ['B', 'B'.repeat(2049)] },171 { nft: ['C'.repeat(2049), 'C'] },172 ];173 const createMultipleItemsTx = await api.tx.nft174 .createMultipleItems(collectionId, Alice.address, args);175 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;176 });177 });69});178});70179tests/src/removeFromWhiteList.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/removeFromWhiteList.test.ts
@@ -0,0 +1,84 @@
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import { default as usingApi } from './substrate/substrate-api';
+import {
+ createCollectionExpectSuccess,
+ destroyCollectionExpectSuccess,
+ enableWhiteListExpectSuccess,
+ addToWhiteListExpectSuccess,
+ removeFromWhiteListExpectSuccess,
+ isWhitelisted,
+ findNotExistingCollection,
+ removeFromWhiteListExpectFailure,
+ disableWhiteListExpectSuccess,
+} from './util/helpers';
+import { IKeyringPair } from '@polkadot/types/types';
+import privateKey from './substrate/privateKey';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+describe('Integration Test removeFromWhiteList', () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async (api) => {
+ alice = privateKey('//Alice');
+ bob = privateKey('//Bob');
+ });
+ });
+
+ it('ensure bob is not in whitelist after removal', async () => {
+ await usingApi(async () => {
+ const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+ await enableWhiteListExpectSuccess(alice, collectionId);
+ await addToWhiteListExpectSuccess(alice, collectionId, bob.address);
+
+ await removeFromWhiteListExpectSuccess(alice, collectionId, bob.address);
+ expect(await isWhitelisted(collectionId, bob.address)).to.be.false;
+ });
+ });
+
+ it('allows removal from collection with unset whitelist status', async () => {
+ await usingApi(async () => {
+ const collectionWithoutWhitelistId = await createCollectionExpectSuccess();
+ await enableWhiteListExpectSuccess(alice, collectionWithoutWhitelistId);
+ await addToWhiteListExpectSuccess(alice, collectionWithoutWhitelistId, bob.address);
+ await disableWhiteListExpectSuccess(alice, collectionWithoutWhitelistId);
+
+ await removeFromWhiteListExpectSuccess(alice, collectionWithoutWhitelistId, bob.address);
+ });
+ });
+});
+
+describe('Negative Integration Test removeFromWhiteList', () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async (api) => {
+ alice = privateKey('//Alice');
+ bob = privateKey('//Bob');
+ });
+ });
+
+ it('fails on removal from not existing collection', async () => {
+ await usingApi(async (api) => {
+ const collectionId = await findNotExistingCollection(api);
+
+ await removeFromWhiteListExpectFailure(alice, collectionId, bob.address);
+ });
+ });
+
+ it('fails on removal from removed collection', async () => {
+ await usingApi(async () => {
+ const collectionId = await createCollectionExpectSuccess();
+ await enableWhiteListExpectSuccess(alice, collectionId);
+ await addToWhiteListExpectSuccess(alice, collectionId, bob.address);
+ await destroyCollectionExpectSuccess(collectionId);
+
+ await removeFromWhiteListExpectFailure(alice, collectionId, bob.address);
+ });
+ });
+});
tests/src/setContractSponsoringRateLimit.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/setContractSponsoringRateLimit.test.ts
@@ -0,0 +1,62 @@
+import { IKeyringPair } from '@polkadot/types/types';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import waitNewBlocks from './substrate/wait-new-blocks';
+import { deployFlipper, toggleFlipValueExpectFailure, toggleFlipValueExpectSuccess } from './util/contracthelpers';
+import {
+ enableContractSponsoringExpectSuccess,
+ findUnusedAddress,
+ setContractSponsoringRateLimitExpectFailure,
+ setContractSponsoringRateLimitExpectSuccess,
+} from './util/helpers';
+
+describe('Integration Test setContractSponsoringRateLimit', () => {
+ it('ensure sponsored contract can\'t be called twice without pause for free', async () => {
+ await usingApi(async (api) => {
+ const user = await findUnusedAddress(api);
+
+ const [flipper, deployer] = await deployFlipper(api);
+ await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+ await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 10);
+ await toggleFlipValueExpectSuccess(user, flipper);
+ await toggleFlipValueExpectFailure(user, flipper);
+ });
+ });
+
+ it('ensure sponsored contract can be called twice with pause for free', async () => {
+ await usingApi(async (api) => {
+ const user = await findUnusedAddress(api);
+
+ const [flipper, deployer] = await deployFlipper(api);
+ await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+ await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 1);
+ await toggleFlipValueExpectSuccess(user, flipper);
+ await waitNewBlocks(api, 1);
+ await toggleFlipValueExpectSuccess(user, flipper);
+ });
+ });
+});
+
+describe('Negative Integration Test setContractSponsoringRateLimit', () => {
+ let alice: IKeyringPair;
+
+ before(async () => {
+ alice = privateKey('//Alice');
+ });
+
+ it('fails when called for non-contract address', async () => {
+ await usingApi(async (api) => {
+ const user = await findUnusedAddress(api);
+
+ await setContractSponsoringRateLimitExpectFailure(alice, user.address, 1);
+ });
+ });
+
+ it('fails when called by non-owning user', async () => {
+ await usingApi(async (api) => {
+ const [flipper, _] = await deployFlipper(api);
+
+ await setContractSponsoringRateLimitExpectFailure(alice, flipper.address, 1);
+ });
+ });
+});
tests/src/substrate/substrate-api.tsdiffbeforeafterboth--- a/tests/src/substrate/substrate-api.ts
+++ b/tests/src/substrate/substrate-api.ts
@@ -123,9 +123,9 @@
// console.log('transactionStatus', transactionStatus, 'events', events);
- if (transactionStatus == TransactionStatus.Success) {
+ if (transactionStatus === TransactionStatus.Success) {
resolve(events);
- } else if (transactionStatus == TransactionStatus.Fail) {
+ } else if (transactionStatus === TransactionStatus.Fail) {
reject(events);
}
});
tests/src/util/contracthelpers.tsdiffbeforeafterboth--- a/tests/src/util/contracthelpers.ts
+++ b/tests/src/util/contracthelpers.ts
@@ -5,7 +5,7 @@
import chai from "chai";
import chaiAsPromised from 'chai-as-promised';
-import { submitTransactionAsync } from "../substrate/substrate-api";
+import { submitTransactionAsync, submitTransactionExpectFailAsync } from "../substrate/substrate-api";
import fs from "fs";
import { Abi, BlueprintPromise as Blueprint, CodePromise, ContractPromise as Contract } from "@polkadot/api-contract";
import { IKeyringPair } from "@polkadot/types/types";
@@ -100,6 +100,11 @@
expect(result.success).to.be.true;
}
+export async function toggleFlipValueExpectFailure(sender: IKeyringPair, contract: Contract) {
+ const tx = contract.tx.flip(value, gasLimit);
+ await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+}
+
function instantiateTransferContract(alice: IKeyringPair, blueprint: Blueprint) : Promise<any> {
return new Promise<any>(async (resolve, reject) => {
const unsub = await blueprint.tx
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -51,7 +51,7 @@
Value: BN;
}
-interface IReFungibleTokenDataType {
+export interface IReFungibleTokenDataType {
Owner: IReFungibleOwner[];
ConstData: number[];
VariableData: number[];
@@ -414,6 +414,16 @@
});
}
+export async function setContractSponsoringRateLimitExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {
+ await usingApi(async (api) => {
+ const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);
+ const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+ const result = getGenericResult(events);
+
+ expect(result.success).to.be.false;
+ });
+}
+
export async function setVariableMetaDataExpectSuccess(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {
await usingApi(async (api) => {
const tx = api.tx.nft.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));
@@ -492,7 +502,7 @@
}
const transferFromTx = await api.tx.nft.transferFrom(
accountFrom.address, accountTo.address, collectionId, tokenId, value);
- const events = await submitTransactionAsync(accountFrom, transferFromTx);
+ const events = await submitTransactionAsync(accountApproved, transferFromTx);
const result = getCreateItemResult(events);
// tslint:disable-next-line:no-unused-expression
expect(result.success).to.be.true;
@@ -635,11 +645,14 @@
return newItemId;
}
-export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {
+export async function setPublicAccessModeExpectSuccess(
+ sender: IKeyringPair, collectionId: number,
+ accessMode: 'Normal' | 'WhiteList',
+) {
await usingApi(async (api) => {
// Run the transaction
- const tx = api.tx.nft.setPublicAccessMode(collectionId, 'WhiteList');
+ const tx = api.tx.nft.setPublicAccessMode(collectionId, accessMode);
const events = await submitTransactionAsync(sender, tx);
const result = getGenericResult(events);
@@ -649,10 +662,18 @@
// What to expect
// tslint:disable-next-line:no-unused-expression
expect(result.success).to.be.true;
- expect(collection.Access).to.be.equal('WhiteList');
+ expect(collection.Access).to.be.equal(accessMode);
});
}
+export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {
+ await setPublicAccessModeExpectSuccess(sender, collectionId, 'WhiteList');
+}
+
+export async function disableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {
+ await setPublicAccessModeExpectSuccess(sender, collectionId, 'Normal');
+}
+
export async function enablePublicMintingExpectSuccess(sender: IKeyringPair, collectionId: number) {
await usingApi(async (api) => {
@@ -670,6 +691,14 @@
});
}
+export async function isWhitelisted(collectionId: number, address: string) {
+ let whitelisted: boolean = false;
+ await usingApi(async (api) => {
+ whitelisted = (await api.query.nft.whiteList(collectionId, address)).toJSON() as unknown as boolean;
+ });
+ return whitelisted;
+}
+
export async function addToWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {
await usingApi(async (api) => {
@@ -692,6 +721,32 @@
});
}
+export async function removeFromWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {
+ await usingApi(async (api) => {
+ // Run the transaction
+ const tx = api.tx.nft.removeFromWhiteList(collectionId, address);
+ const events = await submitTransactionAsync(sender, tx);
+ const result = getGenericResult(events);
+
+ // What to expect
+ // tslint:disable-next-line:no-unused-expression
+ expect(result.success).to.be.true;
+ });
+}
+
+export async function removeFromWhiteListExpectFailure(sender: IKeyringPair, collectionId: number, address: string) {
+ await usingApi(async (api) => {
+ // Run the transaction
+ const tx = api.tx.nft.removeFromWhiteList(collectionId, address);
+ const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+ const result = getGenericResult(events);
+
+ // What to expect
+ // tslint:disable-next-line:no-unused-expression
+ expect(result.success).to.be.false;
+ });
+}
+
export const getDetailedCollectionInfo = async (api: ApiPromise, collectionId: number)
: Promise<ICollectionInterface | null> => {
return await api.query.nft.collection(collectionId) as unknown as ICollectionInterface;