@dhedge/v2-sdk 2.1.7 → 2.1.8
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/config.d.ts +1 -0
- package/dist/services/cowSwap/index.d.ts +10 -0
- package/dist/types.d.ts +2 -1
- package/dist/v2-sdk.cjs.development.js +247 -19
- package/dist/v2-sdk.cjs.development.js.map +1 -1
- package/dist/v2-sdk.cjs.production.min.js +1 -1
- package/dist/v2-sdk.cjs.production.min.js.map +1 -1
- package/dist/v2-sdk.esm.js +247 -19
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +6 -1
- package/src/entities/pool.ts +57 -1
- package/src/services/cowSwap/index.ts +281 -0
- package/src/test/constants.ts +1 -1
- package/src/test/cowswap.test.ts +81 -0
- package/src/types.ts +2 -1
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -35,7 +35,8 @@ export const routerAddress: AddressDappNetworkMap = {
|
|
|
35
35
|
[Dapp.ARRAKIS]: "0xc73fb100a995b33f9fa181d420f4c8d74506df66",
|
|
36
36
|
[Dapp.TOROS]: "0x45b90480D6F643dE2f128db091A357C3c90399f2",
|
|
37
37
|
[Dapp.ODOS]: "0x0D05a7D3448512B78fa8A9e46c4872C88C4a0D05",
|
|
38
|
-
[Dapp.KYBERSWAP]: "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5"
|
|
38
|
+
[Dapp.KYBERSWAP]: "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5",
|
|
39
|
+
[Dapp.COWSWAP]: "0x893223Be4e941fAA8A8DB93D0C097fCac37801ce"
|
|
39
40
|
},
|
|
40
41
|
[Network.OPTIMISM]: {
|
|
41
42
|
[Dapp.UNISWAPV3]: "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
|
|
@@ -88,6 +89,10 @@ export const routerAddress: AddressDappNetworkMap = {
|
|
|
88
89
|
}
|
|
89
90
|
};
|
|
90
91
|
|
|
92
|
+
export const gpv2SettlementAddress: Partial<Record<Network, string>> = {
|
|
93
|
+
[Network.POLYGON]: "0x9008D19f58AAbD9eD0D60971565AA8510560ab41"
|
|
94
|
+
};
|
|
95
|
+
|
|
91
96
|
export const dappFactoryAddress: AddressDappNetworkMap = {
|
|
92
97
|
[Network.POLYGON]: {
|
|
93
98
|
[Dapp.SUSHISWAP]: "0xc35DADB65012eC5796536bD9864eD8773aBc74C4",
|
package/src/entities/pool.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
MaxUint128,
|
|
19
19
|
nonfungiblePositionManagerAddress,
|
|
20
20
|
routerAddress,
|
|
21
|
+
gpv2SettlementAddress,
|
|
21
22
|
stakingAddress,
|
|
22
23
|
SYNTHETIX_TRACKING_CODE,
|
|
23
24
|
limitOrderAddress
|
|
@@ -69,7 +70,7 @@ import {
|
|
|
69
70
|
getExitVestTxData,
|
|
70
71
|
getRewardsTxDta
|
|
71
72
|
} from "../services/ramses/vesting";
|
|
72
|
-
import { getPoolTxOrGasEstimate } from "../utils/contract";
|
|
73
|
+
import { getPoolTxOrGasEstimate, isSdkOptionsBoolean } from "../utils/contract";
|
|
73
74
|
import {
|
|
74
75
|
cancelOrderViaFlatMoney,
|
|
75
76
|
mintUnitViaFlatMoney,
|
|
@@ -96,6 +97,7 @@ import {
|
|
|
96
97
|
hasActiveTorosLimitOrder
|
|
97
98
|
} from "../services/toros/limitOrder";
|
|
98
99
|
import { getKyberSwapTxData } from "../services/kyberSwap";
|
|
100
|
+
import { getCowSwapTxData } from "../services/cowSwap";
|
|
99
101
|
import {
|
|
100
102
|
getClosePositionHyperliquidTxData,
|
|
101
103
|
getDepositHyperliquidTxData,
|
|
@@ -474,6 +476,60 @@ export class Pool {
|
|
|
474
476
|
slippage
|
|
475
477
|
));
|
|
476
478
|
break;
|
|
479
|
+
case Dapp.COWSWAP: {
|
|
480
|
+
const cowSwapEstimateGas = isSdkOptionsBoolean(sdkOptions)
|
|
481
|
+
? sdkOptions
|
|
482
|
+
: sdkOptions.estimateGas;
|
|
483
|
+
if (
|
|
484
|
+
cowSwapEstimateGas ||
|
|
485
|
+
(!isSdkOptionsBoolean(sdkOptions) && sdkOptions.onlyGetTxData)
|
|
486
|
+
) {
|
|
487
|
+
throw new Error(
|
|
488
|
+
"CowSwap requires two sequential transactions (submit + preSign) and does not support estimateGas or onlyGetTxData"
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
const {
|
|
492
|
+
encodedTypedData,
|
|
493
|
+
preSignTxData,
|
|
494
|
+
minAmountOut: cowMinOut
|
|
495
|
+
} = await getCowSwapTxData(
|
|
496
|
+
this,
|
|
497
|
+
assetFrom,
|
|
498
|
+
assetTo,
|
|
499
|
+
amountIn,
|
|
500
|
+
slippage
|
|
501
|
+
);
|
|
502
|
+
// Tx 1: manager calls submit() directly on TypedStructuredDataValidator (not via pool.execTransaction)
|
|
503
|
+
const validatorContract = new Contract(
|
|
504
|
+
routerAddress[this.network][dapp] as string,
|
|
505
|
+
[
|
|
506
|
+
"function submit(address _poolLogic, uint8 _dataType, bytes memory _structuredData) external"
|
|
507
|
+
],
|
|
508
|
+
this.signer
|
|
509
|
+
);
|
|
510
|
+
const submitTx = await validatorContract.submit(
|
|
511
|
+
this.address,
|
|
512
|
+
1 /* COWSWAP_ORDER */,
|
|
513
|
+
encodedTypedData,
|
|
514
|
+
...(options ? [options] : [])
|
|
515
|
+
);
|
|
516
|
+
const submitReceipt = await submitTx.wait(3);
|
|
517
|
+
if (submitReceipt.status === 0) {
|
|
518
|
+
return submitReceipt;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Tx 2: pool.execTransaction → setPreSignature() on GPv2Settlement — guard checks stored digest, solvers execute
|
|
522
|
+
return getPoolTxOrGasEstimate(
|
|
523
|
+
this,
|
|
524
|
+
[
|
|
525
|
+
gpv2SettlementAddress[this.network],
|
|
526
|
+
preSignTxData,
|
|
527
|
+
options,
|
|
528
|
+
cowMinOut
|
|
529
|
+
],
|
|
530
|
+
sdkOptions
|
|
531
|
+
);
|
|
532
|
+
}
|
|
477
533
|
default:
|
|
478
534
|
const iUniswapV2Router = new ethers.utils.Interface(
|
|
479
535
|
IUniswapV2Router.abi
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
import { ethers } from "ethers";
|
|
4
|
+
import { ApiError } from "../..";
|
|
5
|
+
import { networkChainIdMap, gpv2SettlementAddress } from "../../config";
|
|
6
|
+
import { Pool } from "../../entities";
|
|
7
|
+
import BN from "bignumber.js";
|
|
8
|
+
|
|
9
|
+
export const KIND_SELL = ethers.utils.keccak256(
|
|
10
|
+
ethers.utils.toUtf8Bytes("sell")
|
|
11
|
+
);
|
|
12
|
+
export const KIND_BUY = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("buy"));
|
|
13
|
+
export const BALANCE_ERC20 = ethers.utils.keccak256(
|
|
14
|
+
ethers.utils.toUtf8Bytes("erc20")
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
// Matches CowSwapOrderTypeHashLib.ORDER_TYPE_HASH exactly:
|
|
18
|
+
// kind/sellTokenBalance/buyTokenBalance are "string" in the type string
|
|
19
|
+
// but encoded as bytes32 values in abi.encode — must replicate this exactly
|
|
20
|
+
const ORDER_TYPE_HASH = ethers.utils.keccak256(
|
|
21
|
+
ethers.utils.toUtf8Bytes(
|
|
22
|
+
"Order(" +
|
|
23
|
+
"address sellToken," +
|
|
24
|
+
"address buyToken," +
|
|
25
|
+
"address receiver," +
|
|
26
|
+
"uint256 sellAmount," +
|
|
27
|
+
"uint256 buyAmount," +
|
|
28
|
+
"uint32 validTo," +
|
|
29
|
+
"bytes32 appData," +
|
|
30
|
+
"uint256 feeAmount," +
|
|
31
|
+
"string kind," +
|
|
32
|
+
"bool partiallyFillable," +
|
|
33
|
+
"string sellTokenBalance," +
|
|
34
|
+
"string buyTokenBalance" +
|
|
35
|
+
")"
|
|
36
|
+
)
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// Matches CowSwapOrderTypeHashLib.EIP712_DOMAIN_TYPEHASH
|
|
40
|
+
const EIP712_DOMAIN_TYPEHASH = ethers.utils.keccak256(
|
|
41
|
+
ethers.utils.toUtf8Bytes(
|
|
42
|
+
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const cowSwapApiNetworkMap: Record<string, string> = {
|
|
47
|
+
polygon: "polygon"
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const GPv2Settlement_ABI = [
|
|
51
|
+
"function setPreSignature(bytes calldata orderUid, bool signed) external"
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
// Replicates CowSwapOrderTypeHashLib.hashOrder
|
|
55
|
+
function hashOrder(order: {
|
|
56
|
+
sellToken: string;
|
|
57
|
+
buyToken: string;
|
|
58
|
+
receiver: string;
|
|
59
|
+
sellAmount: string;
|
|
60
|
+
buyAmount: string;
|
|
61
|
+
validTo: number;
|
|
62
|
+
appData: string;
|
|
63
|
+
feeAmount: string;
|
|
64
|
+
kind: string;
|
|
65
|
+
partiallyFillable: boolean;
|
|
66
|
+
sellTokenBalance: string;
|
|
67
|
+
buyTokenBalance: string;
|
|
68
|
+
}): string {
|
|
69
|
+
return ethers.utils.keccak256(
|
|
70
|
+
ethers.utils.defaultAbiCoder.encode(
|
|
71
|
+
[
|
|
72
|
+
"bytes32",
|
|
73
|
+
"address",
|
|
74
|
+
"address",
|
|
75
|
+
"address",
|
|
76
|
+
"uint256",
|
|
77
|
+
"uint256",
|
|
78
|
+
"uint32",
|
|
79
|
+
"bytes32",
|
|
80
|
+
"uint256",
|
|
81
|
+
"bytes32",
|
|
82
|
+
"bool",
|
|
83
|
+
"bytes32",
|
|
84
|
+
"bytes32"
|
|
85
|
+
],
|
|
86
|
+
[
|
|
87
|
+
ORDER_TYPE_HASH,
|
|
88
|
+
order.sellToken,
|
|
89
|
+
order.buyToken,
|
|
90
|
+
order.receiver,
|
|
91
|
+
order.sellAmount,
|
|
92
|
+
order.buyAmount,
|
|
93
|
+
order.validTo,
|
|
94
|
+
order.appData,
|
|
95
|
+
order.feeAmount,
|
|
96
|
+
order.kind,
|
|
97
|
+
order.partiallyFillable,
|
|
98
|
+
order.sellTokenBalance,
|
|
99
|
+
order.buyTokenBalance
|
|
100
|
+
]
|
|
101
|
+
)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Replicates CowSwapOrderTypeHashLib.domainSeparator
|
|
106
|
+
function computeDomainSeparator(
|
|
107
|
+
name: string,
|
|
108
|
+
version: string,
|
|
109
|
+
chainId: number,
|
|
110
|
+
verifyingContract: string
|
|
111
|
+
): string {
|
|
112
|
+
return ethers.utils.keccak256(
|
|
113
|
+
ethers.utils.defaultAbiCoder.encode(
|
|
114
|
+
["bytes32", "bytes32", "bytes32", "uint256", "address"],
|
|
115
|
+
[
|
|
116
|
+
EIP712_DOMAIN_TYPEHASH,
|
|
117
|
+
ethers.utils.keccak256(ethers.utils.toUtf8Bytes(name)),
|
|
118
|
+
ethers.utils.keccak256(ethers.utils.toUtf8Bytes(version)),
|
|
119
|
+
chainId,
|
|
120
|
+
verifyingContract
|
|
121
|
+
]
|
|
122
|
+
)
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Replicates CowSwapOrderTypeHashLib.getDigest
|
|
127
|
+
function computeOrderDigest(domainSep: string, orderHash: string): string {
|
|
128
|
+
return ethers.utils.keccak256(
|
|
129
|
+
ethers.utils.solidityPack(
|
|
130
|
+
["bytes2", "bytes32", "bytes32"],
|
|
131
|
+
["0x1901", domainSep, orderHash]
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export async function getCowSwapTxData(
|
|
137
|
+
pool: Pool,
|
|
138
|
+
assetFrom: string,
|
|
139
|
+
assetTo: string,
|
|
140
|
+
amountIn: ethers.BigNumber | string,
|
|
141
|
+
slippage: number,
|
|
142
|
+
kind: "sell" | "buy" = "sell"
|
|
143
|
+
): Promise<{
|
|
144
|
+
encodedTypedData: string;
|
|
145
|
+
preSignTxData: string;
|
|
146
|
+
minAmountOut: string;
|
|
147
|
+
}> {
|
|
148
|
+
const chainId = networkChainIdMap[pool.network];
|
|
149
|
+
const network = cowSwapApiNetworkMap[pool.network];
|
|
150
|
+
if (!network) {
|
|
151
|
+
throw new Error(`CowSwap is not supported on network: ${pool.network}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const gpv2Settlement = gpv2SettlementAddress[pool.network];
|
|
155
|
+
if (!gpv2Settlement) {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`GPv2Settlement address not configured for network: ${pool.network}`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const baseUrl = `https://api.cow.fi/${network}/api/v1`;
|
|
162
|
+
|
|
163
|
+
// 1. Get quote
|
|
164
|
+
let quoteResponse: any;
|
|
165
|
+
try {
|
|
166
|
+
const quoteResult = await axios.post(`${baseUrl}/quote`, {
|
|
167
|
+
sellToken: assetFrom,
|
|
168
|
+
buyToken: assetTo,
|
|
169
|
+
...(kind === "sell"
|
|
170
|
+
? { sellAmountBeforeFee: amountIn.toString() }
|
|
171
|
+
: { buyAmountAfterFee: amountIn.toString() }),
|
|
172
|
+
from: pool.address,
|
|
173
|
+
receiver: pool.address,
|
|
174
|
+
kind,
|
|
175
|
+
signingScheme: "presign",
|
|
176
|
+
partiallyFillable: false,
|
|
177
|
+
sellTokenBalance: "erc20",
|
|
178
|
+
buyTokenBalance: "erc20"
|
|
179
|
+
});
|
|
180
|
+
quoteResponse = quoteResult.data;
|
|
181
|
+
} catch (e) {
|
|
182
|
+
throw new ApiError("CowSwap quote request failed");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const { sellAmount, buyAmount, validTo } = quoteResponse.quote;
|
|
186
|
+
|
|
187
|
+
const buyAmountWithSlippage = ethers.BigNumber.from(
|
|
188
|
+
new BN(buyAmount.toString())
|
|
189
|
+
.times(new BN(1).minus(new BN(slippage).div(100)))
|
|
190
|
+
.toFixed(0, BN.ROUND_DOWN)
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
const orderValues = {
|
|
194
|
+
sellToken: assetFrom,
|
|
195
|
+
buyToken: assetTo,
|
|
196
|
+
receiver: pool.address,
|
|
197
|
+
sellAmount,
|
|
198
|
+
buyAmount: buyAmountWithSlippage.toString(),
|
|
199
|
+
validTo,
|
|
200
|
+
appData: ethers.constants.HashZero,
|
|
201
|
+
feeAmount: "0",
|
|
202
|
+
kind: kind === "sell" ? KIND_SELL : KIND_BUY,
|
|
203
|
+
partiallyFillable: false,
|
|
204
|
+
sellTokenBalance: BALANCE_ERC20,
|
|
205
|
+
buyTokenBalance: BALANCE_ERC20
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// 2. Compute digest matching CowSwapOrderTypeHashLib.getDigest exactly
|
|
209
|
+
const domainSep = computeDomainSeparator(
|
|
210
|
+
"Gnosis Protocol",
|
|
211
|
+
"v2",
|
|
212
|
+
chainId,
|
|
213
|
+
gpv2Settlement
|
|
214
|
+
);
|
|
215
|
+
const orderHash = hashOrder(orderValues);
|
|
216
|
+
const orderDigest = computeOrderDigest(domainSep, orderHash);
|
|
217
|
+
|
|
218
|
+
// orderUid = abi.encodePacked(orderDigest, owner, validTo) — 32 + 20 + 4 = 56 bytes
|
|
219
|
+
const orderUid = ethers.utils.solidityPack(
|
|
220
|
+
["bytes32", "address", "uint32"],
|
|
221
|
+
[orderDigest, pool.address, validTo]
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
// 3. Submit order to CowSwap API — solver waits for on-chain presign before executing
|
|
225
|
+
try {
|
|
226
|
+
await axios.post(`${baseUrl}/orders`, {
|
|
227
|
+
sellToken: assetFrom,
|
|
228
|
+
buyToken: assetTo,
|
|
229
|
+
receiver: pool.address,
|
|
230
|
+
sellAmount,
|
|
231
|
+
buyAmount: buyAmountWithSlippage.toString(),
|
|
232
|
+
validTo,
|
|
233
|
+
appData: ethers.constants.HashZero,
|
|
234
|
+
feeAmount: "0",
|
|
235
|
+
kind,
|
|
236
|
+
partiallyFillable: false,
|
|
237
|
+
signingScheme: "presign",
|
|
238
|
+
signature: pool.address,
|
|
239
|
+
sellTokenBalance: "erc20",
|
|
240
|
+
buyTokenBalance: "erc20",
|
|
241
|
+
from: pool.address,
|
|
242
|
+
quoteId: quoteResponse.id
|
|
243
|
+
});
|
|
244
|
+
} catch (e) {
|
|
245
|
+
throw new ApiError("CowSwap order submission failed");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// 4. Encode CowSwapTypedData for submit() on TypedStructuredDataValidator
|
|
249
|
+
const typedData = {
|
|
250
|
+
domain: {
|
|
251
|
+
name: "Gnosis Protocol",
|
|
252
|
+
version: "v2",
|
|
253
|
+
chainId,
|
|
254
|
+
verifyingContract: gpv2Settlement
|
|
255
|
+
},
|
|
256
|
+
order: orderValues
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const encodedTypedData = ethers.utils.defaultAbiCoder.encode(
|
|
260
|
+
[
|
|
261
|
+
"tuple(" +
|
|
262
|
+
"tuple(string name, string version, uint256 chainId, address verifyingContract) domain," +
|
|
263
|
+
"tuple(address sellToken, address buyToken, address receiver, uint256 sellAmount, uint256 buyAmount, uint32 validTo, bytes32 appData, uint256 feeAmount, bytes32 kind, bool partiallyFillable, bytes32 sellTokenBalance, bytes32 buyTokenBalance) order" +
|
|
264
|
+
")"
|
|
265
|
+
],
|
|
266
|
+
[typedData]
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
// 5. Encode setPreSignature() — guard checks isValidatedHash(pool, orderDigest)
|
|
270
|
+
const settlementIface = new ethers.utils.Interface(GPv2Settlement_ABI);
|
|
271
|
+
const preSignTxData = settlementIface.encodeFunctionData("setPreSignature", [
|
|
272
|
+
orderUid,
|
|
273
|
+
true
|
|
274
|
+
]);
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
encodedTypedData,
|
|
278
|
+
preSignTxData,
|
|
279
|
+
minAmountOut: buyAmountWithSlippage.toString()
|
|
280
|
+
};
|
|
281
|
+
}
|
package/src/test/constants.ts
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
+
|
|
3
|
+
import { Dhedge, Pool } from "..";
|
|
4
|
+
|
|
5
|
+
import { Dapp, Network } from "../types";
|
|
6
|
+
import { CONTRACT_ADDRESS, TEST_POOL } from "./constants";
|
|
7
|
+
import { getTxOptions } from "./txOptions";
|
|
8
|
+
import { TestingRunParams, testingHelper } from "./utils/testingHelper";
|
|
9
|
+
import { balanceDelta } from "./utils/token";
|
|
10
|
+
|
|
11
|
+
const testCowswap = ({ wallet, network }: TestingRunParams) => {
|
|
12
|
+
const USDC = CONTRACT_ADDRESS[network].USDC;
|
|
13
|
+
const WETH = CONTRACT_ADDRESS[network].WETH;
|
|
14
|
+
|
|
15
|
+
let dhedge: Dhedge;
|
|
16
|
+
let pool: Pool;
|
|
17
|
+
jest.setTimeout(100000);
|
|
18
|
+
|
|
19
|
+
describe(`pool on ${network}`, () => {
|
|
20
|
+
beforeAll(async () => {
|
|
21
|
+
dhedge = new Dhedge(wallet, network);
|
|
22
|
+
pool = await dhedge.loadPool(TEST_POOL[network]);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// it("approves unlimited USDC on Cowswap", async () => {
|
|
26
|
+
// await pool.approveSpender(
|
|
27
|
+
// "0xC92E8bdf79f0507f65a392b0ab4667716BFE0110", //Vault relayer
|
|
28
|
+
// USDC,
|
|
29
|
+
// MAX_AMOUNT,
|
|
30
|
+
// await getTxOptions(network)
|
|
31
|
+
// );
|
|
32
|
+
// const usdcAllowanceDelta = await allowanceDelta(
|
|
33
|
+
// pool.address,
|
|
34
|
+
// USDC,
|
|
35
|
+
// "0xC92E8bdf79f0507f65a392b0ab4667716BFE0110", //Vault relayer
|
|
36
|
+
// pool.signer
|
|
37
|
+
// );
|
|
38
|
+
// await expect(usdcAllowanceDelta.gt(0).toBe(true));
|
|
39
|
+
// });
|
|
40
|
+
|
|
41
|
+
// it("gets gas estimation for 2 USDC into WETH on Cowswap", async () => {
|
|
42
|
+
// const gasEstimate = await pool.trade(
|
|
43
|
+
// Dapp.COWSWAP,
|
|
44
|
+
// USDC,
|
|
45
|
+
// WETH,
|
|
46
|
+
// "2000000",
|
|
47
|
+
// 1,
|
|
48
|
+
// await getTxOptions(network),
|
|
49
|
+
// true
|
|
50
|
+
// );
|
|
51
|
+
// console.log(
|
|
52
|
+
// "Gas estimate for trading 2 USDC to WETH on Cowswap:",
|
|
53
|
+
// gasEstimate
|
|
54
|
+
// );
|
|
55
|
+
// expect(gasEstimate.minAmountOut).not.toBeNull();
|
|
56
|
+
// });
|
|
57
|
+
|
|
58
|
+
it("trades 2 USDC into WETH on Cowswap", async () => {
|
|
59
|
+
await pool.trade(
|
|
60
|
+
Dapp.COWSWAP,
|
|
61
|
+
USDC,
|
|
62
|
+
WETH,
|
|
63
|
+
"2000000",
|
|
64
|
+
0.5,
|
|
65
|
+
await getTxOptions(network)
|
|
66
|
+
);
|
|
67
|
+
const wethBalanceDelta = await balanceDelta(
|
|
68
|
+
pool.address,
|
|
69
|
+
WETH,
|
|
70
|
+
pool.signer
|
|
71
|
+
);
|
|
72
|
+
expect(wethBalanceDelta.gt(0)).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
testingHelper({
|
|
78
|
+
network: Network.POLYGON,
|
|
79
|
+
testingRun: testCowswap,
|
|
80
|
+
onFork: false
|
|
81
|
+
});
|