diff --git a/.changeset/swap-success-actual-values.md b/.changeset/swap-success-actual-values.md new file mode 100644 index 000000000..95fd3c923 --- /dev/null +++ b/.changeset/swap-success-actual-values.md @@ -0,0 +1,12 @@ +--- +'@relayprotocol/relay-kit-ui': patch +--- + +Fix the swap completion view showing a provisional token and amount as +received. Destination `actual` values from `GET /requests/v3` are now only +displayed once the request status is `success` — before that, the quoted +output token and amount are shown instead of intermediate route values (e.g. +an origin swap's USDC output on a route that delivers a different token). The +transaction modal also keeps polling the request until it reaches a terminal +status (`success`, `failure`, or `refund`) so the final received amount +replaces the quoted one. diff --git a/packages/ui/src/components/common/TransactionModal/TransactionModalRenderer.tsx b/packages/ui/src/components/common/TransactionModal/TransactionModalRenderer.tsx index 7d99a8229..44e711d9e 100644 --- a/packages/ui/src/components/common/TransactionModal/TransactionModalRenderer.tsx +++ b/packages/ui/src/components/common/TransactionModal/TransactionModalRenderer.tsx @@ -247,6 +247,15 @@ export const TransactionModalRenderer: FC = ({ if (!transaction) { return 2500 } + // Keep polling until the request reaches a terminal status so the + // success view can replace quoted values with the final actual ones + const isTerminalStatus = + transaction.status === 'success' || + transaction.status === 'failure' || + transaction.status === 'refund' + if (!isTerminalStatus) { + return 2500 + } // If this is a refund but outTxs is not populated yet, keep polling const isRefund = transaction.status === 'refund' || diff --git a/packages/ui/src/utils/relayTransaction.ts b/packages/ui/src/utils/relayTransaction.ts index 842e9a71f..fea35740f 100644 --- a/packages/ui/src/utils/relayTransaction.ts +++ b/packages/ui/src/utils/relayTransaction.ts @@ -14,6 +14,12 @@ type RouteAmount = NonNullable< * - currencyIn: the token deposited on the origin side. * - currencyOut: the token received, preferring the destination output and * falling back to the origin output (e.g. same-chain swaps). + * + * `route.actual` is populated progressively while a request is in flight, so + * before the request status is `success` it can hold provisional values (e.g. + * the intermediate origin swap output). Output-side actual values are only + * used once the request status is `success`; until then the quoted values are + * returned so the UI never presents a provisional token/amount as received. */ export const getRequestCurrencies = ( transaction?: RelayTransaction | null @@ -29,13 +35,16 @@ export const getRequestCurrencies = ( const currencyIn = actual?.origin?.inputCurrency ?? quoted?.origin?.inputCurrency + // Only trust output-side actual values once the request has succeeded + const settledActual = transaction?.status === 'success' ? actual : undefined + const currencyOut = - actual?.destination?.outputCurrency ?? + settledActual?.destination?.outputCurrency ?? quoted?.destination?.outputCurrency ?? - actual?.origin?.outputCurrency ?? + settledActual?.origin?.outputCurrency ?? quoted?.origin?.outputCurrency - const currencyGasTopup = actual?.destination?.currencyGasTopup + const currencyGasTopup = settledActual?.destination?.currencyGasTopup return { currencyIn, currencyOut, currencyGasTopup } }