sdk: add generic external payment flow - #69
Conversation
| const sourceAmountUnits = formatNavSourceAmountUnits( | ||
| amount, | ||
| sourceAmount, | ||
| ); |
There was a problem hiding this comment.
🟡 Malformed backend amount precision can leave the payment screen stuck loading forever
The amount is formatted (formatNavSourceAmountUnits at packages/sdk/src/web/hooks/useSessionNav.ts:310-313) before the error-handling block starts, so if the backend describes the amount with an unsupported number of decimal places, preparing the payment throws and the waiting screen never shows an error.
Impact: In that case the user is left staring at an endless loading spinner with no error message and no way to recover.
Why the throw escapes error handling
formatNavSourceAmountUnits throws "invalid external payment amount" when decimals is non-integer, negative, or > 20 (packages/sdk/src/web/api/navTree.ts:213-220). In fetchExternalPayment this call sits at lines 310-313, before the try at packages/sdk/src/web/hooks/useSessionNav.ts:332. The caller handleNavigate (required>0 path) first pushes an external-payment stack entry with paymentUrl undefined and then calls fetchExternalPayment fire-and-forget; the thrown error becomes an unhandled rejection and the entry stays isLoading with no error set, so the catch block that would surface the error at lines ~372-395 is never reached. In handleAmountContinue the same function is also called at lines 904-907 while building amountContext, which would throw synchronously inside the click handler. This only triggers on malformed backend decimals, hence non-severe.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
{ type: "external", id: "CashApp" | "Revolut", sourceAmount }payment-method contract and exportExternalPaymentMethodRequestexternalPaymentthe canonical handoff response, with decimal-string money for source amounts, destination estimates, and feesHostedPaymentnavigation kind withExternalPayment; hosted remains an implementation strategy, not a payment-method categoryExchangeIdbackward compatible but reject Revolut as an exchangeCompatibility
externalValidation
pnpm test