@sodax/dapp-kit 1.3.1-beta-rc2 → 1.3.1-beta

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 (38) hide show
  1. package/README.md +36 -0
  2. package/dist/index.d.mts +650 -12
  3. package/dist/index.d.ts +650 -12
  4. package/dist/index.js +741 -62
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +720 -62
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +3 -3
  9. package/src/hooks/backend/index.ts +4 -0
  10. package/src/hooks/backend/useBackendSubmitSwapTx.ts +55 -0
  11. package/src/hooks/backend/useBackendSubmitSwapTxStatus.ts +79 -0
  12. package/src/hooks/bitcoin/index.ts +1 -0
  13. package/src/hooks/bitcoin/useRadfiAuth.ts +7 -25
  14. package/src/hooks/bitcoin/useRadfiSession.ts +25 -47
  15. package/src/hooks/bitcoin/useRadfiWithdraw.ts +85 -0
  16. package/src/hooks/bitcoin/useRenewUtxos.ts +1 -1
  17. package/src/hooks/dex/index.ts +16 -0
  18. package/src/hooks/dex/useClaimRewards.ts +68 -0
  19. package/src/hooks/dex/useCreateDecreaseLiquidityParams.ts +41 -0
  20. package/src/hooks/dex/useCreateDepositParams.ts +43 -0
  21. package/src/hooks/dex/useCreateSupplyLiquidityParams.ts +84 -0
  22. package/src/hooks/dex/useCreateWithdrawParams.ts +44 -0
  23. package/src/hooks/dex/useDecreaseLiquidity.ts +78 -0
  24. package/src/hooks/dex/useDexAllowance.ts +87 -0
  25. package/src/hooks/dex/useDexApprove.ts +55 -0
  26. package/src/hooks/dex/useDexDeposit.ts +64 -0
  27. package/src/hooks/dex/useDexWithdraw.ts +54 -0
  28. package/src/hooks/dex/useLiquidityAmounts.ts +187 -0
  29. package/src/hooks/dex/usePoolBalances.ts +90 -0
  30. package/src/hooks/dex/usePoolData.ts +57 -0
  31. package/src/hooks/dex/usePools.ts +48 -0
  32. package/src/hooks/dex/usePositionInfo.ts +88 -0
  33. package/src/hooks/dex/useSupplyLiquidity.ts +91 -0
  34. package/src/hooks/index.ts +1 -0
  35. package/src/index.ts +1 -0
  36. package/src/utils/dex-utils.ts +177 -0
  37. package/src/utils/index.ts +1 -0
  38. package/src/hooks/bitcoin/radfiConstants.ts +0 -2
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import React, { createContext, useContext, useState, useCallback, useMemo, useRef, useEffect } from 'react';
2
- import { SpokeService, deriveUserWalletAddress, STELLAR_MAINNET_CHAIN_ID, StellarSpokeProvider, StellarSpokeService, HubService, spokeChainConfig, BitcoinSpokeProvider, SONIC_MAINNET_CHAIN_ID, SonicSpokeProvider, EvmSpokeProvider, SuiSpokeProvider, IconSpokeProvider, InjectiveSpokeProvider, SolanaSpokeProvider, NearSpokeProvider, BitcoinSpokeService, normalizePsbtToBase64, isLegacybnUSDToken, Sodax } from '@sodax/sdk';
2
+ import { SpokeService, deriveUserWalletAddress, STELLAR_MAINNET_CHAIN_ID, StellarSpokeProvider, StellarSpokeService, HubService, spokeChainConfig, BitcoinSpokeProvider, SONIC_MAINNET_CHAIN_ID, SonicSpokeProvider, EvmSpokeProvider, SuiSpokeProvider, IconSpokeProvider, InjectiveSpokeProvider, SolanaSpokeProvider, NearSpokeProvider, BitcoinSpokeService, normalizePsbtToBase64, isLegacybnUSDToken, ClService, Sodax } from '@sodax/sdk';
3
3
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
4
4
  import { isAddress, parseUnits } from 'viem';
5
5
  import { ICON_MAINNET_CHAIN_ID } from '@sodax/types';
@@ -214,12 +214,6 @@ function useSpokeProvider(spokeChainId, walletProvider) {
214
214
  }, [spokeChainId, xChainType, walletProvider, rpcConfig]);
215
215
  return spokeProvider;
216
216
  }
217
-
218
- // src/hooks/bitcoin/radfiConstants.ts
219
- var ACCESS_TOKEN_TTL = 10 * 60 * 1e3;
220
- var REFRESH_TOKEN_TTL = 7 * 24 * 60 * 60 * 1e3;
221
-
222
- // src/hooks/bitcoin/useRadfiAuth.ts
223
217
  var SESSION_KEY = (address) => `radfi_session_${address}`;
