@turtleclub/hooks 0.5.0-beta.41 → 0.5.0-beta.42

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/index.cjs CHANGED
@@ -140,7 +140,10 @@ __export(index_exports, {
140
140
  productsQueries: () => productsQueries,
141
141
  queries: () => queries,
142
142
  requestStreamSignature: () => requestStreamSignature,
143
+ routeMetadataSchema: () => routeMetadataSchema,
144
+ routeStepSchema: () => routeStepSchema,
143
145
  routeToken: () => routeToken,
146
+ routeTokenSchema: () => routeTokenSchema,
144
147
  routerStep: () => routerStep,
145
148
  routerSubstep: () => routerSubstep,
146
149
  snapshotSchema: () => snapshotSchema,
@@ -165,7 +168,7 @@ __export(index_exports, {
165
168
  transactionSchema: () => transactionSchema,
166
169
  txResponseItemSchema: () => txResponseItemSchema,
167
170
  useAttributeAction: () => useAttributeAction,
168
- useBalance: () => useBalance,
171
+ useBalance: () => useBalance2,
169
172
  useCancelDepositAction: () => useCancelDepositAction,
170
173
  useCancelWithdrawAction: () => useCancelWithdrawAction,
171
174
  useCheckMembership: () => useCheckMembership,
@@ -179,7 +182,11 @@ __export(index_exports, {
179
182
  useCreateWithdrawInteraction: () => useCreateWithdrawInteraction,
180
183
  useDeleteProduct: () => useDeleteProduct,
181
184
  useDepositAction: () => useDepositAction,
185
+ useDepositFlow: () => useDepositFlow,
186
+ useDepositSelection: () => useDepositSelection,
187
+ useDepositValidation: () => useDepositValidation,
182
188
  useDeposits: () => useDeposits,
189
+ useEarnDeposit: () => useEarnDeposit,
183
190
  useEarnOpportunities: () => useEarnOpportunities,
184
191
  useEarnRoute: () => useEarnRoute,
185
192
  useEnsoBalances: () => useEnsoBalances,
@@ -384,6 +391,14 @@ var vaultConfigSchema = import_zod.z.object({
384
391
  managementFee: import_zod.z.number().min(0).max(100).optional().nullable(),
385
392
  depositFee: import_zod.z.number().min(0).max(100).optional().nullable(),
386
393
  withdrawalFee: import_zod.z.number().min(0).max(100).optional().nullable(),
394
+ minDepositAmount: import_zod.z.number().optional().nullable(),
395
+ minDepositValueUSD: import_zod.z.number().optional().nullable(),
396
+ depositCapAmount: import_zod.z.number().optional().nullable(),
397
+ depositFillSecs: import_zod.z.number().int().optional().nullable(),
398
+ lockupPeriodSecs: import_zod.z.number().int().optional().nullable(),
399
+ asyncDeposit: import_zod.z.boolean().optional().nullable(),
400
+ asyncWithdraw: import_zod.z.boolean().optional().nullable(),
401
+ secondaryOnly: import_zod.z.boolean().optional().nullable(),
387
402
  createdAt: import_zod.z.string().datetime().optional(),
388
403
  updatedAt: import_zod.z.string().datetime().optional()
389
404
  });
@@ -1880,15 +1895,259 @@ function useCreateMembership() {
1880
1895
  }
1881
1896
 
1882
1897
  // src/v2/earn-deposits/hooks.ts
1883
- var import_react_query4 = require("@tanstack/react-query");
1884
- function useDeposits({ params, enabled = true }) {
1885
- return (0, import_react_query4.useQuery)({
1886
- ...earnDepositsQueries.byParams(params),
1887
- ...queryDefaults,
1888
- enabled
1889
- });
1898
+ var import_react_query6 = require("@tanstack/react-query");
1899
+
1900
+ // src/v2/earn-deposits/hooks/useDepositValidation.ts
1901
+ var import_react = require("react");
1902
+ var import_viem = require("viem");
1903
+ function calculateUsdValue(amount, token) {
1904
+ if (!token.priceUsd) return null;
1905
+ const formatted = parseFloat((0, import_viem.formatUnits)(amount, token.decimals));
1906
+ return formatted * token.priceUsd;
1907
+ }
1908
+ function useDepositValidation({
1909
+ opportunity,
1910
+ selectedTokenBalance,
1911
+ amountBigInt,
1912
+ isPending = false,
1913
+ isConfirming = false,
1914
+ walletChainId
1915
+ }) {
1916
+ return (0, import_react.useMemo)(() => {
1917
+ if (!opportunity) {
1918
+ return {
1919
+ canDeposit: false,
1920
+ isBelowMinimum: false,
1921
+ isAboveMaximum: false,
1922
+ hasInsufficientBalance: false,
1923
+ isDepositDisabled: false,
1924
+ isZeroAmount: true,
1925
+ isNoTokenSelected: true,
1926
+ minDepositUSD: 0,
1927
+ maxDepositUSD: null,
1928
+ depositDisabledReason: null,
1929
+ depositFee: null,
1930
+ performanceFee: null,
1931
+ managementFee: null,
1932
+ withdrawalFee: null,
1933
+ withdrawalCooldownSecs: null,
1934
+ inputAmountUSD: null,
1935
+ balanceUSD: null,
1936
+ hasAsyncDeposit: false,
1937
+ isSecondaryOnly: false,
1938
+ isWrongChain: false,
1939
+ requiredChainId: null,
1940
+ buttonText: "Select opportunity",
1941
+ validationMessage: "Please select an opportunity"
1942
+ };
1943
+ }
1944
+ const vaultConfig = opportunity.vaultConfig;
1945
+ const depositDisabled = opportunity.depositDisabled ?? false;
1946
+ const depositDisabledReason = opportunity.depositDisabledReason || null;
1947
+ const depositFee = vaultConfig?.depositFee ?? null;
1948
+ const performanceFee = vaultConfig?.performanceFee ?? null;
1949
+ const managementFee = vaultConfig?.managementFee ?? null;
1950
+ const withdrawalFee = vaultConfig?.withdrawalFee ?? null;
1951
+ const withdrawalCooldownSecs = vaultConfig?.withdrawalCooldownSecs ?? null;
1952
+ const hasAsyncDeposit = vaultConfig?.asyncDeposit === true;
1953
+ const isSecondaryOnly = vaultConfig?.secondaryOnly === true;
1954
+ const requiredChainId = Number(opportunity.receiptToken.chain.chainId);
1955
+ const isWrongChain = walletChainId !== void 0 && walletChainId !== requiredChainId;
1956
+ const isNoTokenSelected = !selectedTokenBalance;
1957
+ const isZeroAmount = !amountBigInt || amountBigInt <= 0n;
1958
+ const depositTokenPrice = selectedTokenBalance?.token.priceUsd ?? null;
1959
+ let inputAmountUSD = null;
1960
+ let balanceUSD = null;
1961
+ if (selectedTokenBalance && amountBigInt) {
1962
+ inputAmountUSD = calculateUsdValue(amountBigInt, selectedTokenBalance.token);
1963
+ }
1964
+ if (selectedTokenBalance) {
1965
+ const balanceAmount = BigInt(selectedTokenBalance.amount);
1966
+ balanceUSD = calculateUsdValue(balanceAmount, selectedTokenBalance.token);
1967
+ }
1968
+ const minDepositAmount = vaultConfig?.minDepositAmount ?? 0;
1969
+ const minDepositValueUSD = vaultConfig?.minDepositValueUSD ?? 0;
1970
+ const minDepositUSD = Math.max(
1971
+ minDepositAmount * (depositTokenPrice ?? 0),
1972
+ minDepositValueUSD
1973
+ );
1974
+ const depositCapAmount = vaultConfig?.depositCapAmount;
1975
+ const maxDepositUSD = depositCapAmount && depositTokenPrice ? depositCapAmount * depositTokenPrice : null;
1976
+ let hasInsufficientBalance = false;
1977
+ if (selectedTokenBalance && amountBigInt) {
1978
+ const balanceAmount = BigInt(selectedTokenBalance.amount);
1979
+ hasInsufficientBalance = amountBigInt > balanceAmount;
1980
+ }
1981
+ const isBelowMinimum = !!(inputAmountUSD !== null && minDepositUSD > 0 && inputAmountUSD < minDepositUSD);
1982
+ const isAboveMaximum = !!(inputAmountUSD !== null && maxDepositUSD !== null && inputAmountUSD > maxDepositUSD);
1983
+ let buttonText;
1984
+ let validationMessage = null;
1985
+ if (isWrongChain) {
1986
+ buttonText = "Switch chain";
1987
+ } else if (isPending) {
1988
+ buttonText = "Confirming...";
1989
+ } else if (isConfirming) {
1990
+ buttonText = "Processing...";
1991
+ } else if (depositDisabled) {
1992
+ buttonText = depositDisabledReason || "Deposits disabled";
1993
+ validationMessage = depositDisabledReason || "Deposits are currently disabled for this opportunity";
1994
+ } else if (isNoTokenSelected) {
1995
+ buttonText = "Select token";
1996
+ validationMessage = "Please select a token to deposit";
1997
+ } else if (isZeroAmount) {
1998
+ buttonText = "Enter amount";
1999
+ } else if (hasInsufficientBalance) {
2000
+ buttonText = "Insufficient balance";
2001
+ validationMessage = "Your balance is insufficient for this deposit amount";
2002
+ } else if (isBelowMinimum) {
2003
+ buttonText = `Minimum $${minDepositUSD.toLocaleString()}`;
2004
+ validationMessage = `Minimum deposit is $${minDepositUSD.toLocaleString()}`;
2005
+ } else if (isAboveMaximum && maxDepositUSD != null) {
2006
+ buttonText = `Maximum $${maxDepositUSD.toLocaleString()}`;
2007
+ validationMessage = `Maximum deposit is $${maxDepositUSD.toLocaleString()}`;
2008
+ } else if (isSecondaryOnly) {
2009
+ buttonText = "Buy";
2010
+ } else if (hasAsyncDeposit) {
2011
+ buttonText = "Request deposit";
2012
+ } else {
2013
+ buttonText = "Deposit";
2014
+ }
2015
+ const isDepositing = isPending || isConfirming;
2016
+ const canDeposit = !depositDisabled && !isDepositing && !isNoTokenSelected && !isZeroAmount && !hasInsufficientBalance && !isBelowMinimum && !isAboveMaximum;
2017
+ return {
2018
+ canDeposit,
2019
+ isBelowMinimum,
2020
+ isAboveMaximum,
2021
+ hasInsufficientBalance,
2022
+ isDepositDisabled: depositDisabled,
2023
+ isZeroAmount,
2024
+ isNoTokenSelected,
2025
+ minDepositUSD,
2026
+ maxDepositUSD,
2027
+ depositDisabledReason,
2028
+ depositFee,
2029
+ performanceFee,
2030
+ managementFee,
2031
+ withdrawalFee,
2032
+ withdrawalCooldownSecs,
2033
+ inputAmountUSD,
2034
+ balanceUSD,
2035
+ hasAsyncDeposit,
2036
+ isSecondaryOnly,
2037
+ isWrongChain,
2038
+ requiredChainId,
2039
+ buttonText,
2040
+ validationMessage
2041
+ };
2042
+ }, [opportunity, selectedTokenBalance, amountBigInt, isPending, isConfirming, walletChainId]);
2043
+ }
2044
+
2045
+ // src/v2/earn-deposits/hooks/useDepositSelection.ts
2046
+ var import_react3 = require("react");
2047
+
2048
+ // src/v2/balance/hooks/useTokenBalance.ts
2049
+ var import_react2 = require("react");
2050
+ var import_viem2 = require("viem");
2051
+ var import_utils2 = require("@turtleclub/utils");
2052
+ function checkInsufficientBalance(tokenBalance, amount) {
2053
+ if (!tokenBalance || !amount) return false;
2054
+ try {
2055
+ const balance = BigInt(tokenBalance.amount);
2056
+ const amountBigInt = (0, import_viem2.parseUnits)(amount, tokenBalance.token.decimals);
2057
+ return balance < amountBigInt;
2058
+ } catch (error) {
2059
+ console.error("[Balance Check Error]", error, { tokenBalance, amount });
2060
+ return true;
2061
+ }
2062
+ }
2063
+ function useTokenBalance({ tokenBalance, amount, setAmount }) {
2064
+ const token = tokenBalance?.token;
2065
+ const usdValue = (0, import_react2.useMemo)(
2066
+ () => (0, import_utils2.calculateUsdValue)(amount, token?.priceUsd),
2067
+ [amount, token?.priceUsd]
2068
+ );
2069
+ const hasInsufficientBalance = (0, import_react2.useMemo)(
2070
+ () => checkInsufficientBalance(tokenBalance, amount),
2071
+ [tokenBalance, amount]
2072
+ );
2073
+ const handleMaxClick = (0, import_react2.useCallback)(() => {
2074
+ if (!tokenBalance?.token || !tokenBalance.amount) return;
2075
+ const maxAmount = (0, import_utils2.calculateMaxAmount)(tokenBalance.amount, tokenBalance.token.decimals);
2076
+ setAmount(maxAmount);
2077
+ }, [tokenBalance, setAmount]);
2078
+ const amountBigInt = (0, import_react2.useMemo)(() => {
2079
+ if (!token || !amount) return void 0;
2080
+ try {
2081
+ return (0, import_viem2.parseUnits)(amount, token.decimals);
2082
+ } catch {
2083
+ return void 0;
2084
+ }
2085
+ }, [amount, token]);
2086
+ return {
2087
+ usdValue,
2088
+ hasInsufficientBalance,
2089
+ handleMaxClick,
2090
+ amountBigInt
2091
+ };
1890
2092
  }
1891
2093
 
2094
+ // src/v2/earn-deposits/hooks/useDepositSelection.ts
2095
+ function useDepositSelection({
2096
+ balances,
2097
+ opportunityId
2098
+ }) {
2099
+ const [selectedTokenAddress, setSelectedTokenAddress] = (0, import_react3.useState)();
2100
+ const [amount, setAmount] = (0, import_react3.useState)();
2101
+ (0, import_react3.useEffect)(() => {
2102
+ setSelectedTokenAddress(void 0);
2103
+ setAmount(void 0);
2104
+ }, [opportunityId]);
2105
+ (0, import_react3.useEffect)(() => {
2106
+ if (balances.length === 0) return;
2107
+ const tokenExistsInBalances = balances.some(
2108
+ (b) => b.token.address === selectedTokenAddress
2109
+ );
2110
+ if (!selectedTokenAddress || !tokenExistsInBalances) {
2111
+ setSelectedTokenAddress(balances[0].token.address);
2112
+ }
2113
+ }, [selectedTokenAddress, balances]);
2114
+ const selectedTokenBalance = (0, import_react3.useMemo)(
2115
+ () => balances.find((b) => b.token.address === selectedTokenAddress) ?? null,
2116
+ [balances, selectedTokenAddress]
2117
+ );
2118
+ const { handleMaxClick, amountBigInt, usdValue, hasInsufficientBalance } = useTokenBalance({
2119
+ tokenBalance: selectedTokenBalance,
2120
+ amount,
2121
+ setAmount
2122
+ });
2123
+ const reset = (0, import_react3.useCallback)(() => {
2124
+ setSelectedTokenAddress(void 0);
2125
+ setAmount(void 0);
2126
+ }, []);
2127
+ return {
2128
+ selectedTokenAddress,
2129
+ setSelectedTokenAddress,
2130
+ amount,
2131
+ setAmount,
2132
+ selectedTokenBalance,
2133
+ amountBigInt,
2134
+ usdValue,
2135
+ hasInsufficientBalance,
2136
+ handleMaxClick,
2137
+ reset
2138
+ };
2139
+ }
2140
+
2141
+ // src/v2/earn-deposits/hooks/useDepositFlow.ts
2142
+ var import_react5 = require("react");
2143
+
2144
+ // src/v2/earn-actions/useEarnDeposit.ts
2145
+ var import_react4 = require("react");
2146
+ var import_react_query5 = require("@tanstack/react-query");
2147
+
2148
+ // src/v2/earn-actions/hooks.ts
2149
+ var import_react_query4 = require("@tanstack/react-query");
2150
+
1892
2151
  // src/v2/earn-actions/schema.ts
1893
2152
  var import_zod14 = require("zod");
1894
2153
  var transactionSchema = import_zod14.z.object({
@@ -1898,10 +2157,29 @@ var transactionSchema = import_zod14.z.object({
1898
2157
  value: import_zod14.z.string(),
1899
2158
  gasLimit: import_zod14.z.string().optional()
1900
2159
  });
2160
+ var routeTokenSchema = import_zod14.z.object({
2161
+ address: import_zod14.z.string(),
2162
+ symbol: import_zod14.z.string(),
2163
+ decimals: import_zod14.z.number().int(),
2164
+ logoUrl: import_zod14.z.string()
2165
+ });
2166
+ var routeStepSchema = import_zod14.z.object({
2167
+ action: import_zod14.z.string(),
2168
+ from: routeTokenSchema,
2169
+ to: routeTokenSchema
2170
+ });
2171
+ var routeMetadataSchema = import_zod14.z.object({
2172
+ provider: import_zod14.z.string(),
2173
+ providerImg: import_zod14.z.string(),
2174
+ amountOut: import_zod14.z.string(),
2175
+ gas: import_zod14.z.string(),
2176
+ route: import_zod14.z.array(routeStepSchema)
2177
+ });
1901
2178
  var txResponseItemSchema = import_zod14.z.object({
1902
2179
  type: import_zod14.z.string().optional(),
1903
2180
  description: import_zod14.z.string().optional(),
1904
- transaction: transactionSchema
2181
+ transaction: transactionSchema,
2182
+ metadata: routeMetadataSchema.optional()
1905
2183
  });
1906
2184
  var actionResponseSchema = import_zod14.z.object({
1907
2185
  actionId: import_zod14.z.string().uuid().optional(),
@@ -1975,10 +2253,9 @@ var createWithdrawInteraction = createWithdrawAction;
1975
2253
  var createClaimWithdrawInteraction = createClaimWithdrawAction;
1976
2254
 
1977
2255
  // src/v2/earn-actions/hooks.ts
1978
- var import_react_query5 = require("@tanstack/react-query");
1979
2256
  function createActionHook(mutationFn) {
1980
2257
  return function useAction(options) {
1981
- return (0, import_react_query5.useMutation)({
2258
+ return (0, import_react_query4.useMutation)({
1982
2259
  mutationFn,
1983
2260
  ...options
1984
2261
  });
@@ -1991,7 +2268,7 @@ var useClaimDepositAction = createActionHook(createClaimDepositAction);
1991
2268
  var useCancelDepositAction = createActionHook(createCancelDepositAction);
1992
2269
  var useCancelWithdrawAction = createActionHook(createCancelWithdrawAction);
1993
2270
  function useAttributeAction(options) {
1994
- return (0, import_react_query5.useMutation)({
2271
+ return (0, import_react_query4.useMutation)({
1995
2272
  mutationFn: attributeAction,
1996
2273
  ...options
1997
2274
  });
@@ -2000,14 +2277,277 @@ var useCreateDepositInteraction = useDepositAction;
2000
2277
  var useCreateWithdrawInteraction = useWithdrawAction;
2001
2278
  var useCreateClaimWithdrawInteraction = useClaimWithdrawAction;
2002
2279
 
2280
+ // src/v2/balance/queries.ts
2281
+ var import_query_key_factory15 = require("@lukemorales/query-key-factory");
2282
+
2283
+ // src/v2/balance/schema.ts
2284
+ var import_zod15 = require("zod");
2285
+ var portfolioTokenSchema = import_zod15.z.object({
2286
+ id: import_zod15.z.string(),
2287
+ address: import_zod15.z.string(),
2288
+ name: import_zod15.z.string(),
2289
+ symbol: import_zod15.z.string(),
2290
+ decimals: import_zod15.z.number(),
2291
+ isNative: import_zod15.z.boolean(),
2292
+ logoUrl: import_zod15.z.string().nullable(),
2293
+ amount: import_zod15.z.string(),
2294
+ // Portfolio-specific field (decimal format)
2295
+ price: import_zod15.z.string().nullable().transform((val) => val ? parseFloat(val) : null),
2296
+ // Portfolio-specific field
2297
+ // Chain with optional fields to match Portfolio API response
2298
+ chain: chainSchema.partial().required({ chainId: true })
2299
+ });
2300
+ var portfolioWalletSchema = import_zod15.z.object({
2301
+ id: import_zod15.z.string().optional(),
2302
+ address: import_zod15.z.string(),
2303
+ blockchain: import_zod15.z.string().optional(),
2304
+ tokens: import_zod15.z.array(portfolioTokenSchema)
2305
+ });
2306
+ var portfolioHoldingsSchema = import_zod15.z.object({
2307
+ wallets: import_zod15.z.array(portfolioWalletSchema)
2308
+ });
2309
+ var portfolioBalanceResponseSchema = import_zod15.z.object({
2310
+ portfolio: import_zod15.z.object({
2311
+ holdings: portfolioHoldingsSchema
2312
+ })
2313
+ });
2314
+
2315
+ // src/v2/balance/api.ts
2316
+ async function getPortfolioBalance(address, options) {
2317
+ const data = await apiClient.fetch(`/wallet/${address}/balance`, {
2318
+ method: "GET",
2319
+ domain: "api",
2320
+ debug: options?.debug
2321
+ });
2322
+ const result = portfolioBalanceResponseSchema.safeParse(data);
2323
+ if (result.success === false) {
2324
+ console.log("[ZOD ERROR]", result.error);
2325
+ throw new Error(`Failed to parse portfolio balance: ${result.error.message}`);
2326
+ }
2327
+ return result.data;
2328
+ }
2329
+
2330
+ // src/v2/balance/queries.ts
2331
+ var balanceQueries = (0, import_query_key_factory15.createQueryKeys)("balance", {
2332
+ // Portfolio balance by address
2333
+ portfolio: (address) => ({
2334
+ queryKey: [address],
2335
+ queryFn: () => getPortfolioBalance(address)
2336
+ })
2337
+ });
2338
+
2339
+ // src/v2/earn-actions/useEarnDeposit.ts
2340
+ var DEFAULT_SLIPPAGE_BPS = 50;
2341
+ function useEarnDeposit(options) {
2342
+ const { opportunity, userAddress, distributorId, executeTransaction, onSuccess, referralCode } = options;
2343
+ const queryClient = (0, import_react_query5.useQueryClient)();
2344
+ const [isConfirming, setIsConfirming] = (0, import_react4.useState)(false);
2345
+ const [error, setError] = (0, import_react4.useState)(null);
2346
+ const [metadata, setMetadata] = (0, import_react4.useState)(null);
2347
+ const [hasApprove, setHasApprove] = (0, import_react4.useState)(false);
2348
+ const depositAction = useDepositAction();
2349
+ const attributeAction2 = useAttributeAction();
2350
+ const toTransactionRequest = (0, import_react4.useCallback)((txItem) => {
2351
+ return {
2352
+ to: txItem.transaction.to,
2353
+ data: txItem.transaction.data,
2354
+ value: txItem.transaction.value,
2355
+ gasLimit: txItem.transaction.gasLimit
2356
+ };
2357
+ }, []);
2358
+ const executeTransactionsSequentially = (0, import_react4.useCallback)(
2359
+ async (transactions) => {
2360
+ let lastTxHash;
2361
+ for (const txItem of transactions) {
2362
+ const txRequest = toTransactionRequest(txItem);
2363
+ const txHash = await executeTransaction(txRequest);
2364
+ if (!txHash) {
2365
+ throw new Error(`Transaction failed: ${txItem.description || "Unknown transaction"}`);
2366
+ }
2367
+ lastTxHash = txHash;
2368
+ }
2369
+ return lastTxHash;
2370
+ },
2371
+ [executeTransaction, toTransactionRequest]
2372
+ );
2373
+ const attributeTransactionSafely = (0, import_react4.useCallback)(
2374
+ async (actionId, txHash) => {
2375
+ try {
2376
+ await attributeAction2.mutateAsync({ actionId, txHash });
2377
+ } catch (attributeError) {
2378
+ console.warn("[useEarnDeposit] Attribution failed (non-blocking):", attributeError);
2379
+ }
2380
+ },
2381
+ [attributeAction2]
2382
+ );
2383
+ const deposit = (0, import_react4.useCallback)(
2384
+ async (amount, tokenAddress, slippage = DEFAULT_SLIPPAGE_BPS) => {
2385
+ setError(null);
2386
+ if (!opportunity?.id) {
2387
+ const err = new Error("No opportunity selected");
2388
+ setError(err);
2389
+ throw err;
2390
+ }
2391
+ if (!userAddress) {
2392
+ const err = new Error("No wallet connected");
2393
+ setError(err);
2394
+ throw err;
2395
+ }
2396
+ if (amount <= 0n) {
2397
+ const err = new Error("Amount must be greater than 0");
2398
+ setError(err);
2399
+ throw err;
2400
+ }
2401
+ try {
2402
+ const actionResponse = await depositAction.mutateAsync({
2403
+ opportunityId: opportunity.id,
2404
+ userAddress,
2405
+ tokenIn: tokenAddress,
2406
+ amount: amount.toString(),
2407
+ distributorId,
2408
+ referralCode,
2409
+ slippageBps: slippage
2410
+ });
2411
+ const { actionId, transactions } = actionResponse;
2412
+ if (!transactions || transactions.length === 0) {
2413
+ throw new Error("No transactions returned from deposit action");
2414
+ }
2415
+ const txWithMetadata = transactions.find((tx) => tx.metadata);
2416
+ if (txWithMetadata?.metadata) {
2417
+ setMetadata(txWithMetadata.metadata);
2418
+ }
2419
+ const hasApproveTx = transactions.some((tx) => tx.type === "approve");
2420
+ setHasApprove(hasApproveTx);
2421
+ setIsConfirming(true);
2422
+ const finalTxHash = await executeTransactionsSequentially(transactions);
2423
+ if (actionId && finalTxHash) {
2424
+ await attributeTransactionSafely(actionId, finalTxHash);
2425
+ }
2426
+ if (userAddress) {
2427
+ queryClient.invalidateQueries({
2428
+ queryKey: balanceQueries.portfolio(userAddress).queryKey
2429
+ });
2430
+ }
2431
+ onSuccess?.();
2432
+ return finalTxHash;
2433
+ } catch (err) {
2434
+ const error2 = err instanceof Error ? err : new Error(String(err));
2435
+ setError(error2);
2436
+ throw error2;
2437
+ } finally {
2438
+ setIsConfirming(false);
2439
+ }
2440
+ },
2441
+ [
2442
+ opportunity?.id,
2443
+ userAddress,
2444
+ distributorId,
2445
+ referralCode,
2446
+ depositAction,
2447
+ executeTransactionsSequentially,
2448
+ attributeTransactionSafely,
2449
+ queryClient,
2450
+ onSuccess
2451
+ ]
2452
+ );
2453
+ const resetMetadata = (0, import_react4.useCallback)(() => {
2454
+ setMetadata(null);
2455
+ setHasApprove(false);
2456
+ }, []);
2457
+ return {
2458
+ deposit,
2459
+ isPending: depositAction.isPending,
2460
+ isConfirming,
2461
+ error,
2462
+ metadata,
2463
+ hasApprove,
2464
+ resetMetadata
2465
+ };
2466
+ }
2467
+
2468
+ // src/v2/earn-deposits/hooks/useDepositFlow.ts
2469
+ function useDepositFlow({
2470
+ opportunity,
2471
+ userAddress,
2472
+ distributorId,
2473
+ balances,
2474
+ executeTransaction,
2475
+ onDepositSuccess,
2476
+ refetchBalances,
2477
+ slippageBps,
2478
+ walletChainId
2479
+ }) {
2480
+ const selection = useDepositSelection({
2481
+ balances,
2482
+ opportunityId: opportunity?.id
2483
+ });
2484
+ const {
2485
+ deposit: executeDeposit,
2486
+ isPending,
2487
+ isConfirming,
2488
+ error,
2489
+ metadata,
2490
+ hasApprove,
2491
+ resetMetadata
2492
+ } = useEarnDeposit({
2493
+ opportunity,
2494
+ userAddress,
2495
+ distributorId,
2496
+ executeTransaction,
2497
+ onSuccess: () => {
2498
+ selection.setAmount(void 0);
2499
+ refetchBalances?.();
2500
+ onDepositSuccess?.();
2501
+ }
2502
+ });
2503
+ const isDepositing = isPending || isConfirming;
2504
+ const validation = useDepositValidation({
2505
+ opportunity,
2506
+ selectedTokenBalance: selection.selectedTokenBalance,
2507
+ amountBigInt: selection.amountBigInt,
2508
+ isPending,
2509
+ isConfirming,
2510
+ walletChainId
2511
+ });
2512
+ const execute = (0, import_react5.useCallback)(async () => {
2513
+ if (!selection.amountBigInt || !selection.selectedTokenAddress) {
2514
+ return void 0;
2515
+ }
2516
+ return executeDeposit(selection.amountBigInt, selection.selectedTokenAddress, slippageBps);
2517
+ }, [selection.amountBigInt, selection.selectedTokenAddress, executeDeposit, slippageBps]);
2518
+ return {
2519
+ selection,
2520
+ validation,
2521
+ deposit: {
2522
+ execute,
2523
+ isPending,
2524
+ isConfirming,
2525
+ isDepositing,
2526
+ error,
2527
+ metadata,
2528
+ hasApprove,
2529
+ resetMetadata
2530
+ }
2531
+ };
2532
+ }
2533
+
2534
+ // src/v2/earn-deposits/hooks.ts
2535
+ function useDeposits({ params, enabled = true }) {
2536
+ return (0, import_react_query6.useQuery)({
2537
+ ...earnDepositsQueries.byParams(params),
2538
+ ...queryDefaults,
2539
+ enabled
2540
+ });
2541
+ }
2542
+
2003
2543
  // src/v2/enso-balances/hooks.ts
2004
- var import_react = require("react");
2005
- var import_react_query6 = require("@tanstack/react-query");
2544
+ var import_react6 = require("react");
2545
+ var import_react_query7 = require("@tanstack/react-query");
2006
2546
  function useMultiChainBalances({
2007
2547
  chainIds,
2008
2548
  address
2009
2549
  }) {
2010
- const queries2 = (0, import_react_query6.useQueries)({
2550
+ const queries2 = (0, import_react_query7.useQueries)({
2011
2551
  queries: chainIds.map((chainId) => ({
2012
2552
  ...ensoBalancesQueries.byParams({ user: address || "", chain: chainId }),
2013
2553
  enabled: !!address,
@@ -2024,7 +2564,7 @@ function useMultiChainBalances({
2024
2564
  query.refetch();
2025
2565
  });
2026
2566
  };
2027
- const balances = (0, import_react.useMemo)(() => {
2567
+ const balances = (0, import_react6.useMemo)(() => {
2028
2568
  const balanceMap = {};
2029
2569
  queries2.forEach((query, index) => {
2030
2570
  const chainId = chainIds[index];
@@ -2043,9 +2583,9 @@ function useMultiChainBalances({
2043
2583
  }
2044
2584
 
2045
2585
  // src/v2/opportunities/hooks.ts
2046
- var import_react_query7 = require("@tanstack/react-query");
2586
+ var import_react_query8 = require("@tanstack/react-query");
2047
2587
  function useOpportunities(options) {
2048
- return (0, import_react_query7.useQuery)({
2588
+ return (0, import_react_query8.useQuery)({
2049
2589
  ...opportunitiesQueries.all,
2050
2590
  ...queryDefaults,
2051
2591
  select: (data) => {
@@ -2061,7 +2601,7 @@ function useOpportunities(options) {
2061
2601
  });
2062
2602
  }
2063
2603
  function useOpportunity({ id, ...options }) {
2064
- return (0, import_react_query7.useQuery)({
2604
+ return (0, import_react_query8.useQuery)({
2065
2605
  ...opportunitiesQueries.byId(id),
2066
2606
  ...queryDefaults,
2067
2607
  select: (data) => {
@@ -2076,7 +2616,7 @@ function useOpportunitiesPaginated({
2076
2616
  params,
2077
2617
  enabled = true
2078
2618
  } = {}) {
2079
- return (0, import_react_query7.useQuery)({
2619
+ return (0, import_react_query8.useQuery)({
2080
2620
  ...opportunitiesQueries.paginated(params),
2081
2621
  ...queryDefaults,
2082
2622
  enabled
@@ -2085,7 +2625,7 @@ function useOpportunitiesPaginated({
2085
2625
  function useOpportunitiesFilterOptions({
2086
2626
  enabled = true
2087
2627
  } = {}) {
2088
- return (0, import_react_query7.useQuery)({
2628
+ return (0, import_react_query8.useQuery)({
2089
2629
  ...opportunitiesQueries.filterOptions,
2090
2630
  ...queryDefaults,
2091
2631
  enabled
@@ -2093,92 +2633,46 @@ function useOpportunitiesFilterOptions({
2093
2633
  }
2094
2634
 
2095
2635
  // src/v2/products/hooks.ts
2096
- var import_react_query8 = require("@tanstack/react-query");
2636
+ var import_react_query9 = require("@tanstack/react-query");
2097
2637
  function useProducts({ filters, enabled = true }) {
2098
- return (0, import_react_query8.useQuery)({
2638
+ return (0, import_react_query9.useQuery)({
2099
2639
  ...productsQueries.list(filters),
2100
2640
  ...queryDefaults,
2101
2641
  enabled
2102
2642
  });
2103
2643
  }
2104
2644
  function useProduct({ id, enabled = true }) {
2105
- return (0, import_react_query8.useQuery)({
2645
+ return (0, import_react_query9.useQuery)({
2106
2646
  ...productsQueries.byId(id),
2107
2647
  ...queryDefaults,
2108
2648
  enabled
2109
2649
  });
2110
2650
  }
2111
2651
  function useCreateProduct(options) {
2112
- return (0, import_react_query8.useMutation)({
2652
+ return (0, import_react_query9.useMutation)({
2113
2653
  mutationFn: (input) => createProduct(input),
2114
2654
  ...options
2115
2655
  });
2116
2656
  }
2117
2657
  function useUpdateProduct(options) {
2118
- return (0, import_react_query8.useMutation)({
2658
+ return (0, import_react_query9.useMutation)({
2119
2659
  mutationFn: (input) => updateProduct(input),
2120
2660
  ...options
2121
2661
  });
2122
2662
  }
2123
2663
  function useDeleteProduct(options) {
2124
- return (0, import_react_query8.useMutation)({
2664
+ return (0, import_react_query9.useMutation)({
2125
2665
  mutationFn: (id) => deleteProduct(id),
2126
2666
  ...options
2127
2667
  });
2128
2668
  }
2129
2669
  function useUploadProductLogo(options) {
2130
- return (0, import_react_query8.useMutation)({
2670
+ return (0, import_react_query9.useMutation)({
2131
2671
  mutationFn: (request) => uploadProductLogo(request),
2132
2672
  ...options
2133
2673
  });
2134
2674
  }
2135
2675
 
2136
- // src/v2/balance/hooks/useTokenBalance.ts
2137
- var import_react2 = require("react");
2138
- var import_viem = require("viem");
2139
- var import_utils2 = require("@turtleclub/utils");
2140
- function checkInsufficientBalance(tokenBalance, amount) {
2141
- if (!tokenBalance || !amount) return false;
2142
- try {
2143
- const balance = BigInt(tokenBalance.amount);
2144
- const amountBigInt = (0, import_viem.parseUnits)(amount, tokenBalance.token.decimals);
2145
- return balance < amountBigInt;
2146
- } catch (error) {
2147
- console.error("[Balance Check Error]", error, { tokenBalance, amount });
2148
- return true;
2149
- }
2150
- }
2151
- function useTokenBalance({ tokenBalance, amount, setAmount }) {
2152
- const token = tokenBalance?.token;
2153
- const usdValue = (0, import_react2.useMemo)(
2154
- () => (0, import_utils2.calculateUsdValue)(amount, token?.priceUsd),
2155
- [amount, token?.priceUsd]
2156
- );
2157
- const hasInsufficientBalance = (0, import_react2.useMemo)(
2158
- () => checkInsufficientBalance(tokenBalance, amount),
2159
- [tokenBalance, amount]
2160
- );
2161
- const handleMaxClick = (0, import_react2.useCallback)(() => {
2162
- if (!tokenBalance?.token || !tokenBalance.amount) return;
2163
- const maxAmount = (0, import_utils2.calculateMaxAmount)(tokenBalance.amount, tokenBalance.token.decimals);
2164
- setAmount(maxAmount);
2165
- }, [tokenBalance, setAmount]);
2166
- const amountBigInt = (0, import_react2.useMemo)(() => {
2167
- if (!token || !amount) return void 0;
2168
- try {
2169
- return (0, import_viem.parseUnits)(amount, token.decimals);
2170
- } catch {
2171
- return void 0;
2172
- }
2173
- }, [amount, token]);
2174
- return {
2175
- usdValue,
2176
- hasInsufficientBalance,
2177
- handleMaxClick,
2178
- amountBigInt
2179
- };
2180
- }
2181
-
2182
2676
  // src/v2/balance/types.ts
2183
2677
  var BalanceSourcePriority = /* @__PURE__ */ ((BalanceSourcePriority2) => {
2184
2678
  BalanceSourcePriority2[BalanceSourcePriority2["ONCHAIN"] = 1] = "ONCHAIN";
@@ -2187,115 +2681,116 @@ var BalanceSourcePriority = /* @__PURE__ */ ((BalanceSourcePriority2) => {
2187
2681
  return BalanceSourcePriority2;
2188
2682
  })(BalanceSourcePriority || {});
2189
2683
 
2190
- // src/v2/balance/schema.ts
2191
- var import_zod15 = require("zod");
2192
- var portfolioTokenSchema = import_zod15.z.object({
2193
- id: import_zod15.z.string(),
2194
- address: import_zod15.z.string(),
2195
- name: import_zod15.z.string(),
2196
- symbol: import_zod15.z.string(),
2197
- decimals: import_zod15.z.number(),
2198
- isNative: import_zod15.z.boolean(),
2199
- logoUrl: import_zod15.z.string().nullable(),
2200
- amount: import_zod15.z.string(),
2201
- // Portfolio-specific field (decimal format)
2202
- price: import_zod15.z.string().nullable().transform((val) => val ? parseFloat(val) : null),
2203
- // Portfolio-specific field
2204
- // Chain with optional fields to match Portfolio API response
2205
- chain: chainSchema.partial().required({ chainId: true })
2206
- });
2207
- var portfolioWalletSchema = import_zod15.z.object({
2208
- id: import_zod15.z.string().optional(),
2209
- address: import_zod15.z.string(),
2210
- blockchain: import_zod15.z.string().optional(),
2211
- tokens: import_zod15.z.array(portfolioTokenSchema)
2212
- });
2213
- var portfolioHoldingsSchema = import_zod15.z.object({
2214
- wallets: import_zod15.z.array(portfolioWalletSchema)
2215
- });
2216
- var portfolioBalanceResponseSchema = import_zod15.z.object({
2217
- portfolio: import_zod15.z.object({
2218
- holdings: portfolioHoldingsSchema
2219
- })
2220
- });
2221
-
2222
- // src/v2/balance/api.ts
2223
- async function getPortfolioBalance(address, options) {
2224
- const data = await apiClient.fetch(`/wallet/${address}/balance`, {
2225
- method: "GET",
2226
- domain: "api",
2227
- debug: options?.debug
2228
- });
2229
- const result = portfolioBalanceResponseSchema.safeParse(data);
2230
- if (result.success === false) {
2231
- console.log("[ZOD ERROR]", result.error);
2232
- throw new Error(`Failed to parse portfolio balance: ${result.error.message}`);
2233
- }
2234
- return result.data;
2235
- }
2236
-
2237
- // src/v2/balance/queries.ts
2238
- var import_query_key_factory15 = require("@lukemorales/query-key-factory");
2239
- var balanceQueries = (0, import_query_key_factory15.createQueryKeys)("balance", {
2240
- // Portfolio balance by address
2241
- portfolio: (address) => ({
2242
- queryKey: [address],
2243
- queryFn: () => getPortfolioBalance(address)
2244
- })
2245
- });
2246
-
2247
2684
  // src/v2/balance/hooks/useBalance.ts
2248
- var import_react7 = require("react");
2685
+ var import_react10 = require("react");
2249
2686
 
2250
2687
  // src/v2/balance/hooks/useGetOnChainBalance.ts
2251
2688
  var import_wagmi = require("wagmi");
2252
- var import_viem2 = require("viem");
2253
- var import_react3 = require("react");
2689
+ var import_viem3 = require("viem");
2690
+ var import_react7 = require("react");
2691
+ var NATIVE_TOKEN_ADDRESSES = [
2692
+ "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
2693
+ "0x0000000000000000000000000000000000000000"
2694
+ ];
2695
+ var QUERY_REFETCH_INTERVAL = 5e3;
2696
+ function isNativeToken(token) {
2697
+ return token.isNative || NATIVE_TOKEN_ADDRESSES.includes(token.address.toLowerCase());
2698
+ }
2254
2699
  function useGetOnChainBalance({
2255
2700
  tokens,
2256
2701
  chainId,
2257
2702
  address,
2258
2703
  enabled = true
2259
2704
  }) {
2260
- const contracts = (0, import_react3.useMemo)(() => {
2705
+ const { nativeTokens, erc20Tokens } = (0, import_react7.useMemo)(() => {
2706
+ const native = [];
2707
+ const erc20 = [];
2708
+ for (const token of tokens) {
2709
+ if (isNativeToken(token)) {
2710
+ native.push(token);
2711
+ } else {
2712
+ erc20.push(token);
2713
+ }
2714
+ }
2715
+ return { nativeTokens: native, erc20Tokens: erc20 };
2716
+ }, [tokens]);
2717
+ const nativeToken = nativeTokens[0];
2718
+ const {
2719
+ data: nativeBalanceData,
2720
+ isLoading: isNativeLoading,
2721
+ error: nativeError,
2722
+ refetch: refetchNative
2723
+ } = (0, import_wagmi.useBalance)({
2724
+ address,
2725
+ chainId,
2726
+ query: {
2727
+ ...queryDefaults,
2728
+ enabled: enabled && !!address && nativeTokens.length > 0,
2729
+ refetchInterval: QUERY_REFETCH_INTERVAL,
2730
+ refetchOnWindowFocus: true
2731
+ }
2732
+ });
2733
+ const contracts = (0, import_react7.useMemo)(() => {
2261
2734
  if (!address || !enabled) return [];
2262
- return tokens.map((token) => ({
2263
- address: token.address,
2264
- abi: import_viem2.erc20Abi,
2265
- functionName: "balanceOf",
2266
- args: [address],
2267
- chainId
2268
- }));
2269
- }, [tokens, address, chainId, enabled]);
2735
+ return erc20Tokens.map(
2736
+ (token) => ({
2737
+ address: token.address,
2738
+ abi: import_viem3.erc20Abi,
2739
+ functionName: "balanceOf",
2740
+ args: [address],
2741
+ chainId
2742
+ })
2743
+ );
2744
+ }, [erc20Tokens, address, chainId, enabled]);
2270
2745
  const {
2271
- data: results,
2272
- isLoading,
2273
- error,
2274
- refetch
2746
+ data: erc20Results,
2747
+ isLoading: isErc20Loading,
2748
+ error: erc20Error,
2749
+ refetch: refetchErc20
2275
2750
  } = (0, import_wagmi.useReadContracts)({
2276
2751
  contracts,
2277
2752
  query: {
2278
2753
  ...queryDefaults,
2279
- enabled: enabled && !!address && tokens.length > 0,
2280
- refetchInterval: 5e3,
2754
+ enabled: enabled && !!address && erc20Tokens.length > 0,
2755
+ refetchInterval: QUERY_REFETCH_INTERVAL,
2281
2756
  refetchOnWindowFocus: true
2282
2757
  }
2283
2758
  });
2284
- const balances = (0, import_react3.useMemo)(() => {
2285
- if (!results || results.length === 0) return [];
2286
- return tokens.map((token, index) => {
2287
- const result = results[index];
2288
- let balance = "0";
2289
- if (result?.status === "success" && typeof result.result === "bigint") {
2290
- balance = result.result.toString();
2291
- }
2292
- return {
2293
- token,
2294
- amount: balance,
2759
+ const balances = (0, import_react7.useMemo)(() => {
2760
+ const result = [];
2761
+ if (nativeToken && nativeBalanceData) {
2762
+ result.push({
2763
+ token: nativeToken,
2764
+ amount: nativeBalanceData.value.toString(),
2295
2765
  source: "onchain"
2296
- };
2297
- });
2298
- }, [results, tokens]);
2766
+ });
2767
+ }
2768
+ if (erc20Results && erc20Results.length > 0) {
2769
+ erc20Tokens.forEach((token, index) => {
2770
+ const erc20Result = erc20Results[index];
2771
+ let balance = "0";
2772
+ if (erc20Result?.status === "success" && typeof erc20Result.result === "bigint") {
2773
+ balance = erc20Result.result.toString();
2774
+ }
2775
+ result.push({
2776
+ token,
2777
+ amount: balance,
2778
+ source: "onchain"
2779
+ });
2780
+ });
2781
+ }
2782
+ return result;
2783
+ }, [nativeToken, nativeBalanceData, erc20Results, erc20Tokens]);
2784
+ const isLoading = nativeTokens.length > 0 && isNativeLoading || erc20Tokens.length > 0 && isErc20Loading;
2785
+ const error = nativeError || erc20Error;
2786
+ const refetch = (0, import_react7.useCallback)(() => {
2787
+ if (nativeTokens.length > 0) {
2788
+ refetchNative();
2789
+ }
2790
+ if (erc20Tokens.length > 0) {
2791
+ refetchErc20();
2792
+ }
2793
+ }, [nativeTokens.length, erc20Tokens.length, refetchNative, refetchErc20]);
2299
2794
  return {
2300
2795
  balances,
2301
2796
  isLoading,
@@ -2305,13 +2800,13 @@ function useGetOnChainBalance({
2305
2800
  }
2306
2801
 
2307
2802
  // src/v2/balance/hooks/usePortfolioBalance.ts
2308
- var import_react_query11 = require("@tanstack/react-query");
2309
- var import_react5 = require("react");
2803
+ var import_react_query12 = require("@tanstack/react-query");
2804
+ var import_react9 = require("react");
2310
2805
 
2311
2806
  // src/v2/supported-chains/hooks.ts
2312
- var import_react_query9 = require("@tanstack/react-query");
2807
+ var import_react_query10 = require("@tanstack/react-query");
2313
2808
  function useSupportedChains() {
2314
- const { data, isLoading, error, refetch } = (0, import_react_query9.useQuery)({
2809
+ const { data, isLoading, error, refetch } = (0, import_react_query10.useQuery)({
2315
2810
  ...supportedChainsQueries.all,
2316
2811
  ...queryDefaults
2317
2812
  });
@@ -2326,15 +2821,15 @@ function useSupportedChains() {
2326
2821
  }
2327
2822
 
2328
2823
  // src/v2/supported-tokens/hooks.ts
2329
- var import_react_query10 = require("@tanstack/react-query");
2330
- var import_react4 = require("react");
2824
+ var import_react_query11 = require("@tanstack/react-query");
2825
+ var import_react8 = require("react");
2331
2826
  function useSupportedTokens({
2332
2827
  page = 0,
2333
2828
  limit = 20,
2334
2829
  search,
2335
2830
  enabled = true
2336
2831
  } = {}) {
2337
- const { data, isLoading, error, refetch } = (0, import_react_query10.useQuery)({
2832
+ const { data, isLoading, error, refetch } = (0, import_react_query11.useQuery)({
2338
2833
  ...supportedTokensQueries.list({ page, limit, search }),
2339
2834
  ...queryDefaults,
2340
2835
  staleTime: 5 * 60 * 1e3,
@@ -2345,7 +2840,7 @@ function useSupportedTokens({
2345
2840
  // Don't refetch on tab focus
2346
2841
  enabled
2347
2842
  });
2348
- const tokens = (0, import_react4.useMemo)(() => {
2843
+ const tokens = (0, import_react8.useMemo)(() => {
2349
2844
  if (!data?.tokens) return [];
2350
2845
  return data.tokens.map(({ active, ...token }) => token);
2351
2846
  }, [data?.tokens]);
@@ -2365,7 +2860,7 @@ function useSupportedTokens({
2365
2860
  }
2366
2861
 
2367
2862
  // src/v2/balance/hooks/usePortfolioBalance.ts
2368
- var import_viem3 = require("viem");
2863
+ var import_viem4 = require("viem");
2369
2864
  function usePortfolioBalance({
2370
2865
  address
2371
2866
  }) {
@@ -2376,14 +2871,14 @@ function usePortfolioBalance({
2376
2871
  isLoading,
2377
2872
  error,
2378
2873
  refetch
2379
- } = (0, import_react_query11.useQuery)({
2874
+ } = (0, import_react_query12.useQuery)({
2380
2875
  ...balanceQueries.portfolio(address || ""),
2381
2876
  ...queryDefaults,
2382
2877
  enabled: !!address,
2383
2878
  refetchInterval: 1 * 60 * 1e3
2384
2879
  // 1 minute
2385
2880
  });
2386
- const balances = (0, import_react5.useMemo)(() => {
2881
+ const balances = (0, import_react9.useMemo)(() => {
2387
2882
  if (!portfolioData) return [];
2388
2883
  const tokenBalances = [];
2389
2884
  portfolioData.portfolio.holdings.wallets.forEach((wallet) => {
@@ -2412,7 +2907,7 @@ function usePortfolioBalance({
2412
2907
  };
2413
2908
  let amountInWei;
2414
2909
  try {
2415
- amountInWei = (0, import_viem3.parseUnits)(portfolioToken.amount, token.decimals).toString();
2910
+ amountInWei = (0, import_viem4.parseUnits)(portfolioToken.amount, token.decimals).toString();
2416
2911
  } catch (error2) {
2417
2912
  console.error("[Portfolio Balance] Failed to parse amount:", {
2418
2913
  amount: portfolioToken.amount,
@@ -2438,49 +2933,8 @@ function usePortfolioBalance({
2438
2933
  };
2439
2934
  }
2440
2935
 
2441
- // src/v2/balance/hooks/useEnsoBalances.ts
2442
- var import_react6 = require("react");
2443
- function useEnsoBalances({
2444
- address,
2445
- chainIds
2446
- }) {
2447
- const { getToken, isLoading: isSupportedTokensLoading } = useSupportedTokens();
2448
- const {
2449
- balances: ensoBalances,
2450
- isLoading,
2451
- error,
2452
- refetchAll
2453
- } = useMultiChainBalances({
2454
- chainIds,
2455
- address
2456
- });
2457
- const balances = (0, import_react6.useMemo)(() => {
2458
- if (isSupportedTokensLoading || isLoading) return [];
2459
- const tokenBalances = [];
2460
- Object.entries(ensoBalances).forEach(([, chainBalances]) => {
2461
- chainBalances.forEach((walletBalance) => {
2462
- const chainId = walletBalance.token.chain.toString();
2463
- const token = getToken(walletBalance.token.address, chainId);
2464
- if (!token) return;
2465
- tokenBalances.push({
2466
- token,
2467
- amount: walletBalance.amount,
2468
- source: "enso"
2469
- });
2470
- });
2471
- });
2472
- return tokenBalances;
2473
- }, [ensoBalances, getToken, isSupportedTokensLoading, isLoading]);
2474
- return {
2475
- balances,
2476
- isLoading,
2477
- error,
2478
- refetch: refetchAll
2479
- };
2480
- }
2481
-
2482
2936
  // src/v2/balance/utils.ts
2483
- var import_viem4 = require("viem");
2937
+ var import_viem5 = require("viem");
2484
2938
 
2485
2939
  // src/v2/balance/constants.ts
2486
2940
  var EXCLUDE_TOKEN_ADDRESS_LIST = [
@@ -2534,8 +2988,8 @@ function mergeBalancesByPriority(sources, receiptToken) {
2534
2988
  if (a.token.chain.chainId !== b.token.chain.chainId) {
2535
2989
  return Number(a.token.chain.chainId) - Number(b.token.chain.chainId);
2536
2990
  }
2537
- const balanceA = Number((0, import_viem4.formatUnits)(BigInt(a.amount), a.token.decimals));
2538
- const balanceB = Number((0, import_viem4.formatUnits)(BigInt(b.amount), b.token.decimals));
2991
+ const balanceA = Number((0, import_viem5.formatUnits)(BigInt(a.amount), a.token.decimals));
2992
+ const balanceB = Number((0, import_viem5.formatUnits)(BigInt(b.amount), b.token.decimals));
2539
2993
  return balanceB - balanceA;
2540
2994
  });
2541
2995
  }
@@ -2558,7 +3012,7 @@ function filterExcludedTokens(balances) {
2558
3012
  }
2559
3013
 
2560
3014
  // src/v2/balance/hooks/useBalance.ts
2561
- function useBalance({
3015
+ function useBalance2({
2562
3016
  address,
2563
3017
  chainIds,
2564
3018
  depositOpportunity
@@ -2582,16 +3036,7 @@ function useBalance({
2582
3036
  } = usePortfolioBalance({
2583
3037
  address
2584
3038
  });
2585
- const {
2586
- balances: ensoBalances,
2587
- isLoading: isEnsoLoading,
2588
- error: ensoError,
2589
- refetch: refetchEnso
2590
- } = useEnsoBalances({
2591
- address,
2592
- chainIds
2593
- });
2594
- const consolidatedBalances = (0, import_react7.useMemo)(() => {
3039
+ const consolidatedBalances = (0, import_react10.useMemo)(() => {
2595
3040
  const sources = [];
2596
3041
  if (depositOpportunity && onChainBalances.length > 0) {
2597
3042
  sources.push(onChainBalances);
@@ -2599,21 +3044,17 @@ function useBalance({
2599
3044
  if (portfolioBalances.length > 0) {
2600
3045
  sources.push(portfolioBalances);
2601
3046
  }
2602
- if (ensoBalances.length > 0) {
2603
- sources.push(ensoBalances);
2604
- }
2605
3047
  const merged = mergeBalancesByPriority(sources, depositOpportunity?.receiptToken);
2606
3048
  const nonZero = filterNonZeroBalances(merged);
2607
3049
  return filterExcludedTokens(nonZero);
2608
- }, [onChainBalances, portfolioBalances, ensoBalances, depositOpportunity]);
2609
- const isLoading = isOnChainLoading || isPortfolioLoading || isEnsoLoading;
2610
- const error = onChainError || portfolioError || ensoError;
3050
+ }, [onChainBalances, portfolioBalances, depositOpportunity]);
3051
+ const isLoading = isOnChainLoading || isPortfolioLoading;
3052
+ const error = onChainError || portfolioError;
2611
3053
  const refetchAll = () => {
2612
3054
  if (depositOpportunity) {
2613
3055
  refetchOnChain();
2614
3056
  }
2615
3057
  refetchPortfolio();
2616
- refetchEnso();
2617
3058
  };
2618
3059
  return {
2619
3060
  balances: consolidatedBalances,
@@ -2623,10 +3064,51 @@ function useBalance({
2623
3064
  };
2624
3065
  }
2625
3066
 
3067
+ // src/v2/balance/hooks/useEnsoBalances.ts
3068
+ var import_react11 = require("react");
3069
+ function useEnsoBalances({
3070
+ address,
3071
+ chainIds
3072
+ }) {
3073
+ const { getToken, isLoading: isSupportedTokensLoading } = useSupportedTokens();
3074
+ const {
3075
+ balances: ensoBalances,
3076
+ isLoading,
3077
+ error,
3078
+ refetchAll
3079
+ } = useMultiChainBalances({
3080
+ chainIds,
3081
+ address
3082
+ });
3083
+ const balances = (0, import_react11.useMemo)(() => {
3084
+ if (isSupportedTokensLoading || isLoading) return [];
3085
+ const tokenBalances = [];
3086
+ Object.entries(ensoBalances).forEach(([, chainBalances]) => {
3087
+ chainBalances.forEach((walletBalance) => {
3088
+ const chainId = walletBalance.token.chain.toString();
3089
+ const token = getToken(walletBalance.token.address, chainId);
3090
+ if (!token) return;
3091
+ tokenBalances.push({
3092
+ token,
3093
+ amount: walletBalance.amount,
3094
+ source: "enso"
3095
+ });
3096
+ });
3097
+ });
3098
+ return tokenBalances;
3099
+ }, [ensoBalances, getToken, isSupportedTokensLoading, isLoading]);
3100
+ return {
3101
+ balances,
3102
+ isLoading,
3103
+ error,
3104
+ refetch: refetchAll
3105
+ };
3106
+ }
3107
+
2626
3108
  // src/v2/widget/hooks.ts
2627
- var import_react_query12 = require("@tanstack/react-query");
3109
+ var import_react_query13 = require("@tanstack/react-query");
2628
3110
  function useWidgetOpportunities(distributorId) {
2629
- return (0, import_react_query12.useQuery)({
3111
+ return (0, import_react_query13.useQuery)({
2630
3112
  ...widgetQueries.opportunities(distributorId),
2631
3113
  ...queryDefaults,
2632
3114
  select: (data) => {
@@ -2650,7 +3132,7 @@ function useWidgetOpportunities(distributorId) {
2650
3132
  }
2651
3133
 
2652
3134
  // src/v2/geocheck/useGeocheck.ts
2653
- var import_react_query13 = require("@tanstack/react-query");
3135
+ var import_react_query14 = require("@tanstack/react-query");
2654
3136
  var INDEXER_ENDPOINT = "https://api.turtle.xyz";
2655
3137
  async function fetchGeocheck() {
2656
3138
  const url = `${INDEXER_ENDPOINT}/turtle/geocheck`;
@@ -2666,13 +3148,13 @@ async function fetchGeocheck() {
2666
3148
  }
2667
3149
  return data;
2668
3150
  }
2669
- var geocheckQueryOptions = () => (0, import_react_query13.queryOptions)({
3151
+ var geocheckQueryOptions = () => (0, import_react_query14.queryOptions)({
2670
3152
  queryKey: ["geocheck"],
2671
3153
  queryFn: fetchGeocheck
2672
3154
  });
2673
3155
  function useGeocheck(options = {}) {
2674
3156
  const { enabled = true, staleTime, gcTime } = options;
2675
- return (0, import_react_query13.useQuery)({
3157
+ return (0, import_react_query14.useQuery)({
2676
3158
  ...geocheckQueryOptions(),
2677
3159
  enabled,
2678
3160
  staleTime: staleTime ?? 5 * 60 * 1e3,
@@ -2685,39 +3167,39 @@ function useGeocheck(options = {}) {
2685
3167
  }
2686
3168
 
2687
3169
  // src/v2/streams/hooks.ts
2688
- var import_react_query14 = require("@tanstack/react-query");
3170
+ var import_react_query15 = require("@tanstack/react-query");
2689
3171
  function useStreams({
2690
3172
  query,
2691
3173
  options
2692
3174
  } = {}) {
2693
- return (0, import_react_query14.useQuery)(createQueryOptions(streamsQueries.list(query), options));
3175
+ return (0, import_react_query15.useQuery)(createQueryOptions(streamsQueries.list(query), options));
2694
3176
  }
2695
3177
  function useStreamPoints({
2696
3178
  query,
2697
3179
  options
2698
3180
  } = {}) {
2699
- return (0, import_react_query14.useQuery)(createQueryOptions(streamsQueries.points(query), options));
3181
+ return (0, import_react_query15.useQuery)(createQueryOptions(streamsQueries.points(query), options));
2700
3182
  }
2701
3183
  function useStreamWallets({
2702
3184
  query,
2703
3185
  options
2704
3186
  }) {
2705
- return (0, import_react_query14.useQuery)(createQueryOptions(streamsQueries.wallets(query), options));
3187
+ return (0, import_react_query15.useQuery)(createQueryOptions(streamsQueries.wallets(query), options));
2706
3188
  }
2707
3189
  function useStreamWalletDetails({
2708
3190
  query,
2709
3191
  options
2710
3192
  }) {
2711
- return (0, import_react_query14.useQuery)(createQueryOptions(streamsQueries.walletDetails(query), options));
3193
+ return (0, import_react_query15.useQuery)(createQueryOptions(streamsQueries.walletDetails(query), options));
2712
3194
  }
2713
3195
  function useStreamSupportedChains({
2714
3196
  options
2715
3197
  } = {}) {
2716
- return (0, import_react_query14.useQuery)(createQueryOptions(streamsQueries.supportedChains, options));
3198
+ return (0, import_react_query15.useQuery)(createQueryOptions(streamsQueries.supportedChains, options));
2717
3199
  }
2718
3200
 
2719
3201
  // src/v2/swap/useSwapRoute.ts
2720
- var import_react8 = require("react");
3202
+ var import_react12 = require("react");
2721
3203
 
2722
3204
  // src/v2/swap/route-processor.ts
2723
3205
  var import_utils4 = require("@turtleclub/utils");
@@ -2776,7 +3258,7 @@ function toEnsoTokenAddress(address) {
2776
3258
  return address;
2777
3259
  }
2778
3260
  function useSwapRoute(isEnabled, userAddress, distributorId, options, referralCode) {
2779
- const params = (0, import_react8.useMemo)(() => {
3261
+ const params = (0, import_react12.useMemo)(() => {
2780
3262
  if (!options || !isEnabled) return void 0;
2781
3263
  return {
2782
3264
  ...options,
@@ -2785,7 +3267,7 @@ function useSwapRoute(isEnabled, userAddress, distributorId, options, referralCo
2785
3267
  referral_code: referralCode
2786
3268
  };
2787
3269
  }, [options, userAddress, distributorId, referralCode]);
2788
- const hasRequiredParams = (0, import_react8.useMemo)(() => {
3270
+ const hasRequiredParams = (0, import_react12.useMemo)(() => {
2789
3271
  return !!(userAddress && params?.token_in && params?.token_out && params?.amount && params?.chain && params?.slippage && params?.distributor_id);
2790
3272
  }, [options]);
2791
3273
  const { data, isLoading, error } = useEarnRoute({
@@ -2802,7 +3284,7 @@ function useSwapRoute(isEnabled, userAddress, distributorId, options, referralCo
2802
3284
  },
2803
3285
  enabled: hasRequiredParams && isEnabled
2804
3286
  });
2805
- const routeDetails = (0, import_react8.useMemo)(() => processRouteDetails(data ?? null), [data]);
3287
+ const routeDetails = (0, import_react12.useMemo)(() => processRouteDetails(data ?? null), [data]);
2806
3288
  return {
2807
3289
  fetchedRoute: data ?? null,
2808
3290
  outputAmount: data?.amount_out ?? void 0,
@@ -2815,9 +3297,9 @@ function useSwapRoute(isEnabled, userAddress, distributorId, options, referralCo
2815
3297
  }
2816
3298
 
2817
3299
  // src/v2/users/hooks.ts
2818
- var import_react_query15 = require("@tanstack/react-query");
3300
+ var import_react_query16 = require("@tanstack/react-query");
2819
3301
  function useUserById({ userId, enabled = true }) {
2820
- return (0, import_react_query15.useQuery)({
3302
+ return (0, import_react_query16.useQuery)({
2821
3303
  ...usersQueries.byId({ userId }),
2822
3304
  ...queryDefaults,
2823
3305
  enabled
@@ -2825,7 +3307,7 @@ function useUserById({ userId, enabled = true }) {
2825
3307
  }
2826
3308
  function useUserPortfolio({ userId, enabled = true }) {
2827
3309
  const input = { userId };
2828
- return (0, import_react_query15.useQuery)({
3310
+ return (0, import_react_query16.useQuery)({
2829
3311
  ...usersQueries.portfolio(input),
2830
3312
  ...queryDefaults,
2831
3313
  enabled
@@ -2833,17 +3315,17 @@ function useUserPortfolio({ userId, enabled = true }) {
2833
3315
  }
2834
3316
 
2835
3317
  // src/v2/nfts/hooks.ts
2836
- var import_react_query16 = require("@tanstack/react-query");
3318
+ var import_react_query17 = require("@tanstack/react-query");
2837
3319
  function useUserNfts({ userAddress, chain, tokenAddress }) {
2838
- return (0, import_react_query16.useQuery)(
3320
+ return (0, import_react_query17.useQuery)(
2839
3321
  userAddress ? createQueryOptions(nftsQueries.byUser(userAddress, chain), {
2840
3322
  select: (data) => tokenAddress ? data.filter((nft) => nft.token.toLowerCase() === tokenAddress.toLowerCase()) : data
2841
- }) : { queryKey: ["nfts", "byUser", "skip"], queryFn: import_react_query16.skipToken }
3323
+ }) : { queryKey: ["nfts", "byUser", "skip"], queryFn: import_react_query17.skipToken }
2842
3324
  );
2843
3325
  }
2844
3326
 
2845
3327
  // src/v2/covers/hooks.ts
2846
- var import_react_query17 = require("@tanstack/react-query");
3328
+ var import_react_query18 = require("@tanstack/react-query");
2847
3329
 
2848
3330
  // src/v2/covers/schema.ts
2849
3331
  var import_zod16 = require("zod");
@@ -2875,7 +3357,7 @@ async function submitCoverRequest(data) {
2875
3357
 
2876
3358
  // src/v2/covers/hooks.ts
2877
3359
  function useSubmitCoverRequest(options) {
2878
- return (0, import_react_query17.useMutation)({
3360
+ return (0, import_react_query18.useMutation)({
2879
3361
  mutationFn: submitCoverRequest,
2880
3362
  onSuccess: () => {
2881
3363
  options?.onSuccess?.("Cover request submitted successfully!");
@@ -2912,9 +3394,9 @@ async function leaveOrganization(input) {
2912
3394
  }
2913
3395
 
2914
3396
  // src/v2/organizations/hooks.ts
2915
- var import_react_query18 = require("@tanstack/react-query");
3397
+ var import_react_query19 = require("@tanstack/react-query");
2916
3398
  function useLeaveOrganization(options) {
2917
- return (0, import_react_query18.useMutation)({
3399
+ return (0, import_react_query19.useMutation)({
2918
3400
  mutationFn: leaveOrganization,
2919
3401
  ...options
2920
3402
  });
@@ -3077,7 +3559,10 @@ var queries = (0, import_query_key_factory16.mergeQueryKeys)(
3077
3559
  productsQueries,
3078
3560
  queries,
3079
3561
  requestStreamSignature,
3562
+ routeMetadataSchema,
3563
+ routeStepSchema,
3080
3564
  routeToken,
3565
+ routeTokenSchema,
3081
3566
  routerStep,
3082
3567
  routerSubstep,
3083
3568
  snapshotSchema,
@@ -3116,7 +3601,11 @@ var queries = (0, import_query_key_factory16.mergeQueryKeys)(
3116
3601
  useCreateWithdrawInteraction,
3117
3602
  useDeleteProduct,
3118
3603
  useDepositAction,
3604
+ useDepositFlow,
3605
+ useDepositSelection,
3606
+ useDepositValidation,
3119
3607
  useDeposits,
3608
+ useEarnDeposit,
3120
3609
  useEarnOpportunities,
3121
3610
  useEarnRoute,
3122
3611
  useEnsoBalances,