@xchainjs/xchain-thorchain-amm 0.1.0-beta5 → 0.3.0

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
@@ -27,12 +27,13 @@ Following peer dependencies have to be installed into your project. These are no
27
27
  "@xchainjs/xchain-doge": "^0.5.0",
28
28
  "@xchainjs/xchain-ethereum": "^0.27.0",
29
29
  "@xchainjs/xchain-evm": "^0.1.0-alpha2",
30
- "@xchainjs/xchain-avax": "^0.1.0-alpha2",
30
+ "@xchainjs/xchain-avax": "^0.1.0-alpha3",
31
31
  "@xchainjs/xchain-litecoin": "^0.10.0",
32
- "@xchainjs/xchain-midgard": "0.1.0-alpha2",
32
+ "@xchainjs/xchain-midgard": "^0.1.0",
33
33
  "@xchainjs/xchain-terra": "^0.3.0",
34
34
  "@xchainjs/xchain-thorchain": "^0.26.0",
35
- "@xchainjs/xchain-thorchain-query": "^0.1.0-beta",
35
+ "@xchainjs/xchain-thorchain-query": "^0.1.0",
36
+ "@xchainjs/xchain-thornode": "^0.1.0",
36
37
  "@xchainjs/xchain-util": "^0.9.0",
37
38
  "axios": "^0.27.2",
38
39
  "axios-retry": "^3.3.1",
package/lib/index.esm.js CHANGED
@@ -1,14 +1,13 @@
1
- import { Client as Client$9, defaultAvaxParams } from '@xchainjs/xchain-avax';
2
- import { Client as Client$7 } from '@xchainjs/xchain-binance';
1
+ import { Client as Client$8, defaultAvaxParams } from '@xchainjs/xchain-avax';
2
+ import { Client as Client$6 } from '@xchainjs/xchain-binance';
3
3
  import { Client as Client$1 } from '@xchainjs/xchain-bitcoin';
4
4
  import { Client } from '@xchainjs/xchain-bitcoincash';
5
5
  import { Network, FeeOption } from '@xchainjs/xchain-client';
6
- import { Client as Client$8 } from '@xchainjs/xchain-cosmos';
6
+ import { Client as Client$7 } from '@xchainjs/xchain-cosmos';
7
7
  import { Client as Client$2 } from '@xchainjs/xchain-doge';
8
- import { MAX_APPROVAL, ETH_DECIMAL, Client as Client$4 } from '@xchainjs/xchain-ethereum';
9
- import { Client as Client$6 } from '@xchainjs/xchain-litecoin';
10
- import { Client as Client$3 } from '@xchainjs/xchain-terra';
11
- import { Client as Client$5 } from '@xchainjs/xchain-thorchain';
8
+ import { MAX_APPROVAL, ETH_DECIMAL, Client as Client$3 } from '@xchainjs/xchain-ethereum';
9
+ import { Client as Client$5 } from '@xchainjs/xchain-litecoin';
10
+ import { Client as Client$4 } from '@xchainjs/xchain-thorchain';
12
11
  import { eqAsset, AssetETH, getContractAddressFromAsset, baseAmount, Chain, assetToString, AssetBTC } from '@xchainjs/xchain-util';
13
12
  import { ethers } from 'ethers';
14
13
  import { MAX_APPROVAL as MAX_APPROVAL$1 } from '@xchainjs/xchain-evm';
@@ -423,10 +422,13 @@ class EthHelper {
423
422
  */
424
423
  sendDeposit(params) {
425
424
  return __awaiter(this, void 0, void 0, function* () {
426
- const inboundAsgard = (yield this.thorchainCache.getInboundAddressesItems())[params.asset.chain];
425
+ const inboundAsgard = (yield this.thorchainCache.getInboundAddresses())[params.asset.chain];
427
426
  if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.router)) {
428
427
  throw new Error('router address is not defined');
429
428
  }
429
+ if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address)) {
430
+ throw new Error('Vault address is not defined');
431
+ }
430
432
  const address = this.client.getAddress(params.walletIndex);
431
433
  const gasPrice = yield this.ethClient.estimateGasPrices();
