From 22110d8cc93e4fed7a98c51991976a77dfce712d Mon Sep 17 00:00:00 2001 From: kushagrasarathe <76868364+kushagrasarathe@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:05:49 +0530 Subject: [PATCH 1/3] fix: external claim links history ui + badges fix --- src/app/(mobile-ui)/history/page.tsx | 1 + src/components/Home/HomeHistory.tsx | 8 +- .../TransactionDetails/TransactionCard.tsx | 11 +- .../TransactionDetailsHeaderCard.tsx | 11 + .../TransactionDetailsReceipt.tsx | 670 +++++++++--------- .../transactionTransformer.ts | 27 +- 6 files changed, 370 insertions(+), 358 deletions(-) diff --git a/src/app/(mobile-ui)/history/page.tsx b/src/app/(mobile-ui)/history/page.tsx index d80885d5e..35feb7f5c 100644 --- a/src/app/(mobile-ui)/history/page.tsx +++ b/src/app/(mobile-ui)/history/page.tsx @@ -161,6 +161,7 @@ const HistoryPage = () => { initials={transactionDetails.initials} transaction={transactionDetails} position={position} + haveSentMoneyToUser={transactionDetails.haveSentMoneyToUser} /> ) })() diff --git a/src/components/Home/HomeHistory.tsx b/src/components/Home/HomeHistory.tsx index 4fcaf7dd3..444bf5605 100644 --- a/src/components/Home/HomeHistory.tsx +++ b/src/components/Home/HomeHistory.tsx @@ -216,12 +216,6 @@ const HomeHistory = ({ isPublic = false, username }: { isPublic?: boolean; usern // determine card position for styling (first, middle, last, single) const position = getCardPosition(index, pendingRequests.length) - const haveSentMoneyToUser = - item.userRole === 'SENDER' - ? interactions[item.recipientAccount.userId] - : item.senderAccount?.userId - ? interactions[item.senderAccount.userId] - : false return ( ) })} diff --git a/src/components/TransactionDetails/TransactionCard.tsx b/src/components/TransactionDetails/TransactionCard.tsx index 5f7c6411e..51d055b9f 100644 --- a/src/components/TransactionDetails/TransactionCard.tsx +++ b/src/components/TransactionDetails/TransactionCard.tsx @@ -6,13 +6,14 @@ import { TransactionDirection } from '@/components/TransactionDetails/Transactio import { TransactionDetails } from '@/components/TransactionDetails/transactionTransformer' import { useTransactionDetailsDrawer } from '@/hooks/useTransactionDetailsDrawer' import { EHistoryEntryType, EHistoryUserRole } from '@/hooks/useTransactionHistory' -import { formatNumberForDisplay } from '@/utils' +import { formatNumberForDisplay, printableAddress } from '@/utils' import { getDisplayCurrencySymbol } from '@/utils/currency' import React from 'react' import { STABLE_COINS } from '@/constants' import Image from 'next/image' import StatusPill, { StatusPillType } from '../Global/StatusPill' import { VerifiedUserLabel } from '../UserHeader' +import { isAddress } from 'viem' export type TransactionType = | 'send' @@ -24,6 +25,7 @@ export type TransactionType = | 'bank_withdraw' | 'bank_deposit' | 'bank_request_fulfillment' + | 'claim_external' interface TransactionCardProps { type: TransactionType @@ -174,11 +176,10 @@ const TransactionCard: React.FC = ({ {isPending &&
}
- {/* */}
{/* display the action icon and type text */} @@ -229,6 +230,7 @@ function getActionIcon(type: TransactionType, direction: TransactionDirection): case 'withdraw': case 'bank_withdraw': case 'cashout': + case 'claim_external': iconName = 'arrow-up' iconSize = 8 break @@ -252,6 +254,9 @@ function getActionText(type: TransactionType): string { case 'bank_withdraw': actionText = 'Withdraw' break + case 'claim_external': + actionText = 'Claim' + break case 'bank_deposit': actionText = 'Add' break diff --git a/src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx b/src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx index 54d3b6729..3396f0469 100644 --- a/src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx +++ b/src/components/TransactionDetails/TransactionDetailsHeaderCard.tsx @@ -22,6 +22,7 @@ export type TransactionDirection = | 'bank_claim' | 'bank_deposit' | 'bank_request_fulfillment' + | 'claim_external' interface TransactionDetailsHeaderCardProps { direction: TransactionDirection @@ -100,6 +101,15 @@ const getTitle = ( case 'bank_deposit': titleText = `${status === 'completed' ? 'Added' : 'Adding'} from ${displayName}` break + case 'claim_external': + if (status === 'completed') { + titleText = `Claimed to ${displayName}` + } else if (status === 'failed') { + titleText = `Claim to ${displayName}` + } else { + titleText = `Claiming to ${displayName}` + } + break default: titleText = displayName break @@ -124,6 +134,7 @@ const getIcon = (direction: TransactionDirection, isLinkTransaction?: boolean): return 'arrow-down-left' case 'withdraw': case 'bank_claim': + case 'claim_external': return 'arrow-up' case 'add': case 'bank_deposit': diff --git a/src/components/TransactionDetails/TransactionDetailsReceipt.tsx b/src/components/TransactionDetails/TransactionDetailsReceipt.tsx index 5bd3548f9..b65223cef 100644 --- a/src/components/TransactionDetails/TransactionDetailsReceipt.tsx +++ b/src/components/TransactionDetails/TransactionDetailsReceipt.tsx @@ -8,7 +8,7 @@ import { useUserStore } from '@/redux/hooks' import { chargesApi } from '@/services/charges' import { sendLinksApi } from '@/services/sendLinks' import { formatAmount, formatDate, getInitialsFromName } from '@/utils' -import { formatIban, shortenAddress } from '@/utils/general.utils' +import { formatIban, printableAddress, shortenAddress, shortenAddressLong } from '@/utils/general.utils' import { getDisplayCurrencySymbol } from '@/utils/currency' import { cancelOnramp } from '@/app/actions/onramp' import { captureException } from '@sentry/nextjs' @@ -25,6 +25,7 @@ import CopyToClipboard from '../Global/CopyToClipboard' import MoreInfo from '../Global/MoreInfo' import CancelSendLinkModal from '../Global/CancelSendLinkModal' import { twMerge } from 'tailwind-merge' +import { isAddress } from 'viem' const getBankAccountLabel = (type: string) => { switch (type.toLowerCase()) { @@ -83,61 +84,57 @@ export const TransactionDetailsReceipt = ({ ) }, [transaction]) - const shouldHideCreatedRowBorder = useMemo(() => { - if (!transaction) return true - - // the border for the 'Created' row should be hidden if it is the last item in the details card. - // this logic checks for the presence of any other detail rows that might be displayed below it. - // if any of the following conditions are met, a row will be displayed, and the border should NOT be hidden. - - const hasTokenDetails = transaction.tokenDisplayDetails && transaction.sourceView === 'history' - const hasCancellationDate = transaction.status === 'cancelled' && transaction.cancelledDate - const hasClaimDate = transaction.status === 'completed' && transaction.claimedAt - const hasCompletionDate = - transaction.status === 'completed' && - transaction.completedAt && - transaction.extraDataForDrawer?.originalType !== EHistoryEntryType.DIRECT_SEND - const hasFee = transaction.fee !== undefined - const hasExchangeRateInfo = - transaction.direction === 'bank_deposit' && - transaction.status === 'completed' && - transaction.currency?.code && - transaction.currency.code.toUpperCase() !== 'USD' - const hasBankAccountDetails = transaction.bankAccountDetails && transaction.bankAccountDetails.identifier - const hasTransferId = - transaction.id && (transaction.direction === 'bank_withdraw' || transaction.direction === 'bank_claim') - const hasDepositInstructions = - (transaction.extraDataForDrawer?.originalType === EHistoryEntryType.BRIDGE_ONRAMP || - (isPendingBankRequest && - transaction.extraDataForDrawer?.originalUserRole === EHistoryUserRole.SENDER)) && - transaction.status === 'pending' && - transaction.extraDataForDrawer?.depositInstructions && - transaction.extraDataForDrawer.depositInstructions.bank_name - const hasMemo = !!transaction.memo?.trim() - const hasNetworkFee = transaction.networkFeeDetails && transaction.sourceView === 'status' - const hasAttachment = !!transaction.attachmentUrl - - const isNonPendingTransaction = transaction.status !== 'pending' - - // if any of these are true, it means there's another row below "Created", so we should NOT hide the border. - const hasFollowingRows = - hasTokenDetails || - hasCancellationDate || - hasClaimDate || - hasCompletionDate || - hasFee || - hasExchangeRateInfo || - hasBankAccountDetails || - hasTransferId || - hasDepositInstructions || - hasMemo || - hasNetworkFee || - hasAttachment || - isNonPendingTransaction - - return !hasFollowingRows + // config to determine which rows are visible in the receipt + // this helps in managing layout and borders + const rowVisibilityConfig = useMemo(() => { + if (!transaction) return {} + + return { + createdAt: !!transaction.createdAt, + to: transaction.direction === 'claim_external', + tokenAndNetwork: transaction.tokenDisplayDetails && transaction.sourceView === 'history', + txId: transaction.txHash && transaction.explorerUrl, + cancelled: transaction.status === 'cancelled' && transaction.cancelledDate, + claimed: transaction.status === 'completed' && transaction.claimedAt, + completed: + transaction.status === 'completed' && + transaction.completedAt && + transaction.extraDataForDrawer?.originalType !== EHistoryEntryType.DIRECT_SEND, + fee: transaction.fee !== undefined, + exchangeRate: + transaction.direction === 'bank_deposit' && + transaction.status === 'completed' && + transaction.currency?.code && + transaction.currency.code.toUpperCase() !== 'USD', + bankAccountDetails: transaction.bankAccountDetails && transaction.bankAccountDetails.identifier, + transferId: + transaction.id && (transaction.direction === 'bank_withdraw' || transaction.direction === 'bank_claim'), + depositInstructions: + (transaction.extraDataForDrawer?.originalType === EHistoryEntryType.BRIDGE_ONRAMP || + (isPendingBankRequest && + transaction.extraDataForDrawer?.originalUserRole === EHistoryUserRole.SENDER)) && + transaction.status === 'pending' && + transaction.extraDataForDrawer?.depositInstructions && + transaction.extraDataForDrawer.depositInstructions.bank_name, + peanutFee: transaction.status !== 'pending', + comment: !!transaction.memo?.trim(), + networkFee: transaction.networkFeeDetails && transaction.sourceView === 'status', + attachment: !!transaction.attachmentUrl, + } }, [transaction, isPendingBankRequest]) + const visibleRows = useMemo(() => { + return Object.keys(rowVisibilityConfig).filter( + (key) => rowVisibilityConfig[key as keyof typeof rowVisibilityConfig] + ) + }, [rowVisibilityConfig]) + + // helper to hide border for the last visible row + const shouldHideBorder = (rowKey: string) => { + const currentIndex = visibleRows.indexOf(rowKey) + return currentIndex === visibleRows.length - 1 + } + const isPendingRequestee = useMemo(() => { if (!transaction) return false return ( @@ -252,15 +249,32 @@ export const TransactionDetailsReceipt = ({ {/* details card (date, fee, memo) and more */}
- {transaction.createdAt && ( + {rowVisibilityConfig.createdAt && ( )} - {transaction.tokenDisplayDetails && transaction.sourceView === 'history' && ( + {rowVisibilityConfig.to && ( + + + {isAddress(transaction.userName) + ? printableAddress(transaction.userName) + : transaction.userName} + + +
+ } + hideBottomBorder={shouldHideBorder('to')} + /> + )} + + {rowVisibilityConfig.tokenAndNetwork && transaction.tokenDisplayDetails && ( } - hideBottomBorder={!transaction.networkFeeDetails && !transaction.peanutFeeDetails} + hideBottomBorder={shouldHideBorder('tokenAndNetwork')} /> )} - {transaction.status === 'cancelled' && transaction.cancelledDate && ( + {rowVisibilityConfig.txId && transaction.txHash && ( + + {shortenAddressLong(transaction.txHash)} + + + } + hideBottomBorder={shouldHideBorder('txId')} + /> + )} + + {rowVisibilityConfig.cancelled && ( <> {transaction.cancelledDate && ( )} )} - {transaction.status === 'completed' && transaction.claimedAt && ( + {rowVisibilityConfig.claimed && ( <> {transaction.claimedAt && ( - + )} )} - {transaction.status === 'completed' && transaction.completedAt && ( + {rowVisibilityConfig.completed && ( <> )} - {transaction.fee !== undefined && ( - + {rowVisibilityConfig.fee && ( + )} {/* Exchange rate and original currency for completed bank_deposit transactions */} - {transaction.direction === 'bank_deposit' && - transaction.status === 'completed' && - transaction.currency?.code && - transaction.currency.code.toUpperCase() !== 'USD' && ( - <> + {rowVisibilityConfig.exchangeRate && ( + <> + { + const currencyAmount = transaction.currency?.amount || transaction.amount.toString() + const currencySymbol = getDisplayCurrencySymbol(transaction.currency!.code) + return `${currencySymbol} ${formatAmount(Number(currencyAmount))}` + })()} + hideBottomBorder={false} + /> + {transaction.extraDataForDrawer?.receipt?.exchange_rate && ( { - const currencyAmount = - transaction.currency?.amount || transaction.amount.toString() - const currencySymbol = getDisplayCurrencySymbol(transaction.currency.code) - return `${currencySymbol} ${formatAmount(Number(currencyAmount))}` - })()} - hideBottomBorder={false} + label="Exchange rate" + value={`1 ${transaction.currency!.code?.toUpperCase()} = $${formatAmount(Number(transaction.extraDataForDrawer.receipt.exchange_rate))}`} + hideBottomBorder={shouldHideBorder('exchangeRate')} /> - {transaction.extraDataForDrawer?.receipt?.exchange_rate && ( - - )} - - )} + )} + + )} - {transaction.bankAccountDetails && transaction.bankAccountDetails.identifier && ( + {rowVisibilityConfig.bankAccountDetails && transaction.bankAccountDetails && ( @@ -385,212 +406,225 @@ export const TransactionDetailsReceipt = ({ )} } - hideBottomBorder={ - !( - transaction.id && - (transaction.direction === 'bank_withdraw' || - transaction.direction === 'bank_claim') - ) && - !(transaction.direction === 'bank_deposit' && transaction.status === 'pending') && - !transaction.memo && - !transaction.attachmentUrl && - !transaction.networkFeeDetails && - transaction.status === 'pending' + hideBottomBorder={shouldHideBorder('bankAccountDetails')} + /> + )} + {rowVisibilityConfig.transferId && ( + + {shortenAddress(transaction.id.toUpperCase(), 20)} + + } + hideBottomBorder={shouldHideBorder('transferId')} /> )} - {transaction.id && - (transaction.direction === 'bank_withdraw' || transaction.direction === 'bank_claim') && ( + + {/* Onramp deposit instructions for bridge_onramp transactions */} + {rowVisibilityConfig.depositInstructions && transaction.extraDataForDrawer?.depositInstructions && ( + <> + Deposit Message + + + } value={
- {shortenAddress(transaction.id.toUpperCase(), 20)} - + + {transaction.extraDataForDrawer.depositInstructions.deposit_message} + +
} - hideBottomBorder={ - !transaction.status || - (!transaction.memo && - !transaction.attachmentUrl && - !transaction.networkFeeDetails && - transaction.status === 'pending') - } + hideBottomBorder={shouldHideBorder('depositInstructions')} /> - )} - {/* Onramp deposit instructions for bridge_onramp transactions */} - {(transaction.extraDataForDrawer?.originalType === EHistoryEntryType.BRIDGE_ONRAMP || - (isPendingBankRequest && - transaction.extraDataForDrawer?.originalUserRole === EHistoryUserRole.SENDER)) && - transaction.status === 'pending' && - transaction.extraDataForDrawer?.depositInstructions && - transaction.extraDataForDrawer.depositInstructions.bank_name && ( - <> - - Deposit Message - - - } - value={ -
- - {transaction.extraDataForDrawer.depositInstructions.deposit_message} - - -
- } - hideBottomBorder={false} - /> - - {/* Toggle button for bank details */} -
- -
- - {/* Collapsible bank details */} - {showBankDetails && ( - <> - - - {transaction.extraDataForDrawer.depositInstructions.bank_name} - - - - } - hideBottomBorder={false} - /> - - - { - transaction.extraDataForDrawer.depositInstructions - .bank_address - } - - - - } - hideBottomBorder={false} - /> + {/* Toggle button for bank details */} +
+ +
- {/* European format (IBAN/BIC) */} - {transaction.extraDataForDrawer.depositInstructions.iban && - transaction.extraDataForDrawer.depositInstructions.bic ? ( - <> - - - {formatIban( - transaction.extraDataForDrawer.depositInstructions - .iban - )} - - - + {/* Collapsible bank details */} + {showBankDetails && ( + <> + + + {transaction.extraDataForDrawer.depositInstructions.bank_name} + + + + } + hideBottomBorder={false} + /> + + + {transaction.extraDataForDrawer.depositInstructions.bank_address} + + + + } + hideBottomBorder={false} + /> + + {/* European format (IBAN/BIC) */} + {transaction.extraDataForDrawer.depositInstructions.iban && + transaction.extraDataForDrawer.depositInstructions.bic ? ( + <> + + + {formatIban( + transaction.extraDataForDrawer.depositInstructions.iban + )} + + + + } + hideBottomBorder={false} + /> + + + {transaction.extraDataForDrawer.depositInstructions.bic} + + + + } + hideBottomBorder={false} + /> + {transaction.extraDataForDrawer.depositInstructions.account_holder_name && ( - {transaction.extraDataForDrawer.depositInstructions.bic} + { + transaction.extraDataForDrawer.depositInstructions + .account_holder_name + } } - hideBottomBorder={false} + hideBottomBorder={true} /> - {transaction.extraDataForDrawer.depositInstructions - .account_holder_name && ( - - - { - transaction.extraDataForDrawer - .depositInstructions.account_holder_name - } - - - - } - hideBottomBorder={true} - /> - )} - - ) : ( - /* US format (Account Number/Routing Number) */ - <> + )} + + ) : ( + /* US format (Account Number/Routing Number) */ + <> + + + { + transaction.extraDataForDrawer.depositInstructions + .bank_account_number + } + + + + } + hideBottomBorder={false} + /> + + + { + transaction.extraDataForDrawer.depositInstructions + .bank_routing_number + } + + + + } + hideBottomBorder={false} + /> + {transaction.extraDataForDrawer.depositInstructions + .bank_beneficiary_name && ( { transaction.extraDataForDrawer.depositInstructions - .bank_account_number + .bank_beneficiary_name } @@ -598,111 +632,63 @@ export const TransactionDetailsReceipt = ({ } hideBottomBorder={false} /> + )} + {transaction.extraDataForDrawer.depositInstructions + .bank_beneficiary_address && ( { transaction.extraDataForDrawer.depositInstructions - .bank_routing_number + .bank_beneficiary_address } } - hideBottomBorder={false} + hideBottomBorder={true} /> - {transaction.extraDataForDrawer.depositInstructions - .bank_beneficiary_name && ( - - - { - transaction.extraDataForDrawer - .depositInstructions.bank_beneficiary_name - } - - - - } - hideBottomBorder={false} - /> - )} - {transaction.extraDataForDrawer.depositInstructions - .bank_beneficiary_address && ( - - - { - transaction.extraDataForDrawer - .depositInstructions - .bank_beneficiary_address - } - - - - } - hideBottomBorder={true} - /> - )} - - )} - - )} - - )} + )} + + )} + + )} + + )} - {transaction.status !== 'pending' && ( + {rowVisibilityConfig.peanutFee && ( )} - {transaction.memo?.trim() && ( + {rowVisibilityConfig.comment && ( )} - {transaction.networkFeeDetails && transaction.sourceView === 'status' && ( + {rowVisibilityConfig.networkFee && ( )} - {transaction.attachmentUrl && ( + {rowVisibilityConfig.attachment && transaction.attachmentUrl && ( Date: Wed, 27 Aug 2025 15:49:34 +0530 Subject: [PATCH 2/3] fix: resolve codderrabbit suggestions --- .../TransactionDetailsReceipt.tsx | 97 +++++++++++-------- .../transaction-details.utils.ts | 49 ++++++++++ 2 files changed, 103 insertions(+), 43 deletions(-) create mode 100644 src/components/TransactionDetails/transaction-details.utils.ts diff --git a/src/components/TransactionDetails/TransactionDetailsReceipt.tsx b/src/components/TransactionDetails/TransactionDetailsReceipt.tsx index b65223cef..3f9f0ccbf 100644 --- a/src/components/TransactionDetails/TransactionDetailsReceipt.tsx +++ b/src/components/TransactionDetails/TransactionDetailsReceipt.tsx @@ -26,17 +26,7 @@ import MoreInfo from '../Global/MoreInfo' import CancelSendLinkModal from '../Global/CancelSendLinkModal' import { twMerge } from 'tailwind-merge' import { isAddress } from 'viem' - -const getBankAccountLabel = (type: string) => { - switch (type.toLowerCase()) { - case 'iban': - return 'IBAN' - case 'clabe': - return 'CLABE' - default: - return 'Account Number' - } -} +import { getBankAccountLabel, TransactionDetailsRowKey, transactionDetailsRowKeys } from './transaction-details.utils' export const TransactionDetailsReceipt = ({ transaction, @@ -85,54 +75,68 @@ export const TransactionDetailsReceipt = ({ }, [transaction]) // config to determine which rows are visible in the receipt - // this helps in managing layout and borders - const rowVisibilityConfig = useMemo(() => { - if (!transaction) return {} + // this helps in managing layout and borders without repeating code + const rowVisibilityConfig = useMemo((): Record => { + if (!transaction) { + // if no transaction, return all false + return transactionDetailsRowKeys.reduce( + (acc, key) => { + acc[key] = false + return acc + }, + {} as Record + ) + } + // if transaction exists, calculate visibility for each row return { createdAt: !!transaction.createdAt, to: transaction.direction === 'claim_external', - tokenAndNetwork: transaction.tokenDisplayDetails && transaction.sourceView === 'history', - txId: transaction.txHash && transaction.explorerUrl, - cancelled: transaction.status === 'cancelled' && transaction.cancelledDate, - claimed: transaction.status === 'completed' && transaction.claimedAt, - completed: + tokenAndNetwork: !!(transaction.tokenDisplayDetails && transaction.sourceView === 'history'), + txId: !!transaction.txHash, + cancelled: !!(transaction.status === 'cancelled' && transaction.cancelledDate), + claimed: !!(transaction.status === 'completed' && transaction.claimedAt), + completed: !!( transaction.status === 'completed' && transaction.completedAt && - transaction.extraDataForDrawer?.originalType !== EHistoryEntryType.DIRECT_SEND, + transaction.extraDataForDrawer?.originalType !== EHistoryEntryType.DIRECT_SEND + ), fee: transaction.fee !== undefined, - exchangeRate: + exchangeRate: !!( transaction.direction === 'bank_deposit' && transaction.status === 'completed' && transaction.currency?.code && - transaction.currency.code.toUpperCase() !== 'USD', - bankAccountDetails: transaction.bankAccountDetails && transaction.bankAccountDetails.identifier, - transferId: - transaction.id && (transaction.direction === 'bank_withdraw' || transaction.direction === 'bank_claim'), - depositInstructions: + transaction.currency.code.toUpperCase() !== 'USD' + ), + bankAccountDetails: !!(transaction.bankAccountDetails && transaction.bankAccountDetails.identifier), + transferId: !!( + transaction.id && + (transaction.direction === 'bank_withdraw' || transaction.direction === 'bank_claim') + ), + depositInstructions: !!( (transaction.extraDataForDrawer?.originalType === EHistoryEntryType.BRIDGE_ONRAMP || (isPendingBankRequest && transaction.extraDataForDrawer?.originalUserRole === EHistoryUserRole.SENDER)) && transaction.status === 'pending' && transaction.extraDataForDrawer?.depositInstructions && - transaction.extraDataForDrawer.depositInstructions.bank_name, + transaction.extraDataForDrawer.depositInstructions.bank_name + ), peanutFee: transaction.status !== 'pending', comment: !!transaction.memo?.trim(), - networkFee: transaction.networkFeeDetails && transaction.sourceView === 'status', + networkFee: !!(transaction.networkFeeDetails && transaction.sourceView === 'status'), attachment: !!transaction.attachmentUrl, } }, [transaction, isPendingBankRequest]) const visibleRows = useMemo(() => { - return Object.keys(rowVisibilityConfig).filter( - (key) => rowVisibilityConfig[key as keyof typeof rowVisibilityConfig] - ) + // filter rowkeys to only include visible rows, maintaining the order + return transactionDetailsRowKeys.filter((key) => rowVisibilityConfig[key]) }, [rowVisibilityConfig]) // helper to hide border for the last visible row - const shouldHideBorder = (rowKey: string) => { - const currentIndex = visibleRows.indexOf(rowKey) - return currentIndex === visibleRows.length - 1 + const shouldHideBorder = (rowKey: TransactionDetailsRowKey) => { + const lastVisibleRow = visibleRows[visibleRows.length - 1] + return rowKey === lastVisibleRow } const isPendingRequestee = useMemo(() => { @@ -314,15 +318,22 @@ export const TransactionDetailsReceipt = ({ - {shortenAddressLong(transaction.txHash)} - - + transaction.explorerUrl ? ( + + {shortenAddressLong(transaction.txHash)} + + + ) : ( +
+ {shortenAddressLong(transaction.txHash)} + +
+ ) } hideBottomBorder={shouldHideBorder('txId')} /> diff --git a/src/components/TransactionDetails/transaction-details.utils.ts b/src/components/TransactionDetails/transaction-details.utils.ts new file mode 100644 index 000000000..332c61fca --- /dev/null +++ b/src/components/TransactionDetails/transaction-details.utils.ts @@ -0,0 +1,49 @@ +// union type for all possible rows in the receipt +export type TransactionDetailsRowKey = + | 'createdAt' + | 'claimed' + | 'to' + | 'tokenAndNetwork' + | 'txId' + | 'cancelled' + | 'completed' + | 'exchangeRate' + | 'bankAccountDetails' + | 'transferId' + | 'depositInstructions' + | 'networkFee' + | 'fee' + | 'peanutFee' + | 'comment' + | 'attachment' + +// rder of the rows in the receipt +export const transactionDetailsRowKeys: TransactionDetailsRowKey[] = [ + 'createdAt', + 'to', + 'tokenAndNetwork', + 'txId', + 'cancelled', + 'claimed', + 'completed', + 'fee', + 'exchangeRate', + 'bankAccountDetails', + 'transferId', + 'depositInstructions', + 'peanutFee', + 'comment', + 'networkFee', + 'attachment', +] + +export const getBankAccountLabel = (type: string) => { + switch (type.toLowerCase()) { + case 'iban': + return 'IBAN' + case 'clabe': + return 'CLABE' + default: + return 'Account Number' + } +} From c485a98255190451e5a4ec284ad2b5defb6dc765 Mon Sep 17 00:00:00 2001 From: kushagrasarathe <76868364+kushagrasarathe@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:57:13 +0530 Subject: [PATCH 3/3] fix: coderrabbit comment on state stale --- src/components/TransactionDetails/transactionTransformer.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/TransactionDetails/transactionTransformer.ts b/src/components/TransactionDetails/transactionTransformer.ts index ad4cfd30b..dbd4cd21c 100644 --- a/src/components/TransactionDetails/transactionTransformer.ts +++ b/src/components/TransactionDetails/transactionTransformer.ts @@ -321,7 +321,10 @@ export function mapTransactionDataForDrawer(entry: HistoryEntry): MappedTransact uiStatus = 'pending' break case 'COMPLETED': - uiStatus = EHistoryEntryType.SEND_LINK === entry.type ? 'pending' : 'completed' + uiStatus = + EHistoryEntryType.SEND_LINK === entry.type && direction !== 'claim_external' + ? 'pending' + : 'completed' break case 'SUCCESSFUL': case 'CLAIMED':