1234567891011121314151617import '../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 54 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 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 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 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}