432
434
  if (eqAsset(params.asset, AssetETH)) {
@@ -515,10 +517,13 @@ class EvmHelper {
515
517
  */
516
518
  sendDeposit(params) {
517
519
  return __awaiter(this, void 0, void 0, function* () {
518
- const inboundAsgard = (yield this.thorchainCache.getInboundAddressesItems())[params.asset.chain];
520
+ const inboundAsgard = (yield this.thorchainCache.getInboundAddresses())[params.asset.chain];
519
521
  if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.router)) {
520
522
  throw new Error('router address is not defined');
521
523
  }
524
+ if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address)) {
525
+ throw new Error('Vault address is not defined');
526
+ }
522
527
  const address = this.client.getAddress(params.walletIndex);
523
528
  const gasPrice = yield this.evmClient.estimateGasPrices();
524
529
  if (eqAsset(params.asset, this.evmClient.config.gasAsset)) {
@@ -588,7 +593,21 @@ class EvmHelper {
588
593
  const chainIds = {
589
594
  [Network.Mainnet]: 'thorchain-mainnet-v1',
590
595
  [Network.Stagenet]: 'chain-id-stagenet',
591
- [Network.Testnet]: 'thorchain-testnet-v2',
596
+ [Network.Testnet]: 'deprecated',
597
+ };
598
+ const clientUrl = {
599
+ [Network.Stagenet]: {
600
+ node: 'https://stagenet-thornode.ninerealms.com',
601
+ rpc: 'https://stagenet-rpc.ninerealms.com',
602
+ },
603
+ [Network.Mainnet]: {
604
+ node: 'https://thornode.ninerealms.com',
605
+ rpc: 'https://rpc.ninerealms.com',
606
+ },
607
+ [Network.Testnet]: {
608
+ node: 'deprecated',
609
+ rpc: 'deprecated',
610
+ },
592
611
  };
593
612
  /**
594
613
  * Wallet Class for managing all xchain-* wallets with a mnemonic seed.
@@ -608,13 +627,12 @@ class Wallet {
608
627
  BCH: new Client(settings),
609
628
  BTC: new Client$1(settings),
610
629
  DOGE: new Client$2(settings),
611
- TERRA: new Client$3(settings),
612
- ETH: new Client$4(settings),
613
- THOR: new Client$5(Object.assign(Object.assign({}, settings), { chainIds })),
614
- LTC: new Client$6(settings),
615
- BNB: new Client$7(settings),
616
- GAIA: new Client$8(settings),
617
- AVAX: new Client$9(Object.assign(Object.assign({}, defaultAvaxParams), { network: settings.network, phrase })),
630
+ ETH: new Client$3(settings),
631
+ THOR: new Client$4(Object.assign(Object.assign({}, settings), { chainIds, clientUrl })),
632
+ LTC: new Client$5(settings),
633
+ BNB: new Client$6(settings),
634
+ GAIA: new Client$7(settings),
635
+ AVAX: new Client$8(Object.assign(Object.assign({}, defaultAvaxParams), { network: settings.network, phrase })),
618
636
  };
619
637
  this.ethHelper = new EthHelper(this.clients.ETH, this.thorchainQuery.thorchainCache);
620
638
  }
@@ -704,7 +722,9 @@ class Wallet {
704
722
  return __awaiter(this, void 0, void 0, function* () {
705
723
  const client = this.clients[swap.input.asset.chain];
706
724
  const waitTimeSeconds = swap.waitTimeSeconds;
707
- const inboundAsgard = (yield this.thorchainQuery.thorchainCache.getInboundAddressesItems())[swap.input.asset.chain];
725
+ const inbound = (yield this.thorchainQuery.thorchainCache.getInboundDetails())[swap.input.asset.chain];
726
+ if (!(inbound === null || inbound === void 0 ? void 0 : inbound.address))
727
+ throw Error(`no asgard address found for ${swap.input.asset.chain}`);
708
728
  if (swap.input.asset.chain === Chain.Ethereum) {
709
729
  const params = {
710
730
  walletIndex: 0,
@@ -733,7 +753,7 @@ class Wallet {
733
753
  walletIndex: 0,
734
754
  asset: swap.input.asset,
735
755
  amount: swap.input.baseAmount,
736
- recipient: (inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address) || '',
756
+ recipient: inbound.address,
737
757
  memo: this.constructSwapMemo(swap),
738
758
  };
739
759
  const hash = yield client.transfer(params);
@@ -741,6 +761,156 @@ class Wallet {
741
761
  }
742
762
  });
743
763
  }
764
+ /** BASED OFF https://dev.thorchain.or›g/thorchain-dev/network/memos
765
+ *
766
+ * @param params input parameters needed to add liquidity
767
+ * @returns transaction details submitted
768
+ */
769
+ addLiquidity(params) {
770
+ return __awaiter(this, void 0, void 0, function* () {
771
+ const assetClient = this.clients[params.asset.asset.chain];
772
+ const inboundAsgard = (yield this.thorchainQuery.thorchainCache.getInboundDetails())[params.asset.asset.chain]
773
+ .address;
774
+ const thorchainClient = this.clients[params.rune.asset.chain];
775
+ const addressRune = thorchainClient.getAddress();
776
+ const addressAsset = assetClient.getAddress();
777
+ const waitTimeSeconds = params.waitTimeSeconds;
778
+ let constructedMemo = '';
779
+ const txSubmitted = [];
780
+ // symmetrical add
781
+ if (params.asset.assetAmount.gt(0) && params.rune.assetAmount.gt(0)) {
782
+ constructedMemo = `+:${params.asset.asset.chain}.${params.asset.asset.symbol}:${addressRune}`;
783
+ txSubmitted.push(yield this.addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard));
784
+ constructedMemo = `+:${params.asset.asset.chain}.${params.asset.asset.symbol}:${addressAsset}`;
785
+ txSubmitted.push(yield this.addOrRemoveRuneLP(params, constructedMemo, thorchainClient, waitTimeSeconds));
786
+ return txSubmitted;
787
+ }
788
+ else if (params.asset.assetAmount.gt(0) && params.rune.assetAmount.eq(0)) {
789
+ // asymmetrical asset only
790
+ constructedMemo = `+:${params.asset.asset.chain}.${params.asset.asset.symbol}`;
791
+ txSubmitted.push(yield this.addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard));
792
+ return txSubmitted;
793
+ }
794
+ else {
795
+ // asymmetrical rune only
796
+ constructedMemo = `+:${params.asset.asset.chain}.${params.asset.asset.symbol}`;
797
+ txSubmitted.push(yield this.addOrRemoveRuneLP(params, constructedMemo, thorchainClient, waitTimeSeconds));
798
+ return txSubmitted;
799
+ }
800
+ });
801
+ }
802
+ /**
803
+ *
804
+ * @param params - parameters required for liquidity position
805
+ * @returns object with tx response, url and wait time in seconds
806
+ */
807
+ removeLiquidity(params) {
808
+ return __awaiter(this, void 0, void 0, function* () {
809
+ const assetClient = this.clients[params.asset.asset.chain];
810
+ const inboundAsgard = (yield this.thorchainQuery.thorchainCache.getInboundDetails())[params.asset.asset.chain];
811
+ if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address)) {
812
+ throw new Error('Vault address is not defined');
813
+ }
814
+ const waitTimeSeconds = params.waitTimeSeconds;
815
+ const thorchainClient = this.clients[params.rune.asset.chain];
816
+ const basisPoints = (params.percentage * 100).toFixed(); // convert to basis points
817
+ let constructedMemo = '';
818
+ const txSubmitted = [];
819
+ if (params.asset.assetAmount.gt(0) && params.rune.assetAmount.gt(0)) {
820
+ constructedMemo = `-:${params.asset.asset.chain}.${params.asset.asset.symbol}:${basisPoints}`;
821
+ txSubmitted.push(yield this.addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard.address));
822
+ constructedMemo = `-:${params.asset.asset.chain}.${params.asset.asset.symbol}:${basisPoints}`;
823
+ txSubmitted.push(yield this.addOrRemoveRuneLP(params, constructedMemo, thorchainClient, waitTimeSeconds));
824
+ return txSubmitted;
825
+ }
826
+ else if (params.asset.assetAmount.gt(0) && params.rune.assetAmount.eq(0)) {
827
+ // asymmetrical asset only
828
+ constructedMemo = `-:${params.asset.asset.chain}.${params.asset.asset.symbol}:${basisPoints}`;
829
+ txSubmitted.push(yield this.addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard.address));
830
+ return txSubmitted;
831
+ }
832
+ else {
833
+ // asymmetrical rune only
834
+ constructedMemo = `-:${params.asset.asset.chain}.${params.asset.asset.symbol}:${basisPoints}`;
835
+ txSubmitted.push(yield this.addOrRemoveRuneLP(params, constructedMemo, thorchainClient, waitTimeSeconds));
836
+ return txSubmitted;
837
+ }
838
+ });
839
+ }
840
+ /**
841
+ *
842
+ * @param params - parameters for add liquidity
843
+ * @param constructedMemo - memo needed for thorchain
844
+ * @param waitTimeSeconds - wait time for the tx to be confirmed
845
+ * @param assetClient - passing XchainClient
846
+ * @param inboundAsgard - inbound Asgard address for the LP
847
+ * @returns - tx object
848
+ */
849
+ addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard) {
850
+ return __awaiter(this, void 0, void 0, function* () {
851
+ if (params.asset.asset.chain === Chain.Ethereum) {
852
+ const addParams = {
853
+ wallIndex: 0,
854
+ asset: params.asset.asset,
855
+ amount: params.asset.baseAmount,
856
+ feeOption: FeeOption.Fast,
857
+ memo: constructedMemo,
858
+ };
859
+ console.log(addParams.amount.amount().toNumber());
860
+ const hash = yield this.ethHelper.sendDeposit(addParams);
861
+ return { hash, url: assetClient.getExplorerTxUrl(hash), waitTimeSeconds };
862
+ }
863
+ else if (params.asset.asset.chain === Chain.Avalanche) {
864
+ const addParams = {
865
+ wallIndex: 0,
866
+ asset: params.asset.asset,
867
+ amount: params.asset.baseAmount,
868
+ feeOption: FeeOption.Fast,
869
+ memo: constructedMemo,
870
+ };
871
+ const evmHelper = new EvmHelper(this.clients.AVAX, this.thorchainQuery.thorchainCache);
872
+ const hash = yield evmHelper.sendDeposit(addParams);
873
+ return { hash, url: assetClient.getExplorerTxUrl(hash), waitTimeSeconds };
874
+ }
875
+ else {
876
+ const addParams = {
877
+ wallIndex: 0,
878
+ asset: params.asset.asset,
879
+ amount: params.asset.baseAmount,
880
+ recipient: inboundAsgard,
881
+ memo: constructedMemo,
882
+ };
883
+ try {
884
+ console.log(addParams);
885
+ const hash = yield assetClient.transfer(addParams);
886
+ return { hash, url: assetClient.getExplorerTxUrl(hash), waitTimeSeconds };
887
+ }
888
+ catch (err) {
889
+ const hash = JSON.stringify(err);
890
+ return { hash, url: assetClient.getExplorerAddressUrl(assetClient.getAddress()), waitTimeSeconds };
891
+ }
892
+ }
893
+ });
894
+ }
895
+ /**
896
+ *
897
+ * @param params - deposit parameters
898
+ * @param memo - memo needed to withdraw lp
899
+ * @returns - tx object
900
+ */
901
+ addOrRemoveRuneLP(params, memo, thorchainClient, waitTimeSeconds) {
902
+ return __awaiter(this, void 0, void 0, function* () {
903
+ const thorClient = this.clients.THOR;
904
+ const addParams = {
905
+ asset: params.rune.asset,
906
+ amount: params.rune.baseAmount,
907
+ memo: memo,
908
+ };
909
+ console.log(addParams);
910
+ const hash = yield thorClient.deposit(addParams);
911
+ return { hash, url: thorchainClient.getExplorerTxUrl(hash), waitTimeSeconds };
912
+ });
913
+ }
744
914
  }
