@sodax/dapp-kit 1.5.7-beta → 2.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/README.md +300 -422
  2. package/ai-exported/AGENTS.md +134 -0
  3. package/ai-exported/integration/README.md +49 -0
  4. package/ai-exported/integration/ai-rules.md +79 -0
  5. package/ai-exported/integration/architecture.md +274 -0
  6. package/ai-exported/integration/features/README.md +29 -0
  7. package/ai-exported/integration/features/auxiliary-services.md +169 -0
  8. package/ai-exported/integration/features/bitcoin.md +87 -0
  9. package/ai-exported/integration/features/bridge.md +91 -0
  10. package/ai-exported/integration/features/dex.md +152 -0
  11. package/ai-exported/integration/features/migration.md +118 -0
  12. package/ai-exported/integration/features/money-market.md +116 -0
  13. package/ai-exported/integration/features/staking.md +123 -0
  14. package/ai-exported/integration/features/swap.md +101 -0
  15. package/ai-exported/integration/quickstart.md +187 -0
  16. package/ai-exported/integration/recipes/README.md +136 -0
  17. package/ai-exported/integration/recipes/backend-queries.md +157 -0
  18. package/ai-exported/integration/recipes/bitcoin.md +193 -0
  19. package/ai-exported/integration/recipes/bridge.md +174 -0
  20. package/ai-exported/integration/recipes/dex.md +204 -0
  21. package/ai-exported/integration/recipes/invalidations.md +115 -0
  22. package/ai-exported/integration/recipes/migration.md +212 -0
  23. package/ai-exported/integration/recipes/money-market.md +206 -0
  24. package/ai-exported/integration/recipes/mutation-error-handling.md +118 -0
  25. package/ai-exported/integration/recipes/observability.md +93 -0
  26. package/ai-exported/integration/recipes/setup.md +144 -0
  27. package/ai-exported/integration/recipes/staking.md +202 -0
  28. package/ai-exported/integration/recipes/swap.md +272 -0
  29. package/ai-exported/integration/recipes/wallet-connectivity.md +101 -0
  30. package/ai-exported/integration/reference/README.md +12 -0
  31. package/ai-exported/integration/reference/glossary.md +188 -0
  32. package/ai-exported/integration/reference/hooks-index.md +194 -0
  33. package/ai-exported/integration/reference/public-api.md +110 -0
  34. package/ai-exported/integration/reference/querykey-conventions.md +179 -0
  35. package/ai-exported/migration/README.md +60 -0
  36. package/ai-exported/migration/ai-rules.md +81 -0
  37. package/ai-exported/migration/breaking-changes/hook-signatures.md +233 -0
  38. package/ai-exported/migration/breaking-changes/querykey-conventions.md +108 -0
  39. package/ai-exported/migration/breaking-changes/result-handling.md +211 -0
  40. package/ai-exported/migration/breaking-changes/sdk-leakage.md +165 -0
  41. package/ai-exported/migration/checklist.md +89 -0
  42. package/ai-exported/migration/features/README.md +34 -0
  43. package/ai-exported/migration/features/auxiliary-services.md +114 -0
  44. package/ai-exported/migration/features/bitcoin.md +88 -0
  45. package/ai-exported/migration/features/bridge.md +123 -0
  46. package/ai-exported/migration/features/dex.md +101 -0
  47. package/ai-exported/migration/features/migration.md +120 -0
  48. package/ai-exported/migration/features/money-market.md +97 -0
  49. package/ai-exported/migration/features/staking.md +109 -0
  50. package/ai-exported/migration/features/swap.md +118 -0
  51. package/ai-exported/migration/recipes.md +188 -0
  52. package/ai-exported/migration/reference/README.md +15 -0
  53. package/ai-exported/migration/reference/deleted-hooks.md +110 -0
  54. package/ai-exported/migration/reference/error-shape-crosswalk.md +144 -0
  55. package/ai-exported/migration/reference/renamed-hooks.md +66 -0
  56. package/dist/index.cjs +2642 -0
  57. package/dist/index.cjs.map +1 -0
  58. package/dist/index.d.cts +1550 -0
  59. package/dist/index.d.ts +1020 -2051
  60. package/dist/index.mjs +1581 -1531
  61. package/dist/index.mjs.map +1 -1
  62. package/package.json +20 -10
  63. package/src/contexts/index.ts +0 -3
  64. package/src/hooks/_mutationContract.test.ts +99 -0
  65. package/src/hooks/backend/README.md +2 -2
  66. package/src/hooks/backend/index.ts +13 -13
  67. package/src/hooks/backend/unwrapResult.ts +1 -0
  68. package/src/hooks/backend/useBackendAllMoneyMarketAssets.ts +13 -45
  69. package/src/hooks/backend/useBackendAllMoneyMarketBorrowers.ts +29 -59
  70. package/src/hooks/backend/useBackendIntentByHash.ts +21 -47
  71. package/src/hooks/backend/useBackendIntentByTxHash.ts +23 -50
  72. package/src/hooks/backend/useBackendMoneyMarketAsset.ts +21 -54
  73. package/src/hooks/backend/useBackendMoneyMarketAssetBorrowers.ts +30 -57
  74. package/src/hooks/backend/useBackendMoneyMarketAssetSuppliers.ts +31 -58
  75. package/src/hooks/backend/useBackendMoneyMarketPosition.ts +22 -38
  76. package/src/hooks/backend/useBackendOrderbook.ts +27 -49
  77. package/src/hooks/backend/useBackendSubmitSwapTx.ts +30 -36
  78. package/src/hooks/backend/useBackendSubmitSwapTxStatus.ts +38 -58
  79. package/src/hooks/backend/useBackendUserIntents.ts +25 -63
  80. package/src/hooks/bitcoin/index.ts +9 -8
  81. package/src/hooks/bitcoin/useBitcoinBalance.ts +20 -5
  82. package/src/hooks/bitcoin/useExpiredUtxos.ts +26 -16
  83. package/src/hooks/bitcoin/useFundTradingWallet.ts +33 -30
  84. package/src/hooks/bitcoin/useRadfiAuth.ts +43 -40
  85. package/src/hooks/bitcoin/useRadfiSession.ts +53 -59
  86. package/src/hooks/bitcoin/useRadfiWithdraw.ts +35 -53
  87. package/src/hooks/bitcoin/useRenewUtxos.ts +30 -50
  88. package/src/hooks/bitcoin/useTradingWallet.ts +1 -1
  89. package/src/hooks/bitcoin/useTradingWalletBalance.ts +25 -14
  90. package/src/hooks/bridge/index.ts +5 -5
  91. package/src/hooks/bridge/useBridge.ts +29 -55
  92. package/src/hooks/bridge/useBridgeAllowance.ts +38 -38
  93. package/src/hooks/bridge/useBridgeApprove.ts +32 -57
  94. package/src/hooks/bridge/useGetBridgeableAmount.ts +23 -37
  95. package/src/hooks/bridge/useGetBridgeableTokens.ts +27 -50
  96. package/src/hooks/dex/index.ts +16 -16
  97. package/src/hooks/dex/useClaimRewards.ts +35 -54
  98. package/src/hooks/dex/useCreateDecreaseLiquidityParams.ts +7 -20
  99. package/src/hooks/dex/useCreateDepositParams.ts +7 -21
  100. package/src/hooks/dex/useCreateSupplyLiquidityParams.ts +13 -28
  101. package/src/hooks/dex/useCreateWithdrawParams.ts +7 -20
  102. package/src/hooks/dex/useDecreaseLiquidity.ts +40 -66
  103. package/src/hooks/dex/useDexAllowance.ts +29 -75
  104. package/src/hooks/dex/useDexApprove.ts +32 -43
  105. package/src/hooks/dex/useDexDeposit.ts +42 -49
  106. package/src/hooks/dex/useDexWithdraw.ts +32 -43
  107. package/src/hooks/dex/useLiquidityAmounts.ts +13 -82
  108. package/src/hooks/dex/usePoolBalances.ts +50 -72
  109. package/src/hooks/dex/usePoolData.ts +17 -43
  110. package/src/hooks/dex/usePools.ts +11 -38
  111. package/src/hooks/dex/usePositionInfo.ts +27 -62
  112. package/src/hooks/dex/useSupplyLiquidity.ts +80 -75
  113. package/src/hooks/index.ts +12 -10
  114. package/src/hooks/migrate/index.ts +13 -4
  115. package/src/hooks/migrate/useMigrateBaln.ts +42 -0
  116. package/src/hooks/migrate/useMigrateIcxToSoda.ts +44 -0
  117. package/src/hooks/migrate/useMigratebnUSD.ts +47 -0
  118. package/src/hooks/migrate/useMigrationAllowance.ts +76 -0
  119. package/src/hooks/migrate/useMigrationApprove.ts +66 -0
  120. package/src/hooks/migrate/useRevertMigrateSodaToIcx.ts +39 -0
  121. package/src/hooks/mm/index.ts +14 -12
  122. package/src/hooks/mm/useAToken.ts +25 -41
  123. package/src/hooks/mm/useATokensBalances.ts +29 -60
  124. package/src/hooks/mm/useBorrow.ts +38 -56
  125. package/src/hooks/mm/useMMAllowance.ts +37 -73
  126. package/src/hooks/mm/useMMApprove.ts +36 -43
  127. package/src/hooks/mm/useRepay.ts +33 -53
  128. package/src/hooks/mm/useReservesData.ts +12 -38
  129. package/src/hooks/mm/useReservesHumanized.ts +12 -31
  130. package/src/hooks/mm/useReservesList.ts +11 -31
  131. package/src/hooks/mm/useReservesUsdFormat.ts +15 -35
  132. package/src/hooks/mm/useSupply.ts +45 -51
  133. package/src/hooks/mm/useUserFormattedSummary.ts +32 -84
  134. package/src/hooks/mm/useUserReservesData.ts +27 -77
  135. package/src/hooks/mm/useWithdraw.ts +38 -54
  136. package/src/hooks/partner/index.ts +6 -0
  137. package/src/hooks/partner/useApproveToken.ts +42 -0
  138. package/src/hooks/partner/useFeeClaimSwap.ts +38 -0
  139. package/src/hooks/partner/useFetchAssetsBalances.ts +37 -0
  140. package/src/hooks/partner/useGetAutoSwapPreferences.ts +37 -0
  141. package/src/hooks/partner/useIsTokenApproved.ts +39 -0
  142. package/src/hooks/partner/useSetSwapPreference.ts +50 -0
  143. package/src/hooks/provider/index.ts +1 -2
  144. package/src/hooks/provider/useHubProvider.ts +1 -1
  145. package/src/hooks/recovery/index.ts +2 -0
  146. package/src/hooks/recovery/useHubAssetBalances.ts +43 -0
  147. package/src/hooks/recovery/useWithdrawHubAsset.ts +48 -0
  148. package/src/hooks/shared/index.ts +10 -6
  149. package/src/hooks/shared/types.ts +77 -0
  150. package/src/hooks/shared/unwrapResult.ts +19 -0
  151. package/src/hooks/shared/useDeriveUserWalletAddress.ts +22 -40
  152. package/src/hooks/shared/useEstimateGas.ts +18 -15
  153. package/src/hooks/shared/useGetUserHubWalletAddress.ts +25 -26
  154. package/src/hooks/shared/useRequestTrustline.ts +28 -61
  155. package/src/hooks/shared/useSafeMutation.test.ts +43 -0
  156. package/src/hooks/shared/useSafeMutation.ts +68 -0
  157. package/src/hooks/shared/useSodaxContext.ts +1 -1
  158. package/src/hooks/shared/useStellarTrustlineCheck.ts +30 -64
  159. package/src/hooks/shared/useXBalances.test.ts +113 -0
  160. package/src/hooks/shared/useXBalances.ts +61 -0
  161. package/src/hooks/staking/index.ts +18 -18
  162. package/src/hooks/staking/useCancelUnstake.ts +30 -41
  163. package/src/hooks/staking/useClaim.ts +27 -36
  164. package/src/hooks/staking/useConvertedAssets.ts +24 -34
  165. package/src/hooks/staking/useInstantUnstake.ts +33 -40
  166. package/src/hooks/staking/useInstantUnstakeAllowance.ts +37 -45
  167. package/src/hooks/staking/useInstantUnstakeApprove.ts +42 -42
  168. package/src/hooks/staking/useInstantUnstakeRatio.ts +24 -41
  169. package/src/hooks/staking/useStake.ts +32 -37
  170. package/src/hooks/staking/useStakeAllowance.ts +30 -43
  171. package/src/hooks/staking/useStakeApprove.ts +40 -40
  172. package/src/hooks/staking/useStakeRatio.ts +24 -40
  173. package/src/hooks/staking/useStakingConfig.ts +14 -27
  174. package/src/hooks/staking/useStakingInfo.ts +30 -38
  175. package/src/hooks/staking/useUnstake.ts +29 -43
  176. package/src/hooks/staking/useUnstakeAllowance.ts +37 -44
  177. package/src/hooks/staking/useUnstakeApprove.ts +40 -43
  178. package/src/hooks/staking/useUnstakingInfo.ts +29 -41
  179. package/src/hooks/staking/useUnstakingInfoWithPenalty.ts +31 -47
  180. package/src/hooks/swap/index.ts +8 -8
  181. package/src/hooks/swap/useCancelLimitOrder.ts +24 -41
  182. package/src/hooks/swap/useCancelSwap.ts +24 -33
  183. package/src/hooks/swap/useCreateLimitOrder.ts +29 -62
  184. package/src/hooks/swap/useQuote.ts +17 -43
  185. package/src/hooks/swap/useStatus.ts +22 -29
  186. package/src/hooks/swap/useSwap.ts +31 -49
  187. package/src/hooks/swap/useSwapAllowance.ts +38 -35
  188. package/src/hooks/swap/useSwapApprove.ts +48 -57
  189. package/src/index.ts +5 -3
  190. package/src/providers/SodaxProvider.tsx +17 -11
  191. package/src/providers/createSodaxQueryClient.ts +96 -0
  192. package/src/providers/index.ts +2 -1
  193. package/src/utils/dex-utils.ts +27 -5
  194. package/src/utils/index.ts +1 -1
  195. package/dist/index.d.mts +0 -2581
  196. package/dist/index.js +0 -2574
  197. package/dist/index.js.map +0 -1
  198. package/src/hooks/migrate/types.ts +0 -15
  199. package/src/hooks/migrate/useMigrate.tsx +0 -110
  200. package/src/hooks/migrate/useMigrationAllowance.tsx +0 -79
  201. package/src/hooks/migrate/useMigrationApprove.tsx +0 -129
  202. package/src/hooks/provider/useSpokeProvider.ts +0 -172
