@b3dotfun/sdk 0.0.58-alpha.2 → 0.0.58-test.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/global-account/react/hooks/useWagmiConfig.d.ts +1 -441
- package/dist/cjs/global-account/react/hooks/useWagmiConfig.js +0 -2
- package/dist/cjs/shared/react/components/CurrencySelector.js +3 -8
- package/dist/cjs/shared/react/components/FormattedCurrency.d.ts +3 -3
- package/dist/cjs/shared/react/components/FormattedCurrency.js +26 -31
- package/dist/cjs/shared/react/hooks/useCurrencyConversion.d.ts +5 -8
- package/dist/cjs/shared/react/hooks/useCurrencyConversion.js +94 -153
- package/dist/cjs/shared/react/stores/currencyStore.d.ts +8 -83
- package/dist/cjs/shared/react/stores/currencyStore.js +5 -147
- package/dist/esm/global-account/react/hooks/useWagmiConfig.d.ts +1 -441
- package/dist/esm/global-account/react/hooks/useWagmiConfig.js +0 -2
- package/dist/esm/shared/react/components/CurrencySelector.js +5 -10
- package/dist/esm/shared/react/components/FormattedCurrency.d.ts +3 -3
- package/dist/esm/shared/react/components/FormattedCurrency.js +26 -31
- package/dist/esm/shared/react/hooks/useCurrencyConversion.d.ts +5 -8
- package/dist/esm/shared/react/hooks/useCurrencyConversion.js +95 -154
- package/dist/esm/shared/react/stores/currencyStore.d.ts +8 -83
- package/dist/esm/shared/react/stores/currencyStore.js +5 -143
- package/dist/types/global-account/react/hooks/useWagmiConfig.d.ts +1 -441
- package/dist/types/shared/react/components/FormattedCurrency.d.ts +3 -3
- package/dist/types/shared/react/hooks/useCurrencyConversion.d.ts +5 -8
- package/dist/types/shared/react/stores/currencyStore.d.ts +8 -83
- package/package.json +8 -4
- package/src/global-account/react/hooks/useWagmiConfig.tsx +0 -2
- package/src/shared/react/components/CurrencySelector.tsx +5 -36
- package/src/shared/react/components/FormattedCurrency.tsx +30 -36
- package/src/shared/react/hooks/__tests__/useCurrencyConversion.test.ts +14 -14
- package/src/shared/react/hooks/useCurrencyConversion.ts +96 -163
- package/src/shared/react/stores/currencyStore.ts +10 -216
|
@@ -40,10 +40,8 @@ async function fetchAllExchangeRates(baseCurrency) {
|
|
|
40
40
|
function useCurrencyConversion() {
|
|
41
41
|
const selectedCurrency = (0, currencyStore_1.useCurrencyStore)(state => state.selectedCurrency);
|
|
42
42
|
const baseCurrency = (0, currencyStore_1.useCurrencyStore)(state => state.baseCurrency);
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
// Fetch all exchange rates for the base currency from Coinbase API
|
|
46
|
-
const { data: apiExchangeRates } = (0, react_query_1.useQuery)({
|
|
43
|
+
// Fetch all exchange rates for the base currency
|
|
44
|
+
const { data: exchangeRates } = (0, react_query_1.useQuery)({
|
|
47
45
|
queryKey: ["exchangeRates", baseCurrency],
|
|
48
46
|
queryFn: () => fetchAllExchangeRates(baseCurrency),
|
|
49
47
|
refetchInterval: REFETCH_INTERVAL_MS,
|
|
@@ -51,208 +49,155 @@ function useCurrencyConversion() {
|
|
|
51
49
|
retry: 3,
|
|
52
50
|
retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, REFETCH_INTERVAL_MS),
|
|
53
51
|
});
|
|
52
|
+
// Extract specific rates from the full rates object
|
|
53
|
+
const exchangeRate = exchangeRates?.[selectedCurrency];
|
|
54
|
+
const usdRate = exchangeRates?.["USD"];
|
|
54
55
|
/**
|
|
55
|
-
*
|
|
56
|
-
* Supports chaining through base currency for custom currencies.
|
|
56
|
+
* Formats a numeric value as a currency string with proper conversion and formatting.
|
|
57
57
|
*
|
|
58
|
-
*
|
|
59
|
-
* -
|
|
60
|
-
* -
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return 1;
|
|
66
|
-
// 1. Check direct custom exchange rate first
|
|
67
|
-
const directCustomRate = getCustomExchangeRate(from, to);
|
|
68
|
-
if (directCustomRate !== undefined) {
|
|
69
|
-
return directCustomRate;
|
|
70
|
-
}
|
|
71
|
-
// 2. Check direct API rate (from base currency)
|
|
72
|
-
if (from === baseCurrency && apiExchangeRates) {
|
|
73
|
-
return apiExchangeRates[to];
|
|
74
|
-
}
|
|
75
|
-
// 3. Try to chain through base currency using custom rates
|
|
76
|
-
// e.g., WIN → B3 → USD (where WIN→B3 is custom, B3→USD is API)
|
|
77
|
-
const customFromToBase = getCustomExchangeRate(from, baseCurrency);
|
|
78
|
-
if (customFromToBase !== undefined) {
|
|
79
|
-
// We have a custom rate from 'from' to base
|
|
80
|
-
// Now get rate from base to 'to'
|
|
81
|
-
const baseToTo = apiExchangeRates?.[to] ?? getCustomExchangeRate(baseCurrency, to);
|
|
82
|
-
if (baseToTo !== undefined) {
|
|
83
|
-
return customFromToBase * baseToTo;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
// 4. Try reverse: chain from base currency through custom rate
|
|
87
|
-
// e.g., USD → B3 → WIN (where B3→WIN is custom)
|
|
88
|
-
const customBaseToTo = getCustomExchangeRate(baseCurrency, to);
|
|
89
|
-
if (customBaseToTo !== undefined && apiExchangeRates) {
|
|
90
|
-
// We have a custom rate from base to 'to'
|
|
91
|
-
// Now get rate from 'from' to base
|
|
92
|
-
const fromToBase = apiExchangeRates[from];
|
|
93
|
-
if (fromToBase !== undefined && fromToBase !== 0) {
|
|
94
|
-
return fromToBase * customBaseToTo;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// 5. Fall back to pure API conversion through base
|
|
98
|
-
// e.g., EUR to GBP = (EUR to B3) * (B3 to GBP)
|
|
99
|
-
if (apiExchangeRates) {
|
|
100
|
-
const fromToBase = apiExchangeRates[from];
|
|
101
|
-
const baseToTo = apiExchangeRates[to];
|
|
102
|
-
if (fromToBase && baseToTo && fromToBase !== 0) {
|
|
103
|
-
return baseToTo / fromToBase;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return undefined;
|
|
107
|
-
};
|
|
108
|
-
// Extract specific rates
|
|
109
|
-
const exchangeRate = getExchangeRate(baseCurrency, selectedCurrency);
|
|
110
|
-
/**
|
|
111
|
-
* Formats a numeric value as a currency string with automatic conversion.
|
|
112
|
-
*
|
|
113
|
-
* New behavior:
|
|
114
|
-
* - Takes the SOURCE currency (what the value is in) as a required parameter
|
|
115
|
-
* - Automatically converts from source → display currency (selected in picker)
|
|
116
|
-
* - Supports multi-hop conversions (e.g., WIN → B3 → USD)
|
|
117
|
-
* - Applies currency-specific formatting rules to the TARGET currency
|
|
58
|
+
* Behavior:
|
|
59
|
+
* - When exchange rate is unavailable, displays value in base currency
|
|
60
|
+
* - Applies currency-specific formatting rules:
|
|
61
|
+
* - JPY/KRW: No decimal places
|
|
62
|
+
* - ETH/SOL: 6 significant digits with subscript notation for small values
|
|
63
|
+
* - Fiat (USD/EUR/GBP/CAD/AUD): 2 decimal places minimum for values < 1000
|
|
64
|
+
* - Handles symbol positioning (prefix for fiat, suffix for crypto)
|
|
118
65
|
*
|
|
119
|
-
* @param value - The numeric value to format
|
|
120
|
-
* @param sourceCurrency - The currency the value is currently in (e.g., "WIN", "B3", "USD")
|
|
66
|
+
* @param value - The numeric value to format (in base currency)
|
|
121
67
|
* @param options - Optional formatting overrides
|
|
122
|
-
* @param options.decimals - Override number of decimal places
|
|
68
|
+
* @param options.decimals - Override number of decimal places
|
|
69
|
+
* @param options.currency - Override currency (bypasses conversion)
|
|
123
70
|
* @returns Formatted currency string with appropriate symbol and decimal places
|
|
124
71
|
*
|
|
125
72
|
* @example
|
|
126
73
|
* ```tsx
|
|
127
|
-
* //
|
|
128
|
-
* formatCurrencyValue(
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* formatCurrencyValue(100, "B3") // Returns "100 B3"
|
|
132
|
-
*
|
|
133
|
-
* // Value is 50 USD, user has EUR selected
|
|
134
|
-
* formatCurrencyValue(50, "USD") // Returns "€45.50" (converts USD→EUR)
|
|
74
|
+
* formatCurrencyValue(100) // Returns "$100.00" if USD is selected
|
|
75
|
+
* formatCurrencyValue(0.0001) // Returns "0.0₄1 ETH" if ETH is selected
|
|
76
|
+
* formatCurrencyValue(1500) // Returns "¥1,500" if JPY is selected
|
|
77
|
+
* formatCurrencyValue(100, { decimals: 4, currency: "ETH" }) // Returns "100.0000 ETH"
|
|
135
78
|
* ```
|
|
136
79
|
*/
|
|
137
|
-
const formatCurrencyValue = (value,
|
|
80
|
+
const formatCurrencyValue = (value, options) => {
|
|
81
|
+
const overrideCurrency = options?.currency;
|
|
138
82
|
const overrideDecimals = options?.decimals;
|
|
139
|
-
//
|
|
140
|
-
if (
|
|
141
|
-
const
|
|
142
|
-
const decimalsToUse = overrideDecimals !== undefined ? overrideDecimals : customMetadata?.decimals;
|
|
83
|
+
// Custom currency provided - bypass conversion and use simple formatting
|
|
84
|
+
if (overrideCurrency) {
|
|
85
|
+
const decimalsToUse = overrideDecimals !== undefined ? overrideDecimals : overrideCurrency === "B3" ? 0 : 2;
|
|
143
86
|
const formatted = (0, number_1.formatDisplayNumber)(value, {
|
|
144
87
|
fractionDigits: decimalsToUse,
|
|
145
|
-
|
|
146
|
-
showSubscripts: customMetadata?.showSubscripts ?? false,
|
|
88
|
+
showSubscripts: false,
|
|
147
89
|
});
|
|
148
|
-
|
|
149
|
-
const usePrefix = customMetadata?.prefixSymbol ?? ["USD", "EUR", "GBP", "CAD", "AUD"].includes(sourceCurrency);
|
|
150
|
-
return usePrefix ? `${symbol}${formatted}` : `${formatted} ${symbol}`;
|
|
90
|
+
return `${formatted} ${overrideCurrency}`;
|
|
151
91
|
}
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
// If no conversion rate available, display in source currency
|
|
155
|
-
if (conversionRate === undefined) {
|
|
156
|
-
const customMetadata = (0, currencyStore_1.getCurrencyMetadata)(sourceCurrency);
|
|
92
|
+
// Custom decimals for base currency without conversion
|
|
93
|
+
if (overrideDecimals !== undefined && selectedCurrency === baseCurrency) {
|
|
157
94
|
const formatted = (0, number_1.formatDisplayNumber)(value, {
|
|
158
|
-
significantDigits: 6,
|
|
159
|
-
showSubscripts: customMetadata?.showSubscripts ?? false,
|
|
160
|
-
});
|
|
161
|
-
const symbol = (0, currencyStore_1.getCurrencySymbol)(sourceCurrency);
|
|
162
|
-
return `${formatted} ${symbol}`;
|
|
163
|
-
}
|
|
164
|
-
// Convert value
|
|
165
|
-
const convertedValue = value * conversionRate;
|
|
166
|
-
// Get symbol and metadata for display currency
|
|
167
|
-
const symbol = (0, currencyStore_1.getCurrencySymbol)(selectedCurrency);
|
|
168
|
-
const customMetadata = (0, currencyStore_1.getCurrencyMetadata)(selectedCurrency);
|
|
169
|
-
const usePrefix = customMetadata?.prefixSymbol ?? ["USD", "EUR", "GBP", "CAD", "AUD"].includes(selectedCurrency);
|
|
170
|
-
let formatted;
|
|
171
|
-
// Apply formatting based on display currency
|
|
172
|
-
if (overrideDecimals !== undefined) {
|
|
173
|
-
formatted = (0, number_1.formatDisplayNumber)(convertedValue, {
|
|
174
95
|
fractionDigits: overrideDecimals,
|
|
175
96
|
showSubscripts: false,
|
|
176
97
|
});
|
|
98
|
+
return `${formatted} ${baseCurrency}`;
|
|
177
99
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
significantDigits:
|
|
182
|
-
showSubscripts:
|
|
100
|
+
// If showing base currency, no conversion needed
|
|
101
|
+
if (selectedCurrency === baseCurrency || !exchangeRate) {
|
|
102
|
+
const formatted = (0, number_1.formatDisplayNumber)(value, {
|
|
103
|
+
significantDigits: baseCurrency === "B3" ? 6 : 8,
|
|
104
|
+
showSubscripts: true,
|
|
183
105
|
});
|
|
106
|
+
return `${formatted} ${baseCurrency}`;
|
|
184
107
|
}
|
|
185
|
-
|
|
108
|
+
// Convert value using current exchange rate
|
|
109
|
+
const convertedValue = value * exchangeRate;
|
|
110
|
+
const symbol = currencyStore_1.CURRENCY_SYMBOLS[selectedCurrency];
|
|
111
|
+
// Currencies that display symbol before the number (e.g., $100.00)
|
|
112
|
+
const prefixCurrencies = ["USD", "EUR", "GBP", "CAD", "AUD"];
|
|
113
|
+
let formatted;
|
|
114
|
+
if (selectedCurrency === "JPY" || selectedCurrency === "KRW") {
|
|
115
|
+
// Japanese Yen and Korean Won don't use decimal places
|
|
186
116
|
formatted = (0, number_1.formatDisplayNumber)(convertedValue, {
|
|
187
117
|
fractionDigits: 0,
|
|
188
118
|
showSubscripts: false,
|
|
189
119
|
});
|
|
190
120
|
}
|
|
191
121
|
else if (selectedCurrency === "ETH" || selectedCurrency === "SOL") {
|
|
122
|
+
// Crypto currencies use more precision and subscript notation
|
|
123
|
+
// for very small amounts (e.g., 0.0₃45 ETH)
|
|
192
124
|
formatted = (0, number_1.formatDisplayNumber)(convertedValue, {
|
|
193
125
|
significantDigits: 6,
|
|
194
126
|
showSubscripts: true,
|
|
195
127
|
});
|
|
196
128
|
}
|
|
197
129
|
else {
|
|
130
|
+
// Standard fiat currencies (USD, EUR, GBP, CAD, AUD)
|
|
131
|
+
// Use 2 decimal places minimum for amounts under 1000
|
|
198
132
|
formatted = (0, number_1.formatDisplayNumber)(convertedValue, {
|
|
199
133
|
significantDigits: 6,
|
|
200
134
|
fractionDigits: convertedValue < 1000 ? 2 : undefined,
|
|
201
135
|
showSubscripts: true,
|
|
202
136
|
});
|
|
203
137
|
}
|
|
204
|
-
|
|
138
|
+
// Apply currency symbol with correct positioning
|
|
139
|
+
if (prefixCurrencies.includes(selectedCurrency)) {
|
|
140
|
+
return `${symbol}${formatted}`;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
// Suffix currencies: JPY, KRW, ETH, SOL, B3
|
|
144
|
+
return `${formatted} ${symbol}`;
|
|
145
|
+
}
|
|
205
146
|
};
|
|
206
147
|
/**
|
|
207
148
|
* Formats a tooltip value showing the alternate currency representation.
|
|
208
149
|
*
|
|
209
|
-
*
|
|
210
|
-
* -
|
|
211
|
-
* - When displaying
|
|
212
|
-
* -
|
|
150
|
+
* Behavior:
|
|
151
|
+
* - When displaying base currency: Shows USD equivalent
|
|
152
|
+
* - When displaying other currency: Shows base currency equivalent
|
|
153
|
+
* - For custom currencies: Shows appropriate conversion or original value
|
|
213
154
|
*
|
|
214
155
|
* @param value - The numeric value to format
|
|
215
|
-
* @param
|
|
156
|
+
* @param customCurrency - Optional custom currency override
|
|
216
157
|
* @returns Formatted tooltip string
|
|
217
158
|
*
|
|
218
159
|
* @example
|
|
219
160
|
* ```tsx
|
|
220
|
-
* //
|
|
221
|
-
* formatTooltipValue(
|
|
222
|
-
*
|
|
223
|
-
* // Value is 100 B3, displaying as USD
|
|
224
|
-
* formatTooltipValue(100, "B3") // Returns "100 B3"
|
|
161
|
+
* formatTooltipValue(100) // Returns "$150.00 USD" if displaying B3 with rate 1.5
|
|
162
|
+
* formatTooltipValue(100, "ETH") // Returns "100.0000 ETH" if custom currency
|
|
225
163
|
* ```
|
|
226
164
|
*/
|
|
227
|
-
const formatTooltipValue = (value,
|
|
165
|
+
const formatTooltipValue = (value, customCurrency) => {
|
|
166
|
+
const displayCurrency = customCurrency || selectedCurrency;
|
|
228
167
|
const absoluteValue = Math.abs(value);
|
|
229
|
-
//
|
|
230
|
-
if (
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
168
|
+
// Custom currency provided
|
|
169
|
+
if (customCurrency) {
|
|
170
|
+
if (customCurrency === baseCurrency) {
|
|
171
|
+
// Show USD equivalent for base currency using USD rate
|
|
172
|
+
const usdValue = usdRate ? absoluteValue * usdRate : absoluteValue;
|
|
173
|
+
const formatted = (0, number_1.formatDisplayNumber)(usdValue, {
|
|
174
|
+
significantDigits: 6,
|
|
175
|
+
fractionDigits: usdValue < 1000 ? 2 : undefined,
|
|
176
|
+
showSubscripts: true,
|
|
177
|
+
});
|
|
178
|
+
return `$${formatted} USD`;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// Show as-is for other custom currencies
|
|
182
|
+
return `${(0, number_1.formatDisplayNumber)(absoluteValue, { significantDigits: 6 })} ${customCurrency}`;
|
|
183
|
+
}
|
|
237
184
|
}
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const formatted = (0, number_1.formatDisplayNumber)(absoluteValue, {
|
|
185
|
+
// Showing base currency - display USD equivalent
|
|
186
|
+
if (displayCurrency === baseCurrency) {
|
|
187
|
+
const usdValue = usdRate ? absoluteValue * usdRate : absoluteValue;
|
|
188
|
+
const formatted = (0, number_1.formatDisplayNumber)(usdValue, {
|
|
243
189
|
significantDigits: 6,
|
|
244
|
-
|
|
190
|
+
fractionDigits: usdValue < 1000 ? 2 : undefined,
|
|
191
|
+
showSubscripts: true,
|
|
245
192
|
});
|
|
246
|
-
|
|
247
|
-
return `${formatted} ${symbol}`;
|
|
193
|
+
return `$${formatted} USD`;
|
|
248
194
|
}
|
|
249
|
-
|
|
250
|
-
const formatted = (0, number_1.formatDisplayNumber)(
|
|
251
|
-
significantDigits: 6,
|
|
252
|
-
fractionDigits: usdValue < 1000 ? 2 : undefined,
|
|
195
|
+
// Showing other currency - display base currency equivalent
|
|
196
|
+
const formatted = (0, number_1.formatDisplayNumber)(absoluteValue, {
|
|
197
|
+
significantDigits: baseCurrency === "B3" ? 6 : 8,
|
|
253
198
|
showSubscripts: true,
|
|
254
199
|
});
|
|
255
|
-
return
|
|
200
|
+
return `${formatted} ${baseCurrency}`;
|
|
256
201
|
};
|
|
257
202
|
return {
|
|
258
203
|
/** Currently selected display currency */
|
|
@@ -266,12 +211,8 @@ function useCurrencyConversion() {
|
|
|
266
211
|
/** Format a tooltip value showing alternate currency representation */
|
|
267
212
|
formatTooltipValue,
|
|
268
213
|
/** Symbol for the currently selected currency (e.g., "$", "€", "ETH") */
|
|
269
|
-
selectedCurrencySymbol:
|
|
214
|
+
selectedCurrencySymbol: currencyStore_1.CURRENCY_SYMBOLS[selectedCurrency],
|
|
270
215
|
/** Symbol for the base currency */
|
|
271
|
-
baseCurrencySymbol:
|
|
272
|
-
/** Get exchange rate between any two currencies */
|
|
273
|
-
getExchangeRate,
|
|
274
|
-
/** All registered custom currencies */
|
|
275
|
-
customCurrencies,
|
|
216
|
+
baseCurrencySymbol: currencyStore_1.CURRENCY_SYMBOLS[baseCurrency],
|
|
276
217
|
};
|
|
277
218
|
}
|
|
@@ -1,36 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Supported currencies for display and conversion.
|
|
3
3
|
* Includes fiat currencies (USD, EUR, GBP, JPY, CAD, AUD, KRW) and crypto (ETH, SOL, B3).
|
|
4
4
|
*/
|
|
5
5
|
export type SupportedCurrency = "ETH" | "USD" | "EUR" | "GBP" | "JPY" | "CAD" | "AUD" | "B3" | "SOL" | "KRW";
|
|
6
|
-
/**
|
|
7
|
-
* Metadata for a custom currency including display formatting rules.
|
|
8
|
-
*/
|
|
9
|
-
export interface CurrencyMetadata {
|
|
10
|
-
/** The currency code/symbol (e.g., "BTC", "DOGE") */
|
|
11
|
-
code: string;
|
|
12
|
-
/** Display symbol for the currency (e.g., "₿", "Ð") */
|
|
13
|
-
symbol: string;
|
|
14
|
-
/** Human-readable name (e.g., "Bitcoin", "Dogecoin") */
|
|
15
|
-
name: string;
|
|
16
|
-
/** Whether to show symbol before the value (true for $100, false for 100 ETH) */
|
|
17
|
-
prefixSymbol?: boolean;
|
|
18
|
-
/** Number of decimal places to show (undefined uses smart formatting) */
|
|
19
|
-
decimals?: number;
|
|
20
|
-
/** Whether to use subscript notation for small values */
|
|
21
|
-
showSubscripts?: boolean;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Exchange rate between two currencies.
|
|
25
|
-
*/
|
|
26
|
-
export interface ExchangeRate {
|
|
27
|
-
/** Currency code being converted from */
|
|
28
|
-
from: string;
|
|
29
|
-
/** Currency code being converted to */
|
|
30
|
-
to: string;
|
|
31
|
-
/** Exchange rate multiplier (amount_in_to = amount_in_from * rate) */
|
|
32
|
-
rate: number;
|
|
33
|
-
}
|
|
34
6
|
/**
|
|
35
7
|
* Currency symbols used for display formatting.
|
|
36
8
|
* Prefix currencies (USD, EUR, GBP, CAD, AUD) show symbol before the amount.
|
|
@@ -45,51 +17,24 @@ export declare const CURRENCY_NAMES: Record<SupportedCurrency, string>;
|
|
|
45
17
|
* Currency store state interface.
|
|
46
18
|
* @property selectedCurrency - The currency currently selected for display
|
|
47
19
|
* @property baseCurrency - The base currency for conversion (typically B3)
|
|
48
|
-
* @property customCurrencies - Map of custom currency codes to their metadata
|
|
49
|
-
* @property customExchangeRates - Map of "FROM-TO" pairs to exchange rates
|
|
50
20
|
* @property setSelectedCurrency - Update the selected display currency
|
|
51
21
|
* @property setBaseCurrency - Update the base currency for conversions
|
|
52
|
-
* @property addCurrency - Register a new custom currency with metadata
|
|
53
|
-
* @property removeCurrency - Remove a custom currency
|
|
54
|
-
* @property setExchangeRate - Set a custom exchange rate between two currencies
|
|
55
|
-
* @property getExchangeRate - Get exchange rate between two currencies
|
|
56
|
-
* @property getAllCurrencies - Get all available currencies (built-in + custom)
|
|
57
22
|
*/
|
|
58
23
|
interface CurrencyState {
|
|
59
|
-
selectedCurrency:
|
|
60
|
-
baseCurrency:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
setSelectedCurrency: (currency: string) => void;
|
|
64
|
-
setBaseCurrency: (currency: string) => void;
|
|
65
|
-
addCurrency: (metadata: CurrencyMetadata) => void;
|
|
66
|
-
removeCurrency: (code: string) => void;
|
|
67
|
-
setExchangeRate: (from: string, to: string, rate: number) => void;
|
|
68
|
-
getExchangeRate: (from: string, to: string) => number | undefined;
|
|
69
|
-
getAllCurrencies: () => string[];
|
|
24
|
+
selectedCurrency: SupportedCurrency;
|
|
25
|
+
baseCurrency: SupportedCurrency;
|
|
26
|
+
setSelectedCurrency: (currency: SupportedCurrency) => void;
|
|
27
|
+
setBaseCurrency: (currency: SupportedCurrency) => void;
|
|
70
28
|
}
|
|
71
29
|
/**
|
|
72
30
|
* Zustand store for managing currency selection and conversion.
|
|
73
31
|
* Persists user's selected currency preference in localStorage.
|
|
74
|
-
* Supports dynamic currency registration and custom exchange rates.
|
|
75
32
|
*
|
|
76
33
|
* @example
|
|
77
34
|
* ```tsx
|
|
78
|
-
* const { selectedCurrency, setSelectedCurrency
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* addCurrency({
|
|
82
|
-
* code: "BTC",
|
|
83
|
-
* symbol: "₿",
|
|
84
|
-
* name: "Bitcoin",
|
|
85
|
-
* showSubscripts: true,
|
|
86
|
-
* });
|
|
87
|
-
*
|
|
88
|
-
* // Set exchange rate: 1 BTC = 50000 USD
|
|
89
|
-
* setExchangeRate("BTC", "USD", 50000);
|
|
90
|
-
*
|
|
91
|
-
* // Change display currency
|
|
92
|
-
* setSelectedCurrency('BTC');
|
|
35
|
+
* const { selectedCurrency, setSelectedCurrency } = useCurrencyStore();
|
|
36
|
+
* // Change display currency to USD
|
|
37
|
+
* setSelectedCurrency('USD');
|
|
93
38
|
* ```
|
|
94
39
|
*/
|
|
95
40
|
export declare const useCurrencyStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<CurrencyState>, "persist"> & {
|
|
@@ -103,24 +48,4 @@ export declare const useCurrencyStore: import("zustand").UseBoundStore<Omit<impo
|
|
|
103
48
|
getOptions: () => Partial<import("zustand/middleware").PersistOptions<CurrencyState, CurrencyState>>;
|
|
104
49
|
};
|
|
105
50
|
}>;
|
|
106
|
-
/**
|
|
107
|
-
* Get the symbol for any currency (built-in or custom).
|
|
108
|
-
*/
|
|
109
|
-
export declare function getCurrencySymbol(currency: string): string;
|
|
110
|
-
/**
|
|
111
|
-
* Get the name for any currency (built-in or custom).
|
|
112
|
-
*/
|
|
113
|
-
export declare function getCurrencyName(currency: string): string;
|
|
114
|
-
/**
|
|
115
|
-
* Get metadata for a custom currency.
|
|
116
|
-
*/
|
|
117
|
-
export declare function getCurrencyMetadata(currency: string): CurrencyMetadata | undefined;
|
|
118
|
-
/**
|
|
119
|
-
* Get the number of decimal places for a currency (for converting from smallest unit).
|
|
120
|
-
* Used when parsing amounts from wei/smallest unit format.
|
|
121
|
-
*
|
|
122
|
-
* @param currency - Currency code
|
|
123
|
-
* @returns Number of decimal places (e.g., 18 for ETH/wei, 2 for USD cents, 0 for JPY)
|
|
124
|
-
*/
|
|
125
|
-
export declare function getCurrencyDecimalPlaces(currency: string): number;
|
|
126
51
|
export {};
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useCurrencyStore = exports.CURRENCY_NAMES = exports.CURRENCY_SYMBOLS = void 0;
|
|
4
|
-
exports.getCurrencySymbol = getCurrencySymbol;
|
|
5
|
-
exports.getCurrencyName = getCurrencyName;
|
|
6
|
-
exports.getCurrencyMetadata = getCurrencyMetadata;
|
|
7
|
-
exports.getCurrencyDecimalPlaces = getCurrencyDecimalPlaces;
|
|
8
4
|
const zustand_1 = require("zustand");
|
|
9
5
|
const middleware_1 = require("zustand/middleware");
|
|
10
6
|
/**
|
|
@@ -42,158 +38,20 @@ exports.CURRENCY_NAMES = {
|
|
|
42
38
|
/**
|
|
43
39
|
* Zustand store for managing currency selection and conversion.
|
|
44
40
|
* Persists user's selected currency preference in localStorage.
|
|
45
|
-
* Supports dynamic currency registration and custom exchange rates.
|
|
46
41
|
*
|
|
47
42
|
* @example
|
|
48
43
|
* ```tsx
|
|
49
|
-
* const { selectedCurrency, setSelectedCurrency
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* addCurrency({
|
|
53
|
-
* code: "BTC",
|
|
54
|
-
* symbol: "₿",
|
|
55
|
-
* name: "Bitcoin",
|
|
56
|
-
* showSubscripts: true,
|
|
57
|
-
* });
|
|
58
|
-
*
|
|
59
|
-
* // Set exchange rate: 1 BTC = 50000 USD
|
|
60
|
-
* setExchangeRate("BTC", "USD", 50000);
|
|
61
|
-
*
|
|
62
|
-
* // Change display currency
|
|
63
|
-
* setSelectedCurrency('BTC');
|
|
44
|
+
* const { selectedCurrency, setSelectedCurrency } = useCurrencyStore();
|
|
45
|
+
* // Change display currency to USD
|
|
46
|
+
* setSelectedCurrency('USD');
|
|
64
47
|
* ```
|
|
65
48
|
*/
|
|
66
|
-
exports.useCurrencyStore = (0, zustand_1.create)()((0, middleware_1.persist)(
|
|
49
|
+
exports.useCurrencyStore = (0, zustand_1.create)()((0, middleware_1.persist)(set => ({
|
|
67
50
|
selectedCurrency: "B3",
|
|
68
51
|
baseCurrency: "B3",
|
|
69
|
-
customCurrencies: {},
|
|
70
|
-
customExchangeRates: {},
|
|
71
52
|
setSelectedCurrency: currency => set({ selectedCurrency: currency }),
|
|
72
53
|
setBaseCurrency: currency => set({ baseCurrency: currency }),
|
|
73
|
-
addCurrency: metadata => {
|
|
74
|
-
set(state => ({
|
|
75
|
-
customCurrencies: {
|
|
76
|
-
...state.customCurrencies,
|
|
77
|
-
[metadata.code]: metadata,
|
|
78
|
-
},
|
|
79
|
-
}));
|
|
80
|
-
},
|
|
81
|
-
removeCurrency: code => {
|
|
82
|
-
set(state => {
|
|
83
|
-
// Remove the currency
|
|
84
|
-
const { [code]: _removed, ...remaining } = state.customCurrencies;
|
|
85
|
-
// Remove all exchange rates involving this currency
|
|
86
|
-
const filteredRates = {};
|
|
87
|
-
for (const [key, rate] of Object.entries(state.customExchangeRates)) {
|
|
88
|
-
// Key format is "FROM-TO", skip if either matches the removed code
|
|
89
|
-
const [from, to] = key.split("-");
|
|
90
|
-
if (from !== code && to !== code) {
|
|
91
|
-
filteredRates[key] = rate;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
customCurrencies: remaining,
|
|
96
|
-
customExchangeRates: filteredRates,
|
|
97
|
-
};
|
|
98
|
-
});
|
|
99
|
-
},
|
|
100
|
-
setExchangeRate: (from, to, rate) => {
|
|
101
|
-
set(state => {
|
|
102
|
-
const key = `${from}-${to}`;
|
|
103
|
-
const inverseKey = `${to}-${from}`;
|
|
104
|
-
// Only set inverse rate if rate is not 0 (to avoid Infinity)
|
|
105
|
-
const newRates = {
|
|
106
|
-
...state.customExchangeRates,
|
|
107
|
-
[key]: rate,
|
|
108
|
-
};
|
|
109
|
-
if (rate !== 0) {
|
|
110
|
-
newRates[inverseKey] = 1 / rate;
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
customExchangeRates: newRates,
|
|
114
|
-
};
|
|
115
|
-
});
|
|
116
|
-
},
|
|
117
|
-
getExchangeRate: (from, to) => {
|
|
118
|
-
const key = `${from}-${to}`;
|
|
119
|
-
return get().customExchangeRates[key];
|
|
120
|
-
},
|
|
121
|
-
getAllCurrencies: () => {
|
|
122
|
-
const builtIn = Object.keys(exports.CURRENCY_SYMBOLS);
|
|
123
|
-
const custom = Object.keys(get().customCurrencies);
|
|
124
|
-
return [...builtIn, ...custom];
|
|
125
|
-
},
|
|
126
54
|
}), {
|
|
127
55
|
name: "currency-storage",
|
|
128
|
-
version:
|
|
56
|
+
version: 2,
|
|
129
57
|
}));
|
|
130
|
-
/**
|
|
131
|
-
* Get the symbol for any currency (built-in or custom).
|
|
132
|
-
*/
|
|
133
|
-
function getCurrencySymbol(currency) {
|
|
134
|
-
// Check built-in currencies first
|
|
135
|
-
if (currency in exports.CURRENCY_SYMBOLS) {
|
|
136
|
-
return exports.CURRENCY_SYMBOLS[currency];
|
|
137
|
-
}
|
|
138
|
-
// Check custom currencies
|
|
139
|
-
const customCurrencies = exports.useCurrencyStore.getState().customCurrencies;
|
|
140
|
-
const customCurrency = customCurrencies[currency];
|
|
141
|
-
if (customCurrency) {
|
|
142
|
-
return customCurrency.symbol;
|
|
143
|
-
}
|
|
144
|
-
// Fallback to currency code
|
|
145
|
-
return currency;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Get the name for any currency (built-in or custom).
|
|
149
|
-
*/
|
|
150
|
-
function getCurrencyName(currency) {
|
|
151
|
-
// Check built-in currencies first
|
|
152
|
-
if (currency in exports.CURRENCY_NAMES) {
|
|
153
|
-
return exports.CURRENCY_NAMES[currency];
|
|
154
|
-
}
|
|
155
|
-
// Check custom currencies
|
|
156
|
-
const customCurrencies = exports.useCurrencyStore.getState().customCurrencies;
|
|
157
|
-
const customCurrency = customCurrencies[currency];
|
|
158
|
-
if (customCurrency) {
|
|
159
|
-
return customCurrency.name;
|
|
160
|
-
}
|
|
161
|
-
// Fallback to currency code
|
|
162
|
-
return currency;
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Get metadata for a custom currency.
|
|
166
|
-
*/
|
|
167
|
-
function getCurrencyMetadata(currency) {
|
|
168
|
-
const customCurrencies = exports.useCurrencyStore.getState().customCurrencies;
|
|
169
|
-
return customCurrencies[currency];
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Get the number of decimal places for a currency (for converting from smallest unit).
|
|
173
|
-
* Used when parsing amounts from wei/smallest unit format.
|
|
174
|
-
*
|
|
175
|
-
* @param currency - Currency code
|
|
176
|
-
* @returns Number of decimal places (e.g., 18 for ETH/wei, 2 for USD cents, 0 for JPY)
|
|
177
|
-
*/
|
|
178
|
-
function getCurrencyDecimalPlaces(currency) {
|
|
179
|
-
// Check custom currencies first
|
|
180
|
-
const customCurrencies = exports.useCurrencyStore.getState().customCurrencies;
|
|
181
|
-
const customMetadata = customCurrencies[currency];
|
|
182
|
-
if (customMetadata?.decimals !== undefined) {
|
|
183
|
-
return customMetadata.decimals;
|
|
184
|
-
}
|
|
185
|
-
// Built-in currencies with 18 decimals (wei-like)
|
|
186
|
-
if (currency === "WIN" || currency === "ETH" || currency === "SOL" || currency === "B3") {
|
|
187
|
-
return 18;
|
|
188
|
-
}
|
|
189
|
-
// Fiat currencies with cent-like decimals
|
|
190
|
-
if (currency === "USD" || currency === "EUR" || currency === "GBP" || currency === "CAD" || currency === "AUD") {
|
|
191
|
-
return 2;
|
|
192
|
-
}
|
|
193
|
-
// Currencies without fractional units
|
|
194
|
-
if (currency === "JPY" || currency === "KRW") {
|
|
195
|
-
return 0;
|
|
196
|
-
}
|
|
197
|
-
// Default to 18 decimals (wei-like)
|
|
198
|
-
return 18;
|
|
199
|
-
}
|