@xchainjs/xchain-thorchain-query 0.2.3 → 0.2.5
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/lib/index.esm.js +421 -310
- package/lib/index.js +545 -411
- package/lib/types.d.ts +2 -0
- package/lib/utils/const.d.ts +24 -0
- package/lib/utils/index.d.ts +1 -0
- package/package.json +1 -19
package/lib/index.esm.js
CHANGED
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
import { BNBChain, AssetBNB } from '@xchainjs/xchain-binance';
|
|
2
|
-
import { BTCChain, AssetBTC } from '@xchainjs/xchain-bitcoin';
|
|
3
|
-
import { GAIAChain, AssetATOM } from '@xchainjs/xchain-cosmos';
|
|
4
|
-
import { AssetRuneNative, THORChain, isAssetRuneNative } from '@xchainjs/xchain-thorchain';
|
|
5
1
|
import { assetToBase, formatAssetAmountCurrency, baseToAsset, eqAsset, assetToString, assetFromString, baseAmount, assetFromStringEx, assetAmount, getContractAddressFromAsset } from '@xchainjs/xchain-util';
|
|
6
2
|
import { BigNumber } from 'bignumber.js';
|
|
7
3
|
import { Network } from '@xchainjs/xchain-client';
|
|
8
4
|
import { MidgardApi, Configuration } from '@xchainjs/xchain-midgard';
|
|
9
5
|
import axios from 'axios';
|
|
10
6
|
import axiosRetry from 'axios-retry';
|
|
11
|
-
import { AVAXChain, AssetAVAX } from '@xchainjs/xchain-avax';
|
|
12
|
-
import { BCHChain, AssetBCH } from '@xchainjs/xchain-bitcoincash';
|
|
13
|
-
import { DOGEChain, AssetDOGE } from '@xchainjs/xchain-doge';
|
|
14
|
-
import { ETHChain, AssetETH } from '@xchainjs/xchain-ethereum';
|
|
15
|
-
import { LTCChain, AssetLTC } from '@xchainjs/xchain-litecoin';
|
|
16
7
|
import { TransactionsApi, Configuration as Configuration$1, QueueApi, NetworkApi, PoolsApi, LiquidityProvidersApi, SaversApi, QuoteApi, MimirApi } from '@xchainjs/xchain-thornode';
|
|
17
8
|
|
|
18
9
|
/*! *****************************************************************************
|
|
@@ -77,6 +68,14 @@ const DefaultChainAttributes = {
|
|
|
77
68
|
blockReward: 0,
|
|
78
69
|
avgBlockTimeInSecs: 6,
|
|
79
70
|
},
|
|
71
|
+
BSC: {
|
|
72
|
+
blockReward: 0,
|
|
73
|
+
avgBlockTimeInSecs: 3,
|
|
74
|
+
},
|
|
75
|
+
MAYA: {
|
|
76
|
+
blockReward: 0,
|
|
77
|
+
avgBlockTimeInSecs: 6,
|
|
78
|
+
},
|
|
80
79
|
};
|
|
81
80
|
|
|
82
81
|
/**
|
|
@@ -196,148 +195,29 @@ class LiquidityPool {
|
|
|
196
195
|
}
|
|
197
196
|
}
|
|
198
197
|
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
* @returns an array of Pools
|
|
223
|
-
*/
|
|
224
|
-
getPools() {
|
|
225
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
226
|
-
for (const api of this.midgardApis) {
|
|
227
|
-
try {
|
|
228
|
-
return (yield api.getPools()).data;
|
|
229
|
-
}
|
|
230
|
-
catch (e) {
|
|
231
|
-
//console.error(e)
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
throw new Error(`Midgard not responding`);
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Gets the latest block using the Health endpoint within Midgard
|
|
239
|
-
*
|
|
240
|
-
* @returns
|
|
241
|
-
*/
|
|
242
|
-
getLatestBlockHeight() {
|
|
243
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
-
for (const api of this.midgardApis) {
|
|
245
|
-
try {
|
|
246
|
-
const data = (yield api.getHealth()).data;
|
|
247
|
-
return +data.scannerHeight;
|
|
248
|
-
}
|
|
249
|
-
catch (e) {
|
|
250
|
-
//console.error(e)
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
throw Error(`Midgard not responding`);
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Gets actions object for any of the parameters
|
|
258
|
-
* @param txHash transaction id
|
|
259
|
-
* @returns Type Action array of objects
|
|
260
|
-
*/
|
|
261
|
-
getActions(address, txid, asset, type, affiliate, limit, offset) {
|
|
262
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
263
|
-
for (const api of this.midgardApis) {
|
|
264
|
-
try {
|
|
265
|
-
const actions = (yield api.getActions(address, txid, asset, type, affiliate, limit, offset)).data.actions;
|
|
266
|
-
return actions;
|
|
267
|
-
}
|
|
268
|
-
catch (e) {
|
|
269
|
-
//console.error(e)
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
throw Error(`Midgard not responding`);
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Function to return member details based on valid liquidity position
|
|
277
|
-
* @param address - needed to query for Lp details
|
|
278
|
-
* @returns - object type of Member Detail
|
|
279
|
-
*/
|
|
280
|
-
getMember(address) {
|
|
281
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
282
|
-
for (const api of this.midgardApis) {
|
|
283
|
-
try {
|
|
284
|
-
const memberDetail = (yield api.getMemberDetail(address)).data;
|
|
285
|
-
return memberDetail;
|
|
286
|
-
}
|
|
287
|
-
catch (e) {
|
|
288
|
-
//console.error(e)
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
throw Error(`Midgard not responding`);
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Function to return pool statistics for a particular asset
|
|
296
|
-
* @param asset - asset string to query its pool stats
|
|
297
|
-
* @returns - type object poolstatsDetail
|
|
298
|
-
*/
|
|
299
|
-
getPoolStats(asset) {
|
|
300
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
301
|
-
for (const api of this.midgardApis) {
|
|
302
|
-
try {
|
|
303
|
-
const poolDetail = (yield api.getPoolStats(asset)).data;
|
|
304
|
-
return poolDetail;
|
|
305
|
-
}
|
|
306
|
-
catch (e) {
|
|
307
|
-
//console.error(e)
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
throw Error(`Midgard not responding`);
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Function to return THORNameDetails for a particular name
|
|
315
|
-
* @param name - thorname string to query
|
|
316
|
-
* @returns - type object THORNameDetails
|
|
317
|
-
*/
|
|
318
|
-
getTHORNameDetails(name) {
|
|
319
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
320
|
-
for (const api of this.midgardApis) {
|
|
321
|
-
try {
|
|
322
|
-
const resp = yield api.getTHORNameDetail(name);
|
|
323
|
-
if (resp.status == 404) {
|
|
324
|
-
return undefined;
|
|
325
|
-
}
|
|
326
|
-
else if (resp.status == 200) {
|
|
327
|
-
return resp.data;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
catch (e) {
|
|
331
|
-
// if (resp.status == 404) {
|
|
332
|
-
// return undefined
|
|
333
|
-
// }
|
|
334
|
-
//console.error(e)
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
throw Error(`Midgard not responding`);
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
}
|
|
198
|
+
const AssetBNB = assetFromStringEx('BNB.BNB');
|
|
199
|
+
const AssetAVAX = assetFromStringEx('AVAX.AVAX');
|
|
200
|
+
const AssetBTC = assetFromStringEx('BTC.BTC');
|
|
201
|
+
const AssetBCH = assetFromStringEx('BCH.BHC');
|
|
202
|
+
const AssetETH = assetFromStringEx('ETH.ETH');
|
|
203
|
+
const AssetDOGE = assetFromStringEx('DOGE.DOGE');
|
|
204
|
+
const AssetLTC = assetFromStringEx('LTC.LTC');
|
|
205
|
+
const AssetATOM = assetFromStringEx('GAIA.ATOM');
|
|
206
|
+
const AssetMAYA = assetFromStringEx('MAYA.CACAO');
|
|
207
|
+
const AssetBSC = assetFromStringEx('BSC.BNB');
|
|
208
|
+
const AssetRuneNative = assetFromStringEx('THOR.RUNE');
|
|
209
|
+
const BNBChain = 'BNB';
|
|
210
|
+
const BTCChain = 'BTC';
|
|
211
|
+
const BCHChain = 'BCH';
|
|
212
|
+
const ETHChain = 'ETH';
|
|
213
|
+
const GAIAChain = 'GAIA';
|
|
214
|
+
const DOGEChain = 'DOGE';
|
|
215
|
+
const LTCChain = 'LTC';
|
|
216
|
+
const AVAXChain = 'AVAX';
|
|
217
|
+
const MAYAChain = 'MAYA';
|
|
218
|
+
const BSCChain = 'BSC';
|
|
219
|
+
const THORChain = 'THOR';
|
|
220
|
+
const isAssetRuneNative = (asset) => assetToString(asset) === assetToString(AssetRuneNative);
|
|
341
221
|
|
|
342
222
|
const getBaseAmountWithDiffDecimals = (inputAmount, outDecimals) => {
|
|
343
223
|
const inDecimals = inputAmount.baseAmount.decimal;
|
|
@@ -491,6 +371,10 @@ const getChainAsset = (chain) => {
|
|
|
491
371
|
return AssetDOGE;
|
|
492
372
|
case AVAXChain:
|
|
493
373
|
return AssetAVAX;
|
|
374
|
+
case BSCChain:
|
|
375
|
+
return AssetBSC;
|
|
376
|
+
case MAYAChain:
|
|
377
|
+
return AssetMAYA;
|
|
494
378
|
default:
|
|
495
379
|
throw Error('Unknown chain');
|
|
496
380
|
}
|
|
@@ -540,58 +424,300 @@ const calcNetworkFee = (asset, inbound) => {
|
|
|
540
424
|
else {
|
|
541
425
|
return new CryptoAmount(gasRateinETHWei.times(70000), AssetETH);
|
|
542
426
|
}
|
|
543
|
-
case AVAXChain:
|
|
544
|
-
const gasRateinAVAXGwei = inbound.gasRate;
|
|
545
|
-
const gasRateinAVAXWei = baseAmount(gasRateinAVAXGwei.multipliedBy(Math.pow(10, 9)), 18);
|
|
546
|
-
if (eqAsset(asset, AssetAVAX)) {
|
|
547
|
-
return new CryptoAmount(gasRateinAVAXWei.times(21000), AssetAVAX);
|
|
427
|
+
case AVAXChain:
|
|
428
|
+
const gasRateinAVAXGwei = inbound.gasRate;
|
|
429
|
+
const gasRateinAVAXWei = baseAmount(gasRateinAVAXGwei.multipliedBy(Math.pow(10, 9)), 18);
|
|
430
|
+
if (eqAsset(asset, AssetAVAX)) {
|
|
431
|
+
return new CryptoAmount(gasRateinAVAXWei.times(21000), AssetAVAX);
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
return new CryptoAmount(gasRateinAVAXWei.times(70000), AssetAVAX);
|
|
435
|
+
}
|
|
436
|
+
case GAIAChain:
|
|
437
|
+
return new CryptoAmount(baseAmount(inbound.gasRate), AssetATOM);
|
|
438
|
+
case THORChain:
|
|
439
|
+
return new CryptoAmount(baseAmount(2000000), AssetRuneNative);
|
|
440
|
+
case BSCChain:
|
|
441
|
+
return new CryptoAmount(baseAmount(inbound.gasRate), AssetBSC);
|
|
442
|
+
case MAYAChain:
|
|
443
|
+
return new CryptoAmount(baseAmount(inbound.gasRate), AssetMAYA);
|
|
444
|
+
}
|
|
445
|
+
throw new Error(`could not calculate inbound fee for ${asset.chain}`);
|
|
446
|
+
};
|
|
447
|
+
/**
|
|
448
|
+
* Works out the required outbound fee based on the chain.
|
|
449
|
+
* Call getInboundDetails to get the current outbound fee
|
|
450
|
+
*
|
|
451
|
+
* @param sourceAsset
|
|
452
|
+
* @param inbound detail
|
|
453
|
+
* @see https://dev.thorchain.org/thorchain-dev/thorchain-and-fees#fee-calcuation-by-chain
|
|
454
|
+
* @returns
|
|
455
|
+
*/
|
|
456
|
+
const calcOutboundFee = (asset, inbound) => {
|
|
457
|
+
if (asset.synth)
|
|
458
|
+
return new CryptoAmount(baseAmount(2000000), AssetRuneNative);
|
|
459
|
+
switch (asset.chain) {
|
|
460
|
+
case BTCChain:
|
|
461
|
+
return new CryptoAmount(baseAmount(inbound.outboundFee), AssetBTC);
|
|
462
|
+
case BCHChain:
|
|
463
|
+
return new CryptoAmount(baseAmount(inbound.outboundFee), AssetBCH);
|
|
464
|
+
case LTCChain:
|
|
465
|
+
return new CryptoAmount(baseAmount(inbound.outboundFee), AssetLTC);
|
|
466
|
+
case DOGEChain:
|
|
467
|
+
// NOTE: UTXO chains estimate fees with a 250 byte size
|
|
468
|
+
return new CryptoAmount(baseAmount(inbound.outboundFee), AssetDOGE);
|
|
469
|
+
case BNBChain:
|
|
470
|
+
//flat fee
|
|
471
|
+
return new CryptoAmount(baseAmount(inbound.outboundFee), AssetBNB);
|
|
472
|
+
case ETHChain:
|
|
473
|
+
return new CryptoAmount(baseAmount(inbound.outboundFee.multipliedBy(Math.pow(10, 9)), 18), AssetETH);
|
|
474
|
+
case AVAXChain:
|
|
475
|
+
return new CryptoAmount(baseAmount(inbound.outboundFee.multipliedBy(Math.pow(10, 9)), 18), AssetAVAX);
|
|
476
|
+
case GAIAChain:
|
|
477
|
+
return new CryptoAmount(baseAmount(inbound.outboundFee), AssetATOM);
|
|
478
|
+
case BSCChain:
|
|
479
|
+
return new CryptoAmount(baseAmount(inbound.outboundFee), AssetBSC);
|
|
480
|
+
case THORChain:
|
|
481
|
+
return new CryptoAmount(baseAmount(2000000), AssetRuneNative);
|
|
482
|
+
case MAYAChain:
|
|
483
|
+
return new CryptoAmount(baseAmount(2000000), AssetMAYA);
|
|
484
|
+
}
|
|
485
|
+
throw new Error(`could not calculate outbound fee for ${asset.chain}`);
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* https://dev.thorchain.org/thorchain-dev/interface-guide/math#lp-units-add
|
|
490
|
+
* @param liquidity - asset amount added
|
|
491
|
+
* @param pool - pool depths
|
|
492
|
+
* @returns liquidity units - ownership of pool
|
|
493
|
+
*/
|
|
494
|
+
const getLiquidityUnits = (liquidity, pool) => {
|
|
495
|
+
const baseAmount8decimals = getBaseAmountWithDiffDecimals(liquidity.asset, 8);
|
|
496
|
+
const P = new BigNumber(pool.pool.liquidityUnits);
|
|
497
|
+
const r = liquidity.rune.baseAmount.amount();
|
|
498
|
+
const a = baseAmount8decimals;
|
|
499
|
+
const R = pool.runeBalance.amount();
|
|
500
|
+
const A = pool.assetBalance.amount();
|
|
501
|
+
const part1 = R.times(a);
|
|
502
|
+
const part2 = r.times(A);
|
|
503
|
+
const numerator = P.times(part1.plus(part2));
|
|
504
|
+
const denominator = R.times(A).times(2);
|
|
505
|
+
const result = numerator.div(denominator);
|
|
506
|
+
return result;
|
|
507
|
+
};
|
|
508
|
+
/**
|
|
509
|
+
*
|
|
510
|
+
* @param unitData - units for both asset and rune
|
|
511
|
+
* @param pool - pool that the asset is bound to
|
|
512
|
+
* @returns - pool share of both asset and rune in percentage
|
|
513
|
+
*/
|
|
514
|
+
const getPoolShare = (unitData, pool) => {
|
|
515
|
+
// formula: (rune * part) / total; (asset * part) / total
|
|
516
|
+
const units = unitData.liquidityUnits;
|
|
517
|
+
const total = unitData.totalUnits;
|
|
518
|
+
const R = pool.runeBalance.amount();
|
|
519
|
+
const T = pool.assetBalance.amount();
|
|
520
|
+
const asset = T.times(units).div(total);
|
|
521
|
+
const rune = R.times(units).div(total);
|
|
522
|
+
const poolShareDetail = {
|
|
523
|
+
assetShare: new CryptoAmount(baseAmount(asset), pool.asset),
|
|
524
|
+
runeShare: new CryptoAmount(baseAmount(rune), AssetRuneNative),
|
|
525
|
+
};
|
|
526
|
+
return poolShareDetail;
|
|
527
|
+
};
|
|
528
|
+
/**
|
|
529
|
+
*
|
|
530
|
+
* @param poolShare - the share of asset and rune added to the pool
|
|
531
|
+
* @param pool - Pool that the asset is attached to
|
|
532
|
+
* @returns - returns bignumber representing a slip percentage
|
|
533
|
+
*/
|
|
534
|
+
const getSlipOnLiquidity = (stake, pool) => {
|
|
535
|
+
const baseAmount8decimals = getBaseAmountWithDiffDecimals(stake.asset, 8);
|
|
536
|
+
// formula: (t * R - T * r)/ (T*r + R*T)
|
|
537
|
+
const r = stake.rune.baseAmount.amount();
|
|
538
|
+
const t = baseAmount8decimals;
|
|
539
|
+
const R = pool.runeBalance.amount();
|
|
540
|
+
const T = pool.assetBalance.amount();
|
|
541
|
+
const numerator = t.times(R).minus(T.times(r));
|
|
542
|
+
const denominator = T.times(r).plus(R.times(T));
|
|
543
|
+
const result = numerator.div(denominator).abs();
|
|
544
|
+
return result;
|
|
545
|
+
};
|
|
546
|
+
/**
|
|
547
|
+
* https://docs.thorchain.org/thorchain-finance/continuous-liquidity-pools#impermanent-loss-protection
|
|
548
|
+
* @param poolShare - the share of asset and rune added to the pool
|
|
549
|
+
* @param pool - Pool that the asset is attached to
|
|
550
|
+
* @param block - blockl object with current, last added and the constant blocksforlossProtection
|
|
551
|
+
* @returns
|
|
552
|
+
*/
|
|
553
|
+
// Blocks for full protection 1440000 // 100 days
|
|
554
|
+
const getLiquidityProtectionData = (depositValue, poolShare, block) => {
|
|
555
|
+
//Coverage formula coverage=((A0∗P1)+R0)−((A1∗P1)+R1)=>((A0∗R1/A1)+R0)−(R1+R1)
|
|
556
|
+
//formula: protectionProgress (currentHeight-heightLastAdded)/blocksforfullprotection
|
|
557
|
+
const R0 = depositValue.rune.amount(); // rune deposit value
|
|
558
|
+
const A0 = depositValue.asset.amount(); // asset deposit value
|
|
559
|
+
const R1 = poolShare.runeShare.baseAmount.amount(); // rune amount to redeem
|
|
560
|
+
const A1 = poolShare.assetShare.baseAmount.amount(); // asset amount to redeem
|
|
561
|
+
const P1 = R1.div(A1); // Pool ratio at withdrawal
|
|
562
|
+
const part1 = A0.times(P1).plus(R0).minus(A1.times(P1).plus(R1)); // start position minus end position
|
|
563
|
+
const part2 = A0.times(R1.div(A1)).plus(R0).minus(R1.plus(R1)); // different way to check position
|
|
564
|
+
const coverage = part1 >= part2 ? part1 : part2; // Coverage represents how much ILP a LP is entitled to
|
|
565
|
+
const currentHeight = block.current;
|
|
566
|
+
const heightLastAdded = block.lastAdded || 0; //default to zero if undefined
|
|
567
|
+
const blocksforfullprotection = block.fullProtection;
|
|
568
|
+
const fractionOfFullILPProtection = (currentHeight - heightLastAdded) / blocksforfullprotection;
|
|
569
|
+
const protectionProgress = Math.min(fractionOfFullILPProtection, 1); // percentage of entitlement, max 100%
|
|
570
|
+
const result = coverage.times(protectionProgress); // impermanent loss protection result
|
|
571
|
+
const maxILP = result.lt(0) ? new BigNumber(0) : result; // max negative ILP to 0
|
|
572
|
+
const ILProtection = {
|
|
573
|
+
ILProtection: new CryptoAmount(baseAmount(maxILP), AssetRuneNative),
|
|
574
|
+
totalDays: (fractionOfFullILPProtection * 100).toFixed(2),
|
|
575
|
+
};
|
|
576
|
+
return ILProtection;
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
const defaultMidgardConfig = {
|
|
580
|
+
mainnet: {
|
|
581
|
+
apiRetries: 3,
|
|
582
|
+
midgardBaseUrls: ['https://midgard.ninerealms.com'],
|
|
583
|
+
},
|
|
584
|
+
stagenet: {
|
|
585
|
+
apiRetries: 3,
|
|
586
|
+
midgardBaseUrls: ['https://stagenet-midgard.ninerealms.com'],
|
|
587
|
+
},
|
|
588
|
+
testnet: {
|
|
589
|
+
apiRetries: 3,
|
|
590
|
+
midgardBaseUrls: ['https://testnet.midgard.thorchain.info'],
|
|
591
|
+
},
|
|
592
|
+
};
|
|
593
|
+
class Midgard {
|
|
594
|
+
constructor(network = Network.Mainnet, config) {
|
|
595
|
+
this.network = network;
|
|
596
|
+
this.config = config !== null && config !== void 0 ? config : defaultMidgardConfig[this.network];
|
|
597
|
+
axiosRetry(axios, { retries: this.config.apiRetries, retryDelay: axiosRetry.exponentialDelay });
|
|
598
|
+
this.midgardApis = this.config.midgardBaseUrls.map((url) => new MidgardApi(new Configuration({ basePath: url })));
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
*
|
|
602
|
+
* @returns an array of Pools
|
|
603
|
+
*/
|
|
604
|
+
getPools() {
|
|
605
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
606
|
+
for (const api of this.midgardApis) {
|
|
607
|
+
try {
|
|
608
|
+
return (yield api.getPools()).data;
|
|
609
|
+
}
|
|
610
|
+
catch (e) {
|
|
611
|
+
//console.error(e)
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
throw new Error(`Midgard not responding`);
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Gets the latest block using the Health endpoint within Midgard
|
|
619
|
+
*
|
|
620
|
+
* @returns
|
|
621
|
+
*/
|
|
622
|
+
getLatestBlockHeight() {
|
|
623
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
624
|
+
for (const api of this.midgardApis) {
|
|
625
|
+
try {
|
|
626
|
+
const data = (yield api.getHealth()).data;
|
|
627
|
+
return +data.scannerHeight;
|
|
628
|
+
}
|
|
629
|
+
catch (e) {
|
|
630
|
+
//console.error(e)
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
throw Error(`Midgard not responding`);
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Gets actions object for any of the parameters
|
|
638
|
+
* @param txHash transaction id
|
|
639
|
+
* @returns Type Action array of objects
|
|
640
|
+
*/
|
|
641
|
+
getActions(address, txid, asset, type, affiliate, limit, offset) {
|
|
642
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
643
|
+
for (const api of this.midgardApis) {
|
|
644
|
+
try {
|
|
645
|
+
const actions = (yield api.getActions(address, txid, asset, type, affiliate, limit, offset)).data.actions;
|
|
646
|
+
return actions;
|
|
647
|
+
}
|
|
648
|
+
catch (e) {
|
|
649
|
+
//console.error(e)
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
throw Error(`Midgard not responding`);
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Function to return member details based on valid liquidity position
|
|
657
|
+
* @param address - needed to query for Lp details
|
|
658
|
+
* @returns - object type of Member Detail
|
|
659
|
+
*/
|
|
660
|
+
getMember(address) {
|
|
661
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
662
|
+
for (const api of this.midgardApis) {
|
|
663
|
+
try {
|
|
664
|
+
const memberDetail = (yield api.getMemberDetail(address)).data;
|
|
665
|
+
return memberDetail;
|
|
666
|
+
}
|
|
667
|
+
catch (e) {
|
|
668
|
+
//console.error(e)
|
|
669
|
+
}
|
|
548
670
|
}
|
|
549
|
-
|
|
550
|
-
|
|
671
|
+
throw Error(`Midgard not responding`);
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Function to return pool statistics for a particular asset
|
|
676
|
+
* @param asset - asset string to query its pool stats
|
|
677
|
+
* @returns - type object poolstatsDetail
|
|
678
|
+
*/
|
|
679
|
+
getPoolStats(asset) {
|
|
680
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
681
|
+
for (const api of this.midgardApis) {
|
|
682
|
+
try {
|
|
683
|
+
const poolDetail = (yield api.getPoolStats(asset)).data;
|
|
684
|
+
return poolDetail;
|
|
685
|
+
}
|
|
686
|
+
catch (e) {
|
|
687
|
+
//console.error(e)
|
|
688
|
+
}
|
|
551
689
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
case THORChain:
|
|
555
|
-
return new CryptoAmount(baseAmount(2000000), AssetRuneNative);
|
|
690
|
+
throw Error(`Midgard not responding`);
|
|
691
|
+
});
|
|
556
692
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
*
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
return new CryptoAmount(baseAmount(inbound.outboundFee), AssetBNB);
|
|
584
|
-
case ETHChain:
|
|
585
|
-
return new CryptoAmount(baseAmount(inbound.outboundFee.multipliedBy(Math.pow(10, 9)), 18), AssetETH);
|
|
586
|
-
case AVAXChain:
|
|
587
|
-
return new CryptoAmount(baseAmount(inbound.outboundFee.multipliedBy(Math.pow(10, 9)), 18), AssetAVAX);
|
|
588
|
-
case GAIAChain:
|
|
589
|
-
return new CryptoAmount(baseAmount(inbound.outboundFee), AssetATOM);
|
|
590
|
-
case THORChain:
|
|
591
|
-
return new CryptoAmount(baseAmount(2000000), AssetRuneNative);
|
|
693
|
+
/**
|
|
694
|
+
* Function to return THORNameDetails for a particular name
|
|
695
|
+
* @param name - thorname string to query
|
|
696
|
+
* @returns - type object THORNameDetails
|
|
697
|
+
*/
|
|
698
|
+
getTHORNameDetails(name) {
|
|
699
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
700
|
+
for (const api of this.midgardApis) {
|
|
701
|
+
try {
|
|
702
|
+
const resp = yield api.getTHORNameDetail(name);
|
|
703
|
+
if (resp.status == 404) {
|
|
704
|
+
return undefined;
|
|
705
|
+
}
|
|
706
|
+
else if (resp.status == 200) {
|
|
707
|
+
return resp.data;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
catch (e) {
|
|
711
|
+
// if (resp.status == 404) {
|
|
712
|
+
// return undefined
|
|
713
|
+
// }
|
|
714
|
+
//console.error(e)
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
throw Error(`Midgard not responding`);
|
|
718
|
+
});
|
|
592
719
|
}
|
|
593
|
-
|
|
594
|
-
};
|
|
720
|
+
}
|
|
595
721
|
|
|
596
722
|
const defaultThornodeConfig = {
|
|
597
723
|
mainnet: {
|
|
@@ -1356,97 +1482,6 @@ class ThorchainCache {
|
|
|
1356
1482
|
}
|
|
1357
1483
|
}
|
|
1358
1484
|
|
|
1359
|
-
/**
|
|
1360
|
-
* https://dev.thorchain.org/thorchain-dev/interface-guide/math#lp-units-add
|
|
1361
|
-
* @param liquidity - asset amount added
|
|
1362
|
-
* @param pool - pool depths
|
|
1363
|
-
* @returns liquidity units - ownership of pool
|
|
1364
|
-
*/
|
|
1365
|
-
const getLiquidityUnits = (liquidity, pool) => {
|
|
1366
|
-
const baseAmount8decimals = getBaseAmountWithDiffDecimals(liquidity.asset, 8);
|
|
1367
|
-
const P = new BigNumber(pool.pool.liquidityUnits);
|
|
1368
|
-
const r = liquidity.rune.baseAmount.amount();
|
|
1369
|
-
const a = baseAmount8decimals;
|
|
1370
|
-
const R = pool.runeBalance.amount();
|
|
1371
|
-
const A = pool.assetBalance.amount();
|
|
1372
|
-
const part1 = R.times(a);
|
|
1373
|
-
const part2 = r.times(A);
|
|
1374
|
-
const numerator = P.times(part1.plus(part2));
|
|
1375
|
-
const denominator = R.times(A).times(2);
|
|
1376
|
-
const result = numerator.div(denominator);
|
|
1377
|
-
return result;
|
|
1378
|
-
};
|
|
1379
|
-
/**
|
|
1380
|
-
*
|
|
1381
|
-
* @param unitData - units for both asset and rune
|
|
1382
|
-
* @param pool - pool that the asset is bound to
|
|
1383
|
-
* @returns - pool share of both asset and rune in percentage
|
|
1384
|
-
*/
|
|
1385
|
-
const getPoolShare = (unitData, pool) => {
|
|
1386
|
-
// formula: (rune * part) / total; (asset * part) / total
|
|
1387
|
-
const units = unitData.liquidityUnits;
|
|
1388
|
-
const total = unitData.totalUnits;
|
|
1389
|
-
const R = pool.runeBalance.amount();
|
|
1390
|
-
const T = pool.assetBalance.amount();
|
|
1391
|
-
const asset = T.times(units).div(total);
|
|
1392
|
-
const rune = R.times(units).div(total);
|
|
1393
|
-
const poolShareDetail = {
|
|
1394
|
-
assetShare: new CryptoAmount(baseAmount(asset), pool.asset),
|
|
1395
|
-
runeShare: new CryptoAmount(baseAmount(rune), AssetRuneNative),
|
|
1396
|
-
};
|
|
1397
|
-
return poolShareDetail;
|
|
1398
|
-
};
|
|
1399
|
-
/**
|
|
1400
|
-
*
|
|
1401
|
-
* @param poolShare - the share of asset and rune added to the pool
|
|
1402
|
-
* @param pool - Pool that the asset is attached to
|
|
1403
|
-
* @returns - returns bignumber representing a slip percentage
|
|
1404
|
-
*/
|
|
1405
|
-
const getSlipOnLiquidity = (stake, pool) => {
|
|
1406
|
-
const baseAmount8decimals = getBaseAmountWithDiffDecimals(stake.asset, 8);
|
|
1407
|
-
// formula: (t * R - T * r)/ (T*r + R*T)
|
|
1408
|
-
const r = stake.rune.baseAmount.amount();
|
|
1409
|
-
const t = baseAmount8decimals;
|
|
1410
|
-
const R = pool.runeBalance.amount();
|
|
1411
|
-
const T = pool.assetBalance.amount();
|
|
1412
|
-
const numerator = t.times(R).minus(T.times(r));
|
|
1413
|
-
const denominator = T.times(r).plus(R.times(T));
|
|
1414
|
-
const result = numerator.div(denominator).abs();
|
|
1415
|
-
return result;
|
|
1416
|
-
};
|
|
1417
|
-
/**
|
|
1418
|
-
* https://docs.thorchain.org/thorchain-finance/continuous-liquidity-pools#impermanent-loss-protection
|
|
1419
|
-
* @param poolShare - the share of asset and rune added to the pool
|
|
1420
|
-
* @param pool - Pool that the asset is attached to
|
|
1421
|
-
* @param block - blockl object with current, last added and the constant blocksforlossProtection
|
|
1422
|
-
* @returns
|
|
1423
|
-
*/
|
|
1424
|
-
// Blocks for full protection 1440000 // 100 days
|
|
1425
|
-
const getLiquidityProtectionData = (depositValue, poolShare, block) => {
|
|
1426
|
-
//Coverage formula coverage=((A0∗P1)+R0)−((A1∗P1)+R1)=>((A0∗R1/A1)+R0)−(R1+R1)
|
|
1427
|
-
//formula: protectionProgress (currentHeight-heightLastAdded)/blocksforfullprotection
|
|
1428
|
-
const R0 = depositValue.rune.amount(); // rune deposit value
|
|
1429
|
-
const A0 = depositValue.asset.amount(); // asset deposit value
|
|
1430
|
-
const R1 = poolShare.runeShare.baseAmount.amount(); // rune amount to redeem
|
|
1431
|
-
const A1 = poolShare.assetShare.baseAmount.amount(); // asset amount to redeem
|
|
1432
|
-
const P1 = R1.div(A1); // Pool ratio at withdrawal
|
|
1433
|
-
const part1 = A0.times(P1).plus(R0).minus(A1.times(P1).plus(R1)); // start position minus end position
|
|
1434
|
-
const part2 = A0.times(R1.div(A1)).plus(R0).minus(R1.plus(R1)); // different way to check position
|
|
1435
|
-
const coverage = part1 >= part2 ? part1 : part2; // Coverage represents how much ILP a LP is entitled to
|
|
1436
|
-
const currentHeight = block.current;
|
|
1437
|
-
const heightLastAdded = block.lastAdded || 0; //default to zero if undefined
|
|
1438
|
-
const blocksforfullprotection = block.fullProtection;
|
|
1439
|
-
const fractionOfFullILPProtection = (currentHeight - heightLastAdded) / blocksforfullprotection;
|
|
1440
|
-
const protectionProgress = Math.min(fractionOfFullILPProtection, 1); // percentage of entitlement, max 100%
|
|
1441
|
-
const result = coverage.times(protectionProgress); // impermanent loss protection result
|
|
1442
|
-
const maxILP = result.lt(0) ? new BigNumber(0) : result; // max negative ILP to 0
|
|
1443
|
-
const ILProtection = {
|
|
1444
|
-
ILProtection: new CryptoAmount(baseAmount(maxILP), AssetRuneNative),
|
|
1445
|
-
totalDays: (fractionOfFullILPProtection * 100).toFixed(2),
|
|
1446
|
-
};
|
|
1447
|
-
return ILProtection;
|
|
1448
|
-
};
|
|
1449
|
-
|
|
1450
1485
|
const BN_1 = new BigNumber(1);
|
|
1451
1486
|
const defaultCache = new ThorchainCache();
|
|
1452
1487
|
/**
|
|
@@ -2149,6 +2184,20 @@ class ThorchainQuery {
|
|
|
2149
2184
|
rune: new CryptoAmount(assetToBase(assetAmount(0)), AssetRuneNative),
|
|
2150
2185
|
};
|
|
2151
2186
|
return dustValues;
|
|
2187
|
+
case 'BSC':
|
|
2188
|
+
// 0 BSC
|
|
2189
|
+
dustValues = {
|
|
2190
|
+
asset: new CryptoAmount(assetToBase(assetAmount(0)), asset),
|
|
2191
|
+
rune: new CryptoAmount(assetToBase(assetAmount(0)), AssetRuneNative),
|
|
2192
|
+
};
|
|
2193
|
+
return dustValues;
|
|
2194
|
+
case 'MAYA':
|
|
2195
|
+
// 0 MAYA
|
|
2196
|
+
dustValues = {
|
|
2197
|
+
asset: new CryptoAmount(assetToBase(assetAmount(0)), asset),
|
|
2198
|
+
rune: new CryptoAmount(assetToBase(assetAmount(0)), AssetRuneNative),
|
|
2199
|
+
};
|
|
2200
|
+
return dustValues;
|
|
2152
2201
|
default:
|
|
2153
2202
|
throw Error('Unknown chain');
|
|
2154
2203
|
}
|
|
@@ -2159,7 +2208,17 @@ class ThorchainQuery {
|
|
|
2159
2208
|
estimateAddSaver(addAmount) {
|
|
2160
2209
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2161
2210
|
let errors = [];
|
|
2211
|
+
// check for errors before sending quote
|
|
2162
2212
|
errors = yield this.getAddSaversEstimateErrors(addAmount);
|
|
2213
|
+
// request param amount should always be in 1e8 which is why we pass in adjusted decimals if chain decimals != 8
|
|
2214
|
+
const newAddAmount = addAmount.baseAmount.decimal != 8 ? getBaseAmountWithDiffDecimals(addAmount, 8) : addAmount.baseAmount.amount();
|
|
2215
|
+
// Fetch quote
|
|
2216
|
+
const depositQuote = yield this.thorchainCache.thornode.getSaversDepositQuote(assetToString(addAmount.asset), newAddAmount.toNumber());
|
|
2217
|
+
// error handling
|
|
2218
|
+
const response = JSON.parse(JSON.stringify(depositQuote));
|
|
2219
|
+
if (response.error)
|
|
2220
|
+
errors.push(`Thornode request quote failed: ${response.error}`);
|
|
2221
|
+
// Return errors if there is any
|
|
2163
2222
|
if (errors.length > 0) {
|
|
2164
2223
|
return {
|
|
2165
2224
|
assetAmount: addAmount,
|
|
@@ -2179,29 +2238,27 @@ class ThorchainQuery {
|
|
|
2179
2238
|
errors,
|
|
2180
2239
|
};
|
|
2181
2240
|
}
|
|
2182
|
-
// request param amount should always be in 1e8 which is why we pass in adjusted decimals if chain decimals != 8
|
|
2183
|
-
const newAddAmount = addAmount.baseAmount.decimal != 8 ? getBaseAmountWithDiffDecimals(addAmount, 8) : addAmount.baseAmount.amount();
|
|
2184
|
-
const depositQuote = yield this.thorchainCache.thornode.getSaversDepositQuote(assetToString(addAmount.asset), newAddAmount.toNumber());
|
|
2185
2241
|
// Calculate transaction expiry time of the vault address
|
|
2186
2242
|
const currentDatetime = new Date();
|
|
2187
2243
|
const minutesToAdd = 15;
|
|
2188
2244
|
const expiryDatetime = new Date(currentDatetime.getTime() + minutesToAdd * 60000);
|
|
2245
|
+
// Calculate seconds
|
|
2189
2246
|
const estimatedWait = depositQuote.inbound_confirmation_seconds
|
|
2190
2247
|
? depositQuote.inbound_confirmation_seconds
|
|
2191
2248
|
: yield this.confCounting(addAmount);
|
|
2192
2249
|
const pool = (yield this.thorchainCache.getPoolForAsset(addAmount.asset)).pool;
|
|
2193
|
-
|
|
2194
|
-
errors.push(`Amount being added to savers can't pay for fees`);
|
|
2250
|
+
// Organise fees
|
|
2195
2251
|
const saverFees = {
|
|
2196
2252
|
affiliate: new CryptoAmount(baseAmount(depositQuote.fees.affiliate), addAmount.asset),
|
|
2197
2253
|
asset: assetFromStringEx(depositQuote.fees.asset),
|
|
2198
2254
|
outbound: new CryptoAmount(baseAmount(depositQuote.fees.outbound), addAmount.asset),
|
|
2199
2255
|
};
|
|
2256
|
+
// define savers cap
|
|
2200
2257
|
const saverCap = 0.3 * +pool.assetDepth;
|
|
2201
2258
|
const saverCapFilledPercent = (+pool.saversDepth / saverCap) * 100;
|
|
2202
2259
|
const estimateAddSaver = {
|
|
2203
2260
|
assetAmount: new CryptoAmount(baseAmount(depositQuote.expected_amount_out), addAmount.asset),
|
|
2204
|
-
estimatedDepositValue: new CryptoAmount(baseAmount(depositQuote.
|
|
2261
|
+
estimatedDepositValue: new CryptoAmount(baseAmount(depositQuote.expected_amount_deposit), addAmount.asset),
|
|
2205
2262
|
fee: saverFees,
|
|
2206
2263
|
expiry: expiryDatetime,
|
|
2207
2264
|
toAddress: depositQuote.inbound_address,
|
|
@@ -2222,12 +2279,56 @@ class ThorchainQuery {
|
|
|
2222
2279
|
*/
|
|
2223
2280
|
estimateWithdrawSaver(withdrawParams) {
|
|
2224
2281
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2282
|
+
const errors = [];
|
|
2283
|
+
// return error if Asset in is incorrect
|
|
2225
2284
|
if (isAssetRuneNative(withdrawParams.asset) || withdrawParams.asset.synth)
|
|
2226
|
-
|
|
2285
|
+
errors.push(`Native Rune and synth assets are not supported only L1's`);
|
|
2286
|
+
const inboundDetails = yield this.thorchainCache.getInboundDetails();
|
|
2287
|
+
// Check to see if there is a position before calling withdraw quote
|
|
2288
|
+
const checkPositon = yield this.getSaverPosition(withdrawParams);
|
|
2289
|
+
if (checkPositon.errors.length > 0) {
|
|
2290
|
+
for (let i = 0; i < checkPositon.errors.length; i++) {
|
|
2291
|
+
errors.push(checkPositon.errors[i]);
|
|
2292
|
+
}
|
|
2293
|
+
return {
|
|
2294
|
+
expectedAssetAmount: new CryptoAmount(assetToBase(assetAmount(checkPositon.redeemableValue.assetAmount.amount())), withdrawParams.asset),
|
|
2295
|
+
fee: {
|
|
2296
|
+
affiliate: new CryptoAmount(assetToBase(assetAmount(0)), withdrawParams.asset),
|
|
2297
|
+
asset: withdrawParams.asset,
|
|
2298
|
+
outbound: new CryptoAmount(assetToBase(assetAmount(calcOutboundFee(withdrawParams.asset, inboundDetails[withdrawParams.asset.chain]).assetAmount.amount())), withdrawParams.asset),
|
|
2299
|
+
},
|
|
2300
|
+
expiry: new Date(0),
|
|
2301
|
+
toAddress: '',
|
|
2302
|
+
memo: '',
|
|
2303
|
+
estimatedWaitTime: -1,
|
|
2304
|
+
slipBasisPoints: -1,
|
|
2305
|
+
dustAmount: new CryptoAmount(baseAmount(0), withdrawParams.asset),
|
|
2306
|
+
errors,
|
|
2307
|
+
};
|
|
2308
|
+
}
|
|
2309
|
+
// Request withdraw quote
|
|
2227
2310
|
const withdrawQuote = yield this.thorchainCache.thornode.getSaversWithdrawQuote(withdrawParams);
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2311
|
+
// error handling
|
|
2312
|
+
const response = JSON.parse(JSON.stringify(withdrawQuote));
|
|
2313
|
+
if (response.error)
|
|
2314
|
+
errors.push(`Thornode request quote failed: ${response.error}`);
|
|
2315
|
+
if (errors.length > 0) {
|
|
2316
|
+
return {
|
|
2317
|
+
expectedAssetAmount: new CryptoAmount(assetToBase(assetAmount(0)), withdrawParams.asset),
|
|
2318
|
+
fee: {
|
|
2319
|
+
affiliate: new CryptoAmount(assetToBase(assetAmount(0)), withdrawParams.asset),
|
|
2320
|
+
asset: withdrawParams.asset,
|
|
2321
|
+
outbound: new CryptoAmount(assetToBase(assetAmount(0)), withdrawParams.asset),
|
|
2322
|
+
},
|
|
2323
|
+
expiry: new Date(0),
|
|
2324
|
+
toAddress: '',
|
|
2325
|
+
memo: '',
|
|
2326
|
+
estimatedWaitTime: -1,
|
|
2327
|
+
slipBasisPoints: -1,
|
|
2328
|
+
dustAmount: new CryptoAmount(baseAmount(0), withdrawParams.asset),
|
|
2329
|
+
errors,
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2231
2332
|
// Calculate transaction expiry time of the vault address
|
|
2232
2333
|
const currentDatetime = new Date();
|
|
2233
2334
|
const minutesToAdd = 15;
|
|
@@ -2247,6 +2348,7 @@ class ThorchainQuery {
|
|
|
2247
2348
|
estimatedWaitTime: estimatedWait,
|
|
2248
2349
|
slipBasisPoints: withdrawQuote.slippage_bps,
|
|
2249
2350
|
dustAmount: new CryptoAmount(baseAmount(withdrawQuote.dust_amount), withdrawParams.asset),
|
|
2351
|
+
errors,
|
|
2250
2352
|
};
|
|
2251
2353
|
return estimateWithdrawSaver;
|
|
2252
2354
|
});
|
|
@@ -2258,31 +2360,37 @@ class ThorchainQuery {
|
|
|
2258
2360
|
*/
|
|
2259
2361
|
getSaverPosition(params) {
|
|
2260
2362
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2363
|
+
const errors = [];
|
|
2364
|
+
const inboundDetails = yield this.thorchainCache.getInboundDetails();
|
|
2261
2365
|
const blockData = (yield this.thorchainCache.thornode.getLastBlock()).find((item) => item.chain === params.asset.chain);
|
|
2262
2366
|
const savers = (yield this.thorchainCache.thornode.getSavers(`${params.asset.chain}.${params.asset.ticker}`)).find((item) => item.asset_address === params.address);
|
|
2263
2367
|
const pool = (yield this.thorchainCache.getPoolForAsset(params.asset)).pool;
|
|
2264
2368
|
if (!savers)
|
|
2265
|
-
|
|
2266
|
-
if (!savers.last_add_height)
|
|
2267
|
-
|
|
2369
|
+
errors.push(`Could not find position for ${params.address}`);
|
|
2370
|
+
if (!(savers === null || savers === void 0 ? void 0 : savers.last_add_height))
|
|
2371
|
+
errors.push(`Could not find position for ${params.address}`);
|
|
2268
2372
|
if (!(blockData === null || blockData === void 0 ? void 0 : blockData.thorchain))
|
|
2269
|
-
|
|
2270
|
-
const
|
|
2271
|
-
|
|
2373
|
+
errors.push(`Could not get thorchain block height`);
|
|
2374
|
+
const outboundFee = yield calcOutboundFee(params.asset, inboundDetails[params.asset.chain]);
|
|
2375
|
+
if (Number(savers === null || savers === void 0 ? void 0 : savers.asset_redeem_value) < outboundFee.baseAmount.amount().toNumber())
|
|
2376
|
+
errors.push(`Unlikely to withdraw balance as outbound fee is greater than redeemable amount`);
|
|
2377
|
+
const ownerUnits = Number(savers === null || savers === void 0 ? void 0 : savers.units);
|
|
2378
|
+
const lastAdded = Number(savers === null || savers === void 0 ? void 0 : savers.last_add_height);
|
|
2272
2379
|
const saverUnits = Number(pool.saversUnits);
|
|
2273
2380
|
const assetDepth = Number(pool.saversDepth);
|
|
2274
2381
|
const redeemableValue = (ownerUnits / saverUnits) * assetDepth;
|
|
2275
|
-
const depositAmount = new CryptoAmount(baseAmount(savers.asset_deposit_value), params.asset);
|
|
2382
|
+
const depositAmount = new CryptoAmount(baseAmount(savers === null || savers === void 0 ? void 0 : savers.asset_deposit_value), params.asset);
|
|
2276
2383
|
const redeemableAssetAmount = new CryptoAmount(baseAmount(redeemableValue), params.asset);
|
|
2277
|
-
const saversAge = ((blockData === null || blockData === void 0 ? void 0 : blockData.thorchain) - lastAdded) / ((365 * 86400) / 6);
|
|
2384
|
+
const saversAge = (Number(blockData === null || blockData === void 0 ? void 0 : blockData.thorchain) - lastAdded) / ((365 * 86400) / 6);
|
|
2278
2385
|
const saverGrowth = redeemableAssetAmount.minus(depositAmount).div(depositAmount).times(100);
|
|
2279
2386
|
const saversPos = {
|
|
2280
2387
|
depositValue: depositAmount,
|
|
2281
2388
|
redeemableValue: redeemableAssetAmount,
|
|
2282
|
-
lastAddHeight: savers.last_add_height,
|
|
2389
|
+
lastAddHeight: Number(savers === null || savers === void 0 ? void 0 : savers.last_add_height),
|
|
2283
2390
|
percentageGrowth: saverGrowth.assetAmount.amount().toNumber(),
|
|
2284
2391
|
ageInYears: saversAge,
|
|
2285
2392
|
ageInDays: saversAge * 365,
|
|
2393
|
+
errors,
|
|
2286
2394
|
};
|
|
2287
2395
|
return saversPos;
|
|
2288
2396
|
});
|
|
@@ -2301,6 +2409,9 @@ class ThorchainQuery {
|
|
|
2301
2409
|
const pool = (yield this.thorchainCache.getPoolForAsset(addAmount.asset)).pool;
|
|
2302
2410
|
if (pool.status.toLowerCase() !== 'available')
|
|
2303
2411
|
errors.push(`Pool is not available for this asset ${assetToString(addAmount.asset)}`);
|
|
2412
|
+
const inboundFee = calcNetworkFee(addAmount.asset, inboundDetails[addAmount.asset.chain]);
|
|
2413
|
+
if (addAmount.lte(inboundFee))
|
|
2414
|
+
errors.push(`Add amount does not cover fees`);
|
|
2304
2415
|
return errors;
|
|
2305
2416
|
});
|
|
2306
2417
|
}
|
|
@@ -2740,4 +2851,4 @@ class TransactionStage {
|
|
|
2740
2851
|
}
|
|
2741
2852
|
}
|
|
2742
2853
|
|
|
2743
|
-
export { AddLpStatus, AddSaverStatus, CryptoAmount, InboundStatus, LiquidityPool, Midgard, RefundStatus, SwapStatus, ThorchainCache, ThorchainQuery, Thornode, TransactionStage, TxType, WithdrawStatus, calcNetworkFee, getDoubleSwap, getLiquidityProtectionData, getLiquidityUnits, getPoolShare, getSingleSwap, getSlipOnLiquidity };
|
|
2854
|
+
export { AVAXChain, AddLpStatus, AddSaverStatus, AssetATOM, AssetAVAX, AssetBCH, AssetBNB, AssetBSC, AssetBTC, AssetDOGE, AssetETH, AssetLTC, AssetMAYA, AssetRuneNative, BCHChain, BNBChain, BSCChain, BTCChain, CryptoAmount, DOGEChain, ETHChain, GAIAChain, InboundStatus, LTCChain, LiquidityPool, MAYAChain, Midgard, RefundStatus, SwapStatus, THORChain, ThorchainCache, ThorchainQuery, Thornode, TransactionStage, TxType, WithdrawStatus, calcNetworkFee, getDoubleSwap, getLiquidityProtectionData, getLiquidityUnits, getPoolShare, getSingleSwap, getSlipOnLiquidity, isAssetRuneNative };
|