@@ -1,42 +1,23 @@
1
1
  import type { ReservesDataHumanized } from '@sodax/sdk';
2
- import { useQuery, type UseQueryOptions, type UseQueryResult } from '@tanstack/react-query';
3
- import { useSodaxContext } from '../shared/useSodaxContext';
2
+ import { useQuery, type UseQueryResult } from '@tanstack/react-query';
3
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
4
+ import type { ReadHookParams } from '../shared/types.js';
4
5
 
5
- export type UseReservesHumanizedParams = {
6
- queryOptions?: UseQueryOptions<ReservesDataHumanized, Error>;
7
- };
6
+ export type UseReservesHumanizedParams = ReadHookParams<ReservesDataHumanized>;
8
7
 
9
8
  /**
10
- * Hook for fetching humanized reserves data from the Sodax money market.
11
- *
12
- * This hook provides access to the current state of all reserves (humanized format) in the money market protocol,
13
- * including liquidity, interest rates, and other key metrics. The data is automatically
14
- * fetched and cached using React Query.
15
- *
16
- * @example
17
- * ```typescript
18
- * const { data: reservesHumanized, isLoading, error } = useReservesHumanized();
19
- * ```
20
- *
21
- * @returns A React Query result object containing:
22
- * - data: The reserves humanized data when available
23
- * - isLoading: Loading state indicator
24
- * - error: Any error that occurred during data fetching
9
+ * React hook for fetching the human-readable (decimal-normalized, string-formatted) reserves
10
+ * snapshot from the Sodax money market.
25
11
  */