745
915
 
746
916
  const BN_1 = new BigNumber(1);
@@ -813,6 +983,41 @@ class ThorchainAMM {
813
983
  });
814
984
  });
815
985
  }
986
+ /**
987
+ *
988
+ * @param wallet - wallet class
989
+ * @param params - liquidity parameters
990
+ * @returns
991
+ */
992
+ addLiquidityPosition(wallet, params) {
993
+ return __awaiter(this, void 0, void 0, function* () {
994
+ // Check amounts are greater than fees and use return estimated wait
995
+ const checkLPAdd = yield this.thorchainQuery.estimateAddLP(params);
996
+ return wallet.addLiquidity({
997
+ asset: params.asset,
998
+ rune: params.rune,
999
+ waitTimeSeconds: checkLPAdd.estimatedWaitSeconds,
1000
+ });
1001
+ });
1002
+ }
1003
+ /**
1004
+ *
1005
+ * @param params - liquidity parameters
1006
+ * @param wallet - wallet needed to perform tx
1007
+ * @return
1008
+ */
1009
+ removeLiquidityPosition(wallet, params) {
1010
+ return __awaiter(this, void 0, void 0, function* () {
1011
+ // Caution Dust Limits: BTC,BCH,LTC chains 10k sats; DOGE 1m Sats; ETH 0 wei; THOR 0 RUNE.
1012
+ const estimateWithrawLp = yield this.thorchainQuery.estimateWithdrawLP(params);
1013
+ return wallet.removeLiquidity({
1014
+ asset: estimateWithrawLp.transactionFee.assetFee,
1015
+ rune: estimateWithrawLp.transactionFee.runeFee,
1016
+ percentage: params.percentage,
1017
+ waitTimeSeconds: estimateWithrawLp.estimatedWaitSeconds,
1018
+ });
1019
+ });
1020
+ }
816
1021
  }
