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 },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 50 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 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 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 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}