@funkit/connect 9.7.2-next.0 → 9.8.0

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 (105) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/__generated__/default_configs.d.ts +1 -1
  3. package/dist/__generated__/default_feature_gates.d.ts +1 -0
  4. package/dist/clients/chunk-LMEQD56M.js +289 -0
  5. package/dist/clients/fanatics.css +1 -1
  6. package/dist/clients/fanatics.js +55 -329
  7. package/dist/clients/lighter.css +14393 -0
  8. package/dist/clients/lighter.d.ts +30 -34
  9. package/dist/clients/lighter.js +657 -0
  10. package/dist/components/Dropdown/BaseDropdown.d.ts +7 -21
  11. package/dist/components/Dropdown/BaseDropdown.utils.d.ts +23 -0
  12. package/dist/components/Dropdown/ChainDropdown.d.ts +2 -1
  13. package/dist/components/Dropdown/TokenAndChainDropdown.d.ts +9 -3
  14. package/dist/components/Dropdown/TokenDropdown.d.ts +7 -3
  15. package/dist/domains/asset.d.ts +0 -1
  16. package/dist/domains/quoteMode/exactOut.d.ts +2 -1
  17. package/dist/domains/quoteMode/resolveQuoteMode.d.ts +3 -1
  18. package/dist/hooks/queries/useWithdrawalQuote.d.ts +2 -8
  19. package/dist/hooks/useCheckoutDirectExecution.d.ts +1 -1
  20. package/dist/hooks/useIsStablecoin.d.ts +2 -0
  21. package/dist/hooks/useTokenAndChainDropdown.d.ts +13 -7
  22. package/dist/hooks/useTokenTransfer.d.ts +2 -2
  23. package/dist/index.css +99 -99
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.js +5691 -4823
  26. package/dist/modals/CheckoutModal/SourceChange/CryptoCashToggle.d.ts +2 -1
  27. package/dist/modals/CheckoutModal/TransferToken/useTransferTokenTracking.d.ts +2 -2
  28. package/dist/modals/WithdrawalModal/WithdrawalContent.d.ts +11 -1
  29. package/dist/modals/WithdrawalModal/useWithdrawal.d.ts +5 -1
  30. package/dist/providers/FunkitCheckoutContext/types.d.ts +60 -2
  31. package/dist/providers/FunkitHistoryContext.d.ts +2 -2
  32. package/dist/utils/withdrawal.d.ts +6 -1
  33. package/dist/wallets/Wallet.d.ts +11 -0
  34. package/dist/wallets/walletConnectors/bifrostWallet/bifrostWallet.js +2 -2
  35. package/dist/wallets/walletConnectors/bitgetWallet/bitgetWallet.js +2 -2
  36. package/dist/wallets/walletConnectors/bybitWallet/bybitWallet.js +2 -2
  37. package/dist/wallets/walletConnectors/clvWallet/clvWallet.js +2 -2
  38. package/dist/wallets/walletConnectors/coin98Wallet/coin98Wallet.js +2 -2
  39. package/dist/wallets/walletConnectors/coreWallet/coreWallet.js +2 -2
  40. package/dist/wallets/walletConnectors/foxWallet/foxWallet.js +2 -2
  41. package/dist/wallets/walletConnectors/frontierWallet/frontierWallet.js +2 -2
  42. package/dist/wallets/walletConnectors/gateWallet/gateWallet.js +2 -2
  43. package/dist/wallets/walletConnectors/index.js +42 -42
  44. package/dist/wallets/walletConnectors/metaMaskWallet/metaMaskWallet.js +2 -2
  45. package/dist/wallets/walletConnectors/okxWallet/okxWallet.js +2 -2
  46. package/dist/wallets/walletConnectors/rainbowWallet/rainbowWallet.js +2 -2
  47. package/dist/wallets/walletConnectors/roninWallet/roninWallet.js +2 -2
  48. package/dist/wallets/walletConnectors/safepalWallet/safepalWallet.js +2 -2
  49. package/dist/wallets/walletConnectors/subWallet/subWallet.js +2 -2
  50. package/dist/wallets/walletConnectors/tokenPocketWallet/tokenPocketWallet.js +2 -2
  51. package/dist/wallets/walletConnectors/trustWallet/trustWallet.js +2 -2
  52. package/dist/wallets/walletConnectors/zerionWallet/zerionWallet.js +2 -2
  53. package/package.json +6 -5
  54. package/dist/chunk-64NZSUGQ.js +0 -368
  55. package/dist/chunk-B2B6HDIE.js +0 -238
  56. package/dist/chunk-OQNN7EMQ.js +0 -238
  57. package/dist/chunk-S65TG73G.js +0 -247
  58. package/dist/chunk-VLAOBEJN.js +0 -247
  59. package/dist/clients/chunk-SBQ2UUPK.js +0 -214
  60. package/dist/components/Dropdown/TokenAndChainDropdown.css.d.ts +0 -1
  61. package/dist/hooks/track/CheckoutTrackingContext.d.ts +0 -60
  62. package/dist/hooks/useTokenChain.d.ts +0 -21
  63. package/dist/modals/CheckoutModal/SwappedIframe/SwappedIframeContainer.d.ts +0 -17
  64. package/dist/modals/WithdrwalModal/WithdrawalCallbackSuccess.d.ts +0 -10
  65. package/dist/modals/WithdrwalModal/WithdrawalContent.d.ts +0 -11
  66. package/dist/modals/WithdrwalModal/WithdrawalModal.d.ts +0 -9
  67. package/dist/modals/WithdrwalModal/WithdrawalSuccess.d.ts +0 -15
  68. package/dist/modals/WithdrwalModal/types.d.ts +0 -5
  69. package/dist/modals/WithdrwalModal/useWithdrawal.d.ts +0 -24
  70. package/dist/wallets/walletConnectors/chunk-34HACM5U.js +0 -110
  71. package/dist/wallets/walletConnectors/chunk-4C7ER452.js +0 -93
  72. package/dist/wallets/walletConnectors/chunk-53VYSPXK.js +0 -66
  73. package/dist/wallets/walletConnectors/chunk-5TN5Z2WY.js +0 -87
  74. package/dist/wallets/walletConnectors/chunk-6DRCY52E.js +0 -69
  75. package/dist/wallets/walletConnectors/chunk-6UCI7GM6.js +0 -98
  76. package/dist/wallets/walletConnectors/chunk-6YO27XOM.js +0 -96
  77. package/dist/wallets/walletConnectors/chunk-7OARWILZ.js +0 -92
  78. package/dist/wallets/walletConnectors/chunk-7V33VJAL.js +0 -218
  79. package/dist/wallets/walletConnectors/chunk-APHCF4DT.js +0 -103
  80. package/dist/wallets/walletConnectors/chunk-CJJT7LMT.js +0 -96
  81. package/dist/wallets/walletConnectors/chunk-DEFRRPXB.js +0 -98
  82. package/dist/wallets/walletConnectors/chunk-EKJHJFRN.js +0 -69
  83. package/dist/wallets/walletConnectors/chunk-FG2LDVXL.js +0 -92
  84. package/dist/wallets/walletConnectors/chunk-GH4M6FTK.js +0 -95
  85. package/dist/wallets/walletConnectors/chunk-GSHSWVEG.js +0 -70
  86. package/dist/wallets/walletConnectors/chunk-GVOQTORD.js +0 -87
  87. package/dist/wallets/walletConnectors/chunk-HETS3KKI.js +0 -218
  88. package/dist/wallets/walletConnectors/chunk-HOPH3TQ3.js +0 -99
  89. package/dist/wallets/walletConnectors/chunk-HRDPUW3V.js +0 -94
  90. package/dist/wallets/walletConnectors/chunk-HXWUH73P.js +0 -93
  91. package/dist/wallets/walletConnectors/chunk-IICWJWGZ.js +0 -110
  92. package/dist/wallets/walletConnectors/chunk-KO56HCTI.js +0 -106
  93. package/dist/wallets/walletConnectors/chunk-KWX2SYU2.js +0 -100
  94. package/dist/wallets/walletConnectors/chunk-LCIPVVH5.js +0 -70
  95. package/dist/wallets/walletConnectors/chunk-LI6QY2B5.js +0 -94
  96. package/dist/wallets/walletConnectors/chunk-PKMAPNN6.js +0 -92
  97. package/dist/wallets/walletConnectors/chunk-T4ROGPMF.js +0 -106
  98. package/dist/wallets/walletConnectors/chunk-TTHM3WUR.js +0 -100
  99. package/dist/wallets/walletConnectors/chunk-UDTBQV4Q.js +0 -96
  100. package/dist/wallets/walletConnectors/chunk-V6UOWTEZ.js +0 -95
  101. package/dist/wallets/walletConnectors/chunk-VJZWNQOF.js +0 -92
  102. package/dist/wallets/walletConnectors/chunk-XBLHZICW.js +0 -103
  103. package/dist/wallets/walletConnectors/chunk-XVBSJCW5.js +0 -96
  104. package/dist/wallets/walletConnectors/chunk-YIEASHLS.js +0 -99
  105. package/dist/wallets/walletConnectors/chunk-ZPSPK6LH.js +0 -66