817
1022
 
818
1023
  export { ThorchainAMM, Wallet };
package/lib/index.js CHANGED
@@ -11,7 +11,6 @@ var xchainCosmos = require('@xchainjs/xchain-cosmos');
11
11
  var xchainDoge = require('@xchainjs/xchain-doge');
12
12
  var xchainEthereum = require('@xchainjs/xchain-ethereum');
13
13
  var xchainLitecoin = require('@xchainjs/xchain-litecoin');
14
- var xchainTerra = require('@xchainjs/xchain-terra');
15
14
  var xchainThorchain = require('@xchainjs/xchain-thorchain');
16
15
  var xchainUtil = require('@xchainjs/xchain-util');
17
16
  var ethers = require('ethers');
@@ -427,10 +426,13 @@ class EthHelper {
427
426
  */
428
427
  sendDeposit(params) {
429
428
  return __awaiter(this, void 0, void 0, function* () {
430
- const inboundAsgard = (yield this.thorchainCache.getInboundAddressesItems())[params.asset.chain];
429
+ const inboundAsgard = (yield this.thorchainCache.getInboundAddresses())[params.asset.chain];
431
430
  if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.router)) {
432
431
  throw new Error('router address is not defined');
433
432
  }
433
+ if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address)) {
434
+ throw new Error('Vault address is not defined');
435
+ }
434
436
  const address = this.client.getAddress(params.walletIndex);
435
437
  const gasPrice = yield this.ethClient.estimateGasPrices();
