@oydual31/more-vaults-sdk 0.4.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +94 -0
  2. package/dist/{spokeRoutes-B8Lnk-t4.d.cts → curatorBridge-CNs59kT9.d.cts} +222 -1
  3. package/dist/{spokeRoutes-B8Lnk-t4.d.ts → curatorBridge-CNs59kT9.d.ts} +222 -1
  4. package/dist/ethers/index.cjs +328 -3
  5. package/dist/ethers/index.cjs.map +1 -1
  6. package/dist/ethers/index.d.cts +279 -1
  7. package/dist/ethers/index.d.ts +279 -1
  8. package/dist/ethers/index.js +318 -5
  9. package/dist/ethers/index.js.map +1 -1
  10. package/dist/react/index.cjs +375 -0
  11. package/dist/react/index.cjs.map +1 -1
  12. package/dist/react/index.d.cts +266 -2
  13. package/dist/react/index.d.ts +266 -2
  14. package/dist/react/index.js +372 -2
  15. package/dist/react/index.js.map +1 -1
  16. package/dist/viem/index.cjs +377 -0
  17. package/dist/viem/index.cjs.map +1 -1
  18. package/dist/viem/index.d.cts +261 -3
  19. package/dist/viem/index.d.ts +261 -3
  20. package/dist/viem/index.js +367 -2
  21. package/dist/viem/index.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/ethers/abis.ts +24 -0
  24. package/src/ethers/curatorBridge.ts +235 -0
  25. package/src/ethers/curatorSubVaults.ts +443 -0
  26. package/src/ethers/index.ts +26 -0
  27. package/src/ethers/types.ts +99 -0
  28. package/src/react/index.ts +14 -0
  29. package/src/react/useCuratorBridgeQuote.ts +43 -0
  30. package/src/react/useERC7540RequestStatus.ts +43 -0
  31. package/src/react/useExecuteBridge.ts +50 -0
  32. package/src/react/useSubVaultPositions.ts +35 -0
  33. package/src/react/useVaultPortfolio.ts +35 -0
  34. package/src/viem/abis.ts +24 -0
  35. package/src/viem/curatorBridge.ts +288 -0
  36. package/src/viem/curatorSubVaults.ts +514 -0
  37. package/src/viem/index.ts +23 -0
  38. package/src/viem/types.ts +100 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oydual31/more-vaults-sdk",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "description": "TypeScript SDK for MoreVaults protocol — viem/wagmi and ethers.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -177,3 +177,27 @@ export const REGISTRY_ABI = [
177
177
  "function isBridgeAllowed(address bridge) view returns (bool)",
178
178
  "function getAllowedFacets() view returns (address[])",
179
179
  ] as const;