@@ -0,0 +1,657 @@
1
+ "use client";
2
+ import {
3
+ AsyncImage,
4
+ Box,
5
+ useFunkitTranslation
6
+ } from "./chunk-LMEQD56M.js";
7
+ import {
8
+ logger
9
+ } from "./chunk-H6F75ULR.js";
10
+
11
+ // src/clients/lighter.tsx
12
+ import { SOLANA_MAINNET_CHAIN_ID } from "@funkit/chains";
13
+ import { RELAY_LIGHTER_CHAIN_ID } from "@funkit/fun-relay";
14
+ import { retry } from "@lifeomic/attempt";
15
+ import i18next from "i18next";
16
+ import React2, { useEffect, useMemo as useMemo2 } from "react";
17
+ import { arbitrum, base, bsc, mainnet as mainnet2, optimism } from "viem/chains";
18
+
19
+ // src/components/Icons/EvmWallet.tsx
20
+ import React from "react";
21
+ var EvmWallet = ({ size = 20 }) => /* @__PURE__ */ React.createElement(
22
+ "svg",
23
+ {
24
+ width: size,
25
+ height: size,
26
+ viewBox: "0 0 20 20",
27
+ fill: "none",
28
+ xmlns: "http://www.w3.org/2000/svg"
29
+ },
30
+ /* @__PURE__ */ React.createElement(
31
+ "path",
32
+ {
33
+ d: "M13.3333 6.66628V3.75016C13.3333 3.05704 13.3333 2.71048 13.1873 2.49751C13.0598 2.31143 12.8622 2.18503 12.6398 2.14718C12.3852 2.10386 12.0706 2.24909 11.4413 2.53955L4.04918 5.95127C3.48792 6.21031 3.20729 6.33984 3.00175 6.54071C2.82005 6.71829 2.68135 6.93507 2.59625 7.17447C2.5 7.44527 2.5 7.75435 2.5 8.3725V12.4996M13.75 12.0829H13.7583M2.5 9.33295L2.5 14.8329C2.5 15.7664 2.5 16.2331 2.68166 16.5896C2.84144 16.9032 3.09641 17.1582 3.41002 17.318C3.76654 17.4996 4.23325 17.4996 5.16667 17.4996H14.8333C15.7668 17.4996 16.2335 17.4996 16.59 17.318C16.9036 17.1582 17.1586 16.9032 17.3183 16.5896C17.5 16.2331 17.5 15.7664 17.5 14.8329V9.33295C17.5 8.39953 17.5 7.93282 17.3183 7.5763C17.1586 7.26269 16.9036 7.00773 16.59 6.84794C16.2335 6.66628 15.7668 6.66628 14.8333 6.66628L5.16667 6.66628C4.23325 6.66628 3.76654 6.66628 3.41002 6.84793C3.09641 7.00772 2.84144 7.26269 2.68166 7.57629C2.5 7.93281 2.5 8.39952 2.5 9.33295ZM14.1667 12.0829C14.1667 12.3131 13.9801 12.4996 13.75 12.4996C13.5199 12.4996 13.3333 12.3131 13.3333 12.0829C13.3333 11.8528 13.5199 11.6663 13.75 11.6663C13.9801 11.6663 14.1667 11.8528 14.1667 12.0829Z",
34
+ stroke: "currentColor",
35
+ strokeWidth: "1.5",
36
+ strokeLinecap: "round",
37
+ strokeLinejoin: "round"
38
+ }
39
+ )
40
+ );
41
+
42
+ // src/providers/provideFunkitConnectChains.ts
43
+ import { chainMetadataById } from "@funkit/chains";
44
+
45
+ // src/utils/customer.ts
46
+ import { useQuery } from "@tanstack/react-query";
47
+
48
+ // src/consts/customers.ts
49
+ import {
50
+ AVANTIS_API_KEY,
51
+ BASED_API_KEY,
52
+ BSX_API_KEY,
53
+ ETHEREAL_API_KEY,
54
+ FANATICS_API_KEY,
55
+ HYENA_API_KEY,
56
+ HYPERDASH_API_KEY,
57
+ LIGHTERXYZ_API_KEY,
58
+ MONAD_API_KEY,
59
+ MONKEY_TILT_API_KEY,
60
+ OSTIUM_API_KEY,
61
+ PERPL_API_KEY,
62
+ POLYMARKET_API_KEY
63
+ } from "@funkit/api-base";
64
+ import { mainnet } from "viem/chains";
65
+ function isLighterxyzCustomer(apiKey) {
66
+ return apiKey === LIGHTERXYZ_API_KEY;
67
+ }
68
+
69
+ // src/providers/FunkitConfigContext.tsx
70
+ import {
71
+ createContext,
72
+ useContext,
73
+ useMemo
74
+ } from "react";
75
+ var DEFAULT_TEXT_CUSTOMIZATIONS = {
76
+ virtualFiat: "Deposit with SEPA",
77
+ brokerageOrExchange: "Connect Exchange",
78
+ debitOrCredit: "Deposit with Card",
79
+ accountBalance: "Wallet",
80
+ selectAccount: "Select an exchange",
81
+ sourceMethodTitle: "Your source",
82
+ tokensListTitle: "Your tokens",
83
+ transferTokens: "Transfer Crypto",
84
+ receiveDropdownTitle: "",
85
+ // Default to empty
86
+ receiveDropdownLabel: "Asset to Receive",
87
+ confirmationScreen: {
88
+ payAmountLabel: "You send",
89
+ receiveAmountLabel: "You receive"
90
+ },
91
+ paymentMethodSubtitles: {}
92
+ };
93
+ var DEFAULT_UI_CUSTOMIZATIONS = {
94
+ alignTitle: "center",
95
+ alwaysShowTopDivider: false,
96
+ showModalTitle: true,
97
+ callToActionsUppercase: false,
98
+ enableCompactList: false,
99
+ checkoutHistory: {
100
+ showGetHelpAsAlert: true,
101
+ simplifiedUi: false
102
+ },
103
+ confirmationScreen: {
104
+ preferDestinationWhenSame: false,
105
+ showAmountSummaryAbovePaymentMethod: false,
106
+ showDisclaimerAsAlert: true,
107
+ showInstantTimeEstimate: false,
108
+ showLeftAlignedDollarValueWithLabel: false,
109
+ showPaymentAmountUsd: false,
110
+ showReceiveAmountUsd: false,
111
+ stepIndicatorType: "spinner",
112
+ showTokenAmount: true,
113
+ showTransactionDigest: "none"
114
+ },
115
+ sourceChangeScreen: {
116
+ bottomBarCloseButton: {
117
+ enabled: false,
118
+ labelKey: "common.close"
119
+ },
120
+ showTargetAssetSelection: false,
121
+ showWalletOnInsufficientBalance: false,
122
+ paymentMethodIcons: {}
123
+ },
124
+ inputAmountScreen: {
125
+ allowTokenAmountInput: true
126
+ },
127
+ selectAssetScreen: {
128
+ isSecondaryTokenSymbolVisible: true,
129
+ navigateOnAssetClick: false
130
+ },
131
+ transferCryptoScreen: {
132
+ showYouSendYouReceive: false
133
+ },
134
+ withdrawalScreen: {},
135
+ selectBrokerageScreen: {},
136
+ connectExchangeScreen: {},
137
+ customIcons: {},
138
+ customFontFamily: {
139
+ primary: "",
140
+ secondary: "",
141
+ tertiary: ""
142
+ }
143
+ };
144
+ var DEFAULT_FUNKIT_CONFIG = {
145
+ apiKey: "",
146
+ appName: "",
147
+ textCustomizations: DEFAULT_TEXT_CUSTOMIZATIONS,
148
+ uiCustomizations: DEFAULT_UI_CUSTOMIZATIONS
149
+ };
150
+ var FunkitConfigContext = createContext(
151
+ DEFAULT_FUNKIT_CONFIG
152
+ );
153
+ function useFunkitConfig() {
154
+ const originalFunkitConfig = useContext(FunkitConfigContext);
155
+ const { t } = useFunkitTranslation();
156
+ const translatedDefaults = useMemo(() => {
157
+ return {
158
+ virtualFiat: t("textCustomizations.virtualFiat"),
159
+ brokerageOrExchange: t("textCustomizations.brokerageOrExchange"),
160
+ debitOrCredit: t("textCustomizations.debitOrCredit"),
161
+ accountBalance: t("textCustomizations.accountBalance"),
162
+ selectAccount: t("textCustomizations.selectAccount"),
163
+ sourceMethodTitle: t("textCustomizations.sourceMethodTitle"),
164
+ tokensListTitle: t("textCustomizations.tokensListTitle"),
165
+ transferTokens: t("textCustomizations.transferTokens"),
166
+ receiveDropdownTitle: t("textCustomizations.receiveDropdownTitle"),
167
+ receiveDropdownLabel: t("textCustomizations.receiveDropdownLabel"),
168
+ confirmationScreen: {
169
+ payAmountLabel: t("textCustomizations.payAmountLabel"),
170
+ receiveAmountLabel: t("textCustomizations.receiveAmountLabel")
171
+ },
172
+ paymentMethodSubtitles: {}
173
+ };
174
+ }, [t]);
175
+ const finalFunkitConfig = useMemo(() => {
176
+ return {
177
+ ...DEFAULT_FUNKIT_CONFIG,
178
+ ...originalFunkitConfig,
179
+ textCustomizations: {
180
+ ...translatedDefaults,
181
+ ...originalFunkitConfig.textCustomizations,
182
+ confirmationScreen: {
183
+ ...translatedDefaults.confirmationScreen,
184
+ ...originalFunkitConfig.textCustomizations?.confirmationScreen
185
+ },
186
+ paymentMethodSubtitles: {
187
+ ...translatedDefaults.paymentMethodSubtitles,
188
+ ...originalFunkitConfig.textCustomizations?.paymentMethodSubtitles
189
+ }
190
+ },
191
+ uiCustomizations: {
192
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations,
193
+ ...originalFunkitConfig.uiCustomizations,
194
+ checkoutHistory: {
195
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.checkoutHistory,
196
+ ...originalFunkitConfig.uiCustomizations?.checkoutHistory
197
+ },
198
+ confirmationScreen: {
199
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.confirmationScreen,
200
+ ...originalFunkitConfig.uiCustomizations?.confirmationScreen
201
+ },
202
+ connectExchangeScreen: {
203
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.connectExchangeScreen,
204
+ ...originalFunkitConfig.uiCustomizations?.connectExchangeScreen
205
+ },
206
+ inputAmountScreen: {
207
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.inputAmountScreen,
208
+ ...originalFunkitConfig.uiCustomizations?.inputAmountScreen
209
+ },
210
+ selectAssetScreen: {
211
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.selectAssetScreen,
212
+ ...originalFunkitConfig.uiCustomizations?.selectAssetScreen
213
+ },
214
+ selectBrokerageScreen: {
215
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.selectBrokerageScreen,
216
+ ...originalFunkitConfig.uiCustomizations?.selectBrokerageScreen
217
+ },
218
+ sourceChangeScreen: {
219
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.sourceChangeScreen,
220
+ ...originalFunkitConfig.uiCustomizations?.sourceChangeScreen,
221
+ bottomBarCloseButton: {
222
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.sourceChangeScreen.bottomBarCloseButton,
223
+ ...originalFunkitConfig.uiCustomizations?.sourceChangeScreen?.bottomBarCloseButton
224
+ }
225
+ },
226
+ transferCryptoScreen: {
227
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.transferCryptoScreen,
228
+ ...originalFunkitConfig.uiCustomizations?.transferCryptoScreen
229
+ },
230
+ withdrawalScreen: {
231
+ ...DEFAULT_FUNKIT_CONFIG.uiCustomizations.withdrawalScreen,
232
+ ...originalFunkitConfig.uiCustomizations?.withdrawalScreen
233
+ }
234
+ }
235
+ };
236
+ }, [originalFunkitConfig, translatedDefaults]);
237
+ return finalFunkitConfig;
238
+ }
239
+
240
+ // src/utils/customer.ts
241
+ async function getLighterAccount(lookup, activeOnly) {
242
+ const params = new URLSearchParams({
243
+ by: lookup.by,
244
+ value: String(lookup.value),
245
+ ...activeOnly !== void 0 && { active_only: String(activeOnly) }
246
+ });
247
+ const response = await fetch(
248
+ `https://mainnet.zklighter.elliot.ai/api/v1/account?${params}`
249
+ );
250
+ if (!response.ok) {
251
+ throw new Error(`Failed to fetch lighter account: ${response.statusText}`);
252
+ }
253
+ return response.json();
254
+ }
255
+ function useLighterAccount(lookup, options) {
256
+ const { apiKey } = useFunkitConfig();
257
+ const isLighter = isLighterxyzCustomer(apiKey);
258
+ const enabled = isLighter && lookup !== null && (lookup.by === "index" ? true : !!lookup.value && lookup.value !== "0x");
259
+ const query = useQuery({
260
+ queryKey: [
261
+ "lighterAccount",
262
+ lookup?.by,
263
+ lookup?.value,
264
+ options?.activeOnly
265
+ ],
266
+ // biome-ignore lint/style/noNonNullAssertion: already checked for null
267
+ queryFn: () => getLighterAccount(lookup, options?.activeOnly),
268
+ enabled,
269
+ staleTime: 3e4,
270
+ retry: false
271
+ });
272
+ return {
273
+ ...query,
274
+ account: query.data?.accounts?.[0]
275
+ };
276
+ }
277
+
278
+ // src/clients/lighter.tsx
279
+ var LIGHTER_USDC_PERPS_ADDRESS = "0x0000000000000000000000000000000000000000";
280
+ var MAINNET_USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
281
+ var LIGHTER_API_BASE = "https://mainnet.zklighter.elliot.ai";
282
+ var LIGHTER_TX_STATUS = {
283
+ PENDING: 0,
284
+ QUEUED: 1,
285
+ COMMITTED: 2,
286
+ EXECUTED: 3,
287
+ FAILED: 4,
288
+ REJECTED: 5
289
+ };
290
+ function coerceLighterStatus(status) {
291
+ if (typeof status === "number") {
292
+ return status;
293
+ }
294
+ switch (status) {
295
+ case "confirmed":
296
+ return LIGHTER_TX_STATUS.EXECUTED;
297
+ case "failed":
298
+ return LIGHTER_TX_STATUS.FAILED;
299
+ default:
300
+ return LIGHTER_TX_STATUS.PENDING;
301
+ }
302
+ }
303
+ var LighterTerminalError = class extends Error {
304
+ };
305
+ async function pollLighterTransaction(txHash, options) {
306
+ const { pollIntervalMs, maxAttempts, waitFor } = options;
307
+ return retry(
308
+ async () => {
309
+ const resp = await fetch(
310
+ `${LIGHTER_API_BASE}/api/v1/tx?by=hash&value=${txHash}`
311
+ );
312
+ if (!resp.ok) {
313
+ throw new Error(`Lighter API error ${resp.status} for tx ${txHash}`);
314
+ }
315
+ const tx = await resp.json();
316
+ if (!tx.hash) {
317
+ throw new Error(`Lighter tx ${txHash} not found yet`);
318
+ }
319
+ const status = coerceLighterStatus(tx.status ?? LIGHTER_TX_STATUS.PENDING);
320
+ if (status === LIGHTER_TX_STATUS.FAILED || status === LIGHTER_TX_STATUS.REJECTED) {
321
+ const label = status === LIGHTER_TX_STATUS.FAILED ? "failed" : "rejected";
322
+ throw new LighterTerminalError(
323
+ `Lighter transaction ${label}: ${tx.message ?? "unknown error"}`
324
+ );
325
+ }
326
+ if (waitFor === "findable") {
327
+ return tx;
328
+ }
329
+ if (status === LIGHTER_TX_STATUS.COMMITTED || status === LIGHTER_TX_STATUS.EXECUTED) {
330
+ return tx;
331
+ }
332
+ throw new Error(
333
+ `Lighter transaction ${txHash} did not reach '${waitFor}' after ${maxAttempts} attempts`
334
+ );
335
+ },
336
+ {
337
+ maxAttempts,
338
+ delay: pollIntervalMs,
339
+ factor: 1,
340
+ jitter: false,
341
+ handleError: (err, context) => {
342
+ if (err instanceof LighterTerminalError) {
343
+ context.abort();
344
+ }
345
+ }
346
+ }
347
+ );
348
+ }
349
+ function createLighterAdaptedWallet({
350
+ signerClient,
351
+ accountIndex
352
+ }) {
353
+ async function handleSendTransactionStep(_chainId, stepItem) {
354
+ const action = stepItem.data?.action;
355
+ if (!action || action.type !== "transfer") {
356
+ throw new Error(
357
+ `Unsupported Lighter action: ${action?.type ?? "undefined"}`
358
+ );
359
+ }
360
+ const p = action.parameters;
361
+ logger.info("lighter:wallet:transfer", p);
362
+ const [, txHash, error] = await signerClient.transfer({
363
+ toAccountIndex: p.toAccountIndex,
364
+ assetIndex: p.assetIndex,
365
+ fromRouteType: p.fromRouteType,
366
+ toRouteType: p.toRouteType,
367
+ amount: p.amount,
368
+ usdcFee: p.usdcFee,
369
+ memo: p.memo
370
+ });
371
+ if (error) {
372
+ throw new Error(`Lighter transfer failed: ${error}`);
373
+ }
374
+ if (!txHash) {
375
+ throw new Error("Lighter transfer returned no transaction hash");
376
+ }
377
+ logger.info("lighter:wallet:transfer:done", { txHash });
378
+ return txHash;
379
+ }
380
+ return {
381
+ vmType: "lvm",
382
+ getChainId: async () => Number(RELAY_LIGHTER_CHAIN_ID),
383
+ address: async () => accountIndex.toString(),
384
+ handleSignMessageStep: async () => {
385
+ throw new Error("Message signing not implemented for Lighter");
386
+ },
387
+ handleSendTransactionStep,
388
+ handleConfirmTransactionStep: async (txHash) => {
389
+ const tx = await pollLighterTransaction(txHash, {
390
+ pollIntervalMs: 2e3,
391
+ maxAttempts: 60,
392
+ waitFor: "findable"
393
+ });
394
+ return {
395
+ txHash: tx.hash,
396
+ blockHeight: tx.block_height ?? 0,
397
+ status: tx.status
398
+ };
399
+ },
400
+ // biome-ignore lint/suspicious/noEmptyBlockStatements: Lighter is single-chain — no switching needed
401
+ switchChain: async () => {
402
+ }
403
+ };
404
+ }
405
+ function freeBalance(balance, lockedBalance) {
406
+ return String(Math.max(0, Number(balance) - Number(lockedBalance)));
407
+ }
408
+ function asLighterAccountIndex(s) {
409
+ if (!/^\d+$/.test(s)) {
410
+ throw new Error(`Invalid LighterAccountIndex: ${s}`);
411
+ }
412
+ return s;
413
+ }
414
+ function useLighterWithdrawalBalances({
415
+ accountIndex
416
+ }) {
417
+ const { account, isLoading, error } = useLighterAccount(
418
+ accountIndex ? { by: "index", value: accountIndex } : null
419
+ );
420
+ useEffect(() => {
421
+ logger.debug("lighter:withdrawal:balances:query", {
422
+ accountIndex,
423
+ isLoading,
424
+ hasAccount: !!account,
425
+ error: error instanceof Error ? error.message : error
426
+ });
427
+ }, [accountIndex, isLoading, account, error]);
428
+ const balances = useMemo2(() => {
429
+ if (!account) {
430
+ return {};
431
+ }
432
+ const result = {};
433
+ for (const asset of account.assets) {
434
+ const symbol = asset.symbol.toUpperCase();
435
+ if (symbol === "USDC") {
436
+ continue;
437
+ }
438
+ result[symbol] = freeBalance(asset.balance, asset.locked_balance);
439
+ }
440
+ result.USDC = account.total_asset_value;
441
+ logger.info("lighter:withdrawal:balances:resolved", {
442
+ accountIndex,
443
+ balances: result
444
+ });
445
+ return result;
446
+ }, [account, accountIndex]);
447
+ return {
448
+ balances,
449
+ assets: account?.assets ?? [],
450
+ isLoading
451
+ };
452
+ }
453
+ function buildSecureWithdrawalCallback({
454
+ exec
455
+ }) {
456
+ return async (param) => {
457
+ const { targetAssetAddress, destinationAddress } = param;
458
+ const assetIndex = param.lighterAssetIndex;
459
+ if (assetIndex === void 0) {
460
+ logger.error(
461
+ "lighter:withdrawal:secure:missingAssetIndex",
462
+ new Error("Missing lighterAssetIndex for Secure withdrawal"),
463
+ { targetAssetAddress, destinationAddress }
464
+ );
465
+ return;
466
+ }
467
+ const amountTokenUnits = param.userInputAmount;
468
+ if (!amountTokenUnits) {
469
+ logger.error(
470
+ "lighter:withdrawal:secure:missingAmount",
471
+ new Error("Missing userInputAmount for Secure withdrawal"),
472
+ { assetIndex, targetAssetAddress, destinationAddress }
473
+ );
474
+ return;
475
+ }
476
+ logger.info("lighter:withdrawal:secure:start", {
477
+ assetIndex,
478
+ amountTokenUnits,
479
+ targetAssetAddress,
480
+ destinationAddress
481
+ });
482
+ const txHash = await exec({
483
+ amountTokenUnits,
484
+ assetIndex
485
+ });
486
+ logger.info("lighter:withdrawal:secure:submitted", {
487
+ amountTokenUnits,
488
+ assetIndex,
489
+ txHash
490
+ });
491
+ return txHash;
492
+ };
493
+ }
494
+ function createLighterSecureWithdrawalConfig(config) {
495
+ return {
496
+ modalTitle: config.modalTitle ?? i18next.t("withdrawal.withdraw"),
497
+ disableConnectedWallet: config.disableConnectedWallet,
498
+ withdrawCallback: buildSecureWithdrawalCallback({
499
+ exec: config.sendLighterSecureWithdrawal
500
+ }),
501
+ sourceChainId: mainnet2.id.toString(),
502
+ sourceTokenSymbol: "USDC",
503
+ defaultReceiveToken: "USDC",
504
+ sourceTokenAddress: MAINNET_USDC,
505
+ iconSrc: config.iconSrc ?? "https://sdk-cdn.fun.xyz/images/logos/lighter.png",
506
+ getMinWithdrawalUSD: () => 0,
507
+ getMinWithdrawalAmount: config.getMinWithdrawalAmount
508
+ };
509
+ }
510
+ function buildLighterFastWalletWithdrawalConfig({
511
+ signerClient,
512
+ accountIndex,
513
+ modalTitle,
514
+ disableConnectedWallet,
515
+ iconSrc
516
+ }) {
517
+ const adaptedWallet = createLighterAdaptedWallet({
518
+ signerClient,
519
+ accountIndex
520
+ });
521
+ const wallet = {
522
+ _type: "lighter",
523
+ adaptedWallet,
524
+ address: () => String(accountIndex),
525
+ getChainId: async () => Number(RELAY_LIGHTER_CHAIN_ID),
526
+ // biome-ignore lint/suspicious/noEmptyBlockStatements: no-op — Lighter has no EVM chain switching
527
+ switchChain: async () => {
528
+ },
529
+ sendTransaction: async () => {
530
+ throw new Error("Use adaptedWallet for Lighter execution");
531
+ },
532
+ confirmTransaction: async () => {
533
+ throw new Error("Use adaptedWallet for Lighter execution");
534
+ }
535
+ };
536
+ return {
537
+ modalTitle: modalTitle ?? i18next.t("withdrawal.withdraw"),
538
+ disableConnectedWallet,
539
+ wallet,
540
+ sourceChainId: RELAY_LIGHTER_CHAIN_ID,
541
+ sourceTokenSymbol: "USDC",
542
+ defaultReceiveToken: "USDC",
543
+ sourceTokenAddress: LIGHTER_USDC_PERPS_ADDRESS,
544
+ iconSrc: iconSrc ?? "https://sdk-cdn.fun.xyz/images/logos/lighter.png",
545
+ getMinWithdrawalUSD: () => 4
546
+ };
547
+ }
548
+ function ChainIconStack({ chainIds }) {
549
+ return /* @__PURE__ */ React2.createElement(Box, { display: "flex", alignItems: "center", justifyContent: "flex-end" }, chainIds.map((chainId, index) => {
550
+ const metadata = chainMetadataById[chainId];
551
+ return /* @__PURE__ */ React2.createElement(
552
+ Box,
553
+ {
554
+ key: chainId,
555
+ position: "relative",
556
+ style: { right: `${(chainIds.length - index - 1) * -2}px` }
557
+ },
558
+ /* @__PURE__ */ React2.createElement(
559
+ AsyncImage,
560
+ {
561
+ alt: metadata?.name ?? "",
562
+ borderRadius: "full",
563
+ src: metadata?.iconUrl ?? "",
564
+ height: 16,
565
+ width: 16
566
+ }
567
+ )
568
+ );
569
+ }));
570
+ }
571
+ var LIGHTER_FAST_PREVIEW_CHAIN_IDS = [
572
+ arbitrum.id,
573
+ base.id,
574
+ optimism.id,
575
+ bsc.id,
576
+ SOLANA_MAINNET_CHAIN_ID
577
+ ];
578
+ var LIGHTER_SECURE_PREVIEW_CHAIN_IDS = [mainnet2.id];
579
+ function buildLighterMultiMethodConfig({
580
+ config,
581
+ t,
582
+ withBalance
583
+ }) {
584
+ const fastConfig = buildLighterFastWalletWithdrawalConfig({
585
+ signerClient: config.signerClient,
586
+ accountIndex: Number(config.accountIndex),
587
+ modalTitle: config.modalTitle,
588
+ disableConnectedWallet: config.disableConnectedWallet,
589
+ iconSrc: config.fastIconSrc
590
+ });
591
+ const secureConfig = createLighterSecureWithdrawalConfig({
592
+ accountIndex: config.accountIndex,
593
+ modalTitle: config.modalTitle,
594
+ disableConnectedWallet: config.disableConnectedWallet,
595
+ iconSrc: config.secureIconSrc,
596
+ sendLighterSecureWithdrawal: config.sendLighterSecureWithdrawal,
597
+ getMinWithdrawalAmount: config.getSecureMinWithdrawalAmount
598
+ });
599
+ const fast = {
600
+ id: "lighter-fast",
601
+ keyText: t("withdrawal.methodFast"),
602
+ subtitleText: t("withdrawal.fastDisclaimer"),
603
+ icon: /* @__PURE__ */ React2.createElement(EvmWallet, { size: 20 }),
604
+ valueIcon: /* @__PURE__ */ React2.createElement(ChainIconStack, { chainIds: LIGHTER_FAST_PREVIEW_CHAIN_IDS }),
605
+ config: withBalance ? {
606
+ ...fastConfig,
607
+ withdrawalSourceTokenBalance: withBalance(
608
+ fastConfig.sourceTokenSymbol
609
+ )
610
+ } : fastConfig
611
+ };
612
+ const secure = {
613
+ id: "lighter-secure",
614
+ keyText: t("withdrawal.methodSecure"),
615
+ subtitleText: t("withdrawal.secureDisclaimer"),
616
+ icon: /* @__PURE__ */ React2.createElement(EvmWallet, { size: 20 }),
617
+ valueIcon: /* @__PURE__ */ React2.createElement(ChainIconStack, { chainIds: LIGHTER_SECURE_PREVIEW_CHAIN_IDS }),
618
+ config: withBalance ? {
619
+ ...secureConfig,
620
+ withdrawalSourceTokenBalance: withBalance(
621
+ secureConfig.sourceTokenSymbol
622
+ )
623
+ } : secureConfig
624
+ };
625
+ return {
626
+ modalTitle: config.modalTitle ?? t("withdrawal.withdraw"),
627
+ sectionTitle: t("withdrawal.sectionCrypto"),
628
+ methods: [fast, secure]
629
+ };
630
+ }
631
+ function useLighterWithdrawalConfig(config) {
632
+ const { t } = useFunkitTranslation();
633
+ const { balances } = useLighterWithdrawalBalances({
634
+ accountIndex: asLighterAccountIndex(config.accountIndex)
635
+ });
636
+ return useMemo2(
637
+ () => buildLighterMultiMethodConfig({
638
+ config,
639
+ t,
640
+ withBalance: (symbol) => () => balances[symbol.toUpperCase()] ?? "0"
641
+ }),
642
+ [config, balances, t]
643
+ );
644
+ }
645
+ function createLighterWithdrawalConfig(config) {
646
+ return buildLighterMultiMethodConfig({
647
+ config,
648
+ t: i18next.t.bind(i18next)
649
+ });
650
+ }
651
+ export {
652
+ createLighterSecureWithdrawalConfig,
653
+ createLighterWithdrawalConfig,
654
+ freeBalance,
655
+ useLighterWithdrawalBalances,
656
+ useLighterWithdrawalConfig
657
+ };
@@ -2,27 +2,13 @@ import React from 'react';
2
2
  import { type BoxProps } from '../Box/Box';
