@paxoslabs/amplify-sdk 0.0.1-alpha.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/CHANGELOG.md +112 -0
- package/LICENSE +28 -0
- package/README.md +533 -0
- package/dist/amplify-sdk-api-B5hBTGrB.d.ts +258 -0
- package/dist/amplify-sdk-api-DPrRhynk.d.mts +258 -0
- package/dist/chunk-3I3PYX2F.js +45 -0
- package/dist/chunk-3I3PYX2F.js.map +1 -0
- package/dist/chunk-7RWWVUHP.mjs +39 -0
- package/dist/chunk-7RWWVUHP.mjs.map +1 -0
- package/dist/chunk-AFWUOS3M.js +15 -0
- package/dist/chunk-AFWUOS3M.js.map +1 -0
- package/dist/chunk-BDXS57YH.js +828 -0
- package/dist/chunk-BDXS57YH.js.map +1 -0
- package/dist/chunk-FYNPQXCR.mjs +46 -0
- package/dist/chunk-FYNPQXCR.mjs.map +1 -0
- package/dist/chunk-GE2VQUPP.mjs +228 -0
- package/dist/chunk-GE2VQUPP.mjs.map +1 -0
- package/dist/chunk-ICKDAKVS.js +16 -0
- package/dist/chunk-ICKDAKVS.js.map +1 -0
- package/dist/chunk-ISO6Z7LD.mjs +809 -0
- package/dist/chunk-ISO6Z7LD.mjs.map +1 -0
- package/dist/chunk-ITB7FXG4.js +14 -0
- package/dist/chunk-ITB7FXG4.js.map +1 -0
- package/dist/chunk-J3662HYT.mjs +29 -0
- package/dist/chunk-J3662HYT.mjs.map +1 -0
- package/dist/chunk-JLXNOGZB.js +2061 -0
- package/dist/chunk-JLXNOGZB.js.map +1 -0
- package/dist/chunk-O5P6SP2O.js +233 -0
- package/dist/chunk-O5P6SP2O.js.map +1 -0
- package/dist/chunk-R663BFAZ.mjs +14 -0
- package/dist/chunk-R663BFAZ.mjs.map +1 -0
- package/dist/chunk-RUIAH5HY.js +32 -0
- package/dist/chunk-RUIAH5HY.js.map +1 -0
- package/dist/chunk-SIR2TCAR.mjs +13 -0
- package/dist/chunk-SIR2TCAR.mjs.map +1 -0
- package/dist/chunk-XXHRCCZS.mjs +11 -0
- package/dist/chunk-XXHRCCZS.mjs.map +1 -0
- package/dist/chunk-ZSFIOWWT.js +49 -0
- package/dist/chunk-ZSFIOWWT.js.map +1 -0
- package/dist/chunk-ZZBZIDZP.mjs +2050 -0
- package/dist/chunk-ZZBZIDZP.mjs.map +1 -0
- package/dist/config-B-u3VqEX.d.mts +21 -0
- package/dist/config-B-u3VqEX.d.ts +21 -0
- package/dist/config-BQynVNDC.d.mts +101 -0
- package/dist/config-BQynVNDC.d.ts +101 -0
- package/dist/core.d.mts +152 -0
- package/dist/core.d.ts +152 -0
- package/dist/core.js +187 -0
- package/dist/core.js.map +1 -0
- package/dist/core.mjs +150 -0
- package/dist/core.mjs.map +1 -0
- package/dist/display.d.mts +25 -0
- package/dist/display.d.ts +25 -0
- package/dist/display.js +124 -0
- package/dist/display.js.map +1 -0
- package/dist/display.mjs +105 -0
- package/dist/display.mjs.map +1 -0
- package/dist/exchange-rate-CRA_CMaX.d.mts +65 -0
- package/dist/exchange-rate-D3_FVgqa.d.ts +65 -0
- package/dist/index.d.mts +3236 -0
- package/dist/index.d.ts +3236 -0
- package/dist/index.js +1115 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1047 -0
- package/dist/index.mjs.map +1 -0
- package/dist/utils.d.mts +111 -0
- package/dist/utils.d.ts +111 -0
- package/dist/utils.js +51 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.mjs +17 -0
- package/dist/utils.mjs.map +1 -0
- package/dist/vault-config-BNzhv3QV.d.ts +15 -0
- package/dist/vault-config-BjSE7oL8.d.mts +15 -0
- package/dist/vaults.d.mts +6 -0
- package/dist/vaults.d.ts +6 -0
- package/dist/vaults.js +13 -0
- package/dist/vaults.js.map +1 -0
- package/dist/vaults.mjs +4 -0
- package/dist/vaults.mjs.map +1 -0
- package/package.json +142 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,1047 @@
|
|
|
1
|
+
import { DEFAULT_SLIPPAGE_BPS } from './chunk-XXHRCCZS.mjs';
|
|
2
|
+
export { YieldType } from './chunk-XXHRCCZS.mjs';
|
|
3
|
+
export { getDepositExchangeRate, getWithdrawExchangeRate, isDepositSpendApproved, isWithdrawalSpendApproved } from './chunk-GE2VQUPP.mjs';
|
|
4
|
+
import { getRateInQuoteWithAssetDecimals, TellerAbi, getClient, BoringVaultAbi, getRateInQuoteAndSharesAndWantAssetDecimals } from './chunk-ZZBZIDZP.mjs';
|
|
5
|
+
import './chunk-R663BFAZ.mjs';
|
|
6
|
+
import { toChainId } from './chunk-J3662HYT.mjs';
|
|
7
|
+
import { calculateDeadline } from './chunk-SIR2TCAR.mjs';
|
|
8
|
+
import { WAD } from './chunk-7RWWVUHP.mjs';
|
|
9
|
+
import { findVaultByConfig, APIError, getAssetsFromCache, DEFAULT_APPROVAL_AMOUNT, fetchSupportedAssets, ATOMIC_QUEUE_CONTRACT_ADDRESS, DEFAULT_DEADLINE } from './chunk-ISO6Z7LD.mjs';
|
|
10
|
+
export { APIError, fetchSupportedAssets, fetchVaults, findVaultByConfig, getAssetsFromCache, getCache, getWithdrawSupportedAssets, initAmplifySDK, initializeCache, refreshVaultCache } from './chunk-ISO6Z7LD.mjs';
|
|
11
|
+
import { parseUnits, erc20Abi, hexToSignature } from 'viem';
|
|
12
|
+
|
|
13
|
+
async function prepareApproveDepositTokenTxData({
|
|
14
|
+
yieldType,
|
|
15
|
+
depositToken,
|
|
16
|
+
approvalAmount,
|
|
17
|
+
chainId
|
|
18
|
+
}) {
|
|
19
|
+
const normalizedChainId = toChainId(chainId);
|
|
20
|
+
try {
|
|
21
|
+
const config = await findVaultByConfig({
|
|
22
|
+
assetAddress: depositToken,
|
|
23
|
+
yieldType,
|
|
24
|
+
chainId: normalizedChainId
|
|
25
|
+
});
|
|
26
|
+
if (!config) {
|
|
27
|
+
throw new APIError(
|
|
28
|
+
`No vault found for token address ${depositToken} with yield type '${yieldType}' on chain ${normalizedChainId}. This combination may not be supported.`,
|
|
29
|
+
{ endpoint: "prepareApproveDepositToken" }
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
const boringVaultAddress = config.vault.boringVaultAddress;
|
|
33
|
+
if (!boringVaultAddress) {
|
|
34
|
+
throw new APIError(
|
|
35
|
+
`BoringVault contract address not configured for vault ${config.id}`,
|
|
36
|
+
{ endpoint: "prepareApproveDepositToken" }
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const assets = await getAssetsFromCache({ address: depositToken });
|
|
40
|
+
if (assets.length === 0) {
|
|
41
|
+
throw new APIError(
|
|
42
|
+
`Asset metadata not found for token ${depositToken} on chain ${normalizedChainId}`,
|
|
43
|
+
{ endpoint: "prepareApproveDepositToken" }
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
const decimals = assets[0].decimals;
|
|
47
|
+
const amount = approvalAmount ? parseUnits(approvalAmount, decimals) : DEFAULT_APPROVAL_AMOUNT;
|
|
48
|
+
return {
|
|
49
|
+
abi: erc20Abi,
|
|
50
|
+
address: depositToken,
|
|
51
|
+
functionName: "approve",
|
|
52
|
+
args: [boringVaultAddress, amount]
|
|
53
|
+
};
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (error instanceof APIError) {
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
throw new APIError(
|
|
59
|
+
`Failed to prepare approval transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
60
|
+
{
|
|
61
|
+
endpoint: "prepareApproveDepositToken",
|
|
62
|
+
cause: error
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/vaults/deposit/utils.ts
|
|
69
|
+
var calculateMinimumMint = (depositAmount, rate, vaultTokenDecimals, slippage) => {
|
|
70
|
+
const slippageValue = slippage ?? DEFAULT_SLIPPAGE_BPS;
|
|
71
|
+
const slippageAsBigInt = BigInt(slippageValue) * WAD.bigint / BigInt(1e4);
|
|
72
|
+
const minimumMint = depositAmount * WAD.bigint / rate;
|
|
73
|
+
const slippageAmount = minimumMint * slippageAsBigInt / WAD.bigint;
|
|
74
|
+
if (vaultTokenDecimals > 18) {
|
|
75
|
+
return (minimumMint - slippageAmount) * BigInt(10) ** (BigInt(vaultTokenDecimals) - BigInt(18));
|
|
76
|
+
}
|
|
77
|
+
return (minimumMint - slippageAmount) / BigInt(10) ** (BigInt(18) - BigInt(vaultTokenDecimals));
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// src/vaults/deposit/deposit.ts
|
|
81
|
+
async function prepareDepositTxData(params) {
|
|
82
|
+
const {
|
|
83
|
+
yieldType,
|
|
84
|
+
depositToken,
|
|
85
|
+
depositAmount,
|
|
86
|
+
chainId,
|
|
87
|
+
slippage = DEFAULT_SLIPPAGE_BPS
|
|
88
|
+
} = params;
|
|
89
|
+
try {
|
|
90
|
+
const normalizedChainId = toChainId(chainId);
|
|
91
|
+
let vault;
|
|
92
|
+
try {
|
|
93
|
+
vault = await findVaultByConfig({
|
|
94
|
+
assetAddress: depositToken,
|
|
95
|
+
yieldType,
|
|
96
|
+
chainId: normalizedChainId
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
throw new APIError(
|
|
100
|
+
`Failed to resolve vault for token ${depositToken} with yield type ${yieldType} on chain ${normalizedChainId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
101
|
+
{
|
|
102
|
+
endpoint: "prepareDepositTransactionData",
|
|
103
|
+
cause: error
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
if (!vault) {
|
|
108
|
+
throw new APIError(
|
|
109
|
+
`No vault found for token address ${depositToken} with yield type '${yieldType}' on chain ${normalizedChainId}. This combination may not be supported.`,
|
|
110
|
+
{
|
|
111
|
+
endpoint: "prepareDepositTransactionData"
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
let asset = null;
|
|
116
|
+
const assets = await getAssetsFromCache({ address: depositToken });
|
|
117
|
+
if (assets.length > 0) {
|
|
118
|
+
asset = assets.find((a) => a.chains.includes(normalizedChainId)) || assets[0] || null;
|
|
119
|
+
}
|
|
120
|
+
if (!asset) {
|
|
121
|
+
throw new APIError(
|
|
122
|
+
`Asset metadata not found for token ${depositToken} on chain ${normalizedChainId}`,
|
|
123
|
+
{
|
|
124
|
+
endpoint: "prepareDepositTransactionData"
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
const tellerAddress = vault.vault.tellerAddress;
|
|
129
|
+
const accountantAddress = vault.vault.accountantAddress;
|
|
130
|
+
const depositAssetAddress = asset.address;
|
|
131
|
+
const [depositAssetDecimalsResult, rateInQuoteResult] = await getRateInQuoteWithAssetDecimals({
|
|
132
|
+
assetAddress: depositAssetAddress,
|
|
133
|
+
accountantAddress,
|
|
134
|
+
chainId: normalizedChainId
|
|
135
|
+
});
|
|
136
|
+
if (depositAssetDecimalsResult.status === "failure") {
|
|
137
|
+
throw new APIError(
|
|
138
|
+
`Failed to get asset decimals: ${depositAssetDecimalsResult.error?.message || "Unknown error"}`,
|
|
139
|
+
{
|
|
140
|
+
endpoint: "prepareDepositTransactionData",
|
|
141
|
+
cause: depositAssetDecimalsResult.error
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
if (rateInQuoteResult.status === "failure") {
|
|
146
|
+
throw new APIError(
|
|
147
|
+
`Failed to get exchange rate: ${rateInQuoteResult.error?.message || "Unknown error"}`,
|
|
148
|
+
{
|
|
149
|
+
endpoint: "prepareDepositTransactionData",
|
|
150
|
+
cause: rateInQuoteResult.error
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
const depositAmountAsBigInt = parseUnits(
|
|
155
|
+
depositAmount,
|
|
156
|
+
depositAssetDecimalsResult.result
|
|
157
|
+
);
|
|
158
|
+
const vaultSharesAssets = await fetchSupportedAssets({
|
|
159
|
+
address: vault.vault.boringVaultAddress
|
|
160
|
+
});
|
|
161
|
+
if (vaultSharesAssets.length === 0) {
|
|
162
|
+
throw new APIError(
|
|
163
|
+
`Vault shares token not found in supported assets: ${vault.vault.boringVaultAddress}`,
|
|
164
|
+
{ endpoint: "prepareDepositTransactionData" }
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
const minimumMint = calculateMinimumMint(
|
|
168
|
+
depositAmountAsBigInt,
|
|
169
|
+
rateInQuoteResult.result,
|
|
170
|
+
depositAssetDecimalsResult.result,
|
|
171
|
+
slippage
|
|
172
|
+
);
|
|
173
|
+
return {
|
|
174
|
+
abi: TellerAbi,
|
|
175
|
+
address: tellerAddress,
|
|
176
|
+
functionName: "deposit",
|
|
177
|
+
args: [depositAssetAddress, depositAmountAsBigInt, minimumMint],
|
|
178
|
+
chainId: normalizedChainId
|
|
179
|
+
};
|
|
180
|
+
} catch (error) {
|
|
181
|
+
if (error instanceof APIError) {
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
throw new APIError(
|
|
185
|
+
`Failed to prepare deposit transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
186
|
+
{
|
|
187
|
+
endpoint: "prepareDepositTransactionData",
|
|
188
|
+
cause: error
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// src/abi/erc2612-abi.ts
|
|
195
|
+
var erc2612Abi = [
|
|
196
|
+
// Standard ERC20 functions (subset needed for permit flow)
|
|
197
|
+
{
|
|
198
|
+
constant: true,
|
|
199
|
+
inputs: [{ name: "_owner", type: "address" }],
|
|
200
|
+
name: "nonces",
|
|
201
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
202
|
+
type: "function"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
constant: true,
|
|
206
|
+
inputs: [],
|
|
207
|
+
name: "DOMAIN_SEPARATOR",
|
|
208
|
+
outputs: [{ name: "", type: "bytes32" }],
|
|
209
|
+
type: "function"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
constant: false,
|
|
213
|
+
inputs: [
|
|
214
|
+
{ name: "owner", type: "address" },
|
|
215
|
+
{ name: "spender", type: "address" },
|
|
216
|
+
{ name: "value", type: "uint256" },
|
|
217
|
+
{ name: "deadline", type: "uint256" },
|
|
218
|
+
{ name: "v", type: "uint8" },
|
|
219
|
+
{ name: "r", type: "bytes32" },
|
|
220
|
+
{ name: "s", type: "bytes32" }
|
|
221
|
+
],
|
|
222
|
+
name: "permit",
|
|
223
|
+
outputs: [],
|
|
224
|
+
type: "function"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
constant: true,
|
|
228
|
+
inputs: [],
|
|
229
|
+
name: "name",
|
|
230
|
+
outputs: [{ name: "", type: "string" }],
|
|
231
|
+
type: "function"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
constant: true,
|
|
235
|
+
inputs: [],
|
|
236
|
+
name: "version",
|
|
237
|
+
outputs: [{ name: "", type: "string" }],
|
|
238
|
+
type: "function"
|
|
239
|
+
}
|
|
240
|
+
];
|
|
241
|
+
|
|
242
|
+
// src/vaults/deposit/deposit-with-permit.ts
|
|
243
|
+
var PERMIT_TYPES = {
|
|
244
|
+
Permit: [
|
|
245
|
+
{ name: "owner", type: "address" },
|
|
246
|
+
{ name: "spender", type: "address" },
|
|
247
|
+
{ name: "value", type: "uint256" },
|
|
248
|
+
{ name: "nonce", type: "uint256" },
|
|
249
|
+
{ name: "deadline", type: "uint256" }
|
|
250
|
+
]
|
|
251
|
+
};
|
|
252
|
+
async function prepareDepositPermitSignature(params) {
|
|
253
|
+
const {
|
|
254
|
+
yieldType,
|
|
255
|
+
depositToken,
|
|
256
|
+
depositAmount,
|
|
257
|
+
recipientAddress,
|
|
258
|
+
chainId,
|
|
259
|
+
deadline
|
|
260
|
+
} = params;
|
|
261
|
+
try {
|
|
262
|
+
const normalizedChainId = toChainId(chainId);
|
|
263
|
+
let vault;
|
|
264
|
+
try {
|
|
265
|
+
vault = await findVaultByConfig({
|
|
266
|
+
assetAddress: depositToken,
|
|
267
|
+
yieldType,
|
|
268
|
+
chainId: normalizedChainId
|
|
269
|
+
});
|
|
270
|
+
} catch (error) {
|
|
271
|
+
throw new APIError(
|
|
272
|
+
`Failed to resolve vault for token ${depositToken} with yield type ${yieldType} on chain ${normalizedChainId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
273
|
+
{
|
|
274
|
+
endpoint: "prepareDepositPermitSignature",
|
|
275
|
+
cause: error
|
|
276
|
+
}
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
if (!vault) {
|
|
280
|
+
throw new APIError(
|
|
281
|
+
`No vault found for token address ${depositToken} with yield type '${yieldType}' on chain ${normalizedChainId}. This combination may not be supported.`,
|
|
282
|
+
{
|
|
283
|
+
endpoint: "prepareDepositPermitSignature"
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
const tellerAddress = vault.vault.tellerAddress;
|
|
288
|
+
const client = await getClient(normalizedChainId);
|
|
289
|
+
let tokenName;
|
|
290
|
+
let tokenVersion;
|
|
291
|
+
let nonce;
|
|
292
|
+
try {
|
|
293
|
+
const [nameResult, versionResult, nonceResult] = await Promise.allSettled(
|
|
294
|
+
[
|
|
295
|
+
client.readContract({
|
|
296
|
+
address: depositToken,
|
|
297
|
+
abi: erc2612Abi,
|
|
298
|
+
functionName: "name"
|
|
299
|
+
}),
|
|
300
|
+
client.readContract({
|
|
301
|
+
address: depositToken,
|
|
302
|
+
abi: erc2612Abi,
|
|
303
|
+
functionName: "version"
|
|
304
|
+
}),
|
|
305
|
+
client.readContract({
|
|
306
|
+
address: depositToken,
|
|
307
|
+
abi: erc2612Abi,
|
|
308
|
+
functionName: "nonces",
|
|
309
|
+
args: [recipientAddress]
|
|
310
|
+
})
|
|
311
|
+
]
|
|
312
|
+
);
|
|
313
|
+
if (nameResult.status === "fulfilled") {
|
|
314
|
+
tokenName = nameResult.value;
|
|
315
|
+
} else {
|
|
316
|
+
throw new APIError(`Failed to read token name from ${depositToken}`, {
|
|
317
|
+
endpoint: "prepareDepositPermitSignature",
|
|
318
|
+
cause: nameResult.reason
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
if (versionResult.status === "fulfilled") {
|
|
322
|
+
tokenVersion = versionResult.value;
|
|
323
|
+
} else {
|
|
324
|
+
tokenVersion = "1";
|
|
325
|
+
}
|
|
326
|
+
if (nonceResult.status === "fulfilled") {
|
|
327
|
+
nonce = nonceResult.value;
|
|
328
|
+
} else {
|
|
329
|
+
throw new APIError(
|
|
330
|
+
`Token ${depositToken} does not support EIP-2612 permit. Missing required function: nonces()`,
|
|
331
|
+
{
|
|
332
|
+
endpoint: "prepareDepositPermitSignature",
|
|
333
|
+
cause: nonceResult.reason
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
} catch (error) {
|
|
338
|
+
if (error instanceof APIError) {
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
341
|
+
throw new APIError(
|
|
342
|
+
`Failed to read token metadata: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
343
|
+
{
|
|
344
|
+
endpoint: "prepareDepositPermitSignature",
|
|
345
|
+
cause: error
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
const permitDeadline = deadline ?? BigInt(Math.floor(Date.now() / 1e3) + 3600);
|
|
350
|
+
const assets = await fetchSupportedAssets({ address: depositToken });
|
|
351
|
+
if (assets.length === 0) {
|
|
352
|
+
throw new APIError(`Asset metadata not found for token ${depositToken}`, {
|
|
353
|
+
endpoint: "prepareDepositPermitSignature"
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
const asset = assets[0];
|
|
357
|
+
const value = parseUnits(depositAmount, asset.decimals);
|
|
358
|
+
const domain = {
|
|
359
|
+
name: tokenName,
|
|
360
|
+
version: tokenVersion,
|
|
361
|
+
chainId: normalizedChainId,
|
|
362
|
+
verifyingContract: depositToken
|
|
363
|
+
};
|
|
364
|
+
const message = {
|
|
365
|
+
owner: recipientAddress,
|
|
366
|
+
spender: tellerAddress,
|
|
367
|
+
value,
|
|
368
|
+
nonce,
|
|
369
|
+
deadline: permitDeadline
|
|
370
|
+
};
|
|
371
|
+
return {
|
|
372
|
+
domain,
|
|
373
|
+
message,
|
|
374
|
+
primaryType: "Permit",
|
|
375
|
+
types: PERMIT_TYPES
|
|
376
|
+
};
|
|
377
|
+
} catch (error) {
|
|
378
|
+
if (error instanceof APIError) {
|
|
379
|
+
throw error;
|
|
380
|
+
}
|
|
381
|
+
throw new APIError(
|
|
382
|
+
`Failed to prepare permit signature: ${error instanceof Error ? error.message : String(error)}`,
|
|
383
|
+
{
|
|
384
|
+
endpoint: "prepareDepositPermitSignature",
|
|
385
|
+
cause: error
|
|
386
|
+
}
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function parsePermitSignature(signature) {
|
|
391
|
+
try {
|
|
392
|
+
const parsed = hexToSignature(signature);
|
|
393
|
+
let v;
|
|
394
|
+
if (parsed.v !== void 0) {
|
|
395
|
+
v = Number(parsed.v);
|
|
396
|
+
} else if (parsed.yParity !== void 0) {
|
|
397
|
+
v = parsed.yParity + 27;
|
|
398
|
+
} else {
|
|
399
|
+
v = 27;
|
|
400
|
+
}
|
|
401
|
+
return {
|
|
402
|
+
v,
|
|
403
|
+
r: parsed.r,
|
|
404
|
+
s: parsed.s
|
|
405
|
+
};
|
|
406
|
+
} catch (error) {
|
|
407
|
+
throw new APIError(
|
|
408
|
+
`Invalid permit signature format. Expected hex string but received: ${signature}. ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
409
|
+
{
|
|
410
|
+
endpoint: "parsePermitSignature",
|
|
411
|
+
cause: error
|
|
412
|
+
}
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
async function prepareDepositWithPermitTransactionData(params) {
|
|
417
|
+
const {
|
|
418
|
+
yieldType,
|
|
419
|
+
depositToken,
|
|
420
|
+
depositAmount,
|
|
421
|
+
chainId,
|
|
422
|
+
signature,
|
|
423
|
+
deadline,
|
|
424
|
+
slippage = DEFAULT_SLIPPAGE_BPS
|
|
425
|
+
} = params;
|
|
426
|
+
try {
|
|
427
|
+
const { v, r, s } = parsePermitSignature(signature);
|
|
428
|
+
if (slippage < 0 || slippage > 1e4) {
|
|
429
|
+
throw new APIError(
|
|
430
|
+
`Invalid slippage value: ${slippage}. Slippage must be between 0 and 10000 basis points.`,
|
|
431
|
+
{
|
|
432
|
+
endpoint: "prepareDepositWithPermitTransactionData"
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
const normalizedChainId = toChainId(chainId);
|
|
437
|
+
let vault;
|
|
438
|
+
try {
|
|
439
|
+
vault = await findVaultByConfig({
|
|
440
|
+
assetAddress: depositToken,
|
|
441
|
+
yieldType,
|
|
442
|
+
chainId: normalizedChainId
|
|
443
|
+
});
|
|
444
|
+
} catch (error) {
|
|
445
|
+
throw new APIError(
|
|
446
|
+
`Failed to resolve vault for token ${depositToken} with yield type ${yieldType} on chain ${normalizedChainId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
447
|
+
{
|
|
448
|
+
endpoint: "prepareDepositWithPermitTransactionData",
|
|
449
|
+
cause: error
|
|
450
|
+
}
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
if (!vault) {
|
|
454
|
+
throw new APIError(
|
|
455
|
+
`No vault found for token address ${depositToken} with yield type '${yieldType}' on chain ${normalizedChainId}. This combination may not be supported.`,
|
|
456
|
+
{
|
|
457
|
+
endpoint: "prepareDepositWithPermitTransactionData"
|
|
458
|
+
}
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
let asset = null;
|
|
462
|
+
const assets = await fetchSupportedAssets({ address: depositToken });
|
|
463
|
+
if (assets.length > 0) {
|
|
464
|
+
asset = assets.find((a) => a.chains.includes(normalizedChainId)) || assets[0] || null;
|
|
465
|
+
}
|
|
466
|
+
if (!asset) {
|
|
467
|
+
throw new APIError(
|
|
468
|
+
`Asset metadata not found for token ${depositToken} on chain ${normalizedChainId}`,
|
|
469
|
+
{
|
|
470
|
+
endpoint: "prepareDepositWithPermitTransactionData"
|
|
471
|
+
}
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
if (!asset.chains || !asset.chains.includes(normalizedChainId)) {
|
|
475
|
+
throw new APIError(
|
|
476
|
+
`Token ${asset.symbol || depositToken} not supported on chain ${normalizedChainId}`,
|
|
477
|
+
{
|
|
478
|
+
endpoint: "prepareDepositWithPermitTransactionData"
|
|
479
|
+
}
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
const tellerAddress = vault.vault.tellerAddress;
|
|
483
|
+
const accountantAddress = vault.vault.accountantAddress;
|
|
484
|
+
const depositAssetAddress = asset.address;
|
|
485
|
+
const [depositAssetDecimalsResult, rateInQuoteResult] = await getRateInQuoteWithAssetDecimals({
|
|
486
|
+
assetAddress: depositAssetAddress,
|
|
487
|
+
accountantAddress,
|
|
488
|
+
chainId: normalizedChainId
|
|
489
|
+
});
|
|
490
|
+
if (depositAssetDecimalsResult.status === "failure") {
|
|
491
|
+
throw new APIError(
|
|
492
|
+
`Failed to get asset decimals: ${depositAssetDecimalsResult.error?.message || "Unknown error"}`,
|
|
493
|
+
{
|
|
494
|
+
endpoint: "prepareDepositWithPermitTransactionData",
|
|
495
|
+
cause: depositAssetDecimalsResult.error
|
|
496
|
+
}
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
if (rateInQuoteResult.status === "failure") {
|
|
500
|
+
throw new APIError(
|
|
501
|
+
`Failed to get exchange rate: ${rateInQuoteResult.error?.message || "Unknown error"}`,
|
|
502
|
+
{
|
|
503
|
+
endpoint: "prepareDepositWithPermitTransactionData",
|
|
504
|
+
cause: rateInQuoteResult.error
|
|
505
|
+
}
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
const depositAmountAsBigInt = parseUnits(depositAmount, asset.decimals);
|
|
509
|
+
const vaultSharesAssets = await fetchSupportedAssets({
|
|
510
|
+
address: vault.vault.boringVaultAddress
|
|
511
|
+
});
|
|
512
|
+
if (vaultSharesAssets.length === 0) {
|
|
513
|
+
throw new APIError(
|
|
514
|
+
`Vault shares token not found in supported assets: ${vault.vault.boringVaultAddress}`,
|
|
515
|
+
{ endpoint: "prepareDepositWithPermitTransactionData" }
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
const minimumMint = calculateMinimumMint(
|
|
519
|
+
depositAmountAsBigInt,
|
|
520
|
+
rateInQuoteResult.result,
|
|
521
|
+
vaultSharesAssets[0].decimals,
|
|
522
|
+
slippage
|
|
523
|
+
);
|
|
524
|
+
return {
|
|
525
|
+
data: {
|
|
526
|
+
abi: TellerAbi,
|
|
527
|
+
functionName: "depositWithPermit",
|
|
528
|
+
args: [
|
|
529
|
+
depositAssetAddress,
|
|
530
|
+
depositAmountAsBigInt,
|
|
531
|
+
minimumMint,
|
|
532
|
+
deadline,
|
|
533
|
+
v,
|
|
534
|
+
r,
|
|
535
|
+
s
|
|
536
|
+
]
|
|
537
|
+
},
|
|
538
|
+
address: tellerAddress,
|
|
539
|
+
chainId: normalizedChainId
|
|
540
|
+
};
|
|
541
|
+
} catch (error) {
|
|
542
|
+
if (error instanceof APIError) {
|
|
543
|
+
throw error;
|
|
544
|
+
}
|
|
545
|
+
throw new APIError(
|
|
546
|
+
`Failed to prepare deposit with permit transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
547
|
+
{
|
|
548
|
+
endpoint: "prepareDepositWithPermitTransactionData",
|
|
549
|
+
cause: error
|
|
550
|
+
}
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
async function prepareApproveWithdrawTxData({
|
|
555
|
+
yieldType,
|
|
556
|
+
wantAssetAddress,
|
|
557
|
+
withdrawAmount,
|
|
558
|
+
chainId
|
|
559
|
+
}) {
|
|
560
|
+
try {
|
|
561
|
+
const normalizedChainId = toChainId(chainId);
|
|
562
|
+
const config = await findVaultByConfig({
|
|
563
|
+
assetAddress: wantAssetAddress,
|
|
564
|
+
yieldType,
|
|
565
|
+
chainId: normalizedChainId
|
|
566
|
+
});
|
|
567
|
+
if (!config || config.chainId !== normalizedChainId) {
|
|
568
|
+
throw new APIError(
|
|
569
|
+
`Vault chain mismatch: vault is on chain ${config?.chainId}, requested chain ${normalizedChainId}`,
|
|
570
|
+
{ endpoint: "prepareApproveWithdrawToken" }
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
if (!config.vault.boringVaultAddress) {
|
|
574
|
+
throw new APIError(
|
|
575
|
+
`BoringVault contract address not configured for vault ${config.id}`,
|
|
576
|
+
{ endpoint: "prepareApproveWithdrawToken" }
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
const boringVaultAddress = config.vault.boringVaultAddress;
|
|
580
|
+
const vaultSharesAssets = await getAssetsFromCache({
|
|
581
|
+
address: boringVaultAddress
|
|
582
|
+
});
|
|
583
|
+
if (vaultSharesAssets.length === 0) {
|
|
584
|
+
throw new APIError(
|
|
585
|
+
`Vault shares token not found in supported assets: ${boringVaultAddress}`,
|
|
586
|
+
{ endpoint: "prepareApproveWithdrawToken" }
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
const withdrawAmountAsBigInt = withdrawAmount ? parseUnits(withdrawAmount, vaultSharesAssets[0].decimals) : DEFAULT_APPROVAL_AMOUNT;
|
|
590
|
+
return {
|
|
591
|
+
abi: BoringVaultAbi,
|
|
592
|
+
address: boringVaultAddress,
|
|
593
|
+
functionName: "approve",
|
|
594
|
+
args: [ATOMIC_QUEUE_CONTRACT_ADDRESS, withdrawAmountAsBigInt]
|
|
595
|
+
};
|
|
596
|
+
} catch (error) {
|
|
597
|
+
if (error instanceof APIError) {
|
|
598
|
+
throw error;
|
|
599
|
+
}
|
|
600
|
+
throw new APIError(
|
|
601
|
+
`Failed to prepare approval transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
602
|
+
{
|
|
603
|
+
endpoint: "prepareApproveWithdrawToken",
|
|
604
|
+
cause: error
|
|
605
|
+
}
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// src/vaults/withdraw/utils.ts
|
|
611
|
+
var prepareUserRequest = (offerAmount, atomicPrice, deadline) => {
|
|
612
|
+
const deadlineTimeStamp = calculateDeadline(deadline);
|
|
613
|
+
return {
|
|
614
|
+
deadline: deadlineTimeStamp,
|
|
615
|
+
atomicPrice,
|
|
616
|
+
offerAmount,
|
|
617
|
+
inSolve: false
|
|
618
|
+
};
|
|
619
|
+
};
|
|
620
|
+
var calculateAtomicPrice = (rateInQuote, wantAssetDecimals, slippage) => {
|
|
621
|
+
const wantPrecision = BigInt(10 ** wantAssetDecimals);
|
|
622
|
+
const slippageAsBigInt = BigInt(slippage) * wantPrecision / BigInt(1e4);
|
|
623
|
+
return rateInQuote * (wantPrecision - slippageAsBigInt) / wantPrecision;
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
// src/vaults/withdraw/bulk-withdraw.ts
|
|
627
|
+
async function prepareBulkWithdrawTxData(params) {
|
|
628
|
+
const {
|
|
629
|
+
yieldType,
|
|
630
|
+
wantAssetAddress,
|
|
631
|
+
shareAmount,
|
|
632
|
+
chainId,
|
|
633
|
+
slippage = DEFAULT_SLIPPAGE_BPS,
|
|
634
|
+
userAddress
|
|
635
|
+
} = params;
|
|
636
|
+
try {
|
|
637
|
+
const normalizedChainId = toChainId(chainId);
|
|
638
|
+
const vault = await findVaultByConfig({
|
|
639
|
+
assetAddress: wantAssetAddress,
|
|
640
|
+
yieldType,
|
|
641
|
+
chainId: normalizedChainId
|
|
642
|
+
});
|
|
643
|
+
if (vault && vault.chainId !== normalizedChainId) {
|
|
644
|
+
throw new APIError(
|
|
645
|
+
`Vault chain mismatch: vault is on chain ${vault.chainId}, requested chain ${normalizedChainId}`,
|
|
646
|
+
{ endpoint: "prepareBulkWithdrawTransactionData" }
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
if (!vault || !vault.vault.boringVaultAddress) {
|
|
650
|
+
throw new APIError(
|
|
651
|
+
`BoringVault contract address not configured for vault ${vault?.vault.boringVaultAddress}`,
|
|
652
|
+
{ endpoint: "prepareBulkWithdrawTransactionData" }
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
const boringVaultAddress = vault.vault.boringVaultAddress;
|
|
656
|
+
const accountantAddress = vault.vault.accountantAddress;
|
|
657
|
+
const wantAsset = await getAssetsFromCache({
|
|
658
|
+
address: wantAssetAddress
|
|
659
|
+
});
|
|
660
|
+
if (wantAsset.length === 0) {
|
|
661
|
+
throw new APIError(
|
|
662
|
+
`Vault shares token not found in supported assets: ${boringVaultAddress}`,
|
|
663
|
+
{ endpoint: "prepareBulkWithdrawTransactionData" }
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
const [
|
|
667
|
+
wantAssetDecimalsResult,
|
|
668
|
+
sharesAssetDecimalsResult,
|
|
669
|
+
rateInQuoteResult
|
|
670
|
+
] = await getRateInQuoteAndSharesAndWantAssetDecimals({
|
|
671
|
+
sharesAssetAddress: boringVaultAddress,
|
|
672
|
+
wantAssetAddress,
|
|
673
|
+
accountantAddress,
|
|
674
|
+
chainId: normalizedChainId
|
|
675
|
+
});
|
|
676
|
+
if (rateInQuoteResult.status === "failure" || wantAssetDecimalsResult.status === "failure" || sharesAssetDecimalsResult.status === "failure") {
|
|
677
|
+
throw new APIError(
|
|
678
|
+
`Failed to get exchange rate: ${rateInQuoteResult?.error?.message || wantAssetDecimalsResult?.error?.message || sharesAssetDecimalsResult?.error?.message}`,
|
|
679
|
+
{
|
|
680
|
+
endpoint: "prepareBulkWithdrawTransactionData",
|
|
681
|
+
cause: rateInQuoteResult?.error || wantAssetDecimalsResult?.error || sharesAssetDecimalsResult?.error
|
|
682
|
+
}
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
const offerAmountAsBigInt = parseUnits(
|
|
686
|
+
shareAmount,
|
|
687
|
+
sharesAssetDecimalsResult.result
|
|
688
|
+
);
|
|
689
|
+
const atomicPrice = calculateAtomicPrice(
|
|
690
|
+
rateInQuoteResult.result,
|
|
691
|
+
// rateInQuote bigint
|
|
692
|
+
wantAssetDecimalsResult.result,
|
|
693
|
+
// Want asset decimals from API
|
|
694
|
+
slippage
|
|
695
|
+
);
|
|
696
|
+
const minimumAssets = atomicPrice * offerAmountAsBigInt / BigInt(10 ** sharesAssetDecimalsResult.result);
|
|
697
|
+
return {
|
|
698
|
+
abi: TellerAbi,
|
|
699
|
+
address: vault.vault.tellerAddress,
|
|
700
|
+
functionName: "bulkWithdraw",
|
|
701
|
+
args: [wantAssetAddress, offerAmountAsBigInt, minimumAssets, userAddress],
|
|
702
|
+
chainId: normalizedChainId
|
|
703
|
+
};
|
|
704
|
+
} catch (error) {
|
|
705
|
+
if (error instanceof APIError) {
|
|
706
|
+
throw error;
|
|
707
|
+
}
|
|
708
|
+
throw new APIError(
|
|
709
|
+
`Failed to prepare withdrawal transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
710
|
+
{
|
|
711
|
+
endpoint: "prepareBulkWithdrawTransactionData",
|
|
712
|
+
cause: error
|
|
713
|
+
}
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// src/abi/atomic-queue-abi.ts
|
|
719
|
+
var AtomicQueueAbi = [
|
|
720
|
+
{
|
|
721
|
+
type: "function",
|
|
722
|
+
name: "getUserAtomicRequest",
|
|
723
|
+
inputs: [
|
|
724
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
725
|
+
{ name: "offer", type: "address", internalType: "contract ERC20" },
|
|
726
|
+
{ name: "want", type: "address", internalType: "contract ERC20" }
|
|
727
|
+
],
|
|
728
|
+
outputs: [
|
|
729
|
+
{
|
|
730
|
+
name: "",
|
|
731
|
+
type: "tuple",
|
|
732
|
+
internalType: "struct AtomicQueue.AtomicRequest",
|
|
733
|
+
components: [
|
|
734
|
+
{ name: "deadline", type: "uint64", internalType: "uint64" },
|
|
735
|
+
{ name: "atomicPrice", type: "uint88", internalType: "uint88" },
|
|
736
|
+
{ name: "offerAmount", type: "uint96", internalType: "uint96" },
|
|
737
|
+
{ name: "inSolve", type: "bool", internalType: "bool" }
|
|
738
|
+
]
|
|
739
|
+
}
|
|
740
|
+
],
|
|
741
|
+
stateMutability: "view"
|
|
742
|
+
},
|
|
743
|
+
{
|
|
744
|
+
type: "function",
|
|
745
|
+
name: "isAtomicRequestValid",
|
|
746
|
+
inputs: [
|
|
747
|
+
{ name: "offer", type: "address", internalType: "contract ERC20" },
|
|
748
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
749
|
+
{
|
|
750
|
+
name: "userRequest",
|
|
751
|
+
type: "tuple",
|
|
752
|
+
internalType: "struct AtomicQueue.AtomicRequest",
|
|
753
|
+
components: [
|
|
754
|
+
{ name: "deadline", type: "uint64", internalType: "uint64" },
|
|
755
|
+
{ name: "atomicPrice", type: "uint88", internalType: "uint88" },
|
|
756
|
+
{ name: "offerAmount", type: "uint96", internalType: "uint96" },
|
|
757
|
+
{ name: "inSolve", type: "bool", internalType: "bool" }
|
|
758
|
+
]
|
|
759
|
+
}
|
|
760
|
+
],
|
|
761
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
762
|
+
stateMutability: "view"
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
type: "function",
|
|
766
|
+
name: "solve",
|
|
767
|
+
inputs: [
|
|
768
|
+
{ name: "offer", type: "address", internalType: "contract ERC20" },
|
|
769
|
+
{ name: "want", type: "address", internalType: "contract ERC20" },
|
|
770
|
+
{ name: "users", type: "address[]", internalType: "address[]" },
|
|
771
|
+
{ name: "runData", type: "bytes", internalType: "bytes" },
|
|
772
|
+
{ name: "solver", type: "address", internalType: "address" }
|
|
773
|
+
],
|
|
774
|
+
outputs: [],
|
|
775
|
+
stateMutability: "nonpayable"
|
|
776
|
+
},
|
|
777
|
+
{
|
|
778
|
+
type: "function",
|
|
779
|
+
name: "updateAtomicRequest",
|
|
780
|
+
inputs: [
|
|
781
|
+
{ name: "offer", type: "address", internalType: "contract ERC20" },
|
|
782
|
+
{ name: "want", type: "address", internalType: "contract ERC20" },
|
|
783
|
+
{
|
|
784
|
+
name: "userRequest",
|
|
785
|
+
type: "tuple",
|
|
786
|
+
internalType: "struct AtomicQueue.AtomicRequest",
|
|
787
|
+
components: [
|
|
788
|
+
{ name: "deadline", type: "uint64", internalType: "uint64" },
|
|
789
|
+
{ name: "atomicPrice", type: "uint88", internalType: "uint88" },
|
|
790
|
+
{ name: "offerAmount", type: "uint96", internalType: "uint96" },
|
|
791
|
+
{ name: "inSolve", type: "bool", internalType: "bool" }
|
|
792
|
+
]
|
|
793
|
+
}
|
|
794
|
+
],
|
|
795
|
+
outputs: [],
|
|
796
|
+
stateMutability: "nonpayable"
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
type: "function",
|
|
800
|
+
name: "userAtomicRequest",
|
|
801
|
+
inputs: [
|
|
802
|
+
{ name: "", type: "address", internalType: "address" },
|
|
803
|
+
{ name: "", type: "address", internalType: "contract ERC20" },
|
|
804
|
+
{ name: "", type: "address", internalType: "contract ERC20" }
|
|
805
|
+
],
|
|
806
|
+
outputs: [
|
|
807
|
+
{ name: "deadline", type: "uint64", internalType: "uint64" },
|
|
808
|
+
{ name: "atomicPrice", type: "uint88", internalType: "uint88" },
|
|
809
|
+
{ name: "offerAmount", type: "uint96", internalType: "uint96" },
|
|
810
|
+
{ name: "inSolve", type: "bool", internalType: "bool" }
|
|
811
|
+
],
|
|
812
|
+
stateMutability: "view"
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
type: "function",
|
|
816
|
+
name: "viewSolveMetaData",
|
|
817
|
+
inputs: [
|
|
818
|
+
{ name: "offer", type: "address", internalType: "contract ERC20" },
|
|
819
|
+
{ name: "want", type: "address", internalType: "contract ERC20" },
|
|
820
|
+
{ name: "users", type: "address[]", internalType: "address[]" }
|
|
821
|
+
],
|
|
822
|
+
outputs: [
|
|
823
|
+
{
|
|
824
|
+
name: "metaData",
|
|
825
|
+
type: "tuple[]",
|
|
826
|
+
internalType: "struct AtomicQueue.SolveMetaData[]",
|
|
827
|
+
components: [
|
|
828
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
829
|
+
{ name: "flags", type: "uint8", internalType: "uint8" },
|
|
830
|
+
{ name: "assetsToOffer", type: "uint256", internalType: "uint256" },
|
|
831
|
+
{ name: "assetsForWant", type: "uint256", internalType: "uint256" }
|
|
832
|
+
]
|
|
833
|
+
},
|
|
834
|
+
{ name: "totalAssetsForWant", type: "uint256", internalType: "uint256" },
|
|
835
|
+
{ name: "totalAssetsToOffer", type: "uint256", internalType: "uint256" }
|
|
836
|
+
],
|
|
837
|
+
stateMutability: "view"
|
|
838
|
+
},
|
|
839
|
+
{
|
|
840
|
+
type: "event",
|
|
841
|
+
name: "AtomicRequestFulfilled",
|
|
842
|
+
inputs: [
|
|
843
|
+
{
|
|
844
|
+
name: "user",
|
|
845
|
+
type: "address",
|
|
846
|
+
indexed: false,
|
|
847
|
+
internalType: "address"
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
name: "offerToken",
|
|
851
|
+
type: "address",
|
|
852
|
+
indexed: false,
|
|
853
|
+
internalType: "address"
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
name: "wantToken",
|
|
857
|
+
type: "address",
|
|
858
|
+
indexed: false,
|
|
859
|
+
internalType: "address"
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
name: "offerAmountSpent",
|
|
863
|
+
type: "uint256",
|
|
864
|
+
indexed: false,
|
|
865
|
+
internalType: "uint256"
|
|
866
|
+
},
|
|
867
|
+
{
|
|
868
|
+
name: "wantAmountReceived",
|
|
869
|
+
type: "uint256",
|
|
870
|
+
indexed: false,
|
|
871
|
+
internalType: "uint256"
|
|
872
|
+
},
|
|
873
|
+
{
|
|
874
|
+
name: "timestamp",
|
|
875
|
+
type: "uint256",
|
|
876
|
+
indexed: false,
|
|
877
|
+
internalType: "uint256"
|
|
878
|
+
}
|
|
879
|
+
],
|
|
880
|
+
anonymous: false
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
type: "event",
|
|
884
|
+
name: "AtomicRequestUpdated",
|
|
885
|
+
inputs: [
|
|
886
|
+
{
|
|
887
|
+
name: "user",
|
|
888
|
+
type: "address",
|
|
889
|
+
indexed: false,
|
|
890
|
+
internalType: "address"
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
name: "offerToken",
|
|
894
|
+
type: "address",
|
|
895
|
+
indexed: false,
|
|
896
|
+
internalType: "address"
|
|
897
|
+
},
|
|
898
|
+
{
|
|
899
|
+
name: "wantToken",
|
|
900
|
+
type: "address",
|
|
901
|
+
indexed: false,
|
|
902
|
+
internalType: "address"
|
|
903
|
+
},
|
|
904
|
+
{
|
|
905
|
+
name: "amount",
|
|
906
|
+
type: "uint256",
|
|
907
|
+
indexed: false,
|
|
908
|
+
internalType: "uint256"
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
name: "deadline",
|
|
912
|
+
type: "uint256",
|
|
913
|
+
indexed: false,
|
|
914
|
+
internalType: "uint256"
|
|
915
|
+
},
|
|
916
|
+
{
|
|
917
|
+
name: "minPrice",
|
|
918
|
+
type: "uint256",
|
|
919
|
+
indexed: false,
|
|
920
|
+
internalType: "uint256"
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
name: "timestamp",
|
|
924
|
+
type: "uint256",
|
|
925
|
+
indexed: false,
|
|
926
|
+
internalType: "uint256"
|
|
927
|
+
}
|
|
928
|
+
],
|
|
929
|
+
anonymous: false
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
type: "error",
|
|
933
|
+
name: "AtomicQueue__RequestDeadlineExceeded",
|
|
934
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }]
|
|
935
|
+
},
|
|
936
|
+
{
|
|
937
|
+
type: "error",
|
|
938
|
+
name: "AtomicQueue__UserNotInSolve",
|
|
939
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }]
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
type: "error",
|
|
943
|
+
name: "AtomicQueue__UserRepeated",
|
|
944
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }]
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
type: "error",
|
|
948
|
+
name: "AtomicQueue__ZeroOfferAmount",
|
|
949
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }]
|
|
950
|
+
}
|
|
951
|
+
];
|
|
952
|
+
|
|
953
|
+
// src/vaults/withdraw/withdraw.ts
|
|
954
|
+
var prepareWithdrawTxData = async ({
|
|
955
|
+
yieldType,
|
|
956
|
+
wantAssetAddress,
|
|
957
|
+
chainId,
|
|
958
|
+
offerAmount,
|
|
959
|
+
deadline = DEFAULT_DEADLINE,
|
|
960
|
+
slippage = DEFAULT_SLIPPAGE_BPS
|
|
961
|
+
}) => {
|
|
962
|
+
try {
|
|
963
|
+
const normalizedChainId = toChainId(chainId);
|
|
964
|
+
const config = await findVaultByConfig({
|
|
965
|
+
assetAddress: wantAssetAddress,
|
|
966
|
+
yieldType,
|
|
967
|
+
chainId: normalizedChainId
|
|
968
|
+
});
|
|
969
|
+
if (config && config.chainId !== normalizedChainId) {
|
|
970
|
+
throw new APIError(
|
|
971
|
+
`Vault chain mismatch: vault is on chain ${config.chainId}, requested chain ${normalizedChainId}`,
|
|
972
|
+
{ endpoint: "prepareWithdrawTransactionData" }
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
if (!config || !config.vault.boringVaultAddress) {
|
|
976
|
+
throw new APIError(
|
|
977
|
+
`BoringVault contract address not configured for vault ${config?.id}`,
|
|
978
|
+
{ endpoint: "prepareWithdrawTransactionData" }
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
if (!config.vault.accountantAddress) {
|
|
982
|
+
throw new APIError(
|
|
983
|
+
`Accountant contract address not configured for vault ${config.id}`,
|
|
984
|
+
{ endpoint: "prepareWithdrawTransactionData" }
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
const boringVaultAddress = config.vault.boringVaultAddress;
|
|
988
|
+
const accountantAddress = config.vault.accountantAddress;
|
|
989
|
+
const [
|
|
990
|
+
wantAssetDecimalsResult,
|
|
991
|
+
sharesAssetDecimalsResult,
|
|
992
|
+
rateInQuoteResult
|
|
993
|
+
] = await getRateInQuoteAndSharesAndWantAssetDecimals({
|
|
994
|
+
sharesAssetAddress: boringVaultAddress,
|
|
995
|
+
wantAssetAddress,
|
|
996
|
+
accountantAddress,
|
|
997
|
+
chainId: normalizedChainId
|
|
998
|
+
});
|
|
999
|
+
if (rateInQuoteResult?.status === "failure" || wantAssetDecimalsResult?.status === "failure" || sharesAssetDecimalsResult?.status === "failure") {
|
|
1000
|
+
throw new APIError(
|
|
1001
|
+
`Failed to get exchange rate: ${rateInQuoteResult?.error?.message || wantAssetDecimalsResult?.error?.message || sharesAssetDecimalsResult?.error?.message}`,
|
|
1002
|
+
{
|
|
1003
|
+
endpoint: "prepareWithdrawTransactionData",
|
|
1004
|
+
cause: rateInQuoteResult?.error || wantAssetDecimalsResult?.error || sharesAssetDecimalsResult?.error
|
|
1005
|
+
}
|
|
1006
|
+
);
|
|
1007
|
+
}
|
|
1008
|
+
const atomicPrice = calculateAtomicPrice(
|
|
1009
|
+
rateInQuoteResult.result,
|
|
1010
|
+
// rateInQuote bigint
|
|
1011
|
+
wantAssetDecimalsResult.result,
|
|
1012
|
+
// Want asset decimals from API
|
|
1013
|
+
slippage
|
|
1014
|
+
);
|
|
1015
|
+
const formattedOfferAmount = parseUnits(
|
|
1016
|
+
offerAmount,
|
|
1017
|
+
sharesAssetDecimalsResult.result
|
|
1018
|
+
);
|
|
1019
|
+
const userRequest = prepareUserRequest(
|
|
1020
|
+
formattedOfferAmount,
|
|
1021
|
+
atomicPrice,
|
|
1022
|
+
deadline
|
|
1023
|
+
);
|
|
1024
|
+
return {
|
|
1025
|
+
abi: AtomicQueueAbi,
|
|
1026
|
+
address: ATOMIC_QUEUE_CONTRACT_ADDRESS,
|
|
1027
|
+
functionName: "updateAtomicRequest",
|
|
1028
|
+
args: [boringVaultAddress, wantAssetAddress, userRequest],
|
|
1029
|
+
chainId: normalizedChainId
|
|
1030
|
+
};
|
|
1031
|
+
} catch (error) {
|
|
1032
|
+
if (error instanceof APIError) {
|
|
1033
|
+
throw error;
|
|
1034
|
+
}
|
|
1035
|
+
throw new APIError(
|
|
1036
|
+
`Failed to prepare withdrawal transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
1037
|
+
{
|
|
1038
|
+
endpoint: "prepareWithdrawTransactionData",
|
|
1039
|
+
cause: error
|
|
1040
|
+
}
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
|
|
1045
|
+
export { PERMIT_TYPES, parsePermitSignature, prepareApproveDepositTokenTxData, prepareApproveWithdrawTxData, prepareBulkWithdrawTxData, prepareDepositPermitSignature, prepareDepositTxData, prepareDepositWithPermitTransactionData, prepareWithdrawTxData };
|
|
1046
|
+
//# sourceMappingURL=index.mjs.map
|
|
1047
|
+
//# sourceMappingURL=index.mjs.map
|