123456import '../interfaces/augment-api-events';7import {WsProvider, ApiPromise} from '@polkadot/api';8import {EventRecord} from '@polkadot/types/interfaces/system/types';9import {ExtrinsicStatus} from '@polkadot/types/interfaces/author/types';10import {IKeyringPair} from '@polkadot/types/types';1112import config from '../config';13import promisifySubstrate from './promisify-substrate';14import {ApiOptions, SubmittableExtrinsic, ApiTypes} from '@polkadot/api/types';15import * as defs from '../interfaces/definitions';161718function defaultApiOptions(): ApiOptions {19 const wsProvider = new WsProvider(config.substrateUrl);20 return {21 provider: wsProvider, signedExtensions: {22 ContractHelpers: {23 extrinsic: {},24 payload: {},25 },26 },27 rpc: {28 unique: defs.unique.rpc,29 },30 };31}3233export default async function usingApi<T = void>(action: (api: ApiPromise) => Promise<T>, settings: ApiOptions | undefined = undefined): Promise<T> {34 settings = settings || defaultApiOptions();35 const api: ApiPromise = new ApiPromise(settings);36 let result: T = null as unknown as T;3738 39 40 const consoleErr = console.error;41 const consoleLog = console.log;42 const consoleWarn = console.warn;4344 const outFn = (printer: any) => (...args: any[]) => {45 for (const arg of args) {46 if (typeof arg !== 'string')47 continue;48 if (arg.includes('1000:: Normal connection closure' || arg === 'Normal connection closure'))49 return;50 }51 printer(...args);52 };5354 console.error = outFn(consoleErr.bind(console));55 console.log = outFn(consoleLog.bind(console));56 console.warn = outFn(consoleWarn.bind(console));5758 try {59 await promisifySubstrate(api, async () => {60 if (api) {61 await api.isReadyOrError;62 result = await action(api);63 }64 })();65 } finally {66 await api.disconnect();67 console.error = consoleErr;68 console.log = consoleLog;69 console.warn = consoleWarn;70 }71 return result as T;72}7374enum TransactionStatus {75 Success,76 Fail,77 NotReady78}7980function getTransactionStatus(events: EventRecord[], status: ExtrinsicStatus): TransactionStatus {81 if (status.isReady) {82 return TransactionStatus.NotReady;83 }84 if (status.isBroadcast) {85 return TransactionStatus.NotReady;86 }87 if (status.isInBlock || status.isFinalized) {88 if(events.filter(e => e.event.data.method === 'ExtrinsicFailed').length > 0) {89 return TransactionStatus.Fail;90 }91 if(events.filter(e => e.event.data.method === 'ExtrinsicSuccess').length > 0) {92 return TransactionStatus.Success;93 }94 }9596 return TransactionStatus.Fail;97}9899export function executeTransaction(api: ApiPromise, sender: IKeyringPair, transaction: SubmittableExtrinsic<'promise'>): Promise<EventRecord[]> {100 return new Promise(async (res, rej) => {101 try {102 await transaction.signAndSend(sender, ({events, status}) => {103 if (!status.isInBlock && !status.isFinalized) return;104 for (const {event} of events) {105 if (api.events.system.ExtrinsicSuccess.is(event)) {106 res(events);107 } else if (api.events.system.ExtrinsicFailed.is(event)) {108 const {data: [error]} = event;109 if (error.isModule) {110 const decoded = api.registry.findMetaError(error.asModule);111 const {method, section} = decoded;112 rej(new Error(`${section}.${method}`));113 } else {114 rej(new Error(error.toString()));115 }116 }117 }118 });119 } catch (e) {120 rej(e);121 }122 });123}124125export function126submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {127 128 return new Promise(async (resolve, reject) => {129 try {130 await transaction.signAndSend(sender, ({events = [], status}) => {131 const transactionStatus = getTransactionStatus(events, status);132133 if (transactionStatus === TransactionStatus.Success) {134 resolve(events);135 } else if (transactionStatus === TransactionStatus.Fail) {136 console.log(`Something went wrong with transaction. Status: ${status}`);137 reject(events);138 }139 });140 } catch (e) {141 console.log('Error: ', e);142 reject(e);143 }144 });145}146147export function submitTransactionExpectFailAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {148 console.error = () => {};149 console.log = () => {};150151 152 return new Promise<EventRecord[]>(async function(res, rej) {153 const resolve = (rec: EventRecord[]) => {154 setTimeout(() => {155 res(rec);156 });157 };158 const reject = (errror: any) => {159 setTimeout(() => {160 rej(errror);161 });162 };163 try {164 await transaction.signAndSend(sender, ({events = [], status}) => {165 const transactionStatus = getTransactionStatus(events, status);166167 168169 if (transactionStatus === TransactionStatus.Success) {170 resolve(events);171 } else if (transactionStatus === TransactionStatus.Fail) {172 reject(events);173 }174 });175 } catch (e) {176 reject(e);177 }178 });179}