@oydual31/more-vaults-sdk 1.1.21 → 1.1.23
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/dist/ethers/index.cjs +20 -0
- package/dist/ethers/index.cjs.map +1 -1
- package/dist/ethers/index.d.cts +5 -2
- package/dist/ethers/index.d.ts +5 -2
- package/dist/ethers/index.js +20 -1
- package/dist/ethers/index.js.map +1 -1
- package/dist/react/index.cjs +22 -9
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +22 -9
- package/dist/react/index.js.map +1 -1
- package/dist/viem/index.cjs +34 -12
- package/dist/viem/index.cjs.map +1 -1
- package/dist/viem/index.d.cts +20 -4
- package/dist/viem/index.d.ts +20 -4
- package/dist/viem/index.js +34 -13
- package/dist/viem/index.js.map +1 -1
- package/package.json +1 -1
- package/src/ethers/abis.ts +5 -0
- package/src/ethers/errorParser.ts +8 -0
- package/src/ethers/errors.ts +7 -0
- package/src/ethers/index.ts +1 -0
- package/src/ethers/redeemFlows.ts +11 -1
- package/src/viem/abis.ts +4 -0
- package/src/viem/adminActions.ts +2 -2
- package/src/viem/chains.ts +3 -2
- package/src/viem/curatorMulticall.ts +1 -1
- package/src/viem/curatorStatus.ts +4 -4
- package/src/viem/curatorSubVaults.ts +3 -3
- package/src/viem/curatorSwaps.ts +4 -2
- package/src/viem/errorParser.ts +8 -0
- package/src/viem/errors.ts +7 -0
- package/src/viem/index.ts +1 -0
- package/src/viem/redeemFlows.ts +13 -1
- package/src/viem/vaultConfig.ts +1 -1
package/package.json
CHANGED
package/src/ethers/abis.ts
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export const VAULT_ABI = [
|
|
7
|
+
// Errors (for proper revert decoding)
|
|
8
|
+
"error WithdrawalQueueDisabled()",
|
|
9
|
+
"error WithdrawalQueueEnabled()",
|
|
10
|
+
"error RequestWithdrawDisabled()",
|
|
11
|
+
|
|
7
12
|
// ERC4626 core
|
|
8
13
|
"function deposit(uint256 assets, address receiver) returns (uint256 shares)",
|
|
9
14
|
"function mint(uint256 shares, address receiver) returns (uint256 assets)",
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
NoSuchActionsError,
|
|
11
11
|
CapacityFullError,
|
|
12
12
|
InvalidInputError,
|
|
13
|
+
WithdrawalQueueDisabledError,
|
|
13
14
|
} from './errors.js'
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -46,6 +47,13 @@ export function parseContractError(err: unknown, vault: string, caller?: string)
|
|
|
46
47
|
throw new VaultPausedError(vault)
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
// Withdrawal queue disabled — caller used requestRedeem/requestWithdraw on a vault
|
|
51
|
+
// where the queue is off. Should use redeemShares/withdrawAssets directly, or smartRedeem.
|
|
52
|
+
// 0xdbb22fbf is the selector for WithdrawalQueueDisabled().
|
|
53
|
+
if (msg.includes('WithdrawalQueueDisabled') || msg.includes('0xdbb22fbf')) {
|
|
54
|
+
throw new WithdrawalQueueDisabledError(vault)
|
|
55
|
+
}
|
|
56
|
+
|
|
49
57
|
// Role checks
|
|
50
58
|
if (msg.includes('NotCurator') || msg.includes('OwnableUnauthorizedAccount')) {
|
|
51
59
|
if (msg.includes('NotCurator')) {
|
package/src/ethers/errors.ts
CHANGED
|
@@ -42,6 +42,13 @@ export class WhitelistQuotaExhaustedError extends MoreVaultsError {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export class WithdrawalQueueDisabledError extends MoreVaultsError {
|
|
46
|
+
constructor(vault: string) {
|
|
47
|
+
super(`[MoreVaults] Withdrawal queue is disabled on vault ${vault}. Cannot call requestRedeem/requestWithdraw — use redeemShares/withdrawAssets directly, or smartRedeem which auto-selects the correct flow.`)
|
|
48
|
+
this.name = 'WithdrawalQueueDisabledError'
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
export class InsufficientLiquidityError extends MoreVaultsError {
|
|
46
53
|
hubLiquid: bigint
|
|
47
54
|
required: bigint
|
package/src/ethers/index.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "./types";
|
|
16
16
|
import type { ContractTransactionReceipt } from "ethers";
|
|
17
17
|
import { preflightAsync, preflightRedeemLiquidity } from "./preflight";
|
|
18
|
-
import { EscrowNotConfiguredError, InvalidInputError, VaultPausedError, WithdrawalTimelockActiveError } from "./errors";
|
|
18
|
+
import { EscrowNotConfiguredError, InvalidInputError, VaultPausedError, WithdrawalTimelockActiveError, WithdrawalQueueDisabledError } from "./errors";
|
|
19
19
|
import { validateWalletChain } from "./chainValidation";
|
|
20
20
|
import { getVaultStatus, quoteLzFee, detectStargateOft } from "./utils";
|
|
21
21
|
import { CHAIN_ID_TO_EID, OFT_ROUTES, createChainProvider } from "./chains";
|
|
@@ -159,6 +159,16 @@ export async function requestRedeem(
|
|
|
159
159
|
// Validate wallet is on the correct chain (opt-in via hubChainId)
|
|
160
160
|
await validateWalletChain(signer, addresses.hubChainId);
|
|
161
161
|
|
|
162
|
+
// Pre-check: vault must have withdrawal queue enabled — otherwise the contract
|
|
163
|
+
// reverts with WithdrawalQueueDisabled (0xdbb22fbf). Use redeemShares directly
|
|
164
|
+
// or smartRedeem which auto-selects the correct flow.
|
|
165
|
+
const provider = signer.provider!
|
|
166
|
+
const configRead = new Contract(addresses.vault, ['function getWithdrawalQueueStatus() view returns (bool)'], provider)
|
|
167
|
+
const queueEnabled: boolean = await configRead.getWithdrawalQueueStatus()
|
|
168
|
+
if (!queueEnabled) {
|
|
169
|
+
throw new WithdrawalQueueDisabledError(addresses.vault)
|
|
170
|
+
}
|
|
171
|
+
|
|
162
172
|
// Detect which signature the vault supports: new (uint256, address) or legacy (uint256)
|
|
163
173
|
let useLegacy = false
|
|
164
174
|
const vaultNew = new Contract(addresses.vault, VAULT_ABI, signer)
|
package/src/viem/abis.ts
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export const VAULT_ABI = [
|
|
7
|
+
// ── Errors (for proper revert decoding) ──
|
|
8
|
+
{ type: 'error', name: 'WithdrawalQueueDisabled', inputs: [] },
|
|
9
|
+
{ type: 'error', name: 'WithdrawalQueueEnabled', inputs: [] },
|
|
10
|
+
{ type: 'error', name: 'RequestWithdrawDisabled', inputs: [] },
|
|
7
11
|
{
|
|
8
12
|
type: 'function',
|
|
9
13
|
name: 'deposit',
|
package/src/viem/adminActions.ts
CHANGED
|
@@ -126,7 +126,7 @@ export async function addAvailableAssets(
|
|
|
126
126
|
): Promise<{ txHash: `0x${string}` }> {
|
|
127
127
|
const account = walletClient.account!
|
|
128
128
|
const v = getAddress(vault)
|
|
129
|
-
const checksummed = assets.map(getAddress)
|
|
129
|
+
const checksummed = assets.map(a => getAddress(a))
|
|
130
130
|
|
|
131
131
|
try {
|
|
132
132
|
await publicClient.simulateContract({
|
|
@@ -268,7 +268,7 @@ export async function setDepositWhitelist(
|
|
|
268
268
|
throw new InvalidInputError('depositors and caps arrays must have the same length')
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
const checksummed = depositors.map(getAddress)
|
|
271
|
+
const checksummed = depositors.map(a => getAddress(a))
|
|
272
272
|
|
|
273
273
|
try {
|
|
274
274
|
await publicClient.simulateContract({
|
package/src/viem/chains.ts
CHANGED
|
@@ -267,8 +267,9 @@ export const LZ_TIMEOUTS = {
|
|
|
267
267
|
*
|
|
268
268
|
* Note on struct differences:
|
|
269
269
|
* - SwapRouter (Eth/Arb/Op, 0xE592...): exactInputSingle struct includes `deadline`
|
|
270
|
-
* - SwapRouter02 (Base, 0x2626...):
|
|
271
|
-
*
|
|
270
|
+
* - SwapRouter02 (Base/Flow, 0x2626.../0xeEDC...): struct does NOT include `deadline`
|
|
271
|
+
* Flow EVM confirmed via PUSH4 scan: router only dispatches 0x04e45aaf (SwapRouter02),
|
|
272
|
+
* not 0x414bf389 (SwapRouter). Both are in curatorSwaps.ts SWAP_ROUTER02_CHAINS.
|
|
272
273
|
*/
|
|
273
274
|
export const UNISWAP_V3_ROUTERS: Record<number, `0x${string}`> = {
|
|
274
275
|
[8453]: '0x2626664c2603336E57B271c5C0b26F421741e481', // Base — SwapRouter02 (no deadline)
|
|
@@ -138,7 +138,7 @@ export function encodeCuratorAction(action: CuratorAction): `0x${string}` {
|
|
|
138
138
|
return encodeFunctionData({
|
|
139
139
|
abi: ADMIN_WRITE_ABI,
|
|
140
140
|
functionName: 'addAvailableAssets',
|
|
141
|
-
args: [action.assets.map(getAddress)],
|
|
141
|
+
args: [action.assets.map(a => getAddress(a))],
|
|
142
142
|
})
|
|
143
143
|
|
|
144
144
|
case 'disableAssetToDeposit':
|
|
@@ -55,7 +55,7 @@ export async function getCuratorVaultStatus(
|
|
|
55
55
|
timeLockPeriod,
|
|
56
56
|
maxSlippagePercent,
|
|
57
57
|
currentNonce,
|
|
58
|
-
availableAssets: availableAssets.map(getAddress),
|
|
58
|
+
availableAssets: availableAssets.map(a => getAddress(a)),
|
|
59
59
|
lzAdapter: getAddress(lzAdapter),
|
|
60
60
|
paused,
|
|
61
61
|
}
|
|
@@ -177,8 +177,8 @@ export async function getVaultAnalysis(
|
|
|
177
177
|
}).catch(() => null),
|
|
178
178
|
])
|
|
179
179
|
|
|
180
|
-
const availableAddresses = (availableRaw as Address[]).map(getAddress)
|
|
181
|
-
const depositableAddresses = (depositableRaw as Address[]).map(getAddress)
|
|
180
|
+
const availableAddresses = (availableRaw as Address[]).map(a => getAddress(a))
|
|
181
|
+
const depositableAddresses = (depositableRaw as Address[]).map(a => getAddress(a))
|
|
182
182
|
|
|
183
183
|
// Deduplicated set of all asset addresses we need metadata for
|
|
184
184
|
const allAddresses = Array.from(new Set([...availableAddresses, ...depositableAddresses]))
|
|
@@ -302,7 +302,7 @@ export async function getVaultAssetBreakdown(
|
|
|
302
302
|
return { assets: [], totalAssets: 0n, totalSupply: 0n, underlyingDecimals: 6 }
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
-
const addresses = availableRaw.map(getAddress)
|
|
305
|
+
const addresses = availableRaw.map(a => getAddress(a))
|
|
306
306
|
|
|
307
307
|
// Step 2: multicall — balanceOf + metadata for each asset + totalAssets + totalSupply + vault decimals
|
|
308
308
|
const results = await publicClient.multicall({
|
|
@@ -86,8 +86,8 @@ export async function getSubVaultPositions(
|
|
|
86
86
|
.catch(() => [] as Address[]),
|
|
87
87
|
])
|
|
88
88
|
|
|
89
|
-
const erc4626Vaults = (erc4626Raw as Address[]).map(getAddress)
|
|
90
|
-
const erc7540Vaults = (erc7540Raw as Address[]).map(getAddress)
|
|
89
|
+
const erc4626Vaults = (erc4626Raw as Address[]).map(a => getAddress(a))
|
|
90
|
+
const erc7540Vaults = (erc7540Raw as Address[]).map(a => getAddress(a))
|
|
91
91
|
|
|
92
92
|
const allSubVaults: Array<{ address: Address; type: 'erc4626' | 'erc7540' }> = [
|
|
93
93
|
...erc4626Vaults.map((a) => ({ address: a, type: 'erc4626' as const })),
|
|
@@ -465,7 +465,7 @@ export async function getVaultPortfolio(
|
|
|
465
465
|
? getAddress(vaultTotals[2].result as Address)
|
|
466
466
|
: zeroAddress
|
|
467
467
|
|
|
468
|
-
const availableAddresses = (availableRaw as Address[]).map(getAddress)
|
|
468
|
+
const availableAddresses = (availableRaw as Address[]).map(a => getAddress(a))
|
|
469
469
|
|
|
470
470
|
// Sub-vault share addresses to exclude from liquid assets (avoid double-counting)
|
|
471
471
|
const subVaultAddressSet = new Set(subVaultPositions.map((p) => p.address.toLowerCase()))
|
package/src/viem/curatorSwaps.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - Ethereum (1): SwapRouter 0xE592... — HAS deadline field
|
|
11
11
|
* - Arbitrum (42161): SwapRouter 0xE592... — HAS deadline field
|
|
12
12
|
* - Optimism (10): SwapRouter 0xE592... — HAS deadline field
|
|
13
|
-
* - Flow EVM (747): FlowSwap V3 0xeEDC... —
|
|
13
|
+
* - Flow EVM (747): FlowSwap V3 0xeEDC... — NO deadline field (SwapRouter02-compatible)
|
|
14
14
|
*
|
|
15
15
|
* @module curatorSwaps
|
|
16
16
|
*/
|
|
@@ -89,8 +89,10 @@ const UNISWAP_V3_SWAP_ROUTER02_ABI = [
|
|
|
89
89
|
/**
|
|
90
90
|
* Chains that use SwapRouter02 (no deadline in struct).
|
|
91
91
|
* All other chains in UNISWAP_V3_ROUTERS use the original SwapRouter.
|
|
92
|
+
*
|
|
93
|
+
* Flow EVM (747): FlowSwap V3 router exposes exactInputSingle with selector 0x04e45aaf
|
|
92
94
|
*/
|
|
93
|
-
const SWAP_ROUTER02_CHAINS = new Set([8453])
|
|
95
|
+
const SWAP_ROUTER02_CHAINS = new Set([8453, 747])
|
|
94
96
|
|
|
95
97
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
96
98
|
// Calldata encoding
|
package/src/viem/errorParser.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
NoSuchActionsError,
|
|
11
11
|
CapacityFullError,
|
|
12
12
|
InvalidInputError,
|
|
13
|
+
WithdrawalQueueDisabledError,
|
|
13
14
|
} from './errors.js'
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -45,6 +46,13 @@ export function parseContractError(err: unknown, vault: string, caller?: string)
|
|
|
45
46
|
throw new VaultPausedError(vault)
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
// Withdrawal queue disabled — caller used requestRedeem/requestWithdraw on a vault
|
|
50
|
+
// where the queue is off. Should use redeemShares/withdrawAssets directly, or smartRedeem.
|
|
51
|
+
// 0xdbb22fbf is the selector for WithdrawalQueueDisabled().
|
|
52
|
+
if (msg.includes('WithdrawalQueueDisabled') || msg.includes('0xdbb22fbf')) {
|
|
53
|
+
throw new WithdrawalQueueDisabledError(vault)
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
// Role checks
|
|
49
57
|
if (msg.includes('NotCurator') || msg.includes('OwnableUnauthorizedAccount')) {
|
|
50
58
|
// Distinguish curator vs owner by checking the specific error
|
package/src/viem/errors.ts
CHANGED
|
@@ -42,6 +42,13 @@ export class WhitelistQuotaExhaustedError extends MoreVaultsError {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export class WithdrawalQueueDisabledError extends MoreVaultsError {
|
|
46
|
+
constructor(vault: string) {
|
|
47
|
+
super(`[MoreVaults] Withdrawal queue is disabled on vault ${vault}. Cannot call requestRedeem/requestWithdraw — use redeemShares/withdrawAssets directly, or smartRedeem which auto-selects the correct flow.`)
|
|
48
|
+
this.name = 'WithdrawalQueueDisabledError'
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
export class InsufficientLiquidityError extends MoreVaultsError {
|
|
46
53
|
hubLiquid: bigint
|
|
47
54
|
required: bigint
|
package/src/viem/index.ts
CHANGED
package/src/viem/redeemFlows.ts
CHANGED
|
@@ -18,7 +18,7 @@ import type {
|
|
|
18
18
|
import { ActionType } from './types'
|
|
19
19
|
import { ensureAllowance, getVaultStatus, quoteLzFee, detectStargateOft } from './utils'
|
|
20
20
|
import { preflightAsync, preflightRedeemLiquidity } from './preflight'
|
|
21
|
-
import { EscrowNotConfiguredError, VaultPausedError, InvalidInputError, WithdrawalTimelockActiveError } from './errors'
|
|
21
|
+
import { EscrowNotConfiguredError, VaultPausedError, InvalidInputError, WithdrawalTimelockActiveError, WithdrawalQueueDisabledError } from './errors'
|
|
22
22
|
import { validateWalletChain } from './chainValidation'
|
|
23
23
|
import { parseContractError } from './errorParser'
|
|
24
24
|
import { OFT_ROUTES, CHAIN_ID_TO_EID } from './chains'
|
|
@@ -175,6 +175,18 @@ export async function requestRedeem(
|
|
|
175
175
|
// Validate wallet is on the correct chain (opt-in via hubChainId)
|
|
176
176
|
validateWalletChain(walletClient, addresses.hubChainId)
|
|
177
177
|
|
|
178
|
+
// Pre-check: vault must have withdrawal queue enabled — otherwise the contract
|
|
179
|
+
// reverts with WithdrawalQueueDisabled (0xdbb22fbf). Use redeemShares directly
|
|
180
|
+
// or smartRedeem which auto-selects the correct flow.
|
|
181
|
+
const queueEnabled = await publicClient.readContract({
|
|
182
|
+
address: vault,
|
|
183
|
+
abi: CONFIG_ABI,
|
|
184
|
+
functionName: 'getWithdrawalQueueStatus',
|
|
185
|
+
})
|
|
186
|
+
if (!queueEnabled) {
|
|
187
|
+
throw new WithdrawalQueueDisabledError(vault)
|
|
188
|
+
}
|
|
189
|
+
|
|
178
190
|
// Detect which signature the vault supports: new (uint256, address) or legacy (uint256)
|
|
179
191
|
let useLegacy = false
|
|
180
192
|
|
package/src/viem/vaultConfig.ts
CHANGED
|
@@ -93,7 +93,7 @@ export async function getVaultConfiguration(
|
|
|
93
93
|
const num_ = (i: number): number =>
|
|
94
94
|
results[i].status === 'success' ? Number(results[i].result) : 0
|
|
95
95
|
const addrArray = (i: number): Address[] =>
|
|
96
|
-
results[i].status === 'success' ? (results[i].result as Address[]).map(getAddress) : []
|
|
96
|
+
results[i].status === 'success' ? (results[i].result as Address[]).map(a => getAddress(a)) : []
|
|
97
97
|
|
|
98
98
|
return {
|
|
99
99
|
// Roles
|