@b3dotfun/sdk 0.0.42 → 0.0.43-alpha.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.
Files changed (121) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +1 -0
  2. package/dist/cjs/anyspend/react/components/AnySpend.js +11 -4
  3. package/dist/cjs/anyspend/react/components/AnySpendCustom.js +43 -3
  4. package/dist/cjs/anyspend/react/components/AnyspendDepositHype.d.ts +1 -0
  5. package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +2 -2
  6. package/dist/cjs/anyspend/react/components/common/PanelOnramp.d.ts +2 -1
  7. package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +5 -3
  8. package/dist/cjs/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +12 -0
  9. package/dist/cjs/anyspend/types/api.d.ts +2 -10
  10. package/dist/cjs/global-account/react/components/SignInWithB3/SignIn.js +1 -1
  11. package/dist/cjs/global-account/react/components/index.d.ts +8 -7
  12. package/dist/cjs/global-account/react/components/index.js +29 -23
  13. package/dist/cjs/global-account/react/components/ui/dropdown-menu.d.ts +27 -0
  14. package/dist/cjs/global-account/react/components/ui/dropdown-menu.js +100 -0
  15. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +5 -1
  16. package/dist/cjs/shared/constants/currency.d.ts +1 -0
  17. package/dist/cjs/shared/constants/currency.js +5 -0
  18. package/dist/cjs/shared/constants/index.d.ts +1 -0
  19. package/dist/cjs/shared/constants/index.js +15 -0
  20. package/dist/cjs/shared/react/components/CurrencySelector.d.ts +7 -0
  21. package/dist/cjs/shared/react/components/CurrencySelector.js +14 -0
  22. package/dist/cjs/shared/react/components/FormattedCurrency.d.ts +12 -0
  23. package/dist/cjs/shared/react/components/FormattedCurrency.js +60 -0
  24. package/dist/cjs/shared/react/components/index.d.ts +2 -0
  25. package/dist/cjs/shared/react/components/index.js +18 -0
  26. package/dist/cjs/shared/react/hooks/__tests__/useCurrencyConversion.test.d.ts +1 -0
  27. package/dist/cjs/shared/react/hooks/__tests__/useCurrencyConversion.test.js +245 -0
  28. package/dist/cjs/shared/react/hooks/index.d.ts +1 -0
  29. package/dist/cjs/shared/react/hooks/index.js +1 -0
  30. package/dist/cjs/shared/react/hooks/useCurrencyConversion.d.ts +35 -0
  31. package/dist/cjs/shared/react/hooks/useCurrencyConversion.js +200 -0
  32. package/dist/cjs/shared/react/index.d.ts +2 -0
  33. package/dist/cjs/shared/react/index.js +2 -0
  34. package/dist/cjs/shared/react/stores/currencyModalStore.d.ts +7 -0
  35. package/dist/cjs/shared/react/stores/currencyModalStore.js +9 -0
  36. package/dist/cjs/shared/react/stores/currencyStore.d.ts +51 -0
  37. package/dist/cjs/shared/react/stores/currencyStore.js +57 -0
  38. package/dist/cjs/shared/react/stores/index.d.ts +2 -0
  39. package/dist/cjs/shared/react/stores/index.js +18 -0
  40. package/dist/esm/anyspend/react/components/AnySpend.d.ts +1 -0
  41. package/dist/esm/anyspend/react/components/AnySpend.js +11 -4
  42. package/dist/esm/anyspend/react/components/AnySpendCustom.js +10 -3
  43. package/dist/esm/anyspend/react/components/AnyspendDepositHype.d.ts +1 -0
  44. package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +2 -2
  45. package/dist/esm/anyspend/react/components/common/PanelOnramp.d.ts +2 -1
  46. package/dist/esm/anyspend/react/components/common/PanelOnramp.js +5 -3
  47. package/dist/esm/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +12 -0
  48. package/dist/esm/anyspend/types/api.d.ts +2 -10
  49. package/dist/esm/global-account/react/components/SignInWithB3/SignIn.js +1 -1
  50. package/dist/esm/global-account/react/components/index.d.ts +8 -7
  51. package/dist/esm/global-account/react/components/index.js +8 -7
  52. package/dist/esm/global-account/react/components/ui/dropdown-menu.d.ts +27 -0
  53. package/dist/esm/global-account/react/components/ui/dropdown-menu.js +60 -0
  54. package/dist/esm/global-account/react/stores/useModalStore.d.ts +5 -1
  55. package/dist/esm/shared/constants/currency.d.ts +1 -0
  56. package/dist/esm/shared/constants/currency.js +2 -0
  57. package/dist/esm/shared/constants/index.d.ts +1 -0
  58. package/dist/esm/shared/constants/index.js +1 -0
  59. package/dist/esm/shared/react/components/CurrencySelector.d.ts +7 -0
  60. package/dist/esm/shared/react/components/CurrencySelector.js +11 -0
  61. package/dist/esm/shared/react/components/FormattedCurrency.d.ts +12 -0
  62. package/dist/esm/shared/react/components/FormattedCurrency.js +57 -0
  63. package/dist/esm/shared/react/components/index.d.ts +2 -0
  64. package/dist/esm/shared/react/components/index.js +2 -0
  65. package/dist/esm/shared/react/hooks/__tests__/useCurrencyConversion.test.d.ts +1 -0
  66. package/dist/esm/shared/react/hooks/__tests__/useCurrencyConversion.test.js +243 -0
  67. package/dist/esm/shared/react/hooks/index.d.ts +1 -0
  68. package/dist/esm/shared/react/hooks/index.js +1 -0
  69. package/dist/esm/shared/react/hooks/useCurrencyConversion.d.ts +35 -0
  70. package/dist/esm/shared/react/hooks/useCurrencyConversion.js +197 -0
  71. package/dist/esm/shared/react/index.d.ts +2 -0
  72. package/dist/esm/shared/react/index.js +2 -0
  73. package/dist/esm/shared/react/stores/currencyModalStore.d.ts +7 -0
  74. package/dist/esm/shared/react/stores/currencyModalStore.js +6 -0
  75. package/dist/esm/shared/react/stores/currencyStore.d.ts +51 -0
  76. package/dist/esm/shared/react/stores/currencyStore.js +54 -0
  77. package/dist/esm/shared/react/stores/index.d.ts +2 -0
  78. package/dist/esm/shared/react/stores/index.js +2 -0
  79. package/dist/styles/index.css +1 -1
  80. package/dist/types/anyspend/react/components/AnySpend.d.ts +1 -0
  81. package/dist/types/anyspend/react/components/AnyspendDepositHype.d.ts +1 -0
  82. package/dist/types/anyspend/react/components/common/PanelOnramp.d.ts +2 -1
  83. package/dist/types/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +12 -0
  84. package/dist/types/anyspend/types/api.d.ts +2 -10
  85. package/dist/types/global-account/react/components/index.d.ts +8 -7
  86. package/dist/types/global-account/react/components/ui/dropdown-menu.d.ts +27 -0
  87. package/dist/types/global-account/react/stores/useModalStore.d.ts +5 -1
  88. package/dist/types/shared/constants/currency.d.ts +1 -0
  89. package/dist/types/shared/constants/index.d.ts +1 -0
  90. package/dist/types/shared/react/components/CurrencySelector.d.ts +7 -0
  91. package/dist/types/shared/react/components/FormattedCurrency.d.ts +12 -0
  92. package/dist/types/shared/react/components/index.d.ts +2 -0
  93. package/dist/types/shared/react/hooks/__tests__/useCurrencyConversion.test.d.ts +1 -0
  94. package/dist/types/shared/react/hooks/index.d.ts +1 -0
  95. package/dist/types/shared/react/hooks/useCurrencyConversion.d.ts +35 -0
  96. package/dist/types/shared/react/index.d.ts +2 -0
  97. package/dist/types/shared/react/stores/currencyModalStore.d.ts +7 -0
  98. package/dist/types/shared/react/stores/currencyStore.d.ts +51 -0
  99. package/dist/types/shared/react/stores/index.d.ts +2 -0
  100. package/package.json +29 -3
  101. package/src/anyspend/react/components/AnySpend.tsx +15 -2
  102. package/src/anyspend/react/components/AnySpendCustom.tsx +11 -2
  103. package/src/anyspend/react/components/AnyspendDepositHype.tsx +3 -0
  104. package/src/anyspend/react/components/common/PanelOnramp.tsx +19 -15
  105. package/src/anyspend/types/api.ts +2 -10
  106. package/src/global-account/react/components/SignInWithB3/SignIn.tsx +2 -7
  107. package/src/global-account/react/components/index.ts +19 -12
  108. package/src/global-account/react/components/ui/dropdown-menu.tsx +132 -0
  109. package/src/global-account/react/stores/useModalStore.ts +5 -1
  110. package/src/shared/constants/currency.ts +2 -0
  111. package/src/shared/constants/index.ts +2 -0
  112. package/src/shared/react/components/CurrencySelector.tsx +71 -0
  113. package/src/shared/react/components/FormattedCurrency.tsx +106 -0
  114. package/src/shared/react/components/index.ts +2 -0
  115. package/src/shared/react/hooks/__tests__/useCurrencyConversion.test.ts +308 -0
  116. package/src/shared/react/hooks/index.ts +1 -0
  117. package/src/shared/react/hooks/useCurrencyConversion.ts +211 -0
  118. package/src/shared/react/index.ts +2 -0
  119. package/src/shared/react/stores/currencyModalStore.ts +13 -0
  120. package/src/shared/react/stores/currencyStore.ts +82 -0
  121. package/src/shared/react/stores/index.ts +2 -0
