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

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 +190 -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 +21 -11
  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
@@ -0,0 +1,42 @@
1
+ // packages/dapp-kit/src/hooks/partner/useApproveToken.ts
2
+ import type { FeeTokenApproveAction, HubChainKey, TxReturnType } 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';
8
+
9
+ export type UseApproveTokenVars = Omit<FeeTokenApproveAction<HubChainKey, false>, 'raw'>;
10
+
11
+ type ApproveTokenData = TxReturnType<HubChainKey, false>;
12
+
13
+ /**
14
+ * React hook to approve a token to the protocol-intents contract on Sonic with max allowance.
15
+ *
16
+ * Throws on SDK failure so React Query's native error model engages (`isError`, `error`,
17
+ * `onError`, `retry`). Returns the unwrapped tx return value on success.
18
+ */
19
+ export function useApproveToken({
20
+ mutationOptions,
21
+ }: MutationHookParams<ApproveTokenData, UseApproveTokenVars> = {}): SafeUseMutationResult<
22
+ ApproveTokenData,
23
+ Error,
24
+ UseApproveTokenVars
25
+ > {
26
+ const { sodax } = useSodaxContext();
27
+ const queryClient = useQueryClient();
28
+
29
+ return useSafeMutation<ApproveTokenData, Error, UseApproveTokenVars>({
30
+ mutationKey: ['partner', 'approveToken'],
31
+ ...mutationOptions,
32
+ mutationFn: async vars =>
33
+ unwrapResult(await sodax.partners.feeClaim.approveToken<false>({ ...vars, raw: false })),
34
+ onSuccess: async (data, vars, ctx) => {
35
+ const { params } = vars;
36
+ queryClient.invalidateQueries({
37
+ queryKey: ['partner', 'feeClaim', 'isTokenApproved', params.srcChainKey, params.srcAddress, params.token],
38
+ });
39
+ await mutationOptions?.onSuccess?.(data, vars, ctx);
40
+ },
41
+ });
42
+ }
@@ -0,0 +1,38 @@
1
+ // packages/dapp-kit/src/hooks/partner/useFeeClaimSwap.ts
2
+ import type { HubChainKey, IntentAutoSwapResult, PartnerFeeClaimSwapAction } 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';
8
+
9
+ export type UseFeeClaimSwapVars = Omit<PartnerFeeClaimSwapAction<HubChainKey, false>, 'raw'>;
10
+
11
+ /**
12
+ * React hook to create a partner-fee auto-swap intent and wait for the solver execution.
13
+ *
14
+ * Throws on SDK failure so React Query's native error model engages (`isError`, `error`,
15
+ * `onError`, `retry`). Returns the unwrapped `IntentAutoSwapResult` on success.
16
+ */
17
+ export function useFeeClaimSwap({
18
+ mutationOptions,
19
+ }: MutationHookParams<IntentAutoSwapResult, UseFeeClaimSwapVars> = {}): SafeUseMutationResult<
20
+ IntentAutoSwapResult,
21
+ Error,
22
+ UseFeeClaimSwapVars
23
+ > {
24
+ const { sodax } = useSodaxContext();
25
+ const queryClient = useQueryClient();
26
+
27
+ return useSafeMutation<IntentAutoSwapResult, Error, UseFeeClaimSwapVars>({
28
+ mutationKey: ['partner', 'feeClaimSwap'],
29
+ ...mutationOptions,
30
+ mutationFn: async vars => unwrapResult(await sodax.partners.feeClaim.swap({ ...vars, raw: false })),
31
+ onSuccess: async (data, vars, ctx) => {
32
+ queryClient.invalidateQueries({
33
+ queryKey: ['partner', 'feeClaim', 'assetsBalances', vars.params.srcAddress],
34
+ });
35
+ await mutationOptions?.onSuccess?.(data, vars, ctx);
36
+ },
37
+ });
38
+ }
@@ -0,0 +1,37 @@
1
+ import type { PartnerFeeClaimAssetBalance } 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';
5
+
6
+ export type UseFetchAssetsBalancesParams = ReadHookParams<
7
+ Map<string, PartnerFeeClaimAssetBalance>,
8
+ {
9
+ queryAddress: string | undefined;
10
+ }
11
+ >;
12
+
13
+ /**
14
+ * React hook to fetch hub-asset balances on Sonic for a given EVM address. Disabled when
15
+ * `queryAddress` is missing. Throws on `!ok`.
16
+ */
17
+ export function useFetchAssetsBalances({
18
+ params,
19
+ queryOptions,
20
+ }: UseFetchAssetsBalancesParams = {}): UseQueryResult<Map<string, PartnerFeeClaimAssetBalance>, Error> {
21
+ const { sodax } = useSodaxContext();
22
+ const queryAddress = params?.queryAddress;
23
+
24
+ return useQuery<Map<string, PartnerFeeClaimAssetBalance>, Error>({
25
+ queryKey: ['partner', 'feeClaim', 'assetsBalances', queryAddress],
26
+ queryFn: async () => {
27
+ if (!queryAddress) {
28
+ throw new Error('queryAddress is required');
29
+ }
30
+ const result = await sodax.partners.feeClaim.fetchAssetsBalances(queryAddress);
31
+ if (!result.ok) throw result.error;
32
+ return result.value;
33
+ },
34
+ enabled: !!queryAddress,
35
+ ...queryOptions,
36
+ });
37
+ }
@@ -0,0 +1,37 @@
1
+ import type { AutoSwapPreferences } 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';
5
+
6
+ export type UseGetAutoSwapPreferencesParams = ReadHookParams<
7
+ AutoSwapPreferences,
8
+ {
9
+ queryAddress: string | undefined;
10
+ }
11
+ >;
12
+
13
+ /**
14
+ * React hook to fetch the auto-swap preferences (output token, destination chain, destination
15
+ * address) for a given EVM address. Disabled when `queryAddress` is missing. Throws on `!ok`.
16
+ */
17
+ export function useGetAutoSwapPreferences({
18
+ params,
19
+ queryOptions,
20
+ }: UseGetAutoSwapPreferencesParams = {}): UseQueryResult<AutoSwapPreferences, Error> {
21
+ const { sodax } = useSodaxContext();
22
+ const queryAddress = params?.queryAddress;
23
+
24
+ return useQuery<AutoSwapPreferences, Error>({
25
+ queryKey: ['partner', 'feeClaim', 'autoSwapPreferences', queryAddress],
26
+ queryFn: async () => {
27
+ if (!queryAddress) {
28
+ throw new Error('queryAddress is required');
29
+ }
30
+ const result = await sodax.partners.feeClaim.getAutoSwapPreferences(queryAddress);
31
+ if (!result.ok) throw result.error;
32
+ return result.value;
33
+ },
34
+ enabled: !!queryAddress,
35
+ ...queryOptions,
36
+ });
37
+ }
@@ -0,0 +1,39 @@
1
+ import type { FeeTokenApproveParams } 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';
5
+
6
+ export type UseIsTokenApprovedParams = ReadHookParams<
7
+ boolean,
8
+ {
9
+ payload: FeeTokenApproveParams | undefined;
10
+ }
11
+ >;
12
+
13
+ /**
14
+ * React hook to check whether a token is approved to the protocol-intents contract on Sonic for
15
+ * a given owner. Read-only; throws on `!ok`.
16
+ */
17
+ export function useIsTokenApproved({
18
+ params,
19
+ queryOptions,
20
+ }: UseIsTokenApprovedParams = {}): UseQueryResult<boolean, Error> {
21
+ const { sodax } = useSodaxContext();
22
+ const payload = params?.payload;
23
+
24
+ return useQuery<boolean, Error>({
25
+ queryKey: ['partner', 'feeClaim', 'isTokenApproved', payload?.srcChainKey, payload?.srcAddress, payload?.token],
26
+ queryFn: async () => {
27
+ if (!payload) {
28
+ throw new Error('params are required');
29
+ }
30
+ const result = await sodax.partners.feeClaim.isTokenApproved(payload);
31
+ if (!result.ok) throw result.error;
32
+ return result.value;
33
+ },
34
+ enabled: !!payload,
35
+ refetchInterval: 5_000,
36
+ gcTime: 0,
37
+ ...queryOptions,
38
+ });
39
+ }
@@ -0,0 +1,50 @@
1
+ // packages/dapp-kit/src/hooks/partner/useSetSwapPreference.ts
2
+ import type { HubChainKey, SetSwapPreferenceAction, SpokeChainKey, TxReturnType } 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';
8
+
9
+ /**
10
+ * Mutation variables for {@link useSetSwapPreference}. Generic over `K extends SpokeChainKey`
11
+ * for compatibility with the SDK signature; at runtime the SDK enforces hub-only
12
+ * (`isHubChainKeyType(srcChainKey)`).
13
+ */
14
+ export type UseSetSwapPreferenceVars<K extends SpokeChainKey = SpokeChainKey> = Omit<
15
+ SetSwapPreferenceAction<K, false>,
16
+ 'raw'
17
+ >;
18
+
19
+ /**
20
+ * React hook to set the partner's auto-swap preferences (output token + destination chain +
21
+ * destination address) on the protocol-intents contract.
22
+ *
23
+ * Throws on SDK failure so React Query's native error model engages (`isError`, `error`,
24
+ * `onError`, `retry`). Returns the unwrapped tx return value on success.
25
+ */
26
+ export function useSetSwapPreference<K extends SpokeChainKey = SpokeChainKey>({
27
+ mutationOptions,
28
+ }: MutationHookParams<TxReturnType<K, false>, UseSetSwapPreferenceVars<K>> = {}): SafeUseMutationResult<
29
+ TxReturnType<K, false>,
30
+ Error,
31
+ UseSetSwapPreferenceVars<K>
32
+ > {
33
+ const { sodax } = useSodaxContext();
34
+ const queryClient = useQueryClient();
35
+
36
+ return useSafeMutation<TxReturnType<K, false>, Error, UseSetSwapPreferenceVars<K>>({
37
+ mutationKey: ['partner', 'setSwapPreference'],
38
+ ...mutationOptions,
39
+ mutationFn: async vars => unwrapResult(await sodax.partners.feeClaim.setSwapPreference({ ...vars, raw: false })),
40
+ onSuccess: async (data, vars, ctx) => {
41
+ queryClient.invalidateQueries({
42
+ queryKey: ['partner', 'feeClaim', 'autoSwapPreferences', (vars.params as { srcAddress: string }).srcAddress],
43
+ });
44
+ await mutationOptions?.onSuccess?.(data, vars, ctx);
45
+ },
46
+ });
47
+ }
48
+
49
+ // Helper alias for the common Sonic-only call shape.
50
+ export type UseSetSwapPreferenceVarsHub = UseSetSwapPreferenceVars<HubChainKey>;
@@ -1,2 +1 @@
1
- export * from './useHubProvider';
2
- export * from './useSpokeProvider';
1
+ export * from './useHubProvider.js';
@@ -1,5 +1,5 @@
1
1
  import type { EvmHubProvider } from '@sodax/sdk';
