git.delta.rocks / unique-network / refs/commits / af9de18a00d2

difftreelog

source

tests/src/util/helpers.ts18.6 KiBsourcehistory
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 ITokenDataType {40  Owner: number[];41  ConstData: number[];42  VariableData: number[];43}4445export function getGenericResult(events: EventRecord[]): GenericResult {46  const result: GenericResult = {47    success: false,48  };49  events.forEach(({ phase, event: { data, method, section } }) => {50    // console.log(`    ${phase}: ${section}.${method}:: ${data}`);51    if (method === 'ExtrinsicSuccess') {52      result.success = true;53    }54  });55  return result;56}5758export function getCreateCollectionResult(events: EventRecord[]): CreateCollectionResult {59  let success = false;60  let collectionId: number = 0;61  events.forEach(({ phase, event: { data, method, section } }) => {62    // console.log(`    ${phase}: ${section}.${method}:: ${data}`);63    if (method == 'ExtrinsicSuccess') {64      success = true;65    } else if ((section == 'nft') && (method == 'Created')) {66      collectionId = parseInt(data[0].toString());67    }68  });69  const result: CreateCollectionResult = {70    success,71    collectionId,72  };73  return result;74}7576export function getCreateItemResult(events: EventRecord[]): CreateItemResult {77  let success = false;78  let collectionId: number = 0;79  let itemId: number = 0;80  events.forEach(({ phase, event: { data, method, section } }) => {81    // console.log(`    ${phase}: ${section}.${method}:: ${data}`);82    if (method == 'ExtrinsicSuccess') {83      success = true;84    } else if ((section == 'nft') && (method == 'ItemCreated')) {85      collectionId = parseInt(data[0].toString());86      itemId = parseInt(data[1].toString());87    }88  });89  const result: CreateItemResult = {90    success,91    collectionId,92    itemId,93  };94  return result;95}9697interface Invalid {98  type: 'Invalid';99}100101interface Nft {102  type: 'NFT';103}104105interface Fungible {106  type: 'Fungible';107  decimalPoints: number;108}109110interface ReFungible {111  type: 'ReFungible';112  decimalPoints: number;113}114115interface Nft {116  type: 'NFT'117}118119interface Fungible {120  type: 'Fungible',121  decimalPoints: number122}123124interface ReFungible {125  type: 'ReFungible',126  decimalPoints: number127}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: mode.decimalPoints};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: mode.decimalPoints};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}240241function getDestroyResult(events: EventRecord[]): boolean {242  let success: boolean = false;243  events.forEach(({ phase, event: { data, method, section } }) => {244    // console.log(`    ${phase}: ${section}.${method}:: ${data}`);245    if (method == 'ExtrinsicSuccess') {246      success = true;247    }248  });249  return success;250}251252export async function destroyCollectionExpectFailure(collectionId: number, senderSeed: string = '//Alice') {253  await usingApi(async (api) => {254    // Run the DestroyCollection transaction255    const alicePrivateKey = privateKey(senderSeed);256    const tx = api.tx.nft.destroyCollection(collectionId);257    await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;258  });259}260261export async function destroyCollectionExpectSuccess(collectionId: number, senderSeed: string = '//Alice') {262  await usingApi(async (api) => {263    // Run the DestroyCollection transaction264    const alicePrivateKey = privateKey(senderSeed);265    const tx = api.tx.nft.destroyCollection(collectionId);266    const events = await submitTransactionAsync(alicePrivateKey, tx);267    const result = getDestroyResult(events);268269    // Get the collection270    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();271272    // What to expect273    expect(result).to.be.true;274    expect(collection).to.be.not.null;275    expect(collection.Owner).to.be.equal(nullPublicKey);276  });277}278279export async function setCollectionSponsorExpectSuccess(collectionId: number, sponsor: string) {280  await usingApi(async (api) => {281282    // Run the transaction283    const alicePrivateKey = privateKey('//Alice');284    const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);285    const events = await submitTransactionAsync(alicePrivateKey, tx);286    const result = getGenericResult(events);287288    // Get the collection289    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();290291    // What to expect292    expect(result.success).to.be.true;293    expect(collection.Sponsor.toString()).to.be.equal(sponsor.toString());294    expect(collection.SponsorConfirmed).to.be.false;295  });296}297298export async function removeCollectionSponsorExpectSuccess(collectionId: number) {299  await usingApi(async (api) => {300301    // Run the transaction302    const alicePrivateKey = privateKey('//Alice');303    const tx = api.tx.nft.removeCollectionSponsor(collectionId);304    const events = await submitTransactionAsync(alicePrivateKey, tx);305    const result = getGenericResult(events);306307    // Get the collection308    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();309310    // What to expect311    expect(result.success).to.be.true;312    expect(collection.Sponsor).to.be.equal(nullPublicKey);313    expect(collection.SponsorConfirmed).to.be.false;314  });315}316317export async function removeCollectionSponsorExpectFailure(collectionId: number) {318  await usingApi(async (api) => {319320    // Run the transaction321    const alicePrivateKey = privateKey('//Alice');322    const tx = api.tx.nft.removeCollectionSponsor(collectionId);323    await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;324  });325}326327export async function setCollectionSponsorExpectFailure(collectionId: number, sponsor: string, senderSeed: string = '//Alice') {328  await usingApi(async (api) => {329330    // Run the transaction331    const alicePrivateKey = privateKey(senderSeed);332    const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);333    await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;334  });335}336337export async function confirmSponsorshipExpectSuccess(collectionId: number, senderSeed: string = '//Alice') {338  await usingApi(async (api) => {339340    // Run the transaction341    const sender = privateKey(senderSeed);342    const tx = api.tx.nft.confirmSponsorship(collectionId);343    const events = await submitTransactionAsync(sender, tx);344    const result = getGenericResult(events);345346    // Get the collection347    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();348349    // What to expect350    expect(result.success).to.be.true;351    expect(collection.Sponsor).to.be.equal(sender.address);352    expect(collection.SponsorConfirmed).to.be.true;353  });354}355356export async function confirmSponsorshipExpectFailure(collectionId: number, senderSeed: string = '//Alice') {357  await usingApi(async (api) => {358359    // Run the transaction360    const sender = privateKey(senderSeed);361    const tx = api.tx.nft.confirmSponsorship(collectionId);362    await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;363  });364}365366export interface CreateFungibleData extends Struct {367  readonly value: u128;368}369370export interface CreateReFungibleData extends Struct {}371export interface CreateNftData extends Struct {}372373export interface CreateItemData extends Enum {374  NFT: CreateNftData;375  Fungible: CreateFungibleData;376  ReFungible: CreateReFungibleData;377}378379export async function380approveExpectSuccess(collectionId: number,381                     tokenId: number, owner: IKeyringPair, approved: IKeyringPair, amount: number = 1) {382  await usingApi(async (api: ApiPromise) => {383    const allowanceBefore =384      await api.query.nft.allowances(collectionId, [tokenId, owner.address, approved.address]) as unknown as BN;385    const approveNftTx = await api.tx.nft.approve(approved.address, collectionId, tokenId, amount);386    const events = await submitTransactionAsync(owner, approveNftTx);387    const result = getCreateItemResult(events);388    // tslint:disable-next-line:no-unused-expression389    expect(result.success).to.be.true;390    const allowanceAfter =391      await api.query.nft.allowances(collectionId, [tokenId, owner.address, approved.address]) as unknown as BN;392    expect(allowanceAfter.toNumber() - allowanceBefore.toNumber()).to.be.equal(amount);393  });394}395396export async function397transferFromExpectSuccess(collectionId: number, tokenId: number, accountFrom: IKeyringPair,398                          accountTo: IKeyringPair, value: number = 1, type: string = 'NFT') {399  await usingApi(async (api: ApiPromise) => {400    const transferFromTx = await api.tx.nft.transferFrom(401      accountFrom.address, accountTo.address, collectionId, tokenId, value);402    const events = await submitTransactionAsync(accountFrom, transferFromTx);403    const result = getCreateItemResult(events);404    // tslint:disable-next-line:no-unused-expression405    expect(result.success).to.be.true;406    if (type === 'NFT') {407      const nftItemData = api.query.nft.nftItemList(collectionId, tokenId) as unknown as ITokenDataType;408      console.log('NFT data', nftItemData);409    }410    if (type === 'Fungible') {411      const nftItemData = api.query.nft.fungibleItemList(collectionId, tokenId) as unknown as ITokenDataType;412      console.log('Fungible data', nftItemData);413    }414    if (type === 'ReFungible') {415      const nftItemData = api.query.nft.reFungibleItemList(collectionId, tokenId) as unknown as ITokenDataType;416      console.log('reFungibleItemList data', nftItemData);417    }418  });419}420421export async function422approveExpectFail(collectionId: number,423                  tokenId: number, owner: IKeyringPair, approved: IKeyringPair, amount: number = 1) {424  await usingApi(async (api: ApiPromise) => {425    const approveNftTx = await api.tx.nft.approve(approved.address, collectionId, tokenId, amount);426    const events = await expect(submitTransactionExpectFailAsync(owner, approveNftTx)).to.be.rejected;427    const result = getCreateCollectionResult(events);428    // tslint:disable-next-line:no-unused-expression429    expect(result.success).to.be.false;430  });431}432433export async function createItemExpectSuccess(sender: IKeyringPair, collectionId: number, createMode: string, owner: string = '') {434  let newItemId: number = 0;435  await usingApi(async (api) => {436    const AItemCount = parseInt((await api.query.nft.itemListIndex(collectionId)).toString(), 10);437    const Aitem: any = (await api.query.nft.fungibleItemList(collectionId, owner)).toJSON();438    const AItemBalance = new BigNumber(Aitem.Value);439440    if (owner === '') {441      owner = sender.address;442    }443444    let tx;445    if (createMode === 'Fungible') {446      const createData = {fungible: {value: 10}};447      tx = api.tx.nft.createItem(collectionId, owner, createData);448    } else {449      tx = api.tx.nft.createItem(collectionId, owner, createMode);450    }451    const events = await submitTransactionAsync(sender, tx);452    const result = getCreateItemResult(events);453454    const BItemCount = parseInt((await api.query.nft.itemListIndex(collectionId)).toString(), 10);455    const Bitem: any = (await api.query.nft.fungibleItemList(collectionId, owner)).toJSON();456    const BItemBalance = new BigNumber(Bitem.Value);457458    // What to expect459    // tslint:disable-next-line:no-unused-expression460    expect(result.success).to.be.true;461    if (createMode === 'Fungible') {462      expect(BItemBalance.minus(AItemBalance).toNumber()).to.be.equal(10);463    } else {464      expect(BItemCount).to.be.equal(AItemCount + 1);465    }466    expect(collectionId).to.be.equal(result.collectionId);467    expect(BItemCount).to.be.equal(result.itemId);468    newItemId = result.itemId;469  });470  return newItemId;471}472473export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {474  await usingApi(async (api) => {475476    // Run the transaction477    const tx = api.tx.nft.setPublicAccessMode(collectionId, 'WhiteList');478    const events = await submitTransactionAsync(sender, tx);479    const result = getGenericResult(events);480481    // Get the collection482    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();483484    // What to expect485    expect(result.success).to.be.true;486    expect(collection.Access).to.be.equal('WhiteList');487  });488}489490export async function enablePublicMintingExpectSuccess(sender: IKeyringPair, collectionId: number) {491  await usingApi(async (api) => {492493    // Run the transaction494    const tx = api.tx.nft.setMintPermission(collectionId, true);495    const events = await submitTransactionAsync(sender, tx);496    const result = getGenericResult(events);497498    // Get the collection499    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();500501    // What to expect502    expect(result.success).to.be.true;503    expect(collection.MintMode).to.be.equal(true);504  });505}506507export async function addToWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {508  await usingApi(async (api) => {509510    // Run the transaction511    const tx = api.tx.nft.addToWhiteList(collectionId, address);512    const events = await submitTransactionAsync(sender, tx);513    const result = getGenericResult(events);514515    // Get the collection516    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();517518    // What to expect519    expect(result.success).to.be.true;520    expect(collection.MintMode).to.be.equal(true);521  });522}523524export const getDetailedCollectionInfo = async (api: ApiPromise, collectionId: number)525  : Promise<ICollectionInterface | null> => {526  return await api.query.nft.collection(collectionId) as unknown as ICollectionInterface;527};528529export const getCreatedCollectionCount = async (api: ApiPromise): Promise<number> => {530  // set global object - collectionsCount531  return (await api.query.nft.createdCollectionCount() as unknown as BN).toNumber();532};