@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.
@@ -0,0 +1,96 @@
1
+ import { useState, useCallback } from 'react'
2
+ import { usePublicClient, useWalletClient, useChainId } from 'wagmi'
3
+ import {
4
+ asSdkClient,
5
+ redeemAsync,
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 UseOmniRedeemReturn {
13
+ /** Execute approve + redeemAsync. Handles everything internally. */
14
+ redeem: (sharesInWei: bigint, receiver: `0x${string}`, owner: `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 redeems on hub vaults (R5 flow).
29
+ *
30
+ * Handles: fee quote, chain validation, share approve, redeemAsync, and GUID polling.
31
+ *
32
+ * @example
33
+ * const { redeem, isLoading, guid, requestStatus, wrongChain } = useOmniRedeem('0xVAULT', 747)
34
+ *
35
+ * if (wrongChain) return <SwitchNetworkButton chainId={747} />
36
+ *
37
+ * await redeem(sharesInWei, userAddress, userAddress)
38
+ * // requestStatus.status goes: 'pending' → 'completed' | 'refunded'
39
+ */
40
+ export function useOmniRedeem(
41
+ vault: `0x${string}` | undefined,
42
+ hubChainId: number,
43
+ ): UseOmniRedeemReturn {
44
+ const { data: walletClient } = useWalletClient({ chainId: hubChainId })
45
+ const publicClient = usePublicClient({ chainId: hubChainId })
46
+ const currentChainId = useChainId()
47
+
48
+ const [isLoading, setIsLoading] = useState(false)
49
+ const [txHash, setTxHash] = useState<`0x${string}` | undefined>()
50
+ const [guid, setGuid] = useState<`0x${string}` | undefined>()
51
+ const [error, setError] = useState<Error | undefined>()
52
+
53
+ const { feeWithBuffer } = useLzFee(vault, hubChainId)
54
+ const { data: requestStatus } = useAsyncRequestStatus(vault, guid, hubChainId)
55
+
56
+ const wrongChain = currentChainId !== hubChainId
57
+
58
+ const redeem = useCallback(
59
+ async (sharesInWei: bigint, receiver: `0x${string}`, owner: `0x${string}`) => {
60
+ if (!vault || !walletClient || !publicClient || !feeWithBuffer) return
61
+ setIsLoading(true)
62
+ setError(undefined)
63
+ try {
64
+ const pc = asSdkClient(publicClient)
65
+ const status = await getVaultStatus(pc, vault)
66
+ // walletClient from wagmi is structurally compatible with viem WalletClient
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ const result = await redeemAsync(
69
+ walletClient as any,
70
+ pc,
71
+ { vault, escrow: status.escrow, hubChainId },
72
+ sharesInWei,
73
+ receiver,
74
+ owner,
75
+ feeWithBuffer,
76
+ )
77
+ setTxHash(result.txHash)
78
+ setGuid(result.guid)
79
+ } catch (err) {
80
+ setError(err instanceof Error ? err : new Error(String(err)))
81
+ } finally {
82
+ setIsLoading(false)
83
+ }
84
+ },
85
+ [vault, walletClient, publicClient, feeWithBuffer, hubChainId],
86
+ )
87
+
88
+ const reset = useCallback(() => {
89
+ setTxHash(undefined)
90
+ setGuid(undefined)
91
+ setError(undefined)
92
+ setIsLoading(false)
93
+ }, [])
94
+
95
+ return { redeem, isLoading, txHash, guid, requestStatus, wrongChain, error, reset }
96
+ }
@@ -0,0 +1,77 @@
1
+ import { useState, useCallback } from 'react'
2
+ import { usePublicClient, useWalletClient } from 'wagmi'
3
+ import { asSdkClient, redeemShares } from '../viem/index.js'
4
+ import type { RedeemResult } from '../viem/index.js'
5
+
6
+ interface UseRedeemSharesReturn {
7
+ /** Execute redeemShares (R1 flow). */
8
+ redeem: (sharesInWei: bigint, receiver: `0x${string}`, owner: `0x${string}`) => Promise<void>
9
+ isLoading: boolean
10
+ txHash: `0x${string}` | undefined
11
+ /** Assets received. Available after tx confirmation. */
12
+ assets: bigint | undefined
13
+ error: Error | undefined
14
+ reset: () => void
15
+ }
16
+
17
+ /**
18
+ * Hook for standard ERC-4626 share redemption (R1 flow).
19
+ *
20
+ * Used for local and oracle-on cross-chain vaults.
21
+ * No LZ fee required — single transaction.
22
+ *
23
+ * @example
24
+ * const { redeem, isLoading, txHash, assets } = useRedeemShares('0xVAULT', 747)
25
+ * await redeem(sharesInWei, userAddress, userAddress)
26
+ */
27
+ export function useRedeemShares(
28
+ vault: `0x${string}` | undefined,
29
+ chainId: number,
30
+ ): UseRedeemSharesReturn {
31
+ const { data: walletClient } = useWalletClient({ chainId })
32
+ const publicClient = usePublicClient({ chainId })
33
+
34
+ const [isLoading, setIsLoading] = useState(false)
35
+ const [result, setResult] = useState<RedeemResult | undefined>()
36
+ const [error, setError] = useState<Error | undefined>()
37
+
38
+ const redeem = useCallback(
39
+ async (sharesInWei: bigint, receiver: `0x${string}`, owner: `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 redeemShares(
46
+ walletClient as any,
47
+ asSdkClient(publicClient),
48
+ { vault, hubChainId: chainId },
49
+ sharesInWei,
50
+ receiver,
51
+ owner,
52
+ )
53
+ setResult(res)
54
+ } catch (err) {
55
+ setError(err instanceof Error ? err : new Error(String(err)))
56
+ } finally {
57
+ setIsLoading(false)
58
+ }
59
+ },
60
+ [vault, walletClient, publicClient, chainId],
61
+ )
62
+
63
+ const reset = useCallback(() => {
64
+ setResult(undefined)
65
+ setError(undefined)
66
+ setIsLoading(false)
67
+ }, [])
68
+
69
+ return {
70
+ redeem,
71
+ isLoading,
72
+ txHash: result?.txHash,
73
+ assets: result?.assets,
74
+ error,
75
+ reset,
76
+ }
77
+ }
@@ -0,0 +1,70 @@
1
+ import type { DepositResult, AsyncRequestResult, AsyncRequestStatusInfo } from '../viem/index.js'
2
+ import { useVaultStatus } from './useVaultStatus.js'
3
+ import { useOmniDeposit } from './useOmniDeposit.js'
4
+ import { useDepositSimple } from './useDepositSimple.js'
5
+
6
+ interface UseSmartDepositReturn {
7
+ /**
8
+ * Execute deposit using the correct flow for this vault's mode.
9
+ * For async vaults: wraps depositAsync (D4) — returns guid for tracking.
10
+ * For local/oracle vaults: wraps depositSimple (D1/D3) — returns shares.
11
+ */
12
+ deposit: (amountInWei: bigint, receiver: `0x${string}`) => Promise<void>
13
+ isLoading: boolean
14
+ txHash: `0x${string}` | undefined
15
+ /** Shares minted (available for D1/D3 vaults after confirmation, undefined for D4). */
16
+ shares: bigint | undefined
17
+ /** GUID for cross-chain tracking (D4 vaults only). */
18
+ guid: `0x${string}` | undefined
19
+ /** Cross-chain request status (D4 vaults only). */
20
+ requestStatus: AsyncRequestStatusInfo | undefined
21
+ /** true when the wallet is connected to the wrong chain (D4 vaults only). */
22
+ wrongChain: boolean
23
+ /** Vault mode loaded from getVaultStatus. undefined while loading. */
24
+ vaultMode: 'local' | 'cross-chain-oracle' | 'cross-chain-async' | 'paused' | 'full' | undefined
25
+ error: Error | undefined
26
+ reset: () => void
27
+ }
28
+
29
+ /**
30
+ * Auto-selects the correct deposit flow based on vault mode.
31
+ * Best for frontends that support multiple vault types.
32
+ *
33
+ * Internally uses useVaultStatus to detect the mode, then delegates to:
34
+ * - useOmniDeposit (D4) for 'cross-chain-async' vaults
35
+ * - useDepositSimple (D1/D3) for 'local' and 'cross-chain-oracle' vaults
36
+ *
37
+ * @example
38
+ * const { deposit, isLoading, guid, requestStatus, vaultMode } = useSmartDeposit('0xVAULT', 747)
39
+ *
40
+ * if (vaultMode === 'paused') return <PausedBadge />
41
+ *
42
+ * await deposit(parseUnits('100', 6), userAddress)
43
+ * // For async vaults: poll requestStatus until 'completed'
44
+ * // For sync vaults: txHash + shares are available immediately
45
+ */
46
+ export function useSmartDeposit(
47
+ vault: `0x${string}` | undefined,
48
+ hubChainId: number,
49
+ ): UseSmartDepositReturn {
50
+ const { data: status } = useVaultStatus(vault, hubChainId)
51
+ const omni = useOmniDeposit(vault, hubChainId)
52
+ const simple = useDepositSimple(vault, hubChainId)
53
+
54
+ const isAsync = status?.mode === 'cross-chain-async'
55
+
56
+ const deposit = isAsync ? omni.deposit : simple.deposit
57
+
58
+ return {
59
+ deposit,
60
+ isLoading: isAsync ? omni.isLoading : simple.isLoading,
61
+ txHash: isAsync ? omni.txHash : simple.txHash,
62
+ shares: isAsync ? undefined : simple.shares,
63
+ guid: isAsync ? omni.guid : undefined,
64
+ requestStatus: isAsync ? omni.requestStatus : undefined,
65
+ wrongChain: isAsync ? omni.wrongChain : false,
66
+ vaultMode: status?.mode,
67
+ error: isAsync ? omni.error : simple.error,
68
+ reset: isAsync ? omni.reset : simple.reset,
69
+ }
70
+ }
@@ -0,0 +1,29 @@
1
+ import { useQuery } from '@tanstack/react-query'
2
+ import { usePublicClient } from 'wagmi'
3
+ import { asSdkClient, getUserPosition } from '../viem/index.js'
4
+ import type { UserPosition } from '../viem/index.js'
5
+
6
+ export type { UserPosition }
7
+
8
+ /**
9
+ * Read the user's current position in a vault.
10
+ * Refetches every 15s to keep the balance display current.
11
+ *
12
+ * @example
13
+ * const { data: position } = useUserPosition('0xVAULT', '0xUSER', 747)
14
+ * // position.shares, position.estimatedAssets, position.pendingWithdrawal
15
+ */
16
+ export function useUserPosition(
17
+ vault: `0x${string}` | undefined,
18
+ user: `0x${string}` | undefined,
19
+ chainId: number,
20
+ ) {
21
+ const publicClient = usePublicClient({ chainId })
22
+ return useQuery({
23
+ queryKey: ['userPosition', vault, user, chainId],
24
+ queryFn: () => getUserPosition(asSdkClient(publicClient), vault!, user!),
25
+ enabled: !!vault && !!user && !!publicClient,
26
+ refetchInterval: 15_000,
27
+ staleTime: 10_000,
28
+ })
29
+ }
@@ -0,0 +1,29 @@
1
+ import { useQuery } from '@tanstack/react-query'
2
+ import { usePublicClient } from 'wagmi'
3
+ import { asSdkClient, getVaultMetadata } from '../viem/index.js'
4
+ import type { VaultMetadata } from '../viem/index.js'
5
+
6
+ export type { VaultMetadata }
7
+
8
+ /**
9
+ * Read display metadata for a vault and its underlying token.
10
+ * Uses a long stale time (5 min) because metadata rarely changes.
11
+ *
12
+ * @example
13
+ * const { data: meta } = useVaultMetadata('0xVAULT', 747)
14
+ * // meta.name, meta.symbol, meta.underlying, meta.underlyingSymbol
15
+ */
16
+ export function useVaultMetadata(
17
+ vault: `0x${string}` | undefined,
18
+ chainId: number,
19
+ ) {
20
+ const publicClient = usePublicClient({ chainId })
21
+ return useQuery({
22
+ queryKey: ['vaultMetadata', vault, chainId],
23
+ queryFn: () => getVaultMetadata(asSdkClient(publicClient), vault!),
24
+ enabled: !!vault && !!publicClient,
25
+ // Metadata (name, symbol, underlying) changes very rarely — 5 min stale time
26
+ staleTime: 5 * 60_000,
27
+ refetchInterval: 5 * 60_000,
28
+ })
29
+ }
@@ -0,0 +1,34 @@
1
+ import { useQuery } from '@tanstack/react-query'
2
+ import { usePublicClient } from 'wagmi'
3
+ import { asSdkClient, getVaultStatus } from '../viem/index.js'
4
+ import type { VaultStatus } from '../viem/index.js'
5
+
6
+ export type { VaultStatus }
7
+
8
+ interface UseVaultStatusOptions {
9
+ /** Refetch interval in ms. Default: 30_000 (30s) */
10
+ refetchInterval?: number
11
+ }
12
+
13
+ /**
14
+ * Read the full vault status snapshot.
15
+ * Automatically refetches on a configurable interval.
16
+ *
17
+ * @example
18
+ * const { data: status, isLoading } = useVaultStatus('0xVAULT', 747)
19
+ * if (status?.mode === 'cross-chain-async') { ... }
20
+ */
21
+ export function useVaultStatus(
22
+ vault: `0x${string}` | undefined,
23
+ chainId: number,
24
+ options?: UseVaultStatusOptions,
25
+ ) {
26
+ const publicClient = usePublicClient({ chainId })
27
+ return useQuery({
28
+ queryKey: ['vaultStatus', vault, chainId],
29
+ queryFn: () => getVaultStatus(asSdkClient(publicClient), vault!),
30
+ enabled: !!vault && !!publicClient,
31
+ refetchInterval: options?.refetchInterval ?? 30_000,
32
+ staleTime: 15_000,
33
+ })
34
+ }