Skip to content

Commit 98e590d

Browse files
committed
Use useTokenFiatRates
1 parent 458c305 commit 98e590d

4 files changed

Lines changed: 190 additions & 261 deletions

File tree

app/components/Views/confirmations/hooks/pay/useAssetFiatFormatter.test.ts

Lines changed: 36 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@ import { useSelector } from 'react-redux';
33

44
import { useAssetFiatFormatter } from './useAssetFiatFormatter';
55
import { useTransactionPayCurrency } from './useTransactionPayCurrency';
6-
import {
7-
selectCurrencyRates,
8-
selectCurrentCurrency,
9-
} from '../../../../../selectors/currencyRateController';
10-
import { selectEvmNetworkConfigurationsByChainId } from '../../../../../selectors/networkController';
6+
import { selectCurrentCurrency } from '../../../../../selectors/currencyRateController';
117
import { getIntlNumberFormatter } from '../../../../../util/intl';
128

139
jest.mock('react-redux', () => ({
@@ -20,11 +16,6 @@ jest.mock('./useTransactionPayCurrency', () => ({
2016

2117
jest.mock('../../../../../selectors/currencyRateController', () => ({
2218
selectCurrentCurrency: jest.fn(),
23-
selectCurrencyRates: jest.fn(),
24-
}));
25-
26-
jest.mock('../../../../../selectors/networkController', () => ({
27-
selectEvmNetworkConfigurationsByChainId: jest.fn(),
2819
}));
2920

3021
jest.mock('../../../../../util/intl', () => ({
@@ -42,19 +33,9 @@ const mockGetIntlNumberFormatter = jest.mocked(getIntlNumberFormatter);
4233

4334
const mockFormatter = { format: jest.fn() };
4435

45-
function buildState({
46-
preferredCurrency = 'usd',
47-
currencyRates = {} as Record<
48-
string,
49-
{ conversionRate?: number; usdConversionRate?: number }
50-
>,
51-
networkConfigs = {} as Record<string, { nativeCurrency: string }>,
52-
} = {}) {
36+
function buildState({ preferredCurrency = 'usd' } = {}) {
5337
mockUseSelector.mockImplementation((selector) => {
5438
if (selector === selectCurrentCurrency) return preferredCurrency;
55-
if (selector === selectCurrencyRates) return currencyRates;
56-
if (selector === selectEvmNetworkConfigurationsByChainId)
57-
return networkConfigs;
5839
return undefined;
5940
});
6041
}
@@ -69,212 +50,94 @@ describe('useAssetFiatFormatter', () => {
6950
mockFormatter.format.mockImplementation((n) => `formatted:${String(n)}`);
7051
});
7152

72-
describe('outside pay flow', () => {
73-
it('formats using the preferred currency', () => {
53+
describe('fiatCurrency selection', () => {
54+
it('uses the preferred currency outside pay flow', () => {
7455
buildState({ preferredCurrency: 'eur' });
7556

7657
const { result } = renderHook(() => useAssetFiatFormatter());
77-
const output = result.current.format('100', '0x1');
7858

79-
expect(mockGetIntlNumberFormatter).toHaveBeenCalledWith(
80-
'en-US',
81-
expect.objectContaining({ style: 'currency', currency: 'eur' }),
82-
);
83-
expect(mockFormatter.format).toHaveBeenCalledWith('100');
84-
expect(output).toBe('formatted:100');
59+
expect(result.current.fiatCurrency).toBe('eur');
8560
});
8661

87-
it('exposes the fiatCurrency being used', () => {
62+
it('uses the pay currency when useTransactionPayCurrency returns a value', () => {
8863
buildState({ preferredCurrency: 'eur' });
64+
mockUseTransactionPayCurrency.mockReturnValue('USD');
8965

9066
const { result } = renderHook(() => useAssetFiatFormatter());
91-
expect(result.current.fiatCurrency).toBe('eur');
67+
68+
expect(result.current.fiatCurrency).toBe('USD');
9269
});
70+
});
9371

94-
it('uses minimumFractionDigits=0 for integer amounts', () => {
72+
describe('format', () => {
73+
it('formats a numeric amount using Intl currency', () => {
9574
buildState({ preferredCurrency: 'eur' });
9675

97-
renderHook(() => useAssetFiatFormatter()).result.current.format(
98-
'100',
99-
'0x1',
100-
);
76+
const { result } = renderHook(() => useAssetFiatFormatter());
77+
const output = result.current.format('100');
10178

10279
expect(mockGetIntlNumberFormatter).toHaveBeenCalledWith(
10380
'en-US',
104-
expect.objectContaining({ minimumFractionDigits: 0 }),
81+
expect.objectContaining({ style: 'currency', currency: 'eur' }),
10582
);
83+
expect(mockFormatter.format).toHaveBeenCalledWith('100');
84+
expect(output).toBe('formatted:100');
10685
});
10786

108-
it('uses minimumFractionDigits=2 for non-integer amounts', () => {
87+
it('formats with the pay currency when in pay flow', () => {
10988
buildState({ preferredCurrency: 'eur' });
89+
mockUseTransactionPayCurrency.mockReturnValue('USD');
11090

111-
renderHook(() => useAssetFiatFormatter()).result.current.format(
112-
'100.5',
113-
'0x1',
114-
);
91+
const { result } = renderHook(() => useAssetFiatFormatter());
92+
result.current.format('110');
11593

11694
expect(mockGetIntlNumberFormatter).toHaveBeenCalledWith(
11795
'en-US',
118-
expect.objectContaining({ minimumFractionDigits: 2 }),
96+
expect.objectContaining({ currency: 'USD' }),
11997
);
98+
expect(mockFormatter.format).toHaveBeenCalledWith('110');
12099
});
121100

122-
it('treats undefined/null balances as zero', () => {
101+
it('uses minimumFractionDigits=0 for integer amounts', () => {
123102
buildState({ preferredCurrency: 'eur' });
124103

125-
renderHook(() => useAssetFiatFormatter()).result.current.format(
126-
undefined,
127-
'0x1',
128-
);
129-
130-
expect(mockFormatter.format).toHaveBeenCalledWith('0');
131-
});
132-
});
133-
134-
describe('pay flow (USD forced, preferred is EUR)', () => {
135-
const eurUsdRates = {
136-
ETH: { conversionRate: 2000, usdConversionRate: 2200 },
137-
};
138-
const ethChainConfig = { '0x1': { nativeCurrency: 'ETH' } };
139-
140-
beforeEach(() => {
141-
mockUseTransactionPayCurrency.mockReturnValue('USD');
142-
});
143-
144-
it('re-scales the amount by usdRate/preferredRate', () => {
145-
buildState({
146-
preferredCurrency: 'eur',
147-
currencyRates: eurUsdRates,
148-
networkConfigs: ethChainConfig,
149-
});
150-
151-
renderHook(() => useAssetFiatFormatter()).result.current.format(
152-
'100',
153-
'0x1',
154-
);
104+
renderHook(() => useAssetFiatFormatter()).result.current.format('100');
155105

156-
// 100 EUR * (2200 USD/ETH / 2000 EUR/ETH) = 110 USD
157-
expect(mockFormatter.format).toHaveBeenCalledWith('110');
158106
expect(mockGetIntlNumberFormatter).toHaveBeenCalledWith(
159107
'en-US',
160-
expect.objectContaining({ currency: 'USD' }),
108+
expect.objectContaining({ minimumFractionDigits: 0 }),
161109
);
162110
});
163111

164-
it('exposes fiatCurrency as USD', () => {
165-
buildState({
166-
preferredCurrency: 'eur',
167-
currencyRates: eurUsdRates,
168-
networkConfigs: ethChainConfig,
169-
});
170-
171-
const { result } = renderHook(() => useAssetFiatFormatter());
172-
expect(result.current.fiatCurrency).toBe('USD');
173-
});
174-
175-
it('returns undefined when usdConversionRate is missing', () => {
176-
buildState({
177-
preferredCurrency: 'eur',
178-
currencyRates: { ETH: { conversionRate: 2000 } },
179-
networkConfigs: ethChainConfig,
180-
});
181-
182-
const { result } = renderHook(() => useAssetFiatFormatter());
183-
const output = result.current.format('100', '0x1');
184-
185-
expect(output).toBeUndefined();
186-
expect(mockFormatter.format).not.toHaveBeenCalled();
187-
});
188-
189-
it('returns undefined when preferred conversionRate is missing', () => {
190-
buildState({
191-
preferredCurrency: 'eur',
192-
currencyRates: { ETH: { usdConversionRate: 2200 } },
193-
networkConfigs: ethChainConfig,
194-
});
195-
196-
const { result } = renderHook(() => useAssetFiatFormatter());
197-
const output = result.current.format('100', '0x1');
198-
199-
expect(output).toBeUndefined();
200-
expect(mockFormatter.format).not.toHaveBeenCalled();
201-
});
202-
203-
it('returns undefined when chain has no EVM network config', () => {
204-
buildState({
205-
preferredCurrency: 'eur',
206-
currencyRates: eurUsdRates,
207-
networkConfigs: {},
208-
});
209-
210-
const { result } = renderHook(() => useAssetFiatFormatter());
211-
const output = result.current.format('100', '0x1');
212-
213-
expect(output).toBeUndefined();
214-
expect(mockFormatter.format).not.toHaveBeenCalled();
215-
});
216-
217-
it('formats zero even when rates or chain config are missing', () => {
218-
buildState({
219-
preferredCurrency: 'eur',
220-
currencyRates: {},
221-
networkConfigs: {},
222-
});
112+
it('uses minimumFractionDigits=2 for non-integer amounts', () => {
113+
buildState({ preferredCurrency: 'eur' });
223114

224-
const { result } = renderHook(() => useAssetFiatFormatter());
225-
const output = result.current.format(0, undefined);
115+
renderHook(() => useAssetFiatFormatter()).result.current.format('100.5');
226116

227-
expect(output).toBe('formatted:0');
228117
expect(mockGetIntlNumberFormatter).toHaveBeenCalledWith(
229118
'en-US',
230-
expect.objectContaining({ currency: 'USD' }),
231-
);
232-
});
233-
});
234-
235-
describe('pay flow (USD forced, preferred is already USD)', () => {
236-
it('does not re-scale (identity), so numeric value is unchanged', () => {
237-
mockUseTransactionPayCurrency.mockReturnValue('USD');
238-
buildState({
239-
preferredCurrency: 'usd',
240-
currencyRates: {
241-
ETH: { conversionRate: 2200, usdConversionRate: 2200 },
242-
},
243-
networkConfigs: { '0x1': { nativeCurrency: 'ETH' } },
244-
});
245-
246-
renderHook(() => useAssetFiatFormatter()).result.current.format(
247-
'100',
248-
'0x1',
119+
expect.objectContaining({ minimumFractionDigits: 2 }),
249120
);
250-
251-
expect(mockFormatter.format).toHaveBeenCalledWith('100');
252121
});
253122

254-
it('still formats when currency rates are missing (no conversion needed)', () => {
255-
mockUseTransactionPayCurrency.mockReturnValue('USD');
256-
buildState({
257-
preferredCurrency: 'usd',
258-
currencyRates: {},
259-
networkConfigs: {},
260-
});
123+
it('returns undefined when input is undefined', () => {
124+
buildState({ preferredCurrency: 'eur' });
261125

262126
const { result } = renderHook(() => useAssetFiatFormatter());
263-
const output = result.current.format('100', '0x1');
127+
const output = result.current.format(undefined);
264128

265-
expect(output).toBe('formatted:100');
129+
expect(output).toBeUndefined();
130+
expect(mockFormatter.format).not.toHaveBeenCalled();
266131
});
267-
});
268132

269-
describe('formatter error fallback', () => {
270133
it('falls back to `${value} ${currency}` when Intl throws', () => {
271134
buildState({ preferredCurrency: 'eur' });
272135
mockGetIntlNumberFormatter.mockImplementation(() => {
273136
throw new Error('boom');
274137
});
275138

276139
const { result } = renderHook(() => useAssetFiatFormatter());
277-
const output = result.current.format('42', '0x1');
140+
const output = result.current.format('42');
278141

279142
expect(output).toBe('42 eur');
280143
});

0 commit comments

Comments
 (0)