@gauntlet-xyz/sdk 2.3.0 → 2.5.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 (86) hide show
  1. package/README.md +52 -0
  2. package/dist/api/client.d.ts +22 -1
  3. package/dist/api/client.d.ts.map +1 -1
  4. package/dist/api/client.js +11 -1
  5. package/dist/api/client.js.map +1 -1
  6. package/dist/api/generated.d.ts +51 -7
  7. package/dist/api/generated.d.ts.map +1 -1
  8. package/dist/api/index.d.ts +1 -1
  9. package/dist/api/index.d.ts.map +1 -1
  10. package/dist/api/index.js.map +1 -1
  11. package/dist/errors.d.ts +11 -0
  12. package/dist/errors.d.ts.map +1 -1
  13. package/dist/errors.js +21 -2
  14. package/dist/errors.js.map +1 -1
  15. package/dist/evm/abis/priceAndFeeCalculatorV2.d.ts +44 -0
  16. package/dist/evm/abis/priceAndFeeCalculatorV2.d.ts.map +1 -1
  17. package/dist/evm/abis/priceAndFeeCalculatorV2.js +22 -0
  18. package/dist/evm/abis/priceAndFeeCalculatorV2.js.map +1 -1
  19. package/dist/evm/abis/provisionerV2.d.ts +56 -0
  20. package/dist/evm/abis/provisionerV2.d.ts.map +1 -1
  21. package/dist/evm/abis/provisionerV2.js +33 -0
  22. package/dist/evm/abis/provisionerV2.js.map +1 -1
  23. package/dist/evm/adapters/aera.d.ts.map +1 -1
  24. package/dist/evm/adapters/aera.js +41 -10
  25. package/dist/evm/adapters/aera.js.map +1 -1
  26. package/dist/evm/adapters/types.d.ts +2 -0
  27. package/dist/evm/adapters/types.d.ts.map +1 -1
  28. package/dist/evm/aeraContracts/priceAndFeeCalculator.d.ts +10 -5
  29. package/dist/evm/aeraContracts/priceAndFeeCalculator.d.ts.map +1 -1
  30. package/dist/evm/aeraContracts/priceAndFeeCalculator.js +39 -5
  31. package/dist/evm/aeraContracts/priceAndFeeCalculator.js.map +1 -1
  32. package/dist/evm/aeraContracts/readOptions.d.ts +8 -0
  33. package/dist/evm/aeraContracts/readOptions.d.ts.map +1 -0
  34. package/dist/evm/aeraContracts/readOptions.js +4 -0
  35. package/dist/evm/aeraContracts/readOptions.js.map +1 -0
  36. package/dist/evm/aeraContracts/v2.d.ts +373 -2
  37. package/dist/evm/aeraContracts/v2.d.ts.map +1 -1
  38. package/dist/evm/aeraContracts/v2.js +84 -28
  39. package/dist/evm/aeraContracts/v2.js.map +1 -1
  40. package/dist/evm/aeraContracts.d.ts +9 -3
  41. package/dist/evm/aeraContracts.d.ts.map +1 -1
  42. package/dist/evm/aeraContracts.js +69 -8
  43. package/dist/evm/aeraContracts.js.map +1 -1
  44. package/dist/evm/deposit.d.ts.map +1 -1
  45. package/dist/evm/deposit.js +1 -1
  46. package/dist/evm/deposit.js.map +1 -1
  47. package/dist/evm/index.d.ts +8 -0
  48. package/dist/evm/index.d.ts.map +1 -1
  49. package/dist/evm/index.js +3 -0
  50. package/dist/evm/index.js.map +1 -1
  51. package/dist/evm/tokenModes.d.ts +22 -0
  52. package/dist/evm/tokenModes.d.ts.map +1 -0
  53. package/dist/evm/tokenModes.js +34 -0
  54. package/dist/evm/tokenModes.js.map +1 -0
  55. package/dist/evm/withdraw.d.ts +8 -0
  56. package/dist/evm/withdraw.d.ts.map +1 -1
  57. package/dist/evm/withdraw.js +85 -5
  58. package/dist/evm/withdraw.js.map +1 -1
  59. package/dist/evm/withdrawQuote.d.ts +127 -0
  60. package/dist/evm/withdrawQuote.d.ts.map +1 -0
  61. package/dist/evm/withdrawQuote.js +164 -0
  62. package/dist/evm/withdrawQuote.js.map +1 -0
  63. package/dist/index.d.ts +7 -1
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +3 -1
  66. package/dist/index.js.map +1 -1
  67. package/manifest/vaults.json +112 -154
  68. package/package.json +1 -1
  69. package/src/api/client.ts +35 -2
  70. package/src/api/generated.ts +51 -7
  71. package/src/api/index.ts +5 -0
  72. package/src/errors.ts +32 -2
  73. package/src/evm/abis/priceAndFeeCalculatorV2.ts +22 -0
  74. package/src/evm/abis/provisionerV2.ts +33 -0
  75. package/src/evm/adapters/aera.ts +50 -23
  76. package/src/evm/adapters/types.ts +2 -0
  77. package/src/evm/aeraContracts/priceAndFeeCalculator.ts +72 -5
  78. package/src/evm/aeraContracts/readOptions.ts +3 -0
  79. package/src/evm/aeraContracts/v2.ts +158 -34
  80. package/src/evm/aeraContracts.ts +81 -8
  81. package/src/evm/deposit.ts +2 -1
  82. package/src/evm/index.ts +32 -0
  83. package/src/evm/tokenModes.ts +54 -0
  84. package/src/evm/withdraw.ts +131 -7
  85. package/src/evm/withdrawQuote.ts +360 -0
  86. package/src/index.ts +16 -0
