diff --git a/packages/bitcore-node/src/providers/chain-state/evm/api/ecsp.ts b/packages/bitcore-node/src/providers/chain-state/evm/api/ecsp.ts index 3e68250d943..403f7e88c65 100644 --- a/packages/bitcore-node/src/providers/chain-state/evm/api/ecsp.ts +++ b/packages/bitcore-node/src/providers/chain-state/evm/api/ecsp.ts @@ -208,7 +208,10 @@ export class BaseEVMExternalStateProvider extends InternalStateProvider implemen }).bind(this); const txStream = new NodeQueryStream(block?.transactions || [], getTransaction, args); // stream results into response - await NodeQueryStream.onStream(txStream, req!, res!); + const result = await NodeQueryStream.onStream(txStream, req!, res!); + if (result?.success === false) { + logger.error('Error mid-stream (streamTransactions): %o', result.error); + } } catch (err) { logger.error('Error streaming transactions from historical node %o', err); throw err; @@ -220,14 +223,18 @@ export class BaseEVMExternalStateProvider extends InternalStateProvider implemen const { tokenAddress } = args; try { // Calculate confirmations with tip height + let result; const tip = await this.getLocalTip(params); args.tipHeight = tip ? tip.height : 0; if (!args.tokenAddress) { const txStream = MoralisAPI.streamTransactionsByAddress({ chain, network, address, args }); - await ExternalApiStream.onStream(txStream, req!, res!); + result = await ExternalApiStream.onStream(txStream, req!, res!); } else { const tokenTransfers = MoralisAPI.streamERC20TransactionsByAddress({ chain, network, address, tokenAddress, args }); - await ExternalApiStream.onStream(tokenTransfers, req!, res!); + result = await ExternalApiStream.onStream(tokenTransfers, req!, res!); + } + if (result?.success === false) { + logger.error('Error mid-stream (streamAddressTransactions): %o', result.error); } } catch (err) { logger.error('Error streaming address transactions from external provider: %o', err); @@ -258,7 +265,10 @@ export class BaseEVMExternalStateProvider extends InternalStateProvider implemen // Pipe all txStreams to the mergedStream ExternalApiStream.mergeStreams(txStreams, mergedStream); // Ensure mergeStream resolves - await _mergedStream; + const result = await _mergedStream; + if (result?.success === false) { + logger.error('Error mid-stream (streamWalletTransactions): %o', result.error); + } } catch (err) { logger.error('Error streaming wallet transactions from external provider: %o', err); throw err; diff --git a/packages/bitcore-node/src/providers/chain-state/evm/models/transaction.ts b/packages/bitcore-node/src/providers/chain-state/evm/models/transaction.ts index c75e29a5c35..75172f44c48 100644 --- a/packages/bitcore-node/src/providers/chain-state/evm/models/transaction.ts +++ b/packages/bitcore-node/src/providers/chain-state/evm/models/transaction.ts @@ -159,8 +159,8 @@ export class EVMTransactionModel extends BaseTransaction { } } - getAllTouchedAddresses(tx: Partial): { tos: IEVMCachedAddress[], froms: IEVMCachedAddress[] } { - const {to, from, effects} = tx; + getAllTouchedAddresses(tx: Partial): { tos: IEVMCachedAddress[], froms: IEVMCachedAddress[] } { + const { to, from, effects } = tx; let toBatch = new Set(); let fromBatch = new Set(); const addToBatch = (batch: Set, obj: IEVMCachedAddress) => { @@ -179,7 +179,7 @@ export class EVMTransactionModel extends BaseTransaction { // Handle ERC20s addToBatch(toBatch, { address: effect.to, tokenAddress: effect.contractAddress }); addToBatch(fromBatch, { address: effect.from, tokenAddress: effect.contractAddress }); - } + } } } @@ -254,7 +254,7 @@ export class EVMTransactionModel extends BaseTransaction { walletsAddys.map(w => w.wallet), w => w.toHexString() ); - + // If config value is set then only store needed tx properties let leanTx: IEVMTransaction | IEVMTransactionInProcess = tx; if ((Config.chainConfig({ chain, network }) as IEVMNetworkConfig).leanTransactionStorage) { @@ -325,7 +325,7 @@ export class EVMTransactionModel extends BaseTransaction { ...erc20Data }; } - } catch (e) {} + } catch (e) { } try { const erc721Data: IAbiDecodeResponse = getErc721Decoder().decodeMethod(input); if (erc721Data) { @@ -334,7 +334,7 @@ export class EVMTransactionModel extends BaseTransaction { ...erc721Data }; } - } catch (e) {} + } catch (e) { } try { const invoiceData: IAbiDecodeResponse = getInvoiceDecoder().decodeMethod(input); if (invoiceData) { @@ -343,7 +343,7 @@ export class EVMTransactionModel extends BaseTransaction { ...invoiceData }; } - } catch (e) {} + } catch (e) { } try { const multisendData: IAbiDecodeResponse = getMultisendDecoder().decodeMethod(input); if (multisendData) { @@ -352,7 +352,7 @@ export class EVMTransactionModel extends BaseTransaction { ...multisendData }; } - } catch (e) {} + } catch (e) { } try { const multisigData: IAbiDecodeResponse = getMultisigDecoder().decodeMethod(input); if (multisigData) { @@ -361,10 +361,10 @@ export class EVMTransactionModel extends BaseTransaction { ...multisigData }; } - } catch (e) {} + } catch (e) { } return undefined; } - + /** * Creates an object with param names as keys instead of an array of objects * @param abi @@ -530,7 +530,7 @@ export class EVMTransactionModel extends BaseTransaction { tx: IEVMTransactionInProcess | Partial>, options?: TransformOptions ): EVMTransactionJSON | string { - + let transaction: EVMTransactionJSON = { txid: tx.txid || '', network: tx.network || '', @@ -548,7 +548,7 @@ export class EVMTransactionModel extends BaseTransaction { from: tx.from || '', effects: tx.effects || [] }; - + // Add non-lean properties if we aren't excluding them const config = (Config.chainConfig({ chain: tx.chain as string, network: tx.network as string }) as IEVMNetworkConfig); if (config && !config.leanTransactionStorage) { @@ -558,7 +558,7 @@ export class EVMTransactionModel extends BaseTransaction { data: dataStr, abiType: tx.abiType || valueOrDefault(decodedData, undefined), internal: tx.internal - ? tx.internal.map(t => ({ ...t, decodedData: this.abiDecode(t.action.input || '0x') })) + ? tx.internal.map(t => ({ ...t, decodedData: this.abiDecode(t?.action?.input || '0x') })) : [], calls: tx.calls ? tx.calls.map(t => ({ ...t, decodedData: this.abiDecode(t.input || '0x') })) : [] }; diff --git a/packages/bitcore-node/src/providers/chain-state/external/providers/moralis.ts b/packages/bitcore-node/src/providers/chain-state/external/providers/moralis.ts index d5b66d51a05..12e862c9f7e 100644 --- a/packages/bitcore-node/src/providers/chain-state/external/providers/moralis.ts +++ b/packages/bitcore-node/src/providers/chain-state/external/providers/moralis.ts @@ -2,6 +2,7 @@ import request = require('request'); import config from '../../../../config'; import { isDateValid } from '../../../../utils/check'; import { EVMTransactionStorage } from '../../evm/models/transaction'; +import { ErigonTraceResponse } from '../../evm/p2p/rpcs/erigonRpc'; import { EVMTransactionJSON, Transaction } from '../../evm/types'; import moralisChains from '../defaults'; import { ExternalApiStream as apiStream } from '../streams/apiStream'; @@ -151,11 +152,36 @@ const transformTransaction = (tx) => { to: tx.to_address, from: tx.from_address, data: tx.input, - internal: tx.internal_transactions, + internal: tx?.internal_transactions.map(t => transformInternalTransaction(t)), effects: tx.effects, }; } +const transformInternalTransaction = (tx) => { + return { + action: { + callType: tx.type?.toLowerCase(), + from: tx.from, + gas: tx.gas, + input: tx.input, + to: tx.to, + value: tx.value, + }, + blockHash: tx.block_hash, + blockNumber: Number(tx.block_number), + error: tx.error, + result: { + gasUsed: tx.gas_used, + output: tx.output + }, + subtraces: tx.subtraces, + traceAddress: tx.traceAddress || [], + transactionHash: tx.transaction_hash, + transactionPosition: tx.transactionPosition || 0, + type: tx.type?.toLowerCase() + } as ErigonTraceResponse; +} + const transformTokenTransfer = (transfer) => { let _transfer = transformTransaction(transfer); return { diff --git a/packages/bitcore-node/src/providers/chain-state/external/streams/apiStream.ts b/packages/bitcore-node/src/providers/chain-state/external/streams/apiStream.ts index d59b642ee7b..9b80646ebd5 100644 --- a/packages/bitcore-node/src/providers/chain-state/external/streams/apiStream.ts +++ b/packages/bitcore-node/src/providers/chain-state/external/streams/apiStream.ts @@ -71,8 +71,9 @@ export class ExternalApiStream extends Readable { } // handles events emitted by the streamed response, request from client, and response to client - static onStream(stream: Readable, req: Request, res: Response): Promise { - return new Promise((resolve, reject) => { + static onStream(stream: Readable, req: Request, res: Response): + Promise<{ success: boolean, error?: any }> { + return new Promise<{ success: boolean, error?: any }>((resolve, reject) => { let closed = false; let isFirst = true; @@ -88,7 +89,14 @@ export class ExternalApiStream extends Readable { stream.on('error', function (err) { if (!closed) { closed = true; - return reject(err); + if (!isFirst) { + res.write(',\n{"error": "An error occurred during data stream"}\n]'); + res.end(); + res.destroy(); + return resolve({ success: false, error: err }); + } else { + return reject(err); + } } return; }); @@ -115,7 +123,7 @@ export class ExternalApiStream extends Readable { closed = true; } res.end(); - resolve(true); + resolve({ success: true }); } }); }); diff --git a/packages/bitcore-node/src/providers/chain-state/external/streams/nodeStream.ts b/packages/bitcore-node/src/providers/chain-state/external/streams/nodeStream.ts index f2240bfbdea..8d374c8af0d 100644 --- a/packages/bitcore-node/src/providers/chain-state/external/streams/nodeStream.ts +++ b/packages/bitcore-node/src/providers/chain-state/external/streams/nodeStream.ts @@ -37,7 +37,8 @@ export class NodeQueryStream extends Readable { } } - static onStream(stream: Readable, req: Request, res: Response): Promise { + static onStream(stream: Readable, req: Request, res: Response): + Promise<{ success: boolean, error?: any }> { return ExternalApiStream.onStream(stream, req, res); } diff --git a/packages/bitcore-wallet-service/src/lib/model/copayer.ts b/packages/bitcore-wallet-service/src/lib/model/copayer.ts index 34403f2ad23..f144fc65f7c 100644 --- a/packages/bitcore-wallet-service/src/lib/model/copayer.ts +++ b/packages/bitcore-wallet-service/src/lib/model/copayer.ts @@ -63,7 +63,7 @@ export class Copayer { const x = new Copayer(); x.version = 2; - x.createdOn = Math.floor(Date.now() / 1000); + x.createdOn = Math.floor(Date.now() / 1000); x.coin = opts.coin; x.chain = opts.chain || opts.coin; x.xPubKey = opts.xPubKey;