@oydual31/more-vaults-sdk 0.1.2 → 0.1.3

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.
@@ -1,5 +1,6 @@
1
1
  import { Hash, Address, WalletClient, PublicClient } from 'viem';
2
2
  export { PublicClient as SdkPublicClient } from 'viem';
3
+ export { A as AsyncRequestStatus, a as AsyncRequestStatusInfo, D as DepositBlockReason, b as DepositEligibility, M as MaxWithdrawable, U as UserBalances, c as UserPosition, V as VaultMetadata, d as VaultMode, e as VaultStatus, f as VaultSummary, g as canDeposit, h as ensureAllowance, i as getAsyncRequestStatus, j as getAsyncRequestStatusLabel, k as getMaxWithdrawable, l as getUserBalances, m as getUserPosition, n as getVaultMetadata, o as getVaultStatus, p as getVaultSummary, q as isAsyncMode, r as previewDeposit, s as previewRedeem, t as quoteLzFee } from '../userHelpers-CZLB9oQ4.js';
3
4
 
4
5
  /** EVM Chain IDs for chains supported by MoreVaults */
5
6
  declare const CHAIN_IDS: {
@@ -978,154 +979,6 @@ declare function bridgeSharesToHub(walletClient: WalletClient, publicClient: Pub
978
979
  txHash: Hash;
979
980
  }>;
980
981
 
981
- type VaultMode = 'local' | 'cross-chain-oracle' | 'cross-chain-async' | 'paused' | 'full';
982
- interface VaultStatus {
983
- /** Vault operating mode — determines which SDK flow to use */
984
- mode: VaultMode;
985
- /** Which deposit function to call given the current configuration */
986
- recommendedDepositFlow: 'depositSimple' | 'depositAsync' | 'mintAsync' | 'none';
987
- /** Which redeem function to call given the current configuration */
988
- recommendedRedeemFlow: 'redeemShares' | 'redeemAsync' | 'none';
989
- isHub: boolean;
990
- isPaused: boolean;
991
- oracleAccountingEnabled: boolean;
992
- /** address(0) means CCManager is not set — async flows will fail */
993
- ccManager: Address;
994
- /** address(0) means escrow is not configured in the registry */
995
- escrow: Address;
996
- withdrawalQueueEnabled: boolean;
997
- /** Timelock duration in seconds (0 = no timelock) */
998
- withdrawalTimelockSeconds: bigint;
999
- /**
1000
- * Remaining deposit capacity in underlying token decimals.
1001
- * `type(uint256).max` = no cap configured (unlimited).
1002
- * `0n` = vault is full — no more deposits accepted.
1003
- * If `depositAccessRestricted = true`, this value is `type(uint256).max` but
1004
- * deposits are still gated by whitelist or other access control.
1005
- */
1006
- remainingDepositCapacity: bigint;
1007
- /**
1008
- * True when `maxDeposit(address(0))` reverted, indicating the vault uses
1009
- * whitelist or other access control to restrict who can deposit.
1010
- * Deposit flows will succeed only for addresses the vault operator has approved.
1011
- */
1012
- depositAccessRestricted: boolean;
1013
- underlying: Address;
1014
- totalAssets: bigint;
1015
- totalSupply: bigint;
1016
- /** Vault share token decimals. Use this for display — never hardcode 18. */
1017
- decimals: number;
1018
- /**
1019
- * Price of 1 full share expressed in underlying token units.
1020
- * = convertToAssets(10^decimals). Grows over time as the vault earns yield.
1021
- */
1022
- sharePrice: bigint;
1023
- /**
1024
- * Underlying token balance held directly on the hub chain.
1025
- * This is the only portion that can be paid out to redeeming users immediately.
1026
- * (= ERC-20.balanceOf(vault) on the hub)
1027
- */
1028
- hubLiquidBalance: bigint;
1029
- /**
1030
- * Approximate value deployed to spoke chains (totalAssets − hubLiquidBalance).
1031
- * These funds are NOT immediately redeemable — the vault curator must
1032
- * call executeBridging to repatriate them before large redeems can succeed.
1033
- */
1034
- spokesDeployedBalance: bigint;
1035
- /**
1036
- * Maximum assets that can be redeemed right now without curator intervention.
1037
- * - For hub vaults: equals `hubLiquidBalance` (only what the hub holds).
1038
- * - For local/oracle vaults: equals `totalAssets` (all assets are local).
1039
- * Attempting to redeem more than this will revert (R1) or be auto-refunded (R5).
1040
- */
1041
- maxImmediateRedeemAssets: bigint;
1042
- /**
1043
- * Human-readable list of configuration problems that would cause transactions
1044
- * to fail. Empty array = vault is ready to use.
1045
- */
1046
- issues: string[];
1047
- }
1048
- /**
1049
- * Read the full configuration and operational status of a vault in a single
1050
- * multicall-friendly batch.
1051
- *
1052
- * Use this to:
1053
- * - Determine which SDK flow to use (`recommendedDepositFlow`)
1054
- * - Show a configuration checklist in an admin dashboard
1055
- * - Surface `issues` to the developer before any transaction
1056
- *
1057
- * @param publicClient Public client for reads
1058
- * @param vault Vault address (diamond proxy)
1059
- * @returns Full vault status snapshot
1060
- *
1061
- * @example
1062
- * ```ts
1063
- * const status = await getVaultStatus(publicClient, VAULT)
1064
- * if (status.issues.length) {
1065
- * console.warn('Vault misconfigured:', status.issues)
1066
- * }
1067
- * // Use recommended flow:
1068
- * if (status.recommendedDepositFlow === 'depositAsync') {
1069
- * await depositAsync(walletClient, publicClient, { vault: VAULT, escrow: status.escrow }, ...)
1070
- * }
1071
- * ```
1072
- */
1073
- declare function getVaultStatus(publicClient: PublicClient, vault: Address): Promise<VaultStatus>;
1074
- /**
1075
- * Ensure the spender has sufficient ERC-20 allowance; approve if not.
1076
- *
1077
- * Checks the current allowance and only sends an approve transaction if
1078
- * the existing allowance is less than the required amount.
1079
- *
1080
- * @param walletClient Wallet client with account attached
1081
- * @param publicClient Public client for reads
1082
- * @param token ERC-20 token address
1083
- * @param spender Address to approve
1084
- * @param amount Minimum required allowance
1085
- */
1086
- declare function ensureAllowance(walletClient: WalletClient, publicClient: PublicClient, token: Address, spender: Address, amount: bigint): Promise<void>;
1087
- /**
1088
- * Quote the LayerZero native fee required for async vault actions.
1089
- *
1090
- * Call this before `depositAsync`, `mintAsync`, or `redeemAsync` to get the
1091
- * exact `lzFee` (msg.value) needed.
1092
- *
1093
- * @param publicClient Public client for reads
1094
- * @param vault Vault address (diamond proxy)
1095
- * @param extraOptions Optional LZ extra options bytes (default 0x)
1096
- * @returns Required native fee in wei
1097
- */
1098
- declare function quoteLzFee(publicClient: PublicClient, vault: Address, extraOptions?: `0x${string}`): Promise<bigint>;
1099
- /**
1100
- * Check if a vault is operating in async mode (cross-chain hub with oracle OFF).
1101
- *
1102
- * When this returns `true`, deposits and redeems must use the async flows
1103
- * (D4/D5/R5) which go through `initVaultActionRequest`.
1104
- * When `false`, the vault either uses oracle-based accounting (sync) or is
1105
- * a single-chain vault.
1106
- *
1107
- * @param publicClient Public client for reads
1108
- * @param vault Vault address
1109
- * @returns `true` if the vault requires async cross-chain flows
1110
- */
1111
- declare function isAsyncMode(publicClient: PublicClient, vault: Address): Promise<boolean>;
1112
- /**
1113
- * Poll for async request completion status.
1114
- *
1115
- * After calling an async flow (D4/D5/R5), use this to check whether the
1116
- * LZ callback has resolved and `executeRequest` has been called.
1117
- *
1118
- * @param publicClient Public client for reads
1119
- * @param vault Vault address
1120
- * @param guid Request GUID returned by the async flow
1121
- * @returns Whether the request is fulfilled and the finalization result
1122
- */
1123
- declare function getAsyncRequestStatus(publicClient: PublicClient, vault: Address, guid: `0x${string}`): Promise<{
1124
- fulfilled: boolean;
1125
- finalized: boolean;
1126
- result: bigint;
1127
- }>;
1128
-
1129
982
  /**
1130
983
  * Pre-flight validation helpers for MoreVaults SDK flows.
1131
984
  *
@@ -1184,141 +1037,6 @@ declare function preflightRedeemLiquidity(publicClient: PublicClient, vault: Add
1184
1037
  */
1185
1038
  declare function preflightSync(publicClient: PublicClient, vault: Address): Promise<void>;
1186
1039
 
1187
- interface UserPosition {
1188
- /** Vault share balance */
1189
- shares: bigint;
1190
- /** convertToAssets(shares) — what they'd get if they redeemed now */
1191
- estimatedAssets: bigint;
1192
- /** Price of 1 full share in underlying (convertToAssets(10n ** decimals)) */
1193
- sharePrice: bigint;
1194
- /** Vault decimals (for display) */
1195
- decimals: number;
1196
- pendingWithdrawal: {
1197
- shares: bigint;
1198
- timelockEndsAt: bigint;
1199
- /** block.timestamp >= timelockEndsAt (or timelockEndsAt === 0n) */
1200
- canRedeemNow: boolean;
1201
- } | null;
1202
- }
1203
- /**
1204
- * Read the user's current position in the vault.
1205
- *
1206
- * @param publicClient Public client for reads
1207
- * @param vault Vault address (diamond proxy)
1208
- * @param user User wallet address
1209
- * @returns Full user position snapshot
1210
- */
1211
- declare function getUserPosition(publicClient: PublicClient, vault: Address, user: Address): Promise<UserPosition>;
1212
- /**
1213
- * Preview how many shares a given asset amount would mint.
1214
- *
1215
- * @param publicClient Public client for reads
1216
- * @param vault Vault address
1217
- * @param assets Amount of underlying tokens to deposit
1218
- * @returns Estimated shares to be minted
1219
- */
1220
- declare function previewDeposit(publicClient: PublicClient, vault: Address, assets: bigint): Promise<bigint>;
1221
- /**
1222
- * Preview how many underlying assets a given share amount would redeem.
1223
- *
1224
- * @param publicClient Public client for reads
1225
- * @param vault Vault address
1226
- * @param shares Amount of vault shares to redeem
1227
- * @returns Estimated assets to be returned
1228
- */
1229
- declare function previewRedeem(publicClient: PublicClient, vault: Address, shares: bigint): Promise<bigint>;
1230
- type DepositBlockReason = 'paused' | 'capacity-full' | 'not-whitelisted' | 'ok';
1231
- interface DepositEligibility {
1232
- allowed: boolean;
1233
- reason: DepositBlockReason;
1234
- }
1235
- /**
1236
- * Check whether a user is eligible to deposit into the vault right now.
1237
- *
1238
- * @param publicClient Public client for reads
1239
- * @param vault Vault address
1240
- * @param user User wallet address
1241
- * @returns Eligibility result with reason
1242
- */
1243
- declare function canDeposit(publicClient: PublicClient, vault: Address, user: Address): Promise<DepositEligibility>;
1244
- interface VaultMetadata {
1245
- name: string;
1246
- symbol: string;
1247
- decimals: number;
1248
- underlying: Address;
1249
- underlyingSymbol: string;
1250
- underlyingDecimals: number;
1251
- }
1252
- /**
1253
- * Read display metadata for a vault and its underlying token.
1254
- *
1255
- * @param publicClient Public client for reads
1256
- * @param vault Vault address
1257
- * @returns Vault and underlying token metadata
1258
- */
1259
- declare function getVaultMetadata(publicClient: PublicClient, vault: Address): Promise<VaultMetadata>;
1260
- type AsyncRequestStatus = 'pending' | 'ready-to-execute' | 'completed' | 'refunded';
1261
- interface AsyncRequestStatusInfo {
1262
- status: AsyncRequestStatus;
1263
- /** Human-readable description */
1264
- label: string;
1265
- /** Shares minted or assets returned (0 if still pending) */
1266
- result: bigint;
1267
- }
1268
- /**
1269
- * Get the human-readable status of an async cross-chain request.
1270
- *
1271
- * @param publicClient Public client for reads
1272
- * @param vault Vault address
1273
- * @param guid Request GUID returned by depositAsync / mintAsync / redeemAsync
1274
- * @returns Status info with label and result
1275
- */
1276
- declare function getAsyncRequestStatusLabel(publicClient: PublicClient, vault: Address, guid: `0x${string}`): Promise<AsyncRequestStatusInfo>;
1277
- interface UserBalances {
1278
- /** Vault shares the user holds */
1279
- shareBalance: bigint;
1280
- /** Underlying token balance in wallet (for deposit input) */
1281
- underlyingBalance: bigint;
1282
- /** convertToAssets(shareBalance) — vault position value */
1283
- estimatedAssets: bigint;
1284
- }
1285
- /**
1286
- * Read the user's token balances relevant to a vault.
1287
- *
1288
- * @param publicClient Public client for reads
1289
- * @param vault Vault address
1290
- * @param user User wallet address
1291
- * @returns Share balance, underlying wallet balance, and estimated assets
1292
- */
1293
- declare function getUserBalances(publicClient: PublicClient, vault: Address, user: Address): Promise<UserBalances>;
1294
- interface MaxWithdrawable {
1295
- /** How many shares can be redeemed right now */
1296
- shares: bigint;
1297
- /** How many underlying assets that corresponds to */
1298
- assets: bigint;
1299
- }
1300
- /**
1301
- * Calculate the maximum amount a user can withdraw from a vault right now.
1302
- *
1303
- * For hub vaults without oracle accounting, this is limited by hub liquidity.
1304
- * For local and oracle vaults, all assets are immediately redeemable.
1305
- *
1306
- * @param publicClient Public client for reads
1307
- * @param vault Vault address
1308
- * @param user User wallet address
1309
- * @returns Maximum withdrawable shares and assets
1310
- */
1311
- declare function getMaxWithdrawable(publicClient: PublicClient, vault: Address, user: Address): Promise<MaxWithdrawable>;
1312
- type VaultSummary = VaultStatus & VaultMetadata;
1313
- /**
1314
- * Get a combined snapshot of vault status and metadata in one call.
1315
- *
1316
- * @param publicClient Public client for reads
1317
- * @param vault Vault address
1318
- * @returns Merged VaultStatus and VaultMetadata
1319
- */
1320
- declare function getVaultSummary(publicClient: PublicClient, vault: Address): Promise<VaultSummary>;
1321
-
1322
1040
  /**
1323
1041
  * Cast a wagmi PublicClient to the SDK's expected type.
1324
1042
  * Use this in React components to avoid `as any` casts:
@@ -1333,4 +1051,4 @@ declare function getVaultSummary(publicClient: PublicClient, vault: Address): Pr
1333
1051
  */
1334
1052
  declare function asSdkClient(client: unknown): PublicClient;
1335
1053
 
1336
- export { ActionType, type ActionTypeValue, type AsyncRequestResult, type AsyncRequestStatus, type AsyncRequestStatusInfo, BRIDGE_ABI, CCManagerNotConfiguredError, CHAIN_IDS, CHAIN_ID_TO_EID, CONFIG_ABI, CapacityFullError, type CrossChainRequestInfo, type DepositBlockReason, type DepositEligibility, type DepositResult, EID_TO_CHAIN_ID, ERC20_ABI, EscrowNotConfiguredError, InsufficientLiquidityError, LZ_EIDS, METADATA_ABI, type MaxWithdrawable, MissingEscrowAddressError, MoreVaultsError, NotHubVaultError, NotWhitelistedError, OFT_ABI, type RedeemResult, type UserBalances, type UserPosition, VAULT_ABI, type VaultAddresses, type VaultMetadata, type VaultMode, VaultPausedError, type VaultStatus, type VaultSummary, WrongChainError, asSdkClient, bridgeSharesToHub, canDeposit, depositAsync, depositSimple as depositCrossChainOracleOn, depositFromSpoke, depositFromSpoke as depositFromSpokeAsync, depositMultiAsset, depositSimple, ensureAllowance, getAsyncRequestStatus, getAsyncRequestStatusLabel, getMaxWithdrawable, getUserBalances, getUserPosition, getVaultMetadata, getVaultStatus, getVaultSummary, getWithdrawalRequest, isAsyncMode, mintAsync, preflightAsync, preflightRedeemLiquidity, preflightSync, previewDeposit, previewRedeem, quoteDepositFromSpokeFee, quoteLzFee, redeemAsync, redeemShares, requestRedeem, smartDeposit, withdrawAssets };
1054
+ export { ActionType, type ActionTypeValue, type AsyncRequestResult, BRIDGE_ABI, CCManagerNotConfiguredError, CHAIN_IDS, CHAIN_ID_TO_EID, CONFIG_ABI, CapacityFullError, type CrossChainRequestInfo, type DepositResult, EID_TO_CHAIN_ID, ERC20_ABI, EscrowNotConfiguredError, InsufficientLiquidityError, LZ_EIDS, METADATA_ABI, MissingEscrowAddressError, MoreVaultsError, NotHubVaultError, NotWhitelistedError, OFT_ABI, type RedeemResult, VAULT_ABI, type VaultAddresses, VaultPausedError, WrongChainError, asSdkClient, bridgeSharesToHub, depositAsync, depositSimple as depositCrossChainOracleOn, depositFromSpoke, depositFromSpoke as depositFromSpokeAsync, depositMultiAsset, depositSimple, getWithdrawalRequest, mintAsync, preflightAsync, preflightRedeemLiquidity, preflightSync, quoteDepositFromSpokeFee, redeemAsync, redeemShares, requestRedeem, smartDeposit, withdrawAssets };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oydual31/more-vaults-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "TypeScript SDK for MoreVaults protocol — viem/wagmi and ethers.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -13,6 +13,11 @@
13
13
  "types": "./dist/ethers/index.d.ts",
14
14
  "import": "./dist/ethers/index.js",
15
15
  "require": "./dist/ethers/index.cjs"
16
+ },
17
+ "./react": {
18
+ "types": "./dist/react/index.d.ts",
19
+ "import": "./dist/react/index.js",
20
+ "require": "./dist/react/index.cjs"
16
21
  }