@@ -0,0 +1,211 @@
1
+ import { useExchangeRate } from "@b3dotfun/sdk/global-account/react";
2
+ import { formatDisplayNumber } from "@b3dotfun/sdk/shared/utils/number";
3
+ import { CURRENCY_SYMBOLS, useCurrencyStore } from "../stores/currencyStore";
4
+
5
+ /**
6
+ * Hook for currency conversion and formatting with real-time exchange rates.
7
+ *
8
+ * This hook provides currency conversion functionality using live exchange rates
9
+ * and formats values according to currency-specific rules (decimals, symbols, etc.).
10
+ *
11
+ * @returns Currency conversion utilities and state
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * function PriceDisplay({ amount }: { amount: number }) {
16
+ * const { formatCurrencyValue, selectedCurrency } = useCurrencyConversion();
17
+ * return <div>{formatCurrencyValue(amount)}</div>;
18
+ * }
19
+ * ```
20
+ */
21
+ export function useCurrencyConversion() {
22
+ const selectedCurrency = useCurrencyStore(state => state.selectedCurrency);
23
+ const baseCurrency = useCurrencyStore(state => state.baseCurrency);
24
+
25
+ // Get exchange rate for the selected currency
26
+ const { rate: exchangeRate } = useExchangeRate({
27
+ baseCurrency,
28
+ quoteCurrency: selectedCurrency === baseCurrency ? "USD" : selectedCurrency,
29
+ });
30
+
31
+ // Always fetch USD rate for tooltip purposes
32
+ const { rate: usdRate } = useExchangeRate({
33
+ baseCurrency,
34
+ quoteCurrency: "USD",
35
+ });
36
+
37
+ /**
38
+ * Formats a numeric value as a currency string with proper conversion and formatting.
39
+ *
40
+ * Behavior:
41
+ * - When exchange rate is unavailable, displays value in base currency
42
+ * - Applies currency-specific formatting rules:
43
+ * - JPY/KRW: No decimal places
44
+ * - ETH/SOL: 6 significant digits with subscript notation for small values
45
+ * - Fiat (USD/EUR/GBP/CAD/AUD): 2 decimal places minimum for values < 1000
46
+ * - Handles symbol positioning (prefix for fiat, suffix for crypto)
47
+ *
48
+ * @param value - The numeric value to format (in base currency)
49
+ * @param options - Optional formatting overrides
50
+ * @param options.decimals - Override number of decimal places
51
+ * @param options.currency - Override currency (bypasses conversion)
52
+ * @returns Formatted currency string with appropriate symbol and decimal places
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * formatCurrencyValue(100) // Returns "$100.00" if USD is selected
57
+ * formatCurrencyValue(0.0001) // Returns "0.0₄1 ETH" if ETH is selected
58
+ * formatCurrencyValue(1500) // Returns "¥1,500" if JPY is selected
59
+ * formatCurrencyValue(100, { decimals: 4, currency: "ETH" }) // Returns "100.0000 ETH"
60
+ * ```
61
+ */
62
+ const formatCurrencyValue = (value: number, options?: { decimals?: number; currency?: string }): string => {
63
+ const overrideCurrency = options?.currency;
64
+ const overrideDecimals = options?.decimals;
65
+
66
+ // Custom currency provided - bypass conversion and use simple formatting
67
+ if (overrideCurrency) {
68
+ const decimalsToUse = overrideDecimals !== undefined ? overrideDecimals : overrideCurrency === "B3" ? 0 : 2;
69
+
70
+ const formatted = formatDisplayNumber(value, {
71
+ fractionDigits: decimalsToUse,
72
+ showSubscripts: false,
73
+ });
74
+ return `${formatted} ${overrideCurrency}`;
75
+ }
76
+
77
+ // Custom decimals for base currency without conversion
78
+ if (overrideDecimals !== undefined && selectedCurrency === baseCurrency) {
79
+ const formatted = formatDisplayNumber(value, {
80
+ fractionDigits: overrideDecimals,
81
+ showSubscripts: false,
82
+ });
83
+ return `${formatted} ${baseCurrency}`;
84
+ }
85
+
86
+ // If no exchange rate available, show base currency to prevent showing
87
+ // incorrect values with wrong currency symbols during rate fetching
88
+ if (selectedCurrency === baseCurrency || !exchangeRate) {
89
+ const formatted = formatDisplayNumber(value, {
90
+ significantDigits: baseCurrency === "B3" ? 6 : 8,
91
+ showSubscripts: true,
92
+ });
93
+ return `${formatted} ${baseCurrency}`;
94
+ }
95
+
96
+ // Convert value using current exchange rate
97
+ const convertedValue = value * exchangeRate;
98
+ const symbol = CURRENCY_SYMBOLS[selectedCurrency];
99
+
100
+ // Currencies that display symbol before the number (e.g., $100.00)
101
+ const prefixCurrencies = ["USD", "EUR", "GBP", "CAD", "AUD"];
102
+
103
+ let formatted: string;
104
+
105
+ if (selectedCurrency === "JPY" || selectedCurrency === "KRW") {
106
+ // Japanese Yen and Korean Won don't use decimal places
107
+ formatted = formatDisplayNumber(convertedValue, {
108
+ fractionDigits: 0,
109
+ showSubscripts: false,
110
+ });
111
+ } else if (selectedCurrency === "ETH" || selectedCurrency === "SOL") {
112
+ // Crypto currencies use more precision and subscript notation
113
+ // for very small amounts (e.g., 0.0₃45 ETH)
114
+ formatted = formatDisplayNumber(convertedValue, {
115
+ significantDigits: 6,
116
+ showSubscripts: true,
117
+ });
118
+ } else {
119
+ // Standard fiat currencies (USD, EUR, GBP, CAD, AUD)
120
+ // Use 2 decimal places minimum for amounts under 1000
121
+ formatted = formatDisplayNumber(convertedValue, {
122
+ significantDigits: 6,
123
+ fractionDigits: convertedValue < 1000 ? 2 : undefined,
124
+ showSubscripts: true,
125
+ });
126
+ }
127
+
128
+ // Apply currency symbol with correct positioning
129
+ if (prefixCurrencies.includes(selectedCurrency)) {
130
+ return `${symbol}${formatted}`;
131
+ } else {
132
+ // Suffix currencies: JPY, KRW, ETH, SOL, B3
133
+ return `${formatted} ${symbol}`;
134
+ }
135
+ };
136
+
137
+ /**
138
+ * Formats a tooltip value showing the alternate currency representation.
139
+ *
140
+ * Behavior:
141
+ * - When displaying base currency: Shows USD equivalent
142
+ * - When displaying other currency: Shows base currency equivalent
143
+ * - For custom currencies: Shows appropriate conversion or original value
144
+ *
145
+ * @param value - The numeric value to format
146
+ * @param customCurrency - Optional custom currency override
147
+ * @returns Formatted tooltip string
148
+ *
149
+ * @example
150
+ * ```tsx
151
+ * formatTooltipValue(100) // Returns "$150.00 USD" if displaying B3 with rate 1.5
152
+ * formatTooltipValue(100, "ETH") // Returns "100.0000 ETH" if custom currency
153
+ * ```
154
+ */
155
+ const formatTooltipValue = (value: number, customCurrency?: string): string => {
156
+ const displayCurrency = customCurrency || selectedCurrency;
157
+ const absoluteValue = Math.abs(value);
158
+
159
+ // Custom currency provided
160
+ if (customCurrency) {
161
+ if (customCurrency === baseCurrency) {
162
+ // Show USD equivalent for base currency using USD rate
163
+ const usdValue = usdRate ? absoluteValue * usdRate : absoluteValue;
164
+ const formatted = formatDisplayNumber(usdValue, {
165
+ significantDigits: 6,
166
+ fractionDigits: usdValue < 1000 ? 2 : undefined,
167
+ showSubscripts: true,
168
+ });
169
+ return `$${formatted} USD`;
170
+ } else {
171
+ // Show as-is for other custom currencies
172
+ return `${formatDisplayNumber(absoluteValue, { significantDigits: 6 })} ${customCurrency}`;
173
+ }
174
+ }
175
+
176
+ // Showing base currency - display USD equivalent
177
+ if (displayCurrency === baseCurrency) {
178
+ const usdValue = usdRate ? absoluteValue * usdRate : absoluteValue;
179
+ const formatted = formatDisplayNumber(usdValue, {
180
+ significantDigits: 6,
181
+ fractionDigits: usdValue < 1000 ? 2 : undefined,
182
+ showSubscripts: true,
183
+ });
184
+ return `$${formatted} USD`;
185
+ }
186
+
187
+ // Showing other currency - display base currency equivalent
188
+ const formatted = formatDisplayNumber(absoluteValue, {
189
+ significantDigits: baseCurrency === "B3" ? 6 : 8,
190
+ showSubscripts: true,
191
+ });
192
+ return `${formatted} ${baseCurrency}`;
193
+ };
194
+
195
+ return {
196
+ /** Currently selected display currency */
197
+ selectedCurrency,
198
+ /** Base currency used for conversion (typically B3) */
199
+ baseCurrency,
200
+ /** Current exchange rate from base to selected currency (undefined while loading) */
201
+ exchangeRate,
202
+ /** Format a value with currency conversion and proper symbol/decimal handling */
203
+ formatCurrencyValue,
204
+ /** Format a tooltip value showing alternate currency representation */
205
+ formatTooltipValue,
206
+ /** Symbol for the currently selected currency (e.g., "$", "€", "ETH") */
207
+ selectedCurrencySymbol: CURRENCY_SYMBOLS[selectedCurrency],
208
+ /** Symbol for the base currency */
209
+ baseCurrencySymbol: CURRENCY_SYMBOLS[baseCurrency],
210
+ };
211
+ }
@@ -1 +1,3 @@
1
+ export * from "./components";
1
2
  export * from "./hooks";
