git.delta.rocks / unique-network / refs/commits / 2390e1641b99

difftreelog

Merge pull request #67 from usetech-llc/feature/NFTPAR-257

Greg Zaitsev2021-01-19parents: #567e35d #fdbcd55.patch.diff
in: master
Feature/nftpar 257

6 files changed

modifiedtests/package.jsondiffbeforeafterboth
28 "testTransferFrom": "mocha --timeout 9999999 -r ts-node/register ./**/transferFrom.test.ts",28 "testTransferFrom": "mocha --timeout 9999999 -r ts-node/register ./**/transferFrom.test.ts",
29 "testCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",29 "testCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",
30 "testToggleContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/toggleContractWhiteList.test.ts",30 "testToggleContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/toggleContractWhiteList.test.ts",
31 "testAddToContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/addToContractWhiteList.test.ts"31 "testAddToContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/addToContractWhiteList.test.ts",
32 "testTransfer": "mocha --timeout 9999999 -r ts-node/register ./**/transfer.test.ts"
32 },33 },
33 "author": "",34 "author": "",
34 "license": "Apache 2.0",35 "license": "Apache 2.0",
modifiedtests/src/burnItem.test.tsdiffbeforeafterboth
36 const events = await submitTransactionAsync(alice, tx);36 const events = await submitTransactionAsync(alice, tx);
37 const result = getGenericResult(events);37 const result = getGenericResult(events);
38
39 // Get the item 38 // Get the item
40 const item: any = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON();39 const item: any = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON();
41
42 // What to expect40 // What to expect
41 // tslint:disable-next-line:no-unused-expression
43 expect(result.success).to.be.true;42 expect(result.success).to.be.true;
43 // tslint:disable-next-line:no-unused-expression
44 expect(item).to.be.not.null;44 expect(item).to.be.not.null;
45 expect(item.Owner).to.be.equal(nullPublicKey);45 expect(item.Owner).to.be.equal(nullPublicKey);
46 });46 });
modifiedtests/src/substrate/get-balance.tsdiffbeforeafterboth
3// file 'LICENSE', which is part of this source code package.3// file 'LICENSE', which is part of this source code package.
4//4//
55
6import { ApiPromise } from "@polkadot/api";6import { ApiPromise } from '@polkadot/api';
7import promisifySubstrate from "./promisify-substrate";7import {AccountInfo} from '@polkadot/types/interfaces/system';
8import {AccountInfo} from "@polkadot/types/interfaces/system";8import promisifySubstrate from './promisify-substrate';
99
10export default async function getBalance(api: ApiPromise, accounts: string[]): Promise<bigint[]> {10export default async function getBalance(api: ApiPromise, accounts: string[]): Promise<Array<bigint>> {
11 const balance = promisifySubstrate(api, (accounts: string[]) => api.query.system.account.multi(accounts));11 const balance = promisifySubstrate(api, (acc: string[]) => api.query.system.account.multi(acc));
12 const responce = await balance(accounts) as unknown as AccountInfo[];12 const responce = await balance(accounts) as unknown as AccountInfo[];
13 return responce.map(r => r.data.free.toBigInt().valueOf());13 return responce.map((r) => r.data.free.toBigInt().valueOf());
14}14}
1515
modifiedtests/src/substrate/substrate-api.tsdiffbeforeafterboth
6060
61export function submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {61export function
62submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {
62 return new Promise(async function(resolve, reject) {63 return new Promise(async (resolve, reject) => {
63 try {64 try {
64 await transaction.signAndSend(sender, ({ events = [], status }) => {65 await transaction.signAndSend(sender, ({ events = [], status }) => {
65 const transactionStatus = getTransactionStatus(events, status);66 const transactionStatus = getTransactionStatus(events, status);
6667
67 if (transactionStatus == TransactionStatus.Success) {68 if (transactionStatus === TransactionStatus.Success) {
68 resolve(events);69 resolve(events);
69 } else if (transactionStatus == TransactionStatus.Fail) {70 } else if (transactionStatus === TransactionStatus.Fail) {
70 console.log(`Something went wrong with transaction. Status: ${status}`);71 console.log(`Something went wrong with transaction. Status: ${status}`);
71 reject(events);72 reject(events);
72 }73 }
73 });74 });
74 } catch (e) {75 } catch (e) {
75 console.log("Error: ", e);76 console.log('Error: ', e);
76 reject(e);77 reject(e);
77 }78 }
78 });79 });
modifiedtests/src/transfer.test.tsdiffbeforeafterboth
3// file 'LICENSE', which is part of this source code package.3// file 'LICENSE', which is part of this source code package.
4//4//
55
6import { expect, assert } from "chai";6import { ApiPromise } from '@polkadot/api';
7import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api";7import { IKeyringPair } from '@polkadot/types/types';
8import { expect } from 'chai';
8import { alicesPublicKey, bobsPublicKey, ferdiesPublicKey } from "./accounts";9import { alicesPublicKey, bobsPublicKey } from './accounts';
9import privateKey from "./substrate/privateKey";10import getBalance from './substrate/get-balance';
10import getBalance from "./substrate/get-balance";11import privateKey from './substrate/privateKey';
11import { BigNumber } from 'bignumber.js';12import { default as usingApi, submitTransactionAsync } from './substrate/substrate-api';
12import { findUnusedAddress } from './util/helpers'13import {
14 burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess,
15 destroyCollectionExpectSuccess,
16 findUnusedAddress,
17 getCreateCollectionResult,
18 getCreateItemResult,
19 transferExpectFail,
20 transferExpectSuccess,
21} from './util/helpers';
22
23let Alice: IKeyringPair;
24let Bob: IKeyringPair;
25let Charlie: IKeyringPair;
1326
14describe('Transfer', () => {27describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => {
15 it('Balance transfers', async () => {28 it('Balance transfers and check balance', async () => {
16 await usingApi(async api => {29 await usingApi(async (api: ApiPromise) => {
17 const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);30 const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);
1831
19 const alicePrivateKey = privateKey('//Alice');32 const alicePrivateKey = privateKey('//Alice');
20 33
21 const transfer = api.tx.balances.transfer(bobsPublicKey, 1n);34 const transfer = api.tx.balances.transfer(bobsPublicKey, 1n);
22 const result = await submitTransactionAsync(alicePrivateKey, transfer);35 const events = await submitTransactionAsync(alicePrivateKey, transfer);
36 const result = getCreateItemResult(events);
37 // tslint:disable-next-line:no-unused-expression
38 expect(result.success).to.be.true;
2339
24 const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);40 const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);
2541
42 // tslint:disable-next-line:no-unused-expression
26 expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;43 expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;
44 // tslint:disable-next-line:no-unused-expression
27 expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;45 expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;
28 });46 });
29 });47 });
3048
31 it('Inability to pay fees error message is correct', async () => {49 it('Inability to pay fees error message is correct', async () => {
32 await usingApi(async api => {50 await usingApi(async (api) => {
33 // Find unused address51 // Find unused address
34 const pk = await findUnusedAddress(api);52 const pk = await findUnusedAddress(api);
3553
36 const error = console.error;
37 const log = console.log;
38 console.log = function () {};
39 console.error = function () {};
40
41 const badTransfer = api.tx.balances.transfer(bobsPublicKey, 1n);54 const badTransfer = api.tx.balances.transfer(bobsPublicKey, 1n);
55 // const events = await submitTransactionAsync(pk, badTransfer);
42 const badTransaction = async function () { 56 const badTransaction = async () => {
43 const result = await submitTransactionAsync(pk, badTransfer);57 const events = await submitTransactionAsync(pk, badTransfer);
58 const result = getCreateCollectionResult(events);
59 // tslint:disable-next-line:no-unused-expression
60 expect(result.success).to.be.false;
44 };61 };
45 await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");62 expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low');
46
47 console.log = log;
48 console.error = error;
49 });63 });
50 });64 });
65
66 it('Create collection, balance transfers and check balance', async () => {
67 await usingApi(async (api) => {
68 const Alice = privateKey('//Alice');
69 const Bob = privateKey('//Bob');
70 // nft
71 const nftCollectionId = await createCollectionExpectSuccess();
72 const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
73 await transferExpectSuccess(nftCollectionId, newNftTokenId, Alice, Bob, 1, 'NFT');
74 // fungible
75 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
76 const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible');
77 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible');
78 // reFungible
79 const reFungibleCollectionId = await
80 createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
81 const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
82 await transferExpectSuccess(reFungibleCollectionId,
83 newReFungibleTokenId, Alice, Bob, 1, 'ReFungible');
84 });
85 });
51});86});
87
88describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {
89 before(async () => {
90 await usingApi(async (api: ApiPromise) => {
91 Alice = privateKey('//Alice');
92 Bob = privateKey('//Bob');
93 Charlie = privateKey('//Charlie');
94 });
95 });
96 it('Transfer with not existed collection_id', async () => {
97 await usingApi(async (api) => {
98 // nft
99 const nftCollectionCount = await api.query.nft.createdCollectionCount() as unknown as number;
100 await transferExpectFail(nftCollectionCount + 1, 1, Alice, Bob, 1);
101 // fungible
102 const fungibleCollectionCount = await api.query.nft.createdCollectionCount() as unknown as number;
103 await transferExpectFail(fungibleCollectionCount + 1, 1, Alice, Bob, 1);
104 // reFungible
105 const reFungibleCollectionCount = await api.query.nft.createdCollectionCount() as unknown as number;
106 await transferExpectFail(reFungibleCollectionCount + 1, 1, Alice, Bob, 1);
107 });
108 });
109 it('Transfer with deleted collection_id', async () => {
110 // nft
111 const nftCollectionId = await createCollectionExpectSuccess();
112 const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
113 await destroyCollectionExpectSuccess(nftCollectionId);
114 await transferExpectFail(nftCollectionId, newNftTokenId, Alice, Bob, 1, 'NFT');
115 // fungible
116 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
117 const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible');
118 await destroyCollectionExpectSuccess(fungibleCollectionId);
119 await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible');
120 // reFungible
121 const reFungibleCollectionId = await
122 createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
123 const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
124 await destroyCollectionExpectSuccess(reFungibleCollectionId);
125 await transferExpectFail(reFungibleCollectionId,
126 newReFungibleTokenId, Alice, Bob, 1, 'ReFungible');
127 });
128 it('Transfer with not existed item_id', async () => {
129 // nft
130 const nftCollectionId = await createCollectionExpectSuccess();
131 await transferExpectFail(nftCollectionId, 2, Alice, Bob, 1, 'NFT');
132 // fungible
133 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
134 await transferExpectFail(fungibleCollectionId, 2, Alice, Bob, 1, 'Fungible');
135 // reFungible
136 const reFungibleCollectionId = await
137 createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
138 await transferExpectFail(reFungibleCollectionId,
139 2, Alice, Bob, 1, 'ReFungible');
140 });
141 it('Transfer with deleted item_id', async () => {
142 // nft
143 const nftCollectionId = await createCollectionExpectSuccess();
144 const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
145 await burnItemExpectSuccess(Alice, nftCollectionId, newNftTokenId, 1);
146 await transferExpectFail(nftCollectionId, newNftTokenId, Alice, Bob, 1, 'NFT');
147 // fungible
148 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
149 const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible');
150 await burnItemExpectSuccess(Alice, fungibleCollectionId, newFungibleTokenId, 10);
151 await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible');
152 // reFungible
153 const reFungibleCollectionId = await
154 createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
155 const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
156 await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, 1);
157 await transferExpectFail(reFungibleCollectionId,
158 newReFungibleTokenId, Alice, Bob, 1, 'ReFungible');
159 });
160 it('Transfer with recipient that is not owner', async () => {
161 // nft
162 const nftCollectionId = await createCollectionExpectSuccess();
163 const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
164 await transferExpectFail(nftCollectionId, newNftTokenId, Charlie, Bob, 1, 'NFT');
165 // fungible
166 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
167 const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible');
168 await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Charlie, Bob, 1, 'Fungible');
169 // reFungible
170 const reFungibleCollectionId = await
171 createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
172 const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
173 await transferExpectFail(reFungibleCollectionId,
174 newReFungibleTokenId, Charlie, Bob, 1, 'ReFungible');
175 });
176});
52177
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
391 ReFungible: CreateReFungibleData;391 ReFungible: CreateReFungibleData;
392}392}
393
394export async function burnItemExpectSuccess(owner: IKeyringPair, collectionId: number, tokenId: number, value = 0) {
395 await usingApi(async (api) => {
396 const tx = api.tx.nft.burnItem(collectionId, tokenId, value);
397 const events = await submitTransactionAsync(owner, tx);
398 const result = getGenericResult(events);
399 // Get the item
400 const item: any = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON();
401 // What to expect
402 // tslint:disable-next-line:no-unused-expression
403 expect(result.success).to.be.true;
404 // tslint:disable-next-line:no-unused-expression
405 expect(item).to.be.not.null;
406 expect(item.Owner).to.be.equal(nullPublicKey);
407 });
408}
393409
394export async function410export async function
395approveExpectSuccess(collectionId: number,411approveExpectSuccess(collectionId: number,
461 });477 });
462}478}
479
480export async function
481transferExpectSuccess(collectionId: number,
482 tokenId: number,
483 sender: IKeyringPair,
484 recipient: IKeyringPair,
485 value: number = 1,
486 type: string = 'NFT') {
487 await usingApi(async (api: ApiPromise) => {
488 let balanceBefore = new BN(0);
489 if (type === 'Fungible') {
490 balanceBefore = await api.query.nft.balance(collectionId, recipient.address) as unknown as BN;
491 }
492 const transferTx = await api.tx.nft.transfer(recipient.address, collectionId, tokenId, value);
493 const events = await submitTransactionAsync(sender, transferTx);
494 const result = getCreateItemResult(events);
495 // tslint:disable-next-line:no-unused-expression
496 expect(result.success).to.be.true;
497 if (type === 'NFT') {
498 const nftItemData = await api.query.nft.nftItemList(collectionId, tokenId) as unknown as ITokenDataType;
499 expect(nftItemData.Owner.toString()).to.be.equal(recipient.address);
500 }
501 if (type === 'Fungible') {
502 const balanceAfter = await api.query.nft.balance(collectionId, recipient.address) as unknown as BN;
503 expect(balanceAfter.sub(balanceBefore).toNumber()).to.be.equal(value);
504 }
505 if (type === 'ReFungible') {
506 const nftItemData =
507 await api.query.nft.reFungibleItemList(collectionId, tokenId) as unknown as IReFungibleTokenDataType;
508 expect(nftItemData.Owner[0].Owner.toString()).to.be.equal(recipient.address);
509 expect(nftItemData.Owner[0].Fraction.toNumber()).to.be.equal(value);
510 }
511 });
512}
513
514export async function
515transferExpectFail(collectionId: number,
516 tokenId: number,
517 sender: IKeyringPair,
518 recipient: IKeyringPair,
519 value: number = 1,
520 type: string = 'NFT') {
521 await usingApi(async (api: ApiPromise) => {
522 const transferTx = await api.tx.nft.transfer(recipient.address, collectionId, tokenId, value);
523 const events = await expect(submitTransactionExpectFailAsync(sender, transferTx)).to.be.rejected;
524 if (events && Array.isArray(events)) {
525 const result = getCreateCollectionResult(events);
526 // tslint:disable-next-line:no-unused-expression
527 expect(result.success).to.be.false;
528 }
529 });
530}
463531
464export async function532export async function
465approveExpectFail(collectionId: number,533approveExpectFail(collectionId: number,
525 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();594 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
526595
527 // What to expect596 // What to expect
597 // tslint:disable-next-line:no-unused-expression
528 expect(result.success).to.be.true;598 expect(result.success).to.be.true;
529 expect(collection.Access).to.be.equal('WhiteList');599 expect(collection.Access).to.be.equal('WhiteList');
530 });600 });
559 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();629 const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
560630
561 // What to expect631 // What to expect
632 // tslint:disable-next-line:no-unused-expression
562 expect(result.success).to.be.true;633 expect(result.success).to.be.true;
563 expect(collection.MintMode).to.be.equal(true);634 expect(collection.MintMode).to.be.equal(true);
564 });635 });