17
22
  },
18
23
  "files": [
@@ -26,18 +31,25 @@
26
31
  "prepublishOnly": "npm run build"
27
32
  },
28
33
  "dependencies": {
29
- "viem": "^2.21.0",
30
- "ethers": "^6.13.0"
34
+ "ethers": ">=6.0.0",
35
+ "viem": ">=2.0.0"
31
36
  },
32
37
  "devDependencies": {
38
+ "@tanstack/react-query": "^5.90.21",
33
39
  "@types/node": "^22.0.0",
40
+ "@types/react": "^18.3.28",
41
+ "react": "^18.3.1",
34
42
  "tsup": "^8.0.0",
35
43
  "tsx": "^4.19.0",
36
- "typescript": "^5.7.0"
44
+ "typescript": "^5.7.0",
45
+ "wagmi": "^2.19.5"
37
46
  },
38
47
  "peerDependencies": {
48
+ "@tanstack/react-query": ">=5.0.0",
49
+ "ethers": ">=6.0.0",
50
+ "react": ">=18.0.0",
39
51
  "viem": ">=2.0.0",
40
- "ethers": ">=6.0.0"
52
+ "wagmi": ">=2.0.0"
41
53
  },
42
54
  "peerDependenciesMeta": {
43
55
  "viem": {
@@ -45,6 +57,15 @@
45
57
  },
46
58
  "ethers": {
47
59
  "optional": true
60
+ },
61
+ "wagmi": {
62
+ "optional": true
63
+ },
64
+ "react": {
65
+ "optional": true
66
+ },
67
+ "@tanstack/react-query": {
68
+ "optional": true
48
69
  }
49
70
  }
