difftreelog
Merge pull request #639 from UniqueNetwork/feature/playgrounds-nested-ops
in: master
Feature/playgrounds nested ops
5 files changed
tests/src/eth/util/playgrounds/index.tsdiffbeforeafterboth--- a/tests/src/eth/util/playgrounds/index.ts
+++ b/tests/src/eth/util/playgrounds/index.ts
@@ -39,7 +39,6 @@
}
finally {
await helper.disconnect();
- await helper.disconnectWeb3();
silentConsole.disable();
}
};
tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/eth/util/playgrounds/unique.dev.ts
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -321,6 +321,7 @@
}
}
+export type EthUniqueHelperConstructor = new (...args: any[]) => EthUniqueHelper;
export class EthUniqueHelper extends DevUniqueHelper {
web3: Web3 | null = null;
@@ -331,8 +332,10 @@
ethNativeContract: NativeContractGroup;
ethContract: ContractGroup;
- constructor(logger: { log: (msg: any, level: any) => void, level: any }) {
- super(logger);
+ constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {
+ options.helperBase = options.helperBase ?? EthUniqueHelper;
+
+ super(logger, options);
this.eth = new EthGroup(this);
this.ethAddress = new EthAddressGroup(this);
this.ethNativeContract = new NativeContractGroup(this);
@@ -350,10 +353,23 @@
this.web3 = new Web3(this.web3Provider);
}
- async disconnectWeb3() {
+ async disconnect() {
if(this.web3 === null) return;
this.web3Provider?.connection.close();
+
+ await super.disconnect();
+ }
+
+ clearApi() {
this.web3 = null;
}
+
+ clone(helperCls: EthUniqueHelperConstructor, options?: { [key: string]: any; }): EthUniqueHelper {
+ const newHelper = super.clone(helperCls, options) as EthUniqueHelper;
+ newHelper.web3 = this.web3;
+ newHelper.web3Provider = this.web3Provider;
+
+ return newHelper;
+ }
}
\ No newline at end of file
tests/src/util/playgrounds/types.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/types.ts
+++ b/tests/src/util/playgrounds/types.ts
@@ -14,6 +14,7 @@
export interface ITransactionResult {
status: 'Fail' | 'Success';
result: {
+ dispatchError: any,
events: {
phase: any, // {ApplyExtrinsic: number} | 'Initialization',
event: IEvent;
@@ -47,6 +48,7 @@
call: string;
params: any[];
moduleError?: string;
+ dispatchError?: any;
events?: any;
}
@@ -162,6 +164,14 @@
amount: bigint,
}
+export interface ISchedulerOptions {
+ priority?: number,
+ periodic?: {
+ period: number,
+ repetitions: number,
+ },
+}
+
export type TSubstrateAccount = string;
export type TEthereumAccount = string;
export type TApiAllowedListeners = 'connected' | 'disconnected' | 'error' | 'ready' | 'decorated';
tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.dev.ts
+++ b/tests/src/util/playgrounds/unique.dev.ts
@@ -8,7 +8,6 @@
import {IKeyringPair} from '@polkadot/types/types';
import {ICrossAccountId} from './types';
-
export class SilentLogger {
log(_msg: any, _level: any): void { }
level = {
@@ -63,8 +62,10 @@
wait: WaitGroup;
admin: AdminGroup;
- constructor(logger: { log: (msg: any, level: any) => void, level: any }) {
- super(logger);
+ constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {
+ options.helperBase = options.helperBase ?? DevUniqueHelper;
+
+ super(logger, options);
this.arrange = new ArrangeGroup(this);
this.wait = new WaitGroup(this);
this.admin = new AdminGroup(this);
@@ -108,9 +109,9 @@
}
class ArrangeGroup {
- helper: UniqueHelper;
+ helper: DevUniqueHelper;
- constructor(helper: UniqueHelper) {
+ constructor(helper: DevUniqueHelper) {
this.helper = helper;
}
@@ -245,14 +246,14 @@
}
class WaitGroup {
- helper: UniqueHelper;
+ helper: DevUniqueHelper;
- constructor(helper: UniqueHelper) {
+ constructor(helper: DevUniqueHelper) {
this.helper = helper;
}
/**
- * Wait for specified bnumber of blocks
+ * Wait for specified number of blocks
* @param blocksCount number of blocks to wait
* @returns
*/
tests/src/util/playgrounds/unique.tsdiffbeforeafterboth9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';11import {IKeyringPair} from '@polkadot/types/types';11import {IKeyringPair} from '@polkadot/types/types';12import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types';12import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISchedulerOptions, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types';131314export class CrossAccountId implements ICrossAccountId {14export class CrossAccountId implements ICrossAccountId {15 Substrate?: TSubstrateAccount;15 Substrate?: TSubstrateAccount;318 forcedNetwork: TUniqueNetworks | null;318 forcedNetwork: TUniqueNetworks | null;319 network: TUniqueNetworks | null;319 network: TUniqueNetworks | null;320 chainLog: IUniqueHelperLog[];320 chainLog: IUniqueHelperLog[];321 children: ChainHelperBase[];321322322 constructor(logger?: ILogger) {323 constructor(logger?: ILogger) {323 this.util = UniqueUtil;324 this.util = UniqueUtil;328 this.forcedNetwork = null;329 this.forcedNetwork = null;329 this.network = null;330 this.network = null;330 this.chainLog = [];331 this.chainLog = [];332 this.children = [];331 }333 }332334333 getApi(): ApiPromise {335 getApi(): ApiPromise {351 }353 }352354353 async disconnect() {355 async disconnect() {356 for (const child of this.children) {357 child.clearApi();358 }359354 if (this.api === null) return;360 if (this.api === null) return;355 await this.api.disconnect();361 await this.api.disconnect();356 this.api = null;362 this.clearApi();357 this.network = null;358 }363 }364365 clearApi() {366 this.api = null;367 this.network = null;368 }359369360 static async detectNetwork(api: ApiPromise): Promise<TUniqueNetworks> {370 static async detectNetwork(api: ApiPromise): Promise<TUniqueNetworks> {361 const spec = (await api.query.system.lastRuntimeUpgrade()).toJSON() as any;371 const spec = (await api.query.system.lastRuntimeUpgrade()).toJSON() as any;479489480 constructApiCall(apiCall: string, params: any[]) {490 constructApiCall(apiCall: string, params: any[]) {481 if(!apiCall.startsWith('api.')) throw Error(`Invalid api call: ${apiCall}`);491 if(!apiCall.startsWith('api.')) throw Error(`Invalid api call: ${apiCall}`);482 let call = this.api as any;492 let call = this.getApi() as any;483 for(const part of apiCall.slice(4).split('.')) {493 for(const part of apiCall.slice(4).split('.')) {484 call = call[part];494 call = call[part];485 }495 }514 params,524 params,515 } as IUniqueHelperLog;525 } as IUniqueHelperLog;516526517 if(result.status !== this.transactionStatus.SUCCESS && result.moduleError) log.moduleError = result.moduleError;527 if(result.status !== this.transactionStatus.SUCCESS) {528 if (result.moduleError) log.moduleError = result.moduleError;529 else if (result.result.dispatchError) log.dispatchError = result.result.dispatchError;530 }518 if(events.length > 0) log.events = events;531 if(events.length > 0) log.events = events;519532520 this.chainLog.push(log);533 this.chainLog.push(log);521534522 if(expectSuccess && result.status !== this.transactionStatus.SUCCESS) throw Error(`${result.moduleError}`);535 if(expectSuccess && result.status !== this.transactionStatus.SUCCESS) {536 if (result.moduleError) throw Error(`${result.moduleError}`);537 else if (result.result.dispatchError) throw Error(JSON.stringify(result.result.dispatchError));538 }523 return result;539 return result;524 }540 }5255412242 }2258 }2243}2259}22602261class SchedulerGroup extends HelperGroup {2262 constructor(helper: UniqueHelper) {2263 super(helper);2264 }22652266 async cancelScheduled(signer: TSigner, scheduledId: string) {2267 return this.helper.executeExtrinsic(2268 signer,2269 'api.tx.scheduler.cancelNamed',2270 [scheduledId],2271 true,2272 );2273 }22742275 async changePriority(signer: TSigner, scheduledId: string, priority: number) {2276 return this.helper.executeExtrinsic(2277 signer,2278 'api.tx.scheduler.changeNamedPriority',2279 [scheduledId, priority],2280 true,2281 );2282 }22832284 scheduleAt<T extends UniqueHelper>(2285 scheduledId: string,2286 executionBlockNumber: number,2287 options: ISchedulerOptions = {},2288 ) {2289 return this.schedule<T>('scheduleNamed', scheduledId, executionBlockNumber, options);2290 }22912292 scheduleAfter<T extends UniqueHelper>(2293 scheduledId: string,2294 blocksBeforeExecution: number,2295 options: ISchedulerOptions = {},2296 ) {2297 return this.schedule<T>('scheduleNamedAfter', scheduledId, blocksBeforeExecution, options);2298 }22992300 schedule<T extends UniqueHelper>(2301 scheduleFn: 'scheduleNamed' | 'scheduleNamedAfter',2302 scheduledId: string,2303 blocksNum: number,2304 options: ISchedulerOptions = {},2305 ) {2306 // eslint-disable-next-line @typescript-eslint/naming-convention2307 const ScheduledHelperType = ScheduledUniqueHelper(this.helper.helperBase);2308 return this.helper.clone(ScheduledHelperType, {2309 scheduleFn,2310 scheduledId,2311 blocksNum,2312 options,2313 }) as T;2314 }2315}23162317export type UniqueHelperConstructor = new(...args: any[]) => UniqueHelper;224423182245export class UniqueHelper extends ChainHelperBase {2319export class UniqueHelper extends ChainHelperBase {2320 helperBase: any;23212246 chain: ChainGroup;2322 chain: ChainGroup;2247 balance: BalanceGroup;2323 balance: BalanceGroup;2251 rft: RFTGroup;2327 rft: RFTGroup;2252 ft: FTGroup;2328 ft: FTGroup;2253 staking: StakingGroup;2329 staking: StakingGroup;2330 scheduler: SchedulerGroup;225423312255 constructor(logger?: ILogger) {2332 constructor(logger?: ILogger, options: {[key: string]: any} = {}) {2256 super(logger);2333 super(logger);23342335 this.helperBase = options.helperBase ?? UniqueHelper;23362257 this.chain = new ChainGroup(this);2337 this.chain = new ChainGroup(this);2258 this.balance = new BalanceGroup(this);2338 this.balance = new BalanceGroup(this);2262 this.rft = new RFTGroup(this);2342 this.rft = new RFTGroup(this);2263 this.ft = new FTGroup(this);2343 this.ft = new FTGroup(this);2264 this.staking = new StakingGroup(this);2344 this.staking = new StakingGroup(this);2345 this.scheduler = new SchedulerGroup(this);2265 }2346 }23472348 clone(helperCls: UniqueHelperConstructor, options: {[key: string]: any} = {}) {2349 Object.setPrototypeOf(helperCls.prototype, this);2350 const newHelper = new helperCls(this.logger, options);23512352 newHelper.api = this.api;2353 newHelper.network = this.network;2354 newHelper.forceNetwork = this.forceNetwork;23552356 this.children.push(newHelper);23572358 return newHelper;2359 }23602361 getSudo<T extends UniqueHelper>() {2362 // eslint-disable-next-line @typescript-eslint/naming-convention2363 const SudoHelperType = SudoUniqueHelper(this.helperBase);2364 return this.clone(SudoHelperType) as T;2365 }2266}2366}226723672368// eslint-disable-next-line @typescript-eslint/naming-convention2369function ScheduledUniqueHelper<T extends UniqueHelperConstructor>(Base: T) {2370 return class extends Base {2371 scheduleFn: 'scheduleNamed' | 'scheduleNamedAfter';2372 scheduledId: string;2373 blocksNum: number;2374 options: ISchedulerOptions;23752376 constructor(...args: any[]) {2377 const logger = args[0] as ILogger;2378 const options = args[1] as {2379 scheduleFn: 'scheduleNamed' | 'scheduleNamedAfter',2380 scheduledId: string,2381 blocksNum: number,2382 options: ISchedulerOptions2383 };23842385 super(logger);23862387 this.scheduleFn = options.scheduleFn;2388 this.scheduledId = options.scheduledId;2389 this.blocksNum = options.blocksNum;2390 this.options = options.options;2391 }23922393 executeExtrinsic(sender: IKeyringPair, scheduledExtrinsic: string, scheduledParams: any[], expectSuccess?: boolean): Promise<ITransactionResult> {2394 const scheduledTx = this.constructApiCall(scheduledExtrinsic, scheduledParams);2395 const extrinsic = 'api.tx.scheduler.' + this.scheduleFn;23962397 return super.executeExtrinsic(2398 sender,2399 extrinsic,2400 [2401 this.scheduledId,2402 this.blocksNum,2403 this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null,2404 this.options.priority ?? null,2405 {Value: scheduledTx},2406 ],2407 expectSuccess,2408 );2409 }2410 };2411}24122413// eslint-disable-next-line @typescript-eslint/naming-convention2414function SudoUniqueHelper<T extends UniqueHelperConstructor>(Base: T) {2415 return class extends Base {2416 constructor(...args: any[]) {2417 super(...args);2418 }24192420 executeExtrinsic (2421 sender: IKeyringPair,2422 extrinsic: string,2423 params: any[],2424 expectSuccess?: boolean,2425 ): Promise<ITransactionResult> {2426 const call = this.constructApiCall(extrinsic, params);24272428 return super.executeExtrinsic(2429 sender,2430 'api.tx.sudo.sudo',2431 [call],2432 expectSuccess,2433 );2434 }2435 };2436}226824372269export class UniqueBaseCollection {2438export class UniqueBaseCollection {2270 helper: UniqueHelper;2439 helper: UniqueHelper;2367 return await this.helper.collection.burn(signer, this.collectionId);2536 return await this.helper.collection.burn(signer, this.collectionId);2368 }2537 }25382539 scheduleAt<T extends UniqueHelper>(2540 scheduledId: string,2541 executionBlockNumber: number,2542 options: ISchedulerOptions = {},2543 ) {2544 const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);2545 return new UniqueBaseCollection(this.collectionId, scheduledHelper);2546 }25472548 scheduleAfter<T extends UniqueHelper>(2549 scheduledId: string,2550 blocksBeforeExecution: number,2551 options: ISchedulerOptions = {},2552 ) {2553 const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2554 return new UniqueBaseCollection(this.collectionId, scheduledHelper);2555 }25562557 getSudo<T extends UniqueHelper>() {2558 return new UniqueBaseCollection(this.collectionId, this.helper.getSudo<T>());2559 }2369}2560}23702561237125622454 return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);2645 return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);2455 }2646 }26472648 scheduleAt<T extends UniqueHelper>(2649 scheduledId: string,2650 executionBlockNumber: number,2651 options: ISchedulerOptions = {},2652 ) {2653 const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);2654 return new UniqueNFTCollection(this.collectionId, scheduledHelper);2655 }26562657 scheduleAfter<T extends UniqueHelper>(2658 scheduledId: string,2659 blocksBeforeExecution: number,2660 options: ISchedulerOptions = {},2661 ) {2662 const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2663 return new UniqueNFTCollection(this.collectionId, scheduledHelper);2664 }26652666 getSudo<T extends UniqueHelper>() {2667 return new UniqueNFTCollection(this.collectionId, this.helper.getSudo<T>());2668 }2456}2669}24572670245826712537 return await this.helper.rft.setTokenPropertyPermissions(signer, this.collectionId, permissions);2750 return await this.helper.rft.setTokenPropertyPermissions(signer, this.collectionId, permissions);2538 }2751 }27522753 scheduleAt<T extends UniqueHelper>(2754 scheduledId: string,2755 executionBlockNumber: number,2756 options: ISchedulerOptions = {},2757 ) {2758 const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);2759 return new UniqueRFTCollection(this.collectionId, scheduledHelper);2760 }27612762 scheduleAfter<T extends UniqueHelper>(2763 scheduledId: string,2764 blocksBeforeExecution: number,2765 options: ISchedulerOptions = {},2766 ) {2767 const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2768 return new UniqueRFTCollection(this.collectionId, scheduledHelper);2769 }27702771 getSudo<T extends UniqueHelper>() {2772 return new UniqueRFTCollection(this.collectionId, this.helper.getSudo<T>());2773 }2539}2774}25402775254127762584 return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount);2819 return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount);2585 }2820 }28212822 scheduleAt<T extends UniqueHelper>(2823 scheduledId: string,2824 executionBlockNumber: number,2825 options: ISchedulerOptions = {},2826 ) {2827 const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);2828 return new UniqueFTCollection(this.collectionId, scheduledHelper);2829 }28302831 scheduleAfter<T extends UniqueHelper>(2832 scheduledId: string,2833 blocksBeforeExecution: number,2834 options: ISchedulerOptions = {},2835 ) {2836 const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2837 return new UniqueFTCollection(this.collectionId, scheduledHelper);2838 }28392840 getSudo<T extends UniqueHelper>() {2841 return new UniqueFTCollection(this.collectionId, this.helper.getSudo<T>());2842 }2586}2843}25872844258828452621 return this.collection.helper.util.getTokenAccount(this);2878 return this.collection.helper.util.getTokenAccount(this);2622 }2879 }28802881 scheduleAt<T extends UniqueHelper>(2882 scheduledId: string,2883 executionBlockNumber: number,2884 options: ISchedulerOptions = {},2885 ) {2886 const scheduledCollection = this.collection.scheduleAt<T>(scheduledId, executionBlockNumber, options);2887 return new UniqueBaseToken(this.tokenId, scheduledCollection);2888 }28892890 scheduleAfter<T extends UniqueHelper>(2891 scheduledId: string,2892 blocksBeforeExecution: number,2893 options: ISchedulerOptions = {},2894 ) {2895 const scheduledCollection = this.collection.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2896 return new UniqueBaseToken(this.tokenId, scheduledCollection);2897 }28982899 getSudo<T extends UniqueHelper>() {2900 return new UniqueBaseToken(this.tokenId, this.collection.getSudo<T>());2901 }2623}2902}26242903262529042679 return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj);2958 return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj);2680 }2959 }29602961 scheduleAt<T extends UniqueHelper>(2962 scheduledId: string,2963 executionBlockNumber: number,2964 options: ISchedulerOptions = {},2965 ) {2966 const scheduledCollection = this.collection.scheduleAt<T>(scheduledId, executionBlockNumber, options);2967 return new UniqueNFToken(this.tokenId, scheduledCollection);2968 }29692970 scheduleAfter<T extends UniqueHelper>(2971 scheduledId: string,2972 blocksBeforeExecution: number,2973 options: ISchedulerOptions = {},2974 ) {2975 const scheduledCollection = this.collection.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2976 return new UniqueNFToken(this.tokenId, scheduledCollection);2977 }29782979 getSudo<T extends UniqueHelper>() {2980 return new UniqueNFToken(this.tokenId, this.collection.getSudo<T>());2981 }2681}2982}268229832683export class UniqueRFToken extends UniqueBaseToken {2984export class UniqueRFToken extends UniqueBaseToken {2732 return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj, amount);3033 return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj, amount);2733 }3034 }30353036 scheduleAt<T extends UniqueHelper>(3037 scheduledId: string,3038 executionBlockNumber: number,3039 options: ISchedulerOptions = {},3040 ) {3041 const scheduledCollection = this.collection.scheduleAt<T>(scheduledId, executionBlockNumber, options);3042 return new UniqueRFToken(this.tokenId, scheduledCollection);3043 }30443045 scheduleAfter<T extends UniqueHelper>(3046 scheduledId: string,3047 blocksBeforeExecution: number,3048 options: ISchedulerOptions = {},3049 ) {3050 const scheduledCollection = this.collection.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);3051 return new UniqueRFToken(this.tokenId, scheduledCollection);3052 }30533054 getSudo<T extends UniqueHelper>() {3055 return new UniqueRFToken(this.tokenId, this.collection.getSudo<T>());3056 }2734}3057}27353058