From 17d40afda3a715167402780a2125f375b8841aec Mon Sep 17 00:00:00 2001 From: MananTank Date: Thu, 4 Sep 2025 14:45:15 +0000 Subject: [PATCH] Dashboard: fix payments tx history table crashing on onramp type purchase (#7982) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ## PR-Codex overview This PR focuses on refactoring the payment-related types and logic in the application to improve type safety and clarity. It introduces a new `BridgePayment` type, updates the `TableRow` component, and modifies how payments are filtered and processed. ### Detailed summary - Changed `Payment` type to `BridgePayment` in `TableRow` component. - Updated `originAmount` and `destinationAmount` to use `BigInt`. - Introduced `BridgePaymentType` and `OnrampPaymentType`. - Modified `getCSVData` to accept only `BridgePayment` types. - Added `isBridgePayment` function to filter payments. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` ## Summary by CodeRabbit - New Features - Payments views and CSV export now explicitly show only bridge payments; onramp entries are excluded. - Bug Fixes - Improved accuracy for large origin/destination amounts by converting amounts to integer form before token conversion. - Consistent token conversions across table, links, and CSV exports. - Refactor - Payment data reorganized into distinct bridge vs onramp variants to improve filtering and export consistency. --- .../src/@/api/universal-bridge/developer.ts | 49 ++++++++++++------- .../components/PaymentHistory.client.tsx | 35 ++++++++----- .../payments/components/PaymentsTableRow.tsx | 11 +++-- .../components/PaymentLinksTable.client.tsx | 2 +- 4 files changed, 62 insertions(+), 35 deletions(-) diff --git a/apps/dashboard/src/@/api/universal-bridge/developer.ts b/apps/dashboard/src/@/api/universal-bridge/developer.ts index f5987f3ef8e..db86b1bd564 100644 --- a/apps/dashboard/src/@/api/universal-bridge/developer.ts +++ b/apps/dashboard/src/@/api/universal-bridge/developer.ts @@ -297,38 +297,53 @@ export type PaymentsResponse = { totalCount: number; }; }; + +type BridgePaymentType = "buy" | "sell" | "transfer"; +type OnrampPaymentType = "onramp"; + export type Payment = { + // common id: string; - blockNumber?: bigint; - transactionId: string; + createdAt: string; clientId: string; - sender: string; receiver: string; - developerFeeRecipient: string; - developerFeeBps: number; transactions: Array<{ chainId: number; transactionHash: string; }>; status: "PENDING" | "COMPLETED" | "FAILED" | "NOT_FOUND"; - type: "buy" | "sell" | "transfer"; - originAmount: bigint; - destinationAmount: bigint; - purchaseData: unknown; - originToken: { - address: string; - symbol: string; - decimals: number; - chainId: number; - }; + + destinationAmount: string; destinationToken: { address: string; symbol: string; decimals: number; chainId: number; }; - createdAt: string; -}; + purchaseData: unknown; +} & ( + | { + type: BridgePaymentType; + transactionId: string; + blockNumber?: string; + sender: string; + developerFeeRecipient: string; + developerFeeBps: number; + originAmount: string; + originToken: { + address: string; + symbol: string; + decimals: number; + chainId: number; + }; + } + | { + onrampId: string; + type: OnrampPaymentType; + } +); + +export type BridgePayment = Extract; export async function getPayments(props: { clientId: string; diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx index e08bb70c610..da56a465295 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentHistory.client.tsx @@ -4,6 +4,7 @@ import { format } from "date-fns"; import { useMemo, useState } from "react"; import { type ThirdwebClient, toTokens } from "thirdweb"; import { + type BridgePayment, getPayments, type Payment, type PaymentsResponse, @@ -59,7 +60,9 @@ export function PaymentHistory(props: { { - return getCSVData(payPurchaseData?.data || []); + return getCSVData( + payPurchaseData?.data.filter(isBridgePayment) || [], + ); }} /> @@ -82,15 +85,17 @@ export function PaymentHistory(props: { {(!isEmpty || isLoading) && (payPurchaseData && !isLoading - ? payPurchaseData.data.map((purchase) => { - return ( - - ); - }) + ? payPurchaseData.data + .filter(isBridgePayment) + .map((purchase) => { + return ( + + ); + }) : new Array(pageSize).fill(0).map((_, i) => ( // biome-ignore lint/suspicious/noArrayIndexKey: ok @@ -119,16 +124,20 @@ export function PaymentHistory(props: { ); } -function getCSVData(data: Payment[]) { +function isBridgePayment(purchase: Payment): purchase is BridgePayment { + return purchase.type !== "onramp"; +} + +function getCSVData(data: BridgePayment[]) { const header = ["Type", "Bought", "Paid", "Status", "Recipient", "Date"]; const rows: string[][] = data.map((purchase) => { const toAmount = toTokens( - purchase.destinationAmount, + BigInt(purchase.destinationAmount), purchase.destinationToken.decimals, ); const fromAmount = toTokens( - purchase.originAmount, + BigInt(purchase.originAmount), purchase.originToken.decimals, ); const type = (() => { diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentsTableRow.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentsTableRow.tsx index 25fd54e0d6d..160d4c63a55 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentsTableRow.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/PaymentsTableRow.tsx @@ -1,20 +1,23 @@ import { format } from "date-fns"; import { type ThirdwebClient, toTokens } from "thirdweb"; -import type { Payment } from "@/api/universal-bridge/developer"; +import type { BridgePayment } from "@/api/universal-bridge/developer"; import { WalletAddress } from "@/components/blocks/wallet-address"; import { Badge } from "@/components/ui/badge"; import { cn } from "@/lib/utils"; import { TableData } from "./common"; import { formatTokenAmount } from "./format"; -export function TableRow(props: { purchase: Payment; client: ThirdwebClient }) { +export function TableRow(props: { + purchase: BridgePayment; + client: ThirdwebClient; +}) { const { purchase } = props; const originAmount = toTokens( - purchase.originAmount, + BigInt(purchase.originAmount), purchase.originToken.decimals, ); const destinationAmount = toTokens( - purchase.destinationAmount, + BigInt(purchase.destinationAmount), purchase.destinationToken.decimals, ); const type = (() => { diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx index 68b16219786..4e0a7f9b7bc 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/links/components/PaymentLinksTable.client.tsx @@ -192,7 +192,7 @@ function PaymentLinksTableInner(props: { clientId: string; teamId: string }) { acc + Number( toTokens( - curr.destinationAmount, + BigInt(curr.destinationAmount), curr.destinationToken.decimals, ), ),