50
71
  }
@@ -0,0 +1,26 @@
1
+ // MoreVaults SDK — React hooks (wagmi v2 + @tanstack/react-query v5)
2
+ // Peer dependencies: react >=18, wagmi >=2, @tanstack/react-query >=5
3
+
4
+ // --- Read hooks ---
5
+ export { useVaultStatus } from './useVaultStatus.js'
6
+ export type { VaultStatus } from './useVaultStatus.js'
7
+
8
+ export { useVaultMetadata } from './useVaultMetadata.js'
9
+ export type { VaultMetadata } from './useVaultMetadata.js'
10
+
11
+ export { useUserPosition } from './useUserPosition.js'
12
+ export type { UserPosition } from './useUserPosition.js'
13
+
14
+ export { useLzFee } from './useLzFee.js'
15
+
16
+ export { useAsyncRequestStatus } from './useAsyncRequestStatus.js'
17
+ export type { AsyncRequestStatusInfo } from './useAsyncRequestStatus.js'
18
+
19
+ // --- Action hooks ---
20
+ export { useOmniDeposit } from './useOmniDeposit.js'
21
+ export { useOmniRedeem } from './useOmniRedeem.js'
22
+ export { useDepositSimple } from './useDepositSimple.js'
23
+ export { useRedeemShares } from './useRedeemShares.js'
24
+
25
+ // --- Smart (auto-routing) hooks ---
26
+ export { useSmartDeposit } from './useSmartDeposit.js'
@@ -0,0 +1,36 @@
1
+ import { useQuery } from '@tanstack/react-query'
2
+ import { usePublicClient } from 'wagmi'
3
+ import { asSdkClient, getAsyncRequestStatusLabel } from '../viem/index.js'
4
+ import type { AsyncRequestStatusInfo } from '../viem/index.js'
5
+
6
+ export type { AsyncRequestStatusInfo }
7
+
8
+ /**
9
+ * Poll the status of an async cross-chain request (D4/D5/R5) by GUID.
10
+ *
11
+ * Automatically stops polling when status reaches 'completed' or 'refunded'.
12
+ * Polls every 10s while the request is still pending or ready-to-execute.
13
+ *
14
+ * @example
15
+ * const { data } = useAsyncRequestStatus('0xVAULT', guid, 747)
16
+ * // data.status: 'pending' | 'ready-to-execute' | 'completed' | 'refunded'
17
+ * // data.label: human-readable description
18
+ * // data.result: shares minted or assets returned (0n while pending)
19
+ */
20
+ export function useAsyncRequestStatus(
21
+ vault: `0x${string}` | undefined,
22
+ guid: `0x${string}` | undefined,
23
+ chainId: number,
24
+ ) {
25
+ const publicClient = usePublicClient({ chainId })
26
+ return useQuery<AsyncRequestStatusInfo>({
27
+ queryKey: ['asyncRequestStatus', vault, guid, chainId],
28
+ queryFn: () => getAsyncRequestStatusLabel(asSdkClient(publicClient), vault!, guid!),
29
+ enabled: !!vault && !!guid && !!publicClient,
30
+ refetchInterval: (query) => {
31
+ const status = query.state.data?.status
32
+ if (status === 'completed' || status === 'refunded') return false
33
+ return 10_000
34
+ },
35
+ })
36
+ }
@@ -0,0 +1,76 @@
1
+ import { useState, useCallback } from 'react'
2
+ import { usePublicClient, useWalletClient } from 'wagmi'
3
+ import { asSdkClient, depositSimple } from '../viem/index.js'
4
+ import type { DepositResult } from '../viem/index.js'
5
+
6
+ interface UseDepositSimpleReturn {
7
+ /** Execute approve + depositSimple (D1/D3 flows). */
8
+ deposit: (amountInWei: bigint, receiver: `0x${string}`) => Promise<void>
9
+ isLoading: boolean
10
+ txHash: `0x${string}` | undefined
11
+ /** Shares minted. Available after tx confirmation. */
12
+ shares: bigint | undefined
13
+ error: Error | undefined
14
+ reset: () => void
15
+ }
16
+
17
+ /**
18
+ * Hook for local and oracle-on cross-chain vaults (D1/D3 flows).
19
+ *
20
+ * Simpler than useOmniDeposit — no LZ fee, no GUID, no polling.
21
+ * One approve + one deposit transaction.
22
+ *
23
+ * @example
24
+ * const { deposit, isLoading, txHash, shares } = useDepositSimple('0xVAULT', 747)
25
+ * await deposit(parseUnits('100', 6), userAddress)
26
+ */
27
+ export function useDepositSimple(
28
+ vault: `0x${string}` | undefined,
29
+ chainId: number,
30
+ ): UseDepositSimpleReturn {
31
+ const { data: walletClient } = useWalletClient({ chainId })
32
+ const publicClient = usePublicClient({ chainId })
33
+
34
+ const [isLoading, setIsLoading] = useState(false)
35
+ const [result, setResult] = useState<DepositResult | undefined>()
36
+ const [error, setError] = useState<Error | undefined>()
37
+
38
+ const deposit = useCallback(
39
+ async (amountInWei: bigint, receiver: `0x${string}`) => {
40
+ if (!vault || !walletClient || !publicClient) return
41
+ setIsLoading(true)
42
+ setError(undefined)
43
+ try {
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ const res = await depositSimple(
46
+ walletClient as any,
47
+ asSdkClient(publicClient),
48
+ { vault, hubChainId: chainId },
49
+ amountInWei,
50
+ receiver,
51
+ )
52
+ setResult(res)
53
+ } catch (err) {
54
+ setError(err instanceof Error ? err : new Error(String(err)))
55
+ } finally {
56
+ setIsLoading(false)
57
+ }
58
+ },
59
+ [vault, walletClient, publicClient, chainId],
60
+ )
61
+
62
+ const reset = useCallback(() => {
63
+ setResult(undefined)
64
+ setError(undefined)
65
+ setIsLoading(false)
66
+ }, [])
67
+
68
+ return {
69
+ deposit,
70
+ isLoading,
71
+ txHash: result?.txHash,
72
+ shares: result?.shares,
73
+ error,
74
+ reset,
75
+ }
76
+ }
@@ -0,0 +1,27 @@
1
+ import { useQuery } from '@tanstack/react-query'
2
+ import { usePublicClient } from 'wagmi'
3
+ import { asSdkClient, quoteLzFee } from '../viem/index.js'
4
+
5
+ /**
6
+ * Quote the LayerZero fee required for async operations (D4, D5, R5).
7
+ * Refreshes every 60s — fees change with network congestion.
8
+ *
9
+ * @example
10
+ * const { fee, feeWithBuffer } = useLzFee('0xVAULT', 747)
11
+ * // feeWithBuffer adds 1% buffer automatically (fee * 101 / 100)
12
+ */
13
+ export function useLzFee(vault: `0x${string}` | undefined, chainId: number) {
14
+ const publicClient = usePublicClient({ chainId })
15
+ const query = useQuery({
16
+ queryKey: ['lzFee', vault, chainId],
17
+ queryFn: () => quoteLzFee(asSdkClient(publicClient), vault!),
18
+ enabled: !!vault && !!publicClient,
19
+ refetchInterval: 60_000,
20
+ staleTime: 30_000,
21
+ })
22
+ return {
23
+ ...query,
24
+ fee: query.data,
25
+ feeWithBuffer: query.data ? (query.data * 101n) / 100n : undefined,
26
+ }
27
+ }
@@ -0,0 +1,97 @@
1
+ import { useState, useCallback } from 'react'
2
+ import { usePublicClient, useWalletClient, useChainId } from 'wagmi'
3
+ import {
4
+ asSdkClient,
5
+ depositAsync,
6
+ getVaultStatus,
7
+ } from '../viem/index.js'
8
+ import type { AsyncRequestStatusInfo } from '../viem/index.js'
9
+ import { useLzFee } from './useLzFee.js'
10
+ import { useAsyncRequestStatus } from './useAsyncRequestStatus.js'
11
+
12
+ interface UseOmniDepositReturn {
13
+ /** Execute approve + depositAsync. Handles everything internally. */
14
+ deposit: (amountInWei: bigint, receiver: `0x${string}`) => Promise<void>
15
+ isLoading: boolean
16
+ txHash: `0x${string}` | undefined
17
+ /** GUID for cross-chain tracking. Available after tx confirmation. */
18
+ guid: `0x${string}` | undefined
19
+ /** Cross-chain request status. undefined until a guid is available. */
20
+ requestStatus: AsyncRequestStatusInfo | undefined
21
+ /** true when the wallet is connected to the wrong chain */
22
+ wrongChain: boolean
23
+ error: Error | undefined
24
+ reset: () => void
25
+ }
26
+
27
+ /**
28
+ * Complete hook for async deposits on hub vaults (D4 flow).
29
+ *
30
+ * Handles: fee quote, chain validation, approve, depositAsync, and GUID polling.
31
+ * The deposit function wraps the entire flow — callers only pass amount + receiver.
32
+ *
33
+ * @example
34
+ * const { deposit, isLoading, guid, requestStatus, wrongChain } = useOmniDeposit('0xVAULT', 747)
35
+ *
36
+ * if (wrongChain) return <SwitchNetworkButton chainId={747} />
37
+ *
38
+ * await deposit(parseUnits('100', 6), userAddress)
39
+ * // requestStatus.status goes: 'pending' → 'completed' | 'refunded'
40
+ */
41
+ export function useOmniDeposit(
42
+ vault: `0x${string}` | undefined,
43
+ hubChainId: number,
44
+ ): UseOmniDepositReturn {
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ const { data: walletClient } = useWalletClient({ chainId: hubChainId })
47
+ const publicClient = usePublicClient({ chainId: hubChainId })
48
+ const currentChainId = useChainId()
49
+
50
+ const [isLoading, setIsLoading] = useState(false)
51
+ const [txHash, setTxHash] = useState<`0x${string}` | undefined>()
52
+ const [guid, setGuid] = useState<`0x${string}` | undefined>()
53
+ const [error, setError] = useState<Error | undefined>()
54
+
55
+ const { feeWithBuffer } = useLzFee(vault, hubChainId)
56
+ const { data: requestStatus } = useAsyncRequestStatus(vault, guid, hubChainId)
57
+
58
+ const wrongChain = currentChainId !== hubChainId
59
+
60
+ const deposit = useCallback(
61
+ async (amountInWei: bigint, receiver: `0x${string}`) => {
62
+ if (!vault || !walletClient || !publicClient || !feeWithBuffer) return
63
+ setIsLoading(true)
64
+ setError(undefined)
65
+ try {
66
+ const pc = asSdkClient(publicClient)
67
+ const status = await getVaultStatus(pc, vault)
68
+ // walletClient from wagmi is structurally compatible with viem WalletClient
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
+ const result = await depositAsync(
71
+ walletClient as any,
72
+ pc,
73
+ { vault, escrow: status.escrow, hubChainId },
74
+ amountInWei,
75
+ receiver,
76
+ feeWithBuffer,
77
+ )
78
+ setTxHash(result.txHash)
79
+ setGuid(result.guid)
80
+ } catch (err) {
81
+ setError(err instanceof Error ? err : new Error(String(err)))
82
+ } finally {
83
+ setIsLoading(false)
84
+ }
85
+ },
86
+ [vault, walletClient, publicClient, feeWithBuffer, hubChainId],
87
+ )
88
+
89
+ const reset = useCallback(() => {
90
+ setTxHash(undefined)
91
+ setGuid(undefined)
92
+ setError(undefined)
93
+ setIsLoading(false)
94
+ }, [])
95
+
96
+ return { deposit, isLoading, txHash, guid, requestStatus, wrongChain, error, reset }
97
+ }