@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,79 +1,59 @@
1
- import { useQuery, type UseQueryOptions, type UseQueryResult } from '@tanstack/react-query';
2
- import type { SubmitSwapTxStatusResponse } from '@sodax/types';
3
- import type { RequestOverrideConfig } from '@sodax/sdk';
4
- import { useSodaxContext } from '../shared/useSodaxContext';
1
+ import { useQuery, type UseQueryResult } from '@tanstack/react-query';
2
+ import type { RequestOverrideConfig, SubmitSwapTxStatusResponse } from '@sodax/sdk';
3
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
4
+ import { unwrapResult } from './unwrapResult.js';
5
+ import type { ReadHookParams } from '../shared/types.js';
5
6
 
6
- export type UseBackendSubmitSwapTxStatusParams = {
7
- params: {
7
+ export type UseBackendSubmitSwapTxStatusParams = ReadHookParams<
8
+ SubmitSwapTxStatusResponse | undefined,
9
+ {
8
10
  txHash: string | undefined;
9
- srcChainId?: string;
10
- };
11
- apiConfig?: RequestOverrideConfig;
12
- queryOptions?: UseQueryOptions<SubmitSwapTxStatusResponse | undefined, Error>;
13
- };
11
+ srcChainKey?: string;
12
+ apiConfig?: RequestOverrideConfig;
13
+ }
14
+ >;
14
15
 
15
16
  /**
16
17
  * React hook for polling the processing status of a submitted swap transaction.
17
18
  *
18
- * @param {UseBackendSubmitSwapTxStatusParams | undefined} params - Parameters for the query:
19
- * - `params.txHash`: The transaction hash of the submitted swap; query is disabled if undefined or empty.
20
- * - `params.srcChainId`: Optional source chain ID to narrow the status lookup.
21
- * - `queryOptions`: Optional React Query options to override default behavior (e.g., refetchInterval, retry).
22
- *
23
- * @returns {UseQueryResult<SubmitSwapTxStatusResponse | undefined, Error>} React Query result object:
24
- * - `data`: The status response or undefined if unavailable.
25
- * - `isLoading`: Loading state.
26
- * - `error`: Error instance if the query failed.
27
- * - `refetch`: Function to re-trigger the query.
28
- *
29
19
  * @example
30
- * const { data: status, isLoading, error } = useBackendSubmitSwapTxStatus({
31
- * params: { txHash: '0x123...', srcChainId: '1' },
20
+ * const { data: status } = useBackendSubmitSwapTxStatus({
21
+ * params: { txHash: '0x123...', srcChainKey: 'sonic' },
32
22
  * });
33
23
  *
34
- * if (status?.data.status === 'executed') {
35
- * console.log('Swap completed!', status.data.result);
36
- * }
37
- *
38
24
  * @remarks
39
- * - Query is disabled if `params` is undefined or `txHash` is undefined/empty.
40
- * - Default refetch interval is 1 second for real-time status polling.
41
- * - Uses React Query for state management, caching, and retries.
25
+ * - Default refetch interval is 1 second; stops on 'executed' or 'failed' status.
42
26
  */
