@oydual31/more-vaults-sdk 0.2.0 → 0.2.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 +163 -75
- package/dist/ethers/index.cjs +62 -0
- package/dist/ethers/index.cjs.map +1 -1
- package/dist/ethers/index.d.cts +55 -1
- package/dist/ethers/index.d.ts +55 -1
- package/dist/ethers/index.js +60 -1
- package/dist/ethers/index.js.map +1 -1
- package/dist/react/index.cjs +168 -81
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +48 -7
- package/dist/react/index.d.ts +48 -7
- package/dist/react/index.js +168 -82
- package/dist/react/index.js.map +1 -1
- package/dist/{spokeRoutes-BFI1m_zk.d.cts → spokeRoutes-CK5NSOOF.d.cts} +26 -1
- package/dist/{spokeRoutes-BFI1m_zk.d.ts → spokeRoutes-CK5NSOOF.d.ts} +26 -1
- package/dist/viem/index.cjs +139 -87
- package/dist/viem/index.cjs.map +1 -1
- package/dist/viem/index.d.cts +1 -1
- package/dist/viem/index.d.ts +1 -1
- package/dist/viem/index.js +139 -88
- package/dist/viem/index.js.map +1 -1
- package/package.json +1 -1
- package/src/ethers/chains.ts +19 -0
- package/src/ethers/index.ts +3 -1
- package/src/ethers/redeemFlows.ts +109 -0
- package/src/react/index.ts +1 -0
- package/src/react/useSmartRedeem.ts +70 -0
- package/src/react/useVaultTopology.ts +14 -9
- package/src/viem/index.ts +1 -0
- package/src/viem/topology.ts +85 -1
package/README.md
CHANGED
|
@@ -8,10 +8,10 @@ npm install @oydual31/more-vaults-sdk
|
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
10
|
// viem / wagmi
|
|
11
|
-
import {
|
|
11
|
+
import { smartDeposit, smartRedeem, getVaultStatus } from '@oydual31/more-vaults-sdk/viem'
|
|
12
12
|
|
|
13
13
|
// ethers.js v6
|
|
14
|
-
import { getVaultStatus,
|
|
14
|
+
import { getVaultStatus, depositSimple } from '@oydual31/more-vaults-sdk/ethers'
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
---
|
|
@@ -44,8 +44,8 @@ Redeem 100 shares → receive 105 USDC
|
|
|
44
44
|
|
|
45
45
|
MoreVaults uses a **hub-and-spoke** model for cross-chain yield:
|
|
46
46
|
|
|
47
|
-
- **Hub** (`isHub = true`): the chain where the vault does its accounting — mints/burns shares, accepts deposits and redemptions. All SDK flows target the hub.
|
|
48
|
-
- **Spoke**: a position on another chain (Arbitrum, Base, etc.) where the vault has deployed funds for yield. Users on spoke chains bridge tokens to the hub via LayerZero OFT
|
|
47
|
+
- **Hub** (`isHub = true`): the chain where the vault does its accounting — mints/burns shares, accepts deposits and redemptions. All SDK flows target the hub.
|
|
48
|
+
- **Spoke**: a position on another chain (Arbitrum, Base, Ethereum, etc.) where the vault has deployed funds for yield. Users on spoke chains bridge tokens to the hub via LayerZero OFT.
|
|
49
49
|
|
|
50
50
|
If a vault has `isHub = false`, it is a single-chain vault — no cross-chain flows apply, use D1/R1.
|
|
51
51
|
|
|
@@ -79,11 +79,6 @@ This means:
|
|
|
79
79
|
|
|
80
80
|
**Repatriation** is the process of moving funds from spokes back to the hub so they become liquid again. This is a **manual, curator-only operation** (`executeBridging`). There is no automatic mechanism — the protocol does not pull funds from spokes on behalf of users.
|
|
81
81
|
|
|
82
|
-
If a redeem fails because the hub is under-funded:
|
|
83
|
-
1. The user's shares are returned automatically (or the tx reverts before any state change for R1).
|
|
84
|
-
2. The vault curator must repatriate liquidity from the spokes.
|
|
85
|
-
3. The user retries the redeem once sufficient liquidity is available on the hub.
|
|
86
|
-
|
|
87
82
|
### Withdrawal queue and timelock
|
|
88
83
|
|
|
89
84
|
Some vaults require shares to be "queued" before redemption:
|
|
@@ -107,9 +102,7 @@ const escrow = status.escrow // address(0) if not configured
|
|
|
107
102
|
|
|
108
103
|
### Same address on every chain (CREATE3)
|
|
109
104
|
|
|
110
|
-
MoreVaults deploys all contracts using **CREATE3**, which means a vault has the **same address on every chain** where it exists. If the hub vault on
|
|
111
|
-
|
|
112
|
-
This simplifies the frontend significantly — you don't need a separate address map per chain. One address identifies the vault everywhere.
|
|
105
|
+
MoreVaults deploys all contracts using **CREATE3**, which means a vault has the **same address on every chain** where it exists. If the hub vault on Base is `0xABC...`, the corresponding escrow and spoke-side contracts are also at predictable, identical addresses across Arbitrum, Ethereum, etc.
|
|
113
106
|
|
|
114
107
|
### VaultAddresses
|
|
115
108
|
|
|
@@ -118,13 +111,12 @@ Every flow function takes a `VaultAddresses` object:
|
|
|
118
111
|
```ts
|
|
119
112
|
interface VaultAddresses {
|
|
120
113
|
vault: Address // Vault address — same on every chain (CREATE3)
|
|
121
|
-
escrow
|
|
122
|
-
|
|
123
|
-
usdcOFT?: Address // OFT for the underlying token on the spoke — required for D6/D7
|
|
114
|
+
escrow?: Address // MoreVaultsEscrow — required for D4, D5, R5 (auto-resolved if omitted)
|
|
115
|
+
hubChainId?: number // Optional chain validation
|
|
124
116
|
}
|
|
125
117
|
```
|
|
126
118
|
|
|
127
|
-
For simple hub flows (D1, R1) you only need `vault`. For async flows
|
|
119
|
+
For simple hub flows (D1, R1) you only need `vault`. For async flows the SDK auto-resolves the escrow from the vault if not provided.
|
|
128
120
|
|
|
129
121
|
### LayerZero EID
|
|
130
122
|
|
|
@@ -132,10 +124,10 @@ LayerZero identifies chains by an **Endpoint ID (EID)** — different from the c
|
|
|
132
124
|
|
|
133
125
|
| Chain | Chain ID | LayerZero EID |
|
|
134
126
|
|-------|----------|---------------|
|
|
135
|
-
|
|
|
127
|
+
| Ethereum | 1 | 30101 |
|
|
136
128
|
| Arbitrum | 42161 | 30110 |
|
|
137
129
|
| Base | 8453 | 30184 |
|
|
138
|
-
|
|
|
130
|
+
| Flow EVM | 747 | 30332 |
|
|
139
131
|
|
|
140
132
|
### GUID (async request ID)
|
|
141
133
|
|
|
@@ -147,7 +139,6 @@ const { guid } = await depositAsync(...)
|
|
|
147
139
|
// Poll status
|
|
148
140
|
const info = await getAsyncRequestStatusLabel(publicClient, vault, guid)
|
|
149
141
|
// info.status: 'pending' | 'ready-to-execute' | 'completed' | 'refunded'
|
|
150
|
-
// info.result: shares minted or assets received once completed
|
|
151
142
|
```
|
|
152
143
|
|
|
153
144
|
---
|
|
@@ -177,88 +168,126 @@ const { data: walletClient } = useWalletClient()
|
|
|
177
168
|
| `new BrowserProvider(window.ethereum).getSigner()` | Browser — MetaMask or any injected wallet |
|
|
178
169
|
| `new Wallet(PRIVATE_KEY, new JsonRpcProvider(RPC_URL))` | Node.js — scripts, bots, backends |
|
|
179
170
|
|
|
180
|
-
Read-only helpers (`getUserPosition`, `previewDeposit`, etc.) accept a bare `Provider` in the ethers version — no signer needed.
|
|
181
|
-
|
|
182
171
|
> The client's chain must match the chain where the vault lives. Hub flows → the hub chain. Spoke deposit/redeem (D6/D7/R6) → the spoke chain.
|
|
183
172
|
|
|
184
173
|
---
|
|
185
174
|
|
|
186
|
-
## Quick start
|
|
175
|
+
## Quick start — Smart flows (recommended)
|
|
176
|
+
|
|
177
|
+
The simplest way to use the SDK. `smartDeposit` and `smartRedeem` auto-detect the vault type and use the correct flow.
|
|
187
178
|
|
|
188
179
|
### viem / wagmi
|
|
189
180
|
|
|
190
181
|
```ts
|
|
191
|
-
import {
|
|
182
|
+
import { smartDeposit, smartRedeem, getVaultStatus, LZ_TIMEOUTS } from '@oydual31/more-vaults-sdk/viem'
|
|
192
183
|
import { createPublicClient, createWalletClient, http, parseUnits } from 'viem'
|
|
184
|
+
import { base } from 'viem/chains'
|
|
193
185
|
|
|
194
|
-
const publicClient = createPublicClient({ chain:
|
|
195
|
-
const walletClient = createWalletClient({ account, chain:
|
|
196
|
-
|
|
197
|
-
// 1. Check vault status to know which flow to use
|
|
198
|
-
const status = await getVaultStatus(publicClient, VAULT_ADDRESS)
|
|
199
|
-
// status.mode → 'local' | 'cross-chain-oracle' | 'cross-chain-async' | 'paused' | 'full'
|
|
200
|
-
// status.recommendedDepositFlow → 'depositSimple' | 'depositAsync' | 'none'
|
|
201
|
-
// status.escrow → escrow address (needed for async flows)
|
|
186
|
+
const publicClient = createPublicClient({ chain: base, transport: http(RPC_URL) })
|
|
187
|
+
const walletClient = createWalletClient({ account, chain: base, transport: http(RPC_URL) })
|
|
202
188
|
|
|
203
|
-
const
|
|
189
|
+
const VAULT = '0x8f740aba022b3fcc934ab75c581c04b75e72aba6'
|
|
204
190
|
|
|
205
|
-
//
|
|
206
|
-
const
|
|
207
|
-
walletClient, publicClient,
|
|
191
|
+
// --- Deposit ---
|
|
192
|
+
const depositResult = await smartDeposit(
|
|
193
|
+
walletClient, publicClient,
|
|
194
|
+
{ vault: VAULT },
|
|
208
195
|
parseUnits('100', 6), // 100 USDC
|
|
209
196
|
account.address,
|
|
210
197
|
)
|
|
211
198
|
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
console.log('
|
|
215
|
-
console.log('
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
```ts
|
|
221
|
-
import { getVaultStatus, depositSimple, getUserPosition } from '@oydual31/more-vaults-sdk/ethers'
|
|
222
|
-
import { BrowserProvider, parseUnits } from 'ethers'
|
|
223
|
-
|
|
224
|
-
const provider = new BrowserProvider(window.ethereum)
|
|
225
|
-
const signer = await provider.getSigner()
|
|
226
|
-
|
|
227
|
-
const status = await getVaultStatus(provider, VAULT_ADDRESS)
|
|
228
|
-
const addresses = { vault: VAULT_ADDRESS, escrow: status.escrow }
|
|
199
|
+
// Check if async (LZ Read callback needed)
|
|
200
|
+
if ('guid' in depositResult) {
|
|
201
|
+
console.log('Async deposit — waiting for LZ callback (~5 min)')
|
|
202
|
+
console.log('GUID:', depositResult.guid)
|
|
203
|
+
// Poll for shares using LZ_TIMEOUTS.LZ_READ_CALLBACK as timeout
|
|
204
|
+
} else {
|
|
205
|
+
console.log('Sync deposit — shares:', depositResult.shares)
|
|
206
|
+
}
|
|
229
207
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
208
|
+
// --- Redeem ---
|
|
209
|
+
const redeemResult = await smartRedeem(
|
|
210
|
+
walletClient, publicClient,
|
|
211
|
+
{ vault: VAULT },
|
|
212
|
+
shares,
|
|
213
|
+
account.address,
|
|
214
|
+
account.address,
|
|
234
215
|
)
|
|
216
|
+
|
|
217
|
+
if ('guid' in redeemResult) {
|
|
218
|
+
console.log('Async redeem — waiting for LZ callback (~5 min)')
|
|
219
|
+
// Poll for USDC balance increase
|
|
220
|
+
} else {
|
|
221
|
+
console.log('Sync redeem — assets:', redeemResult.assets)
|
|
222
|
+
}
|
|
235
223
|
```
|
|
236
224
|
|
|
237
225
|
---
|
|
238
226
|
|
|
239
227
|
## Flows
|
|
240
228
|
|
|
241
|
-
###
|
|
229
|
+
### Smart flows (auto-detection)
|
|
230
|
+
|
|
231
|
+
| Function | Description |
|
|
232
|
+
|----------|-------------|
|
|
233
|
+
| `smartDeposit` | Auto-detects vault mode → `depositSimple` (sync) or `depositAsync` (async) |
|
|
234
|
+
| `smartRedeem` | Auto-detects vault mode → `redeemShares` (sync) or `redeemAsync` (async) |
|
|
235
|
+
|
|
236
|
+
### Hub-chain deposit
|
|
242
237
|
|
|
243
238
|
| ID | Function | When to use | Doc |
|
|
244
239
|
|----|----------|-------------|-----|
|
|
245
|
-
|
|
|
246
|
-
|
|
|
247
|
-
|
|
|
248
|
-
|
|
|
249
|
-
|
|
|
250
|
-
|
|
|
240
|
+
| — | `smartDeposit` | **Recommended.** Auto-detects vault type. | — |
|
|
241
|
+
| D1 | `depositSimple` | User on hub chain, oracle ON or local vault | [->](./docs/flows/D1-deposit-simple.md) |
|
|
242
|
+
| D2 | `depositMultiAsset` | Deposit multiple tokens in one call | [->](./docs/flows/D2-deposit-multi-asset.md) |
|
|
243
|
+
| D3 | `depositCrossChainOracleOn` | Alias for D1 — hub with oracle ON | [->](./docs/flows/D3-deposit-oracle-on.md) |
|
|
244
|
+
| D4 | `depositAsync` | Hub with oracle OFF — async LZ Read | [->](./docs/flows/D4-deposit-async.md) |
|
|
245
|
+
| D5 | `mintAsync` | Same as D4 but user specifies exact share amount | [->](./docs/flows/D5-mint-async.md) |
|
|
246
|
+
|
|
247
|
+
### Cross-chain deposit (spoke -> hub)
|
|
248
|
+
|
|
249
|
+
| ID | Function | When to use | Doc |
|
|
250
|
+
|----|----------|-------------|-----|
|
|
251
|
+
| D6/D7 | `depositFromSpoke` | User on spoke chain — tokens bridge via LZ OFT | [->](./docs/flows/D6-D7-deposit-from-spoke.md) |
|
|
252
|
+
|
|
253
|
+
For Stargate OFTs (stgUSDC, USDT, WETH), `depositFromSpoke` returns `composeData` — the user must execute a 2nd TX on the hub via `waitForCompose` + `executeCompose`. For standard OFTs, compose auto-executes in 1 TX.
|
|
251
254
|
|
|
252
|
-
###
|
|
255
|
+
### Hub-chain redeem
|
|
253
256
|
|
|
254
257
|
| ID | Function | When to use | Doc |
|
|
255
258
|
|----|----------|-------------|-----|
|
|
256
|
-
|
|
|
257
|
-
|
|
|
258
|
-
|
|
|
259
|
-
|
|
|
260
|
-
|
|
|
261
|
-
|
|
|
259
|
+
| — | `smartRedeem` | **Recommended.** Auto-detects vault type. | — |
|
|
260
|
+
| R1 | `redeemShares` | Standard redeem, hub chain, no queue | [->](./docs/flows/R1-redeem-shares.md) |
|
|
261
|
+
| R2 | `withdrawAssets` | Specify exact asset amount to receive | [->](./docs/flows/R2-withdraw-assets.md) |
|
|
262
|
+
| R3 | `requestRedeem` | Withdrawal queue enabled, no timelock | [->](./docs/flows/R3-R4-request-redeem.md) |
|
|
263
|
+
| R4 | `requestRedeem` | Withdrawal queue + mandatory wait period | [->](./docs/flows/R3-R4-request-redeem.md) |
|
|
264
|
+
| R5 | `redeemAsync` | Hub with oracle OFF — async LZ Read | [->](./docs/flows/R5-redeem-async.md) |
|
|
265
|
+
|
|
266
|
+
### Cross-chain redeem (spoke -> hub -> spoke)
|
|
267
|
+
|
|
268
|
+
Full spoke redeem is a 3-step flow across two chains:
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
Step 1 (Spoke): bridgeSharesToHub() — shares spoke->hub via SHARE_OFT (~7 min)
|
|
272
|
+
Step 2 (Hub): smartRedeem() — redeem on hub (auto-detects async, ~5 min callback)
|
|
273
|
+
Step 3 (Hub): bridgeAssetsToSpoke() — assets hub->spoke via Stargate/OFT (~13 min)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
| Function | Step | Doc |
|
|
277
|
+
|----------|------|-----|
|
|
278
|
+
| `resolveRedeemAddresses` | Pre-step: discover all addresses dynamically | — |
|
|
279
|
+
| `preflightSpokeRedeem` | Pre-step: validate balances + gas on both chains | — |
|
|
280
|
+
| `bridgeSharesToHub` | Step 1: bridge shares spoke->hub | [->](./docs/flows/R6-bridge-shares-to-hub.md) |
|
|
281
|
+
| `smartRedeem` | Step 2: redeem on hub | — |
|
|
282
|
+
| `bridgeAssetsToSpoke` | Step 3: bridge assets hub->spoke | [->](./docs/flows/R7-bridge-assets-to-spoke.md) |
|
|
283
|
+
|
|
284
|
+
### Compose helpers (Stargate 2-TX flow)
|
|
285
|
+
|
|
286
|
+
| Function | Description |
|
|
287
|
+
|----------|-------------|
|
|
288
|
+
| `waitForCompose` | Wait for pending compose in LZ Endpoint's composeQueue |
|
|
289
|
+
| `quoteComposeFee` | Quote ETH needed for `executeCompose` (readFee + shareSendFee) |
|
|
290
|
+
| `executeCompose` | Execute pending compose on hub chain |
|
|
262
291
|
|
|
263
292
|
### User helpers (read-only, no gas)
|
|
264
293
|
|
|
@@ -274,6 +303,64 @@ Full reference: [docs/user-helpers.md](./docs/user-helpers.md)
|
|
|
274
303
|
| `getVaultStatus` | full config snapshot + recommended flow + issues list |
|
|
275
304
|
| `quoteLzFee` | native fee required for D4, D5, R5 |
|
|
276
305
|
| `getAsyncRequestStatusLabel` | pending / ready-to-execute / completed / refunded |
|
|
306
|
+
| `getUserBalances` | shares + underlying balance in one call |
|
|
307
|
+
| `getMaxWithdrawable` | max assets redeemable given hub liquidity |
|
|
308
|
+
| `getVaultSummary` | metadata + status + user position combined |
|
|
309
|
+
|
|
310
|
+
### Spoke route discovery
|
|
311
|
+
|
|
312
|
+
| Function | Description |
|
|
313
|
+
|----------|-------------|
|
|
314
|
+
| `getInboundRoutes` | All routes a user can deposit from (which chains/tokens) |
|
|
315
|
+
| `getUserBalancesForRoutes` | User balances for all inbound routes |
|
|
316
|
+
| `getOutboundRoutes` | All routes for spoke redeem (which chains to bridge back to) |
|
|
317
|
+
| `quoteRouteDepositFee` | LZ fee for a specific inbound route |
|
|
318
|
+
| `resolveRedeemAddresses` | Discover SHARE_OFT, asset OFT, spoke asset for a redeem route |
|
|
319
|
+
|
|
320
|
+
### Topology & distribution
|
|
321
|
+
|
|
322
|
+
| Function | Description |
|
|
323
|
+
|----------|-------------|
|
|
324
|
+
| `getVaultTopology` | Hub/spoke chain IDs, OFT routes, composer addresses |
|
|
325
|
+
| `getFullVaultTopology` | Topology + all on-chain config |
|
|
326
|
+
| `getVaultDistribution` | TVL breakdown across hub + all spokes |
|
|
327
|
+
| `isOnHubChain` | Check if user is on the hub chain |
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## LZ Timeouts (for UI integration)
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
import { LZ_TIMEOUTS } from '@oydual31/more-vaults-sdk/viem'
|
|
335
|
+
|
|
336
|
+
LZ_TIMEOUTS.POLL_INTERVAL // 30s — interval between balance polls
|
|
337
|
+
LZ_TIMEOUTS.OFT_BRIDGE // 15 min — standard OFT bridge (shares or assets)
|
|
338
|
+
LZ_TIMEOUTS.STARGATE_BRIDGE // 30 min — Stargate bridge (slower, pool mechanics)
|
|
339
|
+
LZ_TIMEOUTS.LZ_READ_CALLBACK // 15 min — async deposit/redeem LZ Read callback
|
|
340
|
+
LZ_TIMEOUTS.COMPOSE_DELIVERY // 45 min — compose delivery to hub (spoke deposit)
|
|
341
|
+
LZ_TIMEOUTS.FULL_SPOKE_REDEEM // 60 min — full spoke->hub->spoke redeem
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Use these as timeout values in UI progress indicators. Do NOT timeout before these values — cross-chain operations can legitimately take this long.
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Pre-flight validation
|
|
349
|
+
|
|
350
|
+
Run pre-flight checks before submitting transactions to catch issues early:
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
import { preflightSpokeDeposit, preflightSpokeRedeem } from '@oydual31/more-vaults-sdk/viem'
|
|
354
|
+
|
|
355
|
+
// Before spoke deposit
|
|
356
|
+
const check = await preflightSpokeDeposit(...)
|
|
357
|
+
// Validates: spoke balance, gas, hub composer setup
|
|
358
|
+
|
|
359
|
+
// Before spoke redeem
|
|
360
|
+
const check = await preflightSpokeRedeem(route, shares, userAddress, shareBridgeFee)
|
|
361
|
+
// Validates: shares on spoke, spoke gas (LZ fee + buffer), hub gas (asset bridge fee)
|
|
362
|
+
// Returns: estimatedAssetBridgeFee, hubLiquidBalance, etc.
|
|
363
|
+
```
|
|
277
364
|
|
|
278
365
|
---
|
|
279
366
|
|
|
@@ -282,14 +369,15 @@ Full reference: [docs/user-helpers.md](./docs/user-helpers.md)
|
|
|
282
369
|
```
|
|
283
370
|
more-vaults-sdk/
|
|
284
371
|
├── src/
|
|
285
|
-
│ ├── viem/
|
|
286
|
-
│
|
|
372
|
+
│ ├── viem/ <- viem/wagmi SDK
|
|
373
|
+
│ ├── ethers/ <- ethers.js v6 SDK
|
|
374
|
+
│ └── react/ <- React hooks (wagmi)
|
|
287
375
|
├── docs/
|
|
288
|
-
│ ├── flows/
|
|
376
|
+
│ ├── flows/ <- one .md per flow with detailed examples
|
|
289
377
|
│ ├── user-helpers.md
|
|
290
378
|
│ └── testing.md
|
|
291
|
-
├──
|
|
292
|
-
└──
|
|
379
|
+
├── scripts/ <- E2E test scripts (mainnet)
|
|
380
|
+
└── tests/ <- integration tests (require Foundry + Anvil)
|
|
293
381
|
```
|
|
294
382
|
|
|
295
383
|
Integration tests: [docs/testing.md](./docs/testing.md) — `bash tests/run.sh` runs all 43 tests.
|
package/dist/ethers/index.cjs
CHANGED
|
@@ -31,6 +31,25 @@ var CHAIN_ID_TO_EID = {
|
|
|
31
31
|
[CHAIN_IDS.base]: LZ_EIDS.base,
|
|
32
32
|
[CHAIN_IDS.ethereum]: LZ_EIDS.ethereum
|
|
33
33
|
};
|
|
34
|
+
var LZ_TIMEOUTS = {
|
|
35
|
+
/** Poll interval between balance/event checks */
|
|
36
|
+
POLL_INTERVAL: 3e4,
|
|
37
|
+
/** Standard OFT bridge (shares or assets, non-Stargate) */
|
|
38
|
+
OFT_BRIDGE: 9e5,
|
|
39
|
+
// 15 min
|
|
40
|
+
/** Stargate bridge (USDC, USDT, WETH) — slower due to pool mechanics */
|
|
41
|
+
STARGATE_BRIDGE: 18e5,
|
|
42
|
+
// 30 min
|
|
43
|
+
/** LZ Read callback (async vault actions) */
|
|
44
|
+
LZ_READ_CALLBACK: 9e5,
|
|
45
|
+
// 15 min
|
|
46
|
+
/** Compose delivery to hub (deposit from spoke) */
|
|
47
|
+
COMPOSE_DELIVERY: 27e5,
|
|
48
|
+
// 45 min
|
|
49
|
+
/** Full spoke→hub→spoke redeem (all steps combined) */
|
|
50
|
+
FULL_SPOKE_REDEEM: 36e5
|
|
51
|
+
// 60 min
|
|
52
|
+
};
|
|
34
53
|
|
|
35
54
|
// src/ethers/types.ts
|
|
36
55
|
var ActionType = {
|
|
@@ -827,6 +846,46 @@ async function bridgeSharesToHub(signer, shareOFT, hubChainEid, shares, receiver
|
|
|
827
846
|
const receipt = await tx.wait();
|
|
828
847
|
return { receipt };
|
|
829
848
|
}
|
|
849
|
+
async function smartRedeem(signer, addresses, shares, receiver, owner, extraOptions = "0x") {
|
|
850
|
+
const provider = signer.provider;
|
|
851
|
+
const vault = addresses.vault;
|
|
852
|
+
const status = await getVaultStatus(provider, vault);
|
|
853
|
+
if (status.mode === "paused") {
|
|
854
|
+
throw new Error(`[MoreVaults] Vault ${vault} is paused. Cannot redeem.`);
|
|
855
|
+
}
|
|
856
|
+
if (status.recommendedDepositFlow === "depositAsync") {
|
|
857
|
+
const lzFee = await quoteLzFee(provider, vault, extraOptions);
|
|
858
|
+
return redeemAsync(signer, addresses, shares, receiver, owner, lzFee, extraOptions);
|
|
859
|
+
}
|
|
860
|
+
return redeemShares(signer, addresses, shares, receiver, owner);
|
|
861
|
+
}
|
|
862
|
+
async function bridgeAssetsToSpoke(signer, assetOFT, spokeChainEid, amount, receiver, lzFee, isStargate = true) {
|
|
863
|
+
const oft = new ethers.Contract(assetOFT, OFT_ABI, signer);
|
|
864
|
+
const token = await oft.token();
|
|
865
|
+
if (token.toLowerCase() !== assetOFT.toLowerCase()) {
|
|
866
|
+
await ensureAllowance4(signer, token, assetOFT, amount);
|
|
867
|
+
} else {
|
|
868
|
+
await ensureAllowance4(signer, assetOFT, assetOFT, amount);
|
|
869
|
+
}
|
|
870
|
+
const refundAddress = await signer.getAddress();
|
|
871
|
+
const toBytes32 = ethers.zeroPadValue(receiver, 32);
|
|
872
|
+
const sendParam = {
|
|
873
|
+
dstEid: spokeChainEid,
|
|
874
|
+
to: toBytes32,
|
|
875
|
+
amountLD: amount,
|
|
876
|
+
minAmountLD: amount * 99n / 100n,
|
|
877
|
+
// 1% slippage for Stargate
|
|
878
|
+
extraOptions: "0x",
|
|
879
|
+
composeMsg: "0x",
|
|
880
|
+
oftCmd: isStargate ? "0x01" : "0x"
|
|
881
|
+
};
|
|
882
|
+
const msgFee = { nativeFee: lzFee, lzTokenFee: 0n };
|
|
883
|
+
const tx = await oft.send(sendParam, msgFee, refundAddress, {
|
|
884
|
+
value: lzFee
|
|
885
|
+
});
|
|
886
|
+
const receipt = await tx.wait();
|
|
887
|
+
return { receipt };
|
|
888
|
+
}
|
|
830
889
|
var MULTICALL3_ADDRESS2 = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
831
890
|
var MULTICALL3_ABI2 = [
|
|
832
891
|
"function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)"
|
|
@@ -1057,6 +1116,7 @@ exports.EscrowNotConfiguredError = EscrowNotConfiguredError;
|
|
|
1057
1116
|
exports.InsufficientLiquidityError = InsufficientLiquidityError;
|
|
1058
1117
|
exports.LZ_EIDS = LZ_EIDS;
|
|
1059
1118
|
exports.LZ_ENDPOINT_ABI = LZ_ENDPOINT_ABI;
|
|
1119
|
+
exports.LZ_TIMEOUTS = LZ_TIMEOUTS;
|
|
1060
1120
|
exports.METADATA_ABI = METADATA_ABI;
|
|
1061
1121
|
exports.MissingEscrowAddressError = MissingEscrowAddressError;
|
|
1062
1122
|
exports.MoreVaultsError = MoreVaultsError;
|
|
@@ -1067,6 +1127,7 @@ exports.VAULT_ABI = VAULT_ABI;
|
|
|
1067
1127
|
exports.VaultPausedError = VaultPausedError;
|
|
1068
1128
|
exports.WrongChainError = WrongChainError;
|
|
1069
1129
|
exports.asSdkSigner = asSdkSigner;
|
|
1130
|
+
exports.bridgeAssetsToSpoke = bridgeAssetsToSpoke;
|
|
1070
1131
|
exports.bridgeSharesToHub = bridgeSharesToHub;
|
|
1071
1132
|
exports.canDeposit = canDeposit;
|
|
1072
1133
|
exports.depositAsync = depositAsync;
|
|
@@ -1100,6 +1161,7 @@ exports.redeemAsync = redeemAsync;
|
|
|
1100
1161
|
exports.redeemShares = redeemShares;
|
|
1101
1162
|
exports.requestRedeem = requestRedeem;
|
|
1102
1163
|
exports.smartDeposit = smartDeposit;
|
|
1164
|
+
exports.smartRedeem = smartRedeem;
|
|
1103
1165
|
exports.withdrawAssets = withdrawAssets;
|
|
1104
1166
|
//# sourceMappingURL=index.cjs.map
|
|
1105
1167
|
//# sourceMappingURL=index.cjs.map
|