@xchainjs/xchain-thorchain-query 0.1.4 → 0.1.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/README.md CHANGED
@@ -43,11 +43,13 @@ Estimation example from a swap of 2 BTC to RUNE
43
43
 
44
44
  ## Documentation
45
45
 
46
+ [`Overview `](https://dev.thorchain.org/thorchain-dev/xchainjs-integration-guide/query-package)
47
+
46
48
  For bash exmples, see example folder at the base of this repository xchainjs/xchainjs-lib.
47
49
 
48
50
  ### [`xchain-thorchain-query`](http://docs.xchainjs.org/xchain-thorchain-query/)
49
51
 
50
- [`How xchain-thorchain-query works`](http://docs.xchainjs.org/xchain-thorchain-query/how-it-works.html)\
52
+ [`How xchain-thorchain-query works`](http://docs.xchainjs.org/xchain-thorchain-query/how-it-works.html)
51
53
  [`How to use xchain-thorchain-query`](http://docs.xchainjs.org/xchain-thorchain-query/how-to-use.html)
52
54
 
53
55
  For Live examples
package/lib/index.esm.js CHANGED
@@ -427,6 +427,7 @@ const getBaseAmountWithDiffDecimals = (inputAmount, outDecimals) => {
427
427
  const getSwapFee = (inputAmount, pool, toRune) => {
428
428
  // formula: (x * x * Y) / (x + X) ^ 2
429
429
  // const isInputRune = isAssetRuneNative(inputAmount.asset)
430
+ const decimalsOut = pool.pool.nativeDecimal !== '-1' ? Number(pool.pool.nativeDecimal) : inputAmount.baseAmount.decimal;
430
431
  const x = getBaseAmountWithDiffDecimals(inputAmount, 8);
431
432
  const X = toRune ? pool.assetBalance.amount() : pool.runeBalance.amount(); // input is asset if toRune
432
433
  const Y = toRune ? pool.runeBalance.amount() : pool.assetBalance.amount(); // output is rune if toRune
@@ -435,7 +436,7 @@ const getSwapFee = (inputAmount, pool, toRune) => {
435
436
  const denominator = x.plus(X).pow(2);
436
437
  const result = numerator.div(denominator);
437
438
  const eightDecimalResult = new CryptoAmount(baseAmount(result), units);
438
- const decimals = toRune ? 8 : inputAmount.baseAmount.decimal;
439
+ const decimals = toRune ? 8 : decimalsOut;
439
440
  const baseOut = getBaseAmountWithDiffDecimals(eightDecimalResult, decimals);
440
441
  const swapFee = new CryptoAmount(baseAmount(baseOut, decimals), units);
441
442
  //console.log(` swapFee ${swapFee.assetAmountFixedString()} `)
@@ -465,6 +466,7 @@ const getSwapSlip = (inputAmount, pool, toRune) => {
465
466
  */
466
467
  const getSwapOutput = (inputAmount, pool, toRune) => {
467
468
  // formula: (x * X * Y) / (x + X) ^ 2
469
+ const decimalsOut = pool.pool.nativeDecimal !== '-1' ? Number(pool.pool.nativeDecimal) : inputAmount.baseAmount.decimal;
468
470
  const x = getBaseAmountWithDiffDecimals(inputAmount, 8);
469
471
  const X = toRune ? pool.assetBalance.amount() : pool.runeBalance.amount(); // input is asset if toRune
470
472
  const Y = toRune ? pool.runeBalance.amount() : pool.assetBalance.amount(); // output is rune if toRune
@@ -474,7 +476,7 @@ const getSwapOutput = (inputAmount, pool, toRune) => {
474
476
  const denominator = x.plus(X).pow(2);
475
477
  const result = numerator.div(denominator);
476
478
  const eightDecimalResult = new CryptoAmount(baseAmount(result), units);
477
- const decimals = toRune ? 8 : inputAmount.baseAmount.decimal;
479
+ const decimals = toRune ? 8 : decimalsOut;
478
480
  const baseOut = getBaseAmountWithDiffDecimals(eightDecimalResult, decimals);
479
481
  return new CryptoAmount(baseAmount(baseOut, decimals), units);
480
482
  };
@@ -585,6 +587,42 @@ const calcNetworkFee = (asset, inbound) => {
585
587
  }
586
588
  throw new Error(`could not calculate inbound fee for ${asset.chain}`);
587
589
  };
590
+ /**
591
+ * Works out the required outbound fee based on the chain.
592
+ * Call getInboundDetails to get the current outbound fee
593
+ *
594
+ * @param sourceAsset
595
+ * @param inbound detail
596
+ * @see https://dev.thorchain.org/thorchain-dev/thorchain-and-fees#fee-calcuation-by-chain
597
+ * @returns
598
+ */
599
+ const calcOutboundFee = (asset, inbound) => {
600
+ if (asset.synth)
601
+ return new CryptoAmount(baseAmount(2000000), AssetRuneNative);
602
+ switch (asset.chain) {
603
+ case Chain.Bitcoin:
604
+ return new CryptoAmount(baseAmount(inbound.outboundFee), AssetBTC);
605
+ case Chain.BitcoinCash:
606
+ return new CryptoAmount(baseAmount(inbound.outboundFee), AssetBCH);
607
+ case Chain.Litecoin:
608
+ return new CryptoAmount(baseAmount(inbound.outboundFee), AssetLTC);
609
+ case Chain.Doge:
610
+ // NOTE: UTXO chains estimate fees with a 250 byte size
611
+ return new CryptoAmount(baseAmount(inbound.outboundFee), AssetDOGE);
612
+ case Chain.Binance:
613
+ //flat fee
614
+ return new CryptoAmount(baseAmount(inbound.outboundFee), AssetBNB);
615
+ case Chain.Ethereum:
616
+ return new CryptoAmount(baseAmount(inbound.outboundFee.multipliedBy(Math.pow(10, 9)), 18), AssetETH);
617
+ case Chain.Avalanche:
618
+ return new CryptoAmount(baseAmount(inbound.outboundFee.multipliedBy(Math.pow(10, 9)), 18), AssetAVAX);
619
+ case Chain.Cosmos:
620
+ return new CryptoAmount(baseAmount(inbound.outboundFee), AssetAtom);
621
+ case Chain.THORChain:
622
+ return new CryptoAmount(baseAmount(2000000), AssetRuneNative);
623
+ }
624
+ throw new Error(`could not calculate outbound fee for ${asset.chain}`);
625
+ };
588
626
  /**
589
627
  * Return the chain for a given Asset This method should live somewhere else.
590
628
  * @param chain
@@ -829,14 +867,12 @@ class ThorchainCache {
829
867
  * @param expireNetworkValuesCacheMillis - how long should the Mimir/Constants be cached before expiry
830
868
  * @returns ThorchainCache
831
869
  */
832
- constructor(midgard = defaultMidgard, thornode = defaultThornode, expirePoolCacheMillis = 6000, expireAsgardCacheMillis = TEN_MINUTES, expireInboundDetailsCacheMillis = 6000, expireNetworkValuesCacheMillis = TEN_MINUTES) {
833
- this.asgardAssetsCache = undefined;
870
+ constructor(midgard = defaultMidgard, thornode = defaultThornode, expirePoolCacheMillis = 6000, expireInboundDetailsCacheMillis = 6000, expireNetworkValuesCacheMillis = TEN_MINUTES) {
834
871
  this.inboundDetailCache = undefined;
835
872
  this.networkValuesCache = undefined;
836
873
  this.midgard = midgard;
837
874
  this.thornode = thornode;
838
875
  this.expirePoolCacheMillis = expirePoolCacheMillis;
839
- this.expireAsgardCacheMillis = expireAsgardCacheMillis;
840
876
  this.expireInboundDetailsCacheMillis = expireInboundDetailsCacheMillis;
841
877
  this.expireNetworkValuesCacheMillis = expireNetworkValuesCacheMillis;
842
878
  //initialize the cache
@@ -946,29 +982,6 @@ class ThorchainCache {
946
982
  }
947
983
  });
948
984
  }
949
- /**
950
- * Refreshes the asgardAssetsCache Cache
951
- *
952
- * NOTE: do not call refereshAsgardCache() directly, call getAsgardAssets() instead
953
- * which will refresh the cache if it's expired
954
- */
955
- refereshAsgardCache() {
956
- return __awaiter(this, void 0, void 0, function* () {
957
- const inboundAddresses = yield this.thornode.getInboundAddresses();
958
- const map = {};
959
- if (inboundAddresses) {
960
- for (const inboundAddress of inboundAddresses) {
961
- if (!inboundAddress.chain)
962
- throw Error('chain needed');
963
- map[inboundAddress.chain] = inboundAddress;
964
- }
965
- this.asgardAssetsCache = {
966
- lastRefreshed: Date.now(),
967
- inboundAddresses: map,
968
- };
969
- }
970
- });
971
- }
972
985
  /**
973
986
  * Refreshes the InboundDetailCache Cache
974
987
  *
@@ -1055,22 +1068,26 @@ class ThorchainCache {
1055
1068
  */
1056
1069
  getExpectedSwapOutput(inputAmount, destinationAsset) {
1057
1070
  return __awaiter(this, void 0, void 0, function* () {
1071
+ let swapOutput;
1058
1072
  if (isAssetRuneNative(inputAmount.asset)) {
1059
1073
  //singleswap from rune -> asset
1060
1074
  const pool = yield this.getPoolForAsset(destinationAsset);
1061
- return getSingleSwap(inputAmount, pool, false);
1075
+ swapOutput = getSingleSwap(inputAmount, pool, false);
1062
1076
  }
1063
1077
  else if (isAssetRuneNative(destinationAsset)) {
1064
1078
  //singleswap from asset -> rune
1065
1079
  const pool = yield this.getPoolForAsset(inputAmount.asset);
1066
- return getSingleSwap(inputAmount, pool, true);
1080
+ swapOutput = getSingleSwap(inputAmount, pool, true);
1067
1081
  }
1068
1082
  else {
1069
1083
  //doubleswap asset-> asset
1070
1084
  const inPool = yield this.getPoolForAsset(inputAmount.asset);
1071
1085
  const destPool = yield this.getPoolForAsset(destinationAsset);
1072
- return yield getDoubleSwap(inputAmount, inPool, destPool, this);
1086
+ swapOutput = yield getDoubleSwap(inputAmount, inPool, destPool, this);
1073
1087
  }
1088
+ //Note this is needed to return a synth vs. a native asset on swap out
1089
+ swapOutput.output = new CryptoAmount(swapOutput.output.baseAmount, destinationAsset);
1090
+ return swapOutput;
1074
1091
  });
1075
1092
  }
1076
1093
  /**
@@ -1113,37 +1130,13 @@ class ThorchainCache {
1113
1130
  }
1114
1131
  getRouterAddressForChain(chain) {
1115
1132
  return __awaiter(this, void 0, void 0, function* () {
1116
- const inboundAsgard = (yield this.getInboundAddresses())[chain];
1133
+ const inboundAsgard = (yield this.getInboundDetails())[chain];
1117
1134
  if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.router)) {
1118
1135
  throw new Error('router address is not defined');
1119
1136
  }
1120
1137
  return inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.router;
1121
1138
  });
1122
1139
  }
1123
- /**
1124
- *
1125
- * @returns - inbound adresses item
1126
- */
1127
- getInboundAddresses() {
1128
- var _a;
1129
- return __awaiter(this, void 0, void 0, function* () {
1130
- const millisSinceLastRefeshed = Date.now() - (((_a = this.asgardAssetsCache) === null || _a === void 0 ? void 0 : _a.lastRefreshed) || 0);
1131
- if (millisSinceLastRefeshed > this.expireAsgardCacheMillis) {
1132
- try {
1133
- yield this.refereshAsgardCache();
1134
- }
1135
- catch (e) {
1136
- console.error(e);
1137
- }
1138
- }
1139
- if (this.asgardAssetsCache) {
1140
- return this.asgardAssetsCache.inboundAddresses;
1141
- }
1142
- else {
1143
- throw Error(`Could not refresh refereshAsgardCache `);
1144
- }
1145
- });
1146
- }
1147
1140
  /**
1148
1141
  *
1149
1142
  * @returns - inbound details
@@ -1327,7 +1320,8 @@ class ThorchainQuery {
1327
1320
 
1328
1321
  * @returns The SwapEstimate
1329
1322
  */
1330
- estimateSwap({ input, destinationAsset, destinationAddress, slipLimit, interfaceID = 999, affiliateAddress = '', affiliateFeePercent = 0, }) {
1323
+ estimateSwap({ input, destinationAsset, destinationAddress, slipLimit = new BigNumber('0.03'), //default to 3%
1324
+ interfaceID = '555', affiliateAddress = '', affiliateFeeBasisPoints = 0, }) {
1331
1325
  return __awaiter(this, void 0, void 0, function* () {
1332
1326
  yield this.isValidSwap({
1333
1327
  input,
@@ -1335,7 +1329,7 @@ class ThorchainQuery {
1335
1329
  destinationAddress,
1336
1330
  slipLimit,
1337
1331
  affiliateAddress,
1338
- affiliateFeePercent,
1332
+ affiliateFeeBasisPoints,
1339
1333
  interfaceID,
1340
1334
  });
1341
1335
  const inboundDetails = yield this.thorchainCache.getInboundDetails();
@@ -1348,7 +1342,7 @@ class ThorchainQuery {
1348
1342
  destinationAddress,
1349
1343
  slipLimit,
1350
1344
  affiliateAddress,
1351
- affiliateFeePercent,
1345
+ affiliateFeeBasisPoints,
1352
1346
  interfaceID,
1353
1347
  }, sourceInboundDetails, destinationInboundDetails);
1354
1348
  // Calculate transaction expiry time
@@ -1362,7 +1356,7 @@ class ThorchainQuery {
1362
1356
  destinationAddress,
1363
1357
  slipLimit,
1364
1358
  affiliateAddress,
1365
- affiliateFeePercent,
1359
+ affiliateFeeBasisPoints,
1366
1360
  interfaceID,
1367
1361
  }, swapEstimate, sourceInboundDetails, destinationInboundDetails);
1368
1362
  const txDetails = {
@@ -1377,7 +1371,7 @@ class ThorchainQuery {
1377
1371
  }
1378
1372
  else {
1379
1373
  txDetails.txEstimate.canSwap = true;
1380
- const inboundAsgard = (yield this.thorchainCache.getInboundAddresses())[input.asset.chain];
1374
+ const inboundAsgard = (yield this.thorchainCache.getInboundDetails())[input.asset.chain];
1381
1375
  txDetails.toAddress = (inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address) || '';
1382
1376
  // Work out LIM from the slip percentage
1383
1377
  let limPercentage = BN_1;
@@ -1397,7 +1391,7 @@ class ThorchainQuery {
1397
1391
  limit: baseAmount(limAssetAmount8Decimals),
1398
1392
  destinationAddress: destinationAddress,
1399
1393
  affiliateAddress: affiliateAddress,
1400
- affiliateFee: swapEstimate.totalFees.affiliateFee.baseAmount,
1394
+ affiliateFeeBasisPoints: affiliateFeeBasisPoints,
1401
1395
  interfaceID: interfaceID,
1402
1396
  });
1403
1397
  }
@@ -1409,6 +1403,7 @@ class ThorchainQuery {
1409
1403
  * @param params
1410
1404
  */
1411
1405
  isValidSwap(params) {
1406
+ var _a, _b;
1412
1407
  return __awaiter(this, void 0, void 0, function* () {
1413
1408
  if (isAssetRuneNative(params.input.asset)) {
1414
1409
  if (params.input.baseAmount.decimal !== 8)
@@ -1428,8 +1423,12 @@ class ThorchainQuery {
1428
1423
  if (params.input.baseAmount.lte(0))
1429
1424
  throw Error('inputAmount must be greater than 0');
1430
1425
  // Affiliate fee % can't exceed 10% because this is set by TC.
1431
- if (params.affiliateFeePercent && (params.affiliateFeePercent < 0 || params.affiliateFeePercent > 0.1))
1432
- throw Error(`affiliateFee must be between 0 and 1000 basis points`);
1426
+ if (params.affiliateFeeBasisPoints && (params.affiliateFeeBasisPoints < 0 || params.affiliateFeeBasisPoints > 1000))
1427
+ throw Error(`affiliateFeeBasisPoints must be between 0 and 1000 basis points`);
1428
+ if (params.affiliateFeeBasisPoints && !Number.isInteger(params.affiliateFeeBasisPoints))
1429
+ throw Error(`affiliateFeeBasisPoints must be an integer`);
1430
+ if (((_a = params.slipLimit) === null || _a === void 0 ? void 0 : _a.lte(0)) || ((_b = params.slipLimit) === null || _b === void 0 ? void 0 : _b.gt(1)))
1431
+ throw Error(`slipLimit must be between 0 and 1`);
1433
1432
  });
1434
1433
  }
1435
1434
  /**
@@ -1450,51 +1449,48 @@ class ThorchainQuery {
1450
1449
  const input = params.input.baseAmount.decimal === DEFAULT_THORCHAIN_DECIMALS
1451
1450
  ? params.input
1452
1451
  : yield this.thorchainCache.convert(params.input, params.input.asset);
1453
- // If asset is already rune native, skip the convert
1454
- const inputInRune = input.asset === AssetRuneNative ? input : yield this.thorchainCache.convert(input, AssetRuneNative);
1455
- const inboundFeeInAsset = calcNetworkFee(input.asset, sourceInboundDetails);
1456
- // Retrieve outbound fee from inboundAddressDetails.
1457
- const outboundFeeInAsset = calcNetworkFee(params.destinationAsset, destinationInboundDetails).times(3);
1458
- // convert fees to rune
1459
- const inboundFeeInRune = yield this.thorchainCache.convert(inboundFeeInAsset, AssetRuneNative);
1460
- let outboundFeeInRune = yield this.thorchainCache.convert(outboundFeeInAsset, AssetRuneNative);
1452
+ const inboundFeeInInboundGasAsset = calcNetworkFee(input.asset, sourceInboundDetails);
1453
+ const outboundFeeInOutboundGasAsset = calcOutboundFee(params.destinationAsset, destinationInboundDetails);
1461
1454
  // ----------- Remove Fees from inbound before doing the swap -----------
1462
- const inputMinusInboundFeeInRune = inputInRune.minus(inboundFeeInRune);
1455
+ const inboundFeeInInboundAsset = yield this.thorchainCache.convert(inboundFeeInInboundGasAsset, params.input.asset);
1456
+ const inputMinusInboundFeeInAsset = input.minus(inboundFeeInInboundAsset);
1457
+ // console.log('y', inputMinusInboundFeeInAsset.formatedAssetString())
1463
1458
  // remove any affiliateFee. netInput * affiliateFee (percentage) of the destination asset type
1464
- const affiliateFeeInRune = inputMinusInboundFeeInRune.times(params.affiliateFeePercent || 0);
1465
- // remove the affiliate fee from the input.
1466
- const inputNetAmountInRune = inputMinusInboundFeeInRune.minus(affiliateFeeInRune);
1467
- // convert back to input asset
1468
- const inputNetInAsset = yield this.thorchainCache.convert(inputNetAmountInRune, input.asset);
1469
- // Check outbound fee is equal too or greater than 1 USD * need to find a more permanent solution to this. referencing just 1 stable coin pool has problems
1470
- if (params.destinationAsset.chain !== Chain.THORChain && !params.destinationAsset.synth) {
1471
- const deepestUSDPOOL = yield this.thorchainCache.getDeepestUSDPool();
1472
- const usdAsset = deepestUSDPOOL.asset;
1473
- const networkValues = yield this.thorchainCache.midgard.getNetworkValues();
1474
- const usdMinFee = new CryptoAmount(baseAmount(networkValues['MINIMUML1OUTBOUNDFEEUSD']), usdAsset);
1475
- // const FeeInUSD = await this.convert(outboundFeeInRune, usdAsset)
1476
- const checkOutboundFee = (yield this.convert(outboundFeeInRune, usdAsset)).gte(usdMinFee);
1477
- if (!checkOutboundFee) {
1478
- const newFee = usdMinFee;
1479
- outboundFeeInRune = yield this.convert(newFee, AssetRuneNative);
1480
- }
1459
+ const affiliateFeePercent = params.affiliateFeeBasisPoints ? params.affiliateFeeBasisPoints / 10000 : 0;
1460
+ const affiliateFeeInAsset = inputMinusInboundFeeInAsset.times(affiliateFeePercent);
1461
+ let affiliateFeeSwapOutputInRune;
1462
+ if (isAssetRuneNative(affiliateFeeInAsset.asset)) {
1463
+ affiliateFeeSwapOutputInRune = {
1464
+ output: affiliateFeeInAsset,
1465
+ swapFee: new CryptoAmount(baseAmount(0), AssetRuneNative),
1466
+ slip: new BigNumber(0),
1467
+ };
1468
+ }
1469
+ else {
1470
+ affiliateFeeSwapOutputInRune = yield this.thorchainCache.getExpectedSwapOutput(affiliateFeeInAsset, AssetRuneNative);
1481
1471
  }
1472
+ // remove the affiliate fee from the input.
1473
+ const inputNetInAsset = inputMinusInboundFeeInAsset.minus(affiliateFeeInAsset);
1482
1474
  // Now calculate swap output based on inputNetAmount
1483
- const swapOutput = yield this.thorchainCache.getExpectedSwapOutput(inputNetInAsset, params.destinationAsset);
1484
- const swapFeeInRune = yield this.thorchainCache.convert(swapOutput.swapFee, AssetRuneNative);
1485
- const outputInRune = yield this.thorchainCache.convert(swapOutput.output, AssetRuneNative);
1475
+ const swapOutputInDestinationAsset = yield this.thorchainCache.getExpectedSwapOutput(inputNetInAsset, params.destinationAsset);
1486
1476
  // ---------------- Remove Outbound Fee ---------------------- /
1487
- const netOutputInRune = outputInRune.minus(outboundFeeInRune);
1488
- const netOutputInAsset = yield this.thorchainCache.convert(netOutputInRune, params.destinationAsset);
1477
+ const outboundFeeInDestinationAsset = yield this.thorchainCache.convert(outboundFeeInOutboundGasAsset, params.destinationAsset);
1478
+ // console.log('a', assetToString(swapOutputInDestinationAsset.output.asset))
1479
+ // console.log('b', assetToString(outboundFeeInDestinationAsset.asset))
1480
+ // // console.log('x', swapOutputInDestinationAsset.output.formatedAssetString())
1481
+ // // console.log('y', outboundFeeInDestinationAsset.formatedAssetString())
1482
+ const netOutputInAsset = swapOutputInDestinationAsset.output.minus(outboundFeeInDestinationAsset);
1489
1483
  const totalFees = {
1490
- inboundFee: inboundFeeInRune,
1491
- swapFee: swapFeeInRune,
1492
- outboundFee: outboundFeeInRune,
1493
- affiliateFee: affiliateFeeInRune,
1484
+ inboundFee: inboundFeeInInboundGasAsset,
1485
+ swapFee: swapOutputInDestinationAsset.swapFee,
1486
+ outboundFee: outboundFeeInOutboundGasAsset,
1487
+ affiliateFee: affiliateFeeSwapOutputInRune.output,
1488
+ // totalFees: ,
1494
1489
  };
1490
+ //const totalFeesInUsd = await this.getFeesIn(totalFees, usdAsset)
1495
1491
  const swapEstimate = {
1496
1492
  totalFees: totalFees,
1497
- slipPercentage: swapOutput.slip,
1493
+ slipPercentage: swapOutputInDestinationAsset.slip,
1498
1494
  netOutput: netOutputInAsset,
1499
1495
  waitTimeSeconds: 0,
1500
1496
  canSwap: false,
@@ -1509,15 +1505,16 @@ class ThorchainQuery {
1509
1505
  * @returns - constructed memo string
1510
1506
  */
1511
1507
  constructSwapMemo(params) {
1508
+ var _a;
1512
1509
  const limstring = params.limit.amount().toFixed();
1513
1510
  // create LIM with interface ID
1514
- const lim = limstring.substring(0, limstring.length - 3).concat(params.interfaceID.toString());
1511
+ const lim = limstring.substring(0, limstring.length - 3).concat(params.interfaceID);
1515
1512
  // create the full memo
1516
1513
  let memo = `=:${assetToString(params.destinationAsset)}`;
1517
1514
  // NOTE: we should validate affiliate address is EITHER: a thorname or valid thorchain address, currently we cannot do this without importing xchain-thorchain
1518
- if (params.affiliateAddress != '' || params.affiliateFee == undefined) {
1515
+ if (((_a = params.affiliateAddress) === null || _a === void 0 ? void 0 : _a.length) > 0) {
1519
1516
  // NOTE: we should validate destinationAddress address is valid destination address for the asset type requested
1520
- memo = memo.concat(`:${params.destinationAddress}:${lim}:${params.affiliateAddress}:${params.affiliateFee.amount().toFixed()}`);
1517
+ memo = memo.concat(`:${params.destinationAddress}:${lim}:${params.affiliateAddress}:${params.affiliateFeeBasisPoints}`);
1521
1518
  }
1522
1519
  else {
1523
1520
  memo = memo.concat(`:${params.destinationAddress}:${lim}`);
@@ -1632,6 +1629,9 @@ class ThorchainQuery {
1632
1629
  };
1633
1630
  });
1634
1631
  }
1632
+ // async getTotalFees(inbound: CryptoAmount, swapFee: CryptoAmount, outbound: CryptoAmount, affiliate: CryptoAmount): Promise<TotalFees> {
1633
+ // return {}
1634
+ // }
1635
1635
  /**
1636
1636
  * Returns the exchange of a CryptoAmount to a different Asset
1637
1637
  *
package/lib/index.js CHANGED
@@ -436,6 +436,7 @@ const getBaseAmountWithDiffDecimals = (inputAmount, outDecimals) => {
436
436
  const getSwapFee = (inputAmount, pool, toRune) => {
437
437
  // formula: (x * x * Y) / (x + X) ^ 2
438
438
  // const isInputRune = isAssetRuneNative(inputAmount.asset)
439
+ const decimalsOut = pool.pool.nativeDecimal !== '-1' ? Number(pool.pool.nativeDecimal) : inputAmount.baseAmount.decimal;
439
440
  const x = getBaseAmountWithDiffDecimals(inputAmount, 8);
440
441
  const X = toRune ? pool.assetBalance.amount() : pool.runeBalance.amount(); // input is asset if toRune
441
442
  const Y = toRune ? pool.runeBalance.amount() : pool.assetBalance.amount(); // output is rune if toRune
@@ -444,7 +445,7 @@ const getSwapFee = (inputAmount, pool, toRune) => {
444
445
  const denominator = x.plus(X).pow(2);
445
446
  const result = numerator.div(denominator);
446
447
  const eightDecimalResult = new CryptoAmount(xchainUtil.baseAmount(result), units);
447
- const decimals = toRune ? 8 : inputAmount.baseAmount.decimal;
448
+ const decimals = toRune ? 8 : decimalsOut;
448
449
  const baseOut = getBaseAmountWithDiffDecimals(eightDecimalResult, decimals);
449
450
  const swapFee = new CryptoAmount(xchainUtil.baseAmount(baseOut, decimals), units);
450
451
  //console.log(` swapFee ${swapFee.assetAmountFixedString()} `)
@@ -474,6 +475,7 @@ const getSwapSlip = (inputAmount, pool, toRune) => {
474
475
  */
475
476
  const getSwapOutput = (inputAmount, pool, toRune) => {
476
477
  // formula: (x * X * Y) / (x + X) ^ 2
478
+ const decimalsOut = pool.pool.nativeDecimal !== '-1' ? Number(pool.pool.nativeDecimal) : inputAmount.baseAmount.decimal;
477
479
  const x = getBaseAmountWithDiffDecimals(inputAmount, 8);
478
480
  const X = toRune ? pool.assetBalance.amount() : pool.runeBalance.amount(); // input is asset if toRune
479
481
  const Y = toRune ? pool.runeBalance.amount() : pool.assetBalance.amount(); // output is rune if toRune
@@ -483,7 +485,7 @@ const getSwapOutput = (inputAmount, pool, toRune) => {
483
485
  const denominator = x.plus(X).pow(2);
484
486
  const result = numerator.div(denominator);
485
487
  const eightDecimalResult = new CryptoAmount(xchainUtil.baseAmount(result), units);
486
- const decimals = toRune ? 8 : inputAmount.baseAmount.decimal;
488
+ const decimals = toRune ? 8 : decimalsOut;
487
489
  const baseOut = getBaseAmountWithDiffDecimals(eightDecimalResult, decimals);
488
490
  return new CryptoAmount(xchainUtil.baseAmount(baseOut, decimals), units);
489
491
  };
@@ -594,6 +596,42 @@ const calcNetworkFee = (asset, inbound) => {
594
596
  }
595
597
  throw new Error(`could not calculate inbound fee for ${asset.chain}`);
596
598
  };
599
+ /**
600
+ * Works out the required outbound fee based on the chain.
601
+ * Call getInboundDetails to get the current outbound fee
602
+ *
603
+ * @param sourceAsset
604
+ * @param inbound detail
605
+ * @see https://dev.thorchain.org/thorchain-dev/thorchain-and-fees#fee-calcuation-by-chain
606
+ * @returns
607
+ */
608
+ const calcOutboundFee = (asset, inbound) => {
609
+ if (asset.synth)
610
+ return new CryptoAmount(xchainUtil.baseAmount(2000000), xchainUtil.AssetRuneNative);
611
+ switch (asset.chain) {
612
+ case xchainUtil.Chain.Bitcoin:
613
+ return new CryptoAmount(xchainUtil.baseAmount(inbound.outboundFee), xchainUtil.AssetBTC);
614
+ case xchainUtil.Chain.BitcoinCash:
615
+ return new CryptoAmount(xchainUtil.baseAmount(inbound.outboundFee), xchainUtil.AssetBCH);
616
+ case xchainUtil.Chain.Litecoin:
617
+ return new CryptoAmount(xchainUtil.baseAmount(inbound.outboundFee), xchainUtil.AssetLTC);
618
+ case xchainUtil.Chain.Doge:
619
+ // NOTE: UTXO chains estimate fees with a 250 byte size
620
+ return new CryptoAmount(xchainUtil.baseAmount(inbound.outboundFee), xchainUtil.AssetDOGE);
621
+ case xchainUtil.Chain.Binance:
622
+ //flat fee
623
+ return new CryptoAmount(xchainUtil.baseAmount(inbound.outboundFee), xchainUtil.AssetBNB);
624
+ case xchainUtil.Chain.Ethereum:
625
+ return new CryptoAmount(xchainUtil.baseAmount(inbound.outboundFee.multipliedBy(Math.pow(10, 9)), 18), xchainUtil.AssetETH);
626
+ case xchainUtil.Chain.Avalanche:
627
+ return new CryptoAmount(xchainUtil.baseAmount(inbound.outboundFee.multipliedBy(Math.pow(10, 9)), 18), xchainUtil.AssetAVAX);
628
+ case xchainUtil.Chain.Cosmos:
629
+ return new CryptoAmount(xchainUtil.baseAmount(inbound.outboundFee), xchainUtil.AssetAtom);
630
+ case xchainUtil.Chain.THORChain:
631
+ return new CryptoAmount(xchainUtil.baseAmount(2000000), xchainUtil.AssetRuneNative);
632
+ }
633
+ throw new Error(`could not calculate outbound fee for ${asset.chain}`);
634
+ };
597
635
  /**
598
636
  * Return the chain for a given Asset This method should live somewhere else.
599
637
  * @param chain
@@ -838,14 +876,12 @@ class ThorchainCache {
838
876
  * @param expireNetworkValuesCacheMillis - how long should the Mimir/Constants be cached before expiry
839
877
  * @returns ThorchainCache
840
878
  */
841
- constructor(midgard = defaultMidgard, thornode = defaultThornode, expirePoolCacheMillis = 6000, expireAsgardCacheMillis = TEN_MINUTES, expireInboundDetailsCacheMillis = 6000, expireNetworkValuesCacheMillis = TEN_MINUTES) {
842
- this.asgardAssetsCache = undefined;
879
+ constructor(midgard = defaultMidgard, thornode = defaultThornode, expirePoolCacheMillis = 6000, expireInboundDetailsCacheMillis = 6000, expireNetworkValuesCacheMillis = TEN_MINUTES) {
843
880
  this.inboundDetailCache = undefined;
844
881
  this.networkValuesCache = undefined;
845
882
  this.midgard = midgard;
846
883
  this.thornode = thornode;
847
884
  this.expirePoolCacheMillis = expirePoolCacheMillis;
848
- this.expireAsgardCacheMillis = expireAsgardCacheMillis;
849
885
  this.expireInboundDetailsCacheMillis = expireInboundDetailsCacheMillis;
850
886
  this.expireNetworkValuesCacheMillis = expireNetworkValuesCacheMillis;
851
887
  //initialize the cache
@@ -955,29 +991,6 @@ class ThorchainCache {
955
991
  }
956
992
  });
957
993
  }
958
- /**
959
- * Refreshes the asgardAssetsCache Cache
960
- *
961
- * NOTE: do not call refereshAsgardCache() directly, call getAsgardAssets() instead
962
- * which will refresh the cache if it's expired
963
- */
964
- refereshAsgardCache() {
965
- return __awaiter(this, void 0, void 0, function* () {
966
- const inboundAddresses = yield this.thornode.getInboundAddresses();
967
- const map = {};
968
- if (inboundAddresses) {
969
- for (const inboundAddress of inboundAddresses) {
970
- if (!inboundAddress.chain)
971
- throw Error('chain needed');
972
- map[inboundAddress.chain] = inboundAddress;
973
- }
974
- this.asgardAssetsCache = {
975
- lastRefreshed: Date.now(),
976
- inboundAddresses: map,
977
- };
978
- }
979
- });
980
- }
981
994
  /**
982
995
  * Refreshes the InboundDetailCache Cache
983
996
  *
@@ -1064,22 +1077,26 @@ class ThorchainCache {
1064
1077
  */
1065
1078
  getExpectedSwapOutput(inputAmount, destinationAsset) {
1066
1079
  return __awaiter(this, void 0, void 0, function* () {
1080
+ let swapOutput;
1067
1081
  if (xchainUtil.isAssetRuneNative(inputAmount.asset)) {
1068
1082
  //singleswap from rune -> asset
1069
1083
  const pool = yield this.getPoolForAsset(destinationAsset);
1070
- return getSingleSwap(inputAmount, pool, false);
1084
+ swapOutput = getSingleSwap(inputAmount, pool, false);
1071
1085
  }
1072
1086
  else if (xchainUtil.isAssetRuneNative(destinationAsset)) {
1073
1087
  //singleswap from asset -> rune
1074
1088
  const pool = yield this.getPoolForAsset(inputAmount.asset);
1075
- return getSingleSwap(inputAmount, pool, true);
1089
+ swapOutput = getSingleSwap(inputAmount, pool, true);
1076
1090
  }
1077
1091
  else {
1078
1092
  //doubleswap asset-> asset
1079
1093
  const inPool = yield this.getPoolForAsset(inputAmount.asset);
1080
1094
  const destPool = yield this.getPoolForAsset(destinationAsset);
1081
- return yield getDoubleSwap(inputAmount, inPool, destPool, this);
1095
+ swapOutput = yield getDoubleSwap(inputAmount, inPool, destPool, this);
1082
1096
  }
1097
+ //Note this is needed to return a synth vs. a native asset on swap out
1098
+ swapOutput.output = new CryptoAmount(swapOutput.output.baseAmount, destinationAsset);
1099
+ return swapOutput;
1083
1100
  });
1084
1101
  }
1085
1102
  /**
@@ -1122,37 +1139,13 @@ class ThorchainCache {
1122
1139
  }
1123
1140
  getRouterAddressForChain(chain) {
1124
1141
  return __awaiter(this, void 0, void 0, function* () {
1125
- const inboundAsgard = (yield this.getInboundAddresses())[chain];
1142
+ const inboundAsgard = (yield this.getInboundDetails())[chain];
1126
1143
  if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.router)) {
1127
1144
  throw new Error('router address is not defined');
1128
1145
  }
1129
1146
  return inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.router;
1130
1147
  });
1131
1148
  }
1132
- /**
1133
- *
1134
- * @returns - inbound adresses item
1135
- */
1136
- getInboundAddresses() {
1137
- var _a;
1138
- return __awaiter(this, void 0, void 0, function* () {
1139
- const millisSinceLastRefeshed = Date.now() - (((_a = this.asgardAssetsCache) === null || _a === void 0 ? void 0 : _a.lastRefreshed) || 0);
1140
- if (millisSinceLastRefeshed > this.expireAsgardCacheMillis) {
1141
- try {
1142
- yield this.refereshAsgardCache();
1143
- }
1144
- catch (e) {
1145
- console.error(e);
1146
- }
1147
- }
1148
- if (this.asgardAssetsCache) {
1149
- return this.asgardAssetsCache.inboundAddresses;
1150
- }
1151
- else {
1152
- throw Error(`Could not refresh refereshAsgardCache `);
1153
- }
1154
- });
1155
- }
1156
1149
  /**
1157
1150
  *
1158
1151
  * @returns - inbound details
@@ -1336,7 +1329,8 @@ class ThorchainQuery {
1336
1329
 
1337
1330
  * @returns The SwapEstimate
1338
1331
  */
1339
- estimateSwap({ input, destinationAsset, destinationAddress, slipLimit, interfaceID = 999, affiliateAddress = '', affiliateFeePercent = 0, }) {
1332
+ estimateSwap({ input, destinationAsset, destinationAddress, slipLimit = new bignumber_js.BigNumber('0.03'), //default to 3%
1333
+ interfaceID = '555', affiliateAddress = '', affiliateFeeBasisPoints = 0, }) {
1340
1334
  return __awaiter(this, void 0, void 0, function* () {
1341
1335
  yield this.isValidSwap({
1342
1336
  input,
@@ -1344,7 +1338,7 @@ class ThorchainQuery {
1344
1338
  destinationAddress,
1345
1339
  slipLimit,
1346
1340
  affiliateAddress,
1347
- affiliateFeePercent,
1341
+ affiliateFeeBasisPoints,
1348
1342
  interfaceID,
1349
1343
  });
1350
1344
  const inboundDetails = yield this.thorchainCache.getInboundDetails();
@@ -1357,7 +1351,7 @@ class ThorchainQuery {
1357
1351
  destinationAddress,
1358
1352
  slipLimit,
1359
1353
  affiliateAddress,
1360
- affiliateFeePercent,
1354
+ affiliateFeeBasisPoints,
1361
1355
  interfaceID,
1362
1356
  }, sourceInboundDetails, destinationInboundDetails);
1363
1357
  // Calculate transaction expiry time
@@ -1371,7 +1365,7 @@ class ThorchainQuery {
1371
1365
  destinationAddress,
1372
1366
  slipLimit,
1373
1367
  affiliateAddress,
1374
- affiliateFeePercent,
1368
+ affiliateFeeBasisPoints,
1375
1369
  interfaceID,
1376
1370
  }, swapEstimate, sourceInboundDetails, destinationInboundDetails);
1377
1371
  const txDetails = {
@@ -1386,7 +1380,7 @@ class ThorchainQuery {
1386
1380
  }
1387
1381
  else {
1388
1382
  txDetails.txEstimate.canSwap = true;
1389
- const inboundAsgard = (yield this.thorchainCache.getInboundAddresses())[input.asset.chain];
1383
+ const inboundAsgard = (yield this.thorchainCache.getInboundDetails())[input.asset.chain];
1390
1384
  txDetails.toAddress = (inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address) || '';
1391
1385
  // Work out LIM from the slip percentage
1392
1386
  let limPercentage = BN_1;
@@ -1406,7 +1400,7 @@ class ThorchainQuery {
1406
1400
  limit: xchainUtil.baseAmount(limAssetAmount8Decimals),
1407
1401
  destinationAddress: destinationAddress,
1408
1402
  affiliateAddress: affiliateAddress,
1409
- affiliateFee: swapEstimate.totalFees.affiliateFee.baseAmount,
1403
+ affiliateFeeBasisPoints: affiliateFeeBasisPoints,
1410
1404
  interfaceID: interfaceID,
1411
1405
  });
1412
1406
  }
@@ -1418,6 +1412,7 @@ class ThorchainQuery {
1418
1412
  * @param params
1419
1413
  */
1420
1414
  isValidSwap(params) {
1415
+ var _a, _b;
1421
1416
  return __awaiter(this, void 0, void 0, function* () {
1422
1417
  if (xchainUtil.isAssetRuneNative(params.input.asset)) {
1423
1418
  if (params.input.baseAmount.decimal !== 8)
@@ -1437,8 +1432,12 @@ class ThorchainQuery {
1437
1432
  if (params.input.baseAmount.lte(0))
1438
1433
  throw Error('inputAmount must be greater than 0');
1439
1434
  // Affiliate fee % can't exceed 10% because this is set by TC.
1440
- if (params.affiliateFeePercent && (params.affiliateFeePercent < 0 || params.affiliateFeePercent > 0.1))
1441
- throw Error(`affiliateFee must be between 0 and 1000 basis points`);
1435
+ if (params.affiliateFeeBasisPoints && (params.affiliateFeeBasisPoints < 0 || params.affiliateFeeBasisPoints > 1000))
1436
+ throw Error(`affiliateFeeBasisPoints must be between 0 and 1000 basis points`);
1437
+ if (params.affiliateFeeBasisPoints && !Number.isInteger(params.affiliateFeeBasisPoints))
1438
+ throw Error(`affiliateFeeBasisPoints must be an integer`);
1439
+ if (((_a = params.slipLimit) === null || _a === void 0 ? void 0 : _a.lte(0)) || ((_b = params.slipLimit) === null || _b === void 0 ? void 0 : _b.gt(1)))
1440
+ throw Error(`slipLimit must be between 0 and 1`);
1442
1441
  });
1443
1442
  }
1444
1443
  /**
@@ -1459,51 +1458,48 @@ class ThorchainQuery {
1459
1458
  const input = params.input.baseAmount.decimal === DEFAULT_THORCHAIN_DECIMALS
1460
1459
  ? params.input
1461
1460
  : yield this.thorchainCache.convert(params.input, params.input.asset);
1462
- // If asset is already rune native, skip the convert
1463
- const inputInRune = input.asset === xchainUtil.AssetRuneNative ? input : yield this.thorchainCache.convert(input, xchainUtil.AssetRuneNative);
1464
- const inboundFeeInAsset = calcNetworkFee(input.asset, sourceInboundDetails);
1465
- // Retrieve outbound fee from inboundAddressDetails.
1466
- const outboundFeeInAsset = calcNetworkFee(params.destinationAsset, destinationInboundDetails).times(3);
1467
- // convert fees to rune
1468
- const inboundFeeInRune = yield this.thorchainCache.convert(inboundFeeInAsset, xchainUtil.AssetRuneNative);
1469
- let outboundFeeInRune = yield this.thorchainCache.convert(outboundFeeInAsset, xchainUtil.AssetRuneNative);
1461
+ const inboundFeeInInboundGasAsset = calcNetworkFee(input.asset, sourceInboundDetails);
1462
+ const outboundFeeInOutboundGasAsset = calcOutboundFee(params.destinationAsset, destinationInboundDetails);
1470
1463
  // ----------- Remove Fees from inbound before doing the swap -----------
1471
- const inputMinusInboundFeeInRune = inputInRune.minus(inboundFeeInRune);
1464
+ const inboundFeeInInboundAsset = yield this.thorchainCache.convert(inboundFeeInInboundGasAsset, params.input.asset);
1465
+ const inputMinusInboundFeeInAsset = input.minus(inboundFeeInInboundAsset);
1466
+ // console.log('y', inputMinusInboundFeeInAsset.formatedAssetString())
1472
1467
  // remove any affiliateFee. netInput * affiliateFee (percentage) of the destination asset type
1473
- const affiliateFeeInRune = inputMinusInboundFeeInRune.times(params.affiliateFeePercent || 0);
1474
- // remove the affiliate fee from the input.
1475
- const inputNetAmountInRune = inputMinusInboundFeeInRune.minus(affiliateFeeInRune);
1476
- // convert back to input asset
1477
- const inputNetInAsset = yield this.thorchainCache.convert(inputNetAmountInRune, input.asset);
1478
- // Check outbound fee is equal too or greater than 1 USD * need to find a more permanent solution to this. referencing just 1 stable coin pool has problems
1479
- if (params.destinationAsset.chain !== xchainUtil.Chain.THORChain && !params.destinationAsset.synth) {
1480
- const deepestUSDPOOL = yield this.thorchainCache.getDeepestUSDPool();
1481
- const usdAsset = deepestUSDPOOL.asset;
1482
- const networkValues = yield this.thorchainCache.midgard.getNetworkValues();
1483
- const usdMinFee = new CryptoAmount(xchainUtil.baseAmount(networkValues['MINIMUML1OUTBOUNDFEEUSD']), usdAsset);
1484
- // const FeeInUSD = await this.convert(outboundFeeInRune, usdAsset)
1485
- const checkOutboundFee = (yield this.convert(outboundFeeInRune, usdAsset)).gte(usdMinFee);
1486
- if (!checkOutboundFee) {
1487
- const newFee = usdMinFee;
1488
- outboundFeeInRune = yield this.convert(newFee, xchainUtil.AssetRuneNative);
1489
- }
1468
+ const affiliateFeePercent = params.affiliateFeeBasisPoints ? params.affiliateFeeBasisPoints / 10000 : 0;
1469
+ const affiliateFeeInAsset = inputMinusInboundFeeInAsset.times(affiliateFeePercent);
1470
+ let affiliateFeeSwapOutputInRune;
1471
+ if (xchainUtil.isAssetRuneNative(affiliateFeeInAsset.asset)) {
1472
+ affiliateFeeSwapOutputInRune = {
1473
+ output: affiliateFeeInAsset,
1474
+ swapFee: new CryptoAmount(xchainUtil.baseAmount(0), xchainUtil.AssetRuneNative),
1475
+ slip: new bignumber_js.BigNumber(0),
1476
+ };
1477
+ }
1478
+ else {
1479
+ affiliateFeeSwapOutputInRune = yield this.thorchainCache.getExpectedSwapOutput(affiliateFeeInAsset, xchainUtil.AssetRuneNative);
1490
1480
  }
1481
+ // remove the affiliate fee from the input.
1482
+ const inputNetInAsset = inputMinusInboundFeeInAsset.minus(affiliateFeeInAsset);
1491
1483
  // Now calculate swap output based on inputNetAmount
1492
- const swapOutput = yield this.thorchainCache.getExpectedSwapOutput(inputNetInAsset, params.destinationAsset);
1493
- const swapFeeInRune = yield this.thorchainCache.convert(swapOutput.swapFee, xchainUtil.AssetRuneNative);
1494
- const outputInRune = yield this.thorchainCache.convert(swapOutput.output, xchainUtil.AssetRuneNative);
1484
+ const swapOutputInDestinationAsset = yield this.thorchainCache.getExpectedSwapOutput(inputNetInAsset, params.destinationAsset);
1495
1485
  // ---------------- Remove Outbound Fee ---------------------- /
1496
- const netOutputInRune = outputInRune.minus(outboundFeeInRune);
1497
- const netOutputInAsset = yield this.thorchainCache.convert(netOutputInRune, params.destinationAsset);
1486
+ const outboundFeeInDestinationAsset = yield this.thorchainCache.convert(outboundFeeInOutboundGasAsset, params.destinationAsset);
1487
+ // console.log('a', assetToString(swapOutputInDestinationAsset.output.asset))
1488
+ // console.log('b', assetToString(outboundFeeInDestinationAsset.asset))
1489
+ // // console.log('x', swapOutputInDestinationAsset.output.formatedAssetString())
1490
+ // // console.log('y', outboundFeeInDestinationAsset.formatedAssetString())
1491
+ const netOutputInAsset = swapOutputInDestinationAsset.output.minus(outboundFeeInDestinationAsset);
1498
1492
  const totalFees = {
1499
- inboundFee: inboundFeeInRune,
1500
- swapFee: swapFeeInRune,
1501
- outboundFee: outboundFeeInRune,
1502
- affiliateFee: affiliateFeeInRune,
1493
+ inboundFee: inboundFeeInInboundGasAsset,
1494
+ swapFee: swapOutputInDestinationAsset.swapFee,
1495
+ outboundFee: outboundFeeInOutboundGasAsset,
1496
+ affiliateFee: affiliateFeeSwapOutputInRune.output,
1497
+ // totalFees: ,
1503
1498
  };
1499
+ //const totalFeesInUsd = await this.getFeesIn(totalFees, usdAsset)
1504
1500
  const swapEstimate = {
1505
1501
  totalFees: totalFees,
1506
- slipPercentage: swapOutput.slip,
1502
+ slipPercentage: swapOutputInDestinationAsset.slip,
1507
1503
  netOutput: netOutputInAsset,
1508
1504
  waitTimeSeconds: 0,
1509
1505
  canSwap: false,
@@ -1518,15 +1514,16 @@ class ThorchainQuery {
1518
1514
  * @returns - constructed memo string
1519
1515
  */
1520
1516
  constructSwapMemo(params) {
1517
+ var _a;
1521
1518
  const limstring = params.limit.amount().toFixed();
1522
1519
  // create LIM with interface ID
1523
- const lim = limstring.substring(0, limstring.length - 3).concat(params.interfaceID.toString());
1520
+ const lim = limstring.substring(0, limstring.length - 3).concat(params.interfaceID);
1524
1521
  // create the full memo
1525
1522
  let memo = `=:${xchainUtil.assetToString(params.destinationAsset)}`;
1526
1523
  // NOTE: we should validate affiliate address is EITHER: a thorname or valid thorchain address, currently we cannot do this without importing xchain-thorchain
1527
- if (params.affiliateAddress != '' || params.affiliateFee == undefined) {
1524
+ if (((_a = params.affiliateAddress) === null || _a === void 0 ? void 0 : _a.length) > 0) {
1528
1525
  // NOTE: we should validate destinationAddress address is valid destination address for the asset type requested
1529
- memo = memo.concat(`:${params.destinationAddress}:${lim}:${params.affiliateAddress}:${params.affiliateFee.amount().toFixed()}`);
1526
+ memo = memo.concat(`:${params.destinationAddress}:${lim}:${params.affiliateAddress}:${params.affiliateFeeBasisPoints}`);
1530
1527
  }
1531
1528
  else {
1532
1529
  memo = memo.concat(`:${params.destinationAddress}:${lim}`);
@@ -1641,6 +1638,9 @@ class ThorchainQuery {
1641
1638
  };
1642
1639
  });
1643
1640
  }
1641
+ // async getTotalFees(inbound: CryptoAmount, swapFee: CryptoAmount, outbound: CryptoAmount, affiliate: CryptoAmount): Promise<TotalFees> {
1642
+ // return {}
1643
+ // }
1644
1644
  /**
1645
1645
  * Returns the exchange of a CryptoAmount to a different Asset
1646
1646
  *
@@ -1,4 +1,3 @@
1
- import { InboundAddress } from '@xchainjs/xchain-thornode';
2
1
  import { Address, Asset, Chain } from '@xchainjs/xchain-util';
3
2
  import { BigNumber } from 'bignumber.js';
4
3
  import { CryptoAmount } from './crypto-amount';
@@ -13,11 +12,9 @@ export declare class ThorchainCache {
13
12
  readonly midgard: Midgard;
14
13
  readonly thornode: Thornode;
15
14
  private poolCache;
16
- private asgardAssetsCache;
17
15
  private inboundDetailCache;
18
16
  private networkValuesCache;
19
17
  private expirePoolCacheMillis;
20
- private expireAsgardCacheMillis;
21
18
  private expireInboundDetailsCacheMillis;
22
19
  private expireNetworkValuesCacheMillis;
23
20
  /**
@@ -30,7 +27,7 @@ export declare class ThorchainCache {
30
27
  * @param expireNetworkValuesCacheMillis - how long should the Mimir/Constants be cached before expiry
31
28
  * @returns ThorchainCache
32
29
  */
33
- constructor(midgard?: Midgard, thornode?: Thornode, expirePoolCacheMillis?: number, expireAsgardCacheMillis?: number, expireInboundDetailsCacheMillis?: number, expireNetworkValuesCacheMillis?: number);
30
+ constructor(midgard?: Midgard, thornode?: Thornode, expirePoolCacheMillis?: number, expireInboundDetailsCacheMillis?: number, expireNetworkValuesCacheMillis?: number);
34
31
  /**
35
32
  * Gets the exchange rate of the from asset in terms on the to asset
36
33
  *
@@ -59,13 +56,6 @@ export declare class ThorchainCache {
59
56
  * which will refresh the cache if it's expired
60
57
  */
61
58
  private refereshPoolCache;
62
- /**
63
- * Refreshes the asgardAssetsCache Cache
64
- *
65
- * NOTE: do not call refereshAsgardCache() directly, call getAsgardAssets() instead
66
- * which will refresh the cache if it's expired
67
- */
68
- private refereshAsgardCache;
69
59
  /**
70
60
  * Refreshes the InboundDetailCache Cache
71
61
  *
@@ -105,11 +95,6 @@ export declare class ThorchainCache {
105
95
  convert(input: CryptoAmount, outAsset: Asset): Promise<CryptoAmount>;
106
96
  private getDecimalForAsset;
107
97
  getRouterAddressForChain(chain: Chain): Promise<Address>;
108
- /**
109
- *
110
- * @returns - inbound adresses item
111
- */
112
- getInboundAddresses(): Promise<Record<string, InboundAddress>>;
113
98
  /**
114
99
  *
115
100
  * @returns - inbound details
@@ -26,7 +26,8 @@ export declare class ThorchainQuery {
26
26
 
27
27
  * @returns The SwapEstimate
28
28
  */
29
- estimateSwap({ input, destinationAsset, destinationAddress, slipLimit, interfaceID, affiliateAddress, affiliateFeePercent, }: EstimateSwapParams): Promise<TxDetails>;
29
+ estimateSwap({ input, destinationAsset, destinationAddress, slipLimit, //default to 3%
30
+ interfaceID, affiliateAddress, affiliateFeeBasisPoints, }: EstimateSwapParams): Promise<TxDetails>;
30
31
  /**
31
32
  * Basic Checks for swap information
32
33
  * @param params
package/lib/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { FeeOption } from '@xchainjs/xchain-client';
2
- import { InboundAddress, LiquidityProvider } from '@xchainjs/xchain-thornode';
2
+ import { LiquidityProvider } from '@xchainjs/xchain-thornode';
3
3
  import { Address, Asset, BaseAmount, Chain } from '@xchainjs/xchain-util';
4
4
  import { BigNumber } from 'bignumber.js';
5
5
  import { CryptoAmount } from './crypto-amount';
@@ -22,10 +22,6 @@ export declare type PoolCache = {
22
22
  lastRefreshed: number;
23
23
  pools: Record<string, LiquidityPool>;
24
24
  };
25
- export declare type AsgardCache = {
26
- lastRefreshed: number;
27
- inboundAddresses: Record<string, InboundAddress>;
28
- };
29
25
  export declare type InboundDetailCache = {
30
26
  lastRefreshed: number;
31
27
  inboundDetails: Record<string, InboundDetail>;
@@ -44,8 +40,8 @@ export declare type EstimateSwapParams = {
44
40
  destinationAddress: Address;
45
41
  slipLimit?: BigNumber;
46
42
  affiliateAddress?: Address;
47
- affiliateFeePercent?: number;
48
- interfaceID?: number;
43
+ affiliateFeeBasisPoints?: number;
44
+ interfaceID?: string;
49
45
  };
50
46
  export declare type SwapOutput = {
51
47
  output: CryptoAmount;
@@ -91,9 +87,9 @@ export declare type ConstructMemo = {
91
87
  limit: BaseAmount;
92
88
  destinationAddress: Address;
93
89
  affiliateAddress: Address;
94
- affiliateFee: BaseAmount;
90
+ affiliateFeeBasisPoints: number;
95
91
  feeOption?: FeeOption;
96
- interfaceID: number;
92
+ interfaceID: string;
97
93
  };
98
94
  export declare type TxDetails = {
99
95
  memo: string;
@@ -58,6 +58,16 @@ export declare const getDoubleSwap: (inputAmount: CryptoAmount, pool1: Liquidity
58
58
  * @returns
59
59
  */
60
60
  export declare const calcNetworkFee: (asset: Asset, inbound: InboundDetail) => CryptoAmount;
61
+ /**
62
+ * Works out the required outbound fee based on the chain.
63
+ * Call getInboundDetails to get the current outbound fee
64
+ *
65
+ * @param sourceAsset
66
+ * @param inbound detail
67
+ * @see https://dev.thorchain.org/thorchain-dev/thorchain-and-fees#fee-calcuation-by-chain
68
+ * @returns
69
+ */
70
+ export declare const calcOutboundFee: (asset: Asset, inbound: InboundDetail) => CryptoAmount;
61
71
  /**
62
72
  * Return the chain for a given Asset This method should live somewhere else.
63
73
  * @param chain
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xchainjs/xchain-thorchain-query",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "license": "MIT",
5
5
  "description": "Thorchain query module that is resposible for estimating swap calculations and add/remove liquidity for thorchain ",
6
6
  "keywords": [