Skip to content

Commit b0a3192

Browse files
committed
feat(LIVE-24415): add formatting to wallet quotes
add flexible formatting to swap wallet quote fetching
1 parent 28ecc98 commit b0a3192

24 files changed

Lines changed: 1797 additions & 29 deletions

File tree

.changeset/tough-pumas-repeat.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"@ledgerhq/wallet-api-exchange-module": minor
3+
"@ledgerhq/live-common": minor
4+
"ledger-live-desktop": minor
5+
"live-mobile": minor
6+
---
7+
8+
Centralize swap-quote formatting on the wallet side of `custom.exchange.getQuotes`. Each returned `Quote` now carries an optional `formatted: FormattedQuoteValues`, where every field is a `FormattedNumber` triplet (`numberValue` / `withPrefix` / `withSuffix`) — letting live-app consumers display locale-aware crypto, fiat, rate, and slippage values without owning the formatting logic.
9+
10+
Breaking wire change: `QuotesInput.counterValueCurrency` has been removed. The wallet now sources locale and counter-value currency from its Redux store and threads them into `getQuotes` via the `handlers({ locale, counterValueCurrency, ... })` factory, so the live app no longer needs to pass them on the wire.

apps/ledger-live-desktop/src/renderer/components/WebPTXPlayer/CustomHandlers.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ import { useStake } from "LLD/hooks/useStake";
3535
import { StakeFlowProps } from "~/renderer/screens/stake";
3636
import { useNavigate } from "react-router";
3737
import { walletSelector } from "~/renderer/reducers/wallet";
38+
import {
39+
counterValueCurrencySelector,
40+
localeSelector,
41+
} from "~/renderer/reducers/settings";
3842
import { objectToURLSearchParams } from "@ledgerhq/live-common/wallet-api/helpers";
3943
import { useRemoteLiveAppContext } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index";
4044
import { useLocalLiveAppContext } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
@@ -52,6 +56,8 @@ export function usePTXCustomHandlers(manifest: WebviewProps["manifest"], account
5256
const navigate = useNavigate();
5357
const { isEnabled } = useWalletFeaturesConfig("desktop");
5458
const walletState = useSelector(walletSelector);
59+
const locale = useSelector(localeSelector);
60+
const counterValueCurrency = useSelector(counterValueCurrencySelector);
5561
const { state: liveAppRegistryState } = useRemoteLiveAppContext();
5662
const { state: localLiveAppState } = useLocalLiveAppContext();
5763
const syncAccountsById = useSyncAccountsById();
@@ -171,6 +177,8 @@ export function usePTXCustomHandlers(manifest: WebviewProps["manifest"], account
171177
tracking,
172178
manifest,
173179
flags,
180+
locale,
181+
counterValueCurrency: counterValueCurrency.ticker,
174182
uiHooks: {
175183
"custom.exchange.start": ({ exchangeParams, onSuccess, onCancel }) => {
176184
dispatch(
@@ -392,6 +400,8 @@ export function usePTXCustomHandlers(manifest: WebviewProps["manifest"], account
392400
tracking,
393401
manifest,
394402
flags,
403+
locale,
404+
counterValueCurrency,
395405
dispatch,
396406
setDrawer,
397407
navigate,

apps/ledger-live-mobile/src/components/WebPTXPlayer/CustomHandlers.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ import type { InfoDialogParams } from "@ledgerhq/live-common/wallet-api/validati
4545
import { makeSetEarnInfoBottomSheetAction, makeSetEarnMenuBottomSheetAction } from "~/actions/earn";
4646
import { createOpenActionDialogHandler } from "./actionDialogStore";
4747
import type { Dispatch } from "redux";
48-
import { useDispatch } from "~/context/hooks";
48+
import { useDispatch, useSelector } from "~/context/hooks";
49+
import { counterValueCurrencySelector, localeSelector } from "~/reducers/settings";
4950
import { ExchangeSwap } from "@ledgerhq/live-common/exchange/swap/types";
5051
import { useWalletFeaturesConfig } from "@ledgerhq/live-common/featureFlags/index";
5152

@@ -78,6 +79,8 @@ export function useCustomExchangeHandlers({
7879
const dispatch = useDispatch();
7980
const { isEnabled } = useWalletFeaturesConfig("mobile");
8081
const flags = useMemo(() => ({ wallet40Ux: isEnabled }), [isEnabled]);
82+
const locale = useSelector(localeSelector);
83+
const counterValueCurrency = useSelector(counterValueCurrencySelector);
8184
const { state: liveAppRegistryState } = useRemoteLiveAppContext();
8285
const { state: localLiveAppState } = useLocalLiveAppContext();
8386

@@ -302,6 +305,8 @@ export function useCustomExchangeHandlers({
302305
tracking,
303306
manifest,
304307
flags,
308+
locale,
309+
counterValueCurrency: counterValueCurrency.ticker,
305310
uiHooks: {
306311
"custom.exchange.start": ({ exchangeParams, onSuccess, onCancel }) => {
307312
const promiseId = `start-${Date.now()}`;
@@ -494,6 +499,8 @@ export function useCustomExchangeHandlers({
494499
onCompleteResult,
495500
handleLoaderDrawer,
496501
flags,
502+
locale,
503+
counterValueCurrency,
497504
sendAppReady,
498505
syncAccountById,
499506
tracking,

apps/wallet-cli/src/commands/swap/quote.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ export default defineCommand({
107107
providers: DEFAULT_PROVIDERS,
108108
data: {
109109
amount: flags.amount,
110-
counterValueCurrency: "USD",
111110
uniswapOrderType: "classic",
112111
sendCurrencyId: flags.from,
113112
receiveCurrencyId: flags.to,
@@ -117,7 +116,7 @@ export default defineCommand({
117116
receiveAccountId: "",
118117
},
119118
},
120-
{ accounts: [], spotPrices: {} },
119+
{ accounts: [], spotPrices: {}, locale: "en", counterValueCurrency: "USD" },
121120
);
122121

123122
if (result.quotes.length === 0 && result.errors.length > 0) {

libs/exchange-module/src/types.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ export type QuotesInput = {
122122
receiveAddress: string;
123123
sendCurrencyId: string;
124124
receiveCurrencyId: string;
125-
counterValueCurrency: string;
126125
networkFeesCurrencyId?: string;
127126
slippage?: number;
128127
uniswapOrderType?: UniswapOrderType;
@@ -286,6 +285,23 @@ export type QuoteDetails = {
286285
approvalNetworkFee?: QuoteApprovalNetworkFee;
287286
};
288287

288+
export type FormattedNumber = {
289+
numberValue: string;
290+
withPrefix: string;
291+
withSuffix: string;
292+
};
293+
294+
export type FormattedQuoteValues = {
295+
sendAmount: FormattedNumber;
296+
sendAmountCountervalue: FormattedNumber;
297+
receiveAmount: FormattedNumber;
298+
receiveAmountCountervalue: FormattedNumber;
299+
networkFee: FormattedNumber;
300+
networkFeeCountervalue: FormattedNumber;
301+
rate: FormattedNumber;
302+
slippage: FormattedNumber;
303+
};
304+
289305
export type Quote = {
290306
id?: string;
291307
key: string;
@@ -294,6 +310,12 @@ export type Quote = {
294310
quoteDetails: QuoteDetails;
295311
warning: QuoteWarning | null;
296312
error: QuoteError | null;
313+
/**
314+
* Optional wallet-formatted display strings. Additive field:
315+
* producers that cannot format (no locale / counter-value fiat context)
316+
* omit it, and consumers must handle `undefined`.
317+
*/
318+
formatted?: FormattedQuoteValues;
297319
};
298320

299321
/** Error rows returned next to quotes (swap API error objects). */
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const DEFAULT_MAX_DECIMALS = 8;
2+
3+
export const COUNTERVALUE_MAX_DECIMALS = 7;

0 commit comments

Comments
 (0)