436
438
  if (xchainUtil.eqAsset(params.asset, xchainUtil.AssetETH)) {
@@ -519,10 +521,13 @@ class EvmHelper {
519
521
  */
520
522
  sendDeposit(params) {
521
523
  return __awaiter(this, void 0, void 0, function* () {
522
- const inboundAsgard = (yield this.thorchainCache.getInboundAddressesItems())[params.asset.chain];
524
+ const inboundAsgard = (yield this.thorchainCache.getInboundAddresses())[params.asset.chain];
523
525
  if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.router)) {
524
526
  throw new Error('router address is not defined');
525
527
  }
528
+ if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address)) {
529
+ throw new Error('Vault address is not defined');
530
+ }
526
531
  const address = this.client.getAddress(params.walletIndex);
527
532
  const gasPrice = yield this.evmClient.estimateGasPrices();
528
533
  if (xchainUtil.eqAsset(params.asset, this.evmClient.config.gasAsset)) {
@@ -592,7 +597,21 @@ class EvmHelper {
592
597
  const chainIds = {
593
598
  [xchainClient.Network.Mainnet]: 'thorchain-mainnet-v1',
594
599
  [xchainClient.Network.Stagenet]: 'chain-id-stagenet',
595
- [xchainClient.Network.Testnet]: 'thorchain-testnet-v2',
600
+ [xchainClient.Network.Testnet]: 'deprecated',
601
+ };
602
+ const clientUrl = {
603
+ [xchainClient.Network.Stagenet]: {
604
+ node: 'https://stagenet-thornode.ninerealms.com',
605
+ rpc: 'https://stagenet-rpc.ninerealms.com',
606
+ },
607
+ [xchainClient.Network.Mainnet]: {
608
+ node: 'https://thornode.ninerealms.com',
609
+ rpc: 'https://rpc.ninerealms.com',
610
+ },
611
+ [xchainClient.Network.Testnet]: {
612
+ node: 'deprecated',
613
+ rpc: 'deprecated',
614
+ },
596
615
  };
597
616
  /**
598
617
  * Wallet Class for managing all xchain-* wallets with a mnemonic seed.
@@ -612,9 +631,8 @@ class Wallet {
612
631
  BCH: new xchainBitcoincash.Client(settings),
613
632
  BTC: new xchainBitcoin.Client(settings),
614
633
  DOGE: new xchainDoge.Client(settings),
615
- TERRA: new xchainTerra.Client(settings),
616
634
  ETH: new xchainEthereum.Client(settings),
617
- THOR: new xchainThorchain.Client(Object.assign(Object.assign({}, settings), { chainIds })),
635
+ THOR: new xchainThorchain.Client(Object.assign(Object.assign({}, settings), { chainIds, clientUrl })),
618
636
  LTC: new xchainLitecoin.Client(settings),
619
637
  BNB: new xchainBinance.Client(settings),
620
638
  GAIA: new xchainCosmos.Client(settings),
@@ -708,7 +726,9 @@ class Wallet {
708
726
  return __awaiter(this, void 0, void 0, function* () {
709
727
  const client = this.clients[swap.input.asset.chain];
710
728
  const waitTimeSeconds = swap.waitTimeSeconds;
711
- const inboundAsgard = (yield this.thorchainQuery.thorchainCache.getInboundAddressesItems())[swap.input.asset.chain];
729
+ const inbound = (yield this.thorchainQuery.thorchainCache.getInboundDetails())[swap.input.asset.chain];
730
+ if (!(inbound === null || inbound === void 0 ? void 0 : inbound.address))
731
+ throw Error(`no asgard address found for ${swap.input.asset.chain}`);
712
732
  if (swap.input.asset.chain === xchainUtil.Chain.Ethereum) {
713
733
  const params = {
714
734
  walletIndex: 0,
@@ -737,7 +757,7 @@ class Wallet {
737
757
  walletIndex: 0,
738
758
  asset: swap.input.asset,
739
759
  amount: swap.input.baseAmount,
740
- recipient: (inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address) || '',
760
+ recipient: inbound.address,
741
761
  memo: this.constructSwapMemo(swap),
742
762
  };
743
763
  const hash = yield client.transfer(params);
@@ -745,6 +765,156 @@ class Wallet {
745
765
  }
746
766
  });
747
767
  }
768
+ /** BASED OFF https://dev.thorchain.or›g/thorchain-dev/network/memos
769
+ *
770
+ * @param params input parameters needed to add liquidity
771
+ * @returns transaction details submitted
772
+ */
773
+ addLiquidity(params) {
774
+ return __awaiter(this, void 0, void 0, function* () {
775
+ const assetClient = this.clients[params.asset.asset.chain];
776
+ const inboundAsgard = (yield this.thorchainQuery.thorchainCache.getInboundDetails())[params.asset.asset.chain]
777
+ .address;
778
+ const thorchainClient = this.clients[params.rune.asset.chain];
779
+ const addressRune = thorchainClient.getAddress();
780
+ const addressAsset = assetClient.getAddress();
781
+ const waitTimeSeconds = params.waitTimeSeconds;
782
+ let constructedMemo = '';
783
+ const txSubmitted = [];
784
+ // symmetrical add
785
+ if (params.asset.assetAmount.gt(0) && params.rune.assetAmount.gt(0)) {
786
+ constructedMemo = `+:${params.asset.asset.chain}.${params.asset.asset.symbol}:${addressRune}`;
787
+ txSubmitted.push(yield this.addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard));
788
+ constructedMemo = `+:${params.asset.asset.chain}.${params.asset.asset.symbol}:${addressAsset}`;
789
+ txSubmitted.push(yield this.addOrRemoveRuneLP(params, constructedMemo, thorchainClient, waitTimeSeconds));
790
+ return txSubmitted;
791
+ }
792
+ else if (params.asset.assetAmount.gt(0) && params.rune.assetAmount.eq(0)) {
793
+ // asymmetrical asset only
794
+ constructedMemo = `+:${params.asset.asset.chain}.${params.asset.asset.symbol}`;
795
+ txSubmitted.push(yield this.addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard));
796
+ return txSubmitted;
797
+ }
798
+ else {
799
+ // asymmetrical rune only
800
+ constructedMemo = `+:${params.asset.asset.chain}.${params.asset.asset.symbol}`;
801
+ txSubmitted.push(yield this.addOrRemoveRuneLP(params, constructedMemo, thorchainClient, waitTimeSeconds));
802
+ return txSubmitted;
803
+ }
804
+ });
805
+ }
806
+ /**
807
+ *
808
+ * @param params - parameters required for liquidity position
809
+ * @returns object with tx response, url and wait time in seconds
810
+ */
811
+ removeLiquidity(params) {
812
+ return __awaiter(this, void 0, void 0, function* () {
813
+ const assetClient = this.clients[params.asset.asset.chain];
814
+ const inboundAsgard = (yield this.thorchainQuery.thorchainCache.getInboundDetails())[params.asset.asset.chain];
815
+ if (!(inboundAsgard === null || inboundAsgard === void 0 ? void 0 : inboundAsgard.address)) {
816
+ throw new Error('Vault address is not defined');
817
+ }
818
+ const waitTimeSeconds = params.waitTimeSeconds;
819
+ const thorchainClient = this.clients[params.rune.asset.chain];
820
+ const basisPoints = (params.percentage * 100).toFixed(); // convert to basis points
821
+ let constructedMemo = '';
822
+ const txSubmitted = [];
823
+ if (params.asset.assetAmount.gt(0) && params.rune.assetAmount.gt(0)) {
824
+ constructedMemo = `-:${params.asset.asset.chain}.${params.asset.asset.symbol}:${basisPoints}`;
825
+ txSubmitted.push(yield this.addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard.address));
826
+ constructedMemo = `-:${params.asset.asset.chain}.${params.asset.asset.symbol}:${basisPoints}`;
827
+ txSubmitted.push(yield this.addOrRemoveRuneLP(params, constructedMemo, thorchainClient, waitTimeSeconds));
828
+ return txSubmitted;
829
+ }
830
+ else if (params.asset.assetAmount.gt(0) && params.rune.assetAmount.eq(0)) {
831
+ // asymmetrical asset only
832
+ constructedMemo = `-:${params.asset.asset.chain}.${params.asset.asset.symbol}:${basisPoints}`;
833
+ txSubmitted.push(yield this.addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard.address));
834
+ return txSubmitted;
835
+ }
836
+ else {
837
+ // asymmetrical rune only
838
+ constructedMemo = `-:${params.asset.asset.chain}.${params.asset.asset.symbol}:${basisPoints}`;
839
+ txSubmitted.push(yield this.addOrRemoveRuneLP(params, constructedMemo, thorchainClient, waitTimeSeconds));
840
+ return txSubmitted;
841
+ }
842
+ });
843
+ }
844
+ /**
845
+ *
846
+ * @param params - parameters for add liquidity
847
+ * @param constructedMemo - memo needed for thorchain
848
+ * @param waitTimeSeconds - wait time for the tx to be confirmed
849
+ * @param assetClient - passing XchainClient
850
+ * @param inboundAsgard - inbound Asgard address for the LP
851
+ * @returns - tx object
852
+ */
853
+ addOrRemoveAssetLP(params, constructedMemo, assetClient, waitTimeSeconds, inboundAsgard) {
854
+ return __awaiter(this, void 0, void 0, function* () {
855
+ if (params.asset.asset.chain === xchainUtil.Chain.Ethereum) {
856
+ const addParams = {
857
+ wallIndex: 0,
858
+ asset: params.asset.asset,
859
+ amount: params.asset.baseAmount,
860
+ feeOption: xchainClient.FeeOption.Fast,
861
+ memo: constructedMemo,
862
+ };
863
+ console.log(addParams.amount.amount().toNumber());
864
+ const hash = yield this.ethHelper.sendDeposit(addParams);
865
+ return { hash, url: assetClient.getExplorerTxUrl(hash), waitTimeSeconds };
866
+ }
867
+ else if (params.asset.asset.chain === xchainUtil.Chain.Avalanche) {
868
+ const addParams = {
869
+ wallIndex: 0,
870
+ asset: params.asset.asset,
871
+ amount: params.asset.baseAmount,
872
+ feeOption: xchainClient.FeeOption.Fast,
873
+ memo: constructedMemo,
874
+ };
875
+ const evmHelper = new EvmHelper(this.clients.AVAX, this.thorchainQuery.thorchainCache);
876
+ const hash = yield evmHelper.sendDeposit(addParams);
877
+ return { hash, url: assetClient.getExplorerTxUrl(hash), waitTimeSeconds };
878
+ }
879
+ else {
880
+ const addParams = {
881
+ wallIndex: 0,
882
+ asset: params.asset.asset,
883
+ amount: params.asset.baseAmount,
884
+ recipient: inboundAsgard,
885
+ memo: constructedMemo,
886
+ };
887
+ try {
888
+ console.log(addParams);
889
+ const hash = yield assetClient.transfer(addParams);
890
+ return { hash, url: assetClient.getExplorerTxUrl(hash), waitTimeSeconds };
891
+ }
892
+ catch (err) {
893
+ const hash = JSON.stringify(err);
894
+ return { hash, url: assetClient.getExplorerAddressUrl(assetClient.getAddress()), waitTimeSeconds };
895
+ }
896
+ }
897
+ });
898
+ }
899
+ /**
900
+ *
901
+ * @param params - deposit parameters
902
+ * @param memo - memo needed to withdraw lp
903
+ * @returns - tx object
904
+ */
905
+ addOrRemoveRuneLP(params, memo, thorchainClient, waitTimeSeconds) {
906
+ return __awaiter(this, void 0, void 0, function* () {
907
+ const thorClient = this.clients.THOR;
908
+ const addParams = {
909
+ asset: params.rune.asset,
910
+ amount: params.rune.baseAmount,
911
+ memo: memo,
912
+ };
913
+ console.log(addParams);
914
+ const hash = yield thorClient.deposit(addParams);
915
+ return { hash, url: thorchainClient.getExplorerTxUrl(hash), waitTimeSeconds };
916
+ });
917
+ }
748
918
  }