43
- export const useBackendSubmitSwapTxStatus = (
44
- params: UseBackendSubmitSwapTxStatusParams | undefined,
45
- ): UseQueryResult<SubmitSwapTxStatusResponse | undefined, Error> => {
27
+ export const useBackendSubmitSwapTxStatus = ({
28
+ params,
29
+ queryOptions,
30
+ }: UseBackendSubmitSwapTxStatusParams = {}): UseQueryResult<SubmitSwapTxStatusResponse | undefined, Error> => {
46
31
  const { sodax } = useSodaxContext();
32
+ const txHash = params?.txHash;
33
+ const srcChainKey = params?.srcChainKey;
34
+ const apiConfig = params?.apiConfig;
47
35
 
48
- const defaultQueryOptions = {
49
- queryKey: ['api', 'swaps', 'submit-tx', 'status', params?.params?.txHash, params?.params?.srcChainId],
50
- enabled: !!params?.params?.txHash && params.params.txHash.length > 0,
36
+ return useQuery({
37
+ queryKey: ['backend', 'submitSwapTx', 'status', txHash, srcChainKey],
38
+ queryFn: async (): Promise<SubmitSwapTxStatusResponse | undefined> => {
39
+ if (!txHash) return undefined;
40
+ return unwrapResult(
41
+ await sodax.backendApi.getSubmitSwapTxStatus(
42
+ {
43
+ txHash,
44
+ srcChainKey,
45
+ },
46
+ apiConfig,
47
+ ),
48
+ );
49
+ },
50
+ enabled: !!txHash && txHash.length > 0,
51
51
  retry: 3,
52
- refetchInterval: (query: { state: { data: SubmitSwapTxStatusResponse | undefined } }) => {
52
+ refetchInterval: query => {
53
53
  const status = query.state.data?.data?.status;
54
54
  if (status === 'executed' || status === 'failed') return false;
55
55
  return 1000;
56
56
  },
57
- };
58
-
59
- const queryOptions = {
60
- ...defaultQueryOptions,
61
- ...params?.queryOptions,
62
- };
63
-
64
- return useQuery({
65
57
  ...queryOptions,
66
- queryFn: async (): Promise<SubmitSwapTxStatusResponse | undefined> => {
67
- if (!params?.params?.txHash) {
68
- return undefined;
69
- }
70
- return sodax.backendApi.getSubmitSwapTxStatus(
71
- {
72
- txHash: params.params.txHash,
73
- srcChainId: params.params.srcChainId,
74
- },
75
- params.apiConfig,
76
- );
77
- },
78
58
  });
79
59
  };
@@ -1,81 +1,43 @@
1
1
  import type { UserIntentsResponse, Address } from '@sodax/sdk';
2
- // packages/dapp-kit/src/hooks/backend/useBackendUserIntents.ts
3
- import { useQuery, type UseQueryOptions, type UseQueryResult } from '@tanstack/react-query';
4
- import { useSodaxContext } from '../shared/useSodaxContext';
5
- import type { BackendPaginationParams } from './types';
2
+ import { useQuery, type UseQueryResult } from '@tanstack/react-query';
3
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
4
+ import { unwrapResult } from './unwrapResult.js';
5
+ import type { ReadHookParams } from '../shared/types.js';
6
6
 
7
- export type GetUserIntentsParams = {
8
- userAddress: Address;
9
- startDate?: number;
10
- endDate?: number;
11
- };
12
-
13
- export type UseBackendUserIntentsParams = {
14
- params?: GetUserIntentsParams;
15
- queryOptions?: UseQueryOptions<UserIntentsResponse | undefined, Error>;
16
- pagination?: BackendPaginationParams;
17
- };
7
+ export type UseBackendUserIntentsParams = ReadHookParams<
8
+ UserIntentsResponse | undefined,
9
+ {
10
+ userAddress: Address | undefined;
11
+ startDate?: number;
12
+ endDate?: number;
13
+ }
14
+ >;
18
15
 
19
16
  /**
20
- * React hook for fetching user-created intents from the backend API for a given user address,
21
- * with optional support for a date filtering range.
22
- *
23
- * @param {UseBackendUserIntentsParams} args - Query configuration.
24
- * @param {GetUserIntentsParams | undefined} args.params - User intent filter parameters.
25
- * @param {Address} args.params.userAddress - The wallet address of the user (required).
26
- * @param {number} [args.params.startDate] - Include intents created after this timestamp (ms).
27
- * @param {number} [args.params.endDate] - Include intents created before this timestamp (ms).
28
- * @param {UseQueryOptions<UserIntentsResponse | undefined, Error>} [args.queryOptions] - Optional React Query options.
29
- * @param {BackendPaginationParams} [args.pagination] - (currently ignored) Pagination options.
30
- *
31
- * @returns {UseQueryResult<UserIntentsResponse | undefined, Error>} React Query result:
32
- * - `data`: The user intent response, or undefined if unavailable.
33
- * - `isLoading`: `true` if loading.
34
- * - `error`: An Error instance if any occurred.
35
- * - `refetch`: Function to refetch data.
36
- *
37
- * @example
38
- * const { data: userIntents, isLoading, error } = useBackendUserIntents({
39
- * params: { userAddress: "0x123..." }
40
- * });
17
+ * React hook for fetching user-created intents from the backend API for a given user address.
41
18
  *
42
19
  * @example
43
- * const { data } = useBackendUserIntents({
44
- * params: {
45
- * userAddress: "0xabc...",
46
- * startDate: Date.now() - 1_000_000,
47
- * endDate: Date.now(),
48
- * },
20
+ * const { data: userIntents } = useBackendUserIntents({
21
+ * params: { userAddress: '0x123...' },
49
22
  * });
50
- *
51
- * @remarks
52
- * The query is disabled if `params` or `params.userAddress` is missing or empty. Uses React Query for
53
- * cache/state management and auto-retries failed requests three times by default.
54
23
  */
55
24
  export const useBackendUserIntents = ({
56
25
  params,
57
26
  queryOptions,
58
- }: UseBackendUserIntentsParams): UseQueryResult<UserIntentsResponse | undefined, Error> => {
27
+ }: UseBackendUserIntentsParams = {}): UseQueryResult<UserIntentsResponse | undefined, Error> => {
59
28
  const { sodax } = useSodaxContext();
60
- const defaultQueryOptions = {
61
- queryKey: ['api', 'intent', 'user', params],
62
- enabled: !!params && !!params.userAddress && params.userAddress.length > 0,
63
- retry: 3,
64
- };
65
-
66
- queryOptions = {
67
- ...defaultQueryOptions,
68
- ...queryOptions, // override default query options if provided
69
- };
29
+ const userAddress = params?.userAddress;
30
+ const startDate = params?.startDate;
31
+ const endDate = params?.endDate;
70
32
 
71
33
  return useQuery({
72
- ...queryOptions,
34
+ queryKey: ['backend', 'intent', 'user', userAddress, startDate, endDate],
73
35
  queryFn: async (): Promise<UserIntentsResponse | undefined> => {
74
- if (!params?.userAddress) {
75
- return undefined;
76
- }
77
-
78
- return sodax.backendApi.getUserIntents(params);
36
+ if (!userAddress) return undefined;
37
+ return unwrapResult(await sodax.backendApi.getUserIntents({ userAddress, startDate, endDate }));
79
38
  },
39
+ enabled: !!userAddress && userAddress.length > 0,
40
+ retry: 3,
41
+ ...queryOptions,
80
42
  });
81
43
  };
@@ -1,8 +1,9 @@
1
- export * from './useRadfiAuth';
2
- export * from './useRadfiSession';
3
- export * from './useFundTradingWallet';
4
- export * from './useBitcoinBalance';
5
- export * from './useTradingWalletBalance';
6
- export * from './useExpiredUtxos';
7
- export * from './useRenewUtxos';
8
- export * from './useRadfiWithdraw';
1
+ export * from './useRadfiAuth.js';
2
+ export * from './useRadfiSession.js';
3
+ export * from './useFundTradingWallet.js';
4
+ export * from './useBitcoinBalance.js';
5
+ export * from './useTradingWallet.js';
6
+ export * from './useTradingWalletBalance.js';
7
+ export * from './useExpiredUtxos.js';
8
+ export * from './useRenewUtxos.js';
9
+ export * from './useRadfiWithdraw.js';
@@ -1,4 +1,15 @@
1
1
  import { useQuery, type UseQueryResult } from '@tanstack/react-query';
2
+ import type { ReadHookParams } from '../shared/types.js';
3
+
4
+ export type UseBitcoinBalanceParams = ReadHookParams<
5
+ bigint,
6
+ {
7
+ address: string | undefined;
8
+ rpcUrl?: string;
9
+ }
10
+ >;
11
+
12
+ const DEFAULT_RPC_URL = 'https://mempool.space/api';
2
13
 
3
14
  /**
4
15
  * Hook to fetch BTC balance for any Bitcoin address.
@@ -7,12 +18,15 @@ import { useQuery, type UseQueryResult } from '@tanstack/react-query';
7
18
  * The UTXO set already excludes spent outputs (even from unconfirmed txs),
8
19
  * so the total is always the correct spendable balance.
9
20
  */
10
- export function useBitcoinBalance(
11
- address: string | undefined,
12
- rpcUrl = 'https://mempool.space/api',
13
- ): UseQueryResult<bigint, Error> {
21
+ export function useBitcoinBalance({
22
+ params,
23
+ queryOptions,
24
+ }: UseBitcoinBalanceParams = {}): UseQueryResult<bigint, Error> {
25
+ const address = params?.address;
26
+ const rpcUrl = params?.rpcUrl ?? DEFAULT_RPC_URL;
27
+
14
28
  return useQuery<bigint, Error>({
15
- queryKey: ['btc-balance', address],
29
+ queryKey: ['bitcoin', 'balance', address],
16
30
  queryFn: async () => {
17
31
  if (!address) return 0n;
18
32
 
@@ -23,5 +37,6 @@ export function useBitcoinBalance(
23
37
  return BigInt(utxos.reduce((sum, utxo) => sum + utxo.value, 0));
24
38
  },
25
39
  enabled: !!address,
40
+ ...queryOptions,
26
41
  });
27
42
  }
@@ -1,25 +1,35 @@
1
1
  import { useQuery, type UseQueryResult } from '@tanstack/react-query';
2
- import type { BitcoinSpokeProvider, RadfiUtxo } from '@sodax/sdk';
2
+ import type { RadfiUtxo, IBitcoinWalletProvider } from '@sodax/sdk';
3
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
4
+ import type { ReadHookParams } from '../shared/types.js';
5
+
6
+ export type UseExpiredUtxosParams = ReadHookParams<
7
+ RadfiUtxo[],
8
+ {
9
+ walletProvider: IBitcoinWalletProvider | undefined;
10
+ tradingAddress: string | undefined;
11
+ }
12
+ >;
13
+
14
+ export function useExpiredUtxos({
15
+ params,
16
+ queryOptions,
17
+ }: UseExpiredUtxosParams = {}): UseQueryResult<RadfiUtxo[], Error> {
18
+ const { sodax } = useSodaxContext();
19
+ const walletProvider = params?.walletProvider;
20
+ const tradingAddress = params?.tradingAddress;
3
21
 
4
- /**
5
- * Hook to fetch expired UTXOs for a trading wallet address.
6
- * UTXOs that are expired or within 2 weeks of expiry are considered invalid for trading
7
- * and need to be renewed via the Radfi renew-utxo flow.
8
- */
9
- export function useExpiredUtxos(
10
- spokeProvider: BitcoinSpokeProvider | undefined,
11
- tradingAddress: string | undefined,
12
- ): UseQueryResult<RadfiUtxo[], Error> {
13
22
  return useQuery<RadfiUtxo[], Error>({
14
- queryKey: ['expired-utxos', tradingAddress],
23
+ queryKey: ['bitcoin', 'expiredUtxos', tradingAddress],
15
24
  queryFn: async () => {
16
- if (!spokeProvider || !tradingAddress) {
17
- throw new Error('spokeProvider and tradingAddress are required');
25
+ if (!walletProvider || !tradingAddress) {
26
+ throw new Error('walletProvider and tradingAddress are required');
18
27
  }
19
- const result = await spokeProvider.radfi.getExpiredUtxos(tradingAddress);
28
+ const result = await sodax.spoke.bitcoin.radfi.getExpiredUtxos(tradingAddress);
20
29
  return result.data;
21
30
  },
22
- enabled: !!spokeProvider && !!tradingAddress,
23
- refetchInterval: 60_000, // refetch every minute
31
+ enabled: !!walletProvider && !!tradingAddress,
32
+ refetchInterval: 60_000,
33
+ ...queryOptions,
24
34
  });
25
35
  }
@@ -1,39 +1,42 @@
1
- import { BitcoinSpokeService, type BitcoinSpokeProvider } from '@sodax/sdk';
2
- import { useMutation, useQueryClient, type UseMutationResult } from '@tanstack/react-query';
1
+ // packages/dapp-kit/src/hooks/bitcoin/useFundTradingWallet.ts
2
+ import { useQueryClient } from '@tanstack/react-query';
3
+ import { ChainKeys, type IBitcoinWalletProvider } from '@sodax/sdk';
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
+
8
+ export type UseFundTradingWalletVars = {
9
+ amount: bigint;
10
+ walletProvider: IBitcoinWalletProvider;
11
+ };
3
12
 
4
13
  /**
5
- * Hook to fund the Radfi trading wallet by sending BTC from the user's personal wallet.
6
- *
7
- * @param {BitcoinSpokeProvider | undefined} spokeProvider - The Bitcoin spoke provider with signing capability
8
- * @returns {UseMutationResult} Mutation result — input is amount in satoshis, output is transaction ID
9
- *
10
- * @example
11
- * ```tsx
12
- * const { mutateAsync: fundWallet, isPending } = useFundTradingWallet(spokeProvider);
13
- *
14
- * const handleFund = async () => {
15
- * const txId = await fundWallet(100_000n); // fund 100,000 satoshis
16
- * console.log('Funded:', txId);
17
- * };
18
- * ```
14
+ * React hook for funding the user's Radfi trading wallet from their personal Bitcoin wallet.
15
+ * Pure mutation: pass `{ amount, walletProvider }` to `mutate({...})`. Returns the broadcast tx
16
+ * id on success.
19
17
  */
20
- export function useFundTradingWallet(
21
- spokeProvider: BitcoinSpokeProvider | undefined,
22
- ): UseMutationResult<string, Error, bigint> {
18
+ export function useFundTradingWallet({
19
+ mutationOptions,
20
+ }: MutationHookParams<string, UseFundTradingWalletVars> = {}): SafeUseMutationResult<
21
+ string,
22
+ Error,
23
+ UseFundTradingWalletVars
24
+ > {
25
+ const { sodax } = useSodaxContext();
23
26
  const queryClient = useQueryClient();
24
27
 
25
- return useMutation<string, Error, bigint>({
26
- mutationFn: async (amount: bigint) => {
27
- if (!spokeProvider) {
28
- throw new Error('Bitcoin spoke provider not found');
29
- }
30
-
31
- return BitcoinSpokeService.fundTradingWallet(amount, spokeProvider);
28
+ return useSafeMutation<string, Error, UseFundTradingWalletVars>({
29
+ mutationKey: ['bitcoin', 'fundTradingWallet'],
30
+ ...mutationOptions,
31
+ mutationFn: async ({ amount, walletProvider }) => {
32
+ const walletAddress = await walletProvider.getWalletAddress();
33
+ return sodax.spoke.bitcoin.fundTradingWallet(amount, walletAddress, walletProvider);
32
34
  },
33
- onSuccess: () => {
34
- // Invalidate balance queries to reflect the fund transfer
35
- queryClient.invalidateQueries({ queryKey: ['btc-balance'] });
36
- queryClient.invalidateQueries({ queryKey: ['xBalances'] });
35
+ onSuccess: async (data, vars, ctx) => {
36
+ queryClient.invalidateQueries({ queryKey: ['bitcoin', 'balance'] });
37
+ queryClient.invalidateQueries({ queryKey: ['bitcoin', 'tradingWalletBalance'] });
38
+ queryClient.invalidateQueries({ queryKey: ['shared', 'xBalances', ChainKeys.BITCOIN_MAINNET] });
39
+ await mutationOptions?.onSuccess?.(data, vars, ctx);
37
40
  },
38
41
  });
39
42
  }
@@ -1,5 +1,8 @@
1
- import type { BitcoinSpokeProvider } from '@sodax/sdk';
2
- import { useMutation, type UseMutationResult } from '@tanstack/react-query';
1
+ // packages/dapp-kit/src/hooks/bitcoin/useRadfiAuth.ts
2
+ import { RadfiApiError, type IBitcoinWalletProvider } from '@sodax/sdk';
3
+ import { useSodaxContext } from '../shared/useSodaxContext.js';
4
+ import type { MutationHookParams } from '../shared/types.js';
5
+ import { useSafeMutation, type SafeUseMutationResult } from '../shared/useSafeMutation.js';
3
6
 
4
7
  export type RadfiSession = {
5
8
  accessToken: string;
@@ -8,17 +11,20 @@ export type RadfiSession = {
8
11
  publicKey: string;
9
12
  };
10
13
 
14
+ export type UseRadfiAuthVars = {
15
+ walletProvider: IBitcoinWalletProvider;
16
+ };
17
+
11
18
  type RadfiAuthResult = {
12
19
  accessToken: string;
13
20
  refreshToken: string;
14
21
  tradingAddress: string;
15
22
  };
16
23
 
17
- const SESSION_KEY = (address: string) => `radfi_session_${address}`;
24
+ const SESSION_KEY = (address: string): string => `radfi_session_${address}`;
18
25
 
19
26
  export function saveRadfiSession(address: string, session: RadfiSession): void {
20
27
  try {
21
- // Radfi tokens are only used for API rate-limiting / anti-spam, not for accessing user assets.
22
28
  localStorage.setItem(SESSION_KEY(address), JSON.stringify(session));
23
29
  } catch {}
24
30
  }
@@ -39,62 +45,59 @@ export function clearRadfiSession(address: string): void {
39
45
  }
40
46
 
41
47
  /**
42
- * Hook to authenticate with Radfi using BIP322 message signing.
43
- * Saves session (accessToken, refreshToken, tradingAddress, publicKey) to localStorage.
48
+ * React hook for authenticating with Radfi via BIP322-signed message. Pure mutation: pass
49
+ * `{ walletProvider }` to `mutate({...})`. The hook itself takes no arguments other than the
50
+ * structural `mutationOptions` slot.
44
51
  */
45
- export function useRadfiAuth(
46
- spokeProvider: BitcoinSpokeProvider | undefined,
47
- ): UseMutationResult<RadfiAuthResult, Error, void> {
48
- return useMutation<RadfiAuthResult, Error, void>({
49
- mutationFn: async () => {
50
- if (!spokeProvider) {
51
- throw new Error('Bitcoin spoke provider not found');
52
- }
53
-
54
- const walletAddress = await spokeProvider.walletProvider.getWalletAddress();
52
+ export function useRadfiAuth({
53
+ mutationOptions,
54
+ }: MutationHookParams<RadfiAuthResult, UseRadfiAuthVars> = {}): SafeUseMutationResult<
55
+ RadfiAuthResult,
56
+ Error,
57
+ UseRadfiAuthVars
58
+ > {
59
+ const { sodax } = useSodaxContext();
60
+ return useSafeMutation<RadfiAuthResult, Error, UseRadfiAuthVars>({
61
+ mutationKey: ['bitcoin', 'radfiAuth'],
62
+ ...mutationOptions,
63
+ mutationFn: async ({ walletProvider }) => {
64
+ const radfi = sodax.spoke.bitcoin.radfi;
65
+ const walletAddress = await walletProvider.getWalletAddress();
55
66
  const existingSession = loadRadfiSession(walletAddress);
56
67
  const cachedPublicKey = existingSession?.publicKey;
57
68
 
58
69
  try {
59
- const { accessToken, refreshToken, tradingAddress, publicKey } = await spokeProvider.authenticateWithWallet(cachedPublicKey);
60
-
61
- const session: RadfiSession = {
62
- accessToken,
63
- refreshToken,
64
- tradingAddress,
65
- publicKey,
66
- };
67
-
68
- saveRadfiSession(walletAddress, session);
69
-
70
+ const { accessToken, refreshToken, tradingAddress, publicKey } = await radfi.authenticateWithWallet(
71
+ walletProvider,
72
+ cachedPublicKey,
73
+ );
74
+ saveRadfiSession(walletAddress, { accessToken, refreshToken, tradingAddress, publicKey });
70
75
  return { accessToken, refreshToken, tradingAddress };
71
76
  } catch (err: unknown) {
72
- // Error 4008: wallet already registered authenticate is register+login combined.
73
- // Try to refresh with existing session if available.
74
- const isAlreadyRegistered =
75
- err instanceof Error &&
76
- (err.message.includes('duplicatedPubKey') || err.message.includes('4008'));
77
+ const isAlreadyRegistered = err instanceof RadfiApiError && err.code === '4008';
77
78
 
78
79
  if (isAlreadyRegistered && existingSession?.refreshToken) {
79
80
  try {
80
- const refreshed = await spokeProvider.radfi.refreshAccessToken(existingSession.refreshToken);
81
- const session: RadfiSession = {
81
+ const refreshed = await radfi.refreshAccessToken(existingSession.refreshToken);
82
+ radfi.setRadfiAccessToken(refreshed.accessToken, refreshed.refreshToken);
83
+ saveRadfiSession(walletAddress, {
82
84
  ...existingSession,
83
85
  accessToken: refreshed.accessToken,
84
86
  refreshToken: refreshed.refreshToken,
87
+ });
88
+ return {
89
+ accessToken: refreshed.accessToken,
90
+ refreshToken: refreshed.refreshToken,
91
+ tradingAddress: existingSession.tradingAddress,
85
92
  };
86
- spokeProvider.setRadfiAccessToken(refreshed.accessToken, refreshed.refreshToken);
87
- saveRadfiSession(walletAddress, session);
88
- return { accessToken: refreshed.accessToken, refreshToken: refreshed.refreshToken, tradingAddress: existingSession.tradingAddress };
89
93
  } catch {
90
- // Refresh also failed — clear stale session and guide user
91
94
  clearRadfiSession(walletAddress);
92
95
  }
93
96
 
94
97
  throw new Error(
95
98
  'This wallet is already registered with Radfi from another session. ' +
96
- 'Please clear your browser storage for this site and try again, ' +
97
- 'or wait for the previous session to expire.',
99
+ 'Please clear your browser storage for this site and try again, ' +
100
+ 'or wait for the previous session to expire.',
98
101
  );
99
102
  }
100
103