@sodax/dapp-kit 2.0.0-rc.2 → 2.0.0-rc.20
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 +29 -74
- package/dist/index.d.ts +780 -58
- package/dist/index.mjs +841 -143
- package/package.json +31 -19
- package/src/hooks/_mutationContract.test.ts +15 -2
- package/src/hooks/backend/index.ts +1 -5
- package/src/hooks/bitcoin/index.ts +2 -0
- package/src/hooks/bitcoin/resolveBtcReadAddress.test.ts +54 -0
- package/src/hooks/bitcoin/resolveBtcReadAddress.ts +21 -0
- package/src/hooks/bitcoin/useBitcoinTradingSetup.ts +45 -0
- package/src/hooks/bitcoin/useEnsureRadfiAccessToken.ts +57 -0
- package/src/hooks/bitcoin/useFundTradingWallet.ts +1 -1
- package/src/hooks/bitcoin/useRadfiAuth.ts +2 -2
- package/src/hooks/bitcoin/useRadfiWithdraw.ts +2 -2
- package/src/hooks/bitcoin/useRenewUtxos.ts +2 -2
- package/src/hooks/bitcoin/useTradingWallet.ts +1 -1
- package/src/hooks/index.ts +2 -0
- package/src/hooks/leverageYield/index.ts +9 -0
- package/src/hooks/leverageYield/useLeverageYieldDeposit.ts +40 -0
- package/src/hooks/leverageYield/useLeverageYieldEffectiveApr.ts +42 -0
- package/src/hooks/leverageYield/useLeverageYieldNotifySolver.ts +34 -0
- package/src/hooks/leverageYield/useLeverageYieldPosition.ts +40 -0
- package/src/hooks/leverageYield/useLeverageYieldPreviewRedeem.ts +43 -0
- package/src/hooks/leverageYield/useLeverageYieldShareBalances.ts +74 -0
- package/src/hooks/leverageYield/useLeverageYieldTotalAssets.ts +36 -0
- package/src/hooks/leverageYield/useLeverageYieldVaultSwap.ts +50 -0
- package/src/hooks/leverageYield/useLeverageYieldWithdraw.ts +40 -0
- package/src/hooks/mm/useATokensBalances.ts +7 -1
- package/src/hooks/mm/useUserFormattedSummary.ts +5 -1
- package/src/hooks/mm/useUserReservesData.ts +5 -1
- package/src/hooks/partner/index.ts +4 -0
- package/src/hooks/partner/useFeeClaimWithdraw.ts +88 -0
- package/src/hooks/partner/useGetIntentDetails.ts +39 -0
- package/src/hooks/partner/useGetUserIntent.ts +35 -0
- package/src/hooks/partner/usePartnerCancelIntent.ts +52 -0
- package/src/hooks/shared/index.ts +4 -0
- package/src/hooks/shared/isUserRejectedError.test.ts +42 -0
- package/src/hooks/shared/isUserRejectedError.ts +30 -0
- package/src/hooks/shared/useGetUserHubWalletAddress.ts +5 -1
- package/src/hooks/shared/useNearStorageCheck.ts +45 -0
- package/src/hooks/shared/useNearStorageGate.ts +60 -0
- package/src/hooks/shared/useRegisterNearStorage.ts +46 -0
- package/src/hooks/swapsApi/index.ts +41 -0
- package/src/hooks/swapsApi/isTerminalSwapIntentStatus.test.ts +24 -0
- package/src/hooks/swapsApi/isTerminalSwapIntentStatus.ts +11 -0
- package/src/hooks/swapsApi/useSwapsApiAllowance.ts +40 -0
- package/src/hooks/swapsApi/useSwapsApiApprove.ts +42 -0
- package/src/hooks/swapsApi/useSwapsApiCancelIntent.ts +41 -0
- package/src/hooks/swapsApi/useSwapsApiCreateIntent.ts +41 -0
- package/src/hooks/swapsApi/useSwapsApiCreateLimitOrder.ts +41 -0
- package/src/hooks/swapsApi/useSwapsApiDeadline.ts +36 -0
- package/src/hooks/swapsApi/useSwapsApiEstimateGas.ts +40 -0
- package/src/hooks/swapsApi/useSwapsApiFilledIntent.ts +41 -0
- package/src/hooks/swapsApi/useSwapsApiIntent.ts +40 -0
- package/src/hooks/swapsApi/useSwapsApiIntentExtraData.ts +41 -0
- package/src/hooks/swapsApi/useSwapsApiIntentHash.ts +40 -0
- package/src/hooks/swapsApi/useSwapsApiIntentPacket.ts +43 -0
- package/src/hooks/swapsApi/useSwapsApiPartnerFee.ts +40 -0
- package/src/hooks/swapsApi/useSwapsApiQuote.ts +55 -0
- package/src/hooks/swapsApi/useSwapsApiSolverFee.ts +40 -0
- package/src/hooks/swapsApi/useSwapsApiStatus.ts +45 -0
- package/src/hooks/swapsApi/useSwapsApiSubmitIntent.ts +43 -0
- package/src/hooks/{backend/useBackendSubmitSwapTx.ts → swapsApi/useSwapsApiSubmitTx.ts} +16 -17
- package/src/hooks/swapsApi/useSwapsApiSubmitTxStatus.ts +55 -0
- package/src/hooks/swapsApi/useSwapsApiTokens.ts +34 -0
- package/src/hooks/swapsApi/useSwapsApiTokensByChain.ts +40 -0
- package/src/providers/SodaxProvider.tsx +17 -14
- package/src/utils/index.ts +1 -0
- package/src/utils/nearStorageGate.test.ts +46 -0
- package/src/utils/nearStorageGate.ts +39 -0
- package/ai-exported/AGENTS.md +0 -134
- package/ai-exported/integration/README.md +0 -49
- package/ai-exported/integration/ai-rules.md +0 -79
- package/ai-exported/integration/architecture.md +0 -274
- package/ai-exported/integration/features/README.md +0 -29
- package/ai-exported/integration/features/auxiliary-services.md +0 -169
- package/ai-exported/integration/features/bitcoin.md +0 -87
- package/ai-exported/integration/features/bridge.md +0 -91
- package/ai-exported/integration/features/dex.md +0 -152
- package/ai-exported/integration/features/migration.md +0 -118
- package/ai-exported/integration/features/money-market.md +0 -116
- package/ai-exported/integration/features/staking.md +0 -123
- package/ai-exported/integration/features/swap.md +0 -101
- package/ai-exported/integration/quickstart.md +0 -187
- package/ai-exported/integration/recipes/README.md +0 -136
- package/ai-exported/integration/recipes/backend-queries.md +0 -157
- package/ai-exported/integration/recipes/bitcoin.md +0 -193
- package/ai-exported/integration/recipes/bridge.md +0 -174
- package/ai-exported/integration/recipes/dex.md +0 -204
- package/ai-exported/integration/recipes/invalidations.md +0 -115
- package/ai-exported/integration/recipes/migration.md +0 -212
- package/ai-exported/integration/recipes/money-market.md +0 -206
- package/ai-exported/integration/recipes/mutation-error-handling.md +0 -118
- package/ai-exported/integration/recipes/observability.md +0 -93
- package/ai-exported/integration/recipes/setup.md +0 -144
- package/ai-exported/integration/recipes/staking.md +0 -202
- package/ai-exported/integration/recipes/swap.md +0 -272
- package/ai-exported/integration/recipes/wallet-connectivity.md +0 -101
- package/ai-exported/integration/reference/README.md +0 -12
- package/ai-exported/integration/reference/glossary.md +0 -188
- package/ai-exported/integration/reference/hooks-index.md +0 -190
- package/ai-exported/integration/reference/public-api.md +0 -110
- package/ai-exported/integration/reference/querykey-conventions.md +0 -179
- package/ai-exported/migration/README.md +0 -60
- package/ai-exported/migration/ai-rules.md +0 -81
- package/ai-exported/migration/breaking-changes/hook-signatures.md +0 -233
- package/ai-exported/migration/breaking-changes/querykey-conventions.md +0 -108
- package/ai-exported/migration/breaking-changes/result-handling.md +0 -211
- package/ai-exported/migration/breaking-changes/sdk-leakage.md +0 -165
- package/ai-exported/migration/checklist.md +0 -89
- package/ai-exported/migration/features/README.md +0 -34
- package/ai-exported/migration/features/auxiliary-services.md +0 -114
- package/ai-exported/migration/features/bitcoin.md +0 -88
- package/ai-exported/migration/features/bridge.md +0 -123
- package/ai-exported/migration/features/dex.md +0 -101
- package/ai-exported/migration/features/migration.md +0 -120
- package/ai-exported/migration/features/money-market.md +0 -97
- package/ai-exported/migration/features/staking.md +0 -109
- package/ai-exported/migration/features/swap.md +0 -118
- package/ai-exported/migration/recipes.md +0 -188
- package/ai-exported/migration/reference/README.md +0 -15
- package/ai-exported/migration/reference/deleted-hooks.md +0 -110
- package/ai-exported/migration/reference/error-shape-crosswalk.md +0 -144
- package/ai-exported/migration/reference/renamed-hooks.md +0 -66
- package/dist/index.cjs +0 -2642
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -1550
- package/dist/index.mjs.map +0 -1
- package/src/hooks/backend/useBackendSubmitSwapTxStatus.ts +0 -59
package/package.json
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sodax/dapp-kit",
|
|
3
|
+
"private": false,
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
3
7
|
"license": "MIT",
|
|
4
|
-
"version": "2.0.0-rc.
|
|
5
|
-
"description": "
|
|
8
|
+
"version": "2.0.0-rc.20",
|
|
9
|
+
"description": "React hooks for building dApps on the SODAX cross-chain DeFi platform",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"sodax",
|
|
12
|
+
"dapp-kit",
|
|
13
|
+
"react",
|
|
14
|
+
"react-query",
|
|
15
|
+
"hooks",
|
|
16
|
+
"defi"
|
|
17
|
+
],
|
|
18
|
+
"homepage": "https://github.com/icon-project/sodax-sdks/tree/main/packages/dapp-kit",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/icon-project/sodax-sdks/issues"
|
|
21
|
+
},
|
|
6
22
|
"type": "module",
|
|
7
|
-
"main": "dist/index.
|
|
23
|
+
"main": "dist/index.mjs",
|
|
8
24
|
"types": "dist/index.d.ts",
|
|
9
25
|
"module": "dist/index.mjs",
|
|
10
26
|
"files": [
|
|
11
27
|
"dist",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
28
|
+
"!dist/**/*.map",
|
|
29
|
+
"src"
|
|
14
30
|
],
|
|
15
31
|
"repository": {
|
|
16
32
|
"type": "git",
|
|
@@ -18,29 +34,31 @@
|
|
|
18
34
|
},
|
|
19
35
|
"dependencies": {
|
|
20
36
|
"viem": "2.29.2",
|
|
21
|
-
"@sodax/sdk": "2.0.0-rc.
|
|
37
|
+
"@sodax/sdk": "2.0.0-rc.20"
|
|
22
38
|
},
|
|
23
39
|
"devDependencies": {
|
|
40
|
+
"@arethetypeswrong/cli": "0.17.4",
|
|
24
41
|
"@tanstack/react-query": "5.87.4",
|
|
25
42
|
"@types/react": "19.0.8",
|
|
26
43
|
"knip": "5.30.5",
|
|
44
|
+
"tslib": "2.8.1",
|
|
27
45
|
"tsup": "8.5.0",
|
|
28
46
|
"typescript": "5.5.4",
|
|
29
|
-
"vitest": "2.
|
|
47
|
+
"vitest": "3.2.6"
|
|
30
48
|
},
|
|
31
49
|
"peerDependencies": {
|
|
32
50
|
"@tanstack/react-query": "5.x",
|
|
33
51
|
"react": ">=18"
|
|
34
52
|
},
|
|
35
53
|
"engines": {
|
|
36
|
-
"node": ">=20.
|
|
54
|
+
"node": ">=20.12.0"
|
|
37
55
|
},
|
|
56
|
+
"sideEffects": false,
|
|
38
57
|
"exports": {
|
|
39
58
|
"./package.json": "./package.json",
|
|
40
59
|
".": {
|
|
41
60
|
"types": "./dist/index.d.ts",
|
|
42
|
-
"import": "./dist/index.mjs"
|
|
43
|
-
"require": "./dist/index.cjs"
|
|
61
|
+
"import": "./dist/index.mjs"
|
|
44
62
|
}
|
|
45
63
|
},
|
|
46
64
|
"scripts": {
|
|
@@ -50,14 +68,8 @@
|
|
|
50
68
|
"clean": "rm -rf dist && rm -rf node_modules && rm -rf .turbo",
|
|
51
69
|
"pretty": "biome format . --write",
|
|
52
70
|
"checkTs": "tsc --noEmit",
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"check:ai-scope": "bash ./scripts/check-ai-scope.sh",
|
|
57
|
-
"check:ai-links": "bash ./scripts/check-ai-links.sh",
|
|
58
|
-
"check:ai-imports": "bash ./scripts/check-ai-imports.sh",
|
|
59
|
-
"check:ai-snippets": "bash ./scripts/check-ai-snippets.sh",
|
|
60
|
-
"check:ai-keys": "bash ./scripts/check-ai-keys.sh",
|
|
61
|
-
"check:ai-consistency": "bash ./scripts/check-ai-consistency.sh"
|
|
71
|
+
"check-exports": "attw --pack --profile esm-only",
|
|
72
|
+
"check:knip": "knip",
|
|
73
|
+
"lint": "biome lint . --write"
|
|
62
74
|
}
|
|
63
75
|
}
|
|
@@ -7,13 +7,13 @@ const HOOKS_DIR = resolve(fileURLToPath(import.meta.url), '..');
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Manifest of every mutation hook. `nativeThrow: true` marks hooks whose underlying SDK methods
|
|
10
|
-
* throw natively (
|
|
10
|
+
* throw natively (Bound Exchange APIs) and so don't need `unwrapResult`.
|
|
11
11
|
*
|
|
12
12
|
* To add a new mutation hook, add its path here. The friction is intentional — it forces explicit
|
|
13
13
|
* registration so the contract is enforced from day one.
|
|
14
14
|
*/
|
|
15
15
|
const HOOKS: Array<{ path: string; nativeThrow?: true }> = [
|
|
16
|
-
{ path: '
|
|
16
|
+
{ path: 'bitcoin/useEnsureRadfiAccessToken.ts', nativeThrow: true },
|
|
17
17
|
{ path: 'bitcoin/useFundTradingWallet.ts', nativeThrow: true },
|
|
18
18
|
{ path: 'bitcoin/useRadfiAuth.ts', nativeThrow: true },
|
|
19
19
|
{ path: 'bitcoin/useRadfiWithdraw.ts', nativeThrow: true },
|
|
@@ -26,6 +26,10 @@ const HOOKS: Array<{ path: string; nativeThrow?: true }> = [
|
|
|
26
26
|
{ path: 'dex/useDexDeposit.ts' },
|
|
27
27
|
{ path: 'dex/useDexWithdraw.ts' },
|
|
28
28
|
{ path: 'dex/useSupplyLiquidity.ts' },
|
|
29
|
+
{ path: 'leverageYield/useLeverageYieldDeposit.ts' },
|
|
30
|
+
{ path: 'leverageYield/useLeverageYieldNotifySolver.ts' },
|
|
31
|
+
{ path: 'leverageYield/useLeverageYieldVaultSwap.ts' },
|
|
32
|
+
{ path: 'leverageYield/useLeverageYieldWithdraw.ts' },
|
|
29
33
|
{ path: 'migrate/useMigrateBaln.ts' },
|
|
30
34
|
{ path: 'migrate/useMigrateIcxToSoda.ts' },
|
|
31
35
|
{ path: 'migrate/useMigratebnUSD.ts' },
|
|
@@ -38,9 +42,12 @@ const HOOKS: Array<{ path: string; nativeThrow?: true }> = [
|
|
|
38
42
|
{ path: 'mm/useWithdraw.ts' },
|
|
39
43
|
{ path: 'partner/useApproveToken.ts' },
|
|
40
44
|
{ path: 'partner/useFeeClaimSwap.ts' },
|
|
45
|
+
{ path: 'partner/useFeeClaimWithdraw.ts' },
|
|
46
|
+
{ path: 'partner/usePartnerCancelIntent.ts' },
|
|
41
47
|
{ path: 'partner/useSetSwapPreference.ts' },
|
|
42
48
|
{ path: 'recovery/useWithdrawHubAsset.ts' },
|
|
43
49
|
{ path: 'shared/useEstimateGas.ts' },
|
|
50
|
+
{ path: 'shared/useRegisterNearStorage.ts', nativeThrow: true },
|
|
44
51
|
{ path: 'staking/useCancelUnstake.ts' },
|
|
45
52
|
{ path: 'staking/useClaim.ts' },
|
|
46
53
|
{ path: 'staking/useInstantUnstake.ts' },
|
|
@@ -54,6 +61,12 @@ const HOOKS: Array<{ path: string; nativeThrow?: true }> = [
|
|
|
54
61
|
{ path: 'swap/useCreateLimitOrder.ts' },
|
|
55
62
|
{ path: 'swap/useSwap.ts' },
|
|
56
63
|
{ path: 'swap/useSwapApprove.ts' },
|
|
64
|
+
{ path: 'swapsApi/useSwapsApiApprove.ts' },
|
|
65
|
+
{ path: 'swapsApi/useSwapsApiCancelIntent.ts' },
|
|
66
|
+
{ path: 'swapsApi/useSwapsApiCreateIntent.ts' },
|
|
67
|
+
{ path: 'swapsApi/useSwapsApiCreateLimitOrder.ts' },
|
|
68
|
+
{ path: 'swapsApi/useSwapsApiSubmitIntent.ts' },
|
|
69
|
+
{ path: 'swapsApi/useSwapsApiSubmitTx.ts' },
|
|
57
70
|
];
|
|
58
71
|
|
|
59
72
|
describe.each(HOOKS)('mutation hook contract: $path', ({ path, nativeThrow }) => {
|
|
@@ -12,10 +12,6 @@ export { useBackendIntentByTxHash } from './useBackendIntentByTxHash.js';
|
|
|
12
12
|
export { useBackendIntentByHash } from './useBackendIntentByHash.js';
|
|
13
13
|
export { useBackendUserIntents } from './useBackendUserIntents.js';
|
|
14
14
|
|
|
15
|
-
// Swap submit-tx hooks
|
|
16
|
-
export { useBackendSubmitSwapTx } from './useBackendSubmitSwapTx.js';
|
|
17
|
-
export { useBackendSubmitSwapTxStatus } from './useBackendSubmitSwapTxStatus.js';
|
|
18
|
-
|
|
19
15
|
// Solver hooks
|
|
20
16
|
export { useBackendOrderbook } from './useBackendOrderbook.js';
|
|
21
17
|
|
|
@@ -26,4 +22,4 @@ export { useBackendMoneyMarketAsset } from './useBackendMoneyMarketAsset.js';
|
|
|
26
22
|
export { useBackendMoneyMarketAssetBorrowers } from './useBackendMoneyMarketAssetBorrowers.js';
|
|
27
23
|
export { useBackendMoneyMarketAssetSuppliers } from './useBackendMoneyMarketAssetSuppliers.js';
|
|
28
24
|
export { useBackendAllMoneyMarketBorrowers } from './useBackendAllMoneyMarketBorrowers.js';
|
|
29
|
-
export * from './types.js';
|
|
25
|
+
export * from './types.js';
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export * from './useRadfiAuth.js';
|
|
2
|
+
export * from './useEnsureRadfiAccessToken.js';
|
|
2
3
|
export * from './useRadfiSession.js';
|
|
3
4
|
export * from './useFundTradingWallet.js';
|
|
4
5
|
export * from './useBitcoinBalance.js';
|
|
5
6
|
export * from './useTradingWallet.js';
|
|
6
7
|
export * from './useTradingWalletBalance.js';
|
|
8
|
+
export * from './useBitcoinTradingSetup.js';
|
|
7
9
|
export * from './useExpiredUtxos.js';
|
|
8
10
|
export * from './useRenewUtxos.js';
|
|
9
11
|
export * from './useRadfiWithdraw.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ChainKeys } from '@sodax/sdk';
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import type { RadfiSession } from './useRadfiAuth.js';
|
|
4
|
+
import { loadRadfiSession } from './useRadfiAuth.js';
|
|
5
|
+
import { resolveBtcReadAddress } from './resolveBtcReadAddress.js';
|
|
6
|
+
|
|
7
|
+
// resolveBtcReadAddress reads the Bound Exchange session via loadRadfiSession (localStorage-backed).
|
|
8
|
+
// The dapp-kit test env is `node` (no localStorage), so mock the session lookup to drive each branch.
|
|
9
|
+
vi.mock('./useRadfiAuth.js', () => ({
|
|
10
|
+
loadRadfiSession: vi.fn(),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
const mockLoadRadfiSession = vi.mocked(loadRadfiSession);
|
|
14
|
+
|
|
15
|
+
const PERSONAL_ADDRESS = 'bc1qpersonal00000000000000000000000000000';
|
|
16
|
+
const TRADING_ADDRESS = 'bc1qtrading000000000000000000000000000000';
|
|
17
|
+
|
|
18
|
+
const session = (tradingAddress: string): RadfiSession => ({
|
|
19
|
+
accessToken: 'access',
|
|
20
|
+
refreshToken: 'refresh',
|
|
21
|
+
tradingAddress,
|
|
22
|
+
publicKey: 'pub',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('resolveBtcReadAddress', () => {
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
mockLoadRadfiSession.mockReset();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('passes the address through unchanged for non-Bitcoin chains (no session lookup)', () => {
|
|
31
|
+
const result = resolveBtcReadAddress(ChainKeys.ARBITRUM_MAINNET, PERSONAL_ADDRESS);
|
|
32
|
+
|
|
33
|
+
expect(result).toBe(PERSONAL_ADDRESS);
|
|
34
|
+
expect(mockLoadRadfiSession).not.toHaveBeenCalled();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('returns the trading address from the local session for Bitcoin', () => {
|
|
38
|
+
mockLoadRadfiSession.mockReturnValue(session(TRADING_ADDRESS));
|
|
39
|
+
|
|
40
|
+
const result = resolveBtcReadAddress(ChainKeys.BITCOIN_MAINNET, PERSONAL_ADDRESS);
|
|
41
|
+
|
|
42
|
+
expect(result).toBe(TRADING_ADDRESS);
|
|
43
|
+
// The session is keyed by the personal address.
|
|
44
|
+
expect(mockLoadRadfiSession).toHaveBeenCalledWith(PERSONAL_ADDRESS);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('falls back to the personal address for Bitcoin when there is no session', () => {
|
|
48
|
+
mockLoadRadfiSession.mockReturnValue(null);
|
|
49
|
+
|
|
50
|
+
const result = resolveBtcReadAddress(ChainKeys.BITCOIN_MAINNET, PERSONAL_ADDRESS);
|
|
51
|
+
|
|
52
|
+
expect(result).toBe(PERSONAL_ADDRESS);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ChainKeys, type SpokeChainKey } from '@sodax/sdk';
|
|
2
|
+
import { loadRadfiSession } from './useRadfiAuth.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a spoke address for READ queries (positions, balances, hub-wallet display).
|
|
6
|
+
*
|
|
7
|
+
* Bitcoin positions live under the Bound Exchange trading-wallet-derived hub wallet, so for Bitcoin we
|
|
8
|
+
* resolve to the trading address from the locally-persisted Bound Exchange session. This is intentionally
|
|
9
|
+
* a LOCAL lookup (no network call): a transient Bound Exchange API outage can never make a real position
|
|
10
|
+
* read as empty, and reads never throw "Trading wallet not found". When there is no session, the
|
|
11
|
+
* user has no Bitcoin position to show, so the original (personal) address is returned — deriving
|
|
12
|
+
* an empty hub wallet, which is correct. Non-Bitcoin chains pass through unchanged.
|
|
13
|
+
*
|
|
14
|
+
* The WRITE path resolves the trading address authoritatively in the SDK
|
|
15
|
+
* (`getEffectiveWalletAddress`, called from the money-market create*Intent flows); reads
|
|
16
|
+
* deliberately use this lighter, fail-safe path.
|
|
17
|
+
*/
|
|
18
|
+
export function resolveBtcReadAddress(chainKey: SpokeChainKey, address: string): string {
|
|
19
|
+
if (chainKey !== ChainKeys.BITCOIN_MAINNET) return address;
|
|
20
|
+
return loadRadfiSession(address)?.tradingAddress ?? address;
|
|
21
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChainKeys,
|
|
3
|
+
type IBitcoinWalletProvider,
|
|
4
|
+
type IWalletProvider,
|
|
5
|
+
type RadfiWalletBalance,
|
|
6
|
+
type SpokeChainKey,
|
|
7
|
+
} from '@sodax/sdk';
|
|
8
|
+
import { useTradingWallet } from './useTradingWallet.js';
|
|
9
|
+
import { useTradingWalletBalance } from './useTradingWalletBalance.js';
|
|
10
|
+
|
|
11
|
+
export interface UseBitcoinTradingSetupParams {
|
|
12
|
+
chainKey: SpokeChainKey;
|
|
13
|
+
/** This side's wallet provider + account, e.g. `useWalletProvider` / `useXAccount`. */
|
|
14
|
+
walletProvider: IWalletProvider | undefined;
|
|
15
|
+
address: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface BitcoinTradingSetup {
|
|
19
|
+
wallet: IBitcoinWalletProvider | undefined;
|
|
20
|
+
tradingBalance: RadfiWalletBalance | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const INERT: BitcoinTradingSetup = { wallet: undefined, tradingBalance: undefined };
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Bitcoin trading-wallet setup for one side of a cross-chain flow: Bitcoin funds move through a
|
|
27
|
+
* Bound Exchange (Radfi) trading wallet, not the personal wallet. Inert (no work) unless `chainKey`
|
|
28
|
+
* is Bitcoin. Wallet-layer inputs are passed in — this package doesn't depend on wallet-sdk-react.
|
|
29
|
+
*/
|
|
30
|
+
export function useBitcoinTradingSetup({
|
|
31
|
+
chainKey,
|
|
32
|
+
walletProvider,
|
|
33
|
+
address,
|
|
34
|
+
}: UseBitcoinTradingSetupParams): BitcoinTradingSetup {
|
|
35
|
+
const isBitcoin = chainKey === ChainKeys.BITCOIN_MAINNET;
|
|
36
|
+
// Safe: when this side is Bitcoin its provider IS the Bitcoin one (TS can't relate chainKey to provider type).
|
|
37
|
+
const wallet = isBitcoin ? (walletProvider as IBitcoinWalletProvider | undefined) : undefined;
|
|
38
|
+
|
|
39
|
+
// Hooks run every render; undefined inputs keep the Bound balance query disabled when not Bitcoin.
|
|
40
|
+
const { tradingAddress } = useTradingWallet(isBitcoin ? address : undefined);
|
|
41
|
+
const { data: tradingBalance } = useTradingWalletBalance({ params: { walletProvider: wallet, tradingAddress } });
|
|
42
|
+
|
|
43
|
+
if (!isBitcoin) return INERT;
|
|
44
|
+
return { wallet, tradingBalance };
|
|
45
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { IBitcoinWalletProvider } from '@sodax/sdk';
|
|
2
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
3
|
+
import type { MutationHookParams } from '../shared/types.js';
|
|
4
|
+
import { useSafeMutation, type SafeUseMutationResult } from '../shared/useSafeMutation.js';
|
|
5
|
+
import { loadRadfiSession, saveRadfiSession } from './useRadfiAuth.js';
|
|
6
|
+
|
|
7
|
+
export type UseEnsureRadfiAccessTokenVars = {
|
|
8
|
+
walletProvider: IBitcoinWalletProvider;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Ensure a valid Bound Exchange access token and return it. Refreshes the existing token (no
|
|
13
|
+
* signature prompt) when a refresh token is available, falling back to a full BIP322 re-auth only if
|
|
14
|
+
* refresh fails. Bound tokens are short-lived, so call this right before a Bitcoin-source
|
|
15
|
+
* createIntent — forward the returned token via the typed `extras.bound.accessToken` slot (SDK in-process)
|
|
16
|
+
* or the `accessToken` body field on the backend DTO — or before the client-side sign + co-sign step.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const { mutateAsync: ensureToken } = useEnsureRadfiAccessToken();
|
|
20
|
+
* const accessToken = await ensureToken({ walletProvider });
|
|
21
|
+
* // SDK in-process (Bitcoin-gated extras):
|
|
22
|
+
* await sodax.swaps.createIntent({ params, extras: { bound: { accessToken } }, raw: true });
|
|
23
|
+
* // or backend createIntent — token in the body, not an x-bound-access-token header:
|
|
24
|
+
* await createIntent({ body: { ...body, accessToken } });
|
|
25
|
+
*/
|
|
26
|
+
export function useEnsureRadfiAccessToken({
|
|
27
|
+
mutationOptions,
|
|
28
|
+
}: MutationHookParams<string, UseEnsureRadfiAccessTokenVars> = {}): SafeUseMutationResult<
|
|
29
|
+
string,
|
|
30
|
+
Error,
|
|
31
|
+
UseEnsureRadfiAccessTokenVars
|
|
32
|
+
> {
|
|
33
|
+
const { sodax } = useSodaxContext();
|
|
34
|
+
return useSafeMutation<string, Error, UseEnsureRadfiAccessTokenVars>({
|
|
35
|
+
mutationKey: ['bitcoin', 'ensureAccessToken'],
|
|
36
|
+
...mutationOptions,
|
|
37
|
+
mutationFn: async ({ walletProvider }) => {
|
|
38
|
+
const radfi = sodax.spoke.bitcoin.radfi;
|
|
39
|
+
const walletAddress = await walletProvider.getWalletAddress();
|
|
40
|
+
// Seed in-memory tokens from the saved session so a refresh can run without a re-sign popup.
|
|
41
|
+
const session = loadRadfiSession(walletAddress);
|
|
42
|
+
if (session?.refreshToken && !radfi.refreshToken) {
|
|
43
|
+
radfi.setRadfiAccessToken(session.accessToken, session.refreshToken);
|
|
44
|
+
}
|
|
45
|
+
await radfi.ensureRadfiAccessToken(walletProvider);
|
|
46
|
+
const accessToken = radfi.accessToken;
|
|
47
|
+
if (!accessToken) {
|
|
48
|
+
throw new Error('Failed to obtain a Bound Exchange access token');
|
|
49
|
+
}
|
|
50
|
+
// Persist refreshed tokens so a later reload can refresh again without re-signing.
|
|
51
|
+
if (session) {
|
|
52
|
+
saveRadfiSession(walletAddress, { ...session, accessToken, refreshToken: radfi.refreshToken });
|
|
53
|
+
}
|
|
54
|
+
return accessToken;
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -11,7 +11,7 @@ export type UseFundTradingWalletVars = {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* React hook for funding the user's
|
|
14
|
+
* React hook for funding the user's Bound Exchange trading wallet from their personal Bitcoin wallet.
|
|
15
15
|
* Pure mutation: pass `{ amount, walletProvider }` to `mutate({...})`. Returns the broadcast tx
|
|
16
16
|
* id on success.
|
|
17
17
|
*/
|
|
@@ -45,7 +45,7 @@ export function clearRadfiSession(address: string): void {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* React hook for authenticating with
|
|
48
|
+
* React hook for authenticating with Bound Exchange via BIP322-signed message. Pure mutation: pass
|
|
49
49
|
* `{ walletProvider }` to `mutate({...})`. The hook itself takes no arguments other than the
|
|
50
50
|
* structural `mutationOptions` slot.
|
|
51
51
|
*/
|
|
@@ -95,7 +95,7 @@ export function useRadfiAuth({
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
throw new Error(
|
|
98
|
-
'This wallet is already registered with
|
|
98
|
+
'This wallet is already registered with Bound Exchange from another session. ' +
|
|
99
99
|
'Please clear your browser storage for this site and try again, ' +
|
|
100
100
|
'or wait for the previous session to expire.',
|
|
101
101
|
);
|
|
@@ -19,7 +19,7 @@ type WithdrawResult = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* React hook for withdrawing BTC from the user's
|
|
22
|
+
* React hook for withdrawing BTC from the user's Bound Exchange trading wallet back to their personal
|
|
23
23
|
* Bitcoin wallet. Pure mutation: pass all inputs (including the wallet provider) to
|
|
24
24
|
* `mutate({...})`.
|
|
25
25
|
*/
|
|
@@ -44,7 +44,7 @@ export function useRadfiWithdraw({
|
|
|
44
44
|
const accessToken = session?.accessToken || radfi.accessToken;
|
|
45
45
|
|
|
46
46
|
if (!accessToken) {
|
|
47
|
-
throw new Error('
|
|
47
|
+
throw new Error('Bound Exchange authentication required. Please login first.');
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
const buildResult = await radfi.withdrawToUser({ userAddress, amount, tokenId, withdrawTo }, accessToken);
|
|
@@ -12,7 +12,7 @@ export type UseRenewUtxosVars = {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* React hook for renewing expired UTXOs in the user's
|
|
15
|
+
* React hook for renewing expired UTXOs in the user's Bound Exchange trading wallet. Pure mutation: pass
|
|
16
16
|
* `{ txIdVouts, walletProvider }` to `mutate({...})`.
|
|
17
17
|
*/
|
|
18
18
|
export function useRenewUtxos({
|
|
@@ -32,7 +32,7 @@ export function useRenewUtxos({
|
|
|
32
32
|
const accessToken = session?.accessToken || radfi.accessToken;
|
|
33
33
|
|
|
34
34
|
if (!accessToken) {
|
|
35
|
-
throw new Error('
|
|
35
|
+
throw new Error('Bound Exchange authentication required. Please login first.');
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
const buildResult = await radfi.buildRenewUtxoTransaction({ userAddress, txIdVouts }, accessToken);
|
|
@@ -5,7 +5,7 @@ type UseTradingWalletReturn = {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Returns the
|
|
8
|
+
* Returns the Bound Exchange trading wallet address from the persisted session.
|
|
9
9
|
* Trading wallet is created automatically during authentication — no API call needed.
|
|
10
10
|
*/
|
|
11
11
|
export function useTradingWallet(walletAddress: string | undefined): UseTradingWalletReturn {
|
package/src/hooks/index.ts
CHANGED
|
@@ -4,9 +4,11 @@ export * from './bitcoin/index.js';
|
|
|
4
4
|
export * from './mm/index.js';
|
|
5
5
|
export * from './swap/index.js';
|
|
6
6
|
export * from './backend/index.js';
|
|
7
|
+
export * from './swapsApi/index.js';
|
|
7
8
|
export * from './bridge/index.js';
|
|
8
9
|
export * from './staking/index.js';
|
|
9
10
|
export * from './partner/index.js';
|
|
10
11
|
export * from './recovery/index.js';
|
|
11
12
|
export * from './migrate/index.js';
|
|
12
13
|
export * from './dex/index.js';
|
|
14
|
+
export * from './leverageYield/index.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './useLeverageYieldEffectiveApr.js';
|
|
2
|
+
export * from './useLeverageYieldPosition.js';
|
|
3
|
+
export * from './useLeverageYieldTotalAssets.js';
|
|
4
|
+
export * from './useLeverageYieldPreviewRedeem.js';
|
|
5
|
+
export * from './useLeverageYieldShareBalances.js';
|
|
6
|
+
export * from './useLeverageYieldDeposit.js';
|
|
7
|
+
export * from './useLeverageYieldNotifySolver.js';
|
|
8
|
+
export * from './useLeverageYieldVaultSwap.js';
|
|
9
|
+
export * from './useLeverageYieldWithdraw.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
2
|
+
import type { LeverageYieldSwapPayload, LeverageYieldSwapDepositParams } from '@sodax/sdk';
|
|
3
|
+
import type { MutationHookParams } from '../shared/types.js';
|
|
4
|
+
import { useSafeMutation, type SafeUseMutationResult } from '../shared/useSafeMutation.js';
|
|
5
|
+
import { unwrapResult } from '../shared/unwrapResult.js';
|
|
6
|
+
|
|
7
|
+
/** Mutation variables for {@link useLeverageYieldDeposit} — the swap-style deposit inputs. */
|
|
8
|
+
export type UseLeverageYieldDepositVars = LeverageYieldSwapDepositParams;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Builds the `LeverageYieldSwapPayload` for a leverage-yield deposit (any token → `lsoda*` shares,
|
|
12
|
+
* delivered to the user's hub wallet). Spread the returned payload into
|
|
13
|
+
* {@link useLeverageYieldVaultSwap}.
|
|
14
|
+
*
|
|
15
|
+
* This is a builder, not an executor — it derives the hub wallet and assembles the intent; the
|
|
16
|
+
* actual swap is relayed by `useLeverageYieldVaultSwap`. Throws on SDK failure so React Query's
|
|
17
|
+
* error model engages; returns the unwrapped `LeverageYieldSwapPayload` on success.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const { mutateAsyncSafe: buildDeposit } = useLeverageYieldDeposit();
|
|
22
|
+
* const built = await buildDeposit({ vault, srcChainKey, srcAddress, inputToken, inputAmount, minOutputAmount });
|
|
23
|
+
* if (built.ok) vaultSwap({ ...built.value, walletProvider });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function useLeverageYieldDeposit({
|
|
27
|
+
mutationOptions,
|
|
28
|
+
}: MutationHookParams<LeverageYieldSwapPayload, UseLeverageYieldDepositVars> = {}): SafeUseMutationResult<
|
|
29
|
+
LeverageYieldSwapPayload,
|
|
30
|
+
Error,
|
|
31
|
+
UseLeverageYieldDepositVars
|
|
32
|
+
> {
|
|
33
|
+
const { sodax } = useSodaxContext();
|
|
34
|
+
|
|
35
|
+
return useSafeMutation<LeverageYieldSwapPayload, Error, UseLeverageYieldDepositVars>({
|
|
36
|
+
mutationKey: ['leverageYield', 'deposit'],
|
|
37
|
+
...mutationOptions,
|
|
38
|
+
mutationFn: async vars => unwrapResult(await sodax.leverageYield.deposit(vars)),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useQuery, type UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
3
|
+
import type { Address, LeverageYieldEffectiveApr } from '@sodax/sdk';
|
|
4
|
+
import type { ReadHookParams } from '../shared/types.js';
|
|
5
|
+
|
|
6
|
+
export type UseLeverageYieldEffectiveAprParams = ReadHookParams<
|
|
7
|
+
LeverageYieldEffectiveApr,
|
|
8
|
+
{ vault: Address | undefined }
|
|
9
|
+
>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Reads a leverage-yield vault's effective APR — AAVE supply/borrow rates plus the LSD
|
|
13
|
+
* staking yield, with the vault's leverage formula re-applied on the boosted supply side.
|
|
14
|
+
*
|
|
15
|
+
* The underlying SDK call does the on-chain reads (AAVE rates + `targetLTV`) and the
|
|
16
|
+
* off-chain LSD fetch in parallel. Rates drift slowly, so the default refresh is 60s.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const { data: apr } = useLeverageYieldEffectiveApr({ params: { vault: vault.vault } });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function useLeverageYieldEffectiveApr({
|
|
24
|
+
params,
|
|
25
|
+
queryOptions,
|
|
26
|
+
}: UseLeverageYieldEffectiveAprParams = {}): UseQueryResult<LeverageYieldEffectiveApr, Error> {
|
|
27
|
+
const { sodax } = useSodaxContext();
|
|
28
|
+
const vault = params?.vault;
|
|
29
|
+
|
|
30
|
+
return useQuery<LeverageYieldEffectiveApr, Error>({
|
|
31
|
+
queryKey: ['leverageYield', 'effectiveApr', vault],
|
|
32
|
+
queryFn: async () => {
|
|
33
|
+
if (!vault) throw new Error('vault is required');
|
|
34
|
+
const result = await sodax.leverageYield.getEffectiveApr(vault);
|
|
35
|
+
if (!result.ok) throw result.error;
|
|
36
|
+
return result.value;
|
|
37
|
+
},
|
|
38
|
+
enabled: !!vault,
|
|
39
|
+
refetchInterval: 60_000,
|
|
40
|
+
...queryOptions,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
2
|
+
import type { SolverExecutionRequest, SolverExecutionResponse } from '@sodax/sdk';
|
|
3
|
+
import type { MutationHookParams } from '../shared/types.js';
|
|
4
|
+
import { useSafeMutation, type SafeUseMutationResult } from '../shared/useSafeMutation.js';
|
|
5
|
+
import { unwrapResult } from '../shared/unwrapResult.js';
|
|
6
|
+
|
|
7
|
+
/** Mutation variables for {@link useLeverageYieldNotifySolver} — the hub-side intent tx hash. */
|
|
8
|
+
export type UseLeverageYieldNotifySolverVars = SolverExecutionRequest;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Notifies the solver that a leverage-yield vault intent landed on the hub, triggering the fill.
|
|
12
|
+
* The standalone notify step for the manual create → relay → notify flow: build the intent with
|
|
13
|
+
* `sodax.leverageYield.createVaultIntent`, relay it yourself, then call this with the hub-side
|
|
14
|
+
* intent tx hash. The end-to-end {@link useLeverageYieldVaultSwap} already calls notifySolver
|
|
15
|
+
* internally — only reach for this hook when driving the relay manually.
|
|
16
|
+
*
|
|
17
|
+
* Throws on SDK failure so React Query's error model engages; returns the unwrapped
|
|
18
|
+
* `SolverExecutionResponse` (`{ answer: 'OK', intent_hash }`) on success.
|
|
19
|
+
*/
|
|
20
|
+
export function useLeverageYieldNotifySolver({
|
|
21
|
+
mutationOptions,
|
|
22
|
+
}: MutationHookParams<SolverExecutionResponse, UseLeverageYieldNotifySolverVars> = {}): SafeUseMutationResult<
|
|
23
|
+
SolverExecutionResponse,
|
|
24
|
+
Error,
|
|
25
|
+
UseLeverageYieldNotifySolverVars
|
|
26
|
+
> {
|
|
27
|
+
const { sodax } = useSodaxContext();
|
|
28
|
+
|
|
29
|
+
return useSafeMutation<SolverExecutionResponse, Error, UseLeverageYieldNotifySolverVars>({
|
|
30
|
+
mutationKey: ['leverageYield', 'notifySolver'],
|
|
31
|
+
...mutationOptions,
|
|
32
|
+
mutationFn: async vars => unwrapResult(await sodax.leverageYield.notifySolver(vars)),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useQuery, type UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import { useSodaxContext } from '../shared/useSodaxContext.js';
|
|
3
|
+
import type { Address, LeverageYieldPosition } from '@sodax/sdk';
|
|
4
|
+
import type { ReadHookParams } from '../shared/types.js';
|
|
5
|
+
|
|
6
|
+
export type UseLeverageYieldPositionParams = ReadHookParams<LeverageYieldPosition, { vault: Address | undefined }>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Reads a leverage-yield vault's live position snapshot via the vault's `getPositionDetails`:
|
|
10
|
+
* collateral, debt, current LTV (drift vs `targetLTV`), health factor (∞ when no debt), and
|
|
11
|
+
* idle (not-yet-deployed) asset.
|
|
12
|
+
*
|
|
13
|
+
* LTV shifts with each rebalance/rate tick, so the default refresh (30s) is faster than the
|
|
14
|
+
* APR/stats reads.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const { data: position } = useLeverageYieldPosition({ params: { vault: vault.vault } });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function useLeverageYieldPosition({
|
|
22
|
+
params,
|
|
23
|
+
queryOptions,
|
|
24
|
+
}: UseLeverageYieldPositionParams = {}): UseQueryResult<LeverageYieldPosition, Error> {
|
|
25
|
+
const { sodax } = useSodaxContext();
|
|
26
|
+
const vault = params?.vault;
|
|
27
|
+
|
|
28
|
+
return useQuery<LeverageYieldPosition, Error>({
|
|
29
|
+
queryKey: ['leverageYield', 'position', vault],
|
|
30
|
+
queryFn: async () => {
|
|
31
|
+
if (!vault) throw new Error('vault is required');
|
|
32
|
+
const result = await sodax.leverageYield.getPosition(vault);
|
|
33
|
+
if (!result.ok) throw result.error;
|
|
34
|
+
return result.value;
|
|
35
|
+
},
|
|
36
|
+
enabled: !!vault,
|
|
37
|
+
refetchInterval: 30_000,
|
|
38
|
+
...queryOptions,
|
|
39
|
+
});
|
|
40
|
+
}
|