749
919
 
750
920
  const BN_1 = new bignumber_js.BigNumber(1);
@@ -817,6 +987,41 @@ class ThorchainAMM {
817
987
  });
818
988
  });
819
989
  }
990
+ /**
991
+ *
992
+ * @param wallet - wallet class
993
+ * @param params - liquidity parameters
994
+ * @returns
995
+ */
996
+ addLiquidityPosition(wallet, params) {
997
+ return __awaiter(this, void 0, void 0, function* () {
998
+ // Check amounts are greater than fees and use return estimated wait
999
+ const checkLPAdd = yield this.thorchainQuery.estimateAddLP(params);
1000
+ return wallet.addLiquidity({
1001
+ asset: params.asset,
1002
+ rune: params.rune,
1003
+ waitTimeSeconds: checkLPAdd.estimatedWaitSeconds,
1004
+ });
1005
+ });
1006
+ }
1007
+ /**
1008
+ *
1009
+ * @param params - liquidity parameters
1010
+ * @param wallet - wallet needed to perform tx
1011
+ * @return
1012
+ */
1013
+ removeLiquidityPosition(wallet, params) {
1014
+ return __awaiter(this, void 0, void 0, function* () {
1015
+ // Caution Dust Limits: BTC,BCH,LTC chains 10k sats; DOGE 1m Sats; ETH 0 wei; THOR 0 RUNE.
1016
+ const estimateWithrawLp = yield this.thorchainQuery.estimateWithdrawLP(params);
1017
+ return wallet.removeLiquidity({
1018
+ asset: estimateWithrawLp.transactionFee.assetFee,
1019
+ rune: estimateWithrawLp.transactionFee.runeFee,
1020
+ percentage: params.percentage,
1021
+ waitTimeSeconds: estimateWithrawLp.estimatedWaitSeconds,
1022
+ });
1023
+ });
1024
+ }
820
1025
  }