3
3
  import { type BaseActiveDropdownItemProps } from './BaseActiveDropdownItem';
4
4
  import './BaseDropdownAnimation.css';
5
+ import { type BaseDropdownGroup, type BaseDropdownOption } from './BaseDropdown.utils';
6
+ export type { BaseDropdownGroup, BaseDropdownOption, } from './BaseDropdown.utils';
7
+ export { NO_SELECTION_VALUE } from './BaseDropdown.utils';
5
8
  /** gap between the icon and the label of the item */
6
9
  export declare const HORIZONTAL_ICON_GAP = "4";
7
10
  /** safe spacing, ie. padding, on the left & right of the active item and dropdown item */
8
11
  export declare const HORIZONTAL_OUTER_PADDING_X = "12";
9
- export declare const NO_SELECTION_VALUE = "";
10
- export interface BaseDropdownOption<T = string, G extends string = never> {
11
- label: string;
12
- value: T;
13
- /**
14
- * For grouped dropdowns, this is the {@link BaseDropdownGroup.key} of the group this option belongs to.
15
- *
16
- * If omitted, or if no group has the key, the option is treated as ungrouped.
17
- *
18
- * _See {@link BaseDropdownProps.groups} and {@link BaseDropdownProps.showOthersGroup}_
19
- */
20
- group?: G;
21
- }
22
- export interface BaseDropdownGroup<G extends string> {
23
- key: G;
24
- label: string;
25
- }
26
12
  export interface BaseDropdownProps<T = string, G extends string = never> {
27
13
  value: string;
28
14
  activeItemProps?: Partial<Pick<BaseActiveDropdownItemProps, 'iconComponent' | 'label' | 'color' | 'alwaysVisibleLabel' | 'tagComponent' | 'tagPosition' | 'background'>>;
@@ -31,7 +17,7 @@ export interface BaseDropdownProps<T = string, G extends string = never> {
31
17
  *
32
18
  * _Defaults to ungrouped dropdown behavior_
33
19
  */
34
- groups?: BaseDropdownGroup<G>[];
20
+ groups?: BaseDropdownGroup<T, G>[];
35
21
  /**
36
22
  * Additional group displayed after configured groups (only if there are non-empty groups).
37
23
  * - "all": display all options (grouped options will effectively be shown twice in total)
@@ -56,10 +42,10 @@ export interface BaseDropdownProps<T = string, G extends string = never> {
56
42
  * Label for {@link allowUnselect}
57
43
  */
58
44
  unselectLabel?: string;
59
- options: BaseDropdownOption<T, G>[];
45
+ options: BaseDropdownOption<T>[];
60
46
  onOpen?: () => void;
61
- onOptionSelected?: (item: BaseDropdownOption<T, G>) => void;
62
- renderDropdownOption: (item: BaseDropdownOption<T, G>, isSelected: boolean) => React.ReactNode;
47
+ onOptionSelected?: (item: BaseDropdownOption<T>) => void;
48
+ renderDropdownOption: (item: BaseDropdownOption<T>, isSelected: boolean) => React.ReactNode;
63
49
  searchableOptions?: boolean;
64
50
  searchPlaceholder?: string;
65
51
  placeholder?: string;