@curvefi/api 2.0.0 → 2.2.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.
@@ -3,33 +3,7 @@ import { Contract as MulticallContract, Provider as MulticallProvider } from "et
3
3
  export interface IDict<T> {
4
4
  [index: string]: T;
5
5
  }
6
- export interface ICurve {
7
- provider: ethers.providers.Web3Provider | ethers.providers.JsonRpcProvider;
8
- multicallProvider: MulticallProvider;
9
- signer: ethers.Signer | null;
10
- signerAddress: string;
11
- chainId: number;
12
- contracts: {
13
- [index: string]: {
14
- contract: Contract;
15
- multicallContract: MulticallContract;
16
- };
17
- };
18
- feeData: {
19
- gasPrice?: number;
20
- maxFeePerGas?: number;
21
- maxPriorityFeePerGas?: number;
22
- };
23
- constantOptions: {
24
- gasLimit: number;
25
- };
26
- options: {
27
- gasPrice?: number | ethers.BigNumber;
28
- maxFeePerGas?: number | ethers.BigNumber;
29
- maxPriorityFeePerGas?: number | ethers.BigNumber;
30
- };
31
- constants: IDict<any>;
32
- }
6
+ export declare type INetworkName = "ethereum" | "polygon" | "avalanche";
33
7
  export declare type REFERENCE_ASSET = 'USD' | 'EUR' | 'BTC' | 'ETH' | 'LINK' | 'CRYPTO' | 'OTHER';
