@cowprotocol/sdk-flash-loans 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/README.md +448 -0
- package/dist/index.d.mts +269 -0
- package/dist/index.d.ts +269 -0
- package/dist/index.js +663 -0
- package/dist/index.mjs +629 -0
- package/package.json +52 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
AAVE_ADAPTER_FACTORY: () => AAVE_ADAPTER_FACTORY,
|
|
24
|
+
AAVE_COLLATERAL_SWAP_ADAPTER_HOOK: () => AAVE_COLLATERAL_SWAP_ADAPTER_HOOK,
|
|
25
|
+
AAVE_POOL_ADDRESS: () => AAVE_POOL_ADDRESS,
|
|
26
|
+
ADAPTER_DOMAIN_NAME: () => ADAPTER_DOMAIN_NAME,
|
|
27
|
+
ADAPTER_DOMAIN_VERSION: () => ADAPTER_DOMAIN_VERSION,
|
|
28
|
+
ADAPTER_SIGNATURE_TYPES: () => ADAPTER_SIGNATURE_TYPES,
|
|
29
|
+
AaveCollateralSwapSdk: () => AaveCollateralSwapSdk,
|
|
30
|
+
DEFAULT_HOOK_GAS_LIMIT: () => DEFAULT_HOOK_GAS_LIMIT,
|
|
31
|
+
DEFAULT_VALIDITY: () => DEFAULT_VALIDITY,
|
|
32
|
+
EMPTY_PERMIT: () => EMPTY_PERMIT,
|
|
33
|
+
GAS_ESTIMATION_ADDITION_PERCENT: () => GAS_ESTIMATION_ADDITION_PERCENT,
|
|
34
|
+
HASH_ZERO: () => HASH_ZERO,
|
|
35
|
+
PERCENT_SCALE: () => PERCENT_SCALE
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(src_exports);
|
|
38
|
+
|
|
39
|
+
// src/aave/AaveCollateralSwapSdk.ts
|
|
40
|
+
var import_sdk_common = require("@cowprotocol/sdk-common");
|
|
41
|
+
var import_sdk_order_signing = require("@cowprotocol/sdk-order-signing");
|
|
42
|
+
var import_sdk_order_book = require("@cowprotocol/sdk-order-book");
|
|
43
|
+
|
|
44
|
+
// src/aave/const.ts
|
|
45
|
+
var import_sdk_config = require("@cowprotocol/sdk-config");
|
|
46
|
+
var HASH_ZERO = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
47
|
+
var AAVE_POOL_ADDRESS = (0, import_sdk_config.mapAddressToSupportedNetworks)("0xb50201558B00496A145fE76f7424749556E326D8");
|
|
48
|
+
var AAVE_ADAPTER_FACTORY = {
|
|
49
|
+
...(0, import_sdk_config.mapAddressToSupportedNetworks)("0x1186B5ad42E3e6d6c6901FC53b4A367540E6EcFE"),
|
|
50
|
+
[import_sdk_config.SupportedChainId.GNOSIS_CHAIN]: "0x889ee28C0a8a41a312546A8eeD77b4b097C84016"
|
|
51
|
+
};
|
|
52
|
+
var AAVE_COLLATERAL_SWAP_ADAPTER_HOOK = {
|
|
53
|
+
...(0, import_sdk_config.mapAddressToSupportedNetworks)("0xe80eE1e73f120b1106179Ae3D582CA4Fd768d517"),
|
|
54
|
+
[import_sdk_config.SupportedChainId.GNOSIS_CHAIN]: "0x0aeC794e544B81D96149a4C8C1cC57c6F31A978A"
|
|
55
|
+
};
|
|
56
|
+
var DEFAULT_HOOK_GAS_LIMIT = {
|
|
57
|
+
pre: 300000n,
|
|
58
|
+
post: 600000n
|
|
59
|
+
};
|
|
60
|
+
var PERCENT_SCALE = 1e4;
|
|
61
|
+
var DEFAULT_VALIDITY = 10 * 60;
|
|
62
|
+
var GAS_ESTIMATION_ADDITION_PERCENT = 10;
|
|
63
|
+
var ADAPTER_DOMAIN_NAME = "AaveAdapterFactory";
|
|
64
|
+
var ADAPTER_DOMAIN_VERSION = "1";
|
|
65
|
+
var ADAPTER_SIGNATURE_TYPES = {
|
|
66
|
+
AdapterOrderSig: [
|
|
67
|
+
{ name: "instance", type: "address" },
|
|
68
|
+
{ name: "sellToken", type: "address" },
|
|
69
|
+
{ name: "buyToken", type: "address" },
|
|
70
|
+
{ name: "sellAmount", type: "uint256" },
|
|
71
|
+
{ name: "buyAmount", type: "uint256" },
|
|
72
|
+
{ name: "kind", type: "bytes32" },
|
|
73
|
+
{ name: "validTo", type: "uint32" },
|
|
74
|
+
{ name: "appData", type: "bytes32" }
|
|
75
|
+
]
|
|
76
|
+
};
|
|
77
|
+
var EMPTY_PERMIT = {
|
|
78
|
+
amount: "0",
|
|
79
|
+
deadline: 0,
|
|
80
|
+
v: 0,
|
|
81
|
+
r: HASH_ZERO,
|
|
82
|
+
s: HASH_ZERO
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/aave/abi/AaveAdapterFactory.ts
|
|
86
|
+
var aaveAdapterFactoryAbi = [
|
|
87
|
+
{
|
|
88
|
+
type: "function",
|
|
89
|
+
name: "getInstanceDeterministicAddress",
|
|
90
|
+
inputs: [
|
|
91
|
+
{
|
|
92
|
+
name: "adapterImplementation",
|
|
93
|
+
type: "address",
|
|
94
|
+
internalType: "address"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "hookData",
|
|
98
|
+
type: "tuple",
|
|
99
|
+
internalType: "struct DataTypes.HookOrderData",
|
|
100
|
+
components: [
|
|
101
|
+
{
|
|
102
|
+
name: "owner",
|
|
103
|
+
type: "address",
|
|
104
|
+
internalType: "address"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "receiver",
|
|
108
|
+
type: "address",
|
|
109
|
+
internalType: "address"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "sellToken",
|
|
113
|
+
type: "address",
|
|
114
|
+
internalType: "address"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "buyToken",
|
|
118
|
+
type: "address",
|
|
119
|
+
internalType: "address"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "sellAmount",
|
|
123
|
+
type: "uint256",
|
|
124
|
+
internalType: "uint256"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "buyAmount",
|
|
128
|
+
type: "uint256",
|
|
129
|
+
internalType: "uint256"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "kind",
|
|
133
|
+
type: "bytes32",
|
|
134
|
+
internalType: "bytes32"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "validTo",
|
|
138
|
+
type: "uint256",
|
|
139
|
+
internalType: "uint256"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "flashLoanAmount",
|
|
143
|
+
type: "uint256",
|
|
144
|
+
internalType: "uint256"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "flashLoanFeeAmount",
|
|
148
|
+
type: "uint256",
|
|
149
|
+
internalType: "uint256"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "hookSellTokenAmount",
|
|
153
|
+
type: "uint256",
|
|
154
|
+
internalType: "uint256"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "hookBuyTokenAmount",
|
|
158
|
+
type: "uint256",
|
|
159
|
+
internalType: "uint256"
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
],
|
|
164
|
+
outputs: [
|
|
165
|
+
{
|
|
166
|
+
name: "",
|
|
167
|
+
type: "address",
|
|
168
|
+
internalType: "address"
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
stateMutability: "view"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: "function",
|
|
175
|
+
name: "deployAndTransferFlashLoan",
|
|
176
|
+
inputs: [
|
|
177
|
+
{
|
|
178
|
+
name: "adapterImplementation",
|
|
179
|
+
type: "address",
|
|
180
|
+
internalType: "address"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "hookData",
|
|
184
|
+
type: "tuple",
|
|
185
|
+
internalType: "struct DataTypes.HookOrderData",
|
|
186
|
+
components: [
|
|
187
|
+
{
|
|
188
|
+
name: "owner",
|
|
189
|
+
type: "address",
|
|
190
|
+
internalType: "address"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: "receiver",
|
|
194
|
+
type: "address",
|
|
195
|
+
internalType: "address"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: "sellToken",
|
|
199
|
+
type: "address",
|
|
200
|
+
internalType: "address"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: "buyToken",
|
|
204
|
+
type: "address",
|
|
205
|
+
internalType: "address"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: "sellAmount",
|
|
209
|
+
type: "uint256",
|
|
210
|
+
internalType: "uint256"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
name: "buyAmount",
|
|
214
|
+
type: "uint256",
|
|
215
|
+
internalType: "uint256"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
name: "kind",
|
|
219
|
+
type: "bytes32",
|
|
220
|
+
internalType: "bytes32"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "validTo",
|
|
224
|
+
type: "uint256",
|
|
225
|
+
internalType: "uint256"
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "flashLoanAmount",
|
|
229
|
+
type: "uint256",
|
|
230
|
+
internalType: "uint256"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: "flashLoanFeeAmount",
|
|
234
|
+
type: "uint256",
|
|
235
|
+
internalType: "uint256"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: "hookSellTokenAmount",
|
|
239
|
+
type: "uint256",
|
|
240
|
+
internalType: "uint256"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: "hookBuyTokenAmount",
|
|
244
|
+
type: "uint256",
|
|
245
|
+
internalType: "uint256"
|
|
246
|
+
}
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
],
|
|
250
|
+
outputs: [],
|
|
251
|
+
stateMutability: "nonpayable"
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
inputs: [],
|
|
255
|
+
name: "DOMAIN_SEPARATOR",
|
|
256
|
+
outputs: [
|
|
257
|
+
{
|
|
258
|
+
internalType: "bytes32",
|
|
259
|
+
name: "",
|
|
260
|
+
type: "bytes32"
|
|
261
|
+
}
|
|
262
|
+
],
|
|
263
|
+
stateMutability: "view",
|
|
264
|
+
type: "function"
|
|
265
|
+
}
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
// src/aave/abi/CollateralSwapAdapterHook.ts
|
|
269
|
+
var collateralSwapAdapterHookAbi = [
|
|
270
|
+
{
|
|
271
|
+
type: "function",
|
|
272
|
+
name: "collateralSwapWithFlashLoan",
|
|
273
|
+
inputs: [
|
|
274
|
+
{
|
|
275
|
+
name: "erc20Permit",
|
|
276
|
+
type: "tuple",
|
|
277
|
+
internalType: "struct DataTypes.Permit",
|
|
278
|
+
components: [
|
|
279
|
+
{
|
|
280
|
+
name: "amount",
|
|
281
|
+
type: "uint256",
|
|
282
|
+
internalType: "uint256"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
name: "deadline",
|
|
286
|
+
type: "uint256",
|
|
287
|
+
internalType: "uint256"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: "v",
|
|
291
|
+
type: "uint8",
|
|
292
|
+
internalType: "uint8"
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: "r",
|
|
296
|
+
type: "bytes32",
|
|
297
|
+
internalType: "bytes32"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: "s",
|
|
301
|
+
type: "bytes32",
|
|
302
|
+
internalType: "bytes32"
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
],
|
|
307
|
+
outputs: [],
|
|
308
|
+
stateMutability: "nonpayable"
|
|
309
|
+
}
|
|
310
|
+
];
|
|
311
|
+
|
|
312
|
+
// src/aave/AaveCollateralSwapSdk.ts
|
|
313
|
+
var AaveCollateralSwapSdk = class {
|
|
314
|
+
/**
|
|
315
|
+
* Executes a collateral swap using Aave flash loans.
|
|
316
|
+
*
|
|
317
|
+
* @remarks This method orchestrates a complex flash loan operation:
|
|
318
|
+
* 1. Borrows the sell token via Aave flash loan
|
|
319
|
+
* 2. Uses CoW hooks to deploy adapter contracts and manage the swap
|
|
320
|
+
* 3. Executes a CoW Protocol swap to the buy token
|
|
321
|
+
* 4. Repays the flash loan with fees
|
|
322
|
+
*
|
|
323
|
+
* The order is signed using EIP-1271 with a deterministically generated
|
|
324
|
+
* smart contract address as the signer.
|
|
325
|
+
*
|
|
326
|
+
* @param {CollateralSwapParams} params - Configuration for the collateral swap.
|
|
327
|
+
* @param {TradingSdk} tradingSdk - @cowprotocol/sdk-trading.
|
|
328
|
+
* @returns {Promise<OrderPostingResult>} The result of posting the order to CoW Protocol.
|
|
329
|
+
*
|
|
330
|
+
* @throws Will throw if the quote fails, contract deployment fails, or gas estimation fails.
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
async collateralSwap(params, tradingSdk) {
|
|
334
|
+
const quoteParams = await this.getSwapQuoteParams(params);
|
|
335
|
+
const {
|
|
336
|
+
collateralToken,
|
|
337
|
+
tradeParameters: { amount },
|
|
338
|
+
settings
|
|
339
|
+
} = params;
|
|
340
|
+
const sellAmount = BigInt(amount);
|
|
341
|
+
const quoteAndPost = await tradingSdk.getQuote(quoteParams);
|
|
342
|
+
const { quoteResults, postSwapOrderFromQuote } = quoteAndPost;
|
|
343
|
+
const { swapSettings, instanceAddress } = await this.getOrderPostingSettings(quoteParams, {
|
|
344
|
+
sellAmount,
|
|
345
|
+
buyAmount: quoteResults.amountsAndCosts.afterSlippage.buyAmount,
|
|
346
|
+
orderToSign: quoteResults.orderToSign,
|
|
347
|
+
collateralPermit: settings?.collateralPermit
|
|
348
|
+
});
|
|
349
|
+
const collateralParams = {
|
|
350
|
+
instanceAddress,
|
|
351
|
+
trader: quoteParams.owner,
|
|
352
|
+
collateralToken,
|
|
353
|
+
amount: sellAmount
|
|
354
|
+
};
|
|
355
|
+
if (!settings?.preventApproval && !settings?.collateralPermit) {
|
|
356
|
+
await this.approveCollateralIfNeeded(collateralParams, sellAmount);
|
|
357
|
+
}
|
|
358
|
+
return postSwapOrderFromQuote(swapSettings);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Prepares quote parameters for the collateral swap operation.
|
|
362
|
+
*
|
|
363
|
+
* @remarks This method calculates the adjusted swap amount after deducting the flash loan fee,
|
|
364
|
+
* resolves the trader address, and computes the order validity timestamp. The flash
|
|
365
|
+
* loan fee is deducted from the sell amount before requesting a quote to ensure the
|
|
366
|
+
* final swap amount covers both the desired output and the flash loan repayment.
|
|
367
|
+
*
|
|
368
|
+
* @param {CollateralSwapParams} params - The collateral swap parameters including chain ID,
|
|
369
|
+
* trade parameters, and optional flash loan fee percentage.
|
|
370
|
+
* @returns {Promise<CollateralSwapQuoteParams>} Quote parameters with adjusted amounts and
|
|
371
|
+
* computed validity period.
|
|
372
|
+
* ```
|
|
373
|
+
*/
|
|
374
|
+
async getSwapQuoteParams(params) {
|
|
375
|
+
const { chainId, tradeParameters, flashLoanFeePercent = 0 } = params;
|
|
376
|
+
const { validFor = DEFAULT_VALIDITY, owner, amount } = tradeParameters;
|
|
377
|
+
const adapter = (0, import_sdk_common.getGlobalAdapter)();
|
|
378
|
+
const trader = owner ?? await adapter.signer.getAddress();
|
|
379
|
+
const validTo = tradeParameters.validTo ?? Math.ceil(Date.now() / 1e3) + validFor;
|
|
380
|
+
const sellAmount = BigInt(amount);
|
|
381
|
+
if (!Number.isFinite(flashLoanFeePercent) || flashLoanFeePercent < 0 || flashLoanFeePercent > 100) {
|
|
382
|
+
throw new Error(`flashLoanFeePercent must be between 0 and 100, got: ${flashLoanFeePercent}`);
|
|
383
|
+
}
|
|
384
|
+
const { flashLoanFeeAmount, sellAmountToSign } = this.calculateFlashLoanAmounts({ flashLoanFeePercent, sellAmount });
|
|
385
|
+
const { validFor: _, ...restParameters } = tradeParameters;
|
|
386
|
+
return {
|
|
387
|
+
...restParameters,
|
|
388
|
+
flashLoanFeeAmount,
|
|
389
|
+
chainId,
|
|
390
|
+
owner: trader,
|
|
391
|
+
amount: sellAmountToSign.toString(),
|
|
392
|
+
validTo
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Generates order posting settings including hooks and flash loan metadata.
|
|
397
|
+
*
|
|
398
|
+
* @remarks This method constructs the complete order posting configuration for a flash loan-based
|
|
399
|
+
* collateral swap. It:
|
|
400
|
+
* - Encodes the order data for EIP-1271 signature verification
|
|
401
|
+
* - Calculates the deterministic address for the adapter contract
|
|
402
|
+
* - Configures pre and post-execution hooks for flash loan management
|
|
403
|
+
* - Generates flash loan hint metadata conforming to the flashloan v0.2.0 schema
|
|
404
|
+
* - Sets up EIP-1271 signing scheme with the expected instance address
|
|
405
|
+
* - Includes hooks configuration following the hooks v0.2.0 schema
|
|
406
|
+
*
|
|
407
|
+
* The flash loan metadata includes information about the Aave pool, protocol adapter,
|
|
408
|
+
* and token amounts required for execution. The hooks enable the order to trigger
|
|
409
|
+
* flash loan deployment (pre-hook) and collateral swap execution (post-hook).
|
|
410
|
+
*
|
|
411
|
+
* @param {CollateralSwapTradeParams} params - Trade parameters including chain ID, validity period,
|
|
412
|
+
* owner address, and flash loan fee amount.
|
|
413
|
+
* @param {CollateralSwapOrder} settings - Order configuration including sell/buy amounts, the
|
|
414
|
+
* unsigned order to sign, and optional collateral permit data.
|
|
415
|
+
* @returns {Promise<CollateralSwapPostParams>} Object containing swap advanced settings with
|
|
416
|
+
* appData metadata (flashloan + hooks) and the
|
|
417
|
+
* deterministic adapter instance address.
|
|
418
|
+
*
|
|
419
|
+
* @throws Will throw if contract address calculation fails or gas estimation fails.
|
|
420
|
+
* ```
|
|
421
|
+
*/
|
|
422
|
+
async getOrderPostingSettings(params, settings) {
|
|
423
|
+
const { sellAmount, buyAmount, orderToSign, collateralPermit } = settings;
|
|
424
|
+
const { chainId, flashLoanFeeAmount, validTo, owner: trader } = params;
|
|
425
|
+
const amount = sellAmount.toString();
|
|
426
|
+
const encodedOrder = {
|
|
427
|
+
...import_sdk_order_signing.OrderSigningUtils.encodeUnsignedOrder(orderToSign),
|
|
428
|
+
appData: HASH_ZERO,
|
|
429
|
+
validTo
|
|
430
|
+
};
|
|
431
|
+
const hookAmounts = {
|
|
432
|
+
flashLoanAmount: amount,
|
|
433
|
+
flashLoanFeeAmount: flashLoanFeeAmount.toString(),
|
|
434
|
+
sellAssetAmount: amount,
|
|
435
|
+
buyAssetAmount: buyAmount.toString()
|
|
436
|
+
};
|
|
437
|
+
const instanceAddress = await this.getExpectedInstanceAddress(chainId, trader, hookAmounts, encodedOrder);
|
|
438
|
+
const flashLoanHint = {
|
|
439
|
+
amount,
|
|
440
|
+
// this is actually in UNDERLYING but aave tokens are 1:1
|
|
441
|
+
receiver: AAVE_ADAPTER_FACTORY[chainId],
|
|
442
|
+
liquidityProvider: AAVE_POOL_ADDRESS[chainId],
|
|
443
|
+
protocolAdapter: AAVE_ADAPTER_FACTORY[chainId],
|
|
444
|
+
token: orderToSign.sellToken
|
|
445
|
+
};
|
|
446
|
+
const hooks = await this.getOrderHooks(
|
|
447
|
+
chainId,
|
|
448
|
+
trader,
|
|
449
|
+
instanceAddress,
|
|
450
|
+
hookAmounts,
|
|
451
|
+
{
|
|
452
|
+
...encodedOrder,
|
|
453
|
+
receiver: instanceAddress
|
|
454
|
+
},
|
|
455
|
+
collateralPermit
|
|
456
|
+
);
|
|
457
|
+
const swapSettings = {
|
|
458
|
+
quoteRequest: {
|
|
459
|
+
validTo,
|
|
460
|
+
receiver: instanceAddress,
|
|
461
|
+
from: instanceAddress
|
|
462
|
+
},
|
|
463
|
+
additionalParams: {
|
|
464
|
+
signingScheme: import_sdk_order_book.SigningScheme.EIP1271,
|
|
465
|
+
customEIP1271Signature: (orderToSign2, signer) => {
|
|
466
|
+
return this.adapterEIP1271Signature(chainId, instanceAddress, orderToSign2, signer);
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
appData: {
|
|
470
|
+
metadata: {
|
|
471
|
+
flashloan: flashLoanHint,
|
|
472
|
+
hooks
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
return {
|
|
477
|
+
swapSettings,
|
|
478
|
+
instanceAddress
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Checks the current allowance for the flash loan adapter to spend collateral tokens.
|
|
483
|
+
*
|
|
484
|
+
* @remarks This method queries the ERC-20 token contract to determine how many tokens
|
|
485
|
+
* the deterministic adapter instance address is approved to spend on behalf
|
|
486
|
+
* of the trader. This is useful for verifying if approval is needed before
|
|
487
|
+
* executing a collateral swap.
|
|
488
|
+
*
|
|
489
|
+
* @param {CollateralParameters} params - Parameters including trader address, collateral
|
|
490
|
+
* token address, and adapter instance address.
|
|
491
|
+
* @returns {Promise<bigint>} The current allowance amount in token's smallest unit (wei).
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```typescript
|
|
495
|
+
* const allowance = await sdk.getCollateralAllowance({
|
|
496
|
+
* trader: '0x...',
|
|
497
|
+
* collateralToken: '0x...',
|
|
498
|
+
* amount: BigInt('1000000000000000000'),
|
|
499
|
+
* instanceAddress: '0x...',
|
|
500
|
+
* })
|
|
501
|
+
* console.log('Current allowance:', allowance.toString())
|
|
502
|
+
* ```
|
|
503
|
+
*/
|
|
504
|
+
async getCollateralAllowance(params) {
|
|
505
|
+
const { collateralToken, trader, instanceAddress } = params;
|
|
506
|
+
const adapter = (0, import_sdk_common.getGlobalAdapter)();
|
|
507
|
+
return await adapter.readContract({
|
|
508
|
+
address: collateralToken,
|
|
509
|
+
abi: import_sdk_common.ERC20_ALLOWANCE_ABI,
|
|
510
|
+
functionName: "allowance",
|
|
511
|
+
args: [trader, instanceAddress]
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Approves the flash loan adapter to spend collateral tokens.
|
|
516
|
+
*
|
|
517
|
+
* @remarks This method sends an on-chain approval transaction to allow the deterministic
|
|
518
|
+
* adapter instance address to spend the specified amount of collateral tokens.
|
|
519
|
+
* The approval is required before executing a collateral swap unless using
|
|
520
|
+
* EIP-2612 permit or preventApproval settings.
|
|
521
|
+
*
|
|
522
|
+
* @param {CollateralParameters} params - Parameters including trader address, collateral
|
|
523
|
+
* token address, amount to approve, and adapter
|
|
524
|
+
* instance address.
|
|
525
|
+
* @returns {Promise<TransactionResponse>} The transaction response from the approval transaction.
|
|
526
|
+
*
|
|
527
|
+
* @throws Will throw if the approval transaction fails or is rejected.
|
|
528
|
+
*
|
|
529
|
+
* @example
|
|
530
|
+
* ```typescript
|
|
531
|
+
* const txResponse = await sdk.approveCollateral({
|
|
532
|
+
* trader: '0x...',
|
|
533
|
+
* collateralToken: '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d',
|
|
534
|
+
* amount: BigInt('20000000000000000000'),
|
|
535
|
+
* instanceAddress: '0x...',
|
|
536
|
+
* })
|
|
537
|
+
* console.log('Approval transaction hash:', txResponse.hash)
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
async approveCollateral(params) {
|
|
541
|
+
const { collateralToken, amount, instanceAddress } = params;
|
|
542
|
+
const adapter = (0, import_sdk_common.getGlobalAdapter)();
|
|
543
|
+
const txParams = {
|
|
544
|
+
to: collateralToken,
|
|
545
|
+
data: adapter.utils.encodeFunction(import_sdk_common.ERC20_APPROVE_ABI, "approve", [instanceAddress, "0x" + amount.toString(16)])
|
|
546
|
+
};
|
|
547
|
+
return adapter.signer.sendTransaction(txParams);
|
|
548
|
+
}
|
|
549
|
+
async getExpectedInstanceAddress(chainId, trader, hookAmounts, order) {
|
|
550
|
+
const hookData = this.buildHookOrderData(trader, hookAmounts, order);
|
|
551
|
+
return await (0, import_sdk_common.getGlobalAdapter)().readContract({
|
|
552
|
+
address: AAVE_ADAPTER_FACTORY[chainId],
|
|
553
|
+
args: [AAVE_COLLATERAL_SWAP_ADAPTER_HOOK[chainId], hookData],
|
|
554
|
+
functionName: "getInstanceDeterministicAddress",
|
|
555
|
+
abi: aaveAdapterFactoryAbi
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
async approveCollateralIfNeeded(collateralParams, sellAmount) {
|
|
559
|
+
const allowance = await this.getCollateralAllowance(collateralParams).catch((error) => {
|
|
560
|
+
console.error("[AaveCollateralSwapSdk] Could not get allowance for collateral token", error);
|
|
561
|
+
return null;
|
|
562
|
+
});
|
|
563
|
+
if (!allowance || allowance < sellAmount) {
|
|
564
|
+
await this.approveCollateral(collateralParams);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
calculateFlashLoanAmounts({ sellAmount, flashLoanFeePercent }) {
|
|
568
|
+
const flashLoanFeeAmount = sellAmount * BigInt(Math.round(flashLoanFeePercent * PERCENT_SCALE)) / BigInt(100 * PERCENT_SCALE);
|
|
569
|
+
return {
|
|
570
|
+
flashLoanFeeAmount,
|
|
571
|
+
sellAmountToSign: sellAmount - flashLoanFeeAmount
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
getPreHookCallData(chainId, trader, hookAmounts, order, instanceAddress) {
|
|
575
|
+
const hookData = this.buildHookOrderData(trader, hookAmounts, order);
|
|
576
|
+
const adapterImplementation = AAVE_COLLATERAL_SWAP_ADAPTER_HOOK[chainId];
|
|
577
|
+
return (0, import_sdk_common.getGlobalAdapter)().utils.encodeFunction(aaveAdapterFactoryAbi, "deployAndTransferFlashLoan", [
|
|
578
|
+
adapterImplementation,
|
|
579
|
+
{ ...hookData, receiver: instanceAddress }
|
|
580
|
+
]);
|
|
581
|
+
}
|
|
582
|
+
buildHookOrderData(trader, hookAmounts, order) {
|
|
583
|
+
const { sellToken, buyToken, sellAmount, buyAmount, kind, validTo } = order;
|
|
584
|
+
const parsedValidTo = typeof validTo === "number" ? validTo : Number(validTo ?? 0);
|
|
585
|
+
return {
|
|
586
|
+
owner: trader,
|
|
587
|
+
receiver: import_sdk_common.ZERO_ADDRESS,
|
|
588
|
+
sellToken: String(sellToken),
|
|
589
|
+
buyToken: String(buyToken),
|
|
590
|
+
sellAmount: String(sellAmount),
|
|
591
|
+
buyAmount: String(buyAmount),
|
|
592
|
+
kind: String(kind),
|
|
593
|
+
validTo: parsedValidTo,
|
|
594
|
+
flashLoanAmount: hookAmounts.flashLoanAmount,
|
|
595
|
+
flashLoanFeeAmount: hookAmounts.flashLoanFeeAmount,
|
|
596
|
+
hookSellTokenAmount: hookAmounts.sellAssetAmount,
|
|
597
|
+
hookBuyTokenAmount: hookAmounts.buyAssetAmount
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
getPostHookCallData(collateralPermit = EMPTY_PERMIT) {
|
|
601
|
+
return (0, import_sdk_common.getGlobalAdapter)().utils.encodeFunction(collateralSwapAdapterHookAbi, "collateralSwapWithFlashLoan", [
|
|
602
|
+
collateralPermit
|
|
603
|
+
]);
|
|
604
|
+
}
|
|
605
|
+
async getOrderHooks(chainId, trader, expectedInstanceAddress, hookAmounts, order, collateralPermit) {
|
|
606
|
+
const preHookCallData = this.getPreHookCallData(chainId, trader, hookAmounts, order, expectedInstanceAddress);
|
|
607
|
+
const postHookCallData = this.getPostHookCallData(collateralPermit);
|
|
608
|
+
return {
|
|
609
|
+
pre: [
|
|
610
|
+
{
|
|
611
|
+
target: AAVE_ADAPTER_FACTORY[chainId],
|
|
612
|
+
callData: preHookCallData,
|
|
613
|
+
gasLimit: DEFAULT_HOOK_GAS_LIMIT.pre.toString()
|
|
614
|
+
}
|
|
615
|
+
],
|
|
616
|
+
post: [
|
|
617
|
+
{
|
|
618
|
+
target: expectedInstanceAddress,
|
|
619
|
+
callData: postHookCallData,
|
|
620
|
+
gasLimit: DEFAULT_HOOK_GAS_LIMIT.post.toString()
|
|
621
|
+
}
|
|
622
|
+
]
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
async adapterEIP1271Signature(chainId, instanceAddress, orderToSign, signer) {
|
|
626
|
+
const adapterFactoryAddress = AAVE_ADAPTER_FACTORY[chainId];
|
|
627
|
+
const encodedOrder = import_sdk_order_signing.OrderSigningUtils.encodeUnsignedOrder(orderToSign);
|
|
628
|
+
const domain = {
|
|
629
|
+
name: ADAPTER_DOMAIN_NAME,
|
|
630
|
+
version: ADAPTER_DOMAIN_VERSION,
|
|
631
|
+
chainId,
|
|
632
|
+
verifyingContract: adapterFactoryAddress
|
|
633
|
+
};
|
|
634
|
+
const message = {
|
|
635
|
+
instance: instanceAddress,
|
|
636
|
+
sellToken: encodedOrder.sellToken,
|
|
637
|
+
buyToken: encodedOrder.buyToken,
|
|
638
|
+
sellAmount: encodedOrder.sellAmount,
|
|
639
|
+
buyAmount: encodedOrder.buyAmount,
|
|
640
|
+
kind: encodedOrder.kind,
|
|
641
|
+
validTo: encodedOrder.validTo,
|
|
642
|
+
appData: encodedOrder.appData
|
|
643
|
+
};
|
|
644
|
+
const ecdsaSignature = await signer.signTypedData(domain, ADAPTER_SIGNATURE_TYPES, message);
|
|
645
|
+
return import_sdk_order_signing.OrderSigningUtils.getEip1271Signature(orderToSign, ecdsaSignature);
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
649
|
+
0 && (module.exports = {
|
|
650
|
+
AAVE_ADAPTER_FACTORY,
|
|
651
|
+
AAVE_COLLATERAL_SWAP_ADAPTER_HOOK,
|
|
652
|
+
AAVE_POOL_ADDRESS,
|
|
653
|
+
ADAPTER_DOMAIN_NAME,
|
|
654
|
+
ADAPTER_DOMAIN_VERSION,
|
|
655
|
+
ADAPTER_SIGNATURE_TYPES,
|
|
656
|
+
AaveCollateralSwapSdk,
|
|
657
|
+
DEFAULT_HOOK_GAS_LIMIT,
|
|
658
|
+
DEFAULT_VALIDITY,
|
|
659
|
+
EMPTY_PERMIT,
|
|
660
|
+
GAS_ESTIMATION_ADDITION_PERCENT,
|
|
661
|
+
HASH_ZERO,
|
|
662
|
+
PERCENT_SCALE
|
|
663
|
+
});
|