@gauntlet-xyz/sdk 3.0.1 → 3.1.1
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 +34 -3
- package/dist/api/activity.d.ts +3 -1
- package/dist/api/activity.d.ts.map +1 -1
- package/dist/api/activityRows.d.ts +11 -0
- package/dist/api/activityRows.d.ts.map +1 -0
- package/dist/api/caip.d.ts.map +1 -1
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/decimal.d.ts.map +1 -1
- package/dist/api/http.d.ts.map +1 -1
- package/dist/api/index.js +7 -8
- package/dist/api/positionHistory.d.ts.map +1 -1
- package/dist/attribution/index.d.ts +5 -2
- package/dist/attribution/index.d.ts.map +1 -1
- package/dist/{chunk-HC2BS7MK.js → chunk-JJOLVL5V.js} +113 -6
- package/dist/chunk-JJOLVL5V.js.map +7 -0
- package/dist/{chunk-S2TTA45N.js → chunk-JRSNLXFY.js} +2 -2
- package/dist/{chunk-SU6JAKIA.js → chunk-MEKISE2T.js} +131 -47
- package/dist/chunk-MEKISE2T.js.map +7 -0
- package/dist/{chunk-7TA2OJUK.js → chunk-YQXTLIJA.js} +209 -96
- package/dist/chunk-YQXTLIJA.js.map +7 -0
- package/dist/cjs/api/activity.d.ts +3 -1
- package/dist/cjs/api/activity.d.ts.map +1 -1
- package/dist/cjs/api/activity.js +14 -12
- package/dist/cjs/api/activity.js.map +2 -2
- package/dist/cjs/api/activityRows.d.ts +11 -0
- package/dist/cjs/api/activityRows.d.ts.map +1 -0
- package/dist/cjs/api/activityRows.js +139 -0
- package/dist/cjs/api/activityRows.js.map +7 -0
- package/dist/cjs/api/caip.d.ts.map +1 -1
- package/dist/cjs/api/caip.js +3 -1
- package/dist/cjs/api/caip.js.map +2 -2
- package/dist/cjs/api/client.d.ts.map +1 -1
- package/dist/cjs/api/client.js +29 -1
- package/dist/cjs/api/client.js.map +2 -2
- package/dist/cjs/api/decimal.d.ts.map +1 -1
- package/dist/cjs/api/decimal.js +1 -0
- package/dist/cjs/api/decimal.js.map +2 -2
- package/dist/cjs/api/http.d.ts.map +1 -1
- package/dist/cjs/api/http.js +1 -0
- package/dist/cjs/api/http.js.map +2 -2
- package/dist/cjs/api/positionHistory.d.ts.map +1 -1
- package/dist/cjs/api/positionHistory.js +17 -4
- package/dist/cjs/api/positionHistory.js.map +2 -2
- package/dist/cjs/attribution/index.d.ts +5 -2
- package/dist/cjs/attribution/index.d.ts.map +1 -1
- package/dist/cjs/attribution/index.js +3 -1
- package/dist/cjs/attribution/index.js.map +2 -2
- package/dist/cjs/evm/adapters/aera.d.ts.map +1 -1
- package/dist/cjs/evm/adapters/aera.js +16 -7
- package/dist/cjs/evm/adapters/aera.js.map +2 -2
- package/dist/cjs/evm/adapters/types.d.ts +1 -0
- package/dist/cjs/evm/adapters/types.d.ts.map +1 -1
- package/dist/cjs/evm/adapters/types.js.map +1 -1
- package/dist/cjs/evm/aeraContracts.d.ts.map +1 -1
- package/dist/cjs/evm/aeraContracts.js +21 -11
- package/dist/cjs/evm/aeraContracts.js.map +2 -2
- package/dist/cjs/evm/deposit.d.ts +3 -2
- package/dist/cjs/evm/deposit.d.ts.map +1 -1
- package/dist/cjs/evm/deposit.js +40 -10
- package/dist/cjs/evm/deposit.js.map +2 -2
- package/dist/cjs/evm/depositQuote.d.ts.map +1 -1
- package/dist/cjs/evm/depositQuote.js +1 -0
- package/dist/cjs/evm/depositQuote.js.map +2 -2
- package/dist/cjs/evm/depositReceiverApproval.d.ts.map +1 -1
- package/dist/cjs/evm/depositReceiverApproval.js +14 -9
- package/dist/cjs/evm/depositReceiverApproval.js.map +2 -2
- package/dist/cjs/evm/userCurrentBalance.d.ts +15 -1
- package/dist/cjs/evm/userCurrentBalance.d.ts.map +1 -1
- package/dist/cjs/evm/userCurrentBalance.js +94 -51
- package/dist/cjs/evm/userCurrentBalance.js.map +2 -2
- package/dist/cjs/evm/withdraw.d.ts +2 -0
- package/dist/cjs/evm/withdraw.d.ts.map +1 -1
- package/dist/cjs/evm/withdraw.js +14 -1
- package/dist/cjs/evm/withdraw.js.map +2 -2
- package/dist/cjs/evm/withdrawQuote.d.ts.map +1 -1
- package/dist/cjs/evm/withdrawQuote.js +1 -0
- package/dist/cjs/evm/withdrawQuote.js.map +2 -2
- package/dist/evm/adapters/aera.d.ts.map +1 -1
- package/dist/evm/adapters/types.d.ts +1 -0
- package/dist/evm/adapters/types.d.ts.map +1 -1
- package/dist/evm/aeraContracts.d.ts.map +1 -1
- package/dist/evm/deposit.d.ts +3 -2
- package/dist/evm/deposit.d.ts.map +1 -1
- package/dist/evm/depositQuote.d.ts.map +1 -1
- package/dist/evm/depositReceiverApproval.d.ts.map +1 -1
- package/dist/evm/index.js +6 -8
- package/dist/evm/userCurrentBalance.d.ts +15 -1
- package/dist/evm/userCurrentBalance.d.ts.map +1 -1
- package/dist/evm/withdraw.d.ts +2 -0
- package/dist/evm/withdraw.d.ts.map +1 -1
- package/dist/evm/withdrawQuote.d.ts.map +1 -1
- package/dist/index.js +11 -13
- package/dist/privy/index.js +2 -2
- package/package.json +1 -1
- package/src/api/activity.ts +18 -15
- package/src/api/activityRows.ts +143 -0
- package/src/api/caip.ts +3 -1
- package/src/api/client.ts +36 -1
- package/src/api/decimal.ts +1 -0
- package/src/api/http.ts +1 -0
- package/src/api/positionHistory.ts +20 -5
- package/src/attribution/index.ts +6 -2
- package/src/evm/adapters/aera.ts +26 -8
- package/src/evm/adapters/types.ts +1 -0
- package/src/evm/aeraContracts.ts +29 -14
- package/src/evm/deposit.ts +43 -12
- package/src/evm/depositQuote.ts +1 -0
- package/src/evm/depositReceiverApproval.ts +14 -9
- package/src/evm/userCurrentBalance.ts +144 -60
- package/src/evm/withdraw.ts +20 -1
- package/src/evm/withdrawQuote.ts +1 -0
- package/dist/chunk-7TA2OJUK.js.map +0 -7
- package/dist/chunk-HC2BS7MK.js.map +0 -7
- package/dist/chunk-STIV2CC4.js +0 -57
- package/dist/chunk-STIV2CC4.js.map +0 -7
- package/dist/chunk-SU6JAKIA.js.map +0 -7
- /package/dist/{chunk-S2TTA45N.js.map → chunk-JRSNLXFY.js.map} +0 -0
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
import { parseAbi, type Address } from 'viem';
|
|
2
2
|
import type { GauntletClient } from '../client';
|
|
3
3
|
import type { EvmVaultDeployment } from './types';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ChainMismatchError,
|
|
6
|
+
GauntletSDKError,
|
|
7
|
+
UnsupportedAssetError,
|
|
8
|
+
UnsupportedProtocolError,
|
|
9
|
+
VaultNotFoundError,
|
|
10
|
+
} from '../errors';
|
|
5
11
|
import { getMultiDepositorVault, resolveAeraRuntimeContracts } from './aeraContracts';
|
|
6
12
|
import { convertUnitsToToken } from './aeraContracts/priceAndFeeCalculator';
|
|
7
13
|
import { getUserUnitsRefundableUntil } from './aeraContracts/v2';
|
|
8
14
|
import { provisionerV2Abi } from './abis/provisionerV2';
|
|
9
15
|
import { ContractVersion } from './types';
|
|
10
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
BLOCKS_3_DAYS,
|
|
18
|
+
CHAIN_NAMES,
|
|
19
|
+
DAY,
|
|
20
|
+
DEFAULT_BLOCKS_3_DAYS,
|
|
21
|
+
LOG_PAGE_SIZE,
|
|
22
|
+
} from '../constants';
|
|
23
|
+
|
|
24
|
+
// Log chunks fetched at once per event type.
|
|
25
|
+
const LOG_CHUNK_CONCURRENCY = 16;
|
|
11
26
|
|
|
12
27
|
// Inline as-const ABI items give viem full type inference for args and return types.
|
|
13
28
|
const DEPOSIT_REQUESTED_V1_ABI = [
|
|
@@ -55,9 +70,20 @@ export interface UserCurrentBalanceParams {
|
|
|
55
70
|
vaultId: string;
|
|
56
71
|
address: Address;
|
|
57
72
|
chainId?: number;
|
|
73
|
+
/** Required for deployments that support multiple assets, ignored otherwise. */
|
|
74
|
+
assetSymbol?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Scan from this block, including expired requests that still hold escrow.
|
|
77
|
+
* Requires `chainId` for a vault with more than one deployment.
|
|
78
|
+
*/
|
|
79
|
+
fromBlock?: bigint;
|
|
58
80
|
}
|
|
59
81
|
|
|
60
82
|
export interface UserCurrentBalance {
|
|
83
|
+
/** Block used for balances, conversions, and request state. */
|
|
84
|
+
blockNumber: bigint;
|
|
85
|
+
/** First block included in the request scan. Older escrow is outside this result. */
|
|
86
|
+
fromBlock: bigint;
|
|
61
87
|
/** Chain identifier, e.g. "base" */
|
|
62
88
|
chain: string;
|
|
63
89
|
/** EVM chain id of the deployment, e.g. 8453 */
|
|
@@ -91,23 +117,77 @@ function dedupeByRequestHash<TLog extends { args: { [key: string]: unknown } }>(
|
|
|
91
117
|
});
|
|
92
118
|
}
|
|
93
119
|
|
|
120
|
+
/** Step back by the expected block count, and widen until the block predates the cutoff. */
|
|
121
|
+
async function requestScanStart(
|
|
122
|
+
publicClient: ReturnType<GauntletClient['getPublicClient']>,
|
|
123
|
+
chainId: number,
|
|
124
|
+
blockNumber: bigint,
|
|
125
|
+
days: number,
|
|
126
|
+
cutoff: bigint
|
|
127
|
+
): Promise<bigint> {
|
|
128
|
+
let span = ((BLOCKS_3_DAYS[chainId] ?? DEFAULT_BLOCKS_3_DAYS) * BigInt(days)) / 3n;
|
|
129
|
+
for (;;) {
|
|
130
|
+
if (span >= blockNumber) return 0n;
|
|
131
|
+
const start = blockNumber - span;
|
|
132
|
+
const block = await publicClient.getBlock({ blockNumber: start });
|
|
133
|
+
if (block.timestamp <= cutoff) return start;
|
|
134
|
+
span *= 2n;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function mapInBatches<T, P extends Promise<unknown>>(
|
|
139
|
+
items: T[],
|
|
140
|
+
size: number,
|
|
141
|
+
fn: (item: T) => P
|
|
142
|
+
): Promise<Awaited<P>[]> {
|
|
143
|
+
const results: Awaited<P>[] = [];
|
|
144
|
+
for (let i = 0; i < items.length; i += size) {
|
|
145
|
+
results.push(...(await Promise.all(items.slice(i, i + size).map(fn))));
|
|
146
|
+
}
|
|
147
|
+
return results;
|
|
148
|
+
}
|
|
149
|
+
|
|
94
150
|
async function queryDeploymentBalance(
|
|
95
151
|
client: GauntletClient,
|
|
96
152
|
deployment: EvmVaultDeployment,
|
|
97
|
-
|
|
153
|
+
params: UserCurrentBalanceParams
|
|
98
154
|
): Promise<UserCurrentBalance> {
|
|
99
155
|
const publicClient = client.getPublicClient(deployment.chainId);
|
|
100
|
-
const
|
|
156
|
+
const { address } = params;
|
|
157
|
+
const token =
|
|
158
|
+
deployment.supplyToken.length > 1
|
|
159
|
+
? deployment.supplyToken.find((candidate) => candidate.symbol === params.assetSymbol)
|
|
160
|
+
: deployment.supplyToken[0];
|
|
161
|
+
if (token === undefined)
|
|
162
|
+
throw new UnsupportedAssetError(params.assetSymbol ?? 'unknown', params.vaultId);
|
|
163
|
+
const snapshot = await publicClient.getBlock({ blockTag: 'latest' });
|
|
164
|
+
if (snapshot.number === null) {
|
|
165
|
+
throw new GauntletSDKError('The balance snapshot has no block number');
|
|
166
|
+
}
|
|
167
|
+
const blockNumber = snapshot.number;
|
|
168
|
+
const readOptions = { blockNumber };
|
|
169
|
+
const expirationDays = deployment.expirationDays ?? 3;
|
|
170
|
+
if (!Number.isSafeInteger(expirationDays) || expirationDays <= 0) {
|
|
171
|
+
throw new GauntletSDKError('The request expiration must be a positive integer number of days');
|
|
172
|
+
}
|
|
173
|
+
const scanDays = Math.max(3, expirationDays);
|
|
174
|
+
const cutoff = snapshot.timestamp - BigInt(DAY) * BigInt(scanDays);
|
|
175
|
+
const fromBlock =
|
|
176
|
+
params.fromBlock ??
|
|
177
|
+
(await requestScanStart(publicClient, deployment.chainId, blockNumber, scanDays, cutoff));
|
|
178
|
+
if (fromBlock < 0n || fromBlock > blockNumber) {
|
|
179
|
+
throw new GauntletSDKError('The request scan range is invalid');
|
|
180
|
+
}
|
|
101
181
|
|
|
102
182
|
const vaultContract = getMultiDepositorVault(publicClient, deployment.vaultAddress);
|
|
103
183
|
const [runtime, units] = await Promise.all([
|
|
104
|
-
resolveAeraRuntimeContracts(publicClient, deployment),
|
|
105
|
-
vaultContract.read.balanceOf([address]),
|
|
184
|
+
resolveAeraRuntimeContracts(publicClient, deployment, readOptions),
|
|
185
|
+
vaultContract.read.balanceOf([address], readOptions),
|
|
106
186
|
]);
|
|
107
187
|
const provisionerAddress = runtime.provisioner.address;
|
|
108
188
|
const isV2 = runtime.provisioner.version === ContractVersion.V2;
|
|
109
189
|
const unitsLockedUntilPromise = isV2
|
|
110
|
-
? getUserUnitsRefundableUntil(publicClient, provisionerAddress, address)
|
|
190
|
+
? getUserUnitsRefundableUntil(publicClient, provisionerAddress, address, readOptions)
|
|
111
191
|
: Promise.resolve(undefined);
|
|
112
192
|
|
|
113
193
|
const balance = await convertUnitsToToken(
|
|
@@ -116,63 +196,56 @@ async function queryDeploymentBalance(
|
|
|
116
196
|
runtime.feeCalculator.version,
|
|
117
197
|
deployment.vaultAddress,
|
|
118
198
|
token.address,
|
|
119
|
-
units
|
|
199
|
+
units,
|
|
200
|
+
readOptions
|
|
120
201
|
);
|
|
121
202
|
|
|
122
|
-
//
|
|
123
|
-
const currentBlock = await publicClient.getBlockNumber();
|
|
124
|
-
const lookback = BLOCKS_3_DAYS[deployment.chainId] ?? DEFAULT_BLOCKS_3_DAYS;
|
|
125
|
-
const fromBlock = currentBlock > lookback ? currentBlock - lookback : 0n;
|
|
126
|
-
|
|
127
|
-
// Compute block-range chunks to stay within the 10,000-block RPC limit, then fetch in parallel
|
|
203
|
+
// Compute block-range chunks to stay within the 10,000-block RPC limit, then fetch in bounded batches
|
|
128
204
|
const chunks: [bigint, bigint][] = [];
|
|
129
|
-
for (let cursor = fromBlock; cursor <=
|
|
130
|
-
const end = cursor + LOG_PAGE_SIZE <=
|
|
205
|
+
for (let cursor = fromBlock; cursor <= blockNumber; cursor += LOG_PAGE_SIZE + 1n) {
|
|
206
|
+
const end = cursor + LOG_PAGE_SIZE <= blockNumber ? cursor + LOG_PAGE_SIZE : blockNumber;
|
|
131
207
|
chunks.push([cursor, end]);
|
|
132
208
|
}
|
|
133
209
|
|
|
210
|
+
// Each map keeps LOG_CHUNK_CONCURRENCY queries in flight.
|
|
134
211
|
const [depositPages, redeemPages] = await Promise.all([
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
})
|
|
154
|
-
)
|
|
212
|
+
mapInBatches(chunks, LOG_CHUNK_CONCURRENCY, ([from, to]) =>
|
|
213
|
+
isV2
|
|
214
|
+
? publicClient.getContractEvents({
|
|
215
|
+
address: provisionerAddress,
|
|
216
|
+
abi: provisionerV2Abi,
|
|
217
|
+
eventName: 'DepositRequested',
|
|
218
|
+
args: { receiver: address, token: token.address },
|
|
219
|
+
fromBlock: from,
|
|
220
|
+
toBlock: to,
|
|
221
|
+
})
|
|
222
|
+
: publicClient.getContractEvents({
|
|
223
|
+
address: provisionerAddress,
|
|
224
|
+
abi: DEPOSIT_REQUESTED_V1_ABI,
|
|
225
|
+
eventName: 'DepositRequested',
|
|
226
|
+
args: { user: address, token: token.address },
|
|
227
|
+
fromBlock: from,
|
|
228
|
+
toBlock: to,
|
|
229
|
+
})
|
|
155
230
|
),
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
})
|
|
175
|
-
)
|
|
231
|
+
mapInBatches(chunks, LOG_CHUNK_CONCURRENCY, ([from, to]) =>
|
|
232
|
+
isV2
|
|
233
|
+
? publicClient.getContractEvents({
|
|
234
|
+
address: provisionerAddress,
|
|
235
|
+
abi: provisionerV2Abi,
|
|
236
|
+
eventName: 'RedeemRequested',
|
|
237
|
+
args: { user: address, token: token.address },
|
|
238
|
+
fromBlock: from,
|
|
239
|
+
toBlock: to,
|
|
240
|
+
})
|
|
241
|
+
: publicClient.getContractEvents({
|
|
242
|
+
address: provisionerAddress,
|
|
243
|
+
abi: REDEEM_REQUESTED_V1_ABI,
|
|
244
|
+
eventName: 'RedeemRequested',
|
|
245
|
+
args: { user: address, token: token.address },
|
|
246
|
+
fromBlock: from,
|
|
247
|
+
toBlock: to,
|
|
248
|
+
})
|
|
176
249
|
),
|
|
177
250
|
]);
|
|
178
251
|
|
|
@@ -196,6 +269,7 @@ async function queryDeploymentBalance(
|
|
|
196
269
|
})),
|
|
197
270
|
],
|
|
198
271
|
allowFailure: false,
|
|
272
|
+
blockNumber,
|
|
199
273
|
});
|
|
200
274
|
|
|
201
275
|
const depositChecks = pendingChecks.slice(0, depositLogs.length);
|
|
@@ -223,12 +297,15 @@ async function queryDeploymentBalance(
|
|
|
223
297
|
runtime.feeCalculator.version,
|
|
224
298
|
deployment.vaultAddress,
|
|
225
299
|
token.address,
|
|
226
|
-
pendingWithdrawUnits
|
|
300
|
+
pendingWithdrawUnits,
|
|
301
|
+
readOptions
|
|
227
302
|
)
|
|
228
303
|
: 0n;
|
|
229
304
|
const unitsLockedUntil = await unitsLockedUntilPromise;
|
|
230
305
|
|
|
231
306
|
return {
|
|
307
|
+
blockNumber,
|
|
308
|
+
fromBlock,
|
|
232
309
|
chain: CHAIN_NAMES[deployment.chainId] ?? `chain-${deployment.chainId}`,
|
|
233
310
|
chainId: deployment.chainId,
|
|
234
311
|
token: token.address,
|
|
@@ -249,7 +326,9 @@ async function queryDeploymentBalance(
|
|
|
249
326
|
* - `pendingWithdraw` — vault units locked in a pending async redeem request (converted to tokens).
|
|
250
327
|
*
|
|
251
328
|
* Only supported for Aera multi-depositor vaults. Pending amounts are detected by scanning
|
|
252
|
-
* the
|
|
329
|
+
* the configured request lifetime, with a minimum of three days. Set `fromBlock` (with `chainId`
|
|
330
|
+
* on a multi-chain vault) for older escrow.
|
|
331
|
+
* All state reads use one block. The returned range identifies the scanned history.
|
|
253
332
|
*
|
|
254
333
|
* @param client - A configured `GauntletClient` instance with an EVM public client for each
|
|
255
334
|
* chain the vault is deployed on.
|
|
@@ -260,6 +339,7 @@ async function queryDeploymentBalance(
|
|
|
260
339
|
* @throws {VaultNotFoundError} If the vault ID is not found in the manifest.
|
|
261
340
|
* @throws {UnsupportedProtocolError} If the vault is not an Aera multi-depositor vault.
|
|
262
341
|
* @throws {ChainMismatchError} If `chainId` is specified but no deployment exists for that chain.
|
|
342
|
+
* @throws {UnsupportedAssetError} If a multi-asset deployment gets no matching `assetSymbol`.
|
|
263
343
|
*
|
|
264
344
|
* @example
|
|
265
345
|
* ```ts
|
|
@@ -274,6 +354,7 @@ export async function getUserCurrentBalance(
|
|
|
274
354
|
client: GauntletClient,
|
|
275
355
|
params: UserCurrentBalanceParams
|
|
276
356
|
): Promise<UserCurrentBalance[]> {
|
|
357
|
+
params = { ...params };
|
|
277
358
|
const manifest = await client.manifest;
|
|
278
359
|
const vaultInfo = manifest.vaults.find((v) => v.vaultId === params.vaultId);
|
|
279
360
|
if (!vaultInfo) throw new VaultNotFoundError(params.vaultId);
|
|
@@ -294,8 +375,11 @@ export async function getUserCurrentBalance(
|
|
|
294
375
|
evmDeployments.map((d) => `${d.chainId}`).join(', ')
|
|
295
376
|
);
|
|
296
377
|
}
|
|
297
|
-
return [await queryDeploymentBalance(client, deployment, params
|
|
378
|
+
return [await queryDeploymentBalance(client, deployment, params)];
|
|
379
|
+
}
|
|
380
|
+
if (params.fromBlock !== undefined && evmDeployments.length > 1) {
|
|
381
|
+
throw new GauntletSDKError('fromBlock requires chainId for a vault with several deployments');
|
|
298
382
|
}
|
|
299
383
|
|
|
300
|
-
return Promise.all(evmDeployments.map((d) => queryDeploymentBalance(client, d, params
|
|
384
|
+
return Promise.all(evmDeployments.map((d) => queryDeploymentBalance(client, d, params)));
|
|
301
385
|
}
|
package/src/evm/withdraw.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
AccountRequiredError,
|
|
10
10
|
VaultNotFoundError,
|
|
11
11
|
UnsupportedAssetError,
|
|
12
|
+
UnsupportedFeatureError,
|
|
12
13
|
InvalidSlippageBPSError,
|
|
13
14
|
InvalidWithdrawParamsError,
|
|
14
15
|
} from '../errors';
|
|
@@ -49,6 +50,8 @@ export type EvmWithdrawParams = {
|
|
|
49
50
|
* Supplying bounds implies `depositMode: 'sync'`; explicit async requests are rejected.
|
|
50
51
|
*/
|
|
51
52
|
syncWithdrawQuote?: SyncWithdrawQuoteBounds;
|
|
53
|
+
/** Limit a sync withdrawal to the shares reviewed before a rate change. */
|
|
54
|
+
maxShares?: bigint;
|
|
52
55
|
} & (
|
|
53
56
|
| { shares: bigint; amount?: never; entireAmount?: never }
|
|
54
57
|
| { amount: bigint; shares?: never; entireAmount?: never }
|
|
@@ -56,6 +59,15 @@ export type EvmWithdrawParams = {
|
|
|
56
59
|
);
|
|
57
60
|
|
|
58
61
|
function validateWithdrawParams(params: EvmWithdrawParams) {
|
|
62
|
+
if (params.entireAmount !== undefined && typeof params.entireAmount !== 'boolean') {
|
|
63
|
+
throw new InvalidWithdrawParamsError();
|
|
64
|
+
}
|
|
65
|
+
if (
|
|
66
|
+
(params.amount !== undefined && params.amount < 0n) ||
|
|
67
|
+
(params.shares !== undefined && params.shares < 0n)
|
|
68
|
+
) {
|
|
69
|
+
throw new InvalidWithdrawParamsError();
|
|
70
|
+
}
|
|
59
71
|
const modes = [
|
|
60
72
|
'amount' in params && params.amount != null,
|
|
61
73
|
'shares' in params && params.shares != null,
|
|
@@ -171,6 +183,7 @@ export async function getWithdrawTx(
|
|
|
171
183
|
client: GauntletClient,
|
|
172
184
|
params: EvmWithdrawParams
|
|
173
185
|
): Promise<PreparedTx[]> {
|
|
186
|
+
params = structuredClone(params);
|
|
174
187
|
validateWithdrawParams(params);
|
|
175
188
|
|
|
176
189
|
if (
|
|
@@ -196,6 +209,9 @@ export async function getWithdrawTx(
|
|
|
196
209
|
}
|
|
197
210
|
|
|
198
211
|
const { vault, protocol } = resolved;
|
|
212
|
+
if (params.maxShares !== undefined && protocol !== 'aera') {
|
|
213
|
+
throw new UnsupportedFeatureError('maxShares requires an Aera sync withdrawal');
|
|
214
|
+
}
|
|
199
215
|
|
|
200
216
|
const token =
|
|
201
217
|
vault.supplyToken.length > 1
|
|
@@ -267,6 +283,7 @@ export async function getWithdrawTx(
|
|
|
267
283
|
maxPriceAge: params.maxPriceAge,
|
|
268
284
|
aeraRuntime,
|
|
269
285
|
syncWithdrawQuote: params.syncWithdrawQuote,
|
|
286
|
+
maxShares: params.maxShares,
|
|
270
287
|
...('shares' in params && params.shares != null ? { shares: params.shares } : {}),
|
|
271
288
|
...('amount' in params && params.amount != null ? { amount: params.amount } : {}),
|
|
272
289
|
...('entireAmount' in params && params.entireAmount ? { entireAmount: true as const } : {}),
|
|
@@ -274,5 +291,7 @@ export async function getWithdrawTx(
|
|
|
274
291
|
|
|
275
292
|
const steps = await adapter.buildWithdraw(withdrawParams as AdapterWithdrawParams);
|
|
276
293
|
|
|
277
|
-
return await Promise.all(
|
|
294
|
+
return await Promise.all(
|
|
295
|
+
steps.map((step) => encodeTransactionWithAttribution(client, step, chainId))
|
|
296
|
+
);
|
|
278
297
|
}
|
package/src/evm/withdrawQuote.ts
CHANGED