1import {ApiPromise} from '@polkadot/api';2import {3 RmrkTraitsNftAccountIdOrCollectionNftTuple as NftOwner,4 RmrkTraitsPropertyPropertyInfo as Property,5 RmrkTraitsResourceResourceInfo as ResourceInfo,6} from '@polkadot/types/lookup';7import type {EventRecord} from '@polkadot/types/interfaces';8import type {GenericEventData} from '@polkadot/types';9import privateKey from '../../substrate/privateKey';10import {NftIdTuple, getChildren, getOwnedNfts, getCollectionProperties, getNftProperties, getResources} from './fetch';11import chaiAsPromised from 'chai-as-promised';12import chai from 'chai';1314chai.use(chaiAsPromised);15const expect = chai.expect;1617interface TxResult<T> {18 success: boolean;19 successData: T | null;20}2122export function makeNftOwner(api: ApiPromise, owner: string | NftIdTuple): NftOwner {23 const isNftSending = (typeof owner !== 'string');2425 if (isNftSending) {26 return api.createType('RmrkTraitsNftAccountIdOrCollectionNftTuple', {27 'CollectionAndNftTuple': owner,28 });29 } else {30 const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;31 return api.createType('RmrkTraitsNftAccountIdOrCollectionNftTuple', {32 AccountId: privateKey(owner, Number(ss58Format)).address,33 });34 }35}3637export async function isNftOwnedBy(38 api: ApiPromise,39 owner: string | NftIdTuple,40 collectionId: number,41 nftId: number,42): Promise<boolean> {43 if (typeof owner === 'string') {44 return (await getOwnedNfts(api, owner, collectionId))45 .find(ownedNftId => {46 return ownedNftId === nftId;47 }) !== undefined;48 } else {49 return (await getChildren(api, owner[0], owner[1]))50 .find(child => {51 return collectionId === child.collectionId.toNumber()52 && nftId === child.nftId.toNumber();53 }) !== undefined;54 }55}5657export function isPropertyExists(58 key: string,59 value: string,60 props: Property[],61): boolean {62 let isPropFound = false;63 for (let i = 0; i < props.length && !isPropFound; i++) {64 const fetchedProp = props[i];6566 isPropFound = fetchedProp.key.eq(key)67 && fetchedProp.value.eq(value);68 }6970 return isPropFound;71}7273export async function isCollectionPropertyExists(74 api: ApiPromise,75 collectionId: number,76 key: string,77 value: string,78): Promise<boolean> {79 const fetchedProps = await getCollectionProperties(api, collectionId);80 return isPropertyExists(key, value, fetchedProps);81}8283export async function isNftPropertyExists(84 api: ApiPromise,85 collectionId: number,86 nftId: number,87 key: string,88 value: string,89): Promise<boolean> {90 const fetchedProps = await getNftProperties(api, collectionId, nftId);91 return isPropertyExists(key, value, fetchedProps);92}9394export async function isNftChildOfAnother(95 api: ApiPromise,96 collectionId: number,97 nftId: number,98 parentNft: NftIdTuple,99): Promise<boolean> {100 return (await getChildren(api, parentNft[0], parentNft[1]))101 .find((childNft) => {102 return childNft.collectionId.toNumber() === collectionId103 && childNft.nftId.toNumber() === nftId;104 }) !== undefined;105}106107export function isTxResultSuccess(events: EventRecord[]): boolean {108 let success = false;109110 events.forEach(({event: {data, method, section}}) => {111 if (method == 'ExtrinsicSuccess') {112 success = true;113 }114 });115116 return success;117}118119export async function expectTxFailure(expectedError: RegExp, promise: Promise<any>) {120 await expect(promise).to.be.rejectedWith(expectedError);121}122123export function extractTxResult<T>(124 events: EventRecord[],125 expectSection: string,126 expectMethod: string,127 extractAction: (data: any) => T,128): TxResult<T> {129 let success = false;130 let successData = null;131 events.forEach(({event: {data, method, section}}) => {132 if (method == 'ExtrinsicSuccess') {133 success = true;134 } else if ((expectSection == section) && (expectMethod == method)) {135 successData = extractAction(data);136 }137 });138 const result: TxResult<T> = {139 success,140 successData,141 };142 return result;143}144145export function extractRmrkCoreTxResult<T>(146 events: EventRecord[],147 expectMethod: string,148 extractAction: (data: GenericEventData) => T,149): TxResult<T> {150 return extractTxResult(events, 'rmrkCore', expectMethod, extractAction);151}152153export function extractRmrkEquipTxResult<T>(154 events: EventRecord[],155 expectMethod: string,156 extractAction: (data: GenericEventData) => T,157): TxResult<T> {158 return extractTxResult(events, 'rmrkEquip', expectMethod, extractAction);159}160161export async function findResourceById(162 api: ApiPromise,163 collectionId: number,164 nftId: number,165 resourceId: number,166): Promise<ResourceInfo> {167 const resources = await getResources(api, collectionId, nftId);168169 let resource = null;170171 for (let i = 0; i < resources.length; i++) {172 const res = resources[i];173174 if (res.id.eq(resourceId)) {175 resource = res;176 break;177 }178 }179180 return resource!;181}182183export async function getResourceById(184 api: ApiPromise,185 collectionId: number,186 nftId: number,187 resourceId: number,188): Promise<ResourceInfo> {189 const resource = await findResourceById(190 api,191 collectionId,192 nftId,193 resourceId,194 );195196 expect(resource !== null, 'Error: resource was not found').to.be.true;197198 return resource!;199}200201export function checkResourceStatus(202 resource: ResourceInfo,203 expectedStatus: 'pending' | 'added',204) {205 expect(resource.pending.isTrue, `Error: added resource should be ${expectedStatus}`)206 .to.be.equal(expectedStatus === 'pending');207}