@@ -1,6 +1,13 @@
1
1
  // Compact ABI derived from aera-finance/aera-contracts-v3@f4e3433058c29c3a0b1348ffbd358cc036a1687f
2
2
  // source: src/core/interfaces/IProvisionerV2.sol
3
3
  export const provisionerV2Abi = [
4
+ {
5
+ type: 'function',
6
+ inputs: [],
7
+ name: 'SOLVING_GATE_ENABLED',
8
+ outputs: [{ name: '', internalType: 'bool', type: 'bool' }],
9
+ stateMutability: 'view',
10
+ },
4
11
  {
5
12
  type: 'function',
6
13
  inputs: [
@@ -53,6 +60,25 @@ export const provisionerV2Abi = [
53
60
  ],
54
61
  stateMutability: 'view',
55
62
  },
63
+ {
64
+ type: 'function',
65
+ inputs: [],
66
+ name: 'getSyncRedeemEpochState',
67
+ outputs: [
68
+ { name: 'epochTimestamp', internalType: 'uint256', type: 'uint256' },
69
+ { name: 'epochStartTvlNumeraire', internalType: 'uint256', type: 'uint256' },
70
+ { name: 'epochRedeemedNumeraire', internalType: 'uint256', type: 'uint256' },
71
+ { name: 'epochCapNumeraire', internalType: 'uint256', type: 'uint256' },
72
+ ],
73
+ stateMutability: 'view',
74
+ },
75
+ {
76
+ type: 'function',
77
+ inputs: [{ name: 'user', internalType: 'address', type: 'address' }],
78
+ name: 'userUnitsRefundableUntil',
79
+ outputs: [{ name: 'unitsLockedUntil', internalType: 'uint256', type: 'uint256' }],
80
+ stateMutability: 'view',
81
+ },
56
82
  {
57
83
  type: 'function',
58
84
  inputs: [
@@ -63,6 +89,13 @@ export const provisionerV2Abi = [
63
89
  outputs: [],
64
90
  stateMutability: 'nonpayable',
65
91
  },
92
+ {
93
+ type: 'function',
94
+ inputs: [],
95
+ name: 'solvingGate',
96
+ outputs: [{ name: '', internalType: 'address', type: 'address' }],
97
+ stateMutability: 'view',
98
+ },
66
99
  {
67
100
  type: 'function',
68
101
  inputs: [{ name: 'token', internalType: 'contract IERC20', type: 'address' }],
@@ -3,6 +3,7 @@ import {
3
3
  getMultiDepositorVault,
4
4
  applySlippageDown,
5
5
  applySlippageUp,
6
+ requireAeraSyncRedeemRuntime,
6
7
  resolveContractVersion,
7
8
  type AeraRuntimeContracts,
8
9
  } from '../aeraContracts';
@@ -12,6 +13,7 @@ import * as provisionerV2 from '../aeraContracts/v2';
12
13
  import {
13
14
  InvalidWithdrawParamsError,
14
15
  InvalidSolverTipError,
16
+ requireNonZeroSyncWithdrawBound,
15
17
  UnimplementedFeatureError,
16
18
  UnsupportedFeatureError,
17
19
  } from '../../errors';
@@ -321,9 +323,7 @@ export const aeraAdapter: EvmProtocolAdapter = {
321
323
  throw new UnsupportedFeatureError('Aera: separate receiver address on V1');
322
324
  }
323
325
 
324
- if (!isAsync && !isContractV2) {
325
- throw new UnsupportedFeatureError('Aera: sync operations on V1');
326
- }
326
+ if (!isAsync) requireAeraSyncRedeemRuntime(runtime);
327
327
 
328
328
  const isV2ExactTokenWithdraw =
329
329
  isContractV2 && !isAsync && 'amount' in params && params.amount != null;
@@ -332,40 +332,66 @@ export const aeraAdapter: EvmProtocolAdapter = {
332
332
  let shares: bigint | undefined;
333
333
 
334
334
  if (isContractV2 && !isAsync) {
335
+ const quote = params.syncWithdrawQuote;
335
336
  if ('entireAmount' in params && params.entireAmount) {
336
- shares = await publicClient.readContract({
337
+ const balance = await publicClient.readContract({
337
338
  address: vault.vaultAddress,
338
339
  abi: multiDepositorVaultAbi,
339
340
  functionName: 'balanceOf',
340
341
  args: [account],
341
342
  });
343
+ if (quote !== undefined) {
344
+ if (quote.kind !== 'redeem' || quote.shares !== balance) {
345
+ throw new InvalidWithdrawParamsError();
346
+ }
347
+ }
348
+ shares = balance;
342
349
  } else if ('shares' in params && params.shares != null) {
350
+ if (quote !== undefined && (quote.kind !== 'redeem' || quote.shares !== params.shares)) {
351
+ throw new InvalidWithdrawParamsError();
352
+ }
343
353
  shares = params.shares;
344
354
  } else if (!('amount' in params && params.amount != null)) {
345
355
  throw new InvalidWithdrawParamsError();
346
356
  }
347
357
 
348
358
  if (isV2ExactTokenWithdraw) {
349
- minTokenOut = applySlippageDown(params.amount, slippageBps);
350
- maxUnitsIn = applySlippageUp(
351
- await provisionerV2.getSyncWithdrawUnitsIn(
352
- publicClient,
353
- provisionerAddress,
354
- runtime.feeCalculator.address,
355
- runtime.feeCalculator.version,
356
- vault.vaultAddress,
357
- asset.address,
358
- params.amount
359
- ),
360
- slippageBps
361
- );
359
+ requireNonZeroSyncWithdrawBound(params.amount, 'tokensOut');
360
+ if (quote !== undefined) {
361
+ if (quote.kind !== 'withdraw' || quote.tokensOut !== params.amount) {
362
+ throw new InvalidWithdrawParamsError();
363
+ }
364
+ minTokenOut = quote.tokensOut;
365
+ maxUnitsIn = quote.maxUnitsIn;
366
+ } else {
367
+ minTokenOut = params.amount;
368
+ maxUnitsIn = applySlippageUp(
369
+ await provisionerV2.getSyncWithdrawUnitsIn(
370
+ publicClient,
371
+ provisionerAddress,
372
+ runtime.feeCalculator.address,
373
+ runtime.feeCalculator.version,
374
+ vault.vaultAddress,
375
+ asset.address,
376
+ params.amount
377
+ ),
378
+ slippageBps
379
+ );
380
+ }
381
+ requireNonZeroSyncWithdrawBound(maxUnitsIn, 'maxUnitsIn');
362
382
  } else {
363
383
  if (shares === undefined) {
364
384
  throw new InvalidWithdrawParamsError();
365
385
  }
366
386
 
367
- minTokenOut = applySlippageDown(
368
- await provisionerV2.getSyncRedeemTokenOut(
387
+ requireNonZeroSyncWithdrawBound(shares, 'unitsIn');
388
+ if (quote !== undefined) {
389
+ if (quote.kind !== 'redeem' || quote.shares !== shares) {
390
+ throw new InvalidWithdrawParamsError();
391
+ }
392
+ minTokenOut = quote.minTokensOut;
393
+ } else {
394
+ const tokensOut = await provisionerV2.getSyncRedeemTokenOut(
369
395
  publicClient,
370
396
  provisionerAddress,
371
397
  runtime.feeCalculator.address,
@@ -373,10 +399,11 @@ export const aeraAdapter: EvmProtocolAdapter = {
373
399
  vault.vaultAddress,
374
400
  asset.address,
375
401
  shares
376
- ),
377
- slippageBps
378
- );
379
- maxUnitsIn = applySlippageUp(shares, slippageBps);
402
+ );
403
+ minTokenOut = applySlippageDown(tokensOut, slippageBps);
404
+ }
405
+ requireNonZeroSyncWithdrawBound(minTokenOut, 'minTokensOut');
406
+ maxUnitsIn = shares;
380
407
  }
381
408
  } else {
382
409
  if ('entireAmount' in params && params.entireAmount) {
@@ -1,5 +1,6 @@
1
1
  import type { Abi, Address, Hex, PublicClient } from 'viem';
2
2
  import type { AeraRuntimeContracts } from '../aeraContracts';
3
+ import type { SyncWithdrawQuoteBounds } from '../withdrawQuote';
3
4
  import type { TokenInfo, VaultDeployment } from '../types';
4
5
 
5
6
  export interface EvmTxStep<TAbi extends Abi = Abi, TFunctionName extends string = string> {
@@ -53,6 +54,7 @@ export type AdapterWithdrawParams = {
53
54
  /** Maximum price age passed to async Aera provisioner requests. Defaults to 10 days. */
54
55
  maxPriceAge?: bigint;
55
56
  aeraRuntime?: AeraRuntimeContracts;
57
+ syncWithdrawQuote?: SyncWithdrawQuoteBounds;
56
58
  } & (
57
59
  | { shares: bigint; amount?: never; entireAmount?: never }
58
60
  | { amount: bigint; shares?: never; entireAmount?: never }
@@ -3,6 +3,7 @@ import { UnsupportedFeatureError } from '../../errors';
3
3
  import { priceAndFeeCalculatorAbi } from '../abis/priceAndFeeCalculator';
4
4
  import { priceAndFeeCalculatorV2Abi } from '../abis/priceAndFeeCalculatorV2';
5
5
  import { ContractVersion } from '../types';
6
+ import { readAtBlock } from './readOptions';
6
7
 
7
8
  const ROUNDING_FLOOR = 0;
8
9
  const ROUNDING_CEIL = 1;
@@ -13,6 +14,10 @@ export interface NormalizedVaultPriceState {
13
14
  timestamp: number;
14
15
  }
15
16
 
17
+ type AeraPriceReadOptions = {
18
+ blockNumber?: bigint;
19
+ };
20
+
16
21
  function toNumber(value: bigint | number): number {
17
22
  return typeof value === 'bigint' ? Number(value) : value;
18
23
  }
@@ -54,7 +59,8 @@ export async function convertTokenToUnitsIfActive(
54
59
  vault: Address,
55
60
  token: Address,
56
61
  tokenAmount: bigint,
57
- rounding: typeof ROUNDING_FLOOR | typeof ROUNDING_CEIL
62
+ rounding: typeof ROUNDING_FLOOR | typeof ROUNDING_CEIL,
63
+ options: AeraPriceReadOptions = {}
58
64
  ): Promise<bigint> {
59
65
  if (feeCalculatorVersion === ContractVersion.V2) {
60
66
  return client.readContract({
@@ -62,6 +68,7 @@ export async function convertTokenToUnitsIfActive(
62
68
  abi: priceAndFeeCalculatorV2Abi,
63
69
  functionName: 'convertTokenToUnitsIfActive',
64
70
  args: [vault, token, tokenAmount, rounding],
71
+ ...readAtBlock(options),
65
72
  });
66
73
  }
67
74
 
@@ -70,6 +77,7 @@ export async function convertTokenToUnitsIfActive(
70
77
  abi: priceAndFeeCalculatorAbi,
71
78
  functionName: 'convertTokenToUnitsIfActive',
72
79
  args: [vault, token, tokenAmount, rounding],
80
+ ...readAtBlock(options),
73
81
  });
74
82
  }
75
83
 
@@ -80,7 +88,8 @@ export async function convertUnitsToTokenIfActive(
80
88
  vault: Address,
81
89
  token: Address,
82
90
  unitsAmount: bigint,
83
- rounding: typeof ROUNDING_FLOOR | typeof ROUNDING_CEIL
91
+ rounding: typeof ROUNDING_FLOOR | typeof ROUNDING_CEIL,
92
+ options: AeraPriceReadOptions = {}
84
93
  ): Promise<bigint> {
85
94
  if (feeCalculatorVersion === ContractVersion.V2) {
86
95
  return client.readContract({
@@ -88,6 +97,7 @@ export async function convertUnitsToTokenIfActive(
88
97
  abi: priceAndFeeCalculatorV2Abi,
89
98
  functionName: 'convertUnitsToTokenIfActive',
90
99
  args: [vault, token, unitsAmount, rounding],
100
+ ...readAtBlock(options),
91
101
  });
92
102
  }
93
103
 
@@ -96,6 +106,7 @@ export async function convertUnitsToTokenIfActive(
96
106
  abi: priceAndFeeCalculatorAbi,
97
107
  functionName: 'convertUnitsToTokenIfActive',
98
108
  args: [vault, token, unitsAmount, rounding],
109
+ ...readAtBlock(options),
99
110
  });
100
111
  }
101
112
 
@@ -105,7 +116,8 @@ export async function convertTokenToUnits(
105
116
  feeCalculatorVersion: ContractVersion,
106
117
  vault: Address,
107
118
  token: Address,
108
- tokenAmount: bigint
119
+ tokenAmount: bigint,
120
+ options: AeraPriceReadOptions = {}
109
121
  ): Promise<bigint> {
110
122
  if (feeCalculatorVersion === ContractVersion.V2) {
111
123
  return client.readContract({
@@ -113,6 +125,7 @@ export async function convertTokenToUnits(
113
125
  abi: priceAndFeeCalculatorV2Abi,
114
126
  functionName: 'convertTokenToUnits',
115
127
  args: [vault, token, tokenAmount],
128
+ ...readAtBlock(options),
116
129
  });
117
130
  }
118
131
 
@@ -121,6 +134,7 @@ export async function convertTokenToUnits(
121
134
  abi: priceAndFeeCalculatorAbi,
122
135
  functionName: 'convertTokenToUnits',
123
136
  args: [vault, token, tokenAmount],
137
+ ...readAtBlock(options),
124
138
  });
125
139
  }
126
140
 
@@ -130,7 +144,8 @@ export async function convertUnitsToToken(
130
144
  feeCalculatorVersion: ContractVersion,
131
145
  vault: Address,
132
146
  token: Address,
133
- unitsAmount: bigint
147
+ unitsAmount: bigint,
148
+ options: AeraPriceReadOptions = {}
134
149
  ): Promise<bigint> {
135
150
  if (feeCalculatorVersion === ContractVersion.V2) {
136
151
  return client.readContract({
@@ -138,6 +153,7 @@ export async function convertUnitsToToken(
138
153
  abi: priceAndFeeCalculatorV2Abi,
139
154
  functionName: 'convertUnitsToToken',
140
155
  args: [vault, token, unitsAmount],
156
+ ...readAtBlock(options),
141
157
  });
142
158
  }
143
159
 
@@ -146,6 +162,55 @@ export async function convertUnitsToToken(
146
162
  abi: priceAndFeeCalculatorAbi,
147
163
  functionName: 'convertUnitsToToken',
148
164
  args: [vault, token, unitsAmount],
165
+ ...readAtBlock(options),
166
+ });
167
+ }
168
+
169
+ export async function convertTokenToNumeraire(
170
+ client: PublicClient,
171
+ feeCalculator: Address,
172
+ feeCalculatorVersion: ContractVersion,
173
+ vault: Address,
174
+ token: Address,
175
+ tokenAmount: bigint,
176
+ options: AeraPriceReadOptions = {}
177
+ ): Promise<bigint> {
178
+ if (feeCalculatorVersion !== ContractVersion.V2) {
179
+ throw new UnsupportedFeatureError(
180
+ 'Aera: numeraire conversion requires V2 price and fee calculator'
181
+ );
182
+ }
183
+
184
+ return client.readContract({
185
+ address: feeCalculator,
186
+ abi: priceAndFeeCalculatorV2Abi,
187
+ functionName: 'convertTokenToNumeraire',
188
+ args: [vault, token, tokenAmount],
189
+ ...readAtBlock(options),
190
+ });
191
+ }
192
+
193
+ export async function convertNumeraireToToken(
194
+ client: PublicClient,
195
+ feeCalculator: Address,
196
+ feeCalculatorVersion: ContractVersion,
197
+ vault: Address,
198
+ token: Address,
199
+ numeraireAmount: bigint,
200
+ options: AeraPriceReadOptions = {}
201
+ ): Promise<bigint> {
202
+ if (feeCalculatorVersion !== ContractVersion.V2) {
203
+ throw new UnsupportedFeatureError(
204
+ 'Aera: numeraire conversion requires V2 price and fee calculator'
205
+ );
206
+ }
207
+
208
+ return client.readContract({
209
+ address: feeCalculator,
210
+ abi: priceAndFeeCalculatorV2Abi,
211
+ functionName: 'convertNumeraireToToken',
212
+ args: [vault, token, numeraireAmount],
213
+ ...readAtBlock(options),
149
214
  });
150
215
  }
151
216
 
@@ -153,7 +218,8 @@ export async function getAnchorTimestamp(
153
218
  client: PublicClient,
154
219
  feeCalculator: Address,
155
220
  feeCalculatorVersion: ContractVersion,
156
- vault: Address
221
+ vault: Address,
222
+ options: AeraPriceReadOptions = {}
157
223
  ): Promise<number> {
158
224
  if (feeCalculatorVersion !== ContractVersion.V2) {
159
225
  throw new UnsupportedFeatureError('Aera: sync redeem requires V2 price and fee calculator');
@@ -164,6 +230,7 @@ export async function getAnchorTimestamp(
164
230
  abi: priceAndFeeCalculatorV2Abi,
165
231
  functionName: 'getAnchorTimestamp',
166
232
  args: [vault],
233
+ ...readAtBlock(options),
167
234
  });
168
235
  }
169
236
 
@@ -0,0 +1,3 @@
1
+ export function readAtBlock(options: { blockNumber?: bigint } = {}) {
2
+ return options.blockNumber === undefined ? {} : { blockNumber: options.blockNumber };
3
+ }