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 eth: {45 feeHistory: {46 description: 'Dummy',47 params: [],48 type: 'u8',49 },50 maxPriorityFeePerGas: {51 description: 'Dummy',52 params: [],53 type: 'u8',54 },55 },56 },57 };58}5960export default async function usingApi<T = void>(action: (api: ApiPromise) => Promise<T>, settings: ApiOptions | undefined = undefined): Promise<T> {61 settings = settings || defaultApiOptions();62 const api: ApiPromise = new ApiPromise(settings);63 let result: T = null as unknown as T;6465 66 67 const consoleErr = console.error;68 const consoleLog = console.log;69 const consoleWarn = console.warn;7071 const outFn = (printer: any) => (...args: any[]) => {72 for (const arg of args) {73 if (typeof arg !== 'string')74 continue;75 if (arg.includes('1000:: Normal connection closure' || arg === 'Normal connection closure'))76 return;77 }78 printer(...args);79 };8081 console.error = outFn(consoleErr.bind(console));82 console.log = outFn(consoleLog.bind(console));83 console.warn = outFn(consoleWarn.bind(console));8485 try {86 await promisifySubstrate(api, async () => {87 if (api) {88 await api.isReadyOrError;89 result = await action(api);90 }91 })();92 } finally {93 await api.disconnect();94 console.error = consoleErr;95 console.log = consoleLog;96 console.warn = consoleWarn;97 }98 return result as T;99}100101enum TransactionStatus {102 Success,103 Fail,104 NotReady105}106107function getTransactionStatus(events: EventRecord[], status: ExtrinsicStatus): TransactionStatus {108 if (status.isReady) {109 return TransactionStatus.NotReady;110 }111 if (status.isBroadcast) {112 return TransactionStatus.NotReady;113 }114 if (status.isInBlock || status.isFinalized) {115 if(events.filter(e => e.event.data.method === 'ExtrinsicFailed').length > 0) {116 return TransactionStatus.Fail;117 }118 if(events.filter(e => e.event.data.method === 'ExtrinsicSuccess').length > 0) {119 return TransactionStatus.Success;120 }121 }122123 return TransactionStatus.Fail;124}125126export function executeTransaction(api: ApiPromise, sender: IKeyringPair, transaction: SubmittableExtrinsic<'promise'>): Promise<EventRecord[]> {127 return new Promise(async (res, rej) => {128 try {129 await transaction.signAndSend(sender, ({events, status}) => {130 if (!status.isInBlock && !status.isFinalized) return;131 for (const {event} of events) {132 if (api.events.system.ExtrinsicSuccess.is(event)) {133 res(events);134 } else if (api.events.system.ExtrinsicFailed.is(event)) {135 const {data: [error]} = event;136 if (error.isModule) {137 const decoded = api.registry.findMetaError(error.asModule);138 const {method, section} = decoded;139 rej(new Error(`${section}.${method}`));140 } else {141 rej(new Error(error.toString()));142 }143 }144 }145 });146 } catch (e) {147 rej(e);148 }149 });150}151152export function153submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {154 155 return new Promise(async (resolve, reject) => {156 try {157 await transaction.signAndSend(sender, ({events = [], status}) => {158 const transactionStatus = getTransactionStatus(events, status);159160 if (transactionStatus === TransactionStatus.Success) {161 resolve(events);162 } else if (transactionStatus === TransactionStatus.Fail) {163 console.log(`Something went wrong with transaction. Status: ${status}`);164 reject(events);165 }166 });167 } catch (e) {168 console.log('Error: ', e);169 reject(e);170 }171 });172}173174export function submitTransactionExpectFailAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {175 console.error = () => {};176 console.log = () => {};177178 179 return new Promise<EventRecord[]>(async function(res, rej) {180 const resolve = (rec: EventRecord[]) => {181 setTimeout(() => {182 res(rec);183 });184 };185 const reject = (errror: any) => {186 setTimeout(() => {187 rej(errror);188 });189 };190 try {191 await transaction.signAndSend(sender, ({events = [], status}) => {192 const transactionStatus = getTransactionStatus(events, status);193194 195196 if (transactionStatus === TransactionStatus.Success) {197 resolve(events);198 } else if (transactionStatus === TransactionStatus.Fail) {199 reject(events);200 }201 });202 } catch (e) {203 reject(e);204 }205 });206}