@paxoslabs/amplify-sdk 0.5.3 → 1.0.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/dist/index.d.mts +3157 -759
- package/dist/index.d.ts +3157 -759
- package/dist/index.js +15008 -186
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15067 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +25 -86
- package/CHANGELOG.md +0 -320
- package/LICENSE +0 -28
- package/README.md +0 -119
- package/dist/chain-utils-5r2UnCDS.d.mts +0 -380
- package/dist/chain-utils-5r2UnCDS.d.ts +0 -380
- package/dist/chunk-4NQPS3JC.js +0 -2101
- package/dist/chunk-4NQPS3JC.js.map +0 -1
- package/dist/chunk-6CU533DM.mjs +0 -39
- package/dist/chunk-6CU533DM.mjs.map +0 -1
- package/dist/chunk-6JLKHV6O.js +0 -128
- package/dist/chunk-6JLKHV6O.js.map +0 -1
- package/dist/chunk-FHE43NKY.js +0 -1143
- package/dist/chunk-FHE43NKY.js.map +0 -1
- package/dist/chunk-GOJQYEJQ.js +0 -3212
- package/dist/chunk-GOJQYEJQ.js.map +0 -1
- package/dist/chunk-LMNADWTH.mjs +0 -2073
- package/dist/chunk-LMNADWTH.mjs.map +0 -1
- package/dist/chunk-ODXJYXUH.mjs +0 -3168
- package/dist/chunk-ODXJYXUH.mjs.map +0 -1
- package/dist/chunk-QMFYPHX5.mjs +0 -690
- package/dist/chunk-QMFYPHX5.mjs.map +0 -1
- package/dist/chunk-TNL23CO2.js +0 -45
- package/dist/chunk-TNL23CO2.js.map +0 -1
- package/dist/chunk-UY2WD7MF.mjs +0 -1133
- package/dist/chunk-UY2WD7MF.mjs.map +0 -1
- package/dist/chunk-WD6QFSXZ.js +0 -701
- package/dist/chunk-WD6QFSXZ.js.map +0 -1
- package/dist/chunk-Y5LBT2WT.mjs +0 -118
- package/dist/chunk-Y5LBT2WT.mjs.map +0 -1
- package/dist/core.d.mts +0 -195
- package/dist/core.d.ts +0 -195
- package/dist/core.js +0 -1236
- package/dist/core.js.map +0 -1
- package/dist/core.mjs +0 -1194
- package/dist/core.mjs.map +0 -1
- package/dist/display.d.mts +0 -472
- package/dist/display.d.ts +0 -472
- package/dist/display.js +0 -52
- package/dist/display.js.map +0 -1
- package/dist/display.mjs +0 -7
- package/dist/display.mjs.map +0 -1
- package/dist/index-D8RtV9cB.d.mts +0 -5114
- package/dist/index-ev_V5sjt.d.ts +0 -5114
- package/dist/utils.d.mts +0 -112
- package/dist/utils.d.ts +0 -112
- package/dist/utils.js +0 -67
- package/dist/utils.js.map +0 -1
- package/dist/utils.mjs +0 -25
- package/dist/utils.mjs.map +0 -1
- package/dist/vaults.d.mts +0 -4
- package/dist/vaults.d.ts +0 -4
- package/dist/vaults.js +0 -96
- package/dist/vaults.js.map +0 -1
- package/dist/vaults.mjs +0 -7
- package/dist/vaults.mjs.map +0 -1
package/dist/chunk-LMNADWTH.mjs
DELETED
|
@@ -1,2073 +0,0 @@
|
|
|
1
|
-
import { resolveVault, InvalidChainIdError, TransactionDataError, WithdrawError } from './chunk-Y5LBT2WT.mjs';
|
|
2
|
-
import { getTokenPermitInfoWithAllowance, getErc20AllowanceWithDecimals, getRateInQuoteWithAssetDecimals, erc2612Abi, getErc20Decimals, BoringVaultAbi, AccountantAbi } from './chunk-UY2WD7MF.mjs';
|
|
3
|
-
import { WAD } from './chunk-6CU533DM.mjs';
|
|
4
|
-
import { getLogger, APIError, getRestV2BaseURL, getRequestHeaders, createTimeoutSignal, DEFAULT_TIMEOUT, toChainId, getSupportedAssets, DEFAULT_APPROVAL_AMOUNT, DEFAULT_SLIPPAGE_BPS, DistributorCodeDepositorAbiV0, getClient, WithdrawQueueAbi, readDepositFeeStructure, readSupplyCapInBase } from './chunk-ODXJYXUH.mjs';
|
|
5
|
-
import { formatUnits, parseUnits, erc20Abi, stringToHex, zeroAddress, hexToSignature, maxUint256 } from 'viem';
|
|
6
|
-
|
|
7
|
-
// src/client/kyt-client.ts
|
|
8
|
-
var CHAIN_ID_TO_PREDICATE_CHAIN = {
|
|
9
|
-
1: "ethereum",
|
|
10
|
-
11155111: "sepolia",
|
|
11
|
-
8453: "base",
|
|
12
|
-
84532: "base-sepolia",
|
|
13
|
-
999: "hyperevm",
|
|
14
|
-
2201: "stable-testnet"
|
|
15
|
-
};
|
|
16
|
-
async function fetchKytAttestation(params) {
|
|
17
|
-
const { to, from, chainId } = params;
|
|
18
|
-
const logger = getLogger();
|
|
19
|
-
const chain = CHAIN_ID_TO_PREDICATE_CHAIN[chainId];
|
|
20
|
-
if (!chain) {
|
|
21
|
-
throw new APIError(
|
|
22
|
-
`KYT attestation not supported for chain ID ${chainId}. Supported chains: ${Object.keys(CHAIN_ID_TO_PREDICATE_CHAIN).join(", ")}`,
|
|
23
|
-
{ endpoint: "kytAttestation" }
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
const url = `${getRestV2BaseURL()}/kytAttestation`;
|
|
27
|
-
const headers = getRequestHeaders();
|
|
28
|
-
logger.debug("Fetching KYT attestation", { to, from, chain });
|
|
29
|
-
let response;
|
|
30
|
-
try {
|
|
31
|
-
response = await fetch(url, {
|
|
32
|
-
method: "POST",
|
|
33
|
-
headers,
|
|
34
|
-
body: JSON.stringify({ to, from, chain }),
|
|
35
|
-
signal: createTimeoutSignal(DEFAULT_TIMEOUT)
|
|
36
|
-
});
|
|
37
|
-
} catch (error) {
|
|
38
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
39
|
-
throw new APIError("KYT attestation request timed out", {
|
|
40
|
-
endpoint: "kytAttestation",
|
|
41
|
-
cause: error
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
throw new APIError(
|
|
45
|
-
`KYT attestation request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
46
|
-
{ endpoint: "kytAttestation", cause: error }
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
if (!response.ok) {
|
|
50
|
-
let serverMessage;
|
|
51
|
-
try {
|
|
52
|
-
const errorBody = await response.json();
|
|
53
|
-
serverMessage = errorBody?.error?.message;
|
|
54
|
-
} catch {
|
|
55
|
-
}
|
|
56
|
-
if (response.status === 403) {
|
|
57
|
-
throw new APIError(
|
|
58
|
-
serverMessage ?? "Deposit blocked: transaction is not compliant with KYT policy",
|
|
59
|
-
{ endpoint: "kytAttestation", statusCode: 403 }
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
if (response.status === 400) {
|
|
63
|
-
throw new APIError(
|
|
64
|
-
serverMessage ?? "KYT attestation request was rejected: invalid parameters",
|
|
65
|
-
{ endpoint: "kytAttestation", statusCode: 400 }
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
throw new APIError(
|
|
69
|
-
serverMessage ?? `KYT attestation request failed (HTTP ${response.status})`,
|
|
70
|
-
{ endpoint: "kytAttestation", statusCode: response.status }
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
let body;
|
|
74
|
-
try {
|
|
75
|
-
body = await response.json();
|
|
76
|
-
} catch (error) {
|
|
77
|
-
throw new APIError("KYT attestation response contained invalid JSON", {
|
|
78
|
-
endpoint: "kytAttestation",
|
|
79
|
-
cause: error
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
if (!body.attestation) {
|
|
83
|
-
throw new APIError("KYT attestation response missing attestation field", {
|
|
84
|
-
endpoint: "kytAttestation"
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
const { attestation } = body;
|
|
88
|
-
const missingFields = ["uuid", "attester", "signature", "expiration"].filter((f) => attestation[f] == null);
|
|
89
|
-
if (missingFields.length > 0) {
|
|
90
|
-
throw new APIError(
|
|
91
|
-
`KYT attestation response missing required fields: ${missingFields.join(", ")}`,
|
|
92
|
-
{ endpoint: "kytAttestation" }
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
if (typeof attestation.expiration !== "number" && typeof attestation.expiration !== "string") {
|
|
96
|
-
throw new APIError(
|
|
97
|
-
"KYT attestation response has invalid expiration value",
|
|
98
|
-
{ endpoint: "kytAttestation" }
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
const sig = attestation.signature.startsWith("0x") ? attestation.signature : `0x${attestation.signature}`;
|
|
102
|
-
return {
|
|
103
|
-
uuid: attestation.uuid,
|
|
104
|
-
expiration: BigInt(attestation.expiration),
|
|
105
|
-
attester: attestation.attester,
|
|
106
|
-
signature: sig
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
var isDepositSpendApproved = async ({
|
|
110
|
-
vaultName,
|
|
111
|
-
chainId,
|
|
112
|
-
depositAssetAddress,
|
|
113
|
-
recipientAddress
|
|
114
|
-
}) => {
|
|
115
|
-
try {
|
|
116
|
-
const normalizedChainId = toChainId(chainId);
|
|
117
|
-
const config = await resolveVault({
|
|
118
|
-
vaultName,
|
|
119
|
-
chainId: normalizedChainId,
|
|
120
|
-
assetAddress: depositAssetAddress,
|
|
121
|
-
callerEndpoint: "isDepositSpendApproved"
|
|
122
|
-
});
|
|
123
|
-
const communityCodeDepositorAddress = config.vault.communityCodeDepositorAddress;
|
|
124
|
-
if (!communityCodeDepositorAddress) {
|
|
125
|
-
throw new APIError(
|
|
126
|
-
`Community code depositor contract address not configured for vault ${config.id}`,
|
|
127
|
-
{
|
|
128
|
-
endpoint: "isDepositSpendApproved"
|
|
129
|
-
}
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
const {
|
|
133
|
-
decimals,
|
|
134
|
-
allowance,
|
|
135
|
-
supportsPermit,
|
|
136
|
-
nonce,
|
|
137
|
-
domainSeparator,
|
|
138
|
-
tokenName,
|
|
139
|
-
tokenVersion
|
|
140
|
-
} = await getTokenPermitInfoWithAllowance({
|
|
141
|
-
chainId: normalizedChainId,
|
|
142
|
-
tokenAddress: depositAssetAddress,
|
|
143
|
-
owner: recipientAddress,
|
|
144
|
-
spender: communityCodeDepositorAddress
|
|
145
|
-
});
|
|
146
|
-
return {
|
|
147
|
-
isApproved: allowance > 0n,
|
|
148
|
-
allowance: formatUnits(allowance, decimals),
|
|
149
|
-
allowanceAsBigInt: allowance.toString(),
|
|
150
|
-
decimals,
|
|
151
|
-
supportsPermit,
|
|
152
|
-
nonce,
|
|
153
|
-
domainSeparator,
|
|
154
|
-
tokenName,
|
|
155
|
-
tokenVersion,
|
|
156
|
-
error: null
|
|
157
|
-
};
|
|
158
|
-
} catch (error) {
|
|
159
|
-
if (error instanceof APIError) {
|
|
160
|
-
throw error;
|
|
161
|
-
}
|
|
162
|
-
throw new APIError(
|
|
163
|
-
`Failed to check deposit approval: ${error instanceof Error ? error.message : String(error)}`,
|
|
164
|
-
{
|
|
165
|
-
endpoint: "isDepositSpendApproved",
|
|
166
|
-
cause: error
|
|
167
|
-
}
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
var isWithdrawalSpendApproved = async ({
|
|
172
|
-
vaultName,
|
|
173
|
-
chainId,
|
|
174
|
-
wantAssetAddress,
|
|
175
|
-
recipientAddress
|
|
176
|
-
}) => {
|
|
177
|
-
try {
|
|
178
|
-
const normalizedChainId = toChainId(chainId);
|
|
179
|
-
const config = await resolveVault({
|
|
180
|
-
vaultName,
|
|
181
|
-
chainId: normalizedChainId,
|
|
182
|
-
assetAddress: wantAssetAddress,
|
|
183
|
-
callerEndpoint: "isWithdrawalSpendApproved"
|
|
184
|
-
});
|
|
185
|
-
const boringVaultAddress = config.vault.boringVaultAddress;
|
|
186
|
-
if (!boringVaultAddress) {
|
|
187
|
-
throw new APIError(
|
|
188
|
-
`BoringVault contract address not configured for vault ${config.id}`,
|
|
189
|
-
{
|
|
190
|
-
endpoint: "isWithdrawalSpendApproved"
|
|
191
|
-
}
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
const withdrawQueueAddress = config.vault.withdrawQueueAddress;
|
|
195
|
-
if (!withdrawQueueAddress) {
|
|
196
|
-
throw new APIError(
|
|
197
|
-
`WithdrawQueue contract address not configured for vault ${config.id}`,
|
|
198
|
-
{
|
|
199
|
-
endpoint: "isWithdrawalSpendApproved"
|
|
200
|
-
}
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
const [allowance, decimals] = await getErc20AllowanceWithDecimals({
|
|
204
|
-
chainId: normalizedChainId,
|
|
205
|
-
tokenAddress: boringVaultAddress,
|
|
206
|
-
recipientAddress,
|
|
207
|
-
spenderAddress: withdrawQueueAddress
|
|
208
|
-
});
|
|
209
|
-
if (allowance.status === "failure" || decimals.status === "failure") {
|
|
210
|
-
return {
|
|
211
|
-
isApproved: false,
|
|
212
|
-
allowance: "0",
|
|
213
|
-
allowanceAsBigInt: "0",
|
|
214
|
-
decimals: "0",
|
|
215
|
-
error: allowance.error || decimals.error
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
return {
|
|
219
|
-
isApproved: allowance.result > 0n,
|
|
220
|
-
allowance: formatUnits(allowance.result, decimals.result),
|
|
221
|
-
allowanceAsBigInt: allowance.result.toString(),
|
|
222
|
-
decimals: decimals.result,
|
|
223
|
-
error: null
|
|
224
|
-
};
|
|
225
|
-
} catch (error) {
|
|
226
|
-
if (error instanceof APIError) {
|
|
227
|
-
throw error;
|
|
228
|
-
}
|
|
229
|
-
throw new APIError(
|
|
230
|
-
`Failed to check withdrawal approval: ${error instanceof Error ? error.message : String(error)}`,
|
|
231
|
-
{ endpoint: "isWithdrawalSpendApproved", cause: error }
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
async function prepareApproveDepositTokenTxData({
|
|
236
|
-
vaultName,
|
|
237
|
-
depositAsset,
|
|
238
|
-
approvalAmount,
|
|
239
|
-
chainId
|
|
240
|
-
}) {
|
|
241
|
-
const normalizedChainId = toChainId(chainId);
|
|
242
|
-
try {
|
|
243
|
-
const config = await resolveVault({
|
|
244
|
-
vaultName,
|
|
245
|
-
assetAddress: depositAsset,
|
|
246
|
-
chainId: normalizedChainId,
|
|
247
|
-
callerEndpoint: "prepareApproveDepositToken"
|
|
248
|
-
});
|
|
249
|
-
const communityCodeDepositorAddress = config.vault.communityCodeDepositorAddress;
|
|
250
|
-
if (!communityCodeDepositorAddress) {
|
|
251
|
-
throw new APIError(
|
|
252
|
-
`Community Code Depositor contract address not configured for vault ${config.id}`,
|
|
253
|
-
{ endpoint: "prepareApproveDepositToken" }
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
const assets = await getSupportedAssets({ address: depositAsset });
|
|
257
|
-
if (assets.length === 0) {
|
|
258
|
-
throw new APIError(
|
|
259
|
-
`Asset metadata not found for token ${depositAsset} on chain ${normalizedChainId}`,
|
|
260
|
-
{ endpoint: "prepareApproveDepositToken" }
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
const verifiedAsset = assets.find(
|
|
264
|
-
(asset) => asset.address.toLowerCase() === depositAsset.toLowerCase() && asset.chains.includes(normalizedChainId)
|
|
265
|
-
);
|
|
266
|
-
if (!verifiedAsset) {
|
|
267
|
-
throw new APIError(
|
|
268
|
-
`Asset ${depositAsset} not verified on chain ${normalizedChainId}`,
|
|
269
|
-
{ endpoint: "prepareApproveDepositToken" }
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
const decimals = verifiedAsset.decimals;
|
|
273
|
-
const amount = approvalAmount ? parseUnits(approvalAmount, decimals) : DEFAULT_APPROVAL_AMOUNT;
|
|
274
|
-
return {
|
|
275
|
-
abi: erc20Abi,
|
|
276
|
-
address: depositAsset,
|
|
277
|
-
functionName: "approve",
|
|
278
|
-
args: [communityCodeDepositorAddress, amount]
|
|
279
|
-
};
|
|
280
|
-
} catch (error) {
|
|
281
|
-
if (error instanceof APIError) {
|
|
282
|
-
throw error;
|
|
283
|
-
}
|
|
284
|
-
throw new APIError(
|
|
285
|
-
`Failed to prepare approval transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
286
|
-
{
|
|
287
|
-
endpoint: "prepareApproveDepositToken",
|
|
288
|
-
cause: error
|
|
289
|
-
}
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// src/abi/distributor-code-depositor-abi-v1.ts
|
|
295
|
-
var DistributorCodeDepositorAbiV1 = [
|
|
296
|
-
{
|
|
297
|
-
inputs: [
|
|
298
|
-
{
|
|
299
|
-
internalType: "contract TellerWithMultiAssetSupport",
|
|
300
|
-
name: "_teller",
|
|
301
|
-
type: "address"
|
|
302
|
-
},
|
|
303
|
-
{
|
|
304
|
-
internalType: "contract INativeWrapper",
|
|
305
|
-
name: "_nativeWrapper",
|
|
306
|
-
type: "address"
|
|
307
|
-
},
|
|
308
|
-
{
|
|
309
|
-
internalType: "contract Authority",
|
|
310
|
-
name: "_rolesAuthority",
|
|
311
|
-
type: "address"
|
|
312
|
-
},
|
|
313
|
-
{ internalType: "bool", name: "_isNativeDepositSupported", type: "bool" },
|
|
314
|
-
{ internalType: "uint256", name: "_supplyCap", type: "uint256" },
|
|
315
|
-
{
|
|
316
|
-
internalType: "contract IFeeModule",
|
|
317
|
-
name: "_feeModule",
|
|
318
|
-
type: "address"
|
|
319
|
-
},
|
|
320
|
-
{ internalType: "address", name: "_feeRecipient", type: "address" },
|
|
321
|
-
{ internalType: "address", name: "_registry", type: "address" },
|
|
322
|
-
{ internalType: "string", name: "_policyID", type: "string" },
|
|
323
|
-
{ internalType: "address", name: "_owner", type: "address" }
|
|
324
|
-
],
|
|
325
|
-
stateMutability: "nonpayable",
|
|
326
|
-
type: "constructor"
|
|
327
|
-
},
|
|
328
|
-
{ inputs: [], name: "FeesExceedOrEqualAmount", type: "error" },
|
|
329
|
-
{ inputs: [], name: "IncorrectNativeDepositAmount", type: "error" },
|
|
330
|
-
{
|
|
331
|
-
inputs: [
|
|
332
|
-
{ internalType: "uint256", name: "actual", type: "uint256" },
|
|
333
|
-
{ internalType: "uint256", name: "minimum", type: "uint256" }
|
|
334
|
-
],
|
|
335
|
-
name: "InsufficientSharesAfterFees",
|
|
336
|
-
type: "error"
|
|
337
|
-
},
|
|
338
|
-
{ inputs: [], name: "NativeDepositNotSupported", type: "error" },
|
|
339
|
-
{
|
|
340
|
-
inputs: [],
|
|
341
|
-
name: "NativeWrapperAccountantDecimalsMismatch",
|
|
342
|
-
type: "error"
|
|
343
|
-
},
|
|
344
|
-
{
|
|
345
|
-
inputs: [
|
|
346
|
-
{ internalType: "address", name: "addressEmptyCode", type: "address" }
|
|
347
|
-
],
|
|
348
|
-
name: "NoCode",
|
|
349
|
-
type: "error"
|
|
350
|
-
},
|
|
351
|
-
{ inputs: [], name: "PermitFailedAndAllowanceTooLow", type: "error" },
|
|
352
|
-
{
|
|
353
|
-
inputs: [
|
|
354
|
-
{ internalType: "uint256", name: "resultingValue", type: "uint256" },
|
|
355
|
-
{ internalType: "uint256", name: "supplyCapInBase", type: "uint256" }
|
|
356
|
-
],
|
|
357
|
-
name: "SupplyCapInBaseError",
|
|
358
|
-
type: "error"
|
|
359
|
-
},
|
|
360
|
-
{ inputs: [], name: "UnauthorizedTransaction", type: "error" },
|
|
361
|
-
{ inputs: [], name: "ZeroAddress", type: "error" },
|
|
362
|
-
{
|
|
363
|
-
anonymous: false,
|
|
364
|
-
inputs: [
|
|
365
|
-
{ indexed: true, internalType: "address", name: "user", type: "address" },
|
|
366
|
-
{
|
|
367
|
-
indexed: true,
|
|
368
|
-
internalType: "contract Authority",
|
|
369
|
-
name: "newAuthority",
|
|
370
|
-
type: "address"
|
|
371
|
-
}
|
|
372
|
-
],
|
|
373
|
-
name: "AuthorityUpdated",
|
|
374
|
-
type: "event"
|
|
375
|
-
},
|
|
376
|
-
{
|
|
377
|
-
anonymous: false,
|
|
378
|
-
inputs: [
|
|
379
|
-
{
|
|
380
|
-
indexed: true,
|
|
381
|
-
internalType: "address",
|
|
382
|
-
name: "depositor",
|
|
383
|
-
type: "address"
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
indexed: true,
|
|
387
|
-
internalType: "contract ERC20",
|
|
388
|
-
name: "depositAsset",
|
|
389
|
-
type: "address"
|
|
390
|
-
},
|
|
391
|
-
{
|
|
392
|
-
indexed: false,
|
|
393
|
-
internalType: "uint256",
|
|
394
|
-
name: "depositAmount",
|
|
395
|
-
type: "uint256"
|
|
396
|
-
},
|
|
397
|
-
{
|
|
398
|
-
indexed: false,
|
|
399
|
-
internalType: "uint256",
|
|
400
|
-
name: "minimumMint",
|
|
401
|
-
type: "uint256"
|
|
402
|
-
},
|
|
403
|
-
{ indexed: false, internalType: "address", name: "to", type: "address" },
|
|
404
|
-
{
|
|
405
|
-
indexed: false,
|
|
406
|
-
internalType: "bytes32",
|
|
407
|
-
name: "depositHash",
|
|
408
|
-
type: "bytes32"
|
|
409
|
-
},
|
|
410
|
-
{
|
|
411
|
-
indexed: true,
|
|
412
|
-
internalType: "bytes",
|
|
413
|
-
name: "distributorCode",
|
|
414
|
-
type: "bytes"
|
|
415
|
-
}
|
|
416
|
-
],
|
|
417
|
-
name: "DepositWithDistributorCode",
|
|
418
|
-
type: "event"
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
anonymous: false,
|
|
422
|
-
inputs: [
|
|
423
|
-
{
|
|
424
|
-
indexed: true,
|
|
425
|
-
internalType: "contract IFeeModule",
|
|
426
|
-
name: "newFeeModule",
|
|
427
|
-
type: "address"
|
|
428
|
-
}
|
|
429
|
-
],
|
|
430
|
-
name: "FeeModuleUpdated",
|
|
431
|
-
type: "event"
|
|
432
|
-
},
|
|
433
|
-
{
|
|
434
|
-
anonymous: false,
|
|
435
|
-
inputs: [
|
|
436
|
-
{
|
|
437
|
-
indexed: true,
|
|
438
|
-
internalType: "address",
|
|
439
|
-
name: "newFeeRecipient",
|
|
440
|
-
type: "address"
|
|
441
|
-
}
|
|
442
|
-
],
|
|
443
|
-
name: "FeeRecipientUpdated",
|
|
444
|
-
type: "event"
|
|
445
|
-
},
|
|
446
|
-
{
|
|
447
|
-
anonymous: false,
|
|
448
|
-
inputs: [
|
|
449
|
-
{
|
|
450
|
-
indexed: true,
|
|
451
|
-
internalType: "contract ERC20",
|
|
452
|
-
name: "depositAsset",
|
|
453
|
-
type: "address"
|
|
454
|
-
},
|
|
455
|
-
{ indexed: true, internalType: "bool", name: "enabled", type: "bool" }
|
|
456
|
-
],
|
|
457
|
-
name: "KytStatusUpdated",
|
|
458
|
-
type: "event"
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
anonymous: false,
|
|
462
|
-
inputs: [
|
|
463
|
-
{ indexed: true, internalType: "address", name: "user", type: "address" },
|
|
464
|
-
{
|
|
465
|
-
indexed: true,
|
|
466
|
-
internalType: "address",
|
|
467
|
-
name: "newOwner",
|
|
468
|
-
type: "address"
|
|
469
|
-
}
|
|
470
|
-
],
|
|
471
|
-
name: "OwnershipTransferred",
|
|
472
|
-
type: "event"
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
anonymous: false,
|
|
476
|
-
inputs: [
|
|
477
|
-
{
|
|
478
|
-
indexed: false,
|
|
479
|
-
internalType: "string",
|
|
480
|
-
name: "oldPolicyID",
|
|
481
|
-
type: "string"
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
indexed: false,
|
|
485
|
-
internalType: "string",
|
|
486
|
-
name: "newPolicyID",
|
|
487
|
-
type: "string"
|
|
488
|
-
}
|
|
489
|
-
],
|
|
490
|
-
name: "PredicatePolicyIDUpdated",
|
|
491
|
-
type: "event"
|
|
492
|
-
},
|
|
493
|
-
{
|
|
494
|
-
anonymous: false,
|
|
495
|
-
inputs: [
|
|
496
|
-
{
|
|
497
|
-
indexed: true,
|
|
498
|
-
internalType: "address",
|
|
499
|
-
name: "oldRegistry",
|
|
500
|
-
type: "address"
|
|
501
|
-
},
|
|
502
|
-
{
|
|
503
|
-
indexed: true,
|
|
504
|
-
internalType: "address",
|
|
505
|
-
name: "newRegistry",
|
|
506
|
-
type: "address"
|
|
507
|
-
}
|
|
508
|
-
],
|
|
509
|
-
name: "PredicateRegistryUpdated",
|
|
510
|
-
type: "event"
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
anonymous: false,
|
|
514
|
-
inputs: [
|
|
515
|
-
{
|
|
516
|
-
indexed: false,
|
|
517
|
-
internalType: "uint256",
|
|
518
|
-
name: "newSupplyCapInBase",
|
|
519
|
-
type: "uint256"
|
|
520
|
-
}
|
|
521
|
-
],
|
|
522
|
-
name: "SupplyCapInBaseUpdated",
|
|
523
|
-
type: "event"
|
|
524
|
-
},
|
|
525
|
-
{
|
|
526
|
-
inputs: [],
|
|
527
|
-
name: "PREDICATE_DEPOSIT_SIGNATURE",
|
|
528
|
-
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
529
|
-
stateMutability: "view",
|
|
530
|
-
type: "function"
|
|
531
|
-
},
|
|
532
|
-
{
|
|
533
|
-
inputs: [],
|
|
534
|
-
name: "authority",
|
|
535
|
-
outputs: [
|
|
536
|
-
{ internalType: "contract Authority", name: "", type: "address" }
|
|
537
|
-
],
|
|
538
|
-
stateMutability: "view",
|
|
539
|
-
type: "function"
|
|
540
|
-
},
|
|
541
|
-
{
|
|
542
|
-
inputs: [],
|
|
543
|
-
name: "boringVault",
|
|
544
|
-
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
545
|
-
stateMutability: "view",
|
|
546
|
-
type: "function"
|
|
547
|
-
},
|
|
548
|
-
{
|
|
549
|
-
inputs: [
|
|
550
|
-
{ internalType: "contract ERC20", name: "depositAsset", type: "address" },
|
|
551
|
-
{ internalType: "uint256", name: "depositAmount", type: "uint256" },
|
|
552
|
-
{ internalType: "uint256", name: "minimumMint", type: "uint256" },
|
|
553
|
-
{ internalType: "address", name: "to", type: "address" },
|
|
554
|
-
{ internalType: "bytes", name: "distributorCode", type: "bytes" },
|
|
555
|
-
{
|
|
556
|
-
components: [
|
|
557
|
-
{ internalType: "string", name: "uuid", type: "string" },
|
|
558
|
-
{ internalType: "uint256", name: "expiration", type: "uint256" },
|
|
559
|
-
{ internalType: "address", name: "attester", type: "address" },
|
|
560
|
-
{ internalType: "bytes", name: "signature", type: "bytes" }
|
|
561
|
-
],
|
|
562
|
-
internalType: "struct Attestation",
|
|
563
|
-
name: "_attestation",
|
|
564
|
-
type: "tuple"
|
|
565
|
-
}
|
|
566
|
-
],
|
|
567
|
-
name: "deposit",
|
|
568
|
-
outputs: [{ internalType: "uint256", name: "shares", type: "uint256" }],
|
|
569
|
-
stateMutability: "nonpayable",
|
|
570
|
-
type: "function"
|
|
571
|
-
},
|
|
572
|
-
{
|
|
573
|
-
inputs: [
|
|
574
|
-
{ internalType: "uint256", name: "depositAmount", type: "uint256" },
|
|
575
|
-
{ internalType: "uint256", name: "minimumMint", type: "uint256" },
|
|
576
|
-
{ internalType: "address", name: "to", type: "address" },
|
|
577
|
-
{ internalType: "bytes", name: "distributorCode", type: "bytes" },
|
|
578
|
-
{
|
|
579
|
-
components: [
|
|
580
|
-
{ internalType: "string", name: "uuid", type: "string" },
|
|
581
|
-
{ internalType: "uint256", name: "expiration", type: "uint256" },
|
|
582
|
-
{ internalType: "address", name: "attester", type: "address" },
|
|
583
|
-
{ internalType: "bytes", name: "signature", type: "bytes" }
|
|
584
|
-
],
|
|
585
|
-
internalType: "struct Attestation",
|
|
586
|
-
name: "_attestation",
|
|
587
|
-
type: "tuple"
|
|
588
|
-
}
|
|
589
|
-
],
|
|
590
|
-
name: "depositNative",
|
|
591
|
-
outputs: [{ internalType: "uint256", name: "shares", type: "uint256" }],
|
|
592
|
-
stateMutability: "payable",
|
|
593
|
-
type: "function"
|
|
594
|
-
},
|
|
595
|
-
{
|
|
596
|
-
inputs: [],
|
|
597
|
-
name: "depositNonce",
|
|
598
|
-
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
599
|
-
stateMutability: "view",
|
|
600
|
-
type: "function"
|
|
601
|
-
},
|
|
602
|
-
{
|
|
603
|
-
inputs: [
|
|
604
|
-
{ internalType: "contract ERC20", name: "depositAsset", type: "address" },
|
|
605
|
-
{ internalType: "uint256", name: "depositAmount", type: "uint256" },
|
|
606
|
-
{ internalType: "uint256", name: "minimumMint", type: "uint256" },
|
|
607
|
-
{ internalType: "address", name: "to", type: "address" },
|
|
608
|
-
{ internalType: "bytes", name: "distributorCode", type: "bytes" },
|
|
609
|
-
{
|
|
610
|
-
components: [
|
|
611
|
-
{ internalType: "string", name: "uuid", type: "string" },
|
|
612
|
-
{ internalType: "uint256", name: "expiration", type: "uint256" },
|
|
613
|
-
{ internalType: "address", name: "attester", type: "address" },
|
|
614
|
-
{ internalType: "bytes", name: "signature", type: "bytes" }
|
|
615
|
-
],
|
|
616
|
-
internalType: "struct Attestation",
|
|
617
|
-
name: "_attestation",
|
|
618
|
-
type: "tuple"
|
|
619
|
-
},
|
|
620
|
-
{ internalType: "uint256", name: "deadline", type: "uint256" },
|
|
621
|
-
{ internalType: "uint8", name: "v", type: "uint8" },
|
|
622
|
-
{ internalType: "bytes32", name: "r", type: "bytes32" },
|
|
623
|
-
{ internalType: "bytes32", name: "s", type: "bytes32" }
|
|
624
|
-
],
|
|
625
|
-
name: "depositWithPermit",
|
|
626
|
-
outputs: [{ internalType: "uint256", name: "shares", type: "uint256" }],
|
|
627
|
-
stateMutability: "nonpayable",
|
|
628
|
-
type: "function"
|
|
629
|
-
},
|
|
630
|
-
{
|
|
631
|
-
inputs: [],
|
|
632
|
-
name: "feeModule",
|
|
633
|
-
outputs: [
|
|
634
|
-
{ internalType: "contract IFeeModule", name: "", type: "address" }
|
|
635
|
-
],
|
|
636
|
-
stateMutability: "view",
|
|
637
|
-
type: "function"
|
|
638
|
-
},
|
|
639
|
-
{
|
|
640
|
-
inputs: [],
|
|
641
|
-
name: "feeRecipient",
|
|
642
|
-
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
643
|
-
stateMutability: "view",
|
|
644
|
-
type: "function"
|
|
645
|
-
},
|
|
646
|
-
{
|
|
647
|
-
inputs: [],
|
|
648
|
-
name: "getPolicyID",
|
|
649
|
-
outputs: [{ internalType: "string", name: "policyID", type: "string" }],
|
|
650
|
-
stateMutability: "view",
|
|
651
|
-
type: "function"
|
|
652
|
-
},
|
|
653
|
-
{
|
|
654
|
-
inputs: [],
|
|
655
|
-
name: "getRegistry",
|
|
656
|
-
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
657
|
-
stateMutability: "view",
|
|
658
|
-
type: "function"
|
|
659
|
-
},
|
|
660
|
-
{
|
|
661
|
-
inputs: [],
|
|
662
|
-
name: "isNativeDepositSupported",
|
|
663
|
-
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
664
|
-
stateMutability: "view",
|
|
665
|
-
type: "function"
|
|
666
|
-
},
|
|
667
|
-
{
|
|
668
|
-
inputs: [{ internalType: "contract ERC20", name: "", type: "address" }],
|
|
669
|
-
name: "kytEnabled",
|
|
670
|
-
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
671
|
-
stateMutability: "view",
|
|
672
|
-
type: "function"
|
|
673
|
-
},
|
|
674
|
-
{
|
|
675
|
-
inputs: [],
|
|
676
|
-
name: "nativeWrapper",
|
|
677
|
-
outputs: [
|
|
678
|
-
{ internalType: "contract INativeWrapper", name: "", type: "address" }
|
|
679
|
-
],
|
|
680
|
-
stateMutability: "view",
|
|
681
|
-
type: "function"
|
|
682
|
-
},
|
|
683
|
-
{
|
|
684
|
-
inputs: [],
|
|
685
|
-
name: "owner",
|
|
686
|
-
outputs: [{ internalType: "address", name: "", type: "address" }],
|
|
687
|
-
stateMutability: "view",
|
|
688
|
-
type: "function"
|
|
689
|
-
},
|
|
690
|
-
{
|
|
691
|
-
inputs: [
|
|
692
|
-
{
|
|
693
|
-
internalType: "contract Authority",
|
|
694
|
-
name: "newAuthority",
|
|
695
|
-
type: "address"
|
|
696
|
-
}
|
|
697
|
-
],
|
|
698
|
-
name: "setAuthority",
|
|
699
|
-
outputs: [],
|
|
700
|
-
stateMutability: "nonpayable",
|
|
701
|
-
type: "function"
|
|
702
|
-
},
|
|
703
|
-
{
|
|
704
|
-
inputs: [{ internalType: "string", name: "_policyID", type: "string" }],
|
|
705
|
-
name: "setPolicyID",
|
|
706
|
-
outputs: [],
|
|
707
|
-
stateMutability: "nonpayable",
|
|
708
|
-
type: "function"
|
|
709
|
-
},
|
|
710
|
-
{
|
|
711
|
-
inputs: [{ internalType: "address", name: "_registry", type: "address" }],
|
|
712
|
-
name: "setRegistry",
|
|
713
|
-
outputs: [],
|
|
714
|
-
stateMutability: "nonpayable",
|
|
715
|
-
type: "function"
|
|
716
|
-
},
|
|
717
|
-
{
|
|
718
|
-
inputs: [],
|
|
719
|
-
name: "supplyCapInBase",
|
|
720
|
-
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
721
|
-
stateMutability: "view",
|
|
722
|
-
type: "function"
|
|
723
|
-
},
|
|
724
|
-
{
|
|
725
|
-
inputs: [],
|
|
726
|
-
name: "teller",
|
|
727
|
-
outputs: [
|
|
728
|
-
{
|
|
729
|
-
internalType: "contract TellerWithMultiAssetSupport",
|
|
730
|
-
name: "",
|
|
731
|
-
type: "address"
|
|
732
|
-
}
|
|
733
|
-
],
|
|
734
|
-
stateMutability: "view",
|
|
735
|
-
type: "function"
|
|
736
|
-
},
|
|
737
|
-
{
|
|
738
|
-
inputs: [{ internalType: "address", name: "newOwner", type: "address" }],
|
|
739
|
-
name: "transferOwnership",
|
|
740
|
-
outputs: [],
|
|
741
|
-
stateMutability: "nonpayable",
|
|
742
|
-
type: "function"
|
|
743
|
-
},
|
|
744
|
-
{
|
|
745
|
-
inputs: [
|
|
746
|
-
{
|
|
747
|
-
internalType: "contract IFeeModule",
|
|
748
|
-
name: "newFeeModule",
|
|
749
|
-
type: "address"
|
|
750
|
-
}
|
|
751
|
-
],
|
|
752
|
-
name: "updateFeeModule",
|
|
753
|
-
outputs: [],
|
|
754
|
-
stateMutability: "nonpayable",
|
|
755
|
-
type: "function"
|
|
756
|
-
},
|
|
757
|
-
{
|
|
758
|
-
inputs: [
|
|
759
|
-
{ internalType: "address", name: "newFeeRecipient", type: "address" }
|
|
760
|
-
],
|
|
761
|
-
name: "updateFeeRecipient",
|
|
762
|
-
outputs: [],
|
|
763
|
-
stateMutability: "nonpayable",
|
|
764
|
-
type: "function"
|
|
765
|
-
},
|
|
766
|
-
{
|
|
767
|
-
inputs: [
|
|
768
|
-
{ internalType: "contract ERC20", name: "depositAsset", type: "address" },
|
|
769
|
-
{ internalType: "bool", name: "enabled", type: "bool" }
|
|
770
|
-
],
|
|
771
|
-
name: "updateKytStatus",
|
|
772
|
-
outputs: [],
|
|
773
|
-
stateMutability: "nonpayable",
|
|
774
|
-
type: "function"
|
|
775
|
-
},
|
|
776
|
-
{
|
|
777
|
-
inputs: [
|
|
778
|
-
{ internalType: "uint256", name: "newSupplyCapInBase", type: "uint256" }
|
|
779
|
-
],
|
|
780
|
-
name: "updateSupplyCapInBase",
|
|
781
|
-
outputs: [],
|
|
782
|
-
stateMutability: "nonpayable",
|
|
783
|
-
type: "function"
|
|
784
|
-
}
|
|
785
|
-
];
|
|
786
|
-
var calculateMinimumMint = (depositAmount, rate, vaultTokenDecimals, slippage) => {
|
|
787
|
-
const slippageValue = slippage ?? DEFAULT_SLIPPAGE_BPS;
|
|
788
|
-
const slippageAsBigInt = BigInt(slippageValue) * WAD.bigint / BigInt(1e4);
|
|
789
|
-
const minimumMint = depositAmount * WAD.bigint / rate;
|
|
790
|
-
const slippageAmount = minimumMint * slippageAsBigInt / WAD.bigint;
|
|
791
|
-
if (vaultTokenDecimals > 18) {
|
|
792
|
-
return (minimumMint - slippageAmount) * BigInt(10) ** (BigInt(vaultTokenDecimals) - BigInt(18));
|
|
793
|
-
}
|
|
794
|
-
return (minimumMint - slippageAmount) / BigInt(10) ** (BigInt(18) - BigInt(vaultTokenDecimals));
|
|
795
|
-
};
|
|
796
|
-
async function getDepositFeeForAmount(depositFeeModuleAddress, depositAsset, depositAmount, chainId) {
|
|
797
|
-
if (!depositFeeModuleAddress || depositFeeModuleAddress === zeroAddress) {
|
|
798
|
-
return 0n;
|
|
799
|
-
}
|
|
800
|
-
const { feePercentage, flatFee, oneHundredPercent } = await readDepositFeeStructure(
|
|
801
|
-
depositFeeModuleAddress,
|
|
802
|
-
depositAsset,
|
|
803
|
-
chainId
|
|
804
|
-
);
|
|
805
|
-
const variableFee = oneHundredPercent > 0n ? depositAmount * feePercentage / oneHundredPercent : 0n;
|
|
806
|
-
return variableFee + flatFee;
|
|
807
|
-
}
|
|
808
|
-
async function assertDepositWithinCap(vault, depositAmountRaw, depositAssetAddress, chainId, callerEndpoint) {
|
|
809
|
-
let supplyCapInBase = null;
|
|
810
|
-
let hasDepositCap = false;
|
|
811
|
-
if (vault.depositCap) {
|
|
812
|
-
supplyCapInBase = vault.depositCap.supplyCapInBase;
|
|
813
|
-
hasDepositCap = vault.depositCap.hasDepositCap;
|
|
814
|
-
} else if (vault.vault.communityCodeDepositorAddress && vault.vault.depositFeeModuleAddress) {
|
|
815
|
-
const onChainCap = await readSupplyCapInBase(
|
|
816
|
-
vault.vault.communityCodeDepositorAddress,
|
|
817
|
-
chainId
|
|
818
|
-
);
|
|
819
|
-
supplyCapInBase = onChainCap;
|
|
820
|
-
hasDepositCap = onChainCap !== 0n && onChainCap !== maxUint256;
|
|
821
|
-
}
|
|
822
|
-
if (!hasDepositCap || supplyCapInBase == null) return;
|
|
823
|
-
const client = await getClient(chainId);
|
|
824
|
-
const [supplyResult, baseRateResult, quoteRateResult, decResult] = await client.multicall({
|
|
825
|
-
contracts: [
|
|
826
|
-
{
|
|
827
|
-
abi: BoringVaultAbi,
|
|
828
|
-
address: vault.vault.boringVaultAddress,
|
|
829
|
-
functionName: "totalSupply"
|
|
830
|
-
},
|
|
831
|
-
{
|
|
832
|
-
abi: AccountantAbi,
|
|
833
|
-
address: vault.vault.accountantAddress,
|
|
834
|
-
functionName: "getRate"
|
|
835
|
-
},
|
|
836
|
-
{
|
|
837
|
-
abi: AccountantAbi,
|
|
838
|
-
address: vault.vault.accountantAddress,
|
|
839
|
-
functionName: "getRateInQuote",
|
|
840
|
-
args: [depositAssetAddress]
|
|
841
|
-
},
|
|
842
|
-
{
|
|
843
|
-
abi: AccountantAbi,
|
|
844
|
-
address: vault.vault.accountantAddress,
|
|
845
|
-
functionName: "decimals"
|
|
846
|
-
}
|
|
847
|
-
]
|
|
848
|
-
});
|
|
849
|
-
if (supplyResult.status !== "success" || baseRateResult.status !== "success" || quoteRateResult.status !== "success" || decResult.status !== "success") {
|
|
850
|
-
throw new APIError(
|
|
851
|
-
"Unable to verify deposit against supply cap: on-chain read failed",
|
|
852
|
-
{ endpoint: callerEndpoint }
|
|
853
|
-
);
|
|
854
|
-
}
|
|
855
|
-
const currentValueInBase = supplyResult.result * baseRateResult.result / 10n ** BigInt(decResult.result);
|
|
856
|
-
const depositAmountInBase = quoteRateResult.result > 0n ? depositAmountRaw * baseRateResult.result / quoteRateResult.result : depositAmountRaw;
|
|
857
|
-
const remaining = supplyCapInBase > currentValueInBase ? supplyCapInBase - currentValueInBase : 0n;
|
|
858
|
-
if (depositAmountInBase > remaining) {
|
|
859
|
-
throw new APIError(
|
|
860
|
-
`Deposit would exceed vault supply cap. Remaining capacity: ${remaining}, deposit amount (in base): ${depositAmountInBase}`,
|
|
861
|
-
{ endpoint: callerEndpoint }
|
|
862
|
-
);
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
// src/vaults/deposit/deposit.ts
|
|
867
|
-
var DepositType = {
|
|
868
|
-
STANDARD: "standard",
|
|
869
|
-
KYT: "kyt"
|
|
870
|
-
};
|
|
871
|
-
function isKytDeposit(data) {
|
|
872
|
-
return data.depositType === DepositType.KYT;
|
|
873
|
-
}
|
|
874
|
-
function isStandardDeposit(data) {
|
|
875
|
-
return data.depositType === DepositType.STANDARD;
|
|
876
|
-
}
|
|
877
|
-
async function prepareDepositTxData(params) {
|
|
878
|
-
const {
|
|
879
|
-
vaultName,
|
|
880
|
-
depositAsset,
|
|
881
|
-
depositAmount,
|
|
882
|
-
chainId,
|
|
883
|
-
slippage = DEFAULT_SLIPPAGE_BPS,
|
|
884
|
-
to,
|
|
885
|
-
distributorCode
|
|
886
|
-
} = params;
|
|
887
|
-
try {
|
|
888
|
-
const normalizedChainId = toChainId(chainId);
|
|
889
|
-
const vault = await resolveVault({
|
|
890
|
-
vaultName,
|
|
891
|
-
assetAddress: depositAsset,
|
|
892
|
-
chainId: normalizedChainId,
|
|
893
|
-
callerEndpoint: "prepareDepositTransactionData"
|
|
894
|
-
});
|
|
895
|
-
if (vault.inDeprecation) {
|
|
896
|
-
getLogger().warn(
|
|
897
|
-
`Vault "${vault.name}" is being deprecated. Please contact the Paxos Labs team for migration guidance.`
|
|
898
|
-
);
|
|
899
|
-
}
|
|
900
|
-
const assets = await getSupportedAssets({ address: depositAsset });
|
|
901
|
-
const asset = assets.find((a) => a.chains.includes(normalizedChainId)) || assets.find((a) => a.address.toLowerCase() === depositAsset.toLowerCase());
|
|
902
|
-
if (!asset) {
|
|
903
|
-
throw new APIError(
|
|
904
|
-
`Asset metadata not found for token ${depositAsset} on chain ${normalizedChainId}`,
|
|
905
|
-
{
|
|
906
|
-
endpoint: "prepareDepositTransactionData"
|
|
907
|
-
}
|
|
908
|
-
);
|
|
909
|
-
}
|
|
910
|
-
const communityCodeDepositorAddress = vault.vault.communityCodeDepositorAddress;
|
|
911
|
-
if (!communityCodeDepositorAddress) {
|
|
912
|
-
throw new APIError(
|
|
913
|
-
`Community Code Depositor contract address not found for vault ${vault.id}`,
|
|
914
|
-
{ endpoint: "prepareDepositTransactionData" }
|
|
915
|
-
);
|
|
916
|
-
}
|
|
917
|
-
const accountantAddress = vault.vault.accountantAddress;
|
|
918
|
-
if (!accountantAddress) {
|
|
919
|
-
throw new APIError(
|
|
920
|
-
`Accountant contract address not found for vault ${vault.id}`,
|
|
921
|
-
{ endpoint: "prepareDepositTransactionData" }
|
|
922
|
-
);
|
|
923
|
-
}
|
|
924
|
-
const depositAssetAddress = asset.address;
|
|
925
|
-
const [depositAssetDecimalsResult, rateInQuoteResult] = await getRateInQuoteWithAssetDecimals({
|
|
926
|
-
assetAddress: depositAssetAddress,
|
|
927
|
-
accountantAddress,
|
|
928
|
-
chainId: normalizedChainId
|
|
929
|
-
});
|
|
930
|
-
if (depositAssetDecimalsResult.status === "failure") {
|
|
931
|
-
throw new APIError(
|
|
932
|
-
`Failed to get asset decimals: ${depositAssetDecimalsResult.error?.message || "Unknown error"}`,
|
|
933
|
-
{
|
|
934
|
-
endpoint: "prepareDepositTransactionData",
|
|
935
|
-
cause: depositAssetDecimalsResult.error
|
|
936
|
-
}
|
|
937
|
-
);
|
|
938
|
-
}
|
|
939
|
-
if (rateInQuoteResult.status === "failure") {
|
|
940
|
-
throw new APIError(
|
|
941
|
-
`Failed to get exchange rate: ${rateInQuoteResult.error?.message || "Unknown error"}`,
|
|
942
|
-
{
|
|
943
|
-
endpoint: "prepareDepositTransactionData",
|
|
944
|
-
cause: rateInQuoteResult.error
|
|
945
|
-
}
|
|
946
|
-
);
|
|
947
|
-
}
|
|
948
|
-
const depositAmountAsBigInt = parseUnits(
|
|
949
|
-
depositAmount,
|
|
950
|
-
depositAssetDecimalsResult.result
|
|
951
|
-
);
|
|
952
|
-
const totalFee = await getDepositFeeForAmount(
|
|
953
|
-
vault.vault.depositFeeModuleAddress,
|
|
954
|
-
depositAssetAddress,
|
|
955
|
-
depositAmountAsBigInt,
|
|
956
|
-
normalizedChainId
|
|
957
|
-
);
|
|
958
|
-
if (totalFee >= depositAmountAsBigInt) {
|
|
959
|
-
throw new APIError(
|
|
960
|
-
"Deposit amount is entirely consumed by fees. Increase the deposit amount.",
|
|
961
|
-
{ endpoint: "prepareDepositTransactionData" }
|
|
962
|
-
);
|
|
963
|
-
}
|
|
964
|
-
const depositAmountAfterFees = depositAmountAsBigInt - totalFee;
|
|
965
|
-
await assertDepositWithinCap(
|
|
966
|
-
vault,
|
|
967
|
-
depositAmountAfterFees,
|
|
968
|
-
depositAssetAddress,
|
|
969
|
-
normalizedChainId,
|
|
970
|
-
"prepareDepositTransactionData"
|
|
971
|
-
);
|
|
972
|
-
const minimumMint = calculateMinimumMint(
|
|
973
|
-
depositAmountAfterFees,
|
|
974
|
-
rateInQuoteResult.result,
|
|
975
|
-
depositAssetDecimalsResult.result,
|
|
976
|
-
slippage
|
|
977
|
-
);
|
|
978
|
-
const distributorCodeHex = stringToHex(distributorCode || "");
|
|
979
|
-
const policyId = vault.enterpriseConfig?.predicatePolicyId;
|
|
980
|
-
if (policyId === void 0) {
|
|
981
|
-
return {
|
|
982
|
-
depositType: DepositType.STANDARD,
|
|
983
|
-
abi: DistributorCodeDepositorAbiV0,
|
|
984
|
-
address: communityCodeDepositorAddress,
|
|
985
|
-
functionName: "deposit",
|
|
986
|
-
args: [
|
|
987
|
-
depositAssetAddress,
|
|
988
|
-
depositAmountAsBigInt,
|
|
989
|
-
minimumMint,
|
|
990
|
-
to,
|
|
991
|
-
distributorCodeHex
|
|
992
|
-
],
|
|
993
|
-
chainId: normalizedChainId
|
|
994
|
-
};
|
|
995
|
-
}
|
|
996
|
-
if (policyId === null) {
|
|
997
|
-
const emptyAttestation = {
|
|
998
|
-
uuid: "",
|
|
999
|
-
expiration: 0n,
|
|
1000
|
-
attester: zeroAddress,
|
|
1001
|
-
signature: "0x"
|
|
1002
|
-
};
|
|
1003
|
-
return {
|
|
1004
|
-
depositType: DepositType.KYT,
|
|
1005
|
-
address: communityCodeDepositorAddress,
|
|
1006
|
-
abi: DistributorCodeDepositorAbiV1,
|
|
1007
|
-
functionName: "deposit",
|
|
1008
|
-
args: [
|
|
1009
|
-
depositAssetAddress,
|
|
1010
|
-
depositAmountAsBigInt,
|
|
1011
|
-
minimumMint,
|
|
1012
|
-
to,
|
|
1013
|
-
distributorCodeHex,
|
|
1014
|
-
emptyAttestation
|
|
1015
|
-
],
|
|
1016
|
-
chainId: normalizedChainId
|
|
1017
|
-
};
|
|
1018
|
-
}
|
|
1019
|
-
const attestation = await fetchKytAttestation({
|
|
1020
|
-
to: communityCodeDepositorAddress,
|
|
1021
|
-
from: to,
|
|
1022
|
-
chainId: normalizedChainId
|
|
1023
|
-
});
|
|
1024
|
-
return {
|
|
1025
|
-
depositType: DepositType.KYT,
|
|
1026
|
-
address: communityCodeDepositorAddress,
|
|
1027
|
-
abi: DistributorCodeDepositorAbiV1,
|
|
1028
|
-
functionName: "deposit",
|
|
1029
|
-
args: [
|
|
1030
|
-
depositAssetAddress,
|
|
1031
|
-
depositAmountAsBigInt,
|
|
1032
|
-
minimumMint,
|
|
1033
|
-
to,
|
|
1034
|
-
distributorCodeHex,
|
|
1035
|
-
attestation
|
|
1036
|
-
],
|
|
1037
|
-
chainId: normalizedChainId
|
|
1038
|
-
};
|
|
1039
|
-
} catch (error) {
|
|
1040
|
-
if (error instanceof APIError) {
|
|
1041
|
-
throw error;
|
|
1042
|
-
}
|
|
1043
|
-
throw new APIError(
|
|
1044
|
-
`Failed to prepare deposit transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
1045
|
-
{
|
|
1046
|
-
endpoint: "prepareDepositTransactionData",
|
|
1047
|
-
cause: error
|
|
1048
|
-
}
|
|
1049
|
-
);
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
var PERMIT_TYPES = {
|
|
1053
|
-
Permit: [
|
|
1054
|
-
{ name: "owner", type: "address" },
|
|
1055
|
-
{ name: "spender", type: "address" },
|
|
1056
|
-
{ name: "value", type: "uint256" },
|
|
1057
|
-
{ name: "nonce", type: "uint256" },
|
|
1058
|
-
{ name: "deadline", type: "uint256" }
|
|
1059
|
-
]
|
|
1060
|
-
};
|
|
1061
|
-
var EIP712_DOMAIN_TYPE = [
|
|
1062
|
-
{ name: "name", type: "string" },
|
|
1063
|
-
{ name: "version", type: "string" },
|
|
1064
|
-
{ name: "chainId", type: "uint256" },
|
|
1065
|
-
{ name: "verifyingContract", type: "address" }
|
|
1066
|
-
];
|
|
1067
|
-
function toEthSignTypedDataV4(permitData) {
|
|
1068
|
-
return JSON.stringify({
|
|
1069
|
-
domain: permitData.domain,
|
|
1070
|
-
types: {
|
|
1071
|
-
EIP712Domain: EIP712_DOMAIN_TYPE,
|
|
1072
|
-
...permitData.types
|
|
1073
|
-
},
|
|
1074
|
-
primaryType: permitData.primaryType,
|
|
1075
|
-
message: {
|
|
1076
|
-
owner: permitData.message.owner,
|
|
1077
|
-
spender: permitData.message.spender,
|
|
1078
|
-
value: permitData.message.value.toString(),
|
|
1079
|
-
nonce: permitData.message.nonce.toString(),
|
|
1080
|
-
deadline: permitData.message.deadline.toString()
|
|
1081
|
-
}
|
|
1082
|
-
});
|
|
1083
|
-
}
|
|
1084
|
-
async function prepareDepositPermitSignature(params) {
|
|
1085
|
-
const {
|
|
1086
|
-
vaultName,
|
|
1087
|
-
depositAsset,
|
|
1088
|
-
depositAmount,
|
|
1089
|
-
to,
|
|
1090
|
-
chainId,
|
|
1091
|
-
deadline,
|
|
1092
|
-
// Optional pre-fetched data to skip RPC calls
|
|
1093
|
-
nonce: prefetchedNonce,
|
|
1094
|
-
decimals: prefetchedDecimals,
|
|
1095
|
-
tokenName: prefetchedTokenName,
|
|
1096
|
-
tokenVersion: prefetchedTokenVersion
|
|
1097
|
-
} = params;
|
|
1098
|
-
try {
|
|
1099
|
-
const normalizedChainId = toChainId(chainId);
|
|
1100
|
-
const vault = await resolveVault({
|
|
1101
|
-
vaultName,
|
|
1102
|
-
assetAddress: depositAsset,
|
|
1103
|
-
chainId: normalizedChainId,
|
|
1104
|
-
callerEndpoint: "prepareDepositPermitSignature"
|
|
1105
|
-
});
|
|
1106
|
-
const communityCodeDepositorAddress = vault.vault.communityCodeDepositorAddress;
|
|
1107
|
-
if (!communityCodeDepositorAddress) {
|
|
1108
|
-
throw new APIError(
|
|
1109
|
-
`CommunityCodeDepositor contract address not found for vault ${vault.id}`,
|
|
1110
|
-
{ endpoint: "prepareDepositPermitSignature" }
|
|
1111
|
-
);
|
|
1112
|
-
}
|
|
1113
|
-
let resolvedTokenName;
|
|
1114
|
-
let resolvedTokenVersion;
|
|
1115
|
-
let resolvedNonce;
|
|
1116
|
-
const hasAllPrefetchedData = prefetchedTokenName !== void 0 && prefetchedTokenVersion !== void 0 && prefetchedNonce !== void 0;
|
|
1117
|
-
if (hasAllPrefetchedData) {
|
|
1118
|
-
resolvedTokenName = prefetchedTokenName;
|
|
1119
|
-
resolvedTokenVersion = prefetchedTokenVersion;
|
|
1120
|
-
resolvedNonce = prefetchedNonce;
|
|
1121
|
-
} else {
|
|
1122
|
-
const client = await getClient(normalizedChainId);
|
|
1123
|
-
try {
|
|
1124
|
-
const [nameResult, versionResult, nonceResult] = await client.multicall(
|
|
1125
|
-
{
|
|
1126
|
-
contracts: [
|
|
1127
|
-
{
|
|
1128
|
-
address: depositAsset,
|
|
1129
|
-
abi: erc2612Abi,
|
|
1130
|
-
functionName: "name"
|
|
1131
|
-
},
|
|
1132
|
-
{
|
|
1133
|
-
address: depositAsset,
|
|
1134
|
-
abi: erc2612Abi,
|
|
1135
|
-
functionName: "version"
|
|
1136
|
-
},
|
|
1137
|
-
{
|
|
1138
|
-
address: depositAsset,
|
|
1139
|
-
abi: erc2612Abi,
|
|
1140
|
-
functionName: "nonces",
|
|
1141
|
-
args: [to]
|
|
1142
|
-
}
|
|
1143
|
-
]
|
|
1144
|
-
}
|
|
1145
|
-
);
|
|
1146
|
-
if (prefetchedTokenName !== void 0) {
|
|
1147
|
-
resolvedTokenName = prefetchedTokenName;
|
|
1148
|
-
} else if (nameResult.status === "success") {
|
|
1149
|
-
resolvedTokenName = nameResult.result;
|
|
1150
|
-
} else {
|
|
1151
|
-
throw new APIError(`Failed to read token name from ${depositAsset}`, {
|
|
1152
|
-
endpoint: "prepareDepositPermitSignature",
|
|
1153
|
-
cause: nameResult.error
|
|
1154
|
-
});
|
|
1155
|
-
}
|
|
1156
|
-
if (prefetchedTokenVersion !== void 0) {
|
|
1157
|
-
resolvedTokenVersion = prefetchedTokenVersion;
|
|
1158
|
-
} else if (versionResult.status === "success") {
|
|
1159
|
-
resolvedTokenVersion = versionResult.result;
|
|
1160
|
-
} else {
|
|
1161
|
-
resolvedTokenVersion = "1";
|
|
1162
|
-
}
|
|
1163
|
-
if (prefetchedNonce !== void 0) {
|
|
1164
|
-
resolvedNonce = prefetchedNonce;
|
|
1165
|
-
} else if (nonceResult.status === "success") {
|
|
1166
|
-
resolvedNonce = nonceResult.result;
|
|
1167
|
-
} else {
|
|
1168
|
-
throw new APIError(
|
|
1169
|
-
`Token ${depositAsset} does not support EIP-2612 permit. Missing required function: nonces()`,
|
|
1170
|
-
{
|
|
1171
|
-
endpoint: "prepareDepositPermitSignature",
|
|
1172
|
-
cause: nonceResult.error
|
|
1173
|
-
}
|
|
1174
|
-
);
|
|
1175
|
-
}
|
|
1176
|
-
} catch (error) {
|
|
1177
|
-
if (error instanceof APIError) {
|
|
1178
|
-
throw error;
|
|
1179
|
-
}
|
|
1180
|
-
throw new APIError(
|
|
1181
|
-
`Failed to read token metadata: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1182
|
-
{
|
|
1183
|
-
endpoint: "prepareDepositPermitSignature",
|
|
1184
|
-
cause: error
|
|
1185
|
-
}
|
|
1186
|
-
);
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
const permitDeadline = deadline ?? BigInt(Math.floor(Date.now() / 1e3) + 3600);
|
|
1190
|
-
let resolvedDecimals;
|
|
1191
|
-
if (prefetchedDecimals !== void 0) {
|
|
1192
|
-
resolvedDecimals = prefetchedDecimals;
|
|
1193
|
-
} else {
|
|
1194
|
-
resolvedDecimals = await getErc20Decimals({
|
|
1195
|
-
tokenAddress: depositAsset,
|
|
1196
|
-
chainId: normalizedChainId
|
|
1197
|
-
});
|
|
1198
|
-
}
|
|
1199
|
-
const value = parseUnits(depositAmount, resolvedDecimals);
|
|
1200
|
-
const domain = {
|
|
1201
|
-
name: resolvedTokenName,
|
|
1202
|
-
version: resolvedTokenVersion,
|
|
1203
|
-
chainId: normalizedChainId,
|
|
1204
|
-
verifyingContract: depositAsset
|
|
1205
|
-
};
|
|
1206
|
-
const message = {
|
|
1207
|
-
owner: to,
|
|
1208
|
-
spender: communityCodeDepositorAddress,
|
|
1209
|
-
value,
|
|
1210
|
-
nonce: resolvedNonce,
|
|
1211
|
-
deadline: permitDeadline
|
|
1212
|
-
};
|
|
1213
|
-
return {
|
|
1214
|
-
account: to,
|
|
1215
|
-
domain,
|
|
1216
|
-
types: PERMIT_TYPES,
|
|
1217
|
-
primaryType: "Permit",
|
|
1218
|
-
message
|
|
1219
|
-
};
|
|
1220
|
-
} catch (error) {
|
|
1221
|
-
if (error instanceof APIError) {
|
|
1222
|
-
throw error;
|
|
1223
|
-
}
|
|
1224
|
-
throw new APIError(
|
|
1225
|
-
`Failed to prepare permit signature: ${error instanceof Error ? error.message : String(error)}`,
|
|
1226
|
-
{
|
|
1227
|
-
endpoint: "prepareDepositPermitSignature",
|
|
1228
|
-
cause: error
|
|
1229
|
-
}
|
|
1230
|
-
);
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
function parsePermitSignature(signature) {
|
|
1234
|
-
try {
|
|
1235
|
-
const parsed = hexToSignature(signature);
|
|
1236
|
-
let v;
|
|
1237
|
-
if (parsed.v !== void 0) {
|
|
1238
|
-
v = Number(parsed.v);
|
|
1239
|
-
} else if (parsed.yParity !== void 0) {
|
|
1240
|
-
v = parsed.yParity + 27;
|
|
1241
|
-
} else {
|
|
1242
|
-
v = 27;
|
|
1243
|
-
}
|
|
1244
|
-
return {
|
|
1245
|
-
v,
|
|
1246
|
-
r: parsed.r,
|
|
1247
|
-
s: parsed.s
|
|
1248
|
-
};
|
|
1249
|
-
} catch (error) {
|
|
1250
|
-
throw new APIError(
|
|
1251
|
-
`Invalid permit signature format. Expected hex string but received: ${signature}. ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1252
|
-
{
|
|
1253
|
-
endpoint: "parsePermitSignature",
|
|
1254
|
-
cause: error
|
|
1255
|
-
}
|
|
1256
|
-
);
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
async function prepareDepositWithPermitTxData(params) {
|
|
1260
|
-
const {
|
|
1261
|
-
vaultName,
|
|
1262
|
-
depositAsset,
|
|
1263
|
-
depositAmount,
|
|
1264
|
-
chainId,
|
|
1265
|
-
signature,
|
|
1266
|
-
deadline,
|
|
1267
|
-
slippage = DEFAULT_SLIPPAGE_BPS,
|
|
1268
|
-
to,
|
|
1269
|
-
distributorCode
|
|
1270
|
-
} = params;
|
|
1271
|
-
try {
|
|
1272
|
-
const { v, r, s } = parsePermitSignature(signature);
|
|
1273
|
-
if (slippage < 0 || slippage > 1e4) {
|
|
1274
|
-
throw new APIError(
|
|
1275
|
-
`Invalid slippage value: ${slippage}. Slippage must be between 0 and 10000 basis points.`,
|
|
1276
|
-
{
|
|
1277
|
-
endpoint: "prepareDepositWithPermitTxData"
|
|
1278
|
-
}
|
|
1279
|
-
);
|
|
1280
|
-
}
|
|
1281
|
-
const normalizedChainId = toChainId(chainId);
|
|
1282
|
-
const vault = await resolveVault({
|
|
1283
|
-
vaultName,
|
|
1284
|
-
assetAddress: depositAsset,
|
|
1285
|
-
chainId: normalizedChainId,
|
|
1286
|
-
callerEndpoint: "prepareDepositWithPermitTxData"
|
|
1287
|
-
});
|
|
1288
|
-
if (vault.inDeprecation) {
|
|
1289
|
-
getLogger().warn(
|
|
1290
|
-
`Vault "${vault.name}" is being deprecated. Please contact the Paxos Labs team for migration guidance.`
|
|
1291
|
-
);
|
|
1292
|
-
}
|
|
1293
|
-
let asset = null;
|
|
1294
|
-
const assets = await getSupportedAssets({ address: depositAsset });
|
|
1295
|
-
if (assets.length > 0) {
|
|
1296
|
-
asset = assets.find((a) => a.chains.includes(normalizedChainId)) || assets[0] || null;
|
|
1297
|
-
}
|
|
1298
|
-
if (!asset) {
|
|
1299
|
-
throw new APIError(
|
|
1300
|
-
`Asset metadata not found for token ${depositAsset} on chain ${normalizedChainId}`,
|
|
1301
|
-
{
|
|
1302
|
-
endpoint: "prepareDepositWithPermitTxData"
|
|
1303
|
-
}
|
|
1304
|
-
);
|
|
1305
|
-
}
|
|
1306
|
-
if (!asset.chains || !asset.chains.includes(normalizedChainId)) {
|
|
1307
|
-
throw new APIError(
|
|
1308
|
-
`Token ${asset.symbol || depositAsset} not supported on chain ${normalizedChainId}`,
|
|
1309
|
-
{
|
|
1310
|
-
endpoint: "prepareDepositWithPermitTxData"
|
|
1311
|
-
}
|
|
1312
|
-
);
|
|
1313
|
-
}
|
|
1314
|
-
const communityCodeDepositorAddress = vault.vault.communityCodeDepositorAddress;
|
|
1315
|
-
const accountantAddress = vault.vault.accountantAddress;
|
|
1316
|
-
const depositAssetAddress = depositAsset;
|
|
1317
|
-
if (!communityCodeDepositorAddress) {
|
|
1318
|
-
throw new APIError(
|
|
1319
|
-
`CommunityCodeDepositor contract address not found for vault ${vault.id}`,
|
|
1320
|
-
{ endpoint: "prepareDepositWithPermitTxData" }
|
|
1321
|
-
);
|
|
1322
|
-
}
|
|
1323
|
-
if (!accountantAddress) {
|
|
1324
|
-
throw new APIError(
|
|
1325
|
-
`Accountant contract address not found for vault ${vault.id}`,
|
|
1326
|
-
{ endpoint: "prepareDepositWithPermitTxData" }
|
|
1327
|
-
);
|
|
1328
|
-
}
|
|
1329
|
-
const rateAndDecimalResults = await getRateInQuoteWithAssetDecimals({
|
|
1330
|
-
assetAddress: depositAssetAddress,
|
|
1331
|
-
accountantAddress,
|
|
1332
|
-
chainId: normalizedChainId
|
|
1333
|
-
});
|
|
1334
|
-
const [depositAssetDecimalsResult, rateInQuoteResult] = rateAndDecimalResults;
|
|
1335
|
-
if (depositAssetDecimalsResult.status === "failure") {
|
|
1336
|
-
throw new APIError(
|
|
1337
|
-
`Failed to get asset decimals: ${depositAssetDecimalsResult.error?.message || "Unknown error"}`,
|
|
1338
|
-
{
|
|
1339
|
-
endpoint: "prepareDepositWithPermitTxData",
|
|
1340
|
-
cause: depositAssetDecimalsResult.error
|
|
1341
|
-
}
|
|
1342
|
-
);
|
|
1343
|
-
}
|
|
1344
|
-
if (rateInQuoteResult.status === "failure") {
|
|
1345
|
-
throw new APIError(
|
|
1346
|
-
`Failed to get exchange rate: ${rateInQuoteResult.error?.message || "Unknown error"}`,
|
|
1347
|
-
{
|
|
1348
|
-
endpoint: "prepareDepositWithPermitTxData",
|
|
1349
|
-
cause: rateInQuoteResult.error
|
|
1350
|
-
}
|
|
1351
|
-
);
|
|
1352
|
-
}
|
|
1353
|
-
const onChainDecimals = depositAssetDecimalsResult.result;
|
|
1354
|
-
const depositAmountAsBigInt = parseUnits(depositAmount, onChainDecimals);
|
|
1355
|
-
const totalFee = await getDepositFeeForAmount(
|
|
1356
|
-
vault.vault.depositFeeModuleAddress,
|
|
1357
|
-
depositAssetAddress,
|
|
1358
|
-
depositAmountAsBigInt,
|
|
1359
|
-
normalizedChainId
|
|
1360
|
-
);
|
|
1361
|
-
if (totalFee >= depositAmountAsBigInt) {
|
|
1362
|
-
throw new APIError(
|
|
1363
|
-
"Deposit amount is entirely consumed by fees. Increase the deposit amount.",
|
|
1364
|
-
{ endpoint: "prepareDepositWithPermitTxData" }
|
|
1365
|
-
);
|
|
1366
|
-
}
|
|
1367
|
-
const depositAmountAfterFees = depositAmountAsBigInt - totalFee;
|
|
1368
|
-
await assertDepositWithinCap(
|
|
1369
|
-
vault,
|
|
1370
|
-
depositAmountAfterFees,
|
|
1371
|
-
depositAssetAddress,
|
|
1372
|
-
normalizedChainId,
|
|
1373
|
-
"prepareDepositWithPermitTxData"
|
|
1374
|
-
);
|
|
1375
|
-
const minimumMint = calculateMinimumMint(
|
|
1376
|
-
depositAmountAfterFees,
|
|
1377
|
-
rateInQuoteResult.result,
|
|
1378
|
-
onChainDecimals,
|
|
1379
|
-
slippage
|
|
1380
|
-
);
|
|
1381
|
-
const distributorCodeHex = stringToHex(distributorCode || "");
|
|
1382
|
-
const policyId = vault.enterpriseConfig?.predicatePolicyId;
|
|
1383
|
-
if (policyId === void 0) {
|
|
1384
|
-
return {
|
|
1385
|
-
depositType: DepositType.STANDARD,
|
|
1386
|
-
abi: DistributorCodeDepositorAbiV0,
|
|
1387
|
-
address: communityCodeDepositorAddress,
|
|
1388
|
-
functionName: "depositWithPermit",
|
|
1389
|
-
args: [
|
|
1390
|
-
depositAssetAddress,
|
|
1391
|
-
depositAmountAsBigInt,
|
|
1392
|
-
minimumMint,
|
|
1393
|
-
to,
|
|
1394
|
-
distributorCodeHex,
|
|
1395
|
-
deadline,
|
|
1396
|
-
v,
|
|
1397
|
-
r,
|
|
1398
|
-
s
|
|
1399
|
-
],
|
|
1400
|
-
chainId: normalizedChainId
|
|
1401
|
-
};
|
|
1402
|
-
}
|
|
1403
|
-
if (policyId === null) {
|
|
1404
|
-
const emptyAttestation = {
|
|
1405
|
-
uuid: "",
|
|
1406
|
-
expiration: 0n,
|
|
1407
|
-
attester: zeroAddress,
|
|
1408
|
-
signature: "0x"
|
|
1409
|
-
};
|
|
1410
|
-
return {
|
|
1411
|
-
depositType: DepositType.KYT,
|
|
1412
|
-
abi: DistributorCodeDepositorAbiV1,
|
|
1413
|
-
address: communityCodeDepositorAddress,
|
|
1414
|
-
functionName: "depositWithPermit",
|
|
1415
|
-
args: [
|
|
1416
|
-
depositAssetAddress,
|
|
1417
|
-
depositAmountAsBigInt,
|
|
1418
|
-
minimumMint,
|
|
1419
|
-
to,
|
|
1420
|
-
distributorCodeHex,
|
|
1421
|
-
emptyAttestation,
|
|
1422
|
-
deadline,
|
|
1423
|
-
v,
|
|
1424
|
-
r,
|
|
1425
|
-
s
|
|
1426
|
-
],
|
|
1427
|
-
chainId: normalizedChainId
|
|
1428
|
-
};
|
|
1429
|
-
}
|
|
1430
|
-
const attestation = await fetchKytAttestation({
|
|
1431
|
-
to: communityCodeDepositorAddress,
|
|
1432
|
-
from: to,
|
|
1433
|
-
chainId: normalizedChainId
|
|
1434
|
-
});
|
|
1435
|
-
return {
|
|
1436
|
-
depositType: DepositType.KYT,
|
|
1437
|
-
abi: DistributorCodeDepositorAbiV1,
|
|
1438
|
-
address: communityCodeDepositorAddress,
|
|
1439
|
-
functionName: "depositWithPermit",
|
|
1440
|
-
args: [
|
|
1441
|
-
depositAssetAddress,
|
|
1442
|
-
depositAmountAsBigInt,
|
|
1443
|
-
minimumMint,
|
|
1444
|
-
to,
|
|
1445
|
-
distributorCodeHex,
|
|
1446
|
-
attestation,
|
|
1447
|
-
deadline,
|
|
1448
|
-
v,
|
|
1449
|
-
r,
|
|
1450
|
-
s
|
|
1451
|
-
],
|
|
1452
|
-
chainId: normalizedChainId
|
|
1453
|
-
};
|
|
1454
|
-
} catch (error) {
|
|
1455
|
-
if (error instanceof APIError) {
|
|
1456
|
-
throw error;
|
|
1457
|
-
}
|
|
1458
|
-
throw new APIError(
|
|
1459
|
-
`Failed to prepare deposit with permit transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
1460
|
-
{
|
|
1461
|
-
endpoint: "prepareDepositWithPermitTxData",
|
|
1462
|
-
cause: error
|
|
1463
|
-
}
|
|
1464
|
-
);
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
// src/utils/wallet.ts
|
|
1469
|
-
async function isSmartContractWallet(address, chainId) {
|
|
1470
|
-
const client = await getClient(chainId);
|
|
1471
|
-
const code = await client.getCode({ address });
|
|
1472
|
-
return !!code && code !== "0x";
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
// src/vaults/deposit/index.ts
|
|
1476
|
-
var DepositAuthMethod = {
|
|
1477
|
-
PERMIT: "permit",
|
|
1478
|
-
APPROVAL: "approval",
|
|
1479
|
-
ALREADY_APPROVED: "already_approved"
|
|
1480
|
-
};
|
|
1481
|
-
function isPermitAuth(result) {
|
|
1482
|
-
return result.method === DepositAuthMethod.PERMIT;
|
|
1483
|
-
}
|
|
1484
|
-
function isApprovalAuth(result) {
|
|
1485
|
-
return result.method === DepositAuthMethod.APPROVAL;
|
|
1486
|
-
}
|
|
1487
|
-
function isAlreadyApprovedAuth(result) {
|
|
1488
|
-
return result.method === DepositAuthMethod.ALREADY_APPROVED;
|
|
1489
|
-
}
|
|
1490
|
-
async function prepareDepositAuthorization(params) {
|
|
1491
|
-
const {
|
|
1492
|
-
vaultName,
|
|
1493
|
-
depositAsset,
|
|
1494
|
-
depositAmount,
|
|
1495
|
-
to,
|
|
1496
|
-
chainId,
|
|
1497
|
-
deadline,
|
|
1498
|
-
forceMethod
|
|
1499
|
-
} = params;
|
|
1500
|
-
try {
|
|
1501
|
-
const normalizedChainId = toChainId(chainId);
|
|
1502
|
-
const vault = await resolveVault({
|
|
1503
|
-
vaultName,
|
|
1504
|
-
assetAddress: depositAsset,
|
|
1505
|
-
chainId: normalizedChainId,
|
|
1506
|
-
callerEndpoint: "prepareDepositAuthorization"
|
|
1507
|
-
});
|
|
1508
|
-
if (forceMethod === "approval") {
|
|
1509
|
-
const txData2 = await prepareApproveDepositTokenTxData({
|
|
1510
|
-
vaultName,
|
|
1511
|
-
depositAsset,
|
|
1512
|
-
approvalAmount: depositAmount,
|
|
1513
|
-
chainId: normalizedChainId
|
|
1514
|
-
});
|
|
1515
|
-
return {
|
|
1516
|
-
method: DepositAuthMethod.APPROVAL,
|
|
1517
|
-
txData: txData2
|
|
1518
|
-
};
|
|
1519
|
-
}
|
|
1520
|
-
if (forceMethod === "permit") {
|
|
1521
|
-
const tokenInfo2 = await isDepositSpendApproved({
|
|
1522
|
-
vaultName: vault.name,
|
|
1523
|
-
chainId: normalizedChainId,
|
|
1524
|
-
depositAssetAddress: depositAsset,
|
|
1525
|
-
recipientAddress: to
|
|
1526
|
-
});
|
|
1527
|
-
const permitData = await prepareDepositPermitSignature({
|
|
1528
|
-
vaultName,
|
|
1529
|
-
depositAsset,
|
|
1530
|
-
depositAmount,
|
|
1531
|
-
to,
|
|
1532
|
-
chainId: normalizedChainId,
|
|
1533
|
-
deadline,
|
|
1534
|
-
nonce: tokenInfo2.nonce ?? void 0,
|
|
1535
|
-
decimals: tokenInfo2.decimals,
|
|
1536
|
-
tokenName: tokenInfo2.tokenName,
|
|
1537
|
-
tokenVersion: tokenInfo2.tokenVersion
|
|
1538
|
-
});
|
|
1539
|
-
return {
|
|
1540
|
-
method: DepositAuthMethod.PERMIT,
|
|
1541
|
-
permitData
|
|
1542
|
-
};
|
|
1543
|
-
}
|
|
1544
|
-
const smartWallet = await isSmartContractWallet(to, normalizedChainId);
|
|
1545
|
-
if (smartWallet) {
|
|
1546
|
-
const txData2 = await prepareApproveDepositTokenTxData({
|
|
1547
|
-
vaultName,
|
|
1548
|
-
depositAsset,
|
|
1549
|
-
approvalAmount: depositAmount,
|
|
1550
|
-
chainId: normalizedChainId
|
|
1551
|
-
});
|
|
1552
|
-
return {
|
|
1553
|
-
method: DepositAuthMethod.APPROVAL,
|
|
1554
|
-
txData: txData2
|
|
1555
|
-
};
|
|
1556
|
-
}
|
|
1557
|
-
const tokenInfo = await isDepositSpendApproved({
|
|
1558
|
-
vaultName: vault.name,
|
|
1559
|
-
chainId: normalizedChainId,
|
|
1560
|
-
depositAssetAddress: depositAsset,
|
|
1561
|
-
recipientAddress: to
|
|
1562
|
-
});
|
|
1563
|
-
if (tokenInfo.supportsPermit) {
|
|
1564
|
-
const permitData = await prepareDepositPermitSignature({
|
|
1565
|
-
vaultName,
|
|
1566
|
-
depositAsset,
|
|
1567
|
-
depositAmount,
|
|
1568
|
-
to,
|
|
1569
|
-
chainId: normalizedChainId,
|
|
1570
|
-
deadline,
|
|
1571
|
-
nonce: tokenInfo.nonce ?? void 0,
|
|
1572
|
-
decimals: tokenInfo.decimals,
|
|
1573
|
-
tokenName: tokenInfo.tokenName,
|
|
1574
|
-
tokenVersion: tokenInfo.tokenVersion
|
|
1575
|
-
});
|
|
1576
|
-
return {
|
|
1577
|
-
method: DepositAuthMethod.PERMIT,
|
|
1578
|
-
permitData
|
|
1579
|
-
};
|
|
1580
|
-
}
|
|
1581
|
-
const depositAmountBigInt = parseUnits(depositAmount, tokenInfo.decimals);
|
|
1582
|
-
const currentAllowanceBigInt = BigInt(tokenInfo.allowanceAsBigInt);
|
|
1583
|
-
if (tokenInfo.isApproved && currentAllowanceBigInt >= depositAmountBigInt) {
|
|
1584
|
-
return {
|
|
1585
|
-
method: DepositAuthMethod.ALREADY_APPROVED,
|
|
1586
|
-
allowance: tokenInfo.allowance,
|
|
1587
|
-
allowanceAsBigInt: tokenInfo.allowanceAsBigInt
|
|
1588
|
-
};
|
|
1589
|
-
}
|
|
1590
|
-
const txData = await prepareApproveDepositTokenTxData({
|
|
1591
|
-
vaultName,
|
|
1592
|
-
depositAsset,
|
|
1593
|
-
approvalAmount: depositAmount,
|
|
1594
|
-
chainId: normalizedChainId
|
|
1595
|
-
});
|
|
1596
|
-
return {
|
|
1597
|
-
method: DepositAuthMethod.APPROVAL,
|
|
1598
|
-
txData
|
|
1599
|
-
};
|
|
1600
|
-
} catch (error) {
|
|
1601
|
-
if (error instanceof APIError) {
|
|
1602
|
-
throw error;
|
|
1603
|
-
}
|
|
1604
|
-
throw new APIError(
|
|
1605
|
-
`Failed to prepare deposit authorization: ${error instanceof Error ? error.message : String(error)}`,
|
|
1606
|
-
{
|
|
1607
|
-
endpoint: "prepareDepositAuthorization",
|
|
1608
|
-
cause: error
|
|
1609
|
-
}
|
|
1610
|
-
);
|
|
1611
|
-
}
|
|
1612
|
-
}
|
|
1613
|
-
async function prepareDeposit(params) {
|
|
1614
|
-
const {
|
|
1615
|
-
vaultName,
|
|
1616
|
-
depositAsset,
|
|
1617
|
-
depositAmount,
|
|
1618
|
-
to,
|
|
1619
|
-
chainId,
|
|
1620
|
-
slippage,
|
|
1621
|
-
distributorCode,
|
|
1622
|
-
signature,
|
|
1623
|
-
deadline,
|
|
1624
|
-
forceMethod
|
|
1625
|
-
} = params;
|
|
1626
|
-
try {
|
|
1627
|
-
if (forceMethod === "permit" && (!signature || deadline === void 0)) {
|
|
1628
|
-
throw new APIError(
|
|
1629
|
-
"Permit deposit requires both signature and deadline parameters when forceMethod is 'permit'",
|
|
1630
|
-
{ endpoint: "prepareDeposit" }
|
|
1631
|
-
);
|
|
1632
|
-
}
|
|
1633
|
-
const usePermit = forceMethod === "permit" || forceMethod !== "approval" && signature !== void 0 && deadline !== void 0;
|
|
1634
|
-
if (usePermit) {
|
|
1635
|
-
if (!signature || deadline === void 0) {
|
|
1636
|
-
throw new APIError(
|
|
1637
|
-
"Permit deposit requires both signature and deadline parameters",
|
|
1638
|
-
{ endpoint: "prepareDeposit" }
|
|
1639
|
-
);
|
|
1640
|
-
}
|
|
1641
|
-
const txData2 = await prepareDepositWithPermitTxData({
|
|
1642
|
-
vaultName,
|
|
1643
|
-
depositAsset,
|
|
1644
|
-
depositAmount,
|
|
1645
|
-
to,
|
|
1646
|
-
chainId,
|
|
1647
|
-
signature,
|
|
1648
|
-
deadline,
|
|
1649
|
-
slippage,
|
|
1650
|
-
distributorCode
|
|
1651
|
-
});
|
|
1652
|
-
return {
|
|
1653
|
-
method: DepositAuthMethod.PERMIT,
|
|
1654
|
-
txData: txData2
|
|
1655
|
-
};
|
|
1656
|
-
}
|
|
1657
|
-
const txData = await prepareDepositTxData({
|
|
1658
|
-
vaultName,
|
|
1659
|
-
depositAsset,
|
|
1660
|
-
depositAmount,
|
|
1661
|
-
to,
|
|
1662
|
-
chainId,
|
|
1663
|
-
slippage,
|
|
1664
|
-
distributorCode
|
|
1665
|
-
});
|
|
1666
|
-
return {
|
|
1667
|
-
method: DepositAuthMethod.APPROVAL,
|
|
1668
|
-
txData
|
|
1669
|
-
};
|
|
1670
|
-
} catch (error) {
|
|
1671
|
-
if (error instanceof APIError) {
|
|
1672
|
-
throw error;
|
|
1673
|
-
}
|
|
1674
|
-
throw new APIError(
|
|
1675
|
-
`Failed to prepare deposit: ${error instanceof Error ? error.message : String(error)}`,
|
|
1676
|
-
{
|
|
1677
|
-
endpoint: "prepareDeposit",
|
|
1678
|
-
cause: error
|
|
1679
|
-
}
|
|
1680
|
-
);
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
async function prepareApproveWithdrawOrderTxData({
|
|
1684
|
-
vaultName,
|
|
1685
|
-
wantAssetAddress,
|
|
1686
|
-
withdrawAmount,
|
|
1687
|
-
chainId,
|
|
1688
|
-
shareDecimals
|
|
1689
|
-
}) {
|
|
1690
|
-
try {
|
|
1691
|
-
const normalizedChainId = toChainId(chainId);
|
|
1692
|
-
const config = await resolveVault({
|
|
1693
|
-
vaultName,
|
|
1694
|
-
assetAddress: wantAssetAddress,
|
|
1695
|
-
chainId: normalizedChainId,
|
|
1696
|
-
callerEndpoint: "prepareApproveWithdrawOrderTxData"
|
|
1697
|
-
});
|
|
1698
|
-
if (!config.vault.boringVaultAddress) {
|
|
1699
|
-
throw new APIError(
|
|
1700
|
-
`BoringVault contract address not configured for vault ${config.id}`,
|
|
1701
|
-
{ endpoint: "prepareApproveWithdrawOrderTxData" }
|
|
1702
|
-
);
|
|
1703
|
-
}
|
|
1704
|
-
if (!config.vault.withdrawQueueAddress) {
|
|
1705
|
-
throw new APIError(
|
|
1706
|
-
`WithdrawQueue contract address not configured for vault ${config.id}`,
|
|
1707
|
-
{ endpoint: "prepareApproveWithdrawOrderTxData" }
|
|
1708
|
-
);
|
|
1709
|
-
}
|
|
1710
|
-
const boringVaultAddress = config.vault.boringVaultAddress;
|
|
1711
|
-
const withdrawQueueAddress = config.vault.withdrawQueueAddress;
|
|
1712
|
-
const decimals = shareDecimals ?? await getErc20Decimals({
|
|
1713
|
-
tokenAddress: boringVaultAddress,
|
|
1714
|
-
chainId: normalizedChainId
|
|
1715
|
-
});
|
|
1716
|
-
const withdrawAmountAsBigInt = withdrawAmount ? parseUnits(withdrawAmount, decimals) : DEFAULT_APPROVAL_AMOUNT;
|
|
1717
|
-
return {
|
|
1718
|
-
abi: BoringVaultAbi,
|
|
1719
|
-
address: boringVaultAddress,
|
|
1720
|
-
functionName: "approve",
|
|
1721
|
-
args: [withdrawQueueAddress, withdrawAmountAsBigInt]
|
|
1722
|
-
};
|
|
1723
|
-
} catch (error) {
|
|
1724
|
-
if (error instanceof APIError) {
|
|
1725
|
-
throw error;
|
|
1726
|
-
}
|
|
1727
|
-
throw new APIError(
|
|
1728
|
-
`Failed to prepare approval transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
1729
|
-
{
|
|
1730
|
-
endpoint: "prepareApproveWithdrawOrderTxData",
|
|
1731
|
-
cause: error
|
|
1732
|
-
}
|
|
1733
|
-
);
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
|
|
1737
|
-
// src/vaults/withdraw/cancel-withdraw.ts
|
|
1738
|
-
var prepareCancelWithdrawOrderTxData = async ({
|
|
1739
|
-
vaultName,
|
|
1740
|
-
wantAsset,
|
|
1741
|
-
chainId,
|
|
1742
|
-
orderIndex
|
|
1743
|
-
}) => {
|
|
1744
|
-
try {
|
|
1745
|
-
const normalizedChainId = toChainId(chainId);
|
|
1746
|
-
const config = await resolveVault({
|
|
1747
|
-
vaultName,
|
|
1748
|
-
assetAddress: wantAsset,
|
|
1749
|
-
chainId: normalizedChainId,
|
|
1750
|
-
callerEndpoint: "prepareCancelWithdrawOrderTxData"
|
|
1751
|
-
});
|
|
1752
|
-
if (config.chainId !== normalizedChainId) {
|
|
1753
|
-
throw new APIError(
|
|
1754
|
-
`Vault chain mismatch: vault is on chain ${config.chainId}, requested chain ${normalizedChainId}`,
|
|
1755
|
-
{ endpoint: "prepareCancelWithdrawOrderTxData" }
|
|
1756
|
-
);
|
|
1757
|
-
}
|
|
1758
|
-
if (!config.vault.withdrawQueueAddress) {
|
|
1759
|
-
throw new APIError(
|
|
1760
|
-
`WithdrawQueue contract address not configured for vault ${config.id}`,
|
|
1761
|
-
{ endpoint: "prepareCancelWithdrawOrderTxData" }
|
|
1762
|
-
);
|
|
1763
|
-
}
|
|
1764
|
-
return {
|
|
1765
|
-
abi: WithdrawQueueAbi,
|
|
1766
|
-
address: config.vault.withdrawQueueAddress,
|
|
1767
|
-
functionName: "cancelOrder",
|
|
1768
|
-
args: [orderIndex],
|
|
1769
|
-
chainId: normalizedChainId
|
|
1770
|
-
};
|
|
1771
|
-
} catch (error) {
|
|
1772
|
-
if (error instanceof APIError) {
|
|
1773
|
-
throw error;
|
|
1774
|
-
}
|
|
1775
|
-
throw new APIError(
|
|
1776
|
-
`Failed to prepare cancel order transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
1777
|
-
{
|
|
1778
|
-
endpoint: "prepareCancelWithdrawOrderTxData",
|
|
1779
|
-
cause: error
|
|
1780
|
-
}
|
|
1781
|
-
);
|
|
1782
|
-
}
|
|
1783
|
-
};
|
|
1784
|
-
var ApprovalMethod = {
|
|
1785
|
-
/** Standard ERC20 approve (user has pre-approved via approve()) */
|
|
1786
|
-
EIP20_APPROVE: 0};
|
|
1787
|
-
var EMPTY_SIGNATURE_PARAMS = {
|
|
1788
|
-
approvalMethod: ApprovalMethod.EIP20_APPROVE,
|
|
1789
|
-
approvalV: 0,
|
|
1790
|
-
approvalR: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
1791
|
-
approvalS: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
1792
|
-
submitWithSignature: false,
|
|
1793
|
-
deadline: 0n,
|
|
1794
|
-
eip2612Signature: "0x"
|
|
1795
|
-
};
|
|
1796
|
-
var prepareWithdrawOrderTxData = async ({
|
|
1797
|
-
vaultName,
|
|
1798
|
-
wantAsset,
|
|
1799
|
-
userAddress,
|
|
1800
|
-
chainId,
|
|
1801
|
-
amountOffer
|
|
1802
|
-
}) => {
|
|
1803
|
-
try {
|
|
1804
|
-
const normalizedChainId = toChainId(chainId);
|
|
1805
|
-
const config = await resolveVault({
|
|
1806
|
-
vaultName,
|
|
1807
|
-
assetAddress: wantAsset,
|
|
1808
|
-
chainId: normalizedChainId,
|
|
1809
|
-
callerEndpoint: "prepareWithdrawOrderTxData"
|
|
1810
|
-
});
|
|
1811
|
-
if (config.chainId !== normalizedChainId) {
|
|
1812
|
-
throw new APIError(
|
|
1813
|
-
`Vault chain mismatch: vault is on chain ${config.chainId}, requested chain ${normalizedChainId}`,
|
|
1814
|
-
{ endpoint: "prepareWithdrawOrderTxData" }
|
|
1815
|
-
);
|
|
1816
|
-
}
|
|
1817
|
-
if (!config.vault.withdrawQueueAddress) {
|
|
1818
|
-
throw new APIError(
|
|
1819
|
-
`WithdrawQueue contract address not configured for vault ${config.id}`,
|
|
1820
|
-
{ endpoint: "prepareWithdrawOrderTxData" }
|
|
1821
|
-
);
|
|
1822
|
-
}
|
|
1823
|
-
if (!config.vault.boringVaultAddress) {
|
|
1824
|
-
throw new APIError(
|
|
1825
|
-
`BoringVault contract address not configured for vault ${config.id}`,
|
|
1826
|
-
{ endpoint: "prepareWithdrawOrderTxData" }
|
|
1827
|
-
);
|
|
1828
|
-
}
|
|
1829
|
-
const sharesDecimals = await getErc20Decimals({
|
|
1830
|
-
tokenAddress: config.vault.boringVaultAddress,
|
|
1831
|
-
chainId: normalizedChainId
|
|
1832
|
-
});
|
|
1833
|
-
const formattedAmountOffer = parseUnits(amountOffer, sharesDecimals);
|
|
1834
|
-
return {
|
|
1835
|
-
abi: WithdrawQueueAbi,
|
|
1836
|
-
address: config.vault.withdrawQueueAddress,
|
|
1837
|
-
functionName: "submitOrder",
|
|
1838
|
-
args: [
|
|
1839
|
-
{
|
|
1840
|
-
amountOffer: formattedAmountOffer,
|
|
1841
|
-
wantAsset,
|
|
1842
|
-
intendedDepositor: userAddress,
|
|
1843
|
-
receiver: userAddress,
|
|
1844
|
-
refundReceiver: userAddress,
|
|
1845
|
-
signatureParams: EMPTY_SIGNATURE_PARAMS
|
|
1846
|
-
}
|
|
1847
|
-
],
|
|
1848
|
-
chainId: normalizedChainId
|
|
1849
|
-
};
|
|
1850
|
-
} catch (error) {
|
|
1851
|
-
if (error instanceof APIError) {
|
|
1852
|
-
throw error;
|
|
1853
|
-
}
|
|
1854
|
-
throw new APIError(
|
|
1855
|
-
`Failed to prepare withdraw order transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
1856
|
-
{
|
|
1857
|
-
endpoint: "prepareWithdrawOrderTxData",
|
|
1858
|
-
cause: error
|
|
1859
|
-
}
|
|
1860
|
-
);
|
|
1861
|
-
}
|
|
1862
|
-
};
|
|
1863
|
-
var prepareAtomicWithdrawOrderTxData = async ({
|
|
1864
|
-
vaultName,
|
|
1865
|
-
wantAsset,
|
|
1866
|
-
userAddress,
|
|
1867
|
-
chainId,
|
|
1868
|
-
amountOffer
|
|
1869
|
-
}) => {
|
|
1870
|
-
try {
|
|
1871
|
-
const normalizedChainId = toChainId(chainId);
|
|
1872
|
-
const config = await resolveVault({
|
|
1873
|
-
vaultName,
|
|
1874
|
-
assetAddress: wantAsset,
|
|
1875
|
-
chainId: normalizedChainId,
|
|
1876
|
-
callerEndpoint: "prepareAtomicWithdrawOrderTxData"
|
|
1877
|
-
});
|
|
1878
|
-
if (config.chainId !== normalizedChainId) {
|
|
1879
|
-
throw new InvalidChainIdError(
|
|
1880
|
-
`Vault chain mismatch: vault is on chain ${config.chainId}, requested chain ${normalizedChainId}`,
|
|
1881
|
-
{
|
|
1882
|
-
vaultId: config.id,
|
|
1883
|
-
vaultChainId: config.chainId,
|
|
1884
|
-
requestedChainId: normalizedChainId
|
|
1885
|
-
}
|
|
1886
|
-
);
|
|
1887
|
-
}
|
|
1888
|
-
if (!config.vault.withdrawQueueAddress) {
|
|
1889
|
-
throw new TransactionDataError(
|
|
1890
|
-
`WithdrawQueue contract address not configured for vault ${config.id}`,
|
|
1891
|
-
{ vaultId: config.id, field: "withdrawQueueAddress" }
|
|
1892
|
-
);
|
|
1893
|
-
}
|
|
1894
|
-
if (!config.vault.boringVaultAddress) {
|
|
1895
|
-
throw new TransactionDataError(
|
|
1896
|
-
`BoringVault contract address not configured for vault ${config.id}`,
|
|
1897
|
-
{ vaultId: config.id, field: "boringVaultAddress" }
|
|
1898
|
-
);
|
|
1899
|
-
}
|
|
1900
|
-
const sharesDecimals = await getErc20Decimals({
|
|
1901
|
-
tokenAddress: config.vault.boringVaultAddress,
|
|
1902
|
-
chainId: normalizedChainId
|
|
1903
|
-
});
|
|
1904
|
-
const formattedAmountOffer = parseUnits(amountOffer, sharesDecimals);
|
|
1905
|
-
return {
|
|
1906
|
-
abi: WithdrawQueueAbi,
|
|
1907
|
-
address: config.vault.withdrawQueueAddress,
|
|
1908
|
-
functionName: "submitOrderAndProcessAll",
|
|
1909
|
-
args: [
|
|
1910
|
-
{
|
|
1911
|
-
amountOffer: formattedAmountOffer,
|
|
1912
|
-
wantAsset,
|
|
1913
|
-
intendedDepositor: userAddress,
|
|
1914
|
-
receiver: userAddress,
|
|
1915
|
-
refundReceiver: userAddress,
|
|
1916
|
-
signatureParams: EMPTY_SIGNATURE_PARAMS
|
|
1917
|
-
}
|
|
1918
|
-
],
|
|
1919
|
-
chainId: normalizedChainId
|
|
1920
|
-
};
|
|
1921
|
-
} catch (error) {
|
|
1922
|
-
if (error instanceof WithdrawError) {
|
|
1923
|
-
throw error;
|
|
1924
|
-
}
|
|
1925
|
-
throw new TransactionDataError(
|
|
1926
|
-
`Failed to prepare atomic withdraw order transaction: ${error instanceof Error ? error.message : String(error)}`,
|
|
1927
|
-
{
|
|
1928
|
-
endpoint: "prepareAtomicWithdrawOrderTxData",
|
|
1929
|
-
cause: error
|
|
1930
|
-
}
|
|
1931
|
-
);
|
|
1932
|
-
}
|
|
1933
|
-
};
|
|
1934
|
-
|
|
1935
|
-
// src/vaults/withdraw/index.ts
|
|
1936
|
-
var WithdrawAuthMethod = {
|
|
1937
|
-
APPROVAL: "approval",
|
|
1938
|
-
ALREADY_APPROVED: "already_approved"
|
|
1939
|
-
};
|
|
1940
|
-
function isWithdrawApprovalAuth(result) {
|
|
1941
|
-
return result.method === WithdrawAuthMethod.APPROVAL;
|
|
1942
|
-
}
|
|
1943
|
-
function isWithdrawAlreadyApprovedAuth(result) {
|
|
1944
|
-
return result.method === WithdrawAuthMethod.ALREADY_APPROVED;
|
|
1945
|
-
}
|
|
1946
|
-
async function prepareWithdrawal(params) {
|
|
1947
|
-
const { vaultName, wantAsset, withdrawAmount, userAddress, chainId } = params;
|
|
1948
|
-
try {
|
|
1949
|
-
const normalizedChainId = toChainId(chainId);
|
|
1950
|
-
const vault = await resolveVault({
|
|
1951
|
-
vaultName,
|
|
1952
|
-
assetAddress: wantAsset,
|
|
1953
|
-
chainId: normalizedChainId,
|
|
1954
|
-
callerEndpoint: "prepareWithdrawal"
|
|
1955
|
-
});
|
|
1956
|
-
const builderParams = {
|
|
1957
|
-
vaultName,
|
|
1958
|
-
wantAsset,
|
|
1959
|
-
userAddress,
|
|
1960
|
-
chainId,
|
|
1961
|
-
amountOffer: withdrawAmount
|
|
1962
|
-
};
|
|
1963
|
-
return vault.atomicWithdrawal ? await prepareAtomicWithdrawOrderTxData(builderParams) : await prepareWithdrawOrderTxData(builderParams);
|
|
1964
|
-
} catch (error) {
|
|
1965
|
-
if (error instanceof APIError) {
|
|
1966
|
-
throw error;
|
|
1967
|
-
}
|
|
1968
|
-
throw new APIError(
|
|
1969
|
-
`Failed to prepare withdrawal: ${error instanceof Error ? error.message : String(error)}`,
|
|
1970
|
-
{
|
|
1971
|
-
endpoint: "prepareWithdrawal",
|
|
1972
|
-
cause: error
|
|
1973
|
-
}
|
|
1974
|
-
);
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
async function prepareWithdrawalAuthorization(params) {
|
|
1978
|
-
const {
|
|
1979
|
-
vaultName,
|
|
1980
|
-
wantAsset,
|
|
1981
|
-
withdrawAmount,
|
|
1982
|
-
userAddress,
|
|
1983
|
-
chainId,
|
|
1984
|
-
forceMethod
|
|
1985
|
-
} = params;
|
|
1986
|
-
try {
|
|
1987
|
-
const normalizedChainId = toChainId(chainId);
|
|
1988
|
-
const vault = await resolveVault({
|
|
1989
|
-
vaultName,
|
|
1990
|
-
assetAddress: wantAsset,
|
|
1991
|
-
chainId: normalizedChainId,
|
|
1992
|
-
callerEndpoint: "prepareWithdrawalAuthorization"
|
|
1993
|
-
});
|
|
1994
|
-
if (forceMethod === "approval") {
|
|
1995
|
-
const txData2 = await prepareApproveWithdrawOrderTxData({
|
|
1996
|
-
vaultName,
|
|
1997
|
-
wantAssetAddress: wantAsset,
|
|
1998
|
-
withdrawAmount,
|
|
1999
|
-
chainId: normalizedChainId
|
|
2000
|
-
});
|
|
2001
|
-
return {
|
|
2002
|
-
method: WithdrawAuthMethod.APPROVAL,
|
|
2003
|
-
txData: txData2
|
|
2004
|
-
};
|
|
2005
|
-
}
|
|
2006
|
-
if (forceMethod !== "allowance_check") {
|
|
2007
|
-
const smartWallet = await isSmartContractWallet(
|
|
2008
|
-
userAddress,
|
|
2009
|
-
normalizedChainId
|
|
2010
|
-
);
|
|
2011
|
-
if (smartWallet) {
|
|
2012
|
-
const txData2 = await prepareApproveWithdrawOrderTxData({
|
|
2013
|
-
vaultName,
|
|
2014
|
-
wantAssetAddress: wantAsset,
|
|
2015
|
-
withdrawAmount,
|
|
2016
|
-
chainId: normalizedChainId
|
|
2017
|
-
});
|
|
2018
|
-
return {
|
|
2019
|
-
method: WithdrawAuthMethod.APPROVAL,
|
|
2020
|
-
txData: txData2
|
|
2021
|
-
};
|
|
2022
|
-
}
|
|
2023
|
-
}
|
|
2024
|
-
const approvalInfo = await isWithdrawalSpendApproved({
|
|
2025
|
-
vaultName: vault.name,
|
|
2026
|
-
chainId: normalizedChainId,
|
|
2027
|
-
wantAssetAddress: wantAsset,
|
|
2028
|
-
recipientAddress: userAddress
|
|
2029
|
-
});
|
|
2030
|
-
if (approvalInfo.error) {
|
|
2031
|
-
throw new APIError(
|
|
2032
|
-
`Failed to check withdrawal approval: ${approvalInfo.error}`,
|
|
2033
|
-
{ endpoint: "prepareWithdrawalAuthorization" }
|
|
2034
|
-
);
|
|
2035
|
-
}
|
|
2036
|
-
const decimals = typeof approvalInfo.decimals === "string" ? Number(approvalInfo.decimals) : approvalInfo.decimals;
|
|
2037
|
-
const withdrawAmountBigInt = parseUnits(withdrawAmount, decimals);
|
|
2038
|
-
const currentAllowanceBigInt = BigInt(approvalInfo.allowanceAsBigInt);
|
|
2039
|
-
if (approvalInfo.isApproved && currentAllowanceBigInt >= withdrawAmountBigInt) {
|
|
2040
|
-
return {
|
|
2041
|
-
method: WithdrawAuthMethod.ALREADY_APPROVED,
|
|
2042
|
-
allowance: approvalInfo.allowance,
|
|
2043
|
-
allowanceAsBigInt: approvalInfo.allowanceAsBigInt
|
|
2044
|
-
};
|
|
2045
|
-
}
|
|
2046
|
-
const txData = await prepareApproveWithdrawOrderTxData({
|
|
2047
|
-
vaultName,
|
|
2048
|
-
wantAssetAddress: wantAsset,
|
|
2049
|
-
withdrawAmount,
|
|
2050
|
-
chainId: normalizedChainId,
|
|
2051
|
-
shareDecimals: decimals
|
|
2052
|
-
});
|
|
2053
|
-
return {
|
|
2054
|
-
method: WithdrawAuthMethod.APPROVAL,
|
|
2055
|
-
txData
|
|
2056
|
-
};
|
|
2057
|
-
} catch (error) {
|
|
2058
|
-
if (error instanceof APIError) {
|
|
2059
|
-
throw error;
|
|
2060
|
-
}
|
|
2061
|
-
throw new APIError(
|
|
2062
|
-
`Failed to prepare withdrawal authorization: ${error instanceof Error ? error.message : String(error)}`,
|
|
2063
|
-
{
|
|
2064
|
-
endpoint: "prepareWithdrawalAuthorization",
|
|
2065
|
-
cause: error
|
|
2066
|
-
}
|
|
2067
|
-
);
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
|
|
2071
|
-
export { DepositAuthMethod, DepositType, PERMIT_TYPES, WithdrawAuthMethod, fetchKytAttestation, isAlreadyApprovedAuth, isApprovalAuth, isDepositSpendApproved, isKytDeposit, isPermitAuth, isStandardDeposit, isWithdrawAlreadyApprovedAuth, isWithdrawApprovalAuth, isWithdrawalSpendApproved, parsePermitSignature, prepareApproveDepositTokenTxData, prepareApproveWithdrawOrderTxData, prepareCancelWithdrawOrderTxData, prepareDeposit, prepareDepositAuthorization, prepareDepositPermitSignature, prepareDepositTxData, prepareDepositWithPermitTxData, prepareWithdrawOrderTxData, prepareWithdrawal, prepareWithdrawalAuthorization, toEthSignTypedDataV4 };
|
|
2072
|
-
//# sourceMappingURL=chunk-LMNADWTH.mjs.map
|
|
2073
|
-
//# sourceMappingURL=chunk-LMNADWTH.mjs.map
|