3
+ export * from "./stores";
@@ -0,0 +1,13 @@
1
+ import { create } from "zustand";
2
+
3
+ interface CurrencyModalState {
4
+ isOpen: boolean;
5
+ openModal: () => void;
6
+ closeModal: () => void;
7
+ }
8
+
9
+ export const useCurrencyModalStore = create<CurrencyModalState>(set => ({
10
+ isOpen: false,
11
+ openModal: () => set({ isOpen: true }),
12
+ closeModal: () => set({ isOpen: false }),
13
+ }));
@@ -0,0 +1,82 @@
1
+ import { create } from "zustand";
2
+ import { persist } from "zustand/middleware";
3
+
4
+ /**
5
+ * Supported currencies for display and conversion.
6
+ * Includes fiat currencies (USD, EUR, GBP, JPY, CAD, AUD, KRW) and crypto (ETH, SOL, B3).
7
+ */
8
+ export type SupportedCurrency = "ETH" | "USD" | "EUR" | "GBP" | "JPY" | "CAD" | "AUD" | "B3" | "SOL" | "KRW";
9
+
10
+ /**
11
+ * Currency symbols used for display formatting.
12
+ * Prefix currencies (USD, EUR, GBP, CAD, AUD) show symbol before the amount.
13
+ * Suffix currencies (JPY, KRW, ETH, SOL, B3) show symbol after the amount.
14
+ */
15
+ export const CURRENCY_SYMBOLS: Record<SupportedCurrency, string> = {
16
+ ETH: "ETH",
17
+ USD: "$",
18
+ EUR: "€",
19
+ GBP: "£",
20
+ JPY: "¥",
21
+ CAD: "C$",
22
+ AUD: "A$",
23
+ B3: "B3",
24
+ SOL: "SOL",
25
+ KRW: "₩",
26
+ };
27
+
28
+ /**
29
+ * Human-readable currency names for display in selectors and labels.
30
+ */
31
+ export const CURRENCY_NAMES: Record<SupportedCurrency, string> = {
32
+ ETH: "Ethereum",
33
+ USD: "US Dollar",
34
+ EUR: "Euro",
35
+ GBP: "British Pound",
36
+ JPY: "Japanese Yen",
37
+ CAD: "Canadian Dollar",
38
+ AUD: "Australian Dollar",
39
+ B3: "B3",
40
+ SOL: "Solana",
41
+ KRW: "Korean Won",
42
+ };
43
+
44
+ /**
45
+ * Currency store state interface.
46
+ * @property selectedCurrency - The currency currently selected for display
47
+ * @property baseCurrency - The base currency for conversion (typically B3)
48
+ * @property setSelectedCurrency - Update the selected display currency
49
+ * @property setBaseCurrency - Update the base currency for conversions
50
+ */
51
+ interface CurrencyState {
52
+ selectedCurrency: SupportedCurrency;
53
+ baseCurrency: SupportedCurrency;
54
+ setSelectedCurrency: (currency: SupportedCurrency) => void;
55
+ setBaseCurrency: (currency: SupportedCurrency) => void;
56
+ }
57
+
58
+ /**
59
+ * Zustand store for managing currency selection and conversion.
60
+ * Persists user's selected currency preference in localStorage.
61
+ *
62
+ * @example
63
+ * ```tsx
64
+ * const { selectedCurrency, setSelectedCurrency } = useCurrencyStore();
65
+ * // Change display currency to USD
66
+ * setSelectedCurrency('USD');
67
+ * ```
68
+ */
69
+ export const useCurrencyStore = create<CurrencyState>()(
70
+ persist(
71
+ set => ({
72
+ selectedCurrency: "B3",
73
+ baseCurrency: "B3",
74
+ setSelectedCurrency: currency => set({ selectedCurrency: currency }),
75
+ setBaseCurrency: currency => set({ baseCurrency: currency }),
76
+ }),
77
+ {
78
+ name: "currency-storage",
79
+ version: 2,
80
+ },
81
+ ),
82
+ );
@@ -0,0 +1,2 @@
1
+ export * from "./currencyModalStore";
2
+ export * from "./currencyStore";