224
218
  function saveRadfiSession(address, session) {
225
219
  try {
@@ -241,16 +235,6 @@ function clearRadfiSession(address) {
241
235
  } catch {
242
236
  }
243
237
  }
244
- function isAccessTokenExpired(address) {
245
- const session = loadRadfiSession(address);
246
- if (!session) return true;
247
- return Date.now() >= session.accessTokenExpiry;
248
- }
249
- function isRefreshTokenExpired(address) {
250
- const session = loadRadfiSession(address);
251
- if (!session) return true;
252
- return Date.now() >= session.refreshTokenExpiry;
253
- }
254
238
  function useRadfiAuth(spokeProvider) {
255
239
  return useMutation({
256
240
  mutationFn: async () => {
@@ -266,27 +250,25 @@ function useRadfiAuth(spokeProvider) {
266
250
  accessToken,
267
251
  refreshToken,
268
252
  tradingAddress,
269
- publicKey,
270
- accessTokenExpiry: Date.now() + ACCESS_TOKEN_TTL,
271
- refreshTokenExpiry: Date.now() + REFRESH_TOKEN_TTL
253
+ publicKey
272
254
  };
273
255
  saveRadfiSession(walletAddress, session);
274
256
  return { accessToken, refreshToken, tradingAddress };
275
257
  } catch (err) {
276
258
  const isAlreadyRegistered = err instanceof Error && (err.message.includes("duplicatedPubKey") || err.message.includes("4008"));
277
- if (isAlreadyRegistered) {
278
- if (existingSession && !isRefreshTokenExpired(walletAddress)) {
259
+ if (isAlreadyRegistered && existingSession?.refreshToken) {
260
+ try {
279
261
  const refreshed = await spokeProvider.radfi.refreshAccessToken(existingSession.refreshToken);
280
262
  const session = {
281
263
  ...existingSession,
282
264
  accessToken: refreshed.accessToken,
283
- refreshToken: refreshed.refreshToken,
284
- accessTokenExpiry: Date.now() + ACCESS_TOKEN_TTL,
285
- refreshTokenExpiry: Date.now() + REFRESH_TOKEN_TTL
265
+ refreshToken: refreshed.refreshToken
286
266
  };
287
- spokeProvider.setRadfiAccessToken(refreshed.accessToken);
267
+ spokeProvider.setRadfiAccessToken(refreshed.accessToken, refreshed.refreshToken);
288
268
  saveRadfiSession(walletAddress, session);
289
269
  return { accessToken: refreshed.accessToken, refreshToken: refreshed.refreshToken, tradingAddress: existingSession.tradingAddress };
270
+ } catch {
271
+ clearRadfiSession(walletAddress);
290
272
  }
291
273
  throw new Error(
292
274
  "This wallet is already registered with Radfi from another session. Please clear your browser storage for this site and try again, or wait for the previous session to expire."
@@ -297,7 +279,7 @@ function useRadfiAuth(spokeProvider) {
297
279
  }
298
280
  });
299
281
  }
300
- var POLL_INTERVAL = 3e4;
282
+ var REFRESH_INTERVAL = 5 * 60 * 1e3;
301
283
  function useRadfiSession(spokeProvider) {
302
284
  const [walletAddress, setWalletAddress] = useState();
303
285
  const [isAuthed, setIsAuthed] = useState(false);
@@ -316,17 +298,15 @@ function useRadfiSession(spokeProvider) {
316
298
  const updated = {
317
299
  ...session,
318
300
  accessToken,
319
- refreshToken,
320
- accessTokenExpiry: Date.now() + ACCESS_TOKEN_TTL
321
- // Keep the original refreshTokenExpiry — don't roll it forward on every silent refresh
301
+ refreshToken
322
302
  };
323
303
  saveRadfiSession(address, updated);
324
- spokeProvider.setRadfiAccessToken(accessToken);
304
+ spokeProvider.setRadfiAccessToken(accessToken, refreshToken);
325
305
  setIsAuthed(true);
326
306
  setTradingAddress(updated.tradingAddress || void 0);
327
307
  } catch {
328
308
  clearRadfiSession(address);
329
- spokeProvider.setRadfiAccessToken("");
309
+ spokeProvider.setRadfiAccessToken("", "");
330
310
  setIsAuthed(false);
331
311
  setTradingAddress(void 0);
332
312
  } finally {
@@ -335,39 +315,22 @@ function useRadfiSession(spokeProvider) {
335
315
  }, [spokeProvider]);
336
316
  useEffect(() => {
337
317
  if (!spokeProvider) return;
338
- const fetchAndRestore = () => {
339
- spokeProvider.walletProvider.getWalletAddress().then((addr) => {
340
- setWalletAddress(addr);
341
- const session = loadRadfiSession(addr);
342
- if (!session || isRefreshTokenExpired(addr)) return;
343
- if (!isAccessTokenExpired(addr)) {
344
- spokeProvider.setRadfiAccessToken(session.accessToken);
345
- setIsAuthed(true);
346
- setTradingAddress(session.tradingAddress || void 0);
347
- } else {
348
- silentRefresh(addr);
349
- }
350
- }).catch(() => {
351
- });
352
- };
353
- fetchAndRestore();
354
- const id = setInterval(fetchAndRestore, 3e3);
355
- return () => clearInterval(id);
318
+ setIsAuthed(false);
319
+ setTradingAddress(void 0);
320
+ setWalletAddress(void 0);
321
+ spokeProvider.walletProvider.getWalletAddress().then((addr) => {
322
+ setWalletAddress(addr);
323
+ const session = loadRadfiSession(addr);
324
+ if (!session?.refreshToken) return;
325
+ silentRefresh(addr);
326
+ }).catch(() => {
327
+ });
356
328
  }, [spokeProvider, silentRefresh]);
357
329
  useEffect(() => {
358
330
  if (!walletAddress || !spokeProvider) return;
359
331
  const id = setInterval(() => {
360
- if (isRefreshTokenExpired(walletAddress)) {
361
- clearRadfiSession(walletAddress);
362
- spokeProvider.setRadfiAccessToken("");
363
- setIsAuthed(false);
364
- setTradingAddress(void 0);
365
- return;
366
- }
367
- if (isAccessTokenExpired(walletAddress)) {
368
- silentRefresh(walletAddress);
369
- }
370
- }, POLL_INTERVAL);
332
+ silentRefresh(walletAddress);
333
+ }, REFRESH_INTERVAL);
371
334
  return () => clearInterval(id);
372
335
  }, [walletAddress, spokeProvider, silentRefresh]);
373
336
  const { mutateAsync: loginMutate, isPending: isLoginPending } = useRadfiAuth(spokeProvider);
@@ -466,6 +429,41 @@ function useRenewUtxos(spokeProvider) {
466
429
  }
467
430
  });
468
431
  }
432
+ function useRadfiWithdraw(spokeProvider) {
433
+ const queryClient = useQueryClient();
434
+ return useMutation({
435
+ mutationFn: async ({ amount, tokenId, withdrawTo }) => {
436
+ if (!spokeProvider) {
437
+ throw new Error("Bitcoin spoke provider not found");
438
+ }
439
+ const userAddress = await spokeProvider.walletProvider.getWalletAddress();
440
+ const session = loadRadfiSession(userAddress);
441
+ const accessToken = session?.accessToken || spokeProvider.radfiAccessToken;
442
+ if (!accessToken) {
443
+ throw new Error("Radfi authentication required. Please login first.");
444
+ }
445
+ const buildResult = await spokeProvider.radfi.withdrawToUser(
446
+ { userAddress, amount, tokenId, withdrawTo },
447
+ accessToken
448
+ );
449
+ const signedTx = await spokeProvider.walletProvider.signTransaction(
450
+ buildResult.base64Psbt,
451
+ false
452
+ );
453
+ const signedBase64Tx = normalizePsbtToBase64(signedTx);
454
+ const txId = await spokeProvider.radfi.signAndBroadcastWithdraw(
455
+ { userAddress, signedBase64Tx },
456
+ accessToken
457
+ );
458
+ return { txId, fee: buildResult.fee.totalFee };
459
+ },
460
+ onSuccess: () => {
461
+ queryClient.invalidateQueries({ queryKey: ["trading-wallet-balance"] });
462
+ queryClient.invalidateQueries({ queryKey: ["btc-balance"] });
463
+ queryClient.invalidateQueries({ queryKey: ["xBalances"] });
464
+ }
465
+ });
466
+ }
469
467
  function useBorrow() {
470
468
  const { sodax } = useSodaxContext();
471
469
  return useMutation({
@@ -985,6 +983,54 @@ var useBackendUserIntents = ({
985
983
  }
986
984
  });
987
985
  };
986
+ var useBackendSubmitSwapTx = (params) => {
987
+ const { sodax } = useSodaxContext();
988
+ const defaultMutationOptions = {
989
+ retry: 3
990
+ };
991
+ const mutationOptions = {
992
+ ...defaultMutationOptions,
993
+ ...params?.mutationOptions
994
+ };
995
+ return useMutation({
996
+ ...mutationOptions,
997
+ mutationFn: async (request) => {
998
+ return sodax.backendApi.submitSwapTx(request, params?.apiConfig);
999
+ }
1000
+ });
1001
+ };
1002
+ var useBackendSubmitSwapTxStatus = (params) => {
1003
+ const { sodax } = useSodaxContext();
1004
+ const defaultQueryOptions = {
1005
+ queryKey: ["api", "swaps", "submit-tx", "status", params?.params?.txHash, params?.params?.srcChainId],
1006
+ enabled: !!params?.params?.txHash && params.params.txHash.length > 0,
1007
+ retry: 3,
1008
+ refetchInterval: (query) => {
1009
+ const status = query.state.data?.data?.status;
1010
+ if (status === "executed" || status === "failed") return false;
1011
+ return 1e3;
1012
+ }
1013
+ };
1014
+ const queryOptions = {
1015
+ ...defaultQueryOptions,
1016
+ ...params?.queryOptions
1017
+ };
1018
+ return useQuery({
1019
+ ...queryOptions,
1020
+ queryFn: async () => {
1021
+ if (!params?.params?.txHash) {
1022
+ return void 0;
1023
+ }
1024
+ return sodax.backendApi.getSubmitSwapTxStatus(
1025
+ {
1026
+ txHash: params.params.txHash,
1027
+ srcChainId: params.params.srcChainId
1028
+ },
1029
+ params.apiConfig
1030
+ );
1031
+ }
1032
+ });
1033
+ };
988
1034
  var useBackendOrderbook = (params) => {
989
1035
  const { sodax } = useSodaxContext();
990
1036
  const defaultQueryOptions = {
@@ -1774,11 +1820,623 @@ function useMigrationApprove(params, spokeProvider) {
1774
1820
  isApproved
1775
1821
  };
1776
1822
  }
1823
+ function usePools(params) {
1824
+ const { sodax } = useSodaxContext();
1825
+ const defaultQueryOptions = {
1826
+ queryKey: ["dex", "pools"],
1827
+ staleTime: Number.POSITIVE_INFINITY
1828
+ // Pools list is static, cache indefinitely
1829
+ };
1830
+ const queryOptions = { ...defaultQueryOptions, ...params?.queryOptions };
1831
+ return useQuery({
1832
+ ...queryOptions,
1833
+ queryFn: async () => {
1834
+ return sodax.dex.clService.getPools();
1835
+ }
1836
+ });
1837
+ }
1838
+ function usePoolData({
1839
+ poolKey,
1840
+ queryOptions = {
1841
+ queryKey: ["dex", "poolData", poolKey],
1842
+ enabled: poolKey !== null,
1843
+ staleTime: 1e4,
1844
+ refetchInterval: 3e4
1845
+ }
1846
+ }) {
1847
+ const { sodax } = useSodaxContext();
1848
+ return useQuery({
1849
+ ...queryOptions,
1850
+ queryFn: async () => {
1851
+ if (!poolKey) {
1852
+ throw new Error("Pool key is required");
1853
+ }
1854
+ return await sodax.dex.clService.getPoolData(poolKey, sodax.hubProvider.publicClient);
1855
+ },
1856
+ enabled: poolKey !== null
1857
+ });
1858
+ }
1859
+ function usePoolBalances({
1860
+ poolData,
1861
+ poolKey,
1862
+ spokeProvider,
1863
+ enabled = true,
1864
+ queryOptions = {
1865
+ queryKey: [
1866
+ "dex",
1867
+ "poolBalances",
1868
+ poolData?.poolKey,
1869
+ spokeProvider?.chainConfig.chain.id
1870
+ ],
1871
+ enabled: enabled && poolData !== null && poolKey !== null && spokeProvider !== null,
1872
+ staleTime: 5e3,
1873
+ // Consider data stale after 5 seconds
1874
+ refetchInterval: 1e4
1875
+ // Refetch every 10 seconds
1876
+ }
1877
+ }) {
1878
+ const { sodax } = useSodaxContext();
1879
+ return useQuery({
1880
+ ...queryOptions,
1881
+ queryFn: async () => {
1882
+ if (!poolData || !spokeProvider || !poolKey) {
1883
+ throw new Error("Pool data, pool key, and spoke provider are required");
1884
+ }
1885
+ const [balance0, balance1] = await Promise.all([
1886
+ sodax.dex.assetService.getDeposit(poolData.token0.address, spokeProvider),
1887
+ sodax.dex.assetService.getDeposit(poolData.token1.address, spokeProvider)
1888
+ ]);
1889
+ return {
1890
+ token0Balance: balance0,
1891
+ token1Balance: balance1
1892
+ };
1893
+ }
1894
+ });
1895
+ }
1896
+ function usePositionInfo({
1897
+ tokenId,
1898
+ poolKey,
1899
+ queryOptions = {
1900
+ queryKey: ["dex", "positionInfo", tokenId, poolKey],
1901
+ enabled: tokenId !== null && poolKey !== null && tokenId !== "",
1902
+ staleTime: 1e4
1903
+ // Consider data stale after 10 seconds
1904
+ }
1905
+ }) {
1906
+ const { sodax } = useSodaxContext();
1907
+ return useQuery({
1908
+ queryFn: async () => {
1909
+ if (!tokenId || !poolKey) {
1910
+ throw new Error("Token ID and pool key are required");
1911
+ }
1912
+ const tokenIdBigInt = BigInt(tokenId);
1913
+ const publicClient = sodax.hubProvider.publicClient;
1914
+ const info = await sodax.dex.clService.getPositionInfo(tokenIdBigInt, publicClient);
1915
+ const isValid = info.poolKey.currency0.toLowerCase() === poolKey.currency0.toLowerCase() && info.poolKey.currency1.toLowerCase() === poolKey.currency1.toLowerCase() && info.poolKey.fee === poolKey.fee;
1916
+ return {
1917
+ positionInfo: info,
1918
+ isValid
1919
+ };
1920
+ },
1921
+ ...queryOptions
1922
+ });
1923
+ }
1924
+ function useDexDeposit() {
1925
+ const { sodax } = useSodaxContext();
1926
+ const queryClient = useQueryClient();
1927
+ return useMutation({
1928
+ mutationFn: async ({ params, spokeProvider }) => {
1929
+ if (!spokeProvider) {
1930
+ throw new Error("Spoke provider is required");
1931
+ }
1932
+ if (!params) {
1933
+ throw new Error("Deposit params are required");
1934
+ }
1935
+ const depositResult = await sodax.dex.assetService.deposit({
1936
+ params,
1937
+ spokeProvider
1938
+ });
1939
+ if (!depositResult.ok) {
1940
+ throw new Error(`Deposit failed: ${depositResult.error?.code || "Unknown error"}`);
1941
+ }
1942
+ return depositResult.value;
1943
+ },
1944
+ onSuccess: () => {
1945
+ queryClient.invalidateQueries({ queryKey: ["dex", "poolBalances"] });
1946
+ }
1947
+ });
1948
+ }
1949
+ function useDexWithdraw() {
1950
+ const { sodax } = useSodaxContext();
1951
+ const queryClient = useQueryClient();
1952
+ return useMutation({
1953
+ mutationFn: async ({ params, spokeProvider }) => {
1954
+ if (!spokeProvider) {
1955
+ throw new Error("Spoke provider is required");
1956
+ }
1957
+ const withdrawResult = await sodax.dex.assetService.withdraw({
1958
+ params,
1959
+ spokeProvider
1960
+ });
1961
+ if (!withdrawResult.ok) {
1962
+ throw new Error(`Withdraw failed: ${withdrawResult.error.code}`);
1963
+ }
1964
+ return withdrawResult.value;
1965
+ },
1966
+ onSuccess: () => {
1967
+ queryClient.invalidateQueries({ queryKey: ["dex", "poolBalances"] });
1968
+ }
1969
+ });
1970
+ }
1971
+ function useDexAllowance({
1972
+ params,
1973
+ spokeProvider,
1974
+ queryOptions = {
1975
+ queryKey: [
1976
+ "dex",
1977
+ "allowance",
1978
+ params?.asset,
1979
+ params?.poolToken,
1980
+ params?.amount.toString(),
1981
+ spokeProvider?.chainConfig.chain.id
1982
+ ],
1983
+ enabled: !!params && !!spokeProvider
1984
+ }
1985
+ }) {
1986
+ const { sodax } = useSodaxContext();
1987
+ return useQuery({
1988
+ ...queryOptions,
1989
+ queryFn: async () => {
1990
+ if (!params || !spokeProvider) {
1991
+ throw new Error("Params and spoke provider are required");
1992
+ }
1993
+ const allowanceResult = await sodax.dex.assetService.isAllowanceValid({
1994
+ params: {
1995
+ asset: params.asset,
1996
+ amount: params.amount,
1997
+ poolToken: params.poolToken
1998
+ },
1999
+ spokeProvider
2000
+ });
2001
+ if (!allowanceResult.ok) {
2002
+ return false;
2003
+ }
2004
+ return allowanceResult.value;
2005
+ }
2006
+ });
2007
+ }
2008
+ function useDexApprove() {
2009
+ const { sodax } = useSodaxContext();
2010
+ const queryClient = useQueryClient();
2011
+ return useMutation({
2012
+ mutationFn: async ({ params, spokeProvider }) => {
2013
+ const approveResult = await sodax.dex.assetService.approve({
2014
+ params,
2015
+ spokeProvider,
2016
+ raw: false
2017
+ });
2018
+ if (!approveResult.ok) {
2019
+ throw new Error("Approval failed");
2020
+ }
2021
+ return approveResult.value;
2022
+ },
2023
+ onSuccess: () => {
2024
+ queryClient.invalidateQueries({ queryKey: ["dex", "allowance"] });
2025
+ }
2026
+ });
2027
+ }
2028
+ function useLiquidityAmounts(minPrice, maxPrice, poolData) {
2029
+ const [liquidityToken0Amount, setLiquidityToken0Amount] = useState("");
2030
+ const [liquidityToken1Amount, setLiquidityToken1Amount] = useState("");
2031
+ const [lastEditedToken, setLastEditedToken] = useState(null);
2032
+ const { minPriceNum, maxPriceNum, isValidPriceRange } = useMemo(() => {
2033
+ const parsedMin = Number.parseFloat(minPrice);
2034
+ const parsedMax = Number.parseFloat(maxPrice);
2035
+ const isValid = parsedMin > 0 && parsedMax > 0 && parsedMin < parsedMax;
2036
+ return {
2037
+ minPriceNum: parsedMin,
2038
+ maxPriceNum: parsedMax,
2039
+ isValidPriceRange: isValid
2040
+ };
2041
+ }, [minPrice, maxPrice]);
2042
+ const { tickLower, tickUpper, currentTick } = useMemo(() => {
2043
+ if (!poolData || !isValidPriceRange) {
2044
+ return {
2045
+ tickLower: null,
2046
+ tickUpper: null,
2047
+ currentTick: null
2048
+ };
2049
+ }
2050
+ try {
2051
+ const lower = ClService.priceToTick(minPriceNum, poolData.token0, poolData.token1, poolData.tickSpacing);
2052
+ const upper = ClService.priceToTick(maxPriceNum, poolData.token0, poolData.token1, poolData.tickSpacing);
2053
+ return {
2054
+ tickLower: lower,
2055
+ tickUpper: upper,
2056
+ currentTick: BigInt(poolData.currentTick)
2057
+ };
2058
+ } catch (err) {
2059
+ console.error("Failed to calculate ticks:", err);
2060
+ return {
2061
+ tickLower: null,
2062
+ tickUpper: null,
2063
+ currentTick: null
2064
+ };
2065
+ }
2066
+ }, [minPriceNum, maxPriceNum, poolData, isValidPriceRange]);
2067
+ const handleToken0AmountChange = useCallback(
2068
+ (value) => {
2069
+ setLiquidityToken0Amount(value);
2070
+ setLastEditedToken("token0");
2071
+ if (!value || !poolData || !tickLower || !tickUpper || !currentTick) {
2072
+ return;
2073
+ }
2074
+ const amount0 = Number.parseFloat(value);
2075
+ if (amount0 <= 0 || !isValidPriceRange) {
2076
+ return;
2077
+ }
2078
+ try {
2079
+ const amount0BigInt = BigInt(Math.floor(amount0 * 10 ** poolData.token0.decimals));
2080
+ const amount1BigInt = ClService.calculateAmount1FromAmount0(amount0BigInt, tickLower, tickUpper, currentTick);
2081
+ const amount1 = Number(amount1BigInt) / 10 ** poolData.token1.decimals;
2082
+ setLiquidityToken1Amount(amount1.toFixed(6));
2083
+ } catch (err) {
2084
+ console.error("Failed to calculate token1 amount:", err);
2085
+ }
2086
+ },
2087
+ [poolData, tickLower, tickUpper, currentTick, isValidPriceRange]
2088
+ );
2089
+ const handleToken1AmountChange = useCallback(
2090
+ (value) => {
2091
+ setLiquidityToken1Amount(value);
2092
+ setLastEditedToken("token1");
2093
+ if (!value || !poolData || !tickLower || !tickUpper || !currentTick) {
2094
+ return;
2095
+ }
2096
+ const amount1 = Number.parseFloat(value);
2097
+ if (amount1 <= 0 || !isValidPriceRange) {
2098
+ return;
2099
+ }
2100
+ try {
2101
+ const amount1BigInt = BigInt(Math.floor(amount1 * 10 ** poolData.token1.decimals));
2102
+ const amount0BigInt = ClService.calculateAmount0FromAmount1(amount1BigInt, tickLower, tickUpper, currentTick);
2103
+ const amount0 = Number(amount0BigInt) / 10 ** poolData.token0.decimals;
2104
+ setLiquidityToken0Amount(amount0.toFixed(6));
2105
+ } catch (err) {
2106
+ console.error("Failed to calculate token0 amount:", err);
2107
+ }
2108
+ },
2109
+ [poolData, tickLower, tickUpper, currentTick, isValidPriceRange]
2110
+ );
2111
+ useEffect(() => {
2112
+ if (!poolData || !tickLower || !tickUpper || !lastEditedToken || !isValidPriceRange) {
2113
+ return;
2114
+ }
2115
+ if (lastEditedToken === "token0" && liquidityToken0Amount) {
2116
+ handleToken0AmountChange(liquidityToken0Amount);
2117
+ } else if (lastEditedToken === "token1" && liquidityToken1Amount) {
2118
+ handleToken1AmountChange(liquidityToken1Amount);
2119
+ }
2120
+ }, [
2121
+ poolData,
2122
+ lastEditedToken,
2123
+ liquidityToken0Amount,
2124
+ liquidityToken1Amount,
2125
+ handleToken0AmountChange,
2126
+ handleToken1AmountChange,
2127
+ tickLower,
2128
+ tickUpper,
2129
+ isValidPriceRange
2130
+ ]);
2131
+ return {
2132
+ liquidityToken0Amount,
2133
+ liquidityToken1Amount,
2134
+ lastEditedToken,
2135
+ setLiquidityToken0Amount,
2136
+ setLiquidityToken1Amount,
2137
+ handleToken0AmountChange,
2138
+ handleToken1AmountChange
2139
+ };
2140
+ }
2141
+ function useSupplyLiquidity() {
2142
+ const { sodax } = useSodaxContext();
2143
+ const queryClient = useQueryClient();
2144
+ return useMutation({
2145
+ mutationFn: async ({ params, spokeProvider }) => {
2146
+ if (params.tokenId && params.isValidPosition) {
2147
+ const increaseResult = await sodax.dex.clService.increaseLiquidity({
2148
+ params: {
2149
+ poolKey: params.poolKey,
2150
+ tokenId: BigInt(params.tokenId),
2151
+ tickLower: params.tickLower,
2152
+ tickUpper: params.tickUpper,
2153
+ liquidity: params.liquidity,
2154
+ amount0Max: params.amount0Max,
2155
+ amount1Max: params.amount1Max,
2156
+ sqrtPriceX96: params.sqrtPriceX96
2157
+ },
2158
+ spokeProvider
2159
+ });
2160
+ if (!increaseResult.ok) {
2161
+ throw new Error(`Increase liquidity failed: ${increaseResult.error?.code || "Unknown error"}`);
2162
+ }
2163
+ return increaseResult.value;
2164
+ }
2165
+ const supplyResult = await sodax.dex.clService.supplyLiquidity({
2166
+ params: {
2167
+ poolKey: params.poolKey,
2168
+ tickLower: params.tickLower,
2169
+ tickUpper: params.tickUpper,
2170
+ liquidity: params.liquidity,
2171
+ amount0Max: params.amount0Max,
2172
+ amount1Max: params.amount1Max,
2173
+ sqrtPriceX96: params.sqrtPriceX96
2174
+ },
2175
+ spokeProvider
2176
+ });
2177
+ if (!supplyResult.ok) {
2178
+ throw new Error(`Supply liquidity failed: ${supplyResult.error?.code || "Unknown error"}`);
2179
+ }
2180
+ return supplyResult.value;
2181
+ },
2182
+ onSuccess: () => {
2183
+ queryClient.invalidateQueries({ queryKey: ["dex", "poolBalances"] });
2184
+ queryClient.invalidateQueries({ queryKey: ["dex", "positionInfo"] });
2185
+ }
2186
+ });
2187
+ }
2188
+ function useDecreaseLiquidity() {
2189
+ const { sodax } = useSodaxContext();
2190
+ const queryClient = useQueryClient();
2191
+ return useMutation({
2192
+ mutationFn: async ({ params, spokeProvider }) => {
2193
+ if (!spokeProvider) {
2194
+ throw new Error("Spoke provider is required");
2195
+ }
2196
+ const decreaseResult = await sodax.dex.clService.decreaseLiquidity({
2197
+ params,
2198
+ spokeProvider
2199
+ });
2200
+ if (!decreaseResult.ok) {
2201
+ throw new Error(`Decrease liquidity failed: ${decreaseResult.error?.code || "Unknown error"}`);
2202
+ }
2203
+ return decreaseResult.value;
2204
+ },
2205
+ onSuccess: () => {
2206
+ queryClient.invalidateQueries({ queryKey: ["dex", "poolBalances"] });
2207
+ queryClient.invalidateQueries({ queryKey: ["dex", "positionInfo"] });
2208
+ }
2209
+ });
2210
+ }
2211
+ function createDecreaseLiquidityParamsProps({
2212
+ poolKey,
2213
+ tokenId,
2214
+ percentage,
2215
+ positionInfo,
2216
+ slippageTolerance
2217
+ }) {
2218
+ const percentageNum = Number.parseFloat(String(percentage));
2219
+ const slippage = Number.parseFloat(String(slippageTolerance));
2220
+ if (percentageNum <= 0 || percentageNum > 100) {
2221
+ throw new Error("Percentage must be between 0 and 100");
2222
+ }
2223
+ if (slippage <= 0 || slippage > 100) {
2224
+ throw new Error("Slippage must be between 0 and 100");
2225
+ }
2226
+ const liquidityToRemove = percentageNum === 100 ? positionInfo.liquidity : positionInfo.liquidity * BigInt(Math.floor(percentageNum * 100)) / 10000n;
2227
+ const expectedAmount0 = percentageNum === 100 ? positionInfo.amount0 : positionInfo.amount0 * BigInt(Math.floor(percentageNum * 100)) / 10000n;
2228
+ const expectedAmount1 = percentageNum === 100 ? positionInfo.amount1 : positionInfo.amount1 * BigInt(Math.floor(percentageNum * 100)) / 10000n;
2229
+ const slippageMultiplier = BigInt(Math.floor((100 - slippage) * 100));
2230
+ const amount0Min = expectedAmount0 * slippageMultiplier / 10000n;
2231
+ const amount1Min = expectedAmount1 * slippageMultiplier / 10000n;
2232
+ return {
2233
+ poolKey,
2234
+ tokenId: BigInt(tokenId),
2235
+ liquidity: liquidityToRemove,
2236
+ amount0Min,
2237
+ amount1Min
2238
+ };
2239
+ }
2240
+ function createDepositParamsProps({
2241
+ tokenIndex,
2242
+ amount,
2243
+ poolData,
2244
+ poolSpokeAssets
2245
+ }) {
2246
+ const amountNum = Number.parseFloat(String(amount));
2247
+ if (!amount || amountNum <= 0) {
2248
+ throw new Error("Amount must be greater than 0");
2249
+ }
2250
+ const token = tokenIndex === 0 ? poolData.token0 : poolData.token1;
2251
+ const originalAsset = tokenIndex === 0 ? poolSpokeAssets.token0 : poolSpokeAssets.token1;
2252
+ return {
2253
+ asset: originalAsset.address,
2254
+ amount: parseUnits(String(amount), token.decimals),
2255
+ poolToken: token.address
2256
+ };
2257
+ }
2258
+ function createSupplyLiquidityParamsProps({
2259
+ poolData,
2260
+ poolKey,
2261
+ minPrice,
2262
+ maxPrice,
2263
+ liquidityToken0Amount,
2264
+ liquidityToken1Amount,
2265
+ slippageTolerance,
2266
+ positionId,
2267
+ isValidPosition
2268
+ }) {
2269
+ const slippage = Number.parseFloat(String(slippageTolerance));
2270
+ if (slippage <= 0 || slippage > 100) {
2271
+ throw new Error("Slippage must be between 0 and 100");
2272
+ }
2273
+ const minPriceNum = Number.parseFloat(minPrice);
2274
+ const maxPriceNum = Number.parseFloat(maxPrice);
2275
+ const amount0 = Number.parseFloat(liquidityToken0Amount);
2276
+ const amount1 = Number.parseFloat(liquidityToken1Amount);
2277
+ if (minPriceNum <= 0 || maxPriceNum <= 0 || amount0 <= 0 || amount1 <= 0) {
2278
+ throw new Error("All values must be greater than 0");
2279
+ }
2280
+ if (minPriceNum >= maxPriceNum) {
2281
+ throw new Error("Min price must be less than max price");
2282
+ }
2283
+ const amount0BigInt = parseUnits(liquidityToken0Amount, poolData.token0.decimals);
2284
+ const amount1BigInt = parseUnits(liquidityToken1Amount, poolData.token1.decimals);
2285
+ const token0 = poolData.token0;
2286
+ const token1 = poolData.token1;
2287
+ const tickSpacing = poolData.tickSpacing;
2288
+ const tickLower = ClService.priceToTick(minPriceNum, token0, token1, tickSpacing);
2289
+ const tickUpper = ClService.priceToTick(maxPriceNum, token0, token1, tickSpacing);
2290
+ const slippageMultiplier = BigInt(Math.floor((100 - slippage) * 100));
2291
+ const amount0ForLiquidity = amount0BigInt * slippageMultiplier / 10000n;
2292
+ const amount1ForLiquidity = amount1BigInt * slippageMultiplier / 10000n;
2293
+ const liquidity = ClService.calculateLiquidityFromAmounts(
2294
+ amount0ForLiquidity,
2295
+ amount1ForLiquidity,
2296
+ tickLower,
2297
+ tickUpper,
2298
+ BigInt(poolData.currentTick)
2299
+ );
2300
+ const tokenId = positionId ? BigInt(positionId) : void 0;
2301
+ return {
2302
+ poolKey,
2303
+ tickLower,
2304
+ tickUpper,
2305
+ liquidity,
2306
+ amount0Max: amount0BigInt,
2307
+ amount1Max: amount1BigInt,
2308
+ sqrtPriceX96: poolData.sqrtPriceX96,
2309
+ positionId,
2310
+ isValidPosition,
2311
+ tokenId
2312
+ };
2313
+ }
2314
+ function createWithdrawParamsProps({
2315
+ tokenIndex,
2316
+ amount,
2317
+ poolData,
2318
+ poolSpokeAssets,
2319
+ dst
2320
+ }) {
2321
+ const amountNum = Number.parseFloat(String(amount));
2322
+ if (!amount || amountNum <= 0) {
2323
+ throw new Error("Please enter a valid amount");
2324
+ }
2325
+ const token = tokenIndex === 0 ? poolData.token0 : poolData.token1;
2326
+ const originalAsset = tokenIndex === 0 ? poolSpokeAssets.token0 : poolSpokeAssets.token1;
2327
+ return {
2328
+ asset: originalAsset.address,
2329
+ amount: parseUnits(String(amount), token.decimals),
2330
+ poolToken: token.address,
2331
+ dst
2332
+ };
2333
+ }
2334
+
2335
+ // src/hooks/dex/useCreateDepositParams.ts
2336
+ function useCreateDepositParams({
2337
+ tokenIndex,
2338
+ amount,
2339
+ poolData,
2340
+ poolSpokeAssets
2341
+ }) {
2342
+ return useMemo(() => {
2343
+ if (!amount || Number.parseFloat(String(amount)) <= 0) {
2344
+ return void 0;
2345
+ }
2346
+ return createDepositParamsProps({ tokenIndex, amount, poolData, poolSpokeAssets });
2347
+ }, [tokenIndex, amount, poolData, poolSpokeAssets]);
2348
+ }
2349
+ function useCreateSupplyLiquidityParams({
2350
+ poolData,
2351
+ poolKey,
2352
+ minPrice,
2353
+ maxPrice,
2354
+ liquidityToken0Amount,
2355
+ liquidityToken1Amount,
2356
+ slippageTolerance,
2357
+ positionId,
2358
+ isValidPosition
2359
+ }) {
2360
+ return useMemo(() => {
2361
+ return createSupplyLiquidityParamsProps({
2362
+ poolData,
2363
+ poolKey,
2364
+ minPrice,
2365
+ maxPrice,
2366
+ liquidityToken0Amount,
2367
+ liquidityToken1Amount,
2368
+ slippageTolerance,
2369
+ positionId,
2370
+ isValidPosition
2371
+ });
2372
+ }, [
2373
+ minPrice,
2374
+ maxPrice,
2375
+ liquidityToken0Amount,
2376
+ liquidityToken1Amount,
2377
+ slippageTolerance,
2378
+ poolData,
2379
+ poolKey,
2380
+ positionId,
2381
+ isValidPosition
2382
+ ]);
2383
+ }
2384
+ function useCreateDecreaseLiquidityParams({
2385
+ poolKey,
2386
+ tokenId,
2387
+ percentage,
2388
+ positionInfo,
2389
+ slippageTolerance
2390
+ }) {
2391
+ return useMemo(() => {
2392
+ return createDecreaseLiquidityParamsProps({ poolKey, tokenId, percentage, positionInfo, slippageTolerance });
2393
+ }, [poolKey, tokenId, percentage, positionInfo, slippageTolerance]);
2394
+ }
2395
+ function useCreateWithdrawParams({
2396
+ tokenIndex,
2397
+ amount,
2398
+ poolData,
2399
+ poolSpokeAssets,
2400
+ dst
2401
+ }) {
2402
+ return useMemo(() => {
2403
+ if (!amount || Number.parseFloat(String(amount)) <= 0) {
2404
+ return void 0;
2405
+ }
2406
+ return createWithdrawParamsProps({ tokenIndex, amount, poolData, poolSpokeAssets, dst });
2407
+ }, [tokenIndex, amount, poolData, poolSpokeAssets, dst]);
2408
+ }
2409
+ function useClaimRewards() {
2410
+ const { sodax } = useSodaxContext();
2411
+ const queryClient = useQueryClient();
2412
+ return useMutation({
2413
+ mutationFn: async ({ params, spokeProvider }) => {
2414
+ if (!spokeProvider) {
2415
+ throw new Error("Spoke provider is required");
2416
+ }
2417
+ const result = await sodax.dex.clService.claimRewards({
2418
+ params,
2419
+ spokeProvider
2420
+ });
2421
+ if (!result.ok) {
2422
+ throw new Error(`Claim rewards failed: ${result.error?.code || "Unknown error"}`);
2423
+ }
2424
+ return result.value;
2425
+ },
2426
+ onSuccess: (_, { params, spokeProvider }) => {
2427
+ queryClient.invalidateQueries({
2428
+ queryKey: ["dex", "poolBalances", params.poolKey, spokeProvider.chainConfig.chain.id]
2429
+ });
2430
+ queryClient.invalidateQueries({ queryKey: ["dex", "positionInfo", params.tokenId, params.poolKey] });
2431
+ queryClient.invalidateQueries({ queryKey: ["dex", "poolData", params.poolKey] });
2432
+ }
2433
+ });
2434
+ }
1777
2435
  var SodaxProvider = ({ children, testnet = false, config, rpcConfig }) => {
1778
2436
  const sodax = new Sodax(config);
1779
2437
  return /* @__PURE__ */ React.createElement(SodaxContext.Provider, { value: { sodax, testnet, rpcConfig } }, children);
1780
2438
  };
1781
2439
 
1782
- export { MIGRATION_MODE_BNUSD, MIGRATION_MODE_ICX_SODA, SodaxProvider, clearRadfiSession, isAccessTokenExpired, isRefreshTokenExpired, loadRadfiSession, saveRadfiSession, useAToken, useATokensBalances, useBackendAllMoneyMarketAssets, useBackendAllMoneyMarketBorrowers, useBackendIntentByHash, useBackendIntentByTxHash, useBackendMoneyMarketAsset, useBackendMoneyMarketAssetBorrowers, useBackendMoneyMarketAssetSuppliers, useBackendMoneyMarketPosition, useBackendOrderbook, useBackendUserIntents, useBitcoinBalance, useBorrow, useBridge, useBridgeAllowance, useBridgeApprove, useCancelLimitOrder, useCancelSwap, useCancelUnstake, useClaim, useConvertedAssets, useCreateLimitOrder, useDeriveUserWalletAddress, useEstimateGas, useExpiredUtxos, useFundTradingWallet, useGetBridgeableAmount, useGetBridgeableTokens, useGetUserHubWalletAddress, useHubProvider, useInstantUnstake, useInstantUnstakeAllowance, useInstantUnstakeApprove, useInstantUnstakeRatio, useMMAllowance, useMMApprove, useMigrate, useMigrationAllowance, useMigrationApprove, useQuote, useRadfiAuth, useRadfiSession, useRenewUtxos, useRepay, useRequestTrustline, useReservesData, useReservesUsdFormat, useSodaxContext, useSpokeProvider, useStake, useStakeAllowance, useStakeApprove, useStakeRatio, useStakingConfig, useStakingInfo, useStatus, useStellarTrustlineCheck, useSupply, useSwap, useSwapAllowance, useSwapApprove, useTradingWalletBalance, useUnstake, useUnstakeAllowance, useUnstakeApprove, useUnstakingInfo, useUnstakingInfoWithPenalty, useUserFormattedSummary, useUserReservesData, useWithdraw };
2440
+ export { MIGRATION_MODE_BNUSD, MIGRATION_MODE_ICX_SODA, SodaxProvider, clearRadfiSession, createDecreaseLiquidityParamsProps, createDepositParamsProps, createSupplyLiquidityParamsProps, createWithdrawParamsProps, loadRadfiSession, saveRadfiSession, useAToken, useATokensBalances, useBackendAllMoneyMarketAssets, useBackendAllMoneyMarketBorrowers, useBackendIntentByHash, useBackendIntentByTxHash, useBackendMoneyMarketAsset, useBackendMoneyMarketAssetBorrowers, useBackendMoneyMarketAssetSuppliers, useBackendMoneyMarketPosition, useBackendOrderbook, useBackendSubmitSwapTx, useBackendSubmitSwapTxStatus, useBackendUserIntents, useBitcoinBalance, useBorrow, useBridge, useBridgeAllowance, useBridgeApprove, useCancelLimitOrder, useCancelSwap, useCancelUnstake, useClaim, useClaimRewards, useConvertedAssets, useCreateDecreaseLiquidityParams, useCreateDepositParams, useCreateLimitOrder, useCreateSupplyLiquidityParams, useCreateWithdrawParams, useDecreaseLiquidity, useDeriveUserWalletAddress, useDexAllowance, useDexApprove, useDexDeposit, useDexWithdraw, useEstimateGas, useExpiredUtxos, useFundTradingWallet, useGetBridgeableAmount, useGetBridgeableTokens, useGetUserHubWalletAddress, useHubProvider, useInstantUnstake, useInstantUnstakeAllowance, useInstantUnstakeApprove, useInstantUnstakeRatio, useLiquidityAmounts, useMMAllowance, useMMApprove, useMigrate, useMigrationAllowance, useMigrationApprove, usePoolBalances, usePoolData, usePools, usePositionInfo, useQuote, useRadfiAuth, useRadfiSession, useRadfiWithdraw, useRenewUtxos, useRepay, useRequestTrustline, useReservesData, useReservesUsdFormat, useSodaxContext, useSpokeProvider, useStake, useStakeAllowance, useStakeApprove, useStakeRatio, useStakingConfig, useStakingInfo, useStatus, useStellarTrustlineCheck, useSupply, useSupplyLiquidity, useSwap, useSwapAllowance, useSwapApprove, useTradingWalletBalance, useUnstake, useUnstakeAllowance, useUnstakeApprove, useUnstakingInfo, useUnstakingInfoWithPenalty, useUserFormattedSummary, useUserReservesData, useWithdraw };
1783
2441
  //# sourceMappingURL=index.mjs.map
1784
2442
  //# sourceMappingURL=index.mjs.map