2
- import { useSodaxContext } from '../shared/useSodaxContext';
2
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
3
3
 
4
4
  export function useHubProvider(): EvmHubProvider {
5
5
  const { sodax } = useSodaxContext();
@@ -0,0 +1,2 @@
1
+ export * from './useHubAssetBalances.js';
2
+ export * from './useWithdrawHubAsset.js';
@@ -0,0 +1,43 @@
1
+ import type { HubAssetBalance } 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 UseHubAssetBalancesParams = ReadHookParams<
8
+ HubAssetBalance[],
9
+ {
10
+ chainKey: SpokeChainKey | undefined;
11
+ /** The user's address on the spoke chain. The SDK derives the hub wallet abstraction internally. */
12
+ srcAddress: string | undefined;
13
+ }
14
+ >;
15
+
16
+ /**
17
+ * React hook to fetch the hub-side balances of every supported token on the given spoke chain
18
+ * for the user's hub wallet (derived internally from `srcAddress` + `chainKey`). Disabled when
19
+ * either input is missing. Throws on `!ok`.
20
+ */
21
+ export function useHubAssetBalances({
22
+ params,
23
+ queryOptions,
24
+ }: UseHubAssetBalancesParams = {}): UseQueryResult<HubAssetBalance[], Error> {
25
+ const { sodax } = useSodaxContext();
26
+ const chainKey = params?.chainKey;
27
+ const srcAddress = params?.srcAddress;
28
+
29
+ return useQuery<HubAssetBalance[], Error>({
30
+ queryKey: ['recovery', 'hubAssetBalances', chainKey, srcAddress],
31
+ queryFn: async () => {
32
+ if (!chainKey || !srcAddress) {
33
+ throw new Error('chainKey and srcAddress are required');
34
+ }
35
+ const result = await sodax.recovery.fetchHubAssetBalances({ chainKey, srcAddress });
36
+ if (!result.ok) throw result.error;
37
+ return result.value;
38
+ },
39
+ enabled: !!chainKey && !!srcAddress,
40
+ staleTime: 10_000,
41
+ ...queryOptions,
42
+ });
43
+ }
@@ -0,0 +1,48 @@
1
+ // packages/dapp-kit/src/hooks/recovery/useWithdrawHubAsset.ts
2
+ import type { SpokeChainKey, TxReturnType, WithdrawHubAssetAction } 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';
8
+
9
+ /**
10
+ * Mutation variables for {@link useWithdrawHubAsset}. Generic over `K extends SpokeChainKey`
11
+ * (defaults to the full union). Sophisticated callers can lock K at the hook call site to narrow
12
+ * the `walletProvider` and `params.srcChainKey` types.
13
+ */
14
+ export type UseWithdrawHubAssetVars<K extends SpokeChainKey = SpokeChainKey> = Omit<
15
+ WithdrawHubAssetAction<K, false>,
16
+ 'raw'
17
+ >;
18
+
19
+ /**
20
+ * React hook for withdrawing a hub-side asset back to the user's spoke chain wallet.
21
+ *
22
+ * Throws on SDK failure so React Query's native error model engages (`isError`, `error`,
23
+ * `onError`, `retry`). Returns the unwrapped tx return value on success.
24
+ */
25
+ export function useWithdrawHubAsset<K extends SpokeChainKey = SpokeChainKey>({
26
+ mutationOptions,
27
+ }: MutationHookParams<TxReturnType<K, false>, UseWithdrawHubAssetVars<K>> = {}): SafeUseMutationResult<
28
+ TxReturnType<K, false>,
29
+ Error,
30
+ UseWithdrawHubAssetVars<K>
31
+ > {
32
+ const { sodax } = useSodaxContext();
33
+ const queryClient = useQueryClient();
34
+
35
+ return useSafeMutation<TxReturnType<K, false>, Error, UseWithdrawHubAssetVars<K>>({
36
+ mutationKey: ['recovery', 'withdrawHubAsset'],
37
+ ...mutationOptions,
38
+ mutationFn: async vars => unwrapResult(await sodax.recovery.withdrawHubAsset<K, false>({ ...vars, raw: false })),
39
+ onSuccess: async (data, vars, ctx) => {
40
+ const { params } = vars;
41
+ queryClient.invalidateQueries({
42
+ queryKey: ['recovery', 'hubAssetBalances', params.srcChainKey, params.srcAddress],
43
+ });
44
+ queryClient.invalidateQueries({ queryKey: ['shared', 'xBalances', params.srcChainKey] });
45
+ await mutationOptions?.onSuccess?.(data, vars, ctx);
46
+ },
47
+ });
48
+ }
@@ -1,6 +1,10 @@
1
- export * from './useSodaxContext';
2
- export * from './useEstimateGas';
3
- export * from './useDeriveUserWalletAddress';
4
- export * from './useStellarTrustlineCheck';
5
- export * from './useRequestTrustline';
6
- export * from './useGetUserHubWalletAddress';
1
+ export * from './types.js';
2
+ export * from './unwrapResult.js';
3
+ export * from './useSafeMutation.js';
4
+ export * from './useSodaxContext.js';
5
+ export * from './useEstimateGas.js';
6
+ export * from './useDeriveUserWalletAddress.js';
7
+ export * from './useStellarTrustlineCheck.js';
8
+ export * from './useRequestTrustline.js';
9
+ export * from './useGetUserHubWalletAddress.js';
10
+ export * from './useXBalances.js';
@@ -0,0 +1,77 @@
1
+ // packages/dapp-kit/src/hooks/shared/types.ts
2
+ import type { UseMutationOptions, UseQueryOptions } from '@tanstack/react-query';
3
+
4
+ /**
5
+ * Subset of `UseQueryOptions` consumers may override on dapp-kit read hooks.
6
+ *
7
+ * `queryKey`, `queryFn`, and `enabled` are owned by the hook (the latter is derived
8
+ * from required-input presence) and are intentionally stripped here.
9
+ */
10
+ export type ReadQueryOptions<TData, TError = Error> = Omit<
11
+ UseQueryOptions<TData, TError>,
12
+ 'queryKey' | 'queryFn' | 'enabled'
13
+ >;
14
+
15
+ /**
16
+ * Canonical params shape for read-only `useQuery`-backed hooks in dapp-kit.
17
+ *
18
+ * Two top-level keys, always:
19
+ * - `params`: SDK-feature-domain inputs (the "what" being fetched)
20
+ * - `queryOptions`: React Query behavior knobs (the "how" the query behaves)
21
+ *
22
+ * For hooks with no required inputs, leave `TParams` at its default and accept the
23
+ * whole params object as optional at the call site.
24
+ */
25
+ export type ReadHookParams<TData, TParams = Record<string, never>, TError = Error> = {
26
+ params?: TParams;
27
+ queryOptions?: ReadQueryOptions<TData, TError>;
28
+ };
29
+
30
+ /**
31
+ * Subset of `UseMutationOptions` consumers may override on dapp-kit mutation hooks.
32
+ *
33
+ * `mutationFn` is owned by the hook (it's the SDK integration point) and is
34
+ * intentionally stripped here. Everything else — `mutationKey`, `retry`, `gcTime`,
35
+ * `networkMode`, `onMutate`, `onSuccess`, `onError`, `onSettled`, `meta`, etc. —
36
+ * is consumer-overridable.
37
+ *
38
+ * Conventions enforced by every dapp-kit mutation hook:
39
+ *
40
+ * 1. **`mutationFn` throws on SDK failure.** The SDK returns `Result<T>`; the hook
41
+ * unwraps `result.value` on `ok` and throws `result.error` on `!ok`. So `TData`
42
+ * here is the unwrapped success type, not `Result<T>`. React Query's native
43
+ * error model — `isError`, `error`, `onError`, `retry`, `throwOnError`, devtools —
44
+ * works exactly as documented.
45
+ *
46
+ * 2. **`onSuccess` is composed.** Hook-owned invalidations always run first; then
47
+ * the hook awaits `mutationOptions?.onSuccess?.(data, vars, ctx)`. Per-call
48
+ * `mutate(vars, { onSuccess })` runs after both, per TanStack Query's native
49
+ * ordering. Because invalidations now live inside `onSuccess` (not `onSettled`),
50
+ * they only fire on confirmed success — failed mutations never trigger them.
51
+ *
52
+ * 3. **A default `mutationKey` is set per hook** (e.g. `['mm', 'supply']`,
53
+ * `['swap']`) so consumers can use `useIsMutating(['mm'])` and
54
+ * `useMutationState` without guessing the key shape. The default is set
55
+ * *before* `...mutationOptions` is spread, so consumers can override it.
56
+ */
57
+ export type MutationHookOptions<TData, TVars, TError = Error, TContext = unknown> = Omit<
58
+ UseMutationOptions<TData, TError, TVars, TContext>,
59
+ 'mutationFn'
60
+ >;
61
+
62
+ /**
63
+ * Canonical params shape for `useMutation`-backed hooks in dapp-kit.
64
+ *
65
+ * One top-level key:
66
+ * - `mutationOptions`: React Query behavior knobs (the "how" the mutation behaves)
67
+ *
68
+ * Domain inputs (params, walletProvider, etc.) are NOT here — they belong in
69
+ * `TVars` and flow through `mutate(vars)` so the call site can vary them per
70
+ * invocation without re-rendering the hook.
71
+ *
72
+ * Always accept the whole params object as optional at the call site:
73
+ * `useFoo({ mutationOptions } = {})`.
74
+ */
75
+ export type MutationHookParams<TData, TVars, TError = Error, TContext = unknown> = {
76
+ mutationOptions?: MutationHookOptions<TData, TVars, TError, TContext>;
77
+ };
@@ -0,0 +1,19 @@
1
+ import type { Result } from '@sodax/sdk';
2
+
3
+ /**
4
+ * Translates the SDK's `Result<T>` contract into the React Query contract: returns `value` on
5
+ * success, throws `error` on failure. Non-`Error` throwables are wrapped so consumers always get
6
+ * an `Error` in `mutation.error` / catch blocks.
7
+ *
8
+ * Used by every dapp-kit mutation hook so the React Query error model (`isError`, `error`,
9
+ * `onError`, `retry`, `throwOnError`, devtools) engages uniformly.
10
+ */
11
+ export function unwrapResult<T>(result: Result<T>): T {
12
+ if (!result.ok) {
13
+ if (result.error instanceof Error) throw result.error;
14
+ const e = result.error as { message?: string; detail?: { code?: string; message?: string } };
15
+ const msg = e?.detail?.code ?? e?.detail?.message ?? e?.message ?? 'SDK call failed';
16
+ throw new Error(msg, { cause: result.error });
17
+ }
18
+ return result.value;
19
+ }
@@ -1,53 +1,35 @@
1
- import { deriveUserWalletAddress, type SpokeProvider, type SpokeChainId } from '@sodax/sdk';
1
+ import type { SpokeChainKey } from '@sodax/sdk';
2
2
  import { useQuery, type UseQueryResult } from '@tanstack/react-query';
3
- import { useSodaxContext } from './useSodaxContext';
3
+ import { useSodaxContext } from './useSodaxContext.js';
4
4
  import type { Address } from 'viem';
5
+ import type { ReadHookParams } from './types.js';
5
6
 
6
- /**
7
- * Hook for deriving user wallet address for hub abstraction.
8
- *
9
- * This hook derives the user's abstracted wallet address for the hub chain based on the spoke chain ID and address.
10
- * If the spoke chain is the same as the hub chain, it returns the encoded spoke address.
11
- * Otherwise, it derives and returns the abstracted wallet address for cross-chain operations.
12
- *
13
- * The query is automatically enabled when both `spokeChainId` and `spokeAddress` are provided.
14
- * This is a deterministic operation, so the result is cached and not refetched automatically.
15
- *
16
- * @param spokeChainId - Optional spoke chain ID. If not provided, the query will be disabled.
17
- * @param spokeAddress - Optional user wallet address on the spoke chain. If not provided, the query will be disabled.
18
- * @returns A React Query result object containing:
19
- * - data: The derived user wallet address (Address) when available
20
- * - isLoading: Loading state indicator
21
- * - error: Any error that occurred during derivation (Error)
22
- *
23
- * @example
24
- * ```typescript
25
- * const { data: derivedAddress, isLoading, error } = useDeriveUserWalletAddress(spokeChainId, userAddress);
26
- *
27
- * if (isLoading) return <div>Deriving address...</div>;
28
- * if (error) return <div>Error: {error.message}</div>;
29
- * if (derivedAddress) return <div>Derived Address: {derivedAddress}</div>;
30
- * ```
31
- */
32
- export function useDeriveUserWalletAddress(
33
- spokeChainId?: SpokeChainId | SpokeProvider | undefined,
34
- spokeAddress?: string | undefined,
35
- ): UseQueryResult<Address, Error> {
7
+ export type UseDeriveUserWalletAddressParams = ReadHookParams<
8
+ Address,
9
+ {
10
+ spokeChainId?: SpokeChainKey;
11
+ spokeAddress?: string;
12
+ }
13
+ >;
14
+
15
+ export function useDeriveUserWalletAddress({
16
+ params,
17
+ queryOptions,
18
+ }: UseDeriveUserWalletAddressParams = {}): UseQueryResult<Address, Error> {
36
19
  const { sodax } = useSodaxContext();
20
+ const spokeChainId = params?.spokeChainId;
21
+ const spokeAddress = params?.spokeAddress;
37
22
 
38
- return useQuery({
39
- queryKey: ['deriveUserWalletAddress', spokeChainId, spokeAddress],
23
+ return useQuery<Address, Error>({
24
+ queryKey: ['shared', 'deriveUserWalletAddress', spokeChainId, spokeAddress],
40
25
  queryFn: async (): Promise<Address> => {
41
26
  if (!spokeChainId || !spokeAddress) {
42
27
  throw new Error('Spoke chain id and address are required');
43
28
  }
44
-
45
- // Determine if spokeChainId is a SpokeProvider object or SpokeChainId value
46
- spokeChainId = typeof spokeChainId === 'object' ? spokeChainId.chainConfig.chain.id : spokeChainId;
47
-
48
- return await deriveUserWalletAddress(sodax.hubProvider, spokeChainId, spokeAddress);
29
+ return await sodax.hubProvider.getUserHubWalletAddress(spokeAddress, spokeChainId);
49
30
  },
50
31
  enabled: !!spokeChainId && !!spokeAddress,
51
- refetchInterval: false, // This is a deterministic operation, no need to refetch
32
+ refetchInterval: false,
33
+ ...queryOptions,
52
34
  });
53
35
  }
@@ -1,18 +1,21 @@
1
- import { type GetEstimateGasReturnType, type SpokeProvider, SpokeService, type TxReturnType } from '@sodax/sdk';
2
- import { useMutation, type UseMutationResult } from '@tanstack/react-query';
1
+ // packages/dapp-kit/src/hooks/shared/useEstimateGas.ts
2
+ import type { EstimateGasParams, GetEstimateGasReturnType, SpokeChainKey } from '@sodax/sdk';
3
+ import { useSodaxContext } from './useSodaxContext.js';
4
+ import type { MutationHookParams } from './types.js';
5
+ import { useSafeMutation, type SafeUseMutationResult } from './useSafeMutation.js';
6
+ import { unwrapResult } from './unwrapResult.js';
3
7
 
4
- export function useEstimateGas<T extends SpokeProvider = SpokeProvider>(
5
- spokeProvider: T | undefined,
6
- ): UseMutationResult<GetEstimateGasReturnType<T>, Error, TxReturnType<T, true>> {
7
- return useMutation<GetEstimateGasReturnType<T>, Error, TxReturnType<T, true>>({
8
- mutationFn: async (rawTx: TxReturnType<T, true>) => {
9
- if (!spokeProvider) {
10
- throw new Error('spokeProvider is not found');
11
- }
12
-
13
- const response = await SpokeService.estimateGas(rawTx, spokeProvider);
14
-
15
- return response;
16
- },
8
+ export function useEstimateGas<C extends SpokeChainKey>({
9
+ mutationOptions,
10
+ }: MutationHookParams<GetEstimateGasReturnType<C>, EstimateGasParams<C>> = {}): SafeUseMutationResult<
11
+ GetEstimateGasReturnType<C>,
12
+ Error,
13
+ EstimateGasParams<C>
14
+ > {
15
+ const { sodax } = useSodaxContext();
16
+ return useSafeMutation<GetEstimateGasReturnType<C>, Error, EstimateGasParams<C>>({
17
+ mutationKey: ['shared', 'estimateGas'],
18
+ ...mutationOptions,
19
+ mutationFn: async params => unwrapResult(await sodax.spoke.estimateGas<C>(params)),
17
20
  });
18
21
  }