difftreelog
Merge pull request #539 from UniqueNetwork/test/move-to-playgrounds
in: master
Test/move to playgrounds
3 files changed
tests/src/util/playgrounds/types.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/util/playgrounds/types.ts
@@ -0,0 +1,130 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+import {IKeyringPair} from '@polkadot/types/types';
+
+export interface IChainEvent {
+ data: any;
+ method: string;
+ section: string;
+}
+
+export interface ITransactionResult {
+ status: 'Fail' | 'Success';
+ result: {
+ events: {
+ event: IChainEvent
+ }[];
+ },
+ moduleError?: string;
+}
+
+export interface ILogger {
+ log: (msg: any, level?: string) => void;
+ level: {
+ ERROR: 'ERROR';
+ WARNING: 'WARNING';
+ INFO: 'INFO';
+ [key: string]: string;
+ }
+}
+
+export interface IUniqueHelperLog {
+ executedAt: number;
+ executionTime: number;
+ type: 'extrinsic' | 'rpc';
+ status: 'Fail' | 'Success';
+ call: string;
+ params: any[];
+ moduleError?: string;
+ events?: any;
+}
+
+export interface IApiListeners {
+ connected?: (...args: any[]) => any;
+ disconnected?: (...args: any[]) => any;
+ error?: (...args: any[]) => any;
+ ready?: (...args: any[]) => any;
+ decorated?: (...args: any[]) => any;
+}
+
+export interface ICrossAccountId {
+ Substrate?: TSubstrateAccount;
+ Ethereum?: TEthereumAccount;
+}
+
+export interface ICrossAccountIdLower {
+ substrate?: TSubstrateAccount;
+ ethereum?: TEthereumAccount;
+}
+
+export interface ICollectionLimits {
+ accountTokenOwnershipLimit?: number | null;
+ sponsoredDataSize?: number | null;
+ sponsoredDataRateLimit?: {blocks: number} | {sponsoringDisabled: null} | null;
+ tokenLimit?: number | null;
+ sponsorTransferTimeout?: number | null;
+ sponsorApproveTimeout?: number | null;
+ ownerCanTransfer?: boolean | null;
+ ownerCanDestroy?: boolean | null;
+ transfersEnabled?: boolean | null;
+}
+
+export interface INestingPermissions {
+ tokenOwner?: boolean;
+ collectionAdmin?: boolean;
+ restricted?: number[] | null;
+}
+
+export interface ICollectionPermissions {
+ access?: 'Normal' | 'AllowList';
+ mintMode?: boolean;
+ nesting?: INestingPermissions;
+}
+
+export interface IProperty {
+ key: string;
+ value: string;
+}
+
+export interface ITokenPropertyPermission {
+ key: string;
+ permission: {
+ mutable: boolean;
+ tokenOwner: boolean;
+ collectionAdmin: boolean;
+ }
+}
+
+export interface IToken {
+ collectionId: number;
+ tokenId: number;
+}
+
+export interface ICollectionCreationOptions {
+ name: string | number[];
+ description: string | number[];
+ tokenPrefix: string | number[];
+ mode?: {
+ nft?: null;
+ refungible?: null;
+ fungible?: number;
+ }
+ permissions?: ICollectionPermissions;
+ properties?: IProperty[];
+ tokenPropertyPermissions?: ITokenPropertyPermission[];
+ limits?: ICollectionLimits;
+ pendingSponsor?: TSubstrateAccount;
+}
+
+export interface IChainProperties {
+ ss58Format: number;
+ tokenDecimals: number[];
+ tokenSymbol: string[]
+}
+
+export type TSubstrateAccount = string;
+export type TEthereumAccount = string;
+export type TApiAllowedListeners = 'connected' | 'disconnected' | 'error' | 'ready' | 'decorated';
+export type TUniqueNetworks = 'opal' | 'quartz' | 'unique';
+export type TSigner = IKeyringPair; // | 'string'
\ No newline at end of file
tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth334import {mnemonicGenerate} from '@polkadot/util-crypto';4import {mnemonicGenerate} from '@polkadot/util-crypto';5import {UniqueHelper} from './unique';5import {UniqueHelper} from './unique';6import {IKeyringPair} from '@polkadot/types/types';7import {ApiPromise, WsProvider} from '@polkadot/api';6import {ApiPromise, WsProvider} from '@polkadot/api';8import * as defs from '../../interfaces/definitions';7import * as defs from '../../interfaces/definitions';8import {TSigner} from './types';9import {IKeyringPair} from '@polkadot/types/types';910101111export class DevUniqueHelper extends UniqueHelper {12export class DevUniqueHelper extends UniqueHelper {73 let nonce = await this.helper.chain.getNonce(donor.address);74 let nonce = await this.helper.chain.getNonce(donor.address);74 const tokenNominal = this.helper.balance.getOneTokenNominal();75 const tokenNominal = this.helper.balance.getOneTokenNominal();75 const transactions = [];76 const transactions = [];76 const accounts = [];77 const accounts: IKeyringPair[] = [];77 for (const balance of balances) {78 for (const balance of balances) {78 const recepient = this.helper.util.fromSeed(mnemonicGenerate());79 const recepient = this.helper.util.fromSeed(mnemonicGenerate());79 accounts.push(recepient);80 accounts.push(recepient);84 }85 }85 }86 }868787 await Promise.all(transactions);88 await Promise.all(transactions).catch(e => {});89 90 //#region TODO remove this region, when nonce problem will be solved91 const checkBalances = async () => {92 let isSuccess = true;93 for (let i = 0; i < balances.length; i++) {94 const balance = await this.helper.balance.getSubstrate(accounts[i].address);95 if (balance !== balances[i] * tokenNominal) {96 isSuccess = false;97 break;98 }99 }100 return isSuccess;101 };102103 let accountsCreated = false;104 // checkBalances retry up to 5 blocks105 for (let index = 0; index < 5; index++) {106 console.log(await this.helper.chain.getLatestBlockNumber());107 accountsCreated = await checkBalances();108 if(accountsCreated) break;109 await this.waitNewBlocks(1);110 }111112 if (!accountsCreated) throw Error('Accounts generation failed');113 //#endregion11488 return accounts;115 return accounts;89 };116 };117118 /**119 * Wait for specified bnumber of blocks120 * @param blocksCount number of blocks to wait121 * @returns 122 */123 async waitNewBlocks(blocksCount = 1): Promise<void> {124 const promise = new Promise<void>(async (resolve) => {125 const unsubscribe = await this.helper.api!.rpc.chain.subscribeNewHeads(() => {126 if (blocksCount > 0) {127 blocksCount--;128 } else {129 unsubscribe();130 resolve();131 }132 });133 });134 return promise;135 }90}136}tests/src/util/playgrounds/unique.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -7,10 +7,10 @@
import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';
import {ApiInterfaceEvents} from '@polkadot/api/types';
+import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';
import {IKeyringPair} from '@polkadot/types/types';
-import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';
+import {IApiListeners, IChainEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types';
-
const crossAccountIdFromLower = (lowerAddress: ICrossAccountIdLower): ICrossAccountId => {
const address = {} as ICrossAccountId;
if(lowerAddress.substrate) address.Substrate = lowerAddress.substrate;
@@ -43,133 +43,6 @@
return this.toChecksumAddress(`0xf8238ccfff8ed887463fd5e0${collectionId.toString(16).padStart(8, '0')}${tokenId.toString(16).padStart(8, '0')}`);
},
};
-
-
-interface IChainEvent {
- data: any;
- method: string;
- section: string;
-}
-
-interface ITransactionResult {
- status: 'Fail' | 'Success';
- result: {
- events: {
- event: IChainEvent
- }[];
- },
- moduleError?: string;
-}
-
-interface ILogger {
- log: (msg: any, level?: string) => void;
- level: {
- ERROR: 'ERROR';
- WARNING: 'WARNING';
- INFO: 'INFO';
- [key: string]: string;
- }
-}
-
-interface IUniqueHelperLog {
- executedAt: number;
- executionTime: number;
- type: 'extrinsic' | 'rpc';
- status: 'Fail' | 'Success';
- call: string;
- params: any[];
- moduleError?: string;
- events?: any;
-}
-
-interface IApiListeners {
- connected?: (...args: any[]) => any;
- disconnected?: (...args: any[]) => any;
- error?: (...args: any[]) => any;
- ready?: (...args: any[]) => any;
- decorated?: (...args: any[]) => any;
-}
-
-interface ICrossAccountId {
- Substrate?: TSubstrateAccount;
- Ethereum?: TEthereumAccount;
-}
-
-interface ICrossAccountIdLower {
- substrate?: TSubstrateAccount;
- ethereum?: TEthereumAccount;
-}
-
-interface ICollectionLimits {
- accountTokenOwnershipLimit?: number | null;
- sponsoredDataSize?: number | null;
- sponsoredDataRateLimit?: {blocks: number} | {sponsoringDisabled: null} | null;
- tokenLimit?: number | null;
- sponsorTransferTimeout?: number | null;
- sponsorApproveTimeout?: number | null;
- ownerCanTransfer?: boolean | null;
- ownerCanDestroy?: boolean | null;
- transfersEnabled?: boolean | null;
-}
-
-interface INestingPermissions {
- tokenOwner?: boolean;
- collectionAdmin?: boolean;
- restricted?: number[] | null;
-}
-
-interface ICollectionPermissions {
- access?: 'Normal' | 'AllowList';
- mintMode?: boolean;
- nesting?: INestingPermissions;
-}
-
-interface IProperty {
- key: string;
- value: string;
-}
-
-interface ITokenPropertyPermission {
- key: string;
- permission: {
- mutable: boolean;
- tokenOwner: boolean;
- collectionAdmin: boolean;
- }
-}
-
-interface IToken {
- collectionId: number;
- tokenId: number;
-}
-
-interface ICollectionCreationOptions {
- name: string | number[];
- description: string | number[];
- tokenPrefix: string | number[];
- mode?: {
- nft?: null;
- refungible?: null;
- fungible?: number;
- }
- permissions?: ICollectionPermissions;
- properties?: IProperty[];
- tokenPropertyPermissions?: ITokenPropertyPermission[];
- limits?: ICollectionLimits;
- pendingSponsor?: TSubstrateAccount;
-}
-
-interface IChainProperties {
- ss58Format: number;
- tokenDecimals: number[];
- tokenSymbol: string[]
-}
-
-type TSubstrateAccount = string;
-type TEthereumAccount = string;
-type TApiAllowedListeners = 'connected' | 'disconnected' | 'error' | 'ready' | 'decorated';
-type TUniqueNetworks = 'opal' | 'quartz' | 'unique';
-type TSigner = IKeyringPair; // | 'string'
class UniqueUtil {
static transactionStatus = {
@@ -652,6 +525,22 @@
}
/**
+ * Get the normalized addresses added to the collection allow-list.
+ * @param collectionId ID of collection
+ * @example await getAllowList(1)
+ * @returns array of allow-listed addresses
+ */
+ async getAllowList(collectionId: number): Promise<ICrossAccountId[]> {
+ const normalized = [];
+ const allowListed = (await this.helper.callRpc('api.rpc.unique.allowlist', [collectionId])).toHuman();
+ for (const address of allowListed) {
+ if (address.Substrate) normalized.push({Substrate: this.helper.address.normalizeSubstrate(address.Substrate)});
+ else normalized.push(address);
+ }
+ return normalized;
+ }
+
+ /**
* Get the effective limits of the collection instead of null for default values
*
* @param collectionId ID of collection
@@ -795,6 +684,25 @@
}
/**
+ * Adds an address to allow list
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param addressObj address to add to the allow list
+ * @param label extra label for log
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async addToAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.addToAllowList', [collectionId, addressObj],
+ true, `Unable to add address to allow list for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressAdded');
+ }
+
+ /**
* Removes a collection administrator.
*
* @param signer keyring of signer
@@ -2119,6 +2027,10 @@
return await this.helper.collection.getAdmins(this.collectionId);
}
+ async getAllowList() {
+ return await this.helper.collection.getAllowList(this.collectionId);
+ }
+
async getEffectiveLimits() {
return await this.helper.collection.getEffectiveLimits(this.collectionId);
}
@@ -2143,6 +2055,10 @@
return await this.helper.collection.addAdmin(signer, this.collectionId, adminAddressObj, label);
}
+ async addToAllowList(signer: TSigner, addressObj: ICrossAccountId, label?: string) {
+ return await this.helper.collection.addToAllowList(signer, this.collectionId, addressObj, label);
+ }
+
async removeAdmin(signer: TSigner, adminAddressObj: ICrossAccountId, label?: string) {
return await this.helper.collection.removeAdmin(signer, this.collectionId, adminAddressObj, label);
}