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

difftreelog

source

tests/src/substrate/substrate-api.ts6.0 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import '../interfaces/augment-api-events';18import {WsProvider, ApiPromise} from '@polkadot/api';19import {EventRecord} from '@polkadot/types/interfaces/system/types';20import {ExtrinsicStatus} from '@polkadot/types/interfaces/author/types';21import {IKeyringPair} from '@polkadot/types/types';2223import config from '../config';24import promisifySubstrate from './promisify-substrate';25import {ApiOptions, SubmittableExtrinsic, ApiTypes} from '@polkadot/api/types';26import * as defs from '../interfaces/definitions';272829function defaultApiOptions(): ApiOptions {30  const wsProvider = new WsProvider(config.substrateUrl);31  return {32    provider: wsProvider, signedExtensions: {33      ContractHelpers: {34        extrinsic: {},35        payload: {},36      },37    },38    rpc: {39      unique: defs.unique.rpc,40    },41  };42}4344export default async function usingApi<T = void>(action: (api: ApiPromise) => Promise<T>, settings: ApiOptions | undefined = undefined): Promise<T> {45  settings = settings || defaultApiOptions();46  const api: ApiPromise = new ApiPromise(settings);47  let result: T = null as unknown as T;4849  // TODO: Remove, this is temporary: Filter unneeded API output50  // (Jaco promised it will be removed in the next version)51  const consoleErr = console.error;52  const consoleLog = console.log;53  const consoleWarn = console.warn;5455  const outFn = (printer: any) => (...args: any[]) => {56    for (const arg of args) {57      if (typeof arg !== 'string')58        continue;59      if (arg.includes('1000:: Normal connection closure' || arg === 'Normal connection closure'))60        return;61    }62    printer(...args);63  };6465  console.error = outFn(consoleErr.bind(console));66  console.log = outFn(consoleLog.bind(console));67  console.warn = outFn(consoleWarn.bind(console));6869  try {70    await promisifySubstrate(api, async () => {71      if (api) {72        await api.isReadyOrError;73        result = await action(api);74      }75    })();76  } finally {77    await api.disconnect();78    console.error = consoleErr;79    console.log = consoleLog;80    console.warn = consoleWarn;81  }82  return result as T;83}8485enum TransactionStatus {86  Success,87  Fail,88  NotReady89}9091function getTransactionStatus(events: EventRecord[], status: ExtrinsicStatus): TransactionStatus {92  if (status.isReady) {93    return TransactionStatus.NotReady;94  }95  if (status.isBroadcast) {96    return TransactionStatus.NotReady;97  }98  if (status.isInBlock || status.isFinalized) {99    if(events.filter(e => e.event.data.method === 'ExtrinsicFailed').length > 0) {100      return TransactionStatus.Fail;101    }102    if(events.filter(e => e.event.data.method === 'ExtrinsicSuccess').length > 0) {103      return TransactionStatus.Success;104    }105  }106107  return TransactionStatus.Fail;108}109110export function executeTransaction(api: ApiPromise, sender: IKeyringPair, transaction: SubmittableExtrinsic<'promise'>): Promise<EventRecord[]> {111  return new Promise(async (res, rej) => {112    try {113      await transaction.signAndSend(sender, ({events, status}) => {114        if (!status.isInBlock && !status.isFinalized) return;115        for (const {event} of events) {116          if (api.events.system.ExtrinsicSuccess.is(event)) {117            res(events);118          } else if (api.events.system.ExtrinsicFailed.is(event)) {119            const {data: [error]} = event;120            if (error.isModule) {121              const decoded = api.registry.findMetaError(error.asModule);122              const {method, section} = decoded;123              rej(new Error(`${section}.${method}`));124            } else {125              rej(new Error(error.toString()));126            }127          }128        }129      });130    } catch (e) {131      rej(e);132    }133  });134}135136export function137submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {138  /* eslint no-async-promise-executor: "off" */139  return new Promise(async (resolve, reject) => {140    try {141      await transaction.signAndSend(sender, ({events = [], status}) => {142        const transactionStatus = getTransactionStatus(events, status);143144        if (transactionStatus === TransactionStatus.Success) {145          resolve(events);146        } else if (transactionStatus === TransactionStatus.Fail) {147          console.log(`Something went wrong with transaction. Status: ${status}`);148          reject(events);149        }150      });151    } catch (e) {152      console.log('Error: ', e);153      reject(e);154    }155  });156}157158export function submitTransactionExpectFailAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {159  console.error = () => {};160  console.log = () => {};161162  /* eslint no-async-promise-executor: "off" */163  return new Promise<EventRecord[]>(async function(res, rej) {164    const resolve = (rec: EventRecord[]) => {165      setTimeout(() => {166        res(rec);167      });168    };169    const reject = (errror: any) => {170      setTimeout(() => {171        rej(errror);172      });173    };174    try {175      await transaction.signAndSend(sender, ({events = [], status}) => {176        const transactionStatus = getTransactionStatus(events, status);177178        // console.log('transactionStatus', transactionStatus, 'events', events);179180        if (transactionStatus === TransactionStatus.Success) {181          resolve(events);182        } else if (transactionStatus === TransactionStatus.Fail) {183          reject(events);184        }185      });186    } catch (e) {187      reject(e);188    }189  });190}