26
- export function useReservesHumanized(
27
- params?: UseReservesHumanizedParams,
28
- ): UseQueryResult<ReservesDataHumanized, Error> {
29
- const defaultQueryOptions = { queryKey: ['mm', 'reservesHumanized'], refetchInterval: 5000 };
30
- const queryOptions = {
31
- ...defaultQueryOptions,
32
- ...params?.queryOptions, // override default query options if provided
33
- };
12
+ export function useReservesHumanized({
13
+ queryOptions,
14
+ }: UseReservesHumanizedParams = {}): UseQueryResult<ReservesDataHumanized, Error> {
34
15
  const { sodax } = useSodaxContext();
35
16
 
36
17
  return useQuery({
18
+ queryKey: ['mm', 'reservesHumanized'],
19
+ queryFn: async () => sodax.moneyMarket.data.getReservesHumanized(),
20
+ refetchInterval: 5000,
37
21
  ...queryOptions,
38
- queryFn: async () => {
39
- return await sodax.moneyMarket.data.getReservesHumanized();
40
- },
41
22
  });
42
23
  }
@@ -1,42 +1,22 @@
1
- import { useQuery, type UseQueryResult, type UseQueryOptions } from '@tanstack/react-query';
2
- import { useSodaxContext } from '../shared/useSodaxContext';
3
1
  import type { Address } from '@sodax/sdk';
2
+ import { useQuery, type UseQueryResult } from '@tanstack/react-query';
3
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
4
+ import type { ReadHookParams } from '../shared/types.js';
4
5
 
5
- export type UseReservesListParams = {
6
- queryOptions?: UseQueryOptions<readonly Address[], Error>;
7
- };
6
+ export type UseReservesListParams = ReadHookParams<readonly Address[]>;
8
7
 
9
8
  /**
10
- * React hook for fetching the list of reserve addresses from the Sodax money market.
11
- *
12
- * This hook returns a React Query result object containing the array of all reserve `Address`
13
- * values currently available in the protocol. Optionally, custom React Query options can be provided.
14
- *
15
- * @param params (optional) - Object including:
16
- * - queryOptions: Custom React Query options such as `queryKey`, cache behavior, or refetching policy
17
- *
18
- * @returns {UseQueryResult<readonly Address[], Error>} React Query result object containing:
19
- * - data: Array of reserve addresses, or undefined if loading
20
- * - isLoading: Boolean loading state
21
- * - isError: Boolean error state
22
- * - error: Error object, if present
23
- *
24
- * @example
25
- * const { data: reservesList, isLoading, error } = useReservesList();
26
- * const { data } = useReservesList({ queryOptions: { queryKey: ['custom', 'reservesList'] } });
9
+ * React hook for fetching the list of reserve asset addresses currently registered in the
10
+ * Sodax money market.
27
11
  */
28
- export function useReservesList(params?: UseReservesListParams): UseQueryResult<readonly Address[], Error> {
29
- const defaultQueryOptions = { queryKey: ['mm', 'reservesList'] };
30
- const queryOptions = {
31
- ...defaultQueryOptions,
32
- ...params?.queryOptions, // override default query options if provided
33
- };
12
+ export function useReservesList({
13
+ queryOptions,
14
+ }: UseReservesListParams = {}): UseQueryResult<readonly Address[], Error> {
34
15
  const { sodax } = useSodaxContext();
35
16
 
36
17
  return useQuery<readonly Address[], Error>({
18
+ queryKey: ['mm', 'reservesList'],
19
+ queryFn: async () => sodax.moneyMarket.data.getReservesList(),
37
20
  ...queryOptions,
38
- queryFn: async (): Promise<readonly Address[]> => {
39
- return await sodax.moneyMarket.data.getReservesList();
40
- },
41
21
  });
42
22
  }
@@ -1,47 +1,27 @@
1
- import type { FormatReserveUSDResponse, ReserveData } from '@sodax/sdk';
2
- import { useQuery, type UseQueryOptions, type UseQueryResult } from '@tanstack/react-query';
3
- import { useSodaxContext } from '../shared/useSodaxContext';
1
+ import type { FormatReserveUSDResponse, ReserveDataHumanized } from '@sodax/sdk';
2
+ import { useQuery, type UseQueryResult } from '@tanstack/react-query';
3
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
4
+ import type { ReadHookParams } from '../shared/types.js';
4
5
 
5
- export type UseReservesUsdFormatParams = {
6
- queryOptions?: UseQueryOptions<
7
- (ReserveData & { priceInMarketReferenceCurrency: string } & FormatReserveUSDResponse)[],
8
- Error
9
- >;
10
- };
6
+ export type ReserveUsdFormat = ReserveDataHumanized & FormatReserveUSDResponse;
7
+
8
+ export type UseReservesUsdFormatParams = ReadHookParams<ReserveUsdFormat[]>;
11
9
 
12
10
  /**
13
- * Hook for fetching reserves data formatted with USD values in the Sodax money market.
14
- *
15
- * This hook returns an array of reserve objects, each extended with its price in the market reference
16
- * currency and formatted USD values. Data is automatically fetched and cached using React Query.
17
- *
18
- * @param params (optional) - Object including:
19
- * - queryOptions: Custom React Query options such as `queryKey`, cache behavior, or refetching policy.
20
- *
21
- * @returns {UseQueryResult<(ReserveData & { priceInMarketReferenceCurrency: string } & FormatReserveUSDResponse)[], Error>} React Query result object containing:
22
- * - data: Array of reserves with USD-formatted values, or undefined if loading
23
- * - isLoading: Boolean loading state
24
- * - isError: Boolean error state
25
- * - error: Error object, if present
26
- *
27
- * @example
28
- * const { data: reservesUSD, isLoading, error } = useReservesUsdFormat();
11
+ * React hook returning reserves with USD-formatted values for the Sodax money market.
12
+ * Chains `getReservesHumanized` → `buildReserveDataWithPrice` → `formatReservesUSD`.
29
13
  */
30
- export function useReservesUsdFormat(
31
- params?: UseReservesUsdFormatParams,
32
- ): UseQueryResult<(ReserveData & { priceInMarketReferenceCurrency: string } & FormatReserveUSDResponse)[], Error> {
14
+ export function useReservesUsdFormat({
15
+ queryOptions,
16
+ }: UseReservesUsdFormatParams = {}): UseQueryResult<ReserveUsdFormat[], Error> {
33
17
  const { sodax } = useSodaxContext();
34
- const defaultQueryOptions = { queryKey: ['mm', 'reservesUsdFormat'] };
35
- const queryOptions = {
36
- ...defaultQueryOptions,
37
- ...params?.queryOptions, // override default query options if provided
38
- };
39
18
 
40
- return useQuery({
41
- ...queryOptions,
19
+ return useQuery<ReserveUsdFormat[], Error>({
20
+ queryKey: ['mm', 'reservesUsdFormat'],
42
21
  queryFn: async () => {
43
22
  const reserves = await sodax.moneyMarket.data.getReservesHumanized();
44
23
  return sodax.moneyMarket.data.formatReservesUSD(sodax.moneyMarket.data.buildReserveDataWithPrice(reserves));
45
24
  },
25
+ ...queryOptions,
46
26
  });
47
27
  }
@@ -1,65 +1,59 @@
1
- import type { MoneyMarketError, MoneyMarketSupplyParams, RelayErrorCode, SpokeProvider } from '@sodax/sdk';
2
- import { useMutation, type UseMutationResult } from '@tanstack/react-query';
3
- import { useSodaxContext } from '../shared/useSodaxContext';
1
+ // packages/dapp-kit/src/hooks/mm/useSupply.ts
2
+ import type { MoneyMarketSupplyActionParams, SpokeChainKey, TxHashPair } from '@sodax/sdk';
3
+ import { useQueryClient } from '@tanstack/react-query';
4
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
5
+ import type { MutationHookParams } from '../shared/types.js';
6
+ import { useSafeMutation, type SafeUseMutationResult } from '../shared/useSafeMutation.js';
7
+ import { unwrapResult } from '../shared/unwrapResult.js';
4
8
 
5
- interface SupplyResponse {
6
- ok: true;
7
- value: [string, string];
8
- }
9
-
10
- export type UseSupplyParams = {
11
- params: MoneyMarketSupplyParams;
12
- spokeProvider: SpokeProvider;
13
- };
9
+ /**
10
+ * Mutation variables for {@link useSupply}. Generic over `K extends SpokeChainKey` (defaults to
11
+ * the full union). Sophisticated callers can lock K at the hook call site to narrow the
12
+ * `walletProvider` and `params.srcChainKey` types.
13
+ */
14
+ export type UseSupplyVars<K extends SpokeChainKey = SpokeChainKey> = Omit<
15
+ MoneyMarketSupplyActionParams<K, false>,
16
+ 'raw'
17
+ >;
14
18
 
15
19
  /**
16
20
  * React hook for supplying tokens to the Sodax money market protocol.
17
21
  *
18
- * Provides a mutation for performing the supply operation using React Query. Useful
19
- * for UI components needing to manage the full state (pending, error, etc.) of a supply
20
- * transaction. It handles transaction creation, cross-chain logic, and errors.
21
- *
22
- * @returns {UseMutationResult<SupplyResponse, MoneyMarketError<'CREATE_SUPPLY_INTENT_FAILED' | 'SUPPLY_UNKNOWN_ERROR' | RelayErrorCode>, UseSupplyParams>}
23
- * Mutation result object from React Query, where:
24
- * - mutateAsync(params: UseSupplyParams): Promise<SupplyResponse>
25
- * Initiates a supply transaction using the given MoneyMarketSupplyParams and SpokeProvider.
26
- * - isPending: boolean indicating if a transaction is in progress.
27
- * - error: MoneyMarketError if an error occurred while supplying, otherwise undefined.
22
+ * Throws on SDK failure so React Query's native error model engages (`isError`, `error`,
23
+ * `onError`, `retry`). Returns the unwrapped `TxHashPair` on success.
28
24
  *
29
25
  * @example
30
- * ```typescript
31
- * const { mutateAsync: supply, isPending, error } = useSupply();
32
- * await supply({ params: supplyParams, spokeProvider });
26
+ * ```tsx
27
+ * const walletProvider = useWalletProvider({ xChainId: chainKey });
28
+ * const { mutateAsync: supply, isError, error } = useSupply();
29
+ * if (!walletProvider) return;
30
+ * try {
31
+ * const { spokeTxHash, hubTxHash } = await supply({ params: supplyParams, walletProvider });
32
+ * } catch (e) {
33
+ * // surfaced via mutation.error / onError
34
+ * }
33
35
  * ```
34
- *
35
- * @throws {Error|MoneyMarketError<...>} When:
36
- * - `spokeProvider` is not provided or invalid.
37
- * - The underlying supply transaction fails.
38
36
  */
39
- export function useSupply(): UseMutationResult<
40
- SupplyResponse,
41
- MoneyMarketError<'CREATE_SUPPLY_INTENT_FAILED' | 'SUPPLY_UNKNOWN_ERROR' | RelayErrorCode>,
42
- UseSupplyParams
43
- > {
37
+ export function useSupply<K extends SpokeChainKey = SpokeChainKey>({
38
+ mutationOptions,
39
+ }: MutationHookParams<TxHashPair, UseSupplyVars<K>> = {}): SafeUseMutationResult<TxHashPair, Error, UseSupplyVars<K>> {
44
40
  const { sodax } = useSodaxContext();
41
+ const queryClient = useQueryClient();
45
42
 
46
- return useMutation<
47
- SupplyResponse,
48
- MoneyMarketError<'CREATE_SUPPLY_INTENT_FAILED' | 'SUPPLY_UNKNOWN_ERROR' | RelayErrorCode>,
49
- UseSupplyParams
50
- >({
51
- mutationFn: async ({ params, spokeProvider }: UseSupplyParams) => {
52
- if (!spokeProvider) {
53
- throw new Error('spokeProvider is not found');
54
- }
55
-
56
- const response = await sodax.moneyMarket.supply(params, spokeProvider);
57
-
58
- if (!response.ok) {
59
- throw response.error;
60
- }
61
-
62
- return response;
43
+ return useSafeMutation<TxHashPair, Error, UseSupplyVars<K>>({
44
+ mutationKey: ['mm', 'supply'],
45
+ ...mutationOptions,
46
+ mutationFn: async vars => unwrapResult(await sodax.moneyMarket.supply({ ...vars, raw: false })),
47
+ onSuccess: async (data, vars, ctx) => {
48
+ const { params } = vars;
49
+ queryClient.invalidateQueries({ queryKey: ['mm', 'userReservesData', params.srcChainKey, params.srcAddress] });
50
+ queryClient.invalidateQueries({
51
+ queryKey: ['mm', 'userFormattedSummary', params.srcChainKey, params.srcAddress],
52
+ });
53
+ queryClient.invalidateQueries({ queryKey: ['mm', 'aTokensBalances'] });
54
+ queryClient.invalidateQueries({ queryKey: ['mm', 'allowance', params.srcChainKey, params.token, params.action] });
55
+ queryClient.invalidateQueries({ queryKey: ['shared', 'xBalances', params.srcChainKey] });
56
+ await mutationOptions?.onSuccess?.(data, vars, ctx);
63
57
  },
64
58
  });
65
59
  }
@@ -1,105 +1,53 @@
1
- import type { SpokeChainId } from '@sodax/types';
2
- import type { FormatUserSummaryResponse, FormatReserveUSDResponse, SpokeProvider } from '@sodax/sdk';
3
- import { useQuery, type UseQueryOptions, type UseQueryResult } from '@tanstack/react-query';
4
- import { useSodaxContext } from '../shared/useSodaxContext';
5
-
6
- type BaseQueryOptions = {
7
- queryOptions?: UseQueryOptions<FormatUserSummaryResponse<FormatReserveUSDResponse>, Error>;
8
- };
9
-
10
- type NewParams = BaseQueryOptions & {
11
- /** Spoke chain id (e.g. '0xa86a.avax') */
12
- spokeChainId: SpokeChainId | undefined;
13
- /** User wallet address on the spoke chain */
14
- userAddress: string | undefined;
15
- };
16
-
17
- /** @deprecated Use `{ spokeChainId, userAddress }` instead */
18
- type LegacyParams = BaseQueryOptions & {
19
- /** @deprecated Use `spokeChainId` instead */
20
- spokeProvider: SpokeProvider | undefined;
21
- /** @deprecated Use `userAddress` instead */
22
- address: string | undefined;
23
- };
24
-
25
- export type UseUserFormattedSummaryParams = NewParams | LegacyParams;
26
-
27
- function isLegacyParams(params: UseUserFormattedSummaryParams): params is LegacyParams {
28
- return 'spokeProvider' in params || 'address' in params;
29
- }
30
-
31
- function resolveParams(params: UseUserFormattedSummaryParams): {
32
- spokeChainId: SpokeChainId | undefined;
33
- userAddress: string | undefined;
34
- } {
35
- if (isLegacyParams(params)) {
36
- return {
37
- spokeChainId: params.spokeProvider?.chainConfig.chain.id as SpokeChainId | undefined,
38
- userAddress: params.address,
39
- };
1
+ import type { FormatReserveUSDResponse, FormatUserSummaryResponse } from '@sodax/sdk';
2
+ import type { SpokeChainKey } from '@sodax/sdk';
3
+ import { useQuery, type UseQueryResult } from '@tanstack/react-query';
4
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
5
+ import type { ReadHookParams } from '../shared/types.js';
6
+
7
+ export type UseUserFormattedSummaryParams = ReadHookParams<
8
+ FormatUserSummaryResponse<FormatReserveUSDResponse>,
9
+ {
10
+ spokeChainKey: SpokeChainKey | undefined;
11
+ userAddress: string | undefined;
40
12
  }
41
- return { spokeChainId: params.spokeChainId, userAddress: params.userAddress };
42
- }
13
+ >;
43
14
 
44
15
  /**
45
- * React hook to fetch a formatted summary of a user's Sodax money market portfolio.
46
- *
47
- * @param params (optional) - Object including:
48
- * - spokeChainId: The spoke chain id whose data will be fetched. If not provided, data fetching is disabled.
49
- * - userAddress: The user's address (string) whose summary will be fetched. If not provided, data fetching is disabled.
50
- * - queryOptions: (optional) Custom React Query options such as `queryKey`, `enabled`, or cache policy.
16
+ * React hook returning the user's formatted money market portfolio summary (collateral, borrows,
17
+ * health factor, available borrow power, etc.) for the given spoke chain.
51
18
  *
52
- * @returns {UseQueryResult<FormatUserSummaryResponse<FormatReserveUSDResponse>, Error>}
53
- * A result object from React Query including:
54
- * - data: The user's formatted portfolio summary (or undefined if not loaded)
55
- * - isLoading: Boolean loading state
56
- * - isError: Boolean error state
57
- * - error: Error if thrown in fetching
58
- *
59
- * @example
60
- * const { data, isLoading, error } = useUserFormattedSummary({ spokeChainId, userAddress });
19
+ * Internally chains `getReservesHumanized` → `formatReservesUSD` → `getUserReservesHumanized`
20
+ * `formatUserSummary`.
61
21
  */
62
- export function useUserFormattedSummary(
63
- params?: UseUserFormattedSummaryParams,
64
- ): UseQueryResult<FormatUserSummaryResponse<FormatReserveUSDResponse>, Error> {
22
+ export function useUserFormattedSummary({
23
+ params,
24
+ queryOptions,
25
+ }: UseUserFormattedSummaryParams = {}): UseQueryResult<FormatUserSummaryResponse<FormatReserveUSDResponse>, Error> {
65
26
  const { sodax } = useSodaxContext();
66
- const resolved = params ? resolveParams(params) : { spokeChainId: undefined, userAddress: undefined };
67
- const defaultQueryOptions = {
68
- queryKey: ['mm', 'userFormattedSummary', resolved.spokeChainId, resolved.userAddress],
69
- enabled: !!resolved.spokeChainId && !!resolved.userAddress,
70
- refetchInterval: 5000,
71
- };
72
-
73
- const queryOptions = {
74
- ...defaultQueryOptions,
75
- ...params?.queryOptions, // override default query options if provided
76
- };
27
+ const spokeChainKey = params?.spokeChainKey;
28
+ const userAddress = params?.userAddress;
77
29
 
78
30
  return useQuery({
79
- ...queryOptions,
31
+ queryKey: ['mm', 'userFormattedSummary', spokeChainKey, userAddress],
80
32
  queryFn: async () => {
81
- if (!resolved.spokeChainId || !resolved.userAddress) {
82
- throw new Error('spokeChainId or userAddress is not defined');
33
+ if (!spokeChainKey || !userAddress) {
34
+ throw new Error('spokeChainKey and userAddress are required');
83
35
  }
84
36
 
85
- // fetch reserves and hub wallet address
86
- const reserves = await sodax.moneyMarket.data.getReservesHumanized();
87
-
88
- // format reserves
37
+ const [reserves, userReserves] = await Promise.all([
38
+ sodax.moneyMarket.data.getReservesHumanized(),
39
+ sodax.moneyMarket.data.getUserReservesHumanized(spokeChainKey, userAddress),
40
+ ]);
89
41
  const formattedReserves = sodax.moneyMarket.data.formatReservesUSD(
90
42
  sodax.moneyMarket.data.buildReserveDataWithPrice(reserves),
91
43
  );
92
44
 
93
- // fetch user reserves
94
- const userReserves = await sodax.moneyMarket.data.getUserReservesHumanized(
95
- resolved.spokeChainId,
96
- resolved.userAddress,
97
- );
98
-
99
- // format user summary
100
45
  return sodax.moneyMarket.data.formatUserSummary(
101
46
  sodax.moneyMarket.data.buildUserSummaryRequest(reserves, formattedReserves, userReserves),
102
47
  );
103
48
  },
49
+ enabled: !!spokeChainKey && !!userAddress,
50
+ refetchInterval: 5000,
51
+ ...queryOptions,
104
52
  });
105
53
  }
@@ -1,89 +1,39 @@
1
- import type { SpokeChainId } from '@sodax/types';
2
- import type { SpokeProvider, UserReserveData } from '@sodax/sdk';
3
- import { useQuery, type UseQueryOptions, type UseQueryResult } from '@tanstack/react-query';
4
- import { useSodaxContext } from '../shared/useSodaxContext';
5
-
6
- type BaseQueryOptions = {
7
- queryOptions?: UseQueryOptions<readonly [readonly UserReserveData[], number], Error>;
8
- };
9
-
10
- type NewParams = BaseQueryOptions & {
11
- /** Spoke chain id (e.g. '0xa86a.avax') */
12
- spokeChainId: SpokeChainId | undefined;
13
- /** User wallet address on the spoke chain */
14
- userAddress: string | undefined;
15
- };
16
-
17
- /** @deprecated Use `{ spokeChainId, userAddress }` instead */
18
- type LegacyParams = BaseQueryOptions & {
19
- /** @deprecated Use `spokeChainId` instead */
20
- spokeProvider: SpokeProvider | undefined;
21
- /** @deprecated Use `userAddress` instead */
22
- address: string | undefined;
23
- };
24
-
25
- export type UseUserReservesDataParams = NewParams | LegacyParams;
26
-
27
- function isLegacyParams(params: UseUserReservesDataParams): params is LegacyParams {
28
- return 'spokeProvider' in params || 'address' in params;
29
- }
30
-
31
- function resolveParams(params: UseUserReservesDataParams): {
32
- spokeChainId: SpokeChainId | undefined;
33
- userAddress: string | undefined;
34
- } {
35
- if (isLegacyParams(params)) {
36
- return {
37
- spokeChainId: params.spokeProvider?.chainConfig.chain.id as SpokeChainId | undefined,
38
- userAddress: params.address,
39
- };
1
+ import type { UserReserveData } from '@sodax/sdk';
2
+ import type { SpokeChainKey } from '@sodax/sdk';
3
+ import { useQuery, type UseQueryResult } from '@tanstack/react-query';
4
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
5
+ import type { ReadHookParams } from '../shared/types.js';
6
+
7
+ export type UseUserReservesDataParams = ReadHookParams<
8
+ readonly [readonly UserReserveData[], number],
9
+ {
10
+ spokeChainKey: SpokeChainKey | undefined;
11
+ userAddress: string | undefined;
40
12
  }
41
- return { spokeChainId: params.spokeChainId, userAddress: params.userAddress };
42
- }
13
+ >;
43
14
 
44
15
  /**
45
- * Hook for fetching user reserves data from the Sodax money market.
46
- *
47
- * @param params (optional) - Object including:
48
- * - spokeChainId: The spoke chain id whose reserves data will be fetched. If not provided, data fetching is disabled.
49
- * - userAddress: The user's address (string) whose reserves data will be fetched. If not provided, data fetching is disabled.
50
- * - queryOptions: (optional) Custom React Query options such as `queryKey`, `enabled`, or cache policy.
51
- *
52
- * @returns {UseQueryResult<readonly [readonly UserReserveData[], number], Error>} React Query result object containing:
53
- * - data: A tuple with array of UserReserveData and associated number, or undefined if loading
54
- * - isLoading: Boolean loading state
55
- * - isError: Boolean error state
56
- * - error: Error object, if present
57
- *
58
- * @example
59
- * const { data: userReservesData, isLoading, error } = useUserReservesData({
60
- * spokeChainId,
61
- * userAddress,
62
- * });
16
+ * React hook for fetching the raw user reserves data (positions on the hub) for a given spoke
17
+ * chain and user address.
63
18
  */
64
- export function useUserReservesData(
65
- params?: UseUserReservesDataParams,
66
- ): UseQueryResult<readonly [readonly UserReserveData[], number], Error> {
19
+ export function useUserReservesData({
20
+ params,
21
+ queryOptions,
22
+ }: UseUserReservesDataParams = {}): UseQueryResult<readonly [readonly UserReserveData[], number], Error> {
67
23
  const { sodax } = useSodaxContext();
68
- const resolved = params ? resolveParams(params) : { spokeChainId: undefined, userAddress: undefined };
69
- const defaultQueryOptions = {
70
- queryKey: ['mm', 'userReservesData', resolved.spokeChainId, resolved.userAddress],
71
- enabled: !!resolved.spokeChainId && !!resolved.userAddress,
72
- refetchInterval: 5000,
73
- };
74
- const queryOptions = {
75
- ...defaultQueryOptions,
76
- ...params?.queryOptions, // override default query options if provided
77
- };
24
+ const spokeChainKey = params?.spokeChainKey;
25
+ const userAddress = params?.userAddress;
78
26
 
79
27
  return useQuery({
80
- ...queryOptions,
28
+ queryKey: ['mm', 'userReservesData', spokeChainKey, userAddress],
81
29
  queryFn: async () => {
82
- if (!resolved.spokeChainId || !resolved.userAddress) {
83
- throw new Error('spokeChainId or userAddress is not defined');
30
+ if (!spokeChainKey || !userAddress) {
31
+ throw new Error('spokeChainKey and userAddress are required');
84
32
  }
85
-
86
- return await sodax.moneyMarket.data.getUserReservesData(resolved.spokeChainId, resolved.userAddress);
33
+ return sodax.moneyMarket.data.getUserReservesData(spokeChainKey, userAddress);
87
34
  },
35
+ enabled: !!spokeChainKey && !!userAddress,
36
+ refetchInterval: 5000,
37
+ ...queryOptions,
88
38
  });
89
39
  }
@@ -1,65 +1,49 @@
1
- import type { MoneyMarketError, MoneyMarketWithdrawParams, RelayErrorCode, SpokeProvider } from '@sodax/sdk';
2
- import { useMutation, type UseMutationResult } from '@tanstack/react-query';
3
- import { useSodaxContext } from '../shared/useSodaxContext';
1
+ // packages/dapp-kit/src/hooks/mm/useWithdraw.ts
2
+ import type { MoneyMarketWithdrawActionParams, SpokeChainKey, TxHashPair } from '@sodax/sdk';
3
+ import { useQueryClient } from '@tanstack/react-query';
4
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
5
+ import type { MutationHookParams } from '../shared/types.js';
6
+ import { useSafeMutation, type SafeUseMutationResult } from '../shared/useSafeMutation.js';
7
+ import { unwrapResult } from '../shared/unwrapResult.js';
4
8
 
5
- export type UseWithdrawParams = {
6
- params: MoneyMarketWithdrawParams;
7
- spokeProvider: SpokeProvider;
8
- };
9
-
10
- interface WithdrawResponse {
11
- ok: true;
12
- value: [string, string];
13
- }
9
+ /**
10
+ * Mutation variables for {@link useWithdraw}. Generic over `K extends SpokeChainKey` (defaults to
11
+ * the full union). Sophisticated callers can lock K at the hook call site to narrow the
12
+ * `walletProvider` and `params.srcChainKey` types.
13
+ */
14
+ export type UseWithdrawVars<K extends SpokeChainKey = SpokeChainKey> = Omit<
15
+ MoneyMarketWithdrawActionParams<K, false>,
16
+ 'raw'
17
+ >;
14
18
 
15
19
  /**
16
- * Hook for performing withdrawals from the Sodax money market.
17
- *
18
- * This hook exposes a mutation that executes the complete withdrawal logic, including transaction
19
- * creation and handling cross-chain communication. It leverages React Query's mutation API for
20
- * easy asynchronous handling and status tracking within UI components.
21
- *
22
- * @returns {UseMutationResult<WithdrawResponse, MoneyMarketError<'CREATE_WITHDRAW_INTENT_FAILED' | 'WITHDRAW_UNKNOWN_ERROR' | RelayErrorCode>, UseWithdrawParams>}
23
- * Mutation result object, with:
24
- * - mutateAsync: (params: UseWithdrawParams) => Promise<WithdrawResponse>
25
- * Initiates the withdrawal using the provided params.
26
- * - isPending: boolean indicating if a transaction is in progress.
27
- * - error: MoneyMarketError if an error occurred while withdrawing, otherwise undefined.
20
+ * React hook for withdrawing supplied tokens from the Sodax money market protocol.
28
21
  *
29
- * @example
30
- * ```typescript
31
- * const { mutateAsync: withdraw, isPending, error } = useWithdraw();
32
- * await withdraw({ params: withdrawParams, spokeProvider });
33
- * ```
34
- *
35
- * @throws {Error} When:
36
- * - spokeProvider is not provided or invalid.
37
- * - Underlying withdrawal logic fails.
22
+ * Throws on SDK failure so React Query's native error model engages (`isError`, `error`,
23
+ * `onError`, `retry`). Returns the unwrapped `TxHashPair` on success.
38
24
  */
39
- export function useWithdraw(): UseMutationResult<
40
- WithdrawResponse,
41
- MoneyMarketError<'CREATE_WITHDRAW_INTENT_FAILED' | 'WITHDRAW_UNKNOWN_ERROR' | RelayErrorCode>,
42
- UseWithdrawParams
43
- > {
25
+ export function useWithdraw<K extends SpokeChainKey = SpokeChainKey>({
26
+ mutationOptions,
27
+ }: MutationHookParams<TxHashPair, UseWithdrawVars<K>> = {}): SafeUseMutationResult<TxHashPair, Error, UseWithdrawVars<K>> {
44
28
  const { sodax } = useSodaxContext();
29
+ const queryClient = useQueryClient();
45
30
 
46
- return useMutation<
47
- WithdrawResponse,
48
- MoneyMarketError<'CREATE_WITHDRAW_INTENT_FAILED' | 'WITHDRAW_UNKNOWN_ERROR' | RelayErrorCode>,
49
- UseWithdrawParams
50
- >({
51
- mutationFn: async ({ params, spokeProvider }) => {
52
- if (!spokeProvider) {
53
- throw new Error('spokeProvider is not found');
31
+ return useSafeMutation<TxHashPair, Error, UseWithdrawVars<K>>({
32
+ mutationKey: ['mm', 'withdraw'],
33
+ ...mutationOptions,
34
+ mutationFn: async vars => unwrapResult(await sodax.moneyMarket.withdraw({ ...vars, raw: false })),
35
+ onSuccess: async (data, vars, ctx) => {
36
+ const { params } = vars;
37
+ queryClient.invalidateQueries({ queryKey: ['mm', 'userReservesData', params.srcChainKey, params.srcAddress] });
38
+ queryClient.invalidateQueries({
39
+ queryKey: ['mm', 'userFormattedSummary', params.srcChainKey, params.srcAddress],
40
+ });
41
+ queryClient.invalidateQueries({ queryKey: ['mm', 'aTokensBalances'] });
42
+ const balanceChains = new Set([params.srcChainKey, params.dstChainKey ?? params.srcChainKey]);
43
+ for (const chainKey of balanceChains) {
44
+ queryClient.invalidateQueries({ queryKey: ['shared', 'xBalances', chainKey] });
54
45
  }
55
-
56
- const response = await sodax.moneyMarket.withdraw(params, spokeProvider);
57
-
58
- if (!response.ok) {
59
- throw response.error;
60
- }
61
-
62
- return response;
46
+ await mutationOptions?.onSuccess?.(data, vars, ctx);
63
47
  },
64
48
  });
65
49
  }
@@ -0,0 +1,6 @@
1
+ export * from './useFetchAssetsBalances.js';
2
+ export * from './useGetAutoSwapPreferences.js';
3
+ export * from './useIsTokenApproved.js';
4
+ export * from './useApproveToken.js';
5
+ export * from './useSetSwapPreference.js';
6
+ export * from './useFeeClaimSwap.js';