@gauntlet-xyz/sdk 2.0.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.
- package/README.md +134 -1
- package/dist/api/activity.d.ts +70 -0
- package/dist/api/activity.d.ts.map +1 -0
- package/dist/api/activity.js +154 -0
- package/dist/api/activity.js.map +1 -0
- package/dist/api/caip.d.ts +29 -0
- package/dist/api/caip.d.ts.map +1 -0
- package/dist/api/caip.js +38 -0
- package/dist/api/caip.js.map +1 -0
- package/dist/api/client.d.ts +135 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +119 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/decimal.d.ts +21 -0
- package/dist/api/decimal.d.ts.map +1 -0
- package/dist/api/decimal.js +44 -0
- package/dist/api/decimal.js.map +1 -0
- package/dist/api/errors.d.ts +32 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +41 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/generated.d.ts +1505 -0
- package/dist/api/generated.d.ts.map +1 -0
- package/dist/api/generated.js +6 -0
- package/dist/api/generated.js.map +1 -0
- package/dist/api/http.d.ts +16 -0
- package/dist/api/http.d.ts.map +1 -0
- package/dist/api/http.js +39 -0
- package/dist/api/http.js.map +1 -0
- package/dist/api/index.d.ts +14 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +8 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/positionHistory.d.ts +44 -0
- package/dist/api/positionHistory.d.ts.map +1 -0
- package/dist/api/positionHistory.js +126 -0
- package/dist/api/positionHistory.js.map +1 -0
- package/dist/client.d.ts +6 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +11 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +21 -2
- package/dist/errors.js.map +1 -1
- package/dist/evm/abis/priceAndFeeCalculatorV2.d.ts +44 -0
- package/dist/evm/abis/priceAndFeeCalculatorV2.d.ts.map +1 -1
- package/dist/evm/abis/priceAndFeeCalculatorV2.js +22 -0
- package/dist/evm/abis/priceAndFeeCalculatorV2.js.map +1 -1
- package/dist/evm/abis/provisionerV2.d.ts +280 -0
- package/dist/evm/abis/provisionerV2.d.ts.map +1 -1
- package/dist/evm/abis/provisionerV2.js +92 -0
- package/dist/evm/abis/provisionerV2.js.map +1 -1
- package/dist/evm/adapters/aera.d.ts.map +1 -1
- package/dist/evm/adapters/aera.js +41 -10
- package/dist/evm/adapters/aera.js.map +1 -1
- package/dist/evm/adapters/types.d.ts +2 -0
- package/dist/evm/adapters/types.d.ts.map +1 -1
- package/dist/evm/aeraContracts/priceAndFeeCalculator.d.ts +10 -5
- package/dist/evm/aeraContracts/priceAndFeeCalculator.d.ts.map +1 -1
- package/dist/evm/aeraContracts/priceAndFeeCalculator.js +39 -5
- package/dist/evm/aeraContracts/priceAndFeeCalculator.js.map +1 -1
- package/dist/evm/aeraContracts/readOptions.d.ts +8 -0
- package/dist/evm/aeraContracts/readOptions.d.ts.map +1 -0
- package/dist/evm/aeraContracts/readOptions.js +4 -0
- package/dist/evm/aeraContracts/readOptions.js.map +1 -0
- package/dist/evm/aeraContracts/v2.d.ts +1932 -217
- package/dist/evm/aeraContracts/v2.d.ts.map +1 -1
- package/dist/evm/aeraContracts/v2.js +84 -28
- package/dist/evm/aeraContracts/v2.js.map +1 -1
- package/dist/evm/aeraContracts.d.ts +9 -3
- package/dist/evm/aeraContracts.d.ts.map +1 -1
- package/dist/evm/aeraContracts.js +69 -8
- package/dist/evm/aeraContracts.js.map +1 -1
- package/dist/evm/deposit.d.ts.map +1 -1
- package/dist/evm/deposit.js +1 -1
- package/dist/evm/deposit.js.map +1 -1
- package/dist/evm/index.d.ts +8 -0
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +3 -0
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/tokenModes.d.ts +22 -0
- package/dist/evm/tokenModes.d.ts.map +1 -0
- package/dist/evm/tokenModes.js +34 -0
- package/dist/evm/tokenModes.js.map +1 -0
- package/dist/evm/withdraw.d.ts +8 -0
- package/dist/evm/withdraw.d.ts.map +1 -1
- package/dist/evm/withdraw.js +85 -5
- package/dist/evm/withdraw.js.map +1 -1
- package/dist/evm/withdrawQuote.d.ts +127 -0
- package/dist/evm/withdrawQuote.d.ts.map +1 -0
- package/dist/evm/withdrawQuote.js +164 -0
- package/dist/evm/withdrawQuote.js.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/privy/index.d.ts +52 -0
- package/dist/privy/index.d.ts.map +1 -0
- package/dist/privy/index.js +51 -0
- package/dist/privy/index.js.map +1 -0
- package/manifest/vaults.json +255 -3
- package/package.json +2 -2
- package/src/api/activity.ts +219 -0
- package/src/api/caip.ts +61 -0
- package/src/api/client.ts +234 -0
- package/src/api/decimal.ts +49 -0
- package/src/api/errors.ts +64 -0
- package/src/api/generated.ts +1505 -0
- package/src/api/http.ts +62 -0
- package/src/api/index.ts +70 -0
- package/src/api/positionHistory.ts +167 -0
- package/src/client.ts +7 -1
- package/src/errors.ts +32 -2
- package/src/evm/abis/priceAndFeeCalculatorV2.ts +22 -0
- package/src/evm/abis/provisionerV2.ts +92 -0
- package/src/evm/adapters/aera.ts +50 -23
- package/src/evm/adapters/types.ts +2 -0
- package/src/evm/aeraContracts/priceAndFeeCalculator.ts +72 -5
- package/src/evm/aeraContracts/readOptions.ts +3 -0
- package/src/evm/aeraContracts/v2.ts +158 -34
- package/src/evm/aeraContracts.ts +81 -8
- package/src/evm/deposit.ts +2 -1
- package/src/evm/index.ts +32 -0
- package/src/evm/tokenModes.ts +54 -0
- package/src/evm/withdraw.ts +131 -7
- package/src/evm/withdrawQuote.ts +360 -0
- package/src/index.ts +18 -0
- package/src/privy/index.ts +95 -0
|
@@ -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
|
|
|
@@ -13,8 +13,9 @@ import {
|
|
|
13
13
|
convertUnitsToTokenIfActive,
|
|
14
14
|
} from './priceAndFeeCalculator';
|
|
15
15
|
import { MAX_BPS } from '../../constants';
|
|
16
|
-
import { StalePriceError } from '../../errors';
|
|
16
|
+
import { StalePriceError, UnsupportedFeatureError } from '../../errors';
|
|
17
17
|
import type { ContractVersion } from '../types';
|
|
18
|
+
import { readAtBlock } from './readOptions';
|
|
18
19
|
|
|
19
20
|
export type PriceAndFeeCalculatorContract<T extends Client> = GetContractReturnType<
|
|
20
21
|
typeof priceAndFeeCalculatorV2Abi,
|
|
@@ -33,16 +34,44 @@ export function getPriceAndFeeCalculator<T extends Client>(
|
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
type SyncRedeemReadOptions = {
|
|
38
|
+
blockNumber?: bigint;
|
|
39
|
+
blockTimestamp?: bigint;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
async function resolveReadContext(
|
|
43
|
+
client: PublicClient,
|
|
44
|
+
options: SyncRedeemReadOptions = {}
|
|
45
|
+
): Promise<Required<SyncRedeemReadOptions>> {
|
|
46
|
+
if (options.blockNumber !== undefined && options.blockTimestamp !== undefined) {
|
|
47
|
+
return { blockNumber: options.blockNumber, blockTimestamp: options.blockTimestamp };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const block =
|
|
51
|
+
options.blockNumber === undefined ? await client.getBlock() : await client.getBlock(options);
|
|
52
|
+
if (block.number === null) {
|
|
53
|
+
throw new UnsupportedFeatureError('Aera: sync redeem reads require a numbered block');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
blockNumber: options.blockNumber ?? block.number,
|
|
58
|
+
blockTimestamp: options.blockTimestamp ?? BigInt(block.timestamp),
|
|
59
|
+
};
|
|
42
60
|
}
|
|
43
61
|
|
|
44
|
-
async function getTokenDetails(
|
|
45
|
-
|
|
62
|
+
async function getTokenDetails(
|
|
63
|
+
client: PublicClient,
|
|
64
|
+
provisioner: Address,
|
|
65
|
+
token: Address,
|
|
66
|
+
options: SyncRedeemReadOptions = {}
|
|
67
|
+
) {
|
|
68
|
+
return client.readContract({
|
|
69
|
+
address: provisioner,
|
|
70
|
+
abi: provisionerV2Abi,
|
|
71
|
+
functionName: 'tokensDetails',
|
|
72
|
+
args: [token],
|
|
73
|
+
...readAtBlock(options),
|
|
74
|
+
});
|
|
46
75
|
}
|
|
47
76
|
|
|
48
77
|
async function getDepositUnitsOut({
|
|
@@ -54,6 +83,7 @@ async function getDepositUnitsOut({
|
|
|
54
83
|
token,
|
|
55
84
|
tokensIn,
|
|
56
85
|
multiplierIndex,
|
|
86
|
+
options,
|
|
57
87
|
}: {
|
|
58
88
|
client: PublicClient;
|
|
59
89
|
provisioner: Address;
|
|
@@ -63,8 +93,9 @@ async function getDepositUnitsOut({
|
|
|
63
93
|
token: Address;
|
|
64
94
|
tokensIn: bigint;
|
|
65
95
|
multiplierIndex: 4 | 6;
|
|
96
|
+
options?: SyncRedeemReadOptions;
|
|
66
97
|
}): Promise<bigint> {
|
|
67
|
-
const tokenDetails = await getTokenDetails(client, provisioner, token);
|
|
98
|
+
const tokenDetails = await getTokenDetails(client, provisioner, token, options);
|
|
68
99
|
const multiplier = BigInt(tokenDetails[multiplierIndex]);
|
|
69
100
|
const adjustedTokensIn = (tokensIn * multiplier) / MAX_BPS;
|
|
70
101
|
|
|
@@ -75,7 +106,8 @@ async function getDepositUnitsOut({
|
|
|
75
106
|
vault,
|
|
76
107
|
token,
|
|
77
108
|
adjustedTokensIn,
|
|
78
|
-
Rounding.Floor
|
|
109
|
+
Rounding.Floor,
|
|
110
|
+
options
|
|
79
111
|
);
|
|
80
112
|
}
|
|
81
113
|
|
|
@@ -88,6 +120,7 @@ async function getRedeemTokenOut({
|
|
|
88
120
|
token,
|
|
89
121
|
unitsIn,
|
|
90
122
|
multiplierIndex,
|
|
123
|
+
options,
|
|
91
124
|
}: {
|
|
92
125
|
client: PublicClient;
|
|
93
126
|
provisioner: Address;
|
|
@@ -97,9 +130,10 @@ async function getRedeemTokenOut({
|
|
|
97
130
|
token: Address;
|
|
98
131
|
unitsIn: bigint;
|
|
99
132
|
multiplierIndex: 5 | 7;
|
|
133
|
+
options?: SyncRedeemReadOptions;
|
|
100
134
|
}): Promise<bigint> {
|
|
101
135
|
const [tokenDetails, tokensOut] = await Promise.all([
|
|
102
|
-
getTokenDetails(client, provisioner, token),
|
|
136
|
+
getTokenDetails(client, provisioner, token, options),
|
|
103
137
|
convertUnitsToTokenIfActive(
|
|
104
138
|
client,
|
|
105
139
|
feeCalculator,
|
|
@@ -107,7 +141,8 @@ async function getRedeemTokenOut({
|
|
|
107
141
|
vault,
|
|
108
142
|
token,
|
|
109
143
|
unitsIn,
|
|
110
|
-
Rounding.Floor
|
|
144
|
+
Rounding.Floor,
|
|
145
|
+
options
|
|
111
146
|
),
|
|
112
147
|
]);
|
|
113
148
|
const multiplier = BigInt(tokenDetails[multiplierIndex]);
|
|
@@ -124,6 +159,7 @@ async function getWithdrawUnitsIn({
|
|
|
124
159
|
token,
|
|
125
160
|
tokensOut,
|
|
126
161
|
multiplierIndex,
|
|
162
|
+
options,
|
|
127
163
|
}: {
|
|
128
164
|
client: PublicClient;
|
|
129
165
|
provisioner: Address;
|
|
@@ -133,8 +169,9 @@ async function getWithdrawUnitsIn({
|
|
|
133
169
|
token: Address;
|
|
134
170
|
tokensOut: bigint;
|
|
135
171
|
multiplierIndex: 5 | 7;
|
|
172
|
+
options?: SyncRedeemReadOptions;
|
|
136
173
|
}): Promise<bigint> {
|
|
137
|
-
const tokenDetails = await getTokenDetails(client, provisioner, token);
|
|
174
|
+
const tokenDetails = await getTokenDetails(client, provisioner, token, options);
|
|
138
175
|
const multiplier = BigInt(tokenDetails[multiplierIndex]);
|
|
139
176
|
const preMultiplierTokens = (tokensOut * MAX_BPS + multiplier - 1n) / multiplier;
|
|
140
177
|
|
|
@@ -145,17 +182,37 @@ async function getWithdrawUnitsIn({
|
|
|
145
182
|
vault,
|
|
146
183
|
token,
|
|
147
184
|
preMultiplierTokens,
|
|
148
|
-
Rounding.Ceil
|
|
185
|
+
Rounding.Ceil,
|
|
186
|
+
options
|
|
149
187
|
);
|
|
150
188
|
}
|
|
151
189
|
|
|
152
|
-
|
|
190
|
+
/** Breakdown of the effective sync redeem multiplier, in basis points. */
|
|
191
|
+
export interface SyncRedeemRate {
|
|
192
|
+
/** Base sync redeem multiplier (tokensDetails.syncRedeemMultiplier). */
|
|
193
|
+
baseMultiplierBps: bigint;
|
|
194
|
+
/** Dynamic premium charged for the current oracle price age. */
|
|
195
|
+
dynamicPremiumBps: bigint;
|
|
196
|
+
/** Multiplier actually applied to size the redemption (base - dynamic premium). */
|
|
197
|
+
effectiveMultiplierBps: bigint;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Reads the live sync redeem rate, replicating the provisioner's effective-multiplier
|
|
202
|
+
* derivation (base multiplier minus a price-age-proportional dynamic premium).
|
|
203
|
+
*
|
|
204
|
+
* @throws {StalePriceError} If the oracle price is older than the configured max age,
|
|
205
|
+
* in which case the on-chain sync redeem would revert.
|
|
206
|
+
*/
|
|
207
|
+
export async function getSyncRedeemRate(
|
|
153
208
|
client: PublicClient,
|
|
154
209
|
provisioner: Address,
|
|
155
210
|
vault: Address,
|
|
156
211
|
token: Address,
|
|
157
|
-
feeCalculator: Address
|
|
158
|
-
|
|
212
|
+
feeCalculator: Address,
|
|
213
|
+
options: SyncRedeemReadOptions = {}
|
|
214
|
+
): Promise<SyncRedeemRate> {
|
|
215
|
+
const readContext = await resolveReadContext(client, options);
|
|
159
216
|
const [tokenDetails, syncRedeemDetails, anchorTimestamp] = await client.multicall({
|
|
160
217
|
contracts: [
|
|
161
218
|
{
|
|
@@ -177,12 +234,12 @@ async function getSyncRedeemMultiplier(
|
|
|
177
234
|
},
|
|
178
235
|
],
|
|
179
236
|
allowFailure: false,
|
|
237
|
+
blockNumber: readContext.blockNumber,
|
|
180
238
|
});
|
|
181
|
-
const
|
|
182
|
-
const syncRedeemMultiplier = BigInt(tokenDetails[7]);
|
|
239
|
+
const baseMultiplierBps = BigInt(tokenDetails[7]);
|
|
183
240
|
const maxPriceAge = BigInt(syncRedeemDetails[0]);
|
|
184
241
|
const maxDynamicPremiumBps = BigInt(syncRedeemDetails[2]);
|
|
185
|
-
const blockTimestamp =
|
|
242
|
+
const blockTimestamp = readContext.blockTimestamp;
|
|
186
243
|
const priceTimestamp = BigInt(anchorTimestamp);
|
|
187
244
|
|
|
188
245
|
if (priceTimestamp + maxPriceAge < blockTimestamp) {
|
|
@@ -198,7 +255,23 @@ async function getSyncRedeemMultiplier(
|
|
|
198
255
|
? 0n
|
|
199
256
|
: ((blockTimestamp - priceTimestamp) * maxDynamicPremiumBps + maxPriceAge - 1n) / maxPriceAge;
|
|
200
257
|
|
|
201
|
-
return
|
|
258
|
+
return {
|
|
259
|
+
baseMultiplierBps,
|
|
260
|
+
dynamicPremiumBps,
|
|
261
|
+
effectiveMultiplierBps: baseMultiplierBps - dynamicPremiumBps,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async function getSyncRedeemMultiplier(
|
|
266
|
+
client: PublicClient,
|
|
267
|
+
provisioner: Address,
|
|
268
|
+
vault: Address,
|
|
269
|
+
token: Address,
|
|
270
|
+
feeCalculator: Address,
|
|
271
|
+
options: SyncRedeemReadOptions = {}
|
|
272
|
+
): Promise<bigint> {
|
|
273
|
+
return (await getSyncRedeemRate(client, provisioner, vault, token, feeCalculator, options))
|
|
274
|
+
.effectiveMultiplierBps;
|
|
202
275
|
}
|
|
203
276
|
|
|
204
277
|
export async function getSyncRedeemTokenOut(
|
|
@@ -208,8 +281,12 @@ export async function getSyncRedeemTokenOut(
|
|
|
208
281
|
feeCalculatorVersion: ContractVersion,
|
|
209
282
|
vault: Address,
|
|
210
283
|
token: Address,
|
|
211
|
-
unitsIn: bigint
|
|
284
|
+
unitsIn: bigint,
|
|
285
|
+
effectiveMultiplierBps?: bigint,
|
|
286
|
+
options: SyncRedeemReadOptions = {}
|
|
212
287
|
): Promise<bigint> {
|
|
288
|
+
const readContext =
|
|
289
|
+
effectiveMultiplierBps === undefined ? await resolveReadContext(client, options) : options;
|
|
213
290
|
const [tokenAmount, multiplier] = await Promise.all([
|
|
214
291
|
convertUnitsToTokenIfActive(
|
|
215
292
|
client,
|
|
@@ -218,9 +295,12 @@ export async function getSyncRedeemTokenOut(
|
|
|
218
295
|
vault,
|
|
219
296
|
token,
|
|
220
297
|
unitsIn,
|
|
221
|
-
Rounding.Floor
|
|
298
|
+
Rounding.Floor,
|
|
299
|
+
readContext
|
|
222
300
|
),
|
|
223
|
-
|
|
301
|
+
effectiveMultiplierBps !== undefined
|
|
302
|
+
? Promise.resolve(effectiveMultiplierBps)
|
|
303
|
+
: getSyncRedeemMultiplier(client, provisioner, vault, token, feeCalculator, readContext),
|
|
224
304
|
]);
|
|
225
305
|
|
|
226
306
|
return (tokenAmount * multiplier) / MAX_BPS;
|
|
@@ -317,15 +397,15 @@ export async function getSyncWithdrawUnitsIn(
|
|
|
317
397
|
feeCalculatorVersion: ContractVersion,
|
|
318
398
|
vault: Address,
|
|
319
399
|
token: Address,
|
|
320
|
-
tokensOut: bigint
|
|
400
|
+
tokensOut: bigint,
|
|
401
|
+
effectiveMultiplierBps?: bigint,
|
|
402
|
+
options: SyncRedeemReadOptions = {}
|
|
321
403
|
): Promise<bigint> {
|
|
322
|
-
const
|
|
323
|
-
client,
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
token,
|
|
327
|
-
feeCalculator
|
|
328
|
-
);
|
|
404
|
+
const readContext =
|
|
405
|
+
effectiveMultiplierBps === undefined ? await resolveReadContext(client, options) : options;
|
|
406
|
+
const multiplier =
|
|
407
|
+
effectiveMultiplierBps ??
|
|
408
|
+
(await getSyncRedeemMultiplier(client, provisioner, vault, token, feeCalculator, readContext));
|
|
329
409
|
const prePremiumTokens = (tokensOut * MAX_BPS + multiplier - 1n) / multiplier;
|
|
330
410
|
|
|
331
411
|
return convertTokenToUnitsIfActive(
|
|
@@ -335,10 +415,54 @@ export async function getSyncWithdrawUnitsIn(
|
|
|
335
415
|
vault,
|
|
336
416
|
token,
|
|
337
417
|
prePremiumTokens,
|
|
338
|
-
Rounding.Ceil
|
|
418
|
+
Rounding.Ceil,
|
|
419
|
+
readContext
|
|
339
420
|
);
|
|
340
421
|
}
|
|
341
422
|
|
|
423
|
+
/** Current sync redeem epoch accounting, in numeraire (all values uint256). */
|
|
424
|
+
export interface SyncRedeemEpochState {
|
|
425
|
+
epochTimestamp: bigint;
|
|
426
|
+
epochStartTvlNumeraire: bigint;
|
|
427
|
+
epochRedeemedNumeraire: bigint;
|
|
428
|
+
epochCapNumeraire: bigint;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export async function getSyncRedeemEpochState(
|
|
432
|
+
client: PublicClient,
|
|
433
|
+
provisioner: Address,
|
|
434
|
+
options: SyncRedeemReadOptions = {}
|
|
435
|
+
): Promise<SyncRedeemEpochState> {
|
|
436
|
+
const [epochTimestamp, epochStartTvlNumeraire, epochRedeemedNumeraire, epochCapNumeraire] =
|
|
437
|
+
await client.readContract({
|
|
438
|
+
address: provisioner,
|
|
439
|
+
abi: provisionerV2Abi,
|
|
440
|
+
functionName: 'getSyncRedeemEpochState',
|
|
441
|
+
...readAtBlock(options),
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
return { epochTimestamp, epochStartTvlNumeraire, epochRedeemedNumeraire, epochCapNumeraire };
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Raw expiry timestamp for the user's latest sync-deposit lock (0 if none was recorded).
|
|
449
|
+
* The user is locked while this value is greater than or equal to the relevant block timestamp.
|
|
450
|
+
*/
|
|
451
|
+
export async function getUserUnitsRefundableUntil(
|
|
452
|
+
client: PublicClient,
|
|
453
|
+
provisioner: Address,
|
|
454
|
+
user: Address,
|
|
455
|
+
options: SyncRedeemReadOptions = {}
|
|
456
|
+
): Promise<bigint> {
|
|
457
|
+
return client.readContract({
|
|
458
|
+
address: provisioner,
|
|
459
|
+
abi: provisionerV2Abi,
|
|
460
|
+
functionName: 'userUnitsRefundableUntil',
|
|
461
|
+
args: [user],
|
|
462
|
+
...readAtBlock(options),
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
342
466
|
export function depositTxRequest(
|
|
343
467
|
provisioner: Address,
|
|
344
468
|
token: Address,
|
package/src/evm/aeraContracts.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { provisionerAbi } from './abis/provisioner';
|
|
|
15
15
|
import { provisionerV2Abi } from './abis/provisionerV2';
|
|
16
16
|
import { MAX_BPS } from '../constants';
|
|
17
17
|
import { ContractVersion, type EvmVaultDeployment } from './types';
|
|
18
|
+
import { readAtBlock } from './aeraContracts/readOptions';
|
|
18
19
|
|
|
19
20
|
const contractVersionCache = new Map<string, ContractVersion>();
|
|
20
21
|
|
|
@@ -28,6 +29,19 @@ const contractVersionAbi = [
|
|
|
28
29
|
},
|
|
29
30
|
] as const;
|
|
30
31
|
|
|
32
|
+
const solvingGateAbi = [
|
|
33
|
+
{
|
|
34
|
+
type: 'function',
|
|
35
|
+
inputs: [
|
|
36
|
+
{ name: 'provisioner', internalType: 'address', type: 'address' },
|
|
37
|
+
{ name: 'token', internalType: 'address', type: 'address' },
|
|
38
|
+
],
|
|
39
|
+
name: 'paused',
|
|
40
|
+
outputs: [{ name: '', internalType: 'bool', type: 'bool' }],
|
|
41
|
+
stateMutability: 'view',
|
|
42
|
+
},
|
|
43
|
+
] as const;
|
|
44
|
+
|
|
31
45
|
export interface AeraRuntimeContracts {
|
|
32
46
|
provisioner: {
|
|
33
47
|
address: Address;
|
|
@@ -46,6 +60,19 @@ export interface AeraTokenModeSupport {
|
|
|
46
60
|
syncRedeem: boolean;
|
|
47
61
|
}
|
|
48
62
|
|
|
63
|
+
export function requireAeraSyncRedeemRuntime(runtime: AeraRuntimeContracts): void {
|
|
64
|
+
if (runtime.provisioner.version !== ContractVersion.V2) {
|
|
65
|
+
throw new UnsupportedFeatureError('Aera: sync redeem requires a V2 provisioner');
|
|
66
|
+
}
|
|
67
|
+
if (runtime.feeCalculator.version !== ContractVersion.V2) {
|
|
68
|
+
throw new UnsupportedFeatureError('Aera: sync redeem requires a V2 price and fee calculator');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type AeraReadOptions = {
|
|
73
|
+
blockNumber?: bigint;
|
|
74
|
+
};
|
|
75
|
+
|
|
49
76
|
export function applySlippageDown(amount: bigint, slippageBps: number): bigint {
|
|
50
77
|
return (amount * (MAX_BPS - BigInt(slippageBps))) / MAX_BPS;
|
|
51
78
|
}
|
|
@@ -97,7 +124,8 @@ export function getMultiDepositorVault<T extends Client>(
|
|
|
97
124
|
|
|
98
125
|
export async function resolveContractVersion(
|
|
99
126
|
client: PublicClient,
|
|
100
|
-
address: Address
|
|
127
|
+
address: Address,
|
|
128
|
+
options: AeraReadOptions = {}
|
|
101
129
|
): Promise<ContractVersion> {
|
|
102
130
|
const cacheKey = contractVersionCacheKey(client, address);
|
|
103
131
|
const cached = contractVersionCache.get(cacheKey);
|
|
@@ -108,6 +136,7 @@ export async function resolveContractVersion(
|
|
|
108
136
|
address,
|
|
109
137
|
abi: contractVersionAbi,
|
|
110
138
|
functionName: 'version',
|
|
139
|
+
...readAtBlock(options),
|
|
111
140
|
});
|
|
112
141
|
const version = versionString.startsWith('2.') ? ContractVersion.V2 : ContractVersion.V1;
|
|
113
142
|
contractVersionCache.set(cacheKey, version);
|
|
@@ -123,7 +152,8 @@ export async function resolveContractVersion(
|
|
|
123
152
|
|
|
124
153
|
export async function resolveAeraRuntimeContracts(
|
|
125
154
|
client: PublicClient,
|
|
126
|
-
vault: EvmVaultDeployment
|
|
155
|
+
vault: EvmVaultDeployment,
|
|
156
|
+
options: AeraReadOptions = {}
|
|
127
157
|
): Promise<AeraRuntimeContracts> {
|
|
128
158
|
if (vault.vaultType !== 'multi-depositor') {
|
|
129
159
|
throw new UnimplementedFeatureError('Aera: single depositor vaults');
|
|
@@ -134,11 +164,13 @@ export async function resolveAeraRuntimeContracts(
|
|
|
134
164
|
address: vault.vaultAddress,
|
|
135
165
|
abi: multiDepositorVaultAbi,
|
|
136
166
|
functionName: 'provisioner',
|
|
167
|
+
...readAtBlock(options),
|
|
137
168
|
}),
|
|
138
169
|
client.readContract({
|
|
139
170
|
address: vault.vaultAddress,
|
|
140
171
|
abi: multiDepositorVaultAbi,
|
|
141
172
|
functionName: 'feeCalculator',
|
|
173
|
+
...readAtBlock(options),
|
|
142
174
|
}),
|
|
143
175
|
]);
|
|
144
176
|
|
|
@@ -150,8 +182,8 @@ export async function resolveAeraRuntimeContracts(
|
|
|
150
182
|
}
|
|
151
183
|
|
|
152
184
|
const [provisionerVersion, feeCalculatorVersion] = await Promise.all([
|
|
153
|
-
resolveContractVersion(client, provisionerAddress),
|
|
154
|
-
resolveContractVersion(client, feeCalculatorAddress),
|
|
185
|
+
resolveContractVersion(client, provisionerAddress, options),
|
|
186
|
+
resolveContractVersion(client, feeCalculatorAddress, options),
|
|
155
187
|
]);
|
|
156
188
|
|
|
157
189
|
return {
|
|
@@ -169,21 +201,61 @@ export async function resolveAeraRuntimeContracts(
|
|
|
169
201
|
export async function resolveAeraTokenModeSupport(
|
|
170
202
|
client: PublicClient,
|
|
171
203
|
runtime: AeraRuntimeContracts,
|
|
172
|
-
token: Address
|
|
204
|
+
token: Address,
|
|
205
|
+
options: AeraReadOptions & { includeSyncModes?: boolean } = {}
|
|
173
206
|
): Promise<AeraTokenModeSupport> {
|
|
174
207
|
if (runtime.provisioner.version === ContractVersion.V2) {
|
|
175
|
-
const
|
|
208
|
+
const tokenDetailsPromise = client.readContract({
|
|
176
209
|
address: runtime.provisioner.address,
|
|
177
210
|
abi: provisionerV2Abi,
|
|
178
211
|
functionName: 'tokensDetails',
|
|
179
212
|
args: [token],
|
|
213
|
+
...readAtBlock(options),
|
|
180
214
|
});
|
|
215
|
+
if (options.includeSyncModes === false) {
|
|
216
|
+
const tokenDetails = await tokenDetailsPromise;
|
|
217
|
+
return {
|
|
218
|
+
asyncDeposit: Boolean(tokenDetails[0]),
|
|
219
|
+
asyncRedeem: Boolean(tokenDetails[1]),
|
|
220
|
+
syncDeposit: false,
|
|
221
|
+
syncRedeem: false,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const [tokenDetails, solvingGateEnabled, solvingGate] = await Promise.all([
|
|
226
|
+
tokenDetailsPromise,
|
|
227
|
+
client.readContract({
|
|
228
|
+
address: runtime.provisioner.address,
|
|
229
|
+
abi: provisionerV2Abi,
|
|
230
|
+
functionName: 'SOLVING_GATE_ENABLED',
|
|
231
|
+
...readAtBlock(options),
|
|
232
|
+
}),
|
|
233
|
+
client.readContract({
|
|
234
|
+
address: runtime.provisioner.address,
|
|
235
|
+
abi: provisionerV2Abi,
|
|
236
|
+
functionName: 'solvingGate',
|
|
237
|
+
...readAtBlock(options),
|
|
238
|
+
}),
|
|
239
|
+
]);
|
|
240
|
+
const solvingPaused =
|
|
241
|
+
solvingGateEnabled && solvingGate !== zeroAddress
|
|
242
|
+
? await client.readContract({
|
|
243
|
+
address: solvingGate,
|
|
244
|
+
abi: solvingGateAbi,
|
|
245
|
+
functionName: 'paused',
|
|
246
|
+
args: [runtime.provisioner.address, token],
|
|
247
|
+
...readAtBlock(options),
|
|
248
|
+
})
|
|
249
|
+
: false;
|
|
181
250
|
|
|
182
251
|
return {
|
|
183
252
|
asyncDeposit: Boolean(tokenDetails[0]),
|
|
184
253
|
asyncRedeem: Boolean(tokenDetails[1]),
|
|
185
|
-
syncDeposit: Boolean(tokenDetails[2]),
|
|
186
|
-
syncRedeem:
|
|
254
|
+
syncDeposit: Boolean(tokenDetails[2]) && !solvingPaused,
|
|
255
|
+
syncRedeem:
|
|
256
|
+
Boolean(tokenDetails[3]) &&
|
|
257
|
+
!solvingPaused &&
|
|
258
|
+
runtime.feeCalculator.version === ContractVersion.V2,
|
|
187
259
|
};
|
|
188
260
|
}
|
|
189
261
|
|
|
@@ -192,6 +264,7 @@ export async function resolveAeraTokenModeSupport(
|
|
|
192
264
|
abi: provisionerAbi,
|
|
193
265
|
functionName: 'tokensDetails',
|
|
194
266
|
args: [token],
|
|
267
|
+
...readAtBlock(options),
|
|
195
268
|
});
|
|
196
269
|
|
|
197
270
|
return {
|