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

difftreelog

source

tests/src/substrate/substrate-api.ts6.1 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      FakeTransactionFinalizer: {38        extrinsic: {},39        payload: {},40      },41    },42    rpc: {43      unique: defs.unique.rpc,44    },45  };46}4748export default async function usingApi<T = void>(action: (api: ApiPromise) => Promise<T>, settings: ApiOptions | undefined = undefined): Promise<T> {49  settings = settings || defaultApiOptions();50  const api: ApiPromise = new ApiPromise(settings);51  let result: T = null as unknown as T;5253  // TODO: Remove, this is temporary: Filter unneeded API output54  // (Jaco promised it will be removed in the next version)55  const consoleErr = console.error;56  const consoleLog = console.log;57  const consoleWarn = console.warn;5859  const outFn = (printer: any) => (...args: any[]) => {60    for (const arg of args) {61      if (typeof arg !== 'string')62        continue;63      if (arg.includes('1000:: Normal connection closure' || arg === 'Normal connection closure'))64        return;65    }66    printer(...args);67  };6869  console.error = outFn(consoleErr.bind(console));70  console.log = outFn(consoleLog.bind(console));71  console.warn = outFn(consoleWarn.bind(console));7273  try {74    await promisifySubstrate(api, async () => {75      if (api) {76        await api.isReadyOrError;77        result = await action(api);78      }79    })();80  } finally {81    await api.disconnect();82    console.error = consoleErr;83    console.log = consoleLog;84    console.warn = consoleWarn;85  }86  return result as T;87}8889enum TransactionStatus {90  Success,91  Fail,92  NotReady93}9495function getTransactionStatus(events: EventRecord[], status: ExtrinsicStatus): TransactionStatus {96  if (status.isReady) {97    return TransactionStatus.NotReady;98  }99  if (status.isBroadcast) {100    return TransactionStatus.NotReady;101  }102  if (status.isInBlock || status.isFinalized) {103    if(events.filter(e => e.event.data.method === 'ExtrinsicFailed').length > 0) {104      return TransactionStatus.Fail;105    }106    if(events.filter(e => e.event.data.method === 'ExtrinsicSuccess').length > 0) {107      return TransactionStatus.Success;108    }109  }110111  return TransactionStatus.Fail;112}113114export function executeTransaction(api: ApiPromise, sender: IKeyringPair, transaction: SubmittableExtrinsic<'promise'>): Promise<EventRecord[]> {115  return new Promise(async (res, rej) => {116    try {117      await transaction.signAndSend(sender, ({events, status}) => {118        if (!status.isInBlock && !status.isFinalized) return;119        for (const {event} of events) {120          if (api.events.system.ExtrinsicSuccess.is(event)) {121            res(events);122          } else if (api.events.system.ExtrinsicFailed.is(event)) {123            const {data: [error]} = event;124            if (error.isModule) {125              const decoded = api.registry.findMetaError(error.asModule);126              const {method, section} = decoded;127              rej(new Error(`${section}.${method}`));128            } else {129              rej(new Error(error.toString()));130            }131          }132        }133      });134    } catch (e) {135      rej(e);136    }137  });138}139140export function141submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {142  /* eslint no-async-promise-executor: "off" */143  return new Promise(async (resolve, reject) => {144    try {145      await transaction.signAndSend(sender, ({events = [], status}) => {146        const transactionStatus = getTransactionStatus(events, status);147148        if (transactionStatus === TransactionStatus.Success) {149          resolve(events);150        } else if (transactionStatus === TransactionStatus.Fail) {151          console.log(`Something went wrong with transaction. Status: ${status}`);152          reject(events);153        }154      });155    } catch (e) {156      console.log('Error: ', e);157      reject(e);158    }159  });160}161162export function submitTransactionExpectFailAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {163  console.error = () => {};164  console.log = () => {};165166  /* eslint no-async-promise-executor: "off" */167  return new Promise<EventRecord[]>(async function(res, rej) {168    const resolve = (rec: EventRecord[]) => {169      setTimeout(() => {170        res(rec);171      });172    };173    const reject = (errror: any) => {174      setTimeout(() => {175        rej(errror);176      });177    };178    try {179      await transaction.signAndSend(sender, ({events = [], status}) => {180        const transactionStatus = getTransactionStatus(events, status);181182        // console.log('transactionStatus', transactionStatus, 'events', events);183184        if (transactionStatus === TransactionStatus.Success) {185          resolve(events);186        } else if (transactionStatus === TransactionStatus.Fail) {187          reject(events);188        }189      });190    } catch (e) {191      reject(e);192    }193  });194}