123456import { WsProvider, ApiPromise } from '@polkadot/api';7import { EventRecord } from '@polkadot/types/interfaces/system/types';8import { ExtrinsicStatus } from '@polkadot/types/interfaces/author/types';9import { IKeyringPair } from '@polkadot/types/types';1011import config from '../config';12import promisifySubstrate from './promisify-substrate';13import { ApiOptions, SubmittableExtrinsic, ApiTypes } from '@polkadot/api/types';1415function defaultApiOptions(): ApiOptions {16 const wsProvider = new WsProvider(config.substrateUrl);17 return {18 provider: wsProvider, signedExtensions: {19 ContractHelpers: {20 extrinsic: {},21 payload: {},22 },23 },24 };25}2627export default async function usingApi<T = void>(action: (api: ApiPromise) => Promise<T>, settings: ApiOptions | undefined = undefined): Promise<T> {28 settings = settings || defaultApiOptions();29 const api: ApiPromise = new ApiPromise(settings);30 let result: T = null as unknown as T;3132 33 34 const consoleErr = console.error;35 const consoleLog = console.log;36 const consoleWarn = console.warn;3738 const outFn = (message: string) => {39 if (typeof message !== 'string') {40 consoleErr(message);41 return;42 }43 if (!message.includes('StorageChangeSet:: WebSocket is not connected') &&44 !message.includes('2021-') &&45 !message.includes('StorageChangeSet:: Normal connection closure'))46 consoleErr(message);47 };4849 console.error = outFn;50 console.log = outFn;51 console.warn = outFn;5253 try {54 await promisifySubstrate(api, async () => {55 if (api) {56 await api.isReadyOrError;57 result = await action(api);58 }59 })();60 } finally {61 await api.disconnect();62 console.error = consoleErr;63 console.log = consoleLog;64 console.warn = consoleWarn;65 }66 return result as T;67}6869enum TransactionStatus {70 Success,71 Fail,72 NotReady73}7475function getTransactionStatus(events: EventRecord[], status: ExtrinsicStatus): TransactionStatus {76 if (status.isReady) {77 return TransactionStatus.NotReady;78 }79 if (status.isBroadcast) {80 return TransactionStatus.NotReady;81 }82 if (status.isInBlock || status.isFinalized) {83 if(events.filter(e => e.event.data.method === 'ExtrinsicFailed').length > 0) {84 return TransactionStatus.Fail;85 }86 if(events.filter(e => e.event.data.method === 'ExtrinsicSuccess').length > 0) {87 return TransactionStatus.Success;88 }89 }9091 return TransactionStatus.Fail;92}9394export function95submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {96 97 return new Promise(async (resolve, reject) => {98 try {99 await transaction.signAndSend(sender, ({ events = [], status }) => {100 const transactionStatus = getTransactionStatus(events, status);101102 if (transactionStatus === TransactionStatus.Success) {103 resolve(events);104 } else if (transactionStatus === TransactionStatus.Fail) {105 console.log(`Something went wrong with transaction. Status: ${status}`);106 reject(events);107 }108 });109 } catch (e) {110 console.log('Error: ', e);111 reject(e);112 }113 });114}115116export function submitTransactionExpectFailAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {117 const consoleError = console.error;118 const consoleLog = console.log;119 console.error = () => {};120 console.log = () => {};121122 123 return new Promise<EventRecord[]>(async function(res, rej) {124 const resolve = (rec: EventRecord[]) => {125 setTimeout(() => {126 res(rec);127 console.error = consoleError;128 console.log = consoleLog;129 });130 };131 const reject = (errror: any) => {132 setTimeout(() => {133 rej(errror);134 console.error = consoleError;135 console.log = consoleLog;136 });137 };138 try {139 await transaction.signAndSend(sender, ({ events = [], status }) => {140 const transactionStatus = getTransactionStatus(events, status);141142 143144 if (transactionStatus === TransactionStatus.Success) {145 resolve(events);146 } else if (transactionStatus === TransactionStatus.Fail) {147 reject(events);148 }149 });150 } catch (e) {151 reject(e);152 }153 });154}