34
8
  export interface IPoolData {
35
9
  name: string;
@@ -63,6 +37,42 @@ export interface IPoolData {
63
37
  deposit_abi?: any;
64
38
  sCurveRewards_abi?: any;
65
39
  }
40
+ export interface ICurve {
41
+ provider: ethers.providers.Web3Provider | ethers.providers.JsonRpcProvider;
42
+ multicallProvider: MulticallProvider;
43
+ signer: ethers.Signer | null;
44
+ signerAddress: string;
45
+ chainId: number;
46
+ contracts: {
47
+ [index: string]: {
48
+ contract: Contract;
49
+ multicallContract: MulticallContract;
50
+ };
51
+ };
52
+ feeData: {
53
+ gasPrice?: number;
54
+ maxFeePerGas?: number;
55
+ maxPriorityFeePerGas?: number;
56
+ };
57
+ constantOptions: {
58
+ gasLimit: number;
59
+ };
60
+ options: {
61
+ gasPrice?: number | ethers.BigNumber;
62
+ maxFeePerGas?: number | ethers.BigNumber;
63
+ maxPriorityFeePerGas?: number | ethers.BigNumber;
64
+ };
65
+ constants: {
66
+ NETWORK_NAME: INetworkName;
67
+ ALIASES: IDict<string>;
68
+ POOLS_DATA: IDict<IPoolData>;
69
+ FACTORY_POOLS_DATA: IDict<IPoolData>;
70
+ CRYPTO_FACTORY_POOLS_DATA: IDict<IPoolData>;
71
+ COINS: IDict<string>;
72
+ DECIMALS: IDict<number>;
73
+ GAUGES: string[];
74
+ };
75
+ }
66
76
  export interface ICoinFromPoolDataApi {
67
77
  address: string;
68
78
  symbol: string;
@@ -9,6 +9,7 @@ export declare class PoolTemplate {
9
9
  lpToken: string;
10
10
  gauge: string;
11
11
  zap: string | null;
12
+ sRewardContract: string | null;
12
13
  rewardContract: string | null;
13
14
  isPlain: boolean;
14
15
  isLending: boolean;
@@ -184,6 +185,7 @@ export declare class PoolTemplate {
184
185
  private walletAllCoinBalances;
185
186
  private _swapExpected;
186
187
  swapExpected(inputCoin: string | number, outputCoin: string | number, amount: number | string): Promise<string>;
188
+ swapPriceImpact(inputCoin: string | number, outputCoin: string | number, amount: number | string): Promise<string>;
187
189
  private _swapContractAddress;
188
190
  swapIsApproved(inputCoin: string | number, amount: number | string): Promise<boolean>;
189
191
  private swapApproveEstimateGas;
@@ -192,6 +194,7 @@ export declare class PoolTemplate {
192
194
  swap(inputCoin: string | number, outputCoin: string | number, amount: number | string, slippage?: number): Promise<string>;
193
195
  private _swapWrappedExpected;
194
196
  swapWrappedExpected(inputCoin: string | number, outputCoin: string | number, amount: number | string): Promise<string>;
197
+ swapWrappedPriceImpact(inputCoin: string | number, outputCoin: string | number, amount: number | string): Promise<string>;
195
198
  swapWrappedIsApproved(inputCoin: string | number, amount: number | string): Promise<boolean>;
196
199
  private swapWrappedApproveEstimateGas;
197
200
  swapWrappedApprove(inputCoin: string | number, amount: number | string): Promise<string[]>;
@@ -55,9 +55,13 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
55
55
  }
56
56
  return to.concat(ar || Array.prototype.slice.call(from));
57
57
  };
58
+ var __importDefault = (this && this.__importDefault) || function (mod) {
59
+ return (mod && mod.__esModule) ? mod : { "default": mod };
60
+ };
58
61
  Object.defineProperty(exports, "__esModule", { value: true });
59
62
  exports.PoolTemplate = void 0;
60
63
  var ethers_1 = require("ethers");
64
+ var bignumber_js_1 = __importDefault(require("bignumber.js"));
61
65
  var external_api_1 = require("../external-api");
62
66
  var utils_1 = require("../utils");
63
67
  var curve_1 = require("../curve");
@@ -115,7 +119,7 @@ var PoolTemplate = /** @class */ (function () {
115
119
  switch (_c.label) {
116
120
  case 0:
117
121
  if (!useApi) return [3 /*break*/, 2];
118
- network = curve_1.curve.chainId === 137 ? "polygon" : "ethereum";
122
+ network = curve_1.curve.constants.NETWORK_NAME;
119
123
  poolType = !this.isFactory && !this.isCrypto ? "main" :
120
124
  !this.isFactory ? "crypto" :
121
125
  !(this.isCrypto && this.isFactory) ? "factory" :
@@ -154,7 +158,7 @@ var PoolTemplate = /** @class */ (function () {
154
158
  return __generator(this, function (_a) {
155
159
  switch (_a.label) {
156
160
  case 0:
157
- network = curve_1.curve.chainId === 137 ? "polygon" : "ethereum";
161
+ network = curve_1.curve.constants.NETWORK_NAME;
158
162
  return [4 /*yield*/, (0, external_api_1._getSubgraphData)(network)];
159
163
  case 1:
160
164
  poolsData = (_a.sent());
@@ -171,7 +175,7 @@ var PoolTemplate = /** @class */ (function () {
171
175
  return __generator(this, function (_a) {
172
176
  switch (_a.label) {
173
177
  case 0:
174
- network = curve_1.curve.chainId === 137 ? "polygon" : "ethereum";
178
+ network = curve_1.curve.constants.NETWORK_NAME;
175
179
  return [4 /*yield*/, (0, external_api_1._getSubgraphData)(network)];
176
180
  case 1:
177
181
  poolsData = (_a.sent());
@@ -192,7 +196,7 @@ var PoolTemplate = /** @class */ (function () {
192
196
  case 0:
193
197
  if (this.gauge === ethers_1.ethers.constants.AddressZero)
194
198
  throw Error("".concat(this.name, " doesn't have gauge"));
195
- if (curve_1.curve.chainId === 137)
199
+ if (curve_1.curve.chainId !== 1)
196
200
  throw Error("No such method on network with id ".concat(curve_1.curve.chainId, ". Use getRewardsApy instead"));
197
201
  gaugeContract = curve_1.curve.contracts[this.gauge].multicallContract;
198
202
  lpTokenContract = curve_1.curve.contracts[this.lpToken].multicallContract;
@@ -228,7 +232,7 @@ var PoolTemplate = /** @class */ (function () {
228
232
  return __generator(this, function (_k) {
229
233
  switch (_k.label) {
230
234
  case 0:
231
- if (!(curve_1.curve.chainId === 137)) return [3 /*break*/, 8];
235
+ if (![137, 43114].includes(curve_1.curve.chainId)) return [3 /*break*/, 8];
232
236
  apy = [];
233
237
  _i = 0, _a = this.rewardTokens;
234
238
  _k.label = 1;
@@ -263,7 +267,7 @@ var PoolTemplate = /** @class */ (function () {
263
267
  return [3 /*break*/, 1];
264
268
  case 7: return [2 /*return*/, apy];
265
269
  case 8:
266
- network = curve_1.curve.chainId === 137 ? "polygon" : "ethereum";
270
+ network = curve_1.curve.constants.NETWORK_NAME;
267
271
  promises = [
268
272
  (0, external_api_1._getMainPoolsGaugeRewards)(),
269
273
  (0, external_api_1._getPoolsFromApi)(network, "main"),
@@ -633,6 +637,7 @@ var PoolTemplate = /** @class */ (function () {
633
637
  this.lpToken = poolData.token_address;
634
638
  this.gauge = poolData.gauge_address;
635
639
  this.zap = poolData.deposit_address || null;
640
+ this.sRewardContract = poolData.sCurveRewards_address || null;
636
641
  this.rewardContract = poolData.reward_contract || null;
637
642
  this.isPlain = poolData.is_plain || false;
638
643
  this.isLending = poolData.is_lending || false;
@@ -1140,9 +1145,9 @@ var PoolTemplate = /** @class */ (function () {
1140
1145
  PoolTemplate.prototype.claimableRewards = function (address) {
1141
1146
  if (address === void 0) { address = ""; }
1142
1147
  return __awaiter(this, void 0, void 0, function () {
1143
- var gaugeContract, rewards, _i, _a, rewardToken, rewardTokenContract, symbol, decimals, method, amount, _c, _d, rewardToken, rewardTokenContract, symbol, decimals, amount, _e, _f;
1144
- return __generator(this, function (_g) {
1145
- switch (_g.label) {
1148
+ var gaugeContract, rewards, _i, _a, rewardToken, rewardTokenContract, symbol, decimals, method, amount, _c, _d, rewardToken, rewardTokenContract, symbol, decimals, _totalAmount, _claimedAmount;
1149
+ return __generator(this, function (_e) {
1150
+ switch (_e.label) {
1146
1151
  case 0:
1147
1152
  if (this.gauge === ethers_1.ethers.constants.AddressZero) {
1148
1153
  throw Error("claimableRewards method doesn't exist for pool ".concat(this.name, " (id: ").concat(this.name, "). There is no gauge"));
@@ -1154,53 +1159,55 @@ var PoolTemplate = /** @class */ (function () {
1154
1159
  rewards = [];
1155
1160
  if (!('claimable_reward(address,address)' in gaugeContract)) return [3 /*break*/, 7];
1156
1161
  _i = 0, _a = this.rewardTokens;
1157
- _g.label = 1;
1162
+ _e.label = 1;
1158
1163
  case 1:
1159
1164
  if (!(_i < _a.length)) return [3 /*break*/, 6];
1160
1165
  rewardToken = _a[_i];
1161
1166
  rewardTokenContract = curve_1.curve.contracts[rewardToken].contract;
1162
1167
  return [4 /*yield*/, rewardTokenContract.symbol()];
1163
1168
  case 2:
1164
- symbol = _g.sent();
1169
+ symbol = _e.sent();
1165
1170
  return [4 /*yield*/, rewardTokenContract.decimals()];
1166
1171
  case 3:
1167
- decimals = _g.sent();
1172
+ decimals = _e.sent();
1168
1173
  method = curve_1.curve.chainId === 1 ? "claimable_reward" : "claimable_reward_write";
1169
1174
  _d = (_c = ethers_1.ethers.utils).formatUnits;
1170
1175
  return [4 /*yield*/, gaugeContract[method](address, rewardToken, curve_1.curve.constantOptions)];
1171
1176
  case 4:
1172
- amount = _d.apply(_c, [_g.sent(), decimals]);
1177
+ amount = _d.apply(_c, [_e.sent(), decimals]);
1173
1178
  rewards.push({
1174
1179
  token: rewardToken,
1175
1180
  symbol: symbol,
1176
1181
  amount: amount,
1177
1182
  });
1178
- _g.label = 5;
1183
+ _e.label = 5;
1179
1184
  case 5:
1180
1185
  _i++;
1181
1186
  return [3 /*break*/, 1];
1182
- case 6: return [3 /*break*/, 11];
1187
+ case 6: return [3 /*break*/, 12];
1183
1188
  case 7:
1184
- if (!('claimable_reward(address)' in gaugeContract && this.rewardTokens.length > 0)) return [3 /*break*/, 11];
1189
+ if (!('claimable_reward(address)' in gaugeContract && this.rewardTokens.length > 0)) return [3 /*break*/, 12];
1185
1190
  rewardToken = this.rewardTokens[0];
1186
1191
  rewardTokenContract = curve_1.curve.contracts[rewardToken].contract;
1187
1192
  return [4 /*yield*/, rewardTokenContract.symbol()];
1188
1193
  case 8:
1189
- symbol = _g.sent();
1194
+ symbol = _e.sent();
1190
1195
  return [4 /*yield*/, rewardTokenContract.decimals()];
1191
1196
  case 9:
1192
- decimals = _g.sent();
1193
- _f = (_e = ethers_1.ethers.utils).formatUnits;
1197
+ decimals = _e.sent();
1194
1198
  return [4 /*yield*/, gaugeContract.claimable_reward(address, curve_1.curve.constantOptions)];
1195
1199
  case 10:
1196
- amount = _f.apply(_e, [_g.sent(), decimals]);
1200
+ _totalAmount = _e.sent();
1201
+ return [4 /*yield*/, gaugeContract.claimed_rewards_for(address, curve_1.curve.constantOptions)];
1202
+ case 11:
1203
+ _claimedAmount = _e.sent();
1197
1204
  rewards.push({
1198
1205
  token: rewardToken,
1199
1206
  symbol: symbol,
1200
- amount: amount,
1207
+ amount: ethers_1.ethers.utils.formatUnits(_totalAmount.sub(_claimedAmount), decimals),
1201
1208
  });
1202
- _g.label = 11;
1203
- case 11: return [2 /*return*/, rewards];
1209
+ _e.label = 12;
1210
+ case 12: return [2 /*return*/, rewards];
1204
1211
  }
1205
1212
  });
1206
1213
  });
@@ -2165,8 +2172,44 @@ var PoolTemplate = /** @class */ (function () {
2165
2172
  });
2166
2173
  });
2167
2174
  };
2175
+ PoolTemplate.prototype.swapPriceImpact = function (inputCoin, outputCoin, amount) {
2176
+ return __awaiter(this, void 0, void 0, function () {
2177
+ var i, j, _a, inputCoinDecimals, outputCoinDecimals, _amount, _output, target, amountIntBN, outputIntBN, k, smallAmountIntBN, _smallAmount, _smallOutput, amountBN, outputBN, smallAmountBN, smallOutputBN, rateBN, smallRateBN, slippageBN;
2178
+ return __generator(this, function (_c) {
2179
+ switch (_c.label) {
2180
+ case 0:
2181
+ i = this._getCoinIdx(inputCoin);
2182
+ j = this._getCoinIdx(outputCoin);
2183
+ _a = [this.underlyingDecimals[i], this.underlyingDecimals[j]], inputCoinDecimals = _a[0], outputCoinDecimals = _a[1];
2184
+ _amount = (0, utils_1.parseUnits)(amount, inputCoinDecimals);
2185
+ return [4 /*yield*/, this._swapExpected(i, j, _amount)];
2186
+ case 1:
2187
+ _output = _c.sent();
2188
+ target = (0, utils_1.BN)(Math.pow(10, 15));
2189
+ amountIntBN = (0, utils_1.BN)(amount).times(Math.pow(10, inputCoinDecimals));
2190
+ outputIntBN = (0, utils_1.toBN)(_output, 0);
2191
+ k = bignumber_js_1.default.min(bignumber_js_1.default.max(target.div(amountIntBN), target.div(outputIntBN)), 0.2);
2192
+ smallAmountIntBN = bignumber_js_1.default.min(amountIntBN.times(k), (0, utils_1.BN)(Math.pow(10, inputCoinDecimals)));
2193
+ if (smallAmountIntBN.toFixed(0) === '0')
2194
+ return [2 /*return*/, '0'];
2195
+ _smallAmount = (0, utils_1.fromBN)(smallAmountIntBN.div(Math.pow(10, inputCoinDecimals)), inputCoinDecimals);
2196
+ return [4 /*yield*/, this._swapExpected(i, j, _smallAmount)];
2197
+ case 2:
2198
+ _smallOutput = _c.sent();
2199
+ amountBN = (0, utils_1.BN)(amount);
2200
+ outputBN = (0, utils_1.toBN)(_output, outputCoinDecimals);
2201
+ smallAmountBN = (0, utils_1.toBN)(_smallAmount, inputCoinDecimals);
2202
+ smallOutputBN = (0, utils_1.toBN)(_smallOutput, outputCoinDecimals);
2203
+ rateBN = outputBN.div(amountBN);
2204
+ smallRateBN = smallOutputBN.div(smallAmountBN);
2205
+ slippageBN = (0, utils_1.BN)(1).minus(rateBN.div(smallRateBN)).times(100);
2206
+ return [2 /*return*/, (0, utils_1._cutZeros)(slippageBN.toFixed(6)).replace('-', '')];
2207
+ }
2208
+ });
2209
+ });
2210
+ };
2168
2211
  PoolTemplate.prototype._swapContractAddress = function () {
2169
- return (this.isCrypto && this.isMeta) || (curve_1.curve.chainId === 137 && this.isMetaFactory) ? this.zap : this.address;
2212
+ return (this.isCrypto && this.isMeta) || ([137, 43114].includes(curve_1.curve.chainId) && this.isMetaFactory) ? this.zap : this.address;
2170
2213
  };
2171
2214
  PoolTemplate.prototype.swapIsApproved = function (inputCoin, amount) {
2172
2215
  return __awaiter(this, void 0, void 0, function () {
@@ -2246,6 +2289,45 @@ var PoolTemplate = /** @class */ (function () {
2246
2289
  });
2247
2290
  });
2248
2291
  };
2292
+ PoolTemplate.prototype.swapWrappedPriceImpact = function (inputCoin, outputCoin, amount) {
2293
+ return __awaiter(this, void 0, void 0, function () {
2294
+ var i, j, _a, inputCoinDecimals, outputCoinDecimals, _amount, _output, target, amountIntBN, outputIntBN, k, smallAmountIntBN, _smallAmount, _smallOutput, amountBN, outputBN, smallAmountBN, smallOutputBN, rateBN, smallRateBN, slippageBN;
2295
+ return __generator(this, function (_c) {
2296
+ switch (_c.label) {
2297
+ case 0:
2298
+ if (this.isPlain || this.isFake) {
2299
+ throw Error("swapWrappedPriceImpact method doesn't exist for pool ".concat(this.name, " (id: ").concat(this.name, ")"));
2300
+ }
2301
+ i = this._getCoinIdx(inputCoin, false);
2302
+ j = this._getCoinIdx(outputCoin, false);
2303
+ _a = [this.wrappedDecimals[i], this.wrappedDecimals[j]], inputCoinDecimals = _a[0], outputCoinDecimals = _a[1];
2304
+ _amount = (0, utils_1.parseUnits)(amount, inputCoinDecimals);
2305
+ return [4 /*yield*/, this._swapWrappedExpected(i, j, _amount)];
2306
+ case 1:
2307
+ _output = _c.sent();
2308
+ target = (0, utils_1.BN)(Math.pow(10, 15));
2309
+ amountIntBN = (0, utils_1.BN)(amount).times(Math.pow(10, inputCoinDecimals));
2310
+ outputIntBN = (0, utils_1.toBN)(_output, 0);
2311
+ k = bignumber_js_1.default.min(bignumber_js_1.default.max(target.div(amountIntBN), target.div(outputIntBN)), 0.2);
2312
+ smallAmountIntBN = bignumber_js_1.default.min(amountIntBN.times(k), (0, utils_1.BN)(Math.pow(10, inputCoinDecimals)));
2313
+ if (smallAmountIntBN.toFixed(0) === '0')
2314
+ return [2 /*return*/, '0'];
2315
+ _smallAmount = (0, utils_1.fromBN)(smallAmountIntBN.div(Math.pow(10, inputCoinDecimals)), inputCoinDecimals);
2316
+ return [4 /*yield*/, this._swapWrappedExpected(i, j, _smallAmount)];
2317
+ case 2:
2318
+ _smallOutput = _c.sent();
2319
+ amountBN = (0, utils_1.BN)(amount);
2320
+ outputBN = (0, utils_1.toBN)(_output, outputCoinDecimals);
2321
+ smallAmountBN = (0, utils_1.toBN)(_smallAmount, inputCoinDecimals);
2322
+ smallOutputBN = (0, utils_1.toBN)(_smallOutput, outputCoinDecimals);
2323
+ rateBN = outputBN.div(amountBN);
2324
+ smallRateBN = smallOutputBN.div(smallAmountBN);
2325
+ slippageBN = (0, utils_1.BN)(1).minus(rateBN.div(smallRateBN)).times(100);
2326
+ return [2 /*return*/, (0, utils_1._cutZeros)(slippageBN.toFixed(6)).replace('-', '')];
2327
+ }
2328
+ });
2329
+ });
2330
+ };
2249
2331
  // OVERRIDE
2250
2332
  PoolTemplate.prototype.swapWrappedIsApproved = function (inputCoin, amount) {
2251
2333
  return __awaiter(this, void 0, void 0, function () {
@@ -44,7 +44,7 @@ var getPool = function (poolId) {
44
44
  return Pool;
45
45
  }(PoolTemplate_1.PoolTemplate));
46
46
  // statsBalances
47
- if (poolId === "atricrypto3") {
47
+ if (poolDummy.isFake) {
48
48
  Object.assign(Pool.prototype, poolBalancesMixin_1.poolBalancesAtricrypto3Mixin);
49
49
  }
50
50
  else if (poolDummy.isMeta) {
@@ -101,7 +101,7 @@ var getPool = function (poolId) {
101
101
  Object.assign(Pool.prototype, depositWrappedMixins_1.depositWrapped2argsMixin);
102
102
  }
103
103
  // withdrawExpected
104
- if (poolId === 'atricrypto3') {
104
+ if (poolDummy.isFake) {
105
105
  Object.assign(Pool.prototype, withdrawExpectedMixins_1.withdrawExpectedAtricrypto3Mixin);
106
106
  }
107
107
  else if (poolDummy.isMeta) {
@@ -207,7 +207,7 @@ var getPool = function (poolId) {
207
207
  if (poolId === 'tricrypto2') {
208
208
  Object.assign(Pool.prototype, swapMixins_1.swapTricrypto2Mixin);
209
209
  }
210
- else if (curve_1.curve.chainId === 137 && poolDummy.isMetaFactory) {
210
+ else if ([137, 43114].includes(curve_1.curve.chainId) && poolDummy.isMetaFactory) {
211
211
  Object.assign(Pool.prototype, swapMixins_1.swapMetaFactoryMixin);
212
212
  }
213
213
  else {
package/lib/router.d.ts CHANGED
@@ -5,6 +5,7 @@ export declare const getBestRouteAndOutput: (inputCoin: string, outputCoin: stri
5
5
  output: string;
6
6
  }>;
7
7
  export declare const swapExpected: (inputCoin: string, outputCoin: string, amount: number | string) => Promise<string>;
8
+ export declare const swapPriceImpact: (inputCoin: string, outputCoin: string, amount: number | string) => Promise<string>;
8
9
  export declare const swapIsApproved: (inputCoin: string, amount: number | string) => Promise<boolean>;
9
10
  export declare const swapApproveEstimateGas: (inputCoin: string, amount: number | string) => Promise<number>;
10
11
  export declare const swapApprove: (inputCoin: string, amount: number | string) => Promise<string[]>;
package/lib/router.js CHANGED
@@ -59,13 +59,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
59
59
  return (mod && mod.__esModule) ? mod : { "default": mod };
60
60
  };
61
61
  Object.defineProperty(exports, "__esModule", { value: true });
62
- exports.swap = exports.swapEstimateGas = exports.swapApprove = exports.swapApproveEstimateGas = exports.swapIsApproved = exports.swapExpected = exports.getBestRouteAndOutput = exports._findAllRoutes = void 0;
63
- var curve_1 = require("./curve");
62
+ exports.swap = exports.swapEstimateGas = exports.swapApprove = exports.swapApproveEstimateGas = exports.swapIsApproved = exports.swapPriceImpact = exports.swapExpected = exports.getBestRouteAndOutput = exports._findAllRoutes = void 0;
63
+ var axios_1 = __importDefault(require("axios"));
64
+ var memoizee_1 = __importDefault(require("memoizee"));
65
+ var bignumber_js_1 = __importDefault(require("bignumber.js"));
64
66
  var ethers_1 = require("ethers");
67
+ var curve_1 = require("./curve");
65
68
  var utils_1 = require("./utils");
66
- var memoizee_1 = __importDefault(require("memoizee"));
67
- var axios_1 = __importDefault(require("axios"));
68
69
  var pools_1 = require("./pools");
70
+ // TODO make working or remove
69
71
  var IMBALANCED_POOLS = [];
70
72
  // Inspired by Dijkstra's algorithm
71
73
  var _findAllRoutes = function (inputCoinAddress, outputCoinAddress) { return __awaiter(void 0, void 0, void 0, function () {
@@ -171,7 +173,7 @@ var _findAllRoutes = function (inputCoinAddress, outputCoinAddress) { return __a
171
173
  // No input coin in this pool --> skip
172
174
  if (inCoinIndexes.wrapped_coin === -1 && inCoinIndexes.underlying_coin === -1 && inCoinIndexes.meta_coin === -1)
173
175
  return [3 /*break*/, 17];
174
- if (!(inCoinIndexes.wrapped_coin >= 0 && poolId !== "atricrypto3")) return [3 /*break*/, 7];
176
+ if (!(inCoinIndexes.wrapped_coin >= 0 && !poolData.is_fake)) return [3 /*break*/, 7];
175
177
  j = 0;
176
178
  _5.label = 4;
177
179
  case 4:
@@ -212,14 +214,14 @@ var _findAllRoutes = function (inputCoinAddress, outputCoinAddress) { return __a
212
214
  j++;
213
215
  return [3 /*break*/, 4];
214
216
  case 7:
215
- poolAddress = ["eurtusd", "xautusd", "atricrypto3"].includes(poolId) ||
216
- (curve_1.curve.chainId === 137 && poolData.is_factory) ? poolData.deposit_address : poolData.swap_address;
217
+ poolAddress = (poolData.is_crypto && poolData.is_meta) || ([137, 43114].includes(curve_1.curve.chainId) && poolData.is_factory) ?
218
+ poolData.deposit_address : poolData.swap_address;
217
219
  if (!(wrapped_coin_addresses.join("|") !== underlying_coin_addresses.join("|") && inCoinIndexes.underlying_coin >= 0)) return [3 /*break*/, 11];
218
220
  j = 0;
219
221
  _5.label = 8;
220
222
  case 8:
221
223
  if (!(j < underlying_coin_addresses.length)) return [3 /*break*/, 11];
222
- if (poolId === "atricrypto3" && inCoinIndexes.meta_coin >= 0 && meta_coin_addresses.includes(underlying_coin_addresses[j]))
224
+ if (poolData.is_fake && inCoinIndexes.meta_coin >= 0 && meta_coin_addresses.includes(underlying_coin_addresses[j]))
223
225
  return [3 /*break*/, 10];
224
226
  // If this coin already marked or will be marked on the current step, no need to consider it on the next step
225
227
  if (markedCoins.includes(underlying_coin_addresses[j]) || curCoins.includes(underlying_coin_addresses[j]))
@@ -257,7 +259,7 @@ var _findAllRoutes = function (inputCoinAddress, outputCoinAddress) { return __a
257
259
  j++;
258
260
  return [3 /*break*/, 8];
259
261
  case 11:
260
- if (!(inCoinIndexes.wrapped_coin === 0 && meta_coin_addresses.length > 0 && poolId !== "atricrypto3")) return [3 /*break*/, 15];
262
+ if (!(inCoinIndexes.wrapped_coin === 0 && meta_coin_addresses.length > 0 && !poolData.is_fake)) return [3 /*break*/, 15];
261
263
  j = 0;
262
264
  _5.label = 12;
263
265
  case 12:
@@ -277,7 +279,7 @@ var _findAllRoutes = function (inputCoinAddress, outputCoinAddress) { return __a
277
279
  // Skip imbalanced pools
278
280
  if (IMBALANCED_POOLS.includes(poolId))
279
281
  return [3 /*break*/, 14];
280
- swapType = (curve_1.curve.chainId === 137 && poolData.is_factory) ? 5 : poolData.is_crypto ? 4 : 2;
282
+ swapType = ([137, 43114].includes(curve_1.curve.chainId) && poolData.is_factory) ? 5 : poolData.is_crypto ? 4 : 2;
281
283
  for (_r = 0, _s = routes[inCoin]; _r < _s.length; _r++) {
282
284
  inCoinRoute = _s[_r];
283
285
  routes[meta_coin_addresses[j]] = ((_2 = routes[meta_coin_addresses[j]]) !== null && _2 !== void 0 ? _2 : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
@@ -298,7 +300,7 @@ var _findAllRoutes = function (inputCoinAddress, outputCoinAddress) { return __a
298
300
  j++;
299
301
  return [3 /*break*/, 12];
300
302
  case 15:
301
- if (!(inCoinIndexes.meta_coin >= 0 && poolId !== "atricrypto3")) return [3 /*break*/, 17];
303
+ if (!(inCoinIndexes.meta_coin >= 0 && !poolData.is_fake)) return [3 /*break*/, 17];
302
304
  // If this coin already marked or will be marked on the current step, no need to consider it on the next step
303
305
  if (markedCoins.includes(wrapped_coin_addresses[0]) || curCoins.includes(wrapped_coin_addresses[0]))
304
306
  return [3 /*break*/, 17];
@@ -314,7 +316,7 @@ var _findAllRoutes = function (inputCoinAddress, outputCoinAddress) { return __a
314
316
  // Skip imbalanced pools
315
317
  if (IMBALANCED_POOLS.includes(poolId))
316
318
  return [3 /*break*/, 17];
317
- swapType = (curve_1.curve.chainId === 137 && poolData.is_factory) ? 5 : poolData.is_crypto ? 4 : 2;
319
+ swapType = ([137, 43114].includes(curve_1.curve.chainId) && poolData.is_factory) ? 5 : poolData.is_crypto ? 4 : 2;
318
320
  for (_u = 0, _v = routes[inCoin]; _u < _v.length; _u++) {
319
321
  inCoinRoute = _v[_u];
320
322
  routes[wrapped_coin_addresses[0]] = ((_3 = routes[wrapped_coin_addresses[0]]) !== null && _3 !== void 0 ? _3 : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
@@ -422,56 +424,46 @@ var _estimateGasForDifferentRoutes = function (routes, inputCoinAddress, outputC
422
424
  });
423
425
  }); };
424
426
  var _getBestRouteAndOutput = (0, memoizee_1.default)(function (inputCoinAddress, outputCoinAddress, amount) { return __awaiter(void 0, void 0, void 0, function () {
425
- var _a, inputCoinDecimals, outputCoinDecimals, _amount, routesRaw, routes, calls, promises, multicallContract, contract, _i, routesRaw_1, route, _b, _route, _swapParams, _factorySwapAddresses, calls_1, multicallContract_1, _c, routesRaw_2, route, _d, _route, _swapParams, _factorySwapAddresses, _outputAmounts, i, err_2, promises_1, contract_1, _e, routesRaw_3, route, _f, _route, _swapParams, _factorySwapAddresses, res, i, _h, gasAmounts, outputCoinUsdRate, gasData, ethUsdRate, gasPrice, expectedAmounts, expectedAmountsUsd, txCostsUsd;
426
- return __generator(this, function (_j) {
427
- switch (_j.label) {
427
+ var _a, inputCoinDecimals, outputCoinDecimals, _amount, routesRaw, routes, calls, multicallContract, _i, routesRaw_1, route, _b, _route, _swapParams, _factorySwapAddresses, _outputAmounts, i, err_2, promises, contract, _c, routesRaw_2, route, _d, _route, _swapParams, _factorySwapAddresses, res, i, _e, gasAmounts, outputCoinUsdRate, gasData, ethUsdRate, gasPrice, expectedAmounts, expectedAmountsUsd, txCostsUsd;
428
+ return __generator(this, function (_f) {
429
+ switch (_f.label) {
428
430
  case 0:
429
431
  _a = (0, utils_1._getCoinDecimals)(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _a[0], outputCoinDecimals = _a[1];
430
432
  _amount = (0, utils_1.parseUnits)(amount, inputCoinDecimals);
431
433
  return [4 /*yield*/, (0, exports._findAllRoutes)(inputCoinAddress, outputCoinAddress)];
432
434
  case 1:
433
- routesRaw = (_j.sent()).map(function (steps) { return ({ steps: steps, _output: ethers_1.ethers.BigNumber.from(0), outputUsd: 0, txCostUsd: 0 }); });
435
+ routesRaw = (_f.sent()).map(function (steps) { return ({ steps: steps, _output: ethers_1.ethers.BigNumber.from(0), outputUsd: 0, txCostUsd: 0 }); });
434
436
  routes = [];
437
+ _f.label = 2;
438
+ case 2:
439
+ _f.trys.push([2, 4, , 6]);
435
440
  calls = [];
436
- promises = [];
437
441
  multicallContract = curve_1.curve.contracts[curve_1.curve.constants.ALIASES.registry_exchange].multicallContract;
438
- contract = curve_1.curve.contracts[curve_1.curve.constants.ALIASES.registry_exchange].contract;
439
442
  for (_i = 0, routesRaw_1 = routesRaw; _i < routesRaw_1.length; _i++) {
440
443
  route = routesRaw_1[_i];
441
444
  _b = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _b._route, _swapParams = _b._swapParams, _factorySwapAddresses = _b._factorySwapAddresses;
442
445
  calls.push(multicallContract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses));
443
- promises.push(contract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve_1.curve.constantOptions));
444
- }
445
- _j.label = 2;
446
- case 2:
447
- _j.trys.push([2, 4, , 6]);
448
- calls_1 = [];
449
- multicallContract_1 = curve_1.curve.contracts[curve_1.curve.constants.ALIASES.registry_exchange].multicallContract;
450
- for (_c = 0, routesRaw_2 = routesRaw; _c < routesRaw_2.length; _c++) {
451
- route = routesRaw_2[_c];
452
- _d = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _d._route, _swapParams = _d._swapParams, _factorySwapAddresses = _d._factorySwapAddresses;
453
- calls_1.push(multicallContract_1.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses));
454
446
  }
455
- return [4 /*yield*/, curve_1.curve.multicallProvider.all(calls_1)];
447
+ return [4 /*yield*/, curve_1.curve.multicallProvider.all(calls)];
456
448
  case 3:
457
- _outputAmounts = _j.sent();
449
+ _outputAmounts = _f.sent();
458
450
  for (i = 0; i < _outputAmounts.length; i++) {
459
451
  routesRaw[i]._output = _outputAmounts[i];
460
452
  routes.push(routesRaw[i]);
461
453
  }
462
454
  return [3 /*break*/, 6];
463
455
  case 4:
464
- err_2 = _j.sent();
465
- promises_1 = [];
466
- contract_1 = curve_1.curve.contracts[curve_1.curve.constants.ALIASES.registry_exchange].contract;
467
- for (_e = 0, routesRaw_3 = routesRaw; _e < routesRaw_3.length; _e++) {
468
- route = routesRaw_3[_e];
469
- _f = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _f._route, _swapParams = _f._swapParams, _factorySwapAddresses = _f._factorySwapAddresses;
470
- promises_1.push(contract_1.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve_1.curve.constantOptions));
456
+ err_2 = _f.sent();
457
+ promises = [];
458
+ contract = curve_1.curve.contracts[curve_1.curve.constants.ALIASES.registry_exchange].contract;
459
+ for (_c = 0, routesRaw_2 = routesRaw; _c < routesRaw_2.length; _c++) {
460
+ route = routesRaw_2[_c];
461
+ _d = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _d._route, _swapParams = _d._swapParams, _factorySwapAddresses = _d._factorySwapAddresses;
462
+ promises.push(contract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve_1.curve.constantOptions));
471
463
  }
472
- return [4 /*yield*/, Promise.allSettled(promises_1)];
464
+ return [4 /*yield*/, Promise.allSettled(promises)];
473
465
  case 5:
474
- res = _j.sent();
466
+ res = _f.sent();
475
467
  for (i = 0; i < res.length; i++) {
476
468
  if (res[i].status === 'rejected') {
477
469
  console.log("Route ".concat((routesRaw[i].steps.map(function (s) { return s.poolId; })).join(" --> "), " is anavailable"));
@@ -496,10 +488,10 @@ var _getBestRouteAndOutput = (0, memoizee_1.default)(function (inputCoinAddress,
496
488
  _estimateGasForDifferentRoutes(routes, inputCoinAddress, outputCoinAddress, _amount),
497
489
  (0, utils_1._getUsdRate)(outputCoinAddress),
498
490
  axios_1.default.get("https://api.curve.fi/api/getGas"),
499
- (0, utils_1._getUsdRate)(curve_1.curve.chainId === 137 ? curve_1.curve.constants.COINS.matic : curve_1.curve.constants.COINS.eth),
491
+ (0, utils_1._getUsdRate)(utils_1.ETH_ADDRESS),
500
492
  ])];
501
493
  case 7:
502
- _h = _j.sent(), gasAmounts = _h[0], outputCoinUsdRate = _h[1], gasData = _h[2], ethUsdRate = _h[3];
494
+ _e = _f.sent(), gasAmounts = _e[0], outputCoinUsdRate = _e[1], gasData = _e[2], ethUsdRate = _e[3];
503
495
  gasPrice = gasData.data.data.gas.standard;
504
496
  expectedAmounts = (routes).map(function (route) { return Number(ethers_1.ethers.utils.formatUnits(route._output, outputCoinDecimals)); });
505
497
  expectedAmountsUsd = expectedAmounts.map(function (a) { return a * outputCoinUsdRate; });
@@ -539,6 +531,41 @@ var swapExpected = function (inputCoin, outputCoin, amount) { return __awaiter(v
539
531
  });
540
532
  }); };
541
533
  exports.swapExpected = swapExpected;
534
+ var swapPriceImpact = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
535
+ var _a, inputCoinAddress, outputCoinAddress, _b, inputCoinDecimals, outputCoinDecimals, route, target, amountIntBN, outputIntBN, k, smallAmountIntBN, contract, _smallAmount, _c, _route, _swapParams, _factorySwapAddresses, _smallOutput, amountBN, outputBN, smallAmountBN, smallOutputBN, rateBN, smallRateBN, slippageBN;
536
+ return __generator(this, function (_d) {
537
+ switch (_d.label) {
538
+ case 0:
539
+ _a = (0, utils_1._getCoinAddresses)(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
540
+ _b = (0, utils_1._getCoinDecimals)(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _b[0], outputCoinDecimals = _b[1];
541
+ return [4 /*yield*/, _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount)];
542
+ case 1:
543
+ route = _d.sent();
544
+ target = (0, utils_1.BN)(Math.pow(10, 15));
545
+ amountIntBN = (0, utils_1.BN)(amount).times(Math.pow(10, inputCoinDecimals));
546
+ outputIntBN = (0, utils_1.toBN)(route._output, 0);
547
+ k = bignumber_js_1.default.min(bignumber_js_1.default.max(target.div(amountIntBN), target.div(outputIntBN)), 0.2);
548
+ smallAmountIntBN = bignumber_js_1.default.min(amountIntBN.times(k), (0, utils_1.BN)(Math.pow(10, inputCoinDecimals)));
549
+ if (smallAmountIntBN.toFixed(0) === '0')
550
+ return [2 /*return*/, '0'];
551
+ contract = curve_1.curve.contracts[curve_1.curve.constants.ALIASES.registry_exchange].contract;
552
+ _smallAmount = (0, utils_1.fromBN)(smallAmountIntBN.div(Math.pow(10, inputCoinDecimals)), inputCoinDecimals);
553
+ _c = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _c._route, _swapParams = _c._swapParams, _factorySwapAddresses = _c._factorySwapAddresses;
554
+ return [4 /*yield*/, contract.get_exchange_multiple_amount(_route, _swapParams, _smallAmount, _factorySwapAddresses, curve_1.curve.constantOptions)];
555
+ case 2:
556
+ _smallOutput = _d.sent();
557
+ amountBN = (0, utils_1.BN)(amount);
558
+ outputBN = (0, utils_1.toBN)(route._output, outputCoinDecimals);
559
+ smallAmountBN = (0, utils_1.toBN)(_smallAmount, inputCoinDecimals);
560
+ smallOutputBN = (0, utils_1.toBN)(_smallOutput, outputCoinDecimals);
561
+ rateBN = outputBN.div(amountBN);
562
+ smallRateBN = smallOutputBN.div(smallAmountBN);
563
+ slippageBN = (0, utils_1.BN)(1).minus(rateBN.div(smallRateBN)).times(100);
564
+ return [2 /*return*/, (0, utils_1._cutZeros)(slippageBN.toFixed(6)).replace('-', '')];
565
+ }
566
+ });
567
+ }); };
568
+ exports.swapPriceImpact = swapPriceImpact;
542
569
  var swapIsApproved = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
543
570
  return __generator(this, function (_a) {
544
571
  switch (_a.label) {
package/lib/utils.d.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import { ethers } from 'ethers';
2
2
  import BigNumber from 'bignumber.js';
3
3
  import { IDict } from './interfaces';
4
+ export declare const ETH_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
4
5
  export declare const MAX_ALLOWANCE: ethers.BigNumber;
5
6
  export declare const BN: (val: number | string) => BigNumber;
6
7
  export declare const toBN: (n: ethers.BigNumber, decimals?: number) => BigNumber;
7
8
  export declare const toStringFromBN: (bn: BigNumber, decimals?: number) => string;
8
9
  export declare const fromBN: (bn: BigNumber, decimals?: number) => ethers.BigNumber;
10
+ export declare const _cutZeros: (strn: string) => string;
9
11
  export declare const checkNumber: (n: number | string) => number | string;
10
12
  export declare const formatNumber: (n: number | string, decimals?: number) => string;
11
13
  export declare const parseUnits: (n: number | string, decimals?: number) => ethers.BigNumber;