180
+
181
+ /**
182
+ * Sub-vault ABI — reads for ERC4626/ERC7540 sub-vaults and ConfigurationFacet extensions.
183
+ * Used by curator sub-vault portfolio helpers (Phase 5).
184
+ */
185
+ export const SUB_VAULT_ABI = [
186
+ // ConfigurationFacet reads — called on the MoreVaults diamond proxy
187
+ "function tokensHeld(bytes32 id) view returns (address[])",
188
+ "function lockedTokensAmountOfAsset(address asset) view returns (uint256)",
189
+
190
+ // ERC4626 standard reads — called on the sub-vault contract
191
+ "function convertToAssets(uint256 shares) view returns (uint256)",
192
+ "function convertToShares(uint256 assets) view returns (uint256)",
193
+ "function previewDeposit(uint256 assets) view returns (uint256)",
194
+ "function previewRedeem(uint256 shares) view returns (uint256)",
195
+ "function maxDeposit(address receiver) view returns (uint256)",
196
+ "function maxRedeem(address owner) view returns (uint256)",
197
+
198
+ // ERC7540 async reads — called on the sub-vault contract
199
+ "function pendingDepositRequest(uint256 requestId, address controller) view returns (uint256)",
200
+ "function claimableDepositRequest(uint256 requestId, address controller) view returns (uint256)",
201
+ "function pendingRedeemRequest(uint256 requestId, address controller) view returns (uint256)",
202
+ "function claimableRedeemRequest(uint256 requestId, address controller) view returns (uint256)",
203
+ ] as const;
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Curator BridgeFacet helpers for the MoreVaults ethers.js v6 SDK.
3
+ *
4
+ * Provides typed helpers to quote and execute cross-chain asset bridging
5
+ * via BridgeFacet.executeBridging on any MoreVaults diamond.
6
+ *
7
+ * Key flows:
8
+ * 1. `quoteCuratorBridgeFee` — read-only fee estimation via LzAdapter
9
+ * 2. `executeCuratorBridge` — send bridging transaction (curator only)
10
+ * 3. `encodeBridgeParams` — encode the 5-field bridgeSpecificParams bytes
11
+ * 4. `findBridgeRoute` — resolve OFT route for a token on given chains
12
+ *
13
+ * @module curatorBridge
14
+ */
15
+
16
+ import { AbiCoder, Contract, getAddress } from "ethers";
17
+ import type { Provider, Signer, ContractTransactionReceipt } from "ethers";
18
+ import { BRIDGE_FACET_ABI, LZ_ADAPTER_ABI } from "./abis";
19
+ import { OFT_ROUTES } from "./chains";
20
+ import { getCuratorVaultStatus } from "./curatorStatus";
21
+
22
+ // ─────────────────────────────────────────────────────────────────────────────
23
+ // Types
24
+ // ─────────────────────────────────────────────────────────────────────────────
25
+
26
+ /**
27
+ * Parameters for a curator bridge operation.
28
+ */
29
+ export interface CuratorBridgeParams {
30
+ /** OFT contract address on the source chain (from OFT_ROUTES[symbol][chainId].oft) */
31
+ oftToken: string;
32
+ /** LayerZero endpoint ID of the destination chain */
33
+ dstEid: number;
34
+ /** Amount to bridge (in token's native units) */
35
+ amount: bigint;
36
+ /** Vault address on the destination chain (hub or spoke) */
37
+ dstVault: string;
38
+ /** Address where excess LayerZero gas refunds are sent (usually the curator wallet) */
39
+ refundAddress: string;
40
+ }
41
+
42
+ // ─────────────────────────────────────────────────────────────────────────────
43
+ // Encoding helpers
44
+ // ─────────────────────────────────────────────────────────────────────────────
45
+
46
+ /**
47
+ * Encode the 5-field bridgeSpecificParams for use in `executeBridging`.
48
+ *
49
+ * Encodes: (oftToken, dstEid, amount, dstVault, refundAddress)
50
+ * Types: (address, uint32, uint256, address, address)
51
+ *
52
+ * @param params Full bridge parameters including refundAddress
53
+ * @returns ABI-encoded hex string
54
+ */
55
+ export function encodeBridgeParams(params: CuratorBridgeParams): string {
56
+ const coder = AbiCoder.defaultAbiCoder();
57
+ return coder.encode(
58
+ ["address", "uint32", "uint256", "address", "address"],
59
+ [
60
+ getAddress(params.oftToken),
61
+ params.dstEid,
62
+ params.amount,
63
+ getAddress(params.dstVault),
64
+ getAddress(params.refundAddress),
65
+ ]
66
+ );
67
+ }
68
+
69
+ /**
70
+ * Encode the 4-field bridgeSpecificParams for `quoteBridgeFee`.
71
+ * Does NOT include refundAddress — quoting only needs routing parameters.
72
+ *
73
+ * @internal
74
+ */
75
+ function encodeBridgeParamsForQuote(
76
+ params: Omit<CuratorBridgeParams, "refundAddress">
77
+ ): string {
78
+ const coder = AbiCoder.defaultAbiCoder();
79
+ return coder.encode(
80
+ ["address", "uint32", "uint256", "address"],
81
+ [
82
+ getAddress(params.oftToken),
83
+ params.dstEid,
84
+ params.amount,
85
+ getAddress(params.dstVault),
86
+ ]
87
+ );
88
+ }
89
+
90
+ // ─────────────────────────────────────────────────────────────────────────────
91
+ // Route resolver
92
+ // ─────────────────────────────────────────────────────────────────────────────
93
+
94
+ /**
95
+ * Find the OFT bridge route for a given token address on the source chain.
96
+ *
97
+ * Searches OFT_ROUTES for an asset whose `token` or `oft` field matches
98
+ * the provided address on the given source chainId.
99
+ *
100
+ * @param srcChainId EVM chain ID of the source chain
101
+ * @param dstChainId EVM chain ID of the destination chain
102
+ * @param tokenAddress ERC-20 token address on the source chain
103
+ * @returns Route info or null if no matching route exists
104
+ */
105
+ export function findBridgeRoute(
106
+ srcChainId: number,
107
+ dstChainId: number,
108
+ tokenAddress: string
109
+ ): { oftSrc: string; oftDst: string; symbol: string } | null {
110
+ const normalizedToken = getAddress(tokenAddress);
111
+
112
+ for (const [symbol, chains] of Object.entries(OFT_ROUTES)) {
113
+ const srcEntry = (
114
+ chains as Record<number, { oft: string; token: string }>
115
+ )[srcChainId];
116
+ const dstEntry = (
117
+ chains as Record<number, { oft: string; token: string }>
118
+ )[dstChainId];
119
+
120
+ if (!srcEntry || !dstEntry) continue;
121
+
122
+ const srcToken = getAddress(srcEntry.token);
123
+ const srcOft = getAddress(srcEntry.oft);
124
+
125
+ if (srcToken === normalizedToken || srcOft === normalizedToken) {
126
+ return {
127
+ oftSrc: srcOft,
128
+ oftDst: getAddress(dstEntry.oft),
129
+ symbol,
130
+ };
131
+ }
132
+ }
133
+
134
+ return null;
135
+ }
136
+
137
+ // ─────────────────────────────────────────────────────────────────────────────
138
+ // Read operations
139
+ // ─────────────────────────────────────────────────────────────────────────────
140
+
141
+ /**
142
+ * Quote the native fee required to bridge assets via the vault's LzAdapter.
143
+ *
144
+ * Calls `lzAdapter.quoteBridgeFee(bridgeSpecificParams)` using a 4-field
145
+ * encoding (no refundAddress). The returned fee must be sent as `value`
146
+ * when calling `executeBridging`.
147
+ *
148
+ * @param provider Read-only provider (must be on the vault's chain)
149
+ * @param vault Hub vault address (diamond proxy)
150
+ * @param params Bridge parameters (refundAddress is included but not encoded for quote)
151
+ * @returns Native fee in wei
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * const fee = await quoteCuratorBridgeFee(provider, VAULT, {
156
+ * oftToken: '0x27a16dc786820B16E5c9028b75B99F6f604b5d26',
157
+ * dstEid: 30101,
158
+ * amount: 1_000_000n,
159
+ * dstVault: '0xSpokeVault...',
160
+ * refundAddress: '0xCurator...',
161
+ * })
162
+ * ```
163
+ */
164
+ export async function quoteCuratorBridgeFee(
165
+ provider: Provider,
166
+ vault: string,
167
+ params: CuratorBridgeParams
168
+ ): Promise<bigint> {
169
+ const status = await getCuratorVaultStatus(provider, vault);
170
+ const lzAdapter = status.lzAdapter;
171
+
172
+ const bridgeSpecificParams = encodeBridgeParamsForQuote(params);
173
+
174
+ const adapterContract = new Contract(lzAdapter, LZ_ADAPTER_ABI, provider);
175
+ const nativeFee = (await adapterContract.quoteBridgeFee.staticCall(
176
+ bridgeSpecificParams
177
+ )) as bigint;
178
+
179
+ return nativeFee;
180
+ }
181
+
182
+ // ─────────────────────────────────────────────────────────────────────────────
183
+ // Write operations
184
+ // ─────────────────────────────────────────────────────────────────────────────
185
+
186
+ /**
187
+ * Execute a curator bridge operation via `BridgeFacet.executeBridging`.
188
+ *
189
+ * This is a direct curator call (NOT via multicall). The vault pauses during
190
+ * bridging for security. The `token` parameter is the underlying ERC-20,
191
+ * NOT the OFT address.
192
+ *
193
+ * Steps:
194
+ * 1. Get lzAdapter from `getCuratorVaultStatus`
195
+ * 2. Quote the native bridge fee
196
+ * 3. Encode 5-field bridgeSpecificParams
197
+ * 4. Call `vault.executeBridging(adapter, token, amount, bridgeSpecificParams)` with fee as value
198
+ *
199
+ * @param signer Signer with curator account attached
200
+ * @param vault Hub vault address (diamond proxy)
201
+ * @param token Underlying ERC-20 token address (NOT the OFT address)
202
+ * @param params Full bridge parameters including refundAddress
203
+ * @returns Transaction receipt
204
+ * @throws If caller is not curator, vault is paused, or bridge fails
205
+ */
206
+ export async function executeCuratorBridge(
207
+ signer: Signer,
208
+ vault: string,
209
+ token: string,
210
+ params: CuratorBridgeParams
211
+ ): Promise<ContractTransactionReceipt> {
212
+ const provider = signer.provider!;
213
+
214
+ // Step 1: Get lzAdapter address from vault status
215
+ const status = await getCuratorVaultStatus(provider, vault);
216
+ const lzAdapter = status.lzAdapter;
217
+
218
+ // Step 2: Quote the bridge fee
219
+ const fee = await quoteCuratorBridgeFee(provider, vault, params);
220
+
221
+ // Step 3: Encode full 5-field bridgeSpecificParams
222
+ const bridgeSpecificParams = encodeBridgeParams(params);
223
+
224
+ // Step 4: Execute bridging
225
+ const vaultContract = new Contract(vault, BRIDGE_FACET_ABI, signer);
226
+ const tx = await vaultContract.executeBridging(
227
+ getAddress(lzAdapter),
228
+ getAddress(token),
229
+ params.amount,
230
+ bridgeSpecificParams,
231
+ { value: fee }
232
+ );
233
+
234
+ return tx.wait() as Promise<ContractTransactionReceipt>;
235
+ }