821
1026
 
822
1027
  exports.ThorchainAMM = ThorchainAMM;
@@ -1,5 +1,5 @@
1
- import { EstimateSwapParams, ThorchainQuery, TxDetails } from '@xchainjs/xchain-thorchain-query';
2
- import { SwapSubmitted } from './types';
1
+ import { AddliquidityPosition, EstimateSwapParams, RemoveLiquidityPosition, ThorchainQuery, TxDetails } from '@xchainjs/xchain-thorchain-query';
2
+ import { TxSubmitted } from './types';
3
3
  import { Wallet } from './wallet';
4
4
  /**
5
5
  * THORChain Class for interacting with THORChain.
@@ -31,5 +31,19 @@ export declare class ThorchainAMM {
31
31
  * @param params - swap params
32
32
  * @returns {SwapSubmitted} - Tx Hash, URL of BlockExplorer and expected wait time.
33
33
  */
34
- doSwap(wallet: Wallet, params: EstimateSwapParams): Promise<SwapSubmitted>;
34
+ doSwap(wallet: Wallet, params: EstimateSwapParams): Promise<TxSubmitted>;
35
+ /**
36
+ *
37
+ * @param wallet - wallet class
38
+ * @param params - liquidity parameters
39
+ * @returns
40
+ */
41
+ addLiquidityPosition(wallet: Wallet, params: AddliquidityPosition): Promise<TxSubmitted[]>;
42
+ /**
43
+ *
44
+ * @param params - liquidity parameters
45
+ * @param wallet - wallet needed to perform tx
46
+ * @return
47
+ */
48
+ removeLiquidityPosition(wallet: Wallet, params: RemoveLiquidityPosition): Promise<TxSubmitted[]>;
35
49
  }
package/lib/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { FeeOption } from '@xchainjs/xchain-client';
2
- import { CryptoAmount } from '@xchainjs/xchain-thorchain-query';
2
+ import { CryptoAmount, LiquidityPool } from '@xchainjs/xchain-thorchain-query';
3
3
  import { Address, Asset, BaseAmount } from '@xchainjs/xchain-util';
4
4
  import { BigNumber } from 'bignumber.js';
