/** * Component: TransactionsReceipt * Author: Nearblocks Pte Ltd * License: Business Source License 1.1 * Description: Details of Transaction Receipt on Near Protocol. * @interface Props * @param {string} [network] - The network data to show, either mainnet or testnet * @param {Function} [t] - A function for internationalization (i18n) provided by the next-translate package. * @param {TransactionInfo} [txn] - Information related to a transaction. * @param {RPCTransactionInfo} [rpcTxn] - RPC data of the transaction. */ /* INCLUDE: "includes/libs.jsx" */ function getConfig(network) { switch (network) { case 'mainnet': return { ownerId: 'nearblocks.near', nodeUrl: 'https://rpc.mainnet.near.org', backendUrl: 'https://api3.nearblocks.io/v1/', rpcUrl: 'https://archival-rpc.testnet.near.org', appUrl: 'https://nearblocks.io/', }; case 'testnet': return { ownerId: 'nearblocks.testnet', nodeUrl: 'https://rpc.testnet.near.org', backendUrl: 'https://api3-testnet.nearblocks.io/v1/', rpcUrl: 'https://archival-rpc.testnet.near.org', appUrl: 'https://testnet.nearblocks.io/', }; default: return {}; } } function debounce( delay, func, ) { let timer; let active = true; const debounced = (arg) => { if (active) { clearTimeout(timer); timer = setTimeout(() => { active && func(arg); timer = undefined; }, delay); } else { func(arg); } }; debounced.isPending = () => { return timer !== undefined; }; debounced.cancel = () => { active = false; }; debounced.flush = (arg) => func(arg); return debounced; } function timeAgo(unixTimestamp) { const currentTimestamp = Math.floor(Date.now() / 1000); const secondsAgo = currentTimestamp - unixTimestamp; if (secondsAgo < 5) { return 'Just now'; } else if (secondsAgo < 60) { return `${secondsAgo} seconds ago`; } else if (secondsAgo < 3600) { const minutesAgo = Math.floor(secondsAgo / 60); return `${minutesAgo} minute${minutesAgo > 1 ? 's' : ''} ago`; } else if (secondsAgo < 86400) { const hoursAgo = Math.floor(secondsAgo / 3600); return `${hoursAgo} hour${hoursAgo > 1 ? 's' : ''} ago`; } else { const daysAgo = Math.floor(secondsAgo / 86400); return `${daysAgo} day${daysAgo > 1 ? 's' : ''} ago`; } } function shortenAddress(address) { const string = String(address); if (string.length <= 20) return string; return `${string.substr(0, 10)}...${string.substr(-7)}`; } function urlHostName(url) { try { const domain = new URL(url); return domain?.hostname ?? null; } catch (e) { return null; } } function holderPercentage(supply, quantity) { return Math.min(Big(quantity).div(Big(supply)).mul(Big(100)).toFixed(2), 100); } function isAction(type) { const actions = [ 'DEPLOY_CONTRACT', 'TRANSFER', 'STAKE', 'ADD_KEY', 'DELETE_KEY', 'DELETE_ACCOUNT', ]; return actions.includes(type.toUpperCase()); } function localFormat(number) { const bigNumber = Big(number); const formattedNumber = bigNumber .toFixed(5) .replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); // Add commas before the decimal point return formattedNumber.replace(/\.?0*$/, ''); // Remove trailing zeros and the dot } function formatWithCommas(number) { return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); } /* END_INCLUDE: "includes/libs.jsx" */ /* INCLUDE: "includes/near.jsx" */ function mapRpcActionToAction(action) { if (action === 'CreateAccount') { return { action_kind: 'CreateAccount', args: {}, }; } if (typeof action === 'object') { const kind = Object.keys(action)[0]; return { action_kind: kind, args: action[kind], }; } return null; } function valueFromObj(obj) { const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { const key = keys[i]; const value = obj[key]; if (typeof value === 'string') { return value; } if (typeof value === 'object') { const nestedValue = valueFromObj(value ); if (nestedValue) { return nestedValue; } } } return undefined; } function txnLogs(txn) { let txLogs = []; const outcomes = txn?.receipts_outcome || []; for (let i = 0; i < outcomes.length; i++) { const outcome = outcomes[i]; let logs = outcome?.outcome?.logs || []; if (logs.length > 0) { const mappedLogs = logs.map((log) => ({ contract: outcome?.outcome?.executor_id || '', logs: log, })); txLogs = [...txLogs, ...mappedLogs]; } } return txLogs; } function txnActions(txn) { const txActions = []; const receipts = txn?.receipts || []; for (let i = 0; i < receipts.length; i++) { const receipt = receipts[i]; const from = receipt?.predecessor_id; const to = receipt?.receiver_id; if (Array.isArray(receipt?.receipt)) { const actions = receipt.receipt; for (let j = 0; j < actions.length; j++) { const action = actions[j]; txActions.push({ from, to, ...action }); } } else { const actions = receipt?.receipt?.Action?.actions || []; for (let j = 0; j < actions.length; j++) { const action = mapRpcActionToAction(actions[j]); txActions.push({ from, to, ...action }); } } } return txActions.filter( (action) => action.action_kind !== 'FunctionCall' && action.from !== 'system', ); } function txnErrorMessage(txn) { const kind = txn?.status?.Failure?.ActionError?.kind; if (typeof kind === 'string') return kind; if (typeof kind === 'object') { return valueFromObj(kind); } return null; } function formatLine(line, offset, format) { let result = `${offset.toString(16).padStart(8, '0')} `; const hexValues = line.match(/[0-9a-fA-F]{2}/g) || []; hexValues.forEach((byte, index) => { if (index > 0 && index % 4 === 0) { result += ' '; } result += byte.toUpperCase().padEnd(2, ' ') + ' '; }); if (format === 'twos') { result = result.replace(/(.{4})/g, '$1 '); } else if (format === 'default') { result += ` ${String.fromCharCode( ...hexValues.map((b) => parseInt(b, 16)), )}`; } return result.trimEnd(); } function collectNestedReceiptWithOutcomeOld( idOrHash, parsedMap, ) { const parsedElement = parsedMap.get(idOrHash); if (!parsedElement) { return { id: idOrHash }; } const { receiptIds, ...restOutcome } = parsedElement.outcome; return { ...parsedElement, outcome: { ...restOutcome, nestedReceipts: receiptIds.map((id) => collectNestedReceiptWithOutcomeOld(id, parsedMap), ), }, }; } function parseReceipt( receipt, outcome, transaction, ) { if (!receipt) { return { id: outcome.id, predecessorId: transaction.signer_id, receiverId: transaction.receiver_id, actions: transaction.actions.map(mapRpcActionToAction1), }; } return { id: receipt.receipt_id, predecessorId: receipt.predecessor_id, receiverId: receipt.receiver_id, actions: 'Action' in receipt.receipt ? receipt.receipt.Action.actions.map(mapRpcActionToAction1) : [], }; } function mapNonDelegateRpcActionToAction( rpcAction, ) { if (rpcAction === 'CreateAccount') { return { kind: 'createAccount', args: {}, }; } if ('DeployContract' in rpcAction) { return { kind: 'deployContract', args: rpcAction.DeployContract, }; } if ('FunctionCall' in rpcAction) { return { kind: 'functionCall', args: { methodName: rpcAction.FunctionCall.method_name, args: rpcAction.FunctionCall.args, deposit: rpcAction.FunctionCall.deposit, gas: rpcAction.FunctionCall.gas, }, }; } if ('Transfer' in rpcAction) { return { kind: 'transfer', args: rpcAction.Transfer, }; } if ('Stake' in rpcAction) { return { kind: 'stake', args: { publicKey: rpcAction.Stake.public_key, stake: rpcAction.Stake.stake, }, }; } if ('AddKey' in rpcAction) { return { kind: 'addKey', args: { publicKey: rpcAction.AddKey.public_key, accessKey: { nonce: rpcAction.AddKey.access_key.nonce, permission: rpcAction.AddKey.access_key.permission === 'FullAccess' ? { type: 'fullAccess', } : { type: 'functionCall', contractId: rpcAction.AddKey.access_key.permission.FunctionCall .receiver_id, methodNames: rpcAction.AddKey.access_key.permission.FunctionCall .method_names, }, }, }, }; } if ('DeleteKey' in rpcAction) { return { kind: 'deleteKey', args: { publicKey: rpcAction.DeleteKey.public_key, }, }; } return { kind: 'deleteAccount', args: { beneficiaryId: rpcAction.DeleteAccount.beneficiary_id, }, }; } function mapRpcInvalidAccessKeyError(error) { const UNKNOWN_ERROR = { type: 'unknown' }; if (error === 'DepositWithFunctionCall') { return { type: 'depositWithFunctionCall', }; } if (error === 'RequiresFullAccess') { return { type: 'requiresFullAccess', }; } if ('AccessKeyNotFound' in error) { const { account_id, public_key } = error.AccessKeyNotFound; return { type: 'accessKeyNotFound', accountId: account_id, publicKey: public_key, }; } if ('ReceiverMismatch' in error) { const { ak_receiver, tx_receiver } = error.ReceiverMismatch; return { type: 'receiverMismatch', akReceiver: ak_receiver, transactionReceiver: tx_receiver, }; } if ('MethodNameMismatch' in error) { const { method_name } = error.MethodNameMismatch; return { type: 'methodNameMismatch', methodName: method_name, }; } if ('NotEnoughAllowance' in error) { const { account_id, allowance, cost, public_key } = error.NotEnoughAllowance; return { type: 'notEnoughAllowance', accountId: account_id, allowance: allowance, cost: cost, publicKey: public_key, }; } return UNKNOWN_ERROR; } function mapRpcCompilationError(error) { const UNKNOWN_ERROR = { type: 'unknown' }; if ('CodeDoesNotExist' in error) { return { type: 'codeDoesNotExist', accountId: error.CodeDoesNotExist.account_id, }; } if ('PrepareError' in error) { return { type: 'prepareError', }; } if ('WasmerCompileError' in error) { return { type: 'wasmerCompileError', msg: error.WasmerCompileError.msg, }; } if ('UnsupportedCompiler' in error) { return { type: 'unsupportedCompiler', msg: error.UnsupportedCompiler.msg, }; } return UNKNOWN_ERROR; } function mapRpcFunctionCallError(error) { const UNKNOWN_ERROR = { type: 'unknown' }; if ('CompilationError' in error) { return { type: 'compilationError', error: mapRpcCompilationError(error.CompilationError), }; } if ('LinkError' in error) { return { type: 'linkError', msg: error.LinkError.msg, }; } if ('MethodResolveError' in error) { return { type: 'methodResolveError', }; } if ('WasmTrap' in error) { return { type: 'wasmTrap', }; } if ('WasmUnknownError' in error) { return { type: 'wasmUnknownError', }; } if ('HostError' in error) { return { type: 'hostError', }; } if ('_EVMError' in error) { return { type: 'evmError', }; } if ('ExecutionError' in error) { return { type: 'executionError', error: error.ExecutionError, }; } return UNKNOWN_ERROR; } function mapRpcNewReceiptValidationError( error, ) { const UNKNOWN_ERROR = { type: 'unknown' }; if ('InvalidPredecessorId' in error) { return { type: 'invalidPredecessorId', accountId: error.InvalidPredecessorId.account_id, }; } if ('InvalidReceiverId' in error) { return { type: 'invalidReceiverId', accountId: error.InvalidReceiverId.account_id, }; } if ('InvalidSignerId' in error) { return { type: 'invalidSignerId', accountId: error.InvalidSignerId.account_id, }; } if ('InvalidDataReceiverId' in error) { return { type: 'invalidDataReceiverId', accountId: error.InvalidDataReceiverId.account_id, }; } if ('ReturnedValueLengthExceeded' in error) { return { type: 'returnedValueLengthExceeded', length: error.ReturnedValueLengthExceeded.length, limit: error.ReturnedValueLengthExceeded.limit, }; } if ('NumberInputDataDependenciesExceeded' in error) { return { type: 'numberInputDataDependenciesExceeded', numberOfInputDataDependencies: error.NumberInputDataDependenciesExceeded .number_of_input_data_dependencies, limit: error.NumberInputDataDependenciesExceeded.limit, }; } if ('ActionsValidation' in error) { return { type: 'actionsValidation', }; } return UNKNOWN_ERROR; } function mapRpcReceiptActionError(error) { const UNKNOWN_ERROR = { type: 'unknown' }; const { kind } = error; if (kind === 'DelegateActionExpired') { return { type: 'delegateActionExpired', }; } if (kind === 'DelegateActionInvalidSignature') { return { type: 'delegateActionInvalidSignature', }; } if ('DelegateActionSenderDoesNotMatchTxReceiver' in kind) { return { type: 'delegateActionSenderDoesNotMatchTxReceiver', receiverId: kind.DelegateActionSenderDoesNotMatchTxReceiver.receiver_id, senderId: kind.DelegateActionSenderDoesNotMatchTxReceiver.sender_id, }; } if ('DelegateActionAccessKeyError' in kind) { return { type: 'delegateActionAccessKeyError', error: mapRpcInvalidAccessKeyError(kind.DelegateActionAccessKeyError), }; } if ('DelegateActionInvalidNonce' in kind) { return { type: 'delegateActionInvalidNonce', akNonce: kind.DelegateActionInvalidNonce.ak_nonce, delegateNonce: kind.DelegateActionInvalidNonce.delegate_nonce, }; } if ('DelegateActionNonceTooLarge' in kind) { return { type: 'delegateActionNonceTooLarge', delegateNonce: kind.DelegateActionNonceTooLarge.delegate_nonce, upperBound: kind.DelegateActionNonceTooLarge.upper_bound, }; } if ('AccountAlreadyExists' in kind) { return { type: 'accountAlreadyExists', accountId: kind.AccountAlreadyExists.account_id, }; } if ('AccountDoesNotExist' in kind) { return { type: 'accountDoesNotExist', accountId: kind.AccountDoesNotExist.account_id, }; } if ('CreateAccountOnlyByRegistrar' in kind) { return { type: 'createAccountOnlyByRegistrar', accountId: kind.CreateAccountOnlyByRegistrar.account_id, registrarAccountId: kind.CreateAccountOnlyByRegistrar.registrar_account_id, predecessorId: kind.CreateAccountOnlyByRegistrar.predecessor_id, }; } if ('CreateAccountNotAllowed' in kind) { return { type: 'createAccountNotAllowed', accountId: kind.CreateAccountNotAllowed.account_id, predecessorId: kind.CreateAccountNotAllowed.predecessor_id, }; } if ('ActorNoPermission' in kind) { return { type: 'actorNoPermission', accountId: kind.ActorNoPermission.account_id, actorId: kind.ActorNoPermission.actor_id, }; } if ('DeleteKeyDoesNotExist' in kind) { return { type: 'deleteKeyDoesNotExist', accountId: kind.DeleteKeyDoesNotExist.account_id, publicKey: kind.DeleteKeyDoesNotExist.public_key, }; } if ('AddKeyAlreadyExists' in kind) { return { type: 'addKeyAlreadyExists', accountId: kind.AddKeyAlreadyExists.account_id, publicKey: kind.AddKeyAlreadyExists.public_key, }; } if ('DeleteAccountStaking' in kind) { return { type: 'deleteAccountStaking', accountId: kind.DeleteAccountStaking.account_id, }; } if ('LackBalanceForState' in kind) { return { type: 'lackBalanceForState', accountId: kind.LackBalanceForState.account_id, amount: kind.LackBalanceForState.amount, }; } if ('TriesToUnstake' in kind) { return { type: 'triesToUnstake', accountId: kind.TriesToUnstake.account_id, }; } if ('TriesToStake' in kind) { return { type: 'triesToStake', accountId: kind.TriesToStake.account_id, stake: kind.TriesToStake.stake, locked: kind.TriesToStake.locked, balance: kind.TriesToStake.balance, }; } if ('InsufficientStake' in kind) { return { type: 'insufficientStake', accountId: kind.InsufficientStake.account_id, stake: kind.InsufficientStake.stake, minimumStake: kind.InsufficientStake.minimum_stake, }; } if ('FunctionCallError' in kind) { return { type: 'functionCallError', error: mapRpcFunctionCallError(kind.FunctionCallError), }; } if ('NewReceiptValidationError' in kind) { return { type: 'newReceiptValidationError', error: mapRpcNewReceiptValidationError(kind.NewReceiptValidationError), }; } if ('OnlyImplicitAccountCreationAllowed' in kind) { return { type: 'onlyImplicitAccountCreationAllowed', accountId: kind.OnlyImplicitAccountCreationAllowed.account_id, }; } if ('DeleteAccountWithLargeState' in kind) { return { type: 'deleteAccountWithLargeState', accountId: kind.DeleteAccountWithLargeState.account_id, }; } return UNKNOWN_ERROR; } function mapRpcReceiptInvalidTxError(error) { const UNKNOWN_ERROR = { type: 'unknown' }; if ('InvalidAccessKeyError' in error) { return { type: 'invalidAccessKeyError', error: mapRpcInvalidAccessKeyError(error.InvalidAccessKeyError), }; } if ('InvalidSignerId' in error) { return { type: 'invalidSignerId', signerId: error.InvalidSignerId.signer_id, }; } if ('SignerDoesNotExist' in error) { return { type: 'signerDoesNotExist', signerId: error.SignerDoesNotExist.signer_id, }; } if ('InvalidNonce' in error) { return { type: 'invalidNonce', transactionNonce: error.InvalidNonce.tx_nonce, akNonce: error.InvalidNonce.ak_nonce, }; } if ('NonceTooLarge' in error) { return { type: 'nonceTooLarge', transactionNonce: error.NonceTooLarge.tx_nonce, upperBound: error.NonceTooLarge.upper_bound, }; } if ('InvalidReceiverId' in error) { return { type: 'invalidReceiverId', receiverId: error.InvalidReceiverId.receiver_id, }; } if ('InvalidSignature' in error) { return { type: 'invalidSignature', }; } if ('NotEnoughBalance' in error) { return { type: 'notEnoughBalance', signerId: error.NotEnoughBalance.signer_id, balance: error.NotEnoughBalance.balance, cost: error.NotEnoughBalance.cost, }; } if ('LackBalanceForState' in error) { return { type: 'lackBalanceForState', signerId: error.LackBalanceForState.signer_id, amount: error.LackBalanceForState.amount, }; } if ('CostOverflow' in error) { return { type: 'costOverflow', }; } if ('InvalidChain' in error) { return { type: 'invalidChain', }; } if ('Expired' in error) { return { type: 'expired', }; } if ('ActionsValidation' in error) { return { type: 'actionsValidation', }; } if ('TransactionSizeExceeded' in error) { return { type: 'transactionSizeExceeded', size: error.TransactionSizeExceeded.size, limit: error.TransactionSizeExceeded.limit, }; } return UNKNOWN_ERROR; } function mapRpcReceiptError(error) { let UNKNOWN_ERROR = { type: 'unknown' }; if ('ActionError' in error) { return { type: 'action', error: mapRpcReceiptActionError(error.ActionError), }; } if ('InvalidTxError' in error) { return { type: 'transaction', error: mapRpcReceiptInvalidTxError(error.InvalidTxError), }; } return UNKNOWN_ERROR; } function mapRpcReceiptStatus(status) { if ('SuccessValue' in status) { return { type: 'successValue', value: status.SuccessValue }; } if ('SuccessReceiptId' in status) { return { type: 'successReceiptId', receiptId: status.SuccessReceiptId }; } if ('Failure' in status) { return { type: 'failure', error: mapRpcReceiptError(status.Failure) }; } return { type: 'unknown' }; } function mapRpcActionToAction1(rpcAction) { if (typeof rpcAction === 'object' && 'Delegate' in rpcAction) { return { kind: 'delegateAction', args: { actions: rpcAction.Delegate.delegate_action.actions.map( (subaction, index) => ({ ...mapNonDelegateRpcActionToAction(subaction), delegateIndex: index, }), ), receiverId: rpcAction.Delegate.delegate_action.receiver_id, senderId: rpcAction.Delegate.delegate_action.sender_id, }, }; } return mapNonDelegateRpcActionToAction(rpcAction); } function parseOutcomeOld(outcome) { return { blockHash: outcome.block_hash, tokensBurnt: outcome.outcome.tokens_burnt, gasBurnt: outcome.outcome.gas_burnt, status: mapRpcReceiptStatus(outcome.outcome.status), logs: outcome.outcome.logs, receiptIds: outcome.outcome.receipt_ids, }; } function dollarFormat(number) { const bigNumber = new Big(number); // Format to two decimal places without thousands separator const formattedNumber = bigNumber.toFixed(2); // Add comma as a thousands separator const parts = formattedNumber.split('.'); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); const dollarFormattedNumber = `${parts.join('.')}`; return dollarFormattedNumber; } function localFormat(number) { const bigNumber = Big(number); const formattedNumber = bigNumber .toFixed(5) .replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); // Add commas before the decimal point return formattedNumber.replace(/\.?0*$/, ''); // Remove trailing zeros and the dot } function dollarFormat(number) { const bigNumber = new Big(number); // Format to two decimal places without thousands separator const formattedNumber = bigNumber.toFixed(2); // Add comma as a thousands separator const parts = formattedNumber.split('.'); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); const dollarFormattedNumber = `${parts.join('.')}`; return dollarFormattedNumber; } function localFormat(number) { const bigNumber = Big(number); const formattedNumber = bigNumber .toFixed(5) .replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); // Add commas before the decimal point return formattedNumber.replace(/\.?0*$/, ''); // Remove trailing zeros and the dot } function dollarFormat(number) { const bigNumber = new Big(number); // Format to two decimal places without thousands separator const formattedNumber = bigNumber.toFixed(2); // Add comma as a thousands separator const parts = formattedNumber.split('.'); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); const dollarFormattedNumber = `${parts.join('.')}`; return dollarFormattedNumber; } function localFormat(number) { const bigNumber = Big(number); const formattedNumber = bigNumber .toFixed(5) .replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); // Add commas before the decimal point return formattedNumber.replace(/\.?0*$/, ''); // Remove trailing zeros and the dot } function dollarFormat(number) { const bigNumber = new Big(number); // Format to two decimal places without thousands separator const formattedNumber = bigNumber.toFixed(2); // Add comma as a thousands separator const parts = formattedNumber.split('.'); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); const dollarFormattedNumber = `${parts.join('.')}`; return dollarFormattedNumber; } function localFormat(number) { const bigNumber = Big(number); const formattedNumber = bigNumber .toFixed(5) .replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); // Add commas before the decimal point return formattedNumber.replace(/\.?0*$/, ''); // Remove trailing zeros and the dot } function dollarFormat(number) { const bigNumber = new Big(number); // Format to two decimal places without thousands separator const formattedNumber = bigNumber.toFixed(2); // Add comma as a thousands separator const parts = formattedNumber.split('.'); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); const dollarFormattedNumber = `${parts.join('.')}`; return dollarFormattedNumber; } function localFormat(number) { const bigNumber = Big(number); const formattedNumber = bigNumber .toFixed(5) .replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); // Add commas before the decimal point return formattedNumber.replace(/\.?0*$/, ''); // Remove trailing zeros and the dot } /* END_INCLUDE: "includes/near.jsx" */ function MainComponent(props) { const { network, rpcTxn, txn, t } = props; const [receipt, setReceipt] = useState(null); const config = getConfig(network); function transactionReceipts(txn) { const actions = txn.transaction.actions.map((txn) => mapRpcActionToAction(txn), ); const receipts = txn.receipts; const receiptsOutcome = txn.receipts_outcome; if ( receipts.length === 0 || receipts[0].receipt_id !== receiptsOutcome[0].id ) { receipts.unshift({ predecessor_id: txn.transaction.signer_id, receipt: actions, receipt_id: receiptsOutcome[0].id, receiver_id: txn.transaction.receiver_id, }); } const receiptOutcomesByIdMap = new Map(); const receiptsByIdMap = new Map(); receiptsOutcome.forEach((receipt) => { receiptOutcomesByIdMap.set(receipt.id, receipt); }); receipts.forEach((receiptItem) => { receiptsByIdMap.set(receiptItem.receipt_id, { ...receiptItem, actions: receiptItem.receipt_id === receiptsOutcome[0].id ? actions : receiptItem.receipt?.Action?.actions.map((receipt) => mapRpcActionToAction(receipt), ), }); }); const collectReceipts = (receiptHash) => { const receipt = receiptsByIdMap.get(receiptHash); const receiptOutcome = receiptOutcomesByIdMap.get(receiptHash); return { ...receipt, ...receiptOutcome, outcome: { ...receiptOutcome.outcome, outgoing_receipts: receiptOutcome.outcome.receipt_ids.map(collectReceipts), }, }; }; return collectReceipts(receiptsOutcome[0].id); } useEffect(() => { if (rpcTxn) { const receipt = transactionReceipts(rpcTxn); setReceipt(receipt); } }, [rpcTxn]); return ( <div className="bg-white text-sm text-nearblue-600 divide-solid divide-gray-200 divide-y"> { <Widget src={`${config.ownerId}/widget/bos-components.components.Transactions.ReceiptRow`} props={{ txn: txn, receipt: receipt, network: network, t: t, }} /> } </div> ); } return MainComponent(props, context);