@dhedge/v2-sdk 1.8.3 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhedge/v2-sdk",
3
- "version": "1.8.3",
3
+ "version": "1.9.1",
4
4
  "license": "MIT",
5
5
  "description": "🛠 An SDK for building applications on top of dHEDGE V2",
6
6
  "main": "dist/index.js",
@@ -21,7 +21,8 @@
21
21
  "size": "size-limit",
22
22
  "analyze": "size-limit --why",
23
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)"
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)"
25
26
  },
26
27
  "husky": {
27
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
@@ -15,7 +15,8 @@ export const factoryAddress: AddressNetworkMap = {
15
15
  [Network.POLYGON]: process.env.STAGING_CONTRACTS
16
16
  ? "0xDd87eCdB10cFF7004276AAbAbd30e7a08F69bb53"
17
17
  : "0xfdc7b8bFe0DD3513Cc669bB8d601Cb83e2F69cB0",
18
- [Network.OPTIMISM]: "0x5e61a079A178f0E5784107a4963baAe0c5a680c6"
18
+ [Network.OPTIMISM]: "0x5e61a079A178f0E5784107a4963baAe0c5a680c6",
19
+ [Network.ARBITRUM]: "0xfffb5fb14606eb3a548c113026355020ddf27535"
19
20
  };
20
21
 
21
22
  export const routerAddress: AddressDappNetworkMap = {
@@ -28,7 +29,8 @@ export const routerAddress: AddressDappNetworkMap = {
28
29
  [Dapp.BALANCER]: "0xBA12222222228d8Ba445958a75a0704d566BF2C8",
29
30
  [Dapp.UNISWAPV3]: "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
30
31
  [Dapp.ARRAKIS]: "0xc73fb100a995b33f9fa181d420f4c8d74506df66",
31
- [Dapp.TOROS]: "0xB2F1498983bf9c9442c35F772e6C1AdE66a8DeDE"
32
+ [Dapp.TOROS]: "0xB2F1498983bf9c9442c35F772e6C1AdE66a8DeDE",
33
+ [Dapp.ZEROEX]: "0xdef1c0ded9bec7f1a1670819833240f027b25eff"
32
34
  },
33
35
  [Network.OPTIMISM]: {
34
36
  [Dapp.UNISWAPV3]: "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
@@ -37,8 +39,16 @@ export const routerAddress: AddressDappNetworkMap = {
37
39
  [Dapp.ONEINCH]: "0x1111111254EEB25477B68fb85Ed929f73A960582",
38
40
  [Dapp.TOROS]: "0x3988513793bCE39f0167064A9F7fC3617FaF35AB",
39
41
  [Dapp.VELODROME]: "0x9c12939390052919aF3155f41Bf4160Fd3666A6f",
42
+ [Dapp.VELODROMEV2]: "0xa062ae8a9c5e11aaa026fc2670b0d65ccc8b2858",
40
43
  [Dapp.LYRA]: "0xCCE7819d65f348c64B7Beb205BA367b3fE33763B",
41
- [Dapp.ARRAKIS]: "0x9ce88a56d120300061593eF7AD074A1B710094d5"
44
+ [Dapp.ARRAKIS]: "0x9ce88a56d120300061593eF7AD074A1B710094d5",
45
+ [Dapp.ZEROEX]: "0xdef1abe32c034e558cdd535791643c58a13acc10"
46
+ },
47
+ [Network.ARBITRUM]: {
48
+ [Dapp.ONEINCH]: "0x1111111254EEB25477B68fb85Ed929f73A960582",
49
+ [Dapp.UNISWAPV3]: "0xe592427a0aece92de3edee1f18e0157c05861564",
50
+ [Dapp.AAVEV3]: "0x794a61358D6845594F94dc1DB02A252b5b4814aD",
51
+ [Dapp.BALANCER]: "0xBA12222222228d8Ba445958a75a0704d566BF2C8"
42
52
  }
43
53
  };
44
54
 
@@ -47,7 +57,8 @@ export const dappFactoryAddress: AddressDappNetworkMap = {
47
57
  [Dapp.SUSHISWAP]: "0xc35DADB65012eC5796536bD9864eD8773aBc74C4",
48
58
  [Dapp.QUICKSWAP]: "0x5757371414417b8C6CAad45bAeF941aBc7d3Ab32"
49
59
  },
50
- [Network.OPTIMISM]: {}
60
+ [Network.OPTIMISM]: {},
61
+ [Network.ARBITRUM]: {}
51
62
  };
52
63
 
53
64
  export const stakingAddress: AddressDappNetworkMap = {
@@ -57,7 +68,8 @@ export const stakingAddress: AddressDappNetworkMap = {
57
68
  [Dapp.AAVE]: "0x357D51124f59836DeD84c8a1730D72B749d8BC23",
58
69
  [Dapp.AAVEV3]: "0x929EC64c34a17401F460460D4B9390518E5B473e"
59
70
  },
60
- [Network.OPTIMISM]: {}
71
+ [Network.OPTIMISM]: {},
72
+ [Network.ARBITRUM]: {}
61
73
  };
62
74
 
63
75
  export const aaveAddressProvider: AddressDappNetworkMap = {
@@ -67,27 +79,34 @@ export const aaveAddressProvider: AddressDappNetworkMap = {
67
79
  },
68
80
  [Network.OPTIMISM]: {
69
81
  [Dapp.AAVEV3]: "0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb"
82
+ },
83
+ [Network.ARBITRUM]: {
84
+ [Dapp.AAVEV3]: "0xa97684ead0e402dc232d5a977953df7ecbab3cdb"
70
85
  }
71
86
  };
72
87
  export const nonfungiblePositionManagerAddress: AddressNetworkMap = {
73
88
  [Network.POLYGON]: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
74
- [Network.OPTIMISM]: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88"
89
+ [Network.OPTIMISM]: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
90
+ [Network.ARBITRUM]: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88"
75
91
  };
76
92
 
77
93
  export const networkChainIdMap: NetworkChainIdMap = {
78
94
  [Network.POLYGON]: 137,
79
- [Network.OPTIMISM]: 10
95
+ [Network.OPTIMISM]: 10,
96
+ [Network.ARBITRUM]: 42161
80
97
  };
81
98
 
82
99
  export const balancerSubgraph: AddressNetworkMap = {
83
100
  [Network.POLYGON]:
84
101
  "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-polygon-v2",
85
- [Network.OPTIMISM]: ""
102
+ [Network.OPTIMISM]: "",
103
+ [Network.ARBITRUM]: ""
86
104
  };
87
105
 
88
106
  export const multiCallAddress: AddressNetworkMap = {
89
107
  [Network.POLYGON]: "0x275617327c958bD06b5D6b871E7f491D76113dd8",
90
- [Network.OPTIMISM]: ""
108
+ [Network.OPTIMISM]: "",
109
+ [Network.ARBITRUM]: ""
91
110
  };
92
111
 
93
112
  export const lyraNetworkMap: LyraNetworkMap = {
@@ -59,6 +59,9 @@ import {
59
59
  getFuturesChangePositionTxData,
60
60
  getFuturesChangeMarginTxData
61
61
  } from "../services/futures";
62
+ import { getFuturesCancelOrderTxData } from "../services/futures/trade";
63
+ import { getZeroExTradeTxData } from "../services/zeroEx/zeroExTrade";
64
+ import { ApiError } from "../errors";
62
65
 
63
66
  export class Pool {
64
67
  public readonly poolLogic: Contract;
@@ -285,16 +288,35 @@ export class Pool {
285
288
  ): Promise<any> {
286
289
  let swapTxData: string;
287
290
  switch (dapp) {
291
+ case Dapp.ZEROEX:
292
+ swapTxData = await getZeroExTradeTxData(
293
+ this.network,
294
+ assetFrom,
295
+ assetTo,
296
+ amountIn,
297
+ slippage,
298
+ this.address
299
+ );
300
+ break;
288
301
  case Dapp.ONEINCH:
289
302
  const chainId = networkChainIdMap[this.network];
290
303
  const protocols = await getOneInchProtocols(chainId);
291
- const apiUrl = `https://api.1inch.exchange/v5.0/${chainId}/swap?fromTokenAddress=${assetFrom}&toTokenAddress=${assetTo}&amount=${amountIn.toString()}&fromAddress=${
304
+ if (!process.env.ONEINCH_API_URL)
305
+ throw new Error("ONEINCH_API_URL not configured in .env file");
306
+ const apiUrl = `${
307
+ process.env.ONEINCH_API_URL
308
+ }/${chainId}/swap?fromTokenAddress=${assetFrom}&toTokenAddress=${assetTo}&amount=${amountIn.toString()}&fromAddress=${
292
309
  this.address
293
310
  }&destReceiver=${
294
311
  this.address
295
312
  }&slippage=${slippage.toString()}&disableEstimate=true${protocols}`;
296
- const response = await axios.get(apiUrl);
297
- swapTxData = response.data.tx.data;
313
+ try {
314
+ const response = await axios.get(apiUrl);
315
+ swapTxData = response.data.tx.data;
316
+ } catch (e) {
317
+ throw new ApiError("Swap api request of 1inch failed");
318
+ }
319
+
298
320
  break;
299
321
  case Dapp.BALANCER:
300
322
  swapTxData = await this.utils.getBalancerSwapTx(
@@ -478,7 +500,10 @@ export class Pool {
478
500
  ]);
479
501
  break;
480
502
  case Dapp.VELODROME:
481
- stakeTxData = getVelodromeStakeTxData(amount);
503
+ stakeTxData = getVelodromeStakeTxData(amount, false);
504
+ break;
505
+ case Dapp.VELODROMEV2:
506
+ stakeTxData = getVelodromeStakeTxData(amount, true);
482
507
  break;
483
508
  default:
484
509
  throw new Error("dapp not supported");
@@ -521,7 +546,7 @@ export class Pool {
521
546
  }
522
547
 
523
548
  /**
524
- * Unstake liquidity pool tokens from gauge contract
549
+ * Unstake liquidity pool tokens from Velodrome or Balancer gauge
525
550
  * @param {string} gauge Gauge contract address
526
551
  * @param {BigNumber | string} amount Amount of liquidity pool tokens
527
552
  * @param {any} options Transaction options
@@ -1046,7 +1071,11 @@ export class Pool {
1046
1071
  break;
1047
1072
  case Dapp.VELODROME:
1048
1073
  contractAddress = tokenId;
1049
- txData = getVelodromeClaimTxData(this, tokenId);
1074
+ txData = getVelodromeClaimTxData(this, tokenId, false);
1075
+ break;
1076
+ case Dapp.VELODROMEV2:
1077
+ contractAddress = tokenId;
1078
+ txData = getVelodromeClaimTxData(this, tokenId, true);
1050
1079
  break;
1051
1080
  default:
1052
1081
  throw new Error("dapp not supported");
@@ -1157,6 +1186,69 @@ export class Pool {
1157
1186
  return tx;
1158
1187
  }
1159
1188
 
1189
+ /**
1190
+ * Add liquidity to Velodrome V2 pool
1191
+ * @param {string} assetA First asset
1192
+ * @param {string} assetB Second asset
1193
+ * @param {BigNumber | string} amountA Amount first asset
1194
+ * @param {BigNumber | string} amountB Amount second asset
1195
+ * @param { boolean } isStable Is stable pool
1196
+ * @param {any} options Transaction options
1197
+ * @returns {Promise<any>} Transaction
1198
+ */
1199
+ async addLiquidityVelodromeV2(
1200
+ assetA: string,
1201
+ assetB: string,
1202
+ amountA: BigNumber | string,
1203
+ amountB: BigNumber | string,
1204
+ isStable: boolean,
1205
+ options: any = null
1206
+ ): Promise<any> {
1207
+ const tx = await this.poolLogic.execTransaction(
1208
+ routerAddress[this.network][Dapp.VELODROMEV2],
1209
+ await getVelodromeAddLiquidityTxData(
1210
+ this,
1211
+ assetA,
1212
+ assetB,
1213
+ amountA,
1214
+ amountB,
1215
+ isStable
1216
+ ),
1217
+ options
1218
+ );
1219
+ return tx;
1220
+ }
1221
+
1222
+ /**
1223
+ * Remove liquidity from Velodrome V2 pool
1224
+ * @param {string} assetA First asset
1225
+ * @param {string} assetB Second asset
1226
+ * @param {BigNumber | string} amount Amount of LP tokens
1227
+ * @param { boolean } isStable Is stable pool
1228
+ * @param {any} options Transaction options
1229
+ * @returns {Promise<any>} Transaction
1230
+ */
1231
+ async removeLiquidityVelodromeV2(
1232
+ assetA: string,
1233
+ assetB: string,
1234
+ amount: BigNumber | string,
1235
+ isStable: boolean,
1236
+ options: any = null
1237
+ ): Promise<any> {
1238
+ const tx = await this.poolLogic.execTransaction(
1239
+ routerAddress[this.network][Dapp.VELODROMEV2],
1240
+ await getVelodromeRemoveLiquidityTxData(
1241
+ this,
1242
+ assetA,
1243
+ assetB,
1244
+ amount,
1245
+ isStable
1246
+ ),
1247
+ options
1248
+ );
1249
+ return tx;
1250
+ }
1251
+
1160
1252
  /**
1161
1253
  * Trade options on lyra
1162
1254
  * @param {LyraOptionMarket} market Underlying market e.g. eth
@@ -1251,4 +1343,16 @@ export class Pool {
1251
1343
  const tx = await this.poolLogic.execTransaction(market, txData, options);
1252
1344
  return tx;
1253
1345
  }
1346
+
1347
+ /** Cancels an open oder on Synthetix futures market
1348
+ *
1349
+ * @param {string} market Address of futures market
1350
+ * @param {any} options Transaction options
1351
+ * @returns {Promise<any>} Transaction
1352
+ */
1353
+ async cancelFuturesOrder(market: string, options: any = null): Promise<any> {
1354
+ const txData = await getFuturesCancelOrderTxData(this);
1355
+ const tx = await this.poolLogic.execTransaction(market, txData, options);
1356
+ return tx;
1357
+ }
1254
1358
  }
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
@@ -1,3 +1,4 @@
1
1
  export * from "./entities";
2
2
  export * from "./types";
3
+ export * from "./errors";
3
4
  export { ethers } from "ethers";
@@ -24,3 +24,9 @@ export async function getFuturesChangePositionTxData(
24
24
  ethers.utils.formatBytes32String(FUTURES_TRACKING)
25
25
  ]);
26
26
  }
27
+
28
+ export async function getFuturesCancelOrderTxData(pool: Pool): Promise<string> {
29
+ return new ethers.utils.Interface(
30
+ ISynthetixFuturesMarketV2.abi
31
+ ).encodeFunctionData("cancelOffchainDelayedOrder", [pool.address]);
32
+ }
@@ -1,31 +1,44 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { BigNumber, ethers } from "ethers";
3
- import IVelodromeGauge from "../../abi/IVelodromeGauge.json";
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 iVelodromeGauge = new ethers.utils.Interface(IVelodromeGauge.abi);
7
+ const iVelodromeGaugeV1 = new ethers.utils.Interface(IVelodromeGaugeV1.abi);
8
+ const iVelodromeGaugeV2 = new ethers.utils.Interface(IVelodromeGaugeV2.abi);
8
9
 
9
- export function getVelodromeStakeTxData(amount: BigNumber | string): any {
10
- return iVelodromeGauge.encodeFunctionData(Transaction.DEPOSIT, [amount, "0"]);
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
- const rewardAssetCount = await call(pool.signer, IVelodromeGauge.abi, [
18
- gauge,
19
- "rewardsListLength",
20
- []
21
- ]);
22
- const rewardAssets = await Promise.all(
23
- Array.from(Array(rewardAssetCount.toNumber()).keys()).map(e =>
24
- call(pool.signer, IVelodromeGauge.abi, [gauge, "rewards", [e]])
25
- )
26
- );
27
- return iVelodromeGauge.encodeFunctionData("getReward", [
28
- pool.address,
29
- rewardAssets
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
+ };