5
5
  export declare type MidgardConfig = {
@@ -17,11 +17,29 @@ export declare type ExecuteSwap = {
17
17
  interfaceID: number;
18
18
  waitTimeSeconds: number;
19
19
  };
20
- export declare type SwapSubmitted = {
20
+ export declare type TxSubmitted = {
21
21
  hash: string;
22
22
  url: string;
23
23
  waitTimeSeconds: number;
24
24
  };
25
+ export declare type AddLiquidity = {
26
+ asset: CryptoAmount;
27
+ rune: CryptoAmount;
28
+ waitTimeSeconds: number;
29
+ };
30
+ export declare type LiquidityPosition = {
31
+ assetPool: LiquidityPool;
32
+ assetAmount: CryptoAmount;
33
+ runeAmount: CryptoAmount;
34
+ impermanentLossProtection: number;
35
+ };
36
+ export declare type RemoveLiquidity = {
37
+ asset: CryptoAmount;
38
+ rune: CryptoAmount;
39
+ percentage: number;
40
+ waitTimeSeconds: number;
41
+ asymmetricalWithdraw?: Asset;
42
+ };
25
43
  export declare type DepositParams = {
26
44
  walletIndex?: number;
27
45
  asset: Asset;
@@ -35,10 +53,6 @@ export declare type SwapOutput = {
35
53
  slip: BigNumber;
36
54
  };
37
55
  export declare type UnitData = {
38
- liquidityUnits: BaseAmount;
39
- totalUnits: BaseAmount;
40
- };
41
- export declare type LiquidityData = {
42
- rune: BaseAmount;
43
- asset: BaseAmount;
56
+ liquidityUnits: BigNumber;
57
+ totalUnits: BigNumber;
44
58
  };
package/lib/wallet.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Balance, XChainClient } from '@xchainjs/xchain-client';
2
2
  import { ThorchainQuery } from '@xchainjs/xchain-thorchain-query';
3
3
  import { Chain } from '@xchainjs/xchain-util';
4
- import { ExecuteSwap, SwapSubmitted } from './types';
4
+ import { AddLiquidity, ExecuteSwap, RemoveLiquidity, TxSubmitted } from './types';
5
5
  declare type AllBalances = {
6
6
  chain: Chain;
7
7
  address: string;
@@ -35,10 +35,39 @@ export declare class Wallet {
35
35
  * @returns transaction details and explorer url
36
36
  * @see ThorchainAMM.doSwap()
37
37
  */
38
- executeSwap(swap: ExecuteSwap): Promise<SwapSubmitted>;
38
+ executeSwap(swap: ExecuteSwap): Promise<TxSubmitted>;
39
39
  private constructSwapMemo;
40
40
  private validateSwap;
41
41
  private swapRuneTo;
42
42
  private swapNonRune;
43
+ /** BASED OFF https://dev.thorchain.or›g/thorchain-dev/network/memos
44
+ *
45
+ * @param params input parameters needed to add liquidity
46
+ * @returns transaction details submitted
47
+ */
48
+ addLiquidity(params: AddLiquidity): Promise<TxSubmitted[]>;
49
+ /**
50
+ *
51
+ * @param params - parameters required for liquidity position
52
+ * @returns object with tx response, url and wait time in seconds
53
+ */
54
+ removeLiquidity(params: RemoveLiquidity): Promise<TxSubmitted[]>;
55
+ /**
56
+ *
57
+ * @param params - parameters for add liquidity
58
+ * @param constructedMemo - memo needed for thorchain
59
+ * @param waitTimeSeconds - wait time for the tx to be confirmed
60
+ * @param assetClient - passing XchainClient
61
+ * @param inboundAsgard - inbound Asgard address for the LP
62
+ * @returns - tx object
63
+ */
64
+ private addOrRemoveAssetLP;
65
+ /**
66
+ *
67
+ * @param params - deposit parameters
68
+ * @param memo - memo needed to withdraw lp
69
+ * @returns - tx object
70
+ */
71
+ private addOrRemoveRuneLP;
43
72
  }
44
73
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xchainjs/xchain-thorchain-amm",
3
- "version": "0.1.0-beta5",
3
+ "version": "0.3.0",
4
4
  "description": "module that exposes estimating & swappping cryptocurrency assets on thorchain",
5
5
  "keywords": [
6
6
  "THORChain",
@@ -43,19 +43,19 @@
43
43
  "@xchainjs/xchain-binance": "^5.6.0",
44
44
  "@xchainjs/xchain-bitcoin": "^0.20.0",
45
45
  "@xchainjs/xchain-bitcoincash": "^0.15.0",
46
- "@xchainjs/xchain-client": "^0.13.1",
46
+ "@xchainjs/xchain-client": "^0.13.2",
47
47
  "@xchainjs/xchain-cosmos": "^0.20.0",
48
48
  "@xchainjs/xchain-crypto": "^0.2.6",
49
49
  "@xchainjs/xchain-doge": "^0.5.0",
50
50
  "@xchainjs/xchain-ethereum": "^0.27.0",
51
51
  "@xchainjs/xchain-evm": "^0.1.0-alpha2",
52
- "@xchainjs/xchain-avax": "^0.1.0-alpha2",
52
+ "@xchainjs/xchain-avax": "^0.1.0-alpha3",
53
53
  "@xchainjs/xchain-litecoin": "^0.10.0",
54
- "@xchainjs/xchain-midgard": "0.1.0-alpha2",
55
- "@xchainjs/xchain-terra": "^0.3.0",
56
- "@xchainjs/xchain-thorchain": "^0.26.0",
57
- "@xchainjs/xchain-thorchain-query": "^0.1.0-beta",
58
- "@xchainjs/xchain-util": "^0.10.0",
54
+ "@xchainjs/xchain-midgard": "0.1.0",
55
+ "@xchainjs/xchain-thorchain": "^0.27.0",
56
+ "@xchainjs/xchain-thorchain-query": "^0.1.0",
57
+ "@xchainjs/xchain-thornode": "^0.1.0",
58
+ "@xchainjs/xchain-util": "^0.11.0",
59
59
  "axios": "^0.25.0",
60
60
  "axios-retry": "^3.2.5",
61
61
  "bchaddrjs": "^0.5.2",
@@ -77,19 +77,19 @@
77
77
  "@xchainjs/xchain-binance": "^5.6.0",
78
78
  "@xchainjs/xchain-bitcoin": "^0.20.0",
79
79
  "@xchainjs/xchain-bitcoincash": "^0.15.0",
80
- "@xchainjs/xchain-client": "^0.13.1",
80
+ "@xchainjs/xchain-client": "^0.13.2",
81
81
  "@xchainjs/xchain-cosmos": "^0.20.0",
82
82
  "@xchainjs/xchain-crypto": "^0.2.6",
83
83
  "@xchainjs/xchain-doge": "^0.5.0",
84
84
  "@xchainjs/xchain-ethereum": "^0.27.0",
85
85
  "@xchainjs/xchain-evm": "^0.1.0-alpha2",
86
- "@xchainjs/xchain-avax": "^0.1.0-alpha2",
86
+ "@xchainjs/xchain-avax": "^0.1.0-alpha3",
87
87
  "@xchainjs/xchain-litecoin": "^0.10.0",
88
- "@xchainjs/xchain-midgard": "0.1.0-alpha2",
89
- "@xchainjs/xchain-terra": "^0.3.0",
88
+ "@xchainjs/xchain-midgard": "0.1.0",
89
+ "@xchainjs/xchain-thornode": "^0.1.0",
90
90
  "@xchainjs/xchain-thorchain": "^0.26.0",
91
- "@xchainjs/xchain-thorchain-query": "^0.1.0-alpha1",
92
- "@xchainjs/xchain-util": "^0.10.0",
91
+ "@xchainjs/xchain-thorchain-query": "^0.1.0",
92
+ "@xchainjs/xchain-util": "^0.11.0",
93
93
  "axios": "^0.25.0",
94
94
  "axios-retry": "^3.2.5",
95
95
  "bchaddrjs": "^0.5.2",