@dhedge/v2-sdk 1.9.0 → 1.9.2
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 +2 -2
- package/dist/entities/pool.d.ts +22 -1
- package/dist/errors.d.ts +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/services/oneInch/index.d.ts +3 -0
- package/dist/services/velodrome/staking.d.ts +2 -2
- package/dist/services/zeroEx/zeroExTrade.d.ts +3 -0
- package/dist/test/utils/testingHelper.d.ts +13 -0
- package/dist/test/wallet.d.ts +7 -0
- package/dist/types.d.ts +3 -1
- package/dist/v2-sdk.cjs.development.js +882 -362
- 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 +882 -363
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +4 -4
- package/src/abi/IVelodromeGaugeV2.json +191 -0
- package/src/config.ts +5 -2
- package/src/entities/pool.ts +92 -19
- package/src/errors.ts +10 -0
- package/src/index.ts +1 -0
- package/src/services/oneInch/index.ts +33 -0
- package/src/services/velodrome/staking.ts +33 -20
- package/src/services/zeroEx/zeroExTrade.ts +52 -0
- package/src/test/oneInch.test.ts +40 -32
- package/src/test/txOptions.ts +1 -1
- package/src/test/utils/testingHelper.ts +20 -0
- package/src/test/velodromeV2.test.ts +114 -0
- package/src/test/wallet.ts +14 -1
- package/src/test/zeroEx.test.ts +54 -0
- package/src/types.ts +3 -1
- package/dist/services/oneInch/protocols.d.ts +0 -1
- package/src/services/oneInch/protocols.ts +0 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dhedge/v2-sdk",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "🛠 An SDK for building applications on top of dHEDGE V2",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"prepare": "tsdx build",
|
|
21
21
|
"size": "size-limit",
|
|
22
22
|
"analyze": "size-limit --why",
|
|
23
|
-
"fork:polygon": "hardhat node --fork $(grep POLYGON_URL .env | cut -d '=' -f2)",
|
|
24
|
-
"fork:optimism": "hardhat node --fork $(grep OPTIMISM_URL .env | cut -d '=' -f2)",
|
|
25
|
-
"fork:arbitrum": "hardhat node --fork $(grep ARBITRUM_URL .env | cut -d '=' -f2)"
|
|
23
|
+
"fork:polygon": "hardhat node --port 8542 --fork $(grep POLYGON_URL .env | cut -d '=' -f2)",
|
|
24
|
+
"fork:optimism": "hardhat node --port 8544 --fork $(grep OPTIMISM_URL .env | cut -d '=' -f2)",
|
|
25
|
+
"fork:arbitrum": "hardhat node --port 8540 --fork $(grep ARBITRUM_URL .env | cut -d '=' -f2)"
|
|
26
26
|
},
|
|
27
27
|
"husky": {
|
|
28
28
|
"hooks": {
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
{
|
|
2
|
+
"abi": [
|
|
3
|
+
{
|
|
4
|
+
"inputs": [
|
|
5
|
+
{
|
|
6
|
+
"internalType": "address",
|
|
7
|
+
"name": "user",
|
|
8
|
+
"type": "address"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"name": "balanceOf",
|
|
12
|
+
"outputs": [
|
|
13
|
+
{
|
|
14
|
+
"internalType": "uint256",
|
|
15
|
+
"name": "",
|
|
16
|
+
"type": "uint256"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"stateMutability": "view",
|
|
20
|
+
"type": "function"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"inputs": [
|
|
24
|
+
{
|
|
25
|
+
"internalType": "uint256",
|
|
26
|
+
"name": "_amount",
|
|
27
|
+
"type": "uint256"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"internalType": "address",
|
|
31
|
+
"name": "_recipient",
|
|
32
|
+
"type": "address"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"name": "deposit",
|
|
36
|
+
"outputs": [],
|
|
37
|
+
"stateMutability": "nonpayable",
|
|
38
|
+
"type": "function"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"inputs": [
|
|
42
|
+
{
|
|
43
|
+
"internalType": "uint256",
|
|
44
|
+
"name": "_amount",
|
|
45
|
+
"type": "uint256"
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"name": "deposit",
|
|
49
|
+
"outputs": [],
|
|
50
|
+
"stateMutability": "nonpayable",
|
|
51
|
+
"type": "function"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"inputs": [
|
|
55
|
+
{
|
|
56
|
+
"internalType": "address",
|
|
57
|
+
"name": "_account",
|
|
58
|
+
"type": "address"
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"name": "earned",
|
|
62
|
+
"outputs": [
|
|
63
|
+
{
|
|
64
|
+
"internalType": "uint256",
|
|
65
|
+
"name": "_earned",
|
|
66
|
+
"type": "uint256"
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"stateMutability": "view",
|
|
70
|
+
"type": "function"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"inputs": [
|
|
74
|
+
{
|
|
75
|
+
"internalType": "address",
|
|
76
|
+
"name": "_account",
|
|
77
|
+
"type": "address"
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"name": "getReward",
|
|
81
|
+
"outputs": [],
|
|
82
|
+
"stateMutability": "nonpayable",
|
|
83
|
+
"type": "function"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"inputs": [],
|
|
87
|
+
"name": "isPool",
|
|
88
|
+
"outputs": [
|
|
89
|
+
{
|
|
90
|
+
"internalType": "bool",
|
|
91
|
+
"name": "_isPool",
|
|
92
|
+
"type": "bool"
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
"stateMutability": "view",
|
|
96
|
+
"type": "function"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"inputs": [],
|
|
100
|
+
"name": "lastTimeRewardApplicable",
|
|
101
|
+
"outputs": [
|
|
102
|
+
{
|
|
103
|
+
"internalType": "uint256",
|
|
104
|
+
"name": "_time",
|
|
105
|
+
"type": "uint256"
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
"stateMutability": "view",
|
|
109
|
+
"type": "function"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"inputs": [],
|
|
113
|
+
"name": "left",
|
|
114
|
+
"outputs": [
|
|
115
|
+
{
|
|
116
|
+
"internalType": "uint256",
|
|
117
|
+
"name": "_left",
|
|
118
|
+
"type": "uint256"
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
"stateMutability": "view",
|
|
122
|
+
"type": "function"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"inputs": [
|
|
126
|
+
{
|
|
127
|
+
"internalType": "uint256",
|
|
128
|
+
"name": "amount",
|
|
129
|
+
"type": "uint256"
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
"name": "notifyRewardAmount",
|
|
133
|
+
"outputs": [],
|
|
134
|
+
"stateMutability": "nonpayable",
|
|
135
|
+
"type": "function"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"inputs": [],
|
|
139
|
+
"name": "rewardPerToken",
|
|
140
|
+
"outputs": [
|
|
141
|
+
{
|
|
142
|
+
"internalType": "uint256",
|
|
143
|
+
"name": "_rewardPerToken",
|
|
144
|
+
"type": "uint256"
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"stateMutability": "view",
|
|
148
|
+
"type": "function"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"inputs": [],
|
|
152
|
+
"name": "rewardToken",
|
|
153
|
+
"outputs": [
|
|
154
|
+
{
|
|
155
|
+
"internalType": "address",
|
|
156
|
+
"name": "_token",
|
|
157
|
+
"type": "address"
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
"stateMutability": "view",
|
|
161
|
+
"type": "function"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"inputs": [],
|
|
165
|
+
"name": "stakingToken",
|
|
166
|
+
"outputs": [
|
|
167
|
+
{
|
|
168
|
+
"internalType": "address",
|
|
169
|
+
"name": "_pool",
|
|
170
|
+
"type": "address"
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
"stateMutability": "view",
|
|
174
|
+
"type": "function"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"inputs": [
|
|
178
|
+
{
|
|
179
|
+
"internalType": "uint256",
|
|
180
|
+
"name": "_amount",
|
|
181
|
+
"type": "uint256"
|
|
182
|
+
}
|
|
183
|
+
],
|
|
184
|
+
"name": "withdraw",
|
|
185
|
+
"outputs": [],
|
|
186
|
+
"stateMutability": "nonpayable",
|
|
187
|
+
"type": "function"
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
}
|
package/src/config.ts
CHANGED
|
@@ -29,7 +29,8 @@ export const routerAddress: AddressDappNetworkMap = {
|
|
|
29
29
|
[Dapp.BALANCER]: "0xBA12222222228d8Ba445958a75a0704d566BF2C8",
|
|
30
30
|
[Dapp.UNISWAPV3]: "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
|
|
31
31
|
[Dapp.ARRAKIS]: "0xc73fb100a995b33f9fa181d420f4c8d74506df66",
|
|
32
|
-
[Dapp.TOROS]: "0xB2F1498983bf9c9442c35F772e6C1AdE66a8DeDE"
|
|
32
|
+
[Dapp.TOROS]: "0xB2F1498983bf9c9442c35F772e6C1AdE66a8DeDE",
|
|
33
|
+
[Dapp.ZEROEX]: "0xdef1c0ded9bec7f1a1670819833240f027b25eff"
|
|
33
34
|
},
|
|
34
35
|
[Network.OPTIMISM]: {
|
|
35
36
|
[Dapp.UNISWAPV3]: "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
|
|
@@ -38,8 +39,10 @@ export const routerAddress: AddressDappNetworkMap = {
|
|
|
38
39
|
[Dapp.ONEINCH]: "0x1111111254EEB25477B68fb85Ed929f73A960582",
|
|
39
40
|
[Dapp.TOROS]: "0x3988513793bCE39f0167064A9F7fC3617FaF35AB",
|
|
40
41
|
[Dapp.VELODROME]: "0x9c12939390052919aF3155f41Bf4160Fd3666A6f",
|
|
42
|
+
[Dapp.VELODROMEV2]: "0xa062ae8a9c5e11aaa026fc2670b0d65ccc8b2858",
|
|
41
43
|
[Dapp.LYRA]: "0xCCE7819d65f348c64B7Beb205BA367b3fE33763B",
|
|
42
|
-
[Dapp.ARRAKIS]: "0x9ce88a56d120300061593eF7AD074A1B710094d5"
|
|
44
|
+
[Dapp.ARRAKIS]: "0x9ce88a56d120300061593eF7AD074A1B710094d5",
|
|
45
|
+
[Dapp.ZEROEX]: "0xdef1abe32c034e558cdd535791643c58a13acc10"
|
|
43
46
|
},
|
|
44
47
|
[Network.ARBITRUM]: {
|
|
45
48
|
[Dapp.ONEINCH]: "0x1111111254EEB25477B68fb85Ed929f73A960582",
|
package/src/entities/pool.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
import axios from "axios";
|
|
4
3
|
import { Contract, ethers, Wallet, BigNumber } from "ethers";
|
|
5
4
|
|
|
6
5
|
import IERC20 from "../abi/IERC20.json";
|
|
@@ -16,7 +15,6 @@ import IBalancerRewardsGauge from "../abi/IBalancerRewardsGauge.json";
|
|
|
16
15
|
|
|
17
16
|
import {
|
|
18
17
|
MaxUint128,
|
|
19
|
-
networkChainIdMap,
|
|
20
18
|
nonfungiblePositionManagerAddress,
|
|
21
19
|
routerAddress,
|
|
22
20
|
stakingAddress,
|
|
@@ -42,7 +40,6 @@ import {
|
|
|
42
40
|
import { FeeAmount } from "@uniswap/v3-sdk";
|
|
43
41
|
import { getUniswapV3SwapTxData } from "../services/uniswap/V3Trade";
|
|
44
42
|
import { getEasySwapperTxData } from "../services/toros/easySwapper";
|
|
45
|
-
import { getOneInchProtocols } from "../services/oneInch/protocols";
|
|
46
43
|
import { getAaveV3ClaimTxData } from "../services/aave/incentives";
|
|
47
44
|
import {
|
|
48
45
|
getVelodromeAddLiquidityTxData,
|
|
@@ -60,6 +57,8 @@ import {
|
|
|
60
57
|
getFuturesChangeMarginTxData
|
|
61
58
|
} from "../services/futures";
|
|
62
59
|
import { getFuturesCancelOrderTxData } from "../services/futures/trade";
|
|
60
|
+
import { getZeroExTradeTxData } from "../services/zeroEx/zeroExTrade";
|
|
61
|
+
import { getOneInchSwapTxData } from "../services/oneInch";
|
|
63
62
|
|
|
64
63
|
export class Pool {
|
|
65
64
|
public readonly poolLogic: Contract;
|
|
@@ -286,20 +285,24 @@ export class Pool {
|
|
|
286
285
|
): Promise<any> {
|
|
287
286
|
let swapTxData: string;
|
|
288
287
|
switch (dapp) {
|
|
289
|
-
case Dapp.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}/${chainId}/swap?fromTokenAddress=${assetFrom}&toTokenAddress=${assetTo}&amount=${amountIn.toString()}&fromAddress=${
|
|
297
|
-
this.address
|
|
298
|
-
}&destReceiver=${
|
|
288
|
+
case Dapp.ZEROEX:
|
|
289
|
+
swapTxData = await getZeroExTradeTxData(
|
|
290
|
+
this.network,
|
|
291
|
+
assetFrom,
|
|
292
|
+
assetTo,
|
|
293
|
+
amountIn,
|
|
294
|
+
slippage,
|
|
299
295
|
this.address
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
296
|
+
);
|
|
297
|
+
break;
|
|
298
|
+
case Dapp.ONEINCH:
|
|
299
|
+
swapTxData = await getOneInchSwapTxData(
|
|
300
|
+
this,
|
|
301
|
+
assetFrom,
|
|
302
|
+
assetTo,
|
|
303
|
+
amountIn,
|
|
304
|
+
slippage
|
|
305
|
+
);
|
|
303
306
|
break;
|
|
304
307
|
case Dapp.BALANCER:
|
|
305
308
|
swapTxData = await this.utils.getBalancerSwapTx(
|
|
@@ -483,7 +486,10 @@ export class Pool {
|
|
|
483
486
|
]);
|
|
484
487
|
break;
|
|
485
488
|
case Dapp.VELODROME:
|
|
486
|
-
stakeTxData = getVelodromeStakeTxData(amount);
|
|
489
|
+
stakeTxData = getVelodromeStakeTxData(amount, false);
|
|
490
|
+
break;
|
|
491
|
+
case Dapp.VELODROMEV2:
|
|
492
|
+
stakeTxData = getVelodromeStakeTxData(amount, true);
|
|
487
493
|
break;
|
|
488
494
|
default:
|
|
489
495
|
throw new Error("dapp not supported");
|
|
@@ -526,7 +532,7 @@ export class Pool {
|
|
|
526
532
|
}
|
|
527
533
|
|
|
528
534
|
/**
|
|
529
|
-
* Unstake liquidity pool tokens from gauge
|
|
535
|
+
* Unstake liquidity pool tokens from Velodrome or Balancer gauge
|
|
530
536
|
* @param {string} gauge Gauge contract address
|
|
531
537
|
* @param {BigNumber | string} amount Amount of liquidity pool tokens
|
|
532
538
|
* @param {any} options Transaction options
|
|
@@ -1051,7 +1057,11 @@ export class Pool {
|
|
|
1051
1057
|
break;
|
|
1052
1058
|
case Dapp.VELODROME:
|
|
1053
1059
|
contractAddress = tokenId;
|
|
1054
|
-
txData = getVelodromeClaimTxData(this, tokenId);
|
|
1060
|
+
txData = getVelodromeClaimTxData(this, tokenId, false);
|
|
1061
|
+
break;
|
|
1062
|
+
case Dapp.VELODROMEV2:
|
|
1063
|
+
contractAddress = tokenId;
|
|
1064
|
+
txData = getVelodromeClaimTxData(this, tokenId, true);
|
|
1055
1065
|
break;
|
|
1056
1066
|
default:
|
|
1057
1067
|
throw new Error("dapp not supported");
|
|
@@ -1162,6 +1172,69 @@ export class Pool {
|
|
|
1162
1172
|
return tx;
|
|
1163
1173
|
}
|
|
1164
1174
|
|
|
1175
|
+
/**
|
|
1176
|
+
* Add liquidity to Velodrome V2 pool
|
|
1177
|
+
* @param {string} assetA First asset
|
|
1178
|
+
* @param {string} assetB Second asset
|
|
1179
|
+
* @param {BigNumber | string} amountA Amount first asset
|
|
1180
|
+
* @param {BigNumber | string} amountB Amount second asset
|
|
1181
|
+
* @param { boolean } isStable Is stable pool
|
|
1182
|
+
* @param {any} options Transaction options
|
|
1183
|
+
* @returns {Promise<any>} Transaction
|
|
1184
|
+
*/
|
|
1185
|
+
async addLiquidityVelodromeV2(
|
|
1186
|
+
assetA: string,
|
|
1187
|
+
assetB: string,
|
|
1188
|
+
amountA: BigNumber | string,
|
|
1189
|
+
amountB: BigNumber | string,
|
|
1190
|
+
isStable: boolean,
|
|
1191
|
+
options: any = null
|
|
1192
|
+
): Promise<any> {
|
|
1193
|
+
const tx = await this.poolLogic.execTransaction(
|
|
1194
|
+
routerAddress[this.network][Dapp.VELODROMEV2],
|
|
1195
|
+
await getVelodromeAddLiquidityTxData(
|
|
1196
|
+
this,
|
|
1197
|
+
assetA,
|
|
1198
|
+
assetB,
|
|
1199
|
+
amountA,
|
|
1200
|
+
amountB,
|
|
1201
|
+
isStable
|
|
1202
|
+
),
|
|
1203
|
+
options
|
|
1204
|
+
);
|
|
1205
|
+
return tx;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Remove liquidity from Velodrome V2 pool
|
|
1210
|
+
* @param {string} assetA First asset
|
|
1211
|
+
* @param {string} assetB Second asset
|
|
1212
|
+
* @param {BigNumber | string} amount Amount of LP tokens
|
|
1213
|
+
* @param { boolean } isStable Is stable pool
|
|
1214
|
+
* @param {any} options Transaction options
|
|
1215
|
+
* @returns {Promise<any>} Transaction
|
|
1216
|
+
*/
|
|
1217
|
+
async removeLiquidityVelodromeV2(
|
|
1218
|
+
assetA: string,
|
|
1219
|
+
assetB: string,
|
|
1220
|
+
amount: BigNumber | string,
|
|
1221
|
+
isStable: boolean,
|
|
1222
|
+
options: any = null
|
|
1223
|
+
): Promise<any> {
|
|
1224
|
+
const tx = await this.poolLogic.execTransaction(
|
|
1225
|
+
routerAddress[this.network][Dapp.VELODROMEV2],
|
|
1226
|
+
await getVelodromeRemoveLiquidityTxData(
|
|
1227
|
+
this,
|
|
1228
|
+
assetA,
|
|
1229
|
+
assetB,
|
|
1230
|
+
amount,
|
|
1231
|
+
isStable
|
|
1232
|
+
),
|
|
1233
|
+
options
|
|
1234
|
+
);
|
|
1235
|
+
return tx;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1165
1238
|
/**
|
|
1166
1239
|
* Trade options on lyra
|
|
1167
1240
|
* @param {LyraOptionMarket} market Underlying market e.g. eth
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// see https://stackoverflow.com/a/41102306
|
|
2
|
+
const CAN_SET_PROTOTYPE = "setPrototypeOf" in Object;
|
|
3
|
+
|
|
4
|
+
export class ApiError extends Error {
|
|
5
|
+
public constructor(message?: string) {
|
|
6
|
+
super(message ?? "Api request failed");
|
|
7
|
+
this.name = this.constructor.name;
|
|
8
|
+
if (CAN_SET_PROTOTYPE) Object.setPrototypeOf(this, new.target.prototype);
|
|
9
|
+
}
|
|
10
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
import { ApiError, ethers } from "../..";
|
|
4
|
+
import { networkChainIdMap } from "../../config";
|
|
5
|
+
import { Pool } from "../../entities";
|
|
6
|
+
|
|
7
|
+
const oneInchBaseUrl = "https://api.1inch.dev/swap/v5.2/";
|
|
8
|
+
|
|
9
|
+
export async function getOneInchSwapTxData(
|
|
10
|
+
pool: Pool,
|
|
11
|
+
assetFrom: string,
|
|
12
|
+
assetTo: string,
|
|
13
|
+
amountIn: ethers.BigNumber | string,
|
|
14
|
+
slippage: number
|
|
15
|
+
): Promise<string> {
|
|
16
|
+
if (!process.env.ONEINCH_API_KEY)
|
|
17
|
+
throw new Error("ONEINCH_API_KEY not configured in .env file");
|
|
18
|
+
|
|
19
|
+
const chainId = networkChainIdMap[pool.network];
|
|
20
|
+
const apiUrl = `${oneInchBaseUrl}${chainId}/swap?src=${assetFrom}&dst=${assetTo}&amount=${amountIn.toString()}&from=${
|
|
21
|
+
pool.address
|
|
22
|
+
}&slippage=${slippage.toString()}&disableEstimate=true`;
|
|
23
|
+
try {
|
|
24
|
+
const response = await axios.get(apiUrl, {
|
|
25
|
+
headers: {
|
|
26
|
+
Authorization: `Bearer ${process.env.ONEINCH_API_KEY}`
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return response.data.tx.data;
|
|
30
|
+
} catch (e) {
|
|
31
|
+
throw new ApiError("Swap api request of 1inch failed");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -1,31 +1,44 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { BigNumber, ethers } from "ethers";
|
|
3
|
-
import
|
|
3
|
+
import IVelodromeGaugeV1 from "../../abi/IVelodromeGauge.json";
|
|
4
|
+
import IVelodromeGaugeV2 from "../../abi/IVelodromeGaugeV2.json";
|
|
4
5
|
import { Pool } from "../../entities";
|
|
5
|
-
import { Transaction } from "../../types";
|
|
6
6
|
import { call } from "../../utils/contract";
|
|
7
|
-
const
|
|
7
|
+
const iVelodromeGaugeV1 = new ethers.utils.Interface(IVelodromeGaugeV1.abi);
|
|
8
|
+
const iVelodromeGaugeV2 = new ethers.utils.Interface(IVelodromeGaugeV2.abi);
|
|
8
9
|
|
|
9
|
-
export function getVelodromeStakeTxData(
|
|
10
|
-
|
|
10
|
+
export function getVelodromeStakeTxData(
|
|
11
|
+
amount: BigNumber | string,
|
|
12
|
+
v2: boolean
|
|
13
|
+
): any {
|
|
14
|
+
const depositParams: [string, unknown[]] = v2
|
|
15
|
+
? ["deposit(uint256)", [amount]]
|
|
16
|
+
: ["deposit", [amount, 0]];
|
|
17
|
+
const iVelodromeGauge = v2 ? iVelodromeGaugeV2 : iVelodromeGaugeV1;
|
|
18
|
+
return iVelodromeGauge.encodeFunctionData(...depositParams);
|
|
11
19
|
}
|
|
12
20
|
|
|
13
21
|
export async function getVelodromeClaimTxData(
|
|
14
22
|
pool: Pool,
|
|
15
|
-
gauge: string
|
|
23
|
+
gauge: string,
|
|
24
|
+
v2: boolean
|
|
16
25
|
): Promise<any> {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
[
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
if (v2) {
|
|
27
|
+
return iVelodromeGaugeV2.encodeFunctionData("getReward", [pool.address]);
|
|
28
|
+
} else {
|
|
29
|
+
const rewardAssetCount = await call(pool.signer, IVelodromeGaugeV1.abi, [
|
|
30
|
+
gauge,
|
|
31
|
+
"rewardsListLength",
|
|
32
|
+
[]
|
|
33
|
+
]);
|
|
34
|
+
const rewardAssets = await Promise.all(
|
|
35
|
+
Array.from(Array(rewardAssetCount.toNumber()).keys()).map(e =>
|
|
36
|
+
call(pool.signer, IVelodromeGaugeV1.abi, [gauge, "rewards", [e]])
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
return iVelodromeGaugeV1.encodeFunctionData("getReward", [
|
|
40
|
+
pool.address,
|
|
41
|
+
rewardAssets
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
31
44
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { BigNumber } from "ethers";
|
|
3
|
+
import { Network } from "../../types";
|
|
4
|
+
import { ApiError } from "../../errors";
|
|
5
|
+
|
|
6
|
+
// slippage of 0x is different from that of 1Inch
|
|
7
|
+
// in 0x, e.g. 0.03 for 3% slippage allowed
|
|
8
|
+
// 1inch slippage 0.5% represented by 0.5
|
|
9
|
+
// 0x slippage 0.5% represented by 0.005
|
|
10
|
+
const getZeroExSlippage = (slippage: number): number => {
|
|
11
|
+
return Number(slippage) / 100;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const getZeroExTradeTxData = async (
|
|
15
|
+
network: Network,
|
|
16
|
+
assetFrom: string,
|
|
17
|
+
assetTo: string,
|
|
18
|
+
amountIn: BigNumber | string,
|
|
19
|
+
slippage = 0.5,
|
|
20
|
+
takerAddress: string
|
|
21
|
+
): Promise<string> => {
|
|
22
|
+
if (!process.env.ZEROEX_API_KEY)
|
|
23
|
+
throw new Error("ZEROEX_API_KEY not configured in .env file");
|
|
24
|
+
try {
|
|
25
|
+
const slippagePercentage = getZeroExSlippage(slippage);
|
|
26
|
+
const params = {
|
|
27
|
+
buyToken: assetTo,
|
|
28
|
+
sellToken: assetFrom,
|
|
29
|
+
sellAmount: amountIn.toString(),
|
|
30
|
+
// necessary to skip quote validation is that in which the takerAddress refers to a smart contract
|
|
31
|
+
skipValidation: true,
|
|
32
|
+
// Used to enable RFQ-T liquidity
|
|
33
|
+
intentOnFilling: true,
|
|
34
|
+
takerAddress,
|
|
35
|
+
slippagePercentage
|
|
36
|
+
// excludedSourcesParam
|
|
37
|
+
};
|
|
38
|
+
const response = await axios.get(
|
|
39
|
+
`https://${network}.api.0x.org/swap/v1/quote`,
|
|
40
|
+
{
|
|
41
|
+
params,
|
|
42
|
+
headers: {
|
|
43
|
+
"0x-api-key": process.env.ZEROEX_API_KEY
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return response.data.data;
|
|
49
|
+
} catch (e) {
|
|
50
|
+
throw new ApiError("Swap api request of 0x failed");
|
|
51
|
+
}
|
|
52
|
+
};
|
package/src/test/oneInch.test.ts
CHANGED
|
@@ -3,44 +3,52 @@ import { Dhedge, Pool } from "..";
|
|
|
3
3
|
import { routerAddress } from "../config";
|
|
4
4
|
import { Dapp, Network } from "../types";
|
|
5
5
|
import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
|
|
6
|
+
import { TestingRunParams, testingHelper } from "./utils/testingHelper";
|
|
6
7
|
import { allowanceDelta, balanceDelta } from "./utils/token";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
const testOneInch = ({ wallet, network }: TestingRunParams) => {
|
|
10
|
+
const USDC = CONTRACT_ADDRESS[network].USDC;
|
|
11
|
+
const WETH = CONTRACT_ADDRESS[network].WETH;
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const USDC = CONTRACT_ADDRESS[network].USDC;
|
|
14
|
-
const WETH = CONTRACT_ADDRESS[network].WETH;
|
|
13
|
+
let dhedge: Dhedge;
|
|
14
|
+
let pool: Pool;
|
|
15
|
+
jest.setTimeout(100000);
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
describe(`pool on ${network}`, () => {
|
|
18
|
+
beforeAll(async () => {
|
|
19
|
+
dhedge = new Dhedge(wallet, network);
|
|
20
|
+
pool = await dhedge.loadPool(TEST_POOL[network]);
|
|
21
|
+
});
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
it("approves unlimited USDC on 1Inch", async () => {
|
|
24
|
+
await pool.approve(Dapp.ONEINCH, USDC, MAX_AMOUNT);
|
|
25
|
+
const usdcAllowanceDelta = await allowanceDelta(
|
|
26
|
+
pool.address,
|
|
27
|
+
USDC,
|
|
28
|
+
routerAddress[network]["1inch"]!,
|
|
29
|
+
pool.signer
|
|
30
|
+
);
|
|
31
|
+
await expect(usdcAllowanceDelta.gt(0));
|
|
32
|
+
});
|
|
25
33
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
it("trades 2 USDC into WETH on 1Inch", async () => {
|
|
35
|
+
await pool.trade(Dapp.ONEINCH, USDC, WETH, "2000000", 0.5);
|
|
36
|
+
const wethBalanceDelta = await balanceDelta(
|
|
37
|
+
pool.address,
|
|
38
|
+
WETH,
|
|
39
|
+
pool.signer
|
|
40
|
+
);
|
|
41
|
+
expect(wethBalanceDelta.gt(0));
|
|
42
|
+
});
|
|
35
43
|
});
|
|
44
|
+
};
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
});
|
|
46
|
+
testingHelper({
|
|
47
|
+
network: Network.OPTIMISM,
|
|
48
|
+
testingRun: testOneInch
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
testingHelper({
|
|
52
|
+
network: Network.POLYGON,
|
|
53
|
+
testingRun: testOneInch
|
|
46
54
|
});
|
package/src/test/txOptions.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Network } from "../types";
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
6
|
export const getTxOptions = async (network: Network): Promise<any> => {
|
|
7
7
|
if (network === Network.POLYGON) {
|
|
8
|
-
const result = await axios("https://gasstation
|
|
8
|
+
const result = await axios("https://gasstation.polygon.technology/v2");
|
|
9
9
|
return {
|
|
10
10
|
gasLimit: "3000000",
|
|
11
11
|
maxPriorityFeePerGas: new BigNumber(result.data.fast.maxPriorityFee)
|