@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.
- package/README.md +300 -422
- package/ai-exported/AGENTS.md +134 -0
- package/ai-exported/integration/README.md +49 -0
- package/ai-exported/integration/ai-rules.md +79 -0
- package/ai-exported/integration/architecture.md +274 -0
- package/ai-exported/integration/features/README.md +29 -0
- package/ai-exported/integration/features/auxiliary-services.md +169 -0
- package/ai-exported/integration/features/bitcoin.md +87 -0
- package/ai-exported/integration/features/bridge.md +91 -0
- package/ai-exported/integration/features/dex.md +152 -0
- package/ai-exported/integration/features/migration.md +118 -0
- package/ai-exported/integration/features/money-market.md +116 -0
- package/ai-exported/integration/features/staking.md +123 -0
- package/ai-exported/integration/features/swap.md +101 -0
- package/ai-exported/integration/quickstart.md +187 -0
- package/ai-exported/integration/recipes/README.md +136 -0
- package/ai-exported/integration/recipes/backend-queries.md +157 -0
- package/ai-exported/integration/recipes/bitcoin.md +193 -0
- package/ai-exported/integration/recipes/bridge.md +174 -0
- package/ai-exported/integration/recipes/dex.md +204 -0
- package/ai-exported/integration/recipes/invalidations.md +115 -0
- package/ai-exported/integration/recipes/migration.md +212 -0
- package/ai-exported/integration/recipes/money-market.md +206 -0
- package/ai-exported/integration/recipes/mutation-error-handling.md +118 -0
- package/ai-exported/integration/recipes/observability.md +93 -0
- package/ai-exported/integration/recipes/setup.md +144 -0
- package/ai-exported/integration/recipes/staking.md +202 -0
- package/ai-exported/integration/recipes/swap.md +272 -0
- package/ai-exported/integration/recipes/wallet-connectivity.md +101 -0
- package/ai-exported/integration/reference/README.md +12 -0
- package/ai-exported/integration/reference/glossary.md +188 -0
- package/ai-exported/integration/reference/hooks-index.md +190 -0
- package/ai-exported/integration/reference/public-api.md +110 -0
- package/ai-exported/integration/reference/querykey-conventions.md +179 -0
- package/ai-exported/migration/README.md +60 -0
- package/ai-exported/migration/ai-rules.md +81 -0
- package/ai-exported/migration/breaking-changes/hook-signatures.md +233 -0
- package/ai-exported/migration/breaking-changes/querykey-conventions.md +108 -0
- package/ai-exported/migration/breaking-changes/result-handling.md +211 -0
- package/ai-exported/migration/breaking-changes/sdk-leakage.md +165 -0
- package/ai-exported/migration/checklist.md +89 -0
- package/ai-exported/migration/features/README.md +34 -0
- package/ai-exported/migration/features/auxiliary-services.md +114 -0
- package/ai-exported/migration/features/bitcoin.md +88 -0
- package/ai-exported/migration/features/bridge.md +123 -0
- package/ai-exported/migration/features/dex.md +101 -0
- package/ai-exported/migration/features/migration.md +120 -0
- package/ai-exported/migration/features/money-market.md +97 -0
- package/ai-exported/migration/features/staking.md +109 -0
- package/ai-exported/migration/features/swap.md +118 -0
- package/ai-exported/migration/recipes.md +188 -0
- package/ai-exported/migration/reference/README.md +15 -0
- package/ai-exported/migration/reference/deleted-hooks.md +110 -0
- package/ai-exported/migration/reference/error-shape-crosswalk.md +144 -0
- package/ai-exported/migration/reference/renamed-hooks.md +66 -0
- package/dist/index.cjs +2642 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1550 -0
- package/dist/index.d.ts +1020 -2051
- package/dist/index.mjs +1581 -1531
- package/dist/index.mjs.map +1 -1
- package/package.json +21 -11
- package/src/contexts/index.ts +0 -3
- package/src/hooks/_mutationContract.test.ts +99 -0
- package/src/hooks/backend/README.md +2 -2
- package/src/hooks/backend/index.ts +13 -13
- package/src/hooks/backend/unwrapResult.ts +1 -0
- package/src/hooks/backend/useBackendAllMoneyMarketAssets.ts +13 -45
- package/src/hooks/backend/useBackendAllMoneyMarketBorrowers.ts +29 -59
- package/src/hooks/backend/useBackendIntentByHash.ts +21 -47
- package/src/hooks/backend/useBackendIntentByTxHash.ts +23 -50
- package/src/hooks/backend/useBackendMoneyMarketAsset.ts +21 -54
- package/src/hooks/backend/useBackendMoneyMarketAssetBorrowers.ts +30 -57
- package/src/hooks/backend/useBackendMoneyMarketAssetSuppliers.ts +31 -58
- package/src/hooks/backend/useBackendMoneyMarketPosition.ts +22 -38
- package/src/hooks/backend/useBackendOrderbook.ts +27 -49
- package/src/hooks/backend/useBackendSubmitSwapTx.ts +30 -36
- package/src/hooks/backend/useBackendSubmitSwapTxStatus.ts +38 -58
- package/src/hooks/backend/useBackendUserIntents.ts +25 -63
- package/src/hooks/bitcoin/index.ts +9 -8
- package/src/hooks/bitcoin/useBitcoinBalance.ts +20 -5
- package/src/hooks/bitcoin/useExpiredUtxos.ts +26 -16
- package/src/hooks/bitcoin/useFundTradingWallet.ts +33 -30
- package/src/hooks/bitcoin/useRadfiAuth.ts +43 -40
- package/src/hooks/bitcoin/useRadfiSession.ts +53 -59
- package/src/hooks/bitcoin/useRadfiWithdraw.ts +35 -53
- package/src/hooks/bitcoin/useRenewUtxos.ts +30 -50
- package/src/hooks/bitcoin/useTradingWallet.ts +1 -1
- package/src/hooks/bitcoin/useTradingWalletBalance.ts +25 -14
- package/src/hooks/bridge/index.ts +5 -5
- package/src/hooks/bridge/useBridge.ts +29 -55
- package/src/hooks/bridge/useBridgeAllowance.ts +38 -38
- package/src/hooks/bridge/useBridgeApprove.ts +32 -57
- package/src/hooks/bridge/useGetBridgeableAmount.ts +23 -37
- package/src/hooks/bridge/useGetBridgeableTokens.ts +27 -50
- package/src/hooks/dex/index.ts +16 -16
- package/src/hooks/dex/useClaimRewards.ts +35 -54
- package/src/hooks/dex/useCreateDecreaseLiquidityParams.ts +7 -20
- package/src/hooks/dex/useCreateDepositParams.ts +7 -21
- package/src/hooks/dex/useCreateSupplyLiquidityParams.ts +13 -28
- package/src/hooks/dex/useCreateWithdrawParams.ts +7 -20
- package/src/hooks/dex/useDecreaseLiquidity.ts +40 -66
- package/src/hooks/dex/useDexAllowance.ts +29 -75
- package/src/hooks/dex/useDexApprove.ts +32 -43
- package/src/hooks/dex/useDexDeposit.ts +42 -49
- package/src/hooks/dex/useDexWithdraw.ts +32 -43
- package/src/hooks/dex/useLiquidityAmounts.ts +13 -82
- package/src/hooks/dex/usePoolBalances.ts +50 -72
- package/src/hooks/dex/usePoolData.ts +17 -43
- package/src/hooks/dex/usePools.ts +11 -38
- package/src/hooks/dex/usePositionInfo.ts +27 -62
- package/src/hooks/dex/useSupplyLiquidity.ts +80 -75
- package/src/hooks/index.ts +12 -10
- package/src/hooks/migrate/index.ts +13 -4
- package/src/hooks/migrate/useMigrateBaln.ts +42 -0
- package/src/hooks/migrate/useMigrateIcxToSoda.ts +44 -0
- package/src/hooks/migrate/useMigratebnUSD.ts +47 -0
- package/src/hooks/migrate/useMigrationAllowance.ts +76 -0
- package/src/hooks/migrate/useMigrationApprove.ts +66 -0
- package/src/hooks/migrate/useRevertMigrateSodaToIcx.ts +39 -0
- package/src/hooks/mm/index.ts +14 -12
- package/src/hooks/mm/useAToken.ts +25 -41
- package/src/hooks/mm/useATokensBalances.ts +29 -60
- package/src/hooks/mm/useBorrow.ts +38 -56
- package/src/hooks/mm/useMMAllowance.ts +37 -73
- package/src/hooks/mm/useMMApprove.ts +36 -43
- package/src/hooks/mm/useRepay.ts +33 -53
- package/src/hooks/mm/useReservesData.ts +12 -38
- package/src/hooks/mm/useReservesHumanized.ts +12 -31
- package/src/hooks/mm/useReservesList.ts +11 -31
- package/src/hooks/mm/useReservesUsdFormat.ts +15 -35
- package/src/hooks/mm/useSupply.ts +45 -51
- package/src/hooks/mm/useUserFormattedSummary.ts +32 -84
- package/src/hooks/mm/useUserReservesData.ts +27 -77
- package/src/hooks/mm/useWithdraw.ts +38 -54
- package/src/hooks/partner/index.ts +6 -0
- package/src/hooks/partner/useApproveToken.ts +42 -0
- package/src/hooks/partner/useFeeClaimSwap.ts +38 -0
- package/src/hooks/partner/useFetchAssetsBalances.ts +37 -0
- package/src/hooks/partner/useGetAutoSwapPreferences.ts +37 -0
- package/src/hooks/partner/useIsTokenApproved.ts +39 -0
- package/src/hooks/partner/useSetSwapPreference.ts +50 -0
- package/src/hooks/provider/index.ts +1 -2
- package/src/hooks/provider/useHubProvider.ts +1 -1
- package/src/hooks/recovery/index.ts +2 -0
- package/src/hooks/recovery/useHubAssetBalances.ts +43 -0
- package/src/hooks/recovery/useWithdrawHubAsset.ts +48 -0
- package/src/hooks/shared/index.ts +10 -6
- package/src/hooks/shared/types.ts +77 -0
- package/src/hooks/shared/unwrapResult.ts +19 -0
- package/src/hooks/shared/useDeriveUserWalletAddress.ts +22 -40
- package/src/hooks/shared/useEstimateGas.ts +18 -15
- package/src/hooks/shared/useGetUserHubWalletAddress.ts +25 -26
- package/src/hooks/shared/useRequestTrustline.ts +28 -61
- package/src/hooks/shared/useSafeMutation.test.ts +43 -0
- package/src/hooks/shared/useSafeMutation.ts +68 -0
- package/src/hooks/shared/useSodaxContext.ts +1 -1
- package/src/hooks/shared/useStellarTrustlineCheck.ts +30 -64
- package/src/hooks/shared/useXBalances.test.ts +113 -0
- package/src/hooks/shared/useXBalances.ts +61 -0
- package/src/hooks/staking/index.ts +18 -18
- package/src/hooks/staking/useCancelUnstake.ts +30 -41
- package/src/hooks/staking/useClaim.ts +27 -36
- package/src/hooks/staking/useConvertedAssets.ts +24 -34
- package/src/hooks/staking/useInstantUnstake.ts +33 -40
- package/src/hooks/staking/useInstantUnstakeAllowance.ts +37 -45
- package/src/hooks/staking/useInstantUnstakeApprove.ts +42 -42
- package/src/hooks/staking/useInstantUnstakeRatio.ts +24 -41
- package/src/hooks/staking/useStake.ts +32 -37
- package/src/hooks/staking/useStakeAllowance.ts +30 -43
- package/src/hooks/staking/useStakeApprove.ts +40 -40
- package/src/hooks/staking/useStakeRatio.ts +24 -40
- package/src/hooks/staking/useStakingConfig.ts +14 -27
- package/src/hooks/staking/useStakingInfo.ts +30 -38
- package/src/hooks/staking/useUnstake.ts +29 -43
- package/src/hooks/staking/useUnstakeAllowance.ts +37 -44
- package/src/hooks/staking/useUnstakeApprove.ts +40 -43
- package/src/hooks/staking/useUnstakingInfo.ts +29 -41
- package/src/hooks/staking/useUnstakingInfoWithPenalty.ts +31 -47
- package/src/hooks/swap/index.ts +8 -8
- package/src/hooks/swap/useCancelLimitOrder.ts +24 -41
- package/src/hooks/swap/useCancelSwap.ts +24 -33
- package/src/hooks/swap/useCreateLimitOrder.ts +29 -62
- package/src/hooks/swap/useQuote.ts +17 -43
- package/src/hooks/swap/useStatus.ts +22 -29
- package/src/hooks/swap/useSwap.ts +31 -49
- package/src/hooks/swap/useSwapAllowance.ts +38 -35
- package/src/hooks/swap/useSwapApprove.ts +48 -57
- package/src/index.ts +5 -3
- package/src/providers/SodaxProvider.tsx +17 -11
- package/src/providers/createSodaxQueryClient.ts +96 -0
- package/src/providers/index.ts +2 -1
- package/src/utils/dex-utils.ts +27 -5
- package/src/utils/index.ts +1 -1
- package/dist/index.d.mts +0 -2581
- package/dist/index.js +0 -2574
- package/dist/index.js.map +0 -1
- package/src/hooks/migrate/types.ts +0 -15
- package/src/hooks/migrate/useMigrate.tsx +0 -110
- package/src/hooks/migrate/useMigrationAllowance.tsx +0 -79
- package/src/hooks/migrate/useMigrationApprove.tsx +0 -129
- package/src/hooks/provider/useSpokeProvider.ts +0 -172
|
@@ -1,62 +1,35 @@
|
|
|
1
|
-
import type { SolverErrorResponse, SolverIntentQuoteRequest, SolverIntentQuoteResponse
|
|
2
|
-
import {
|
|
1
|
+
import type { SolverErrorResponse, SolverIntentQuoteRequest, SolverIntentQuoteResponse } from '@sodax/sdk';
|
|
2
|
+
import type { Result } from '@sodax/sdk';
|
|
3
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
3
4
|
import { useQuery, type UseQueryResult } from '@tanstack/react-query';
|
|
4
|
-
import {
|
|
5
|
+
import type { ReadHookParams } from '../shared/types.js';
|
|
6
|
+
|
|
7
|
+
export type UseQuoteParams = ReadHookParams<
|
|
8
|
+
Result<SolverIntentQuoteResponse, SolverErrorResponse> | undefined,
|
|
9
|
+
{ payload: SolverIntentQuoteRequest | undefined }
|
|
10
|
+
>;
|
|
5
11
|
|
|
6
12
|
/**
|
|
7
13
|
* Hook for fetching a quote for an intent-based swap.
|
|
8
14
|
*
|
|
9
|
-
* This hook provides real-time quote data for an intent-based swap.
|
|
10
|
-
*
|
|
11
|
-
* @param {SolverIntentQuoteRequest | undefined} payload - The intent quote request parameters. If undefined, the query will be disabled.
|
|
12
|
-
*
|
|
13
|
-
* @returns {UseQueryResult<Result<SolverIntentQuoteResponse, SolverErrorResponse> | undefined>} A query result object containing:
|
|
14
|
-
* - data: The quote result from the solver
|
|
15
|
-
* - isLoading: Boolean indicating if the quote is being fetched
|
|
16
|
-
* - error: Error object if the quote request failed
|
|
17
|
-
* - refetch: Function to manually trigger a quote refresh
|
|
18
|
-
*
|
|
19
15
|
* @example
|
|
20
16
|
* ```typescript
|
|
21
|
-
* const { data: quote, isLoading } = useQuote({
|
|
22
|
-
* token_src: '0x...',
|
|
23
|
-
* token_src_blockchain_id: '1',
|
|
24
|
-
* token_dst: '0x...',
|
|
25
|
-
* token_dst_blockchain_id: '2',
|
|
26
|
-
* amount: '1000000000000000000',
|
|
27
|
-
* quote_type: 'exact_input',
|
|
28
|
-
* });
|
|
29
|
-
*
|
|
30
|
-
* if (isLoading) return <div>Loading quote...</div>;
|
|
31
|
-
* if (quote) {
|
|
32
|
-
* console.log('Quote received:', quote);
|
|
33
|
-
* }
|
|
17
|
+
* const { data: quote, isLoading } = useQuote({ params: { payload } });
|
|
34
18
|
* ```
|
|
35
19
|
*
|
|
36
20
|
* @remarks
|
|
37
21
|
* - The quote is automatically refreshed every 3 seconds
|
|
38
22
|
* - The query is disabled when payload is undefined
|
|
39
|
-
* - Uses React Query for efficient caching and state management
|
|
40
23
|
*/
|
|
41
|
-
export const useQuote = (
|
|
42
|
-
|
|
43
|
-
|
|
24
|
+
export const useQuote = ({
|
|
25
|
+
params,
|
|
26
|
+
queryOptions,
|
|
27
|
+
}: UseQuoteParams = {}): UseQueryResult<Result<SolverIntentQuoteResponse, SolverErrorResponse> | undefined> => {
|
|
44
28
|
const { sodax } = useSodaxContext();
|
|
45
|
-
|
|
46
|
-
// Create a serializable query key by converting BigInt to string
|
|
47
|
-
const queryKey = useMemo(() => {
|
|
48
|
-
if (!payload) return ['quote', undefined];
|
|
49
|
-
return [
|
|
50
|
-
'quote',
|
|
51
|
-
{
|
|
52
|
-
...payload,
|
|
53
|
-
amount: payload.amount.toString(),
|
|
54
|
-
},
|
|
55
|
-
];
|
|
56
|
-
}, [payload]);
|
|
29
|
+
const payload = params?.payload;
|
|
57
30
|
|
|
58
31
|
return useQuery({
|
|
59
|
-
queryKey,
|
|
32
|
+
queryKey: ['swap', 'quote', payload && { ...payload, amount: payload.amount.toString() }],
|
|
60
33
|
queryFn: async () => {
|
|
61
34
|
if (!payload) {
|
|
62
35
|
return undefined;
|
|
@@ -65,5 +38,6 @@ export const useQuote = (
|
|
|
65
38
|
},
|
|
66
39
|
enabled: !!payload,
|
|
67
40
|
refetchInterval: 3000,
|
|
41
|
+
...queryOptions,
|
|
68
42
|
});
|
|
69
43
|
};
|
|
@@ -1,44 +1,37 @@
|
|
|
1
|
-
import type { Hex, SolverErrorResponse, SolverIntentStatusResponse
|
|
1
|
+
import type { Hex, SolverErrorResponse, SolverIntentStatusResponse } from '@sodax/sdk';
|
|
2
|
+
import type { Result } from '@sodax/sdk';
|
|
2
3
|
import { useQuery, type UseQueryResult } from '@tanstack/react-query';
|
|
3
|
-
import { useSodaxContext } from '../shared/useSodaxContext';
|
|
4
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
5
|
+
import type { ReadHookParams } from '../shared/types.js';
|
|
6
|
+
|
|
7
|
+
export type UseStatusParams = ReadHookParams<
|
|
8
|
+
Result<SolverIntentStatusResponse, SolverErrorResponse> | undefined,
|
|
9
|
+
{ intentTxHash: Hex | undefined }
|
|
10
|
+
>;
|
|
4
11
|
|
|
5
12
|
/**
|
|
6
13
|
* Hook for monitoring the status of an intent-based swap.
|
|
7
14
|
*
|
|
8
|
-
* This hook provides real-time status updates for an intent-based swap transaction.
|
|
9
|
-
*
|
|
10
|
-
* @param {Hex} intent_tx_hash - The transaction hash of the intent order on the hub chain
|
|
11
|
-
*
|
|
12
|
-
* @returns {UseQueryResult<Result<SolverIntentStatusResponse, SolverErrorResponse> | undefined>} A query result object containing:
|
|
13
|
-
* - data: The status result from the solver
|
|
14
|
-
* - isLoading: Boolean indicating if the status is being fetched
|
|
15
|
-
* - error: Error object if the status request failed
|
|
16
|
-
* - refetch: Function to manually trigger a status refresh
|
|
17
|
-
*
|
|
18
15
|
* @example
|
|
19
16
|
* ```typescript
|
|
20
|
-
* const { data: status, isLoading } = useStatus(
|
|
21
|
-
*
|
|
22
|
-
* if (isLoading) return <div>Loading status...</div>;
|
|
23
|
-
* if (status?.ok) {
|
|
24
|
-
* console.log('Status:', status.value);
|
|
25
|
-
* }
|
|
17
|
+
* const { data: status, isLoading } = useStatus({ params: { intentTxHash } });
|
|
26
18
|
* ```
|
|
27
|
-
*
|
|
28
|
-
* @remarks
|
|
29
|
-
* - The status is automatically refreshed every 3 seconds
|
|
30
|
-
* - Uses React Query for efficient caching and state management
|
|
31
19
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
): UseQueryResult<Result<SolverIntentStatusResponse, SolverErrorResponse> | undefined> => {
|
|
20
|
+
export const useStatus = ({
|
|
21
|
+
params,
|
|
22
|
+
queryOptions,
|
|
23
|
+
}: UseStatusParams = {}): UseQueryResult<Result<SolverIntentStatusResponse, SolverErrorResponse> | undefined> => {
|
|
36
24
|
const { sodax } = useSodaxContext();
|
|
25
|
+
const intentTxHash = params?.intentTxHash;
|
|
26
|
+
|
|
37
27
|
return useQuery({
|
|
38
|
-
queryKey: [
|
|
28
|
+
queryKey: ['swap', 'status', intentTxHash],
|
|
39
29
|
queryFn: async () => {
|
|
40
|
-
|
|
30
|
+
if (!intentTxHash) return undefined;
|
|
31
|
+
return sodax.swaps.getStatus({ intent_tx_hash: intentTxHash });
|
|
41
32
|
},
|
|
42
|
-
|
|
33
|
+
enabled: !!intentTxHash,
|
|
34
|
+
refetchInterval: 3000,
|
|
35
|
+
...queryOptions,
|
|
43
36
|
});
|
|
44
37
|
};
|
|
@@ -1,60 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
IntentError,
|
|
9
|
-
SpokeProvider,
|
|
10
|
-
IntentDeliveryInfo,
|
|
11
|
-
} from '@sodax/sdk';
|
|
12
|
-
import { useMutation, type UseMutationResult, useQueryClient } from '@tanstack/react-query';
|
|
1
|
+
// packages/dapp-kit/src/hooks/swap/useSwap.ts
|
|
2
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
3
|
+
import type { SpokeChainKey, SwapActionParams, SwapResponse } from '@sodax/sdk';
|
|
4
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
5
|
+
import type { MutationHookParams } from '../shared/types.js';
|
|
6
|
+
import { useSafeMutation, type SafeUseMutationResult } from '../shared/useSafeMutation.js';
|
|
7
|
+
import { unwrapResult } from '../shared/unwrapResult.js';
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Mutation variables for {@link useSwap}. Generic over `K extends SpokeChainKey` (defaults to the
|
|
11
|
+
* 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 UseSwapVars<K extends SpokeChainKey = SpokeChainKey> = Omit<SwapActionParams<K, false>, 'raw'>;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
* Uses React Query's useMutation for better state management and caching.
|
|
19
|
-
*
|
|
20
|
-
* @param {SpokeProvider} spokeProvider - The spoke provider to use for the swap
|
|
21
|
-
* @returns {UseMutationResult} Mutation result object containing mutation function and state
|
|
17
|
+
* React hook for executing an intent-based cross-chain swap.
|
|
22
18
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* const { mutateAsync: swap, isPending } = useSwap(spokeProvider);
|
|
26
|
-
*
|
|
27
|
-
* const handleSwap = async () => {
|
|
28
|
-
* const result = await swap({
|
|
29
|
-
* token_src: '0x...',
|
|
30
|
-
* token_src_blockchain_id: 'arbitrum',
|
|
31
|
-
* token_dst: '0x...',
|
|
32
|
-
* token_dst_blockchain_id: 'polygon',
|
|
33
|
-
* amount: '1000000000000000000',
|
|
34
|
-
* min_output_amount: '900000000000000000'
|
|
35
|
-
* });
|
|
36
|
-
* };
|
|
37
|
-
* ```
|
|
19
|
+
* Throws on SDK failure so React Query's native error model engages (`isError`, `error`,
|
|
20
|
+
* `onError`, `retry`). Returns the unwrapped `SwapResponse` on success.
|
|
38
21
|
*/
|
|
39
|
-
export function useSwap(
|
|
40
|
-
|
|
41
|
-
|
|
22
|
+
export function useSwap<K extends SpokeChainKey = SpokeChainKey>({
|
|
23
|
+
mutationOptions,
|
|
24
|
+
}: MutationHookParams<SwapResponse, UseSwapVars<K>> = {}): SafeUseMutationResult<
|
|
25
|
+
SwapResponse,
|
|
26
|
+
Error,
|
|
27
|
+
UseSwapVars<K>
|
|
28
|
+
> {
|
|
42
29
|
const { sodax } = useSodaxContext();
|
|
43
30
|
const queryClient = useQueryClient();
|
|
44
31
|
|
|
45
|
-
return
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
});
|
|
54
|
-
},
|
|
55
|
-
onSuccess: () => {
|
|
56
|
-
// Invalidate balance queries to refresh both source and destination token balances
|
|
57
|
-
queryClient.invalidateQueries({ queryKey: ['xBalances'] });
|
|
32
|
+
return useSafeMutation<SwapResponse, Error, UseSwapVars<K>>({
|
|
33
|
+
mutationKey: ['swap'],
|
|
34
|
+
...mutationOptions,
|
|
35
|
+
mutationFn: async vars => unwrapResult(await sodax.swaps.swap({ ...vars, raw: false })),
|
|
36
|
+
onSuccess: async (data, vars, ctx) => {
|
|
37
|
+
queryClient.invalidateQueries({ queryKey: ['shared', 'xBalances', vars.params.srcChainKey] });
|
|
38
|
+
queryClient.invalidateQueries({ queryKey: ['shared', 'xBalances', vars.params.dstChainKey] });
|
|
39
|
+
await mutationOptions?.onSuccess?.(data, vars, ctx);
|
|
58
40
|
},
|
|
59
41
|
});
|
|
60
42
|
}
|
|
@@ -1,48 +1,51 @@
|
|
|
1
1
|
import { useQuery, type UseQueryResult } from '@tanstack/react-query';
|
|
2
|
-
import { useSodaxContext } from '../shared/useSodaxContext';
|
|
3
|
-
import type { CreateIntentParams, CreateLimitOrderParams
|
|
2
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
3
|
+
import type { CreateIntentParams, CreateLimitOrderParams } from '@sodax/sdk';
|
|
4
|
+
import type { GetWalletProviderType, SpokeChainKey } from '@sodax/sdk';
|
|
5
|
+
import type { ReadHookParams } from '../shared/types.js';
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```typescript
|
|
21
|
-
* const { data: hasAllowed, isLoading } = useSwapAllowance(params, spokeProvider);
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
export function useSwapAllowance(
|
|
25
|
-
params: CreateIntentParams | CreateLimitOrderParams | undefined,
|
|
26
|
-
spokeProvider: SpokeProvider | undefined,
|
|
27
|
-
): UseQueryResult<boolean, Error> {
|
|
7
|
+
export type UseSwapAllowanceParams<K extends SpokeChainKey> = ReadHookParams<
|
|
8
|
+
boolean,
|
|
9
|
+
{
|
|
10
|
+
payload: CreateIntentParams | CreateLimitOrderParams | undefined;
|
|
11
|
+
srcChainKey: K | undefined;
|
|
12
|
+
walletProvider: GetWalletProviderType<K> | undefined;
|
|
13
|
+
}
|
|
14
|
+
>;
|
|
15
|
+
|
|
16
|
+
export function useSwapAllowance<K extends SpokeChainKey>({
|
|
17
|
+
params,
|
|
18
|
+
queryOptions,
|
|
19
|
+
}: UseSwapAllowanceParams<K> = {}): UseQueryResult<boolean, Error> {
|
|
28
20
|
const { sodax } = useSodaxContext();
|
|
21
|
+
const payload = params?.payload;
|
|
22
|
+
const srcChainKey = params?.srcChainKey;
|
|
23
|
+
const walletProvider = params?.walletProvider;
|
|
29
24
|
|
|
30
|
-
return useQuery({
|
|
31
|
-
|
|
25
|
+
return useQuery<boolean, Error>({
|
|
26
|
+
// Extract the (chain, owner, token, amount) tuple that actually scopes the allowance —
|
|
27
|
+
// raw-object keys break per Rule 4 (bigints) and churn on every render.
|
|
28
|
+
queryKey: [
|
|
29
|
+
'swap',
|
|
30
|
+
'allowance',
|
|
31
|
+
payload?.srcChainKey,
|
|
32
|
+
payload?.srcAddress,
|
|
33
|
+
payload?.inputToken,
|
|
34
|
+
payload?.inputAmount?.toString(),
|
|
35
|
+
],
|
|
32
36
|
queryFn: async () => {
|
|
33
|
-
if (!
|
|
37
|
+
if (!srcChainKey || !walletProvider || !payload) {
|
|
34
38
|
return false;
|
|
35
39
|
}
|
|
36
40
|
const allowance = await sodax.swaps.isAllowanceValid({
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
params: payload as CreateIntentParams,
|
|
42
|
+
raw: false,
|
|
43
|
+
walletProvider,
|
|
39
44
|
});
|
|
40
|
-
|
|
41
|
-
return allowance.value;
|
|
42
|
-
}
|
|
43
|
-
return false;
|
|
45
|
+
return allowance.ok ? allowance.value : false;
|
|
44
46
|
},
|
|
45
|
-
enabled: !!
|
|
47
|
+
enabled: !!srcChainKey && !!walletProvider && !!payload,
|
|
46
48
|
refetchInterval: 2000,
|
|
49
|
+
...queryOptions,
|
|
47
50
|
});
|
|
48
51
|
}
|
|
@@ -1,68 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
// packages/dapp-kit/src/hooks/swap/useSwapApprove.ts
|
|
2
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
3
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
4
|
+
import type {
|
|
5
|
+
CreateIntentParams,
|
|
6
|
+
CreateLimitOrderParams,
|
|
7
|
+
GetWalletProviderType,
|
|
8
|
+
SpokeChainKey,
|
|
9
|
+
TxReturnType,
|
|
10
|
+
} from '@sodax/sdk';
|
|
11
|
+
import type { MutationHookParams } from '../shared/types.js';
|
|
12
|
+
import { useSafeMutation, type SafeUseMutationResult } from '../shared/useSafeMutation.js';
|
|
13
|
+
import { unwrapResult } from '../shared/unwrapResult.js';
|
|
4
14
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Mutation variables for {@link useSwapApprove}. Generic over `K extends SpokeChainKey` (defaults
|
|
17
|
+
* to the full union). Sophisticated callers can lock K at the call site to narrow the
|
|
18
|
+
* `walletProvider` and `params.srcChainKey` types.
|
|
19
|
+
*/
|
|
20
|
+
export type UseSwapApproveVars<K extends SpokeChainKey = SpokeChainKey> = {
|
|
21
|
+
params: CreateIntentParams<K> | CreateLimitOrderParams<K>;
|
|
22
|
+
walletProvider: GetWalletProviderType<K>;
|
|
23
|
+
};
|
|
11
24
|
|
|
12
25
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* @param spokeProvider The spoke provider instance for the chain
|
|
16
|
-
* @returns Object containing approve function, loading state, error state and reset function
|
|
17
|
-
* @example
|
|
18
|
-
* ```tsx
|
|
19
|
-
* const { approve, isLoading, error } = useApprove(token, spokeProvider);
|
|
26
|
+
* React hook for approving ERC-20 token spending (or trustline establishment) for a swap or
|
|
27
|
+
* limit-order intent.
|
|
20
28
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
29
|
+
* Throws on SDK failure so React Query's native error model engages (`isError`, `error`,
|
|
30
|
+
* `onError`, `retry`). Returns the unwrapped tx return value on success. Invalidates all
|
|
31
|
+
* `['swap', 'allowance', ...]` queries so any pending allowance check refreshes.
|
|
24
32
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
export function useSwapApprove<K extends SpokeChainKey = SpokeChainKey>({
|
|
34
|
+
mutationOptions,
|
|
35
|
+
}: MutationHookParams<TxReturnType<K, false>, UseSwapApproveVars<K>> = {}): SafeUseMutationResult<
|
|
36
|
+
TxReturnType<K, false>,
|
|
37
|
+
Error,
|
|
38
|
+
UseSwapApproveVars<K>
|
|
39
|
+
> {
|
|
30
40
|
const { sodax } = useSodaxContext();
|
|
31
41
|
const queryClient = useQueryClient();
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const allowance = await sodax.swaps.approve({
|
|
48
|
-
intentParams: params,
|
|
49
|
-
spokeProvider,
|
|
50
|
-
});
|
|
51
|
-
if (!allowance.ok) {
|
|
52
|
-
throw new Error('Failed to approve input token');
|
|
53
|
-
}
|
|
54
|
-
return allowance.ok;
|
|
55
|
-
},
|
|
56
|
-
onSuccess: () => {
|
|
57
|
-
// Invalidate allowance query to refetch the new allowance
|
|
58
|
-
queryClient.invalidateQueries({ queryKey: ['allowance', params] });
|
|
43
|
+
return useSafeMutation<TxReturnType<K, false>, Error, UseSwapApproveVars<K>>({
|
|
44
|
+
mutationKey: ['swap', 'approve'],
|
|
45
|
+
...mutationOptions,
|
|
46
|
+
mutationFn: async ({ params, walletProvider }) =>
|
|
47
|
+
unwrapResult(
|
|
48
|
+
await sodax.swaps.approve<K, false>({
|
|
49
|
+
params: params as CreateIntentParams<K>,
|
|
50
|
+
raw: false,
|
|
51
|
+
walletProvider,
|
|
52
|
+
}),
|
|
53
|
+
),
|
|
54
|
+
onSuccess: async (data, vars, ctx) => {
|
|
55
|
+
queryClient.invalidateQueries({ queryKey: ['swap', 'allowance'] });
|
|
56
|
+
await mutationOptions?.onSuccess?.(data, vars, ctx);
|
|
59
57
|
},
|
|
60
58
|
});
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
approve,
|
|
64
|
-
isLoading: isPending,
|
|
65
|
-
error: error,
|
|
66
|
-
resetError,
|
|
67
|
-
};
|
|
68
59
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
1
|
+
import { useMemo, useRef, type ReactNode, type ReactElement } from 'react';
|
|
4
2
|
import { Sodax, type SodaxConfig } from '@sodax/sdk';
|
|
5
|
-
import { SodaxContext } from '@/contexts';
|
|
6
|
-
import type {
|
|
3
|
+
import { SodaxContext } from '@/contexts/index.js';
|
|
4
|
+
import type { DeepPartial } from '@sodax/sdk';
|
|
7
5
|
|
|
8
6
|
interface SodaxProviderProps {
|
|
9
7
|
children: ReactNode;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Sodax config (overrides defaults including rpcUrls). **Read-once at mount** —
|
|
10
|
+
* changes after first render are ignored to prevent re-instantiating the SDK
|
|
11
|
+
* from unstable parent references. To switch config (e.g. testnet ↔ mainnet),
|
|
12
|
+
* unmount/remount the provider.
|
|
13
|
+
*/
|
|
14
|
+
config?: DeepPartial<SodaxConfig>;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
export const SodaxProvider = ({ children,
|
|
16
|
-
|
|
17
|
+
export const SodaxProvider = ({ children, config }: SodaxProviderProps): ReactElement => {
|
|
18
|
+
// Freeze config on first render so the SDK instance and consumers share one
|
|
19
|
+
// snapshot (matches SodaxWalletProvider semantic).
|
|
20
|
+
const configRef = useRef<DeepPartial<SodaxConfig> | undefined>(config);
|
|
21
|
+
const frozen = configRef.current;
|
|
22
|
+
const sodax = useMemo(() => new Sodax(frozen), [frozen]);
|
|
17
23
|
|
|
18
|
-
return <SodaxContext.Provider value={{ sodax
|
|
24
|
+
return <SodaxContext.Provider value={{ sodax }}>{children}</SodaxContext.Provider>;
|
|
19
25
|
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// packages/dapp-kit/src/providers/createSodaxQueryClient.ts
|
|
2
|
+
import { MutationCache, QueryClient, type QueryClientConfig } from '@tanstack/react-query';
|
|
3
|
+
|
|
4
|
+
export type CreateSodaxQueryClientOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Called for every mutation failure (i.e. every time `mutationFn` throws) that does NOT opt out
|
|
7
|
+
* via `meta: { silent: true }` on the mutation. Defaults to `console.error`.
|
|
8
|
+
*
|
|
9
|
+
* This is **global observability** — it runs alongside any per-hook `onError` handler the
|
|
10
|
+
* consumer set, NOT instead of them. In particular, it fires:
|
|
11
|
+
* - whether or not `mutateAsync` was awaited inside `try/catch`
|
|
12
|
+
* - whether or not `mutateAsyncSafe` was used (the wrapper packs into `Result<T>` AFTER React
|
|
13
|
+
* Query has already entered the error state and dispatched its callbacks)
|
|
14
|
+
* - whether or not the consumer's `mutationOptions.onError` already toasted/logged
|
|
15
|
+
*
|
|
16
|
+
* It is NOT a "did this rejection escape to the global handler?" detector — accurate
|
|
17
|
+
* unhandled-rejection detection lives at `window.onunhandledrejection`, not here.
|
|
18
|
+
*
|
|
19
|
+
* To silence the default for a specific mutation that the consumer is handling locally, set
|
|
20
|
+
* `meta: { silent: true }`:
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* useSwap({ mutationOptions: { meta: { silent: true }, onError: (e) => toast(e.message) } });
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* To disable the default globally (e.g. wire your own error boundary), pass a no-op:
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* createSodaxQueryClient({ onMutationError: () => {} });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
onMutationError?: (error: unknown) => void;
|
|
33
|
+
/** Pass-through for any other QueryClient config (default queries options, etc.) */
|
|
34
|
+
config?: QueryClientConfig;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const defaultOnMutationError = (error: unknown): void => {
|
|
38
|
+
console.error('[sodax] Mutation error:', error);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Creates a `QueryClient` pre-wired with a mutation-error observability hook that gives dapp-kit
|
|
43
|
+
* consumers a single seam for every mutation failure across the app — wire to Sentry/Datadog/console
|
|
44
|
+
* as you like. Optional opt-in: consumers who construct their own `QueryClient` are unaffected.
|
|
45
|
+
*
|
|
46
|
+
* **Composition with a custom `MutationCache`.** If you pass `config.mutationCache`, we keep your
|
|
47
|
+
* cache instance (preserving its own `onError` / `onSuccess` / etc.) and *additionally* subscribe
|
|
48
|
+
* to its event stream to dispatch `onMutationError`. Both your handler and the dapp-kit handler
|
|
49
|
+
* fire — neither replaces the other. If you don't pass one, we install our own.
|
|
50
|
+
*
|
|
51
|
+
* @example default — logs to console
|
|
52
|
+
* const queryClient = createSodaxQueryClient();
|
|
53
|
+
*
|
|
54
|
+
* @example custom — Sentry
|
|
55
|
+
* const queryClient = createSodaxQueryClient({
|
|
56
|
+
* onMutationError: (e) => Sentry.captureException(e),
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* @example silent — disable the default
|
|
60
|
+
* const queryClient = createSodaxQueryClient({ onMutationError: () => {} });
|
|
61
|
+
*
|
|
62
|
+
* @example bring-your-own MutationCache
|
|
63
|
+
* const myCache = new MutationCache({ onError: myOwnErrorHandler });
|
|
64
|
+
* const queryClient = createSodaxQueryClient({ config: { mutationCache: myCache } });
|
|
65
|
+
* // myOwnErrorHandler still runs; onMutationError ALSO runs (unless meta.silent).
|
|
66
|
+
*/
|
|
67
|
+
export function createSodaxQueryClient({
|
|
68
|
+
onMutationError = defaultOnMutationError,
|
|
69
|
+
config,
|
|
70
|
+
}: CreateSodaxQueryClientOptions = {}): QueryClient {
|
|
71
|
+
if (config?.mutationCache) {
|
|
72
|
+
// Compose: keep the consumer's cache, attach our observability as an extra subscriber.
|
|
73
|
+
// The consumer's own `MutationCache.onError` (if any) still fires — subscribe is additive.
|
|
74
|
+
config.mutationCache.subscribe(event => {
|
|
75
|
+
if (
|
|
76
|
+
event.type === 'updated' &&
|
|
77
|
+
event.action.type === 'error' &&
|
|
78
|
+
event.mutation.options.meta?.silent !== true
|
|
79
|
+
) {
|
|
80
|
+
onMutationError(event.action.error);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return new QueryClient(config);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// No consumer cache: install our own with `onError` directly (cheaper than a subscribe loop).
|
|
87
|
+
return new QueryClient({
|
|
88
|
+
...config,
|
|
89
|
+
mutationCache: new MutationCache({
|
|
90
|
+
onError: (error, _vars, _ctx, mutation) => {
|
|
91
|
+
if (mutation.options.meta?.silent === true) return;
|
|
92
|
+
onMutationError(error);
|
|
93
|
+
},
|
|
94
|
+
}),
|
|
95
|
+
});
|
|
96
|
+
}
|
package/src/providers/index.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { SodaxProvider } from './SodaxProvider';
|
|
1
|
+
export { SodaxProvider } from './SodaxProvider.js';
|
|
2
|
+
export { createSodaxQueryClient, type CreateSodaxQueryClientOptions } from './createSodaxQueryClient.js';
|