@shapeshiftoss/swapper 11.1.3 → 11.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.
Files changed (29) hide show
  1. package/dist/adapters.d.ts +2 -0
  2. package/dist/adapters.js +94 -0
  3. package/dist/api.d.ts +3 -3
  4. package/dist/swappercli.js +83 -52
  5. package/dist/swappers/cow/cowBuildTrade/cowBuildTrade.js +2 -2
  6. package/dist/swappers/cow/getCowSwapTradeQuote/getCowSwapTradeQuote.js +2 -2
  7. package/dist/swappers/osmosis/OsmosisSwapper.js +7 -13
  8. package/dist/swappers/thorchain/ThorchainSwapper.js +6 -1
  9. package/dist/swappers/thorchain/buildThorTrade/buildThorTrade.js +7 -5
  10. package/dist/swappers/thorchain/getThorTradeQuote/getTradeQuote.js +7 -4
  11. package/dist/swappers/thorchain/thorTradeApprovalNeeded/thorTradeApprovalNeeded.js +1 -3
  12. package/dist/swappers/thorchain/utils/cosmos/cosmosTxData.d.ts +2 -0
  13. package/dist/swappers/thorchain/utils/cosmos/cosmosTxData.js +22 -2
  14. package/dist/swappers/thorchain/utils/estimateTradeFee/estimateTradeFee.js +5 -0
  15. package/dist/swappers/thorchain/utils/getTradeRate/getTradeRate.js +64 -23
  16. package/dist/swappers/thorchain/utils/getUsdRate/getUsdRate.js +25 -3
  17. package/dist/swappers/thorchain/utils/isRune/isRune.d.ts +2 -0
  18. package/dist/swappers/thorchain/utils/isRune/isRune.js +6 -0
  19. package/dist/swappers/thorchain/utils/makeSwapMemo/makeSwapMemo.js +4 -1
  20. package/dist/swappers/utils/helpers/helpers.js +1 -2
  21. package/dist/swappers/utils/test-data/setupSwapQuote.d.ts +1 -1
  22. package/dist/swappers/utils/test-data/setupSwapQuote.js +3 -3
  23. package/dist/swappers/zrx/getZrxTradeQuote/getZrxTradeQuote.js +2 -2
  24. package/dist/swappers/zrx/utils/test-data/setupZrxSwapQuote.d.ts +5 -1
  25. package/dist/swappers/zrx/utils/test-data/setupZrxSwapQuote.js +1 -1
  26. package/dist/swappers/zrx/zrxApprovalNeeded/zrxApprovalNeeded.js +1 -3
  27. package/dist/swappers/zrx/zrxBuildTrade/zrxBuildTrade.js +2 -2
  28. package/dist/swappers/zrx/zrxExecuteTrade/zrxExecuteTrade.js +1 -4
  29. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ import { ChainAdapterManager } from '@shapeshiftoss/chain-adapters';
2
+ export declare const getAdapterManager: () => ChainAdapterManager;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.getAdapterManager = void 0;
30
+ const chain_adapters_1 = require("@shapeshiftoss/chain-adapters");
31
+ const types_1 = require("@shapeshiftoss/types");
32
+ const unchained = __importStar(require("@shapeshiftoss/unchained-client"));
33
+ const dotenv_1 = __importDefault(require("dotenv"));
34
+ dotenv_1.default.config();
35
+ const { UNCHAINED_ETH_HTTPS_API = 'http://localhost:31300', UNCHAINED_ETH_WS_API = 'wss://localhost:31300', UNCHAINED_BTC_HTTPS_API = 'http://localhost:31300', UNCHAINED_BTC_WS_API = 'wss://localhost:31300', UNCHAINED_LTC_HTTPS_API = 'http://localhost:31300', UNCHAINED_LTC_WS_API = 'wss://localhost:31300', UNCHAINED_RUNE_HTTPS_API = 'http://localhost:31300', UNCHAINED_RUNE_WS_API = 'wss://localhost:31300', UNCHAINED_ATOM_HTTPS_API = 'http://localhost:31300', UNCHAINED_ATOM_WS_API = 'wss://localhost:31300', ETH_NODE_URL = 'http://localhost:31300', } = process.env;
36
+ const getAdapterManager = () => {
37
+ const ethChainAdapter = new chain_adapters_1.ethereum.ChainAdapter({
38
+ providers: {
39
+ ws: new unchained.ws.Client(UNCHAINED_ETH_WS_API),
40
+ http: new unchained.ethereum.V1Api(new unchained.ethereum.Configuration({
41
+ basePath: UNCHAINED_ETH_HTTPS_API,
42
+ })),
43
+ },
44
+ rpcUrl: ETH_NODE_URL,
45
+ });
46
+ const btcAdapterArgs = {
47
+ coinName: 'bitcoin',
48
+ providers: {
49
+ ws: new unchained.ws.Client(UNCHAINED_BTC_WS_API),
50
+ http: new unchained.bitcoin.V1Api(new unchained.bitcoin.Configuration({
51
+ basePath: UNCHAINED_BTC_HTTPS_API,
52
+ })),
53
+ },
54
+ };
55
+ const bitcoinChainAdapter = new chain_adapters_1.bitcoin.ChainAdapter(btcAdapterArgs);
56
+ const ltcAdapterArgs = {
57
+ coinName: 'litecoin',
58
+ providers: {
59
+ ws: new unchained.ws.Client(UNCHAINED_LTC_WS_API),
60
+ http: new unchained.bitcoin.V1Api(new unchained.bitcoin.Configuration({
61
+ basePath: UNCHAINED_LTC_HTTPS_API,
62
+ })),
63
+ },
64
+ };
65
+ const litecoinChainAdapter = new chain_adapters_1.bitcoin.ChainAdapter(ltcAdapterArgs);
66
+ const runeAdapterArgs = {
67
+ coinName: 'rune',
68
+ providers: {
69
+ ws: new unchained.ws.Client(UNCHAINED_RUNE_WS_API),
70
+ http: new unchained.thorchain.V1Api(new unchained.thorchain.Configuration({
71
+ basePath: UNCHAINED_RUNE_HTTPS_API,
72
+ })),
73
+ },
74
+ };
75
+ const thorchainChainAdapter = new chain_adapters_1.thorchain.ChainAdapter(runeAdapterArgs);
76
+ const cosmosAdapterArgs = {
77
+ coinName: 'atom',
78
+ providers: {
79
+ ws: new unchained.ws.Client(UNCHAINED_ATOM_WS_API),
80
+ http: new unchained.thorchain.V1Api(new unchained.thorchain.Configuration({
81
+ basePath: UNCHAINED_ATOM_HTTPS_API,
82
+ })),
83
+ },
84
+ };
85
+ const cosmosChainAdapter = new chain_adapters_1.cosmos.ChainAdapter(cosmosAdapterArgs);
86
+ const adapterManager = new Map();
87
+ adapterManager.set(types_1.KnownChainIds.BitcoinMainnet, bitcoinChainAdapter);
88
+ adapterManager.set(types_1.KnownChainIds.EthereumMainnet, ethChainAdapter);
89
+ adapterManager.set(types_1.KnownChainIds.ThorchainMainnet, thorchainChainAdapter);
90
+ adapterManager.set(types_1.KnownChainIds.LitecoinMainnet, litecoinChainAdapter);
91
+ adapterManager.set(types_1.KnownChainIds.CosmosMainnet, cosmosChainAdapter);
92
+ return adapterManager;
93
+ };
94
+ exports.getAdapterManager = getAdapterManager;
package/dist/api.d.ts CHANGED
@@ -78,11 +78,11 @@ declare type CommonTradeInput = {
78
78
  buyAsset: Asset;
79
79
  sellAmount: string;
80
80
  sendMax: boolean;
81
- sellAssetAccountNumber: number;
82
81
  receiveAddress: string;
82
+ bip44Params: BIP44Params;
83
83
  };
84
84
  export declare type EvmSupportedChainIds = KnownChainIds.EthereumMainnet | KnownChainIds.AvalancheMainnet;
85
- export declare type CosmosSdkSupportedChainIds = KnownChainIds.CosmosMainnet | KnownChainIds.OsmosisMainnet;
85
+ export declare type CosmosSdkSupportedChainIds = KnownChainIds.CosmosMainnet | KnownChainIds.OsmosisMainnet | KnownChainIds.ThorchainMainnet;
86
86
  export declare type EvmSupportedChainAdapters = ethereum.ChainAdapter | avalanche.ChainAdapter;
87
87
  export declare type CosmosSdkSupportedChainAdapters = cosmos.ChainAdapter | osmosis.ChainAdapter;
88
88
  export declare type UtxoSupportedChainIds = KnownChainIds.BitcoinMainnet | KnownChainIds.DogecoinMainnet | KnownChainIds.LitecoinMainnet | KnownChainIds.BitcoinCashMainnet;
@@ -111,7 +111,7 @@ interface TradeBase<C extends ChainId> {
111
111
  sources: SwapSource[];
112
112
  buyAsset: Asset;
113
113
  sellAsset: Asset;
114
- sellAssetAccountNumber: number;
114
+ bip44Params: BIP44Params;
115
115
  }
116
116
  export interface TradeQuote<C extends ChainId> extends TradeBase<C> {
117
117
  allowanceContract: string;
@@ -1,44 +1,22 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
6
  const asset_service_1 = require("@shapeshiftoss/asset-service");
7
+ const caip_1 = require("@shapeshiftoss/caip");
30
8
  const chain_adapters_1 = require("@shapeshiftoss/chain-adapters");
31
9
  const hdwallet_native_1 = require("@shapeshiftoss/hdwallet-native");
32
- const types_1 = require("@shapeshiftoss/types");
33
- const unchained = __importStar(require("@shapeshiftoss/unchained-client"));
34
10
  const bignumber_js_1 = __importDefault(require("bignumber.js"));
35
11
  const dotenv_1 = __importDefault(require("dotenv"));
36
12
  const readline_sync_1 = __importDefault(require("readline-sync"));
37
13
  const web3_1 = __importDefault(require("web3"));
14
+ const adapters_1 = require("./adapters");
38
15
  const SwapperManager_1 = require("./manager/SwapperManager");
16
+ const swappers_1 = require("./swappers");
39
17
  const ZrxSwapper_1 = require("./swappers/zrx/ZrxSwapper");
40
18
  dotenv_1.default.config();
41
- const { UNCHAINED_HTTP_API = 'http://localhost:31300', UNCHAINED_WS_API = 'wss://localhost:31300', ETH_NODE_URL = 'http://localhost:3000', DEVICE_ID = 'device123', MNEMONIC = 'all all all all all all all all all all all all', } = process.env;
19
+ const { ETH_NODE_URL = 'http://localhost:3000', MIDGARD_URL = 'https://dev-indexer.thorchain.shapeshift.com/v2', DEVICE_ID = 'device123', MNEMONIC = 'all all all all all all all all all all all all', } = process.env;
42
20
  const toBaseUnit = (amount, precision) => {
43
21
  return new bignumber_js_1.default(amount)
44
22
  .multipliedBy(new bignumber_js_1.default(10).exponentiatedBy(new bignumber_js_1.default(precision)))
@@ -62,7 +40,7 @@ const getWallet = async () => {
62
40
  const main = async () => {
63
41
  const [, , ...args] = process.argv;
64
42
  const [sellSymbol, buySymbol, sellAmount] = args;
65
- console.info(`sellSymbol: sell ${sellAmount} of ${sellSymbol} to ${buySymbol}`);
43
+ console.info(`sell ${sellAmount} of ${sellSymbol} to ${buySymbol}`);
66
44
  if (!sellAmount || !sellSymbol || !buySymbol) {
67
45
  console.error(`
68
46
  Usage:
@@ -82,64 +60,117 @@ const main = async () => {
82
60
  console.error(`No asset ${buySymbol} found in asset service`);
83
61
  return;
84
62
  }
63
+ const adapterManager = (0, adapters_1.getAdapterManager)();
64
+ const ethAdapter = adapterManager.get(caip_1.ethChainId);
65
+ if (!ethAdapter) {
66
+ throw new Error('no ethAdapter');
67
+ }
68
+ const sellAdapter = adapterManager.get(sellAsset.chainId);
69
+ if (!sellAdapter) {
70
+ throw new Error(`no sellAdapter ${sellAsset.chainId}`);
71
+ }
72
+ const buyAdapter = adapterManager.get(buyAsset.chainId);
73
+ if (!buyAdapter) {
74
+ throw new Error(`no buyAdapter ${buyAsset.chainId}`);
75
+ }
85
76
  // Swapper Deps
86
77
  const wallet = await getWallet();
87
- const ethChainAdapter = new chain_adapters_1.ethereum.ChainAdapter({
88
- providers: {
89
- ws: new unchained.ws.Client(UNCHAINED_WS_API),
90
- http: new unchained.ethereum.V1Api(new unchained.ethereum.Configuration({
91
- basePath: UNCHAINED_HTTP_API,
92
- })),
93
- },
94
- rpcUrl: 'https://mainnet.infura.io/v3/d734c7eebcdf400185d7eb67322a7e57',
95
- });
96
78
  const web3Provider = new web3_1.default.providers.HttpProvider(ETH_NODE_URL);
97
79
  const web3 = new web3_1.default(web3Provider);
98
- const zrxSwapperDeps = { wallet, adapter: ethChainAdapter, web3 };
99
- const manager = new SwapperManager_1.SwapperManager();
80
+ const zrxSwapperDeps = {
81
+ wallet,
82
+ adapter: ethAdapter,
83
+ web3,
84
+ };
85
+ const swapManager = new SwapperManager_1.SwapperManager();
100
86
  const zrxSwapper = new ZrxSwapper_1.ZrxSwapper(zrxSwapperDeps);
101
- manager.addSwapper(zrxSwapper);
102
- const swapper = await manager.getBestSwapper({
103
- sellAssetId: 'eip155:1/slip44:60',
104
- buyAssetId: 'eip155:1/erc20:0xc770eefad204b5180df6a14ee197d99d808ee52d',
87
+ swapManager.addSwapper(zrxSwapper);
88
+ const tcDeps = { midgardUrl: MIDGARD_URL, web3, adapterManager };
89
+ const tc = new swappers_1.ThorchainSwapper(tcDeps);
90
+ await tc.initialize();
91
+ swapManager.addSwapper(tc);
92
+ const swapper = await swapManager.getBestSwapper({
93
+ sellAssetId: sellAsset.assetId,
94
+ buyAssetId: buyAsset.assetId,
105
95
  });
106
- if (!swapper)
96
+ console.info(`using swapper ${swapper === null || swapper === void 0 ? void 0 : swapper.getType()}`);
97
+ if (!swapper) {
98
+ console.warn(`no swapper found for specified assets`);
107
99
  return;
100
+ }
101
+ if (sellAdapter == undefined || sellAdapter == null) {
102
+ throw new Error('huh');
103
+ }
104
+ let utxoAccountType;
105
+ if (sellAdapter.getSupportedAccountTypes) {
106
+ utxoAccountType = chain_adapters_1.bitcoin.ChainAdapter.defaultUtxoAccountType;
107
+ }
108
+ const bip44Params = sellAdapter.getBIP44Params({
109
+ accountNumber: 0,
110
+ accountType: utxoAccountType,
111
+ });
112
+ if (!bip44Params) {
113
+ throw new Error('falsy bip44Params');
114
+ }
115
+ const { chainNamespace: sellChainNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
116
+ switch (sellChainNamespace) {
117
+ case caip_1.CHAIN_NAMESPACE.Evm:
118
+ case caip_1.CHAIN_NAMESPACE.Utxo:
119
+ case caip_1.CHAIN_NAMESPACE.CosmosSdk:
120
+ }
121
+ let publicKey;
122
+ if (sellChainNamespace == caip_1.CHAIN_NAMESPACE.Utxo) {
123
+ if (!utxoAccountType) {
124
+ throw new Error('utxoAccountType must be defined');
125
+ }
126
+ publicKey = await sellAdapter.getPublicKey(wallet, bip44Params, utxoAccountType);
127
+ }
108
128
  const sellAmountBase = toBaseUnit(sellAmount, sellAsset.precision);
129
+ const buyAssetReceiveAddr = await buyAdapter.getAddress({
130
+ wallet,
131
+ accountType: utxoAccountType,
132
+ bip44Params,
133
+ });
134
+ console.info(`${buyAsset.name} using receive addr ${buyAssetReceiveAddr}`);
109
135
  let quote;
110
136
  try {
111
137
  quote = await swapper.getTradeQuote({
112
- chainId: types_1.KnownChainIds.EthereumMainnet,
138
+ chainId: sellAsset.chainId,
113
139
  sellAsset,
114
140
  buyAsset,
115
141
  sellAmount: sellAmountBase,
116
- sellAssetAccountNumber: 0,
117
142
  sendMax: false,
118
- receiveAddress: '0xc770eefad204b5180df6a14ee197d99d808ee52d',
143
+ accountType: utxoAccountType || chain_adapters_1.bitcoin.ChainAdapter.defaultUtxoAccountType,
144
+ bip44Params,
145
+ xpub: (publicKey === null || publicKey === void 0 ? void 0 : publicKey.xpub) || '',
146
+ receiveAddress: buyAssetReceiveAddr,
119
147
  });
120
148
  }
121
149
  catch (e) {
122
150
  console.error(e);
151
+ return;
123
152
  }
124
153
  if (!quote) {
154
+ console.warn('no quote returned');
125
155
  return;
126
156
  }
127
- console.info('quote = ', JSON.stringify(quote));
128
157
  const buyAmount = fromBaseUnit(quote.buyAmount || '0', buyAsset.precision);
129
158
  const answer = readline_sync_1.default.question(`Swap ${sellAmount} ${sellAsset.symbol} for ${buyAmount} ${buyAsset.symbol} on ${swapper.getType()}? (y/n): `);
130
159
  if (answer === 'y') {
131
160
  const trade = await swapper.buildTrade({
132
- chainId: types_1.KnownChainIds.EthereumMainnet,
161
+ chainId: sellAsset.chainId,
133
162
  wallet,
134
163
  buyAsset,
135
164
  sendMax: false,
136
165
  sellAmount: sellAmountBase,
137
166
  sellAsset,
138
- sellAssetAccountNumber: 0,
139
- receiveAddress: '0xc770eefad204b5180df6a14ee197d99d808ee52d',
167
+ receiveAddress: buyAssetReceiveAddr,
168
+ accountType: utxoAccountType || chain_adapters_1.bitcoin.ChainAdapter.defaultUtxoAccountType,
169
+ bip44Params,
170
+ xpub: (publicKey === null || publicKey === void 0 ? void 0 : publicKey.xpub) || '',
140
171
  });
141
- const txid = await swapper.executeTrade({ trade, wallet });
142
- console.info('broadcast tx with id: ', txid);
172
+ const tradeResult = await swapper.executeTrade({ trade, wallet });
173
+ console.info('broadcast tx with id: ', tradeResult.tradeId);
143
174
  }
144
175
  };
145
176
  main().then(() => console.info('Done'));
@@ -12,7 +12,7 @@ const cowService_1 = require("../utils/cowService");
12
12
  const helpers_2 = require("../utils/helpers/helpers");
13
13
  async function cowBuildTrade(deps, input) {
14
14
  try {
15
- const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber, wallet } = input;
15
+ const { sellAsset, buyAsset, sellAmount, bip44Params, wallet } = input;
16
16
  const { adapter, web3 } = deps;
17
17
  const { assetReference: sellAssetErc20Address, assetNamespace: sellAssetNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
18
18
  const { assetReference: buyAssetErc20Address, chainId: buyAssetChainId } = (0, caip_1.fromAssetId)(buyAsset.assetId);
@@ -86,7 +86,7 @@ async function cowBuildTrade(deps, input) {
86
86
  sources: constants_1.DEFAULT_SOURCE,
87
87
  buyAsset,
88
88
  sellAsset,
89
- sellAssetAccountNumber,
89
+ bip44Params,
90
90
  receiveAddress,
91
91
  feeAmountInSellToken: quote.feeAmount,
92
92
  sellAmountWithoutFee: quote.sellAmount,
@@ -17,7 +17,7 @@ const helpers_2 = require("../utils/helpers/helpers");
17
17
  async function getCowSwapTradeQuote(deps, input) {
18
18
  var _a, _b;
19
19
  try {
20
- const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber, receiveAddress } = input;
20
+ const { sellAsset, buyAsset, sellAmount, bip44Params, receiveAddress } = input;
21
21
  const { adapter, web3 } = deps;
22
22
  const { assetReference: sellAssetErc20Address, assetNamespace: sellAssetNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
23
23
  const { assetReference: buyAssetErc20Address, chainId: buyAssetChainId } = (0, caip_1.fromAssetId)(buyAsset.assetId);
@@ -113,7 +113,7 @@ async function getCowSwapTradeQuote(deps, input) {
113
113
  allowanceContract: constants_1.COW_SWAP_VAULT_RELAYER_ADDRESS,
114
114
  buyAsset,
115
115
  sellAsset,
116
- sellAssetAccountNumber,
116
+ bip44Params,
117
117
  };
118
118
  }
119
119
  catch (e) {
@@ -87,7 +87,7 @@ class OsmosisSwapper {
87
87
  return this.supportedAssetIds;
88
88
  }
89
89
  async buildTrade(args) {
90
- const { sellAsset, buyAsset, sellAmount, receiveAddress } = args;
90
+ const { sellAsset, buyAsset, sellAmount, receiveAddress, bip44Params } = args;
91
91
  if (!sellAmount) {
92
92
  throw new api_1.SwapError('sellAmount is required', {
93
93
  code: api_1.SwapErrorTypes.BUILD_TRADE_FAILED,
@@ -111,12 +111,12 @@ class OsmosisSwapper {
111
111
  receiveAddress,
112
112
  sellAmount: amountBaseSell,
113
113
  sellAsset,
114
- sellAssetAccountNumber: 0,
114
+ bip44Params,
115
115
  sources: [{ name: 'Osmosis', proportion: '100' }],
116
116
  };
117
117
  }
118
118
  async getTradeQuote(input) {
119
- const { sellAsset, buyAsset, sellAmount } = input;
119
+ const { bip44Params, sellAsset, buyAsset, sellAmount } = input;
120
120
  if (!sellAmount) {
121
121
  throw new api_1.SwapError('sellAmount is required', {
122
122
  code: api_1.SwapErrorTypes.RESPONSE_ERROR,
@@ -136,7 +136,7 @@ class OsmosisSwapper {
136
136
  feeData: { fee, tradeFee },
137
137
  maximum,
138
138
  minimum,
139
- sellAssetAccountNumber: 0,
139
+ bip44Params,
140
140
  rate,
141
141
  sellAsset,
142
142
  sellAmount,
@@ -146,7 +146,7 @@ class OsmosisSwapper {
146
146
  };
147
147
  }
148
148
  async executeTrade({ trade, wallet }) {
149
- const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber, receiveAddress } = trade;
149
+ const { sellAsset, buyAsset, sellAmount, bip44Params, receiveAddress } = trade;
150
150
  const isFromOsmo = sellAsset.assetId === caip_1.osmosisAssetId;
151
151
  const sellAssetDenom = helpers_1.symbolDenomMapping[sellAsset.symbol];
152
152
  const buyAssetDenom = helpers_1.symbolDenomMapping[buyAsset.symbol];
@@ -163,10 +163,7 @@ class OsmosisSwapper {
163
163
  let sellAddress;
164
164
  let cosmosIbcTradeId = '';
165
165
  if (!isFromOsmo) {
166
- const sellBip44Params = cosmosAdapter.buildBIP44Params({
167
- accountNumber: Number(sellAssetAccountNumber),
168
- });
169
- sellAddress = await cosmosAdapter.getAddress({ wallet, bip44Params: sellBip44Params });
166
+ sellAddress = await cosmosAdapter.getAddress({ wallet, bip44Params });
170
167
  if (!sellAddress)
171
168
  throw new api_1.SwapError('Failed to get address', {
172
169
  code: api_1.SwapErrorTypes.EXECUTE_TRADE_FAILED,
@@ -193,10 +190,7 @@ class OsmosisSwapper {
193
190
  await new Promise((resolve) => setTimeout(resolve, 5000));
194
191
  }
195
192
  else {
196
- const sellBip44Params = osmosisAdapter.buildBIP44Params({
197
- accountNumber: Number(sellAssetAccountNumber),
198
- });
199
- sellAddress = await osmosisAdapter.getAddress({ wallet, bip44Params: sellBip44Params });
193
+ sellAddress = await osmosisAdapter.getAddress({ wallet, bip44Params });
200
194
  if (!sellAddress)
201
195
  throw new api_1.SwapError('failed to get osmoAddress', {
202
196
  code: api_1.SwapErrorTypes.EXECUTE_TRADE_FAILED,
@@ -58,6 +58,7 @@ class ThorchainSwapper {
58
58
  acc.push(assetId);
59
59
  return acc;
60
60
  }, []);
61
+ this.supportedSellAssetIds.push(caip_1.thorchainAssetId);
61
62
  this.supportedBuyAssetIds = responseData.reduce((acc, midgardPool) => {
62
63
  const assetId = caip_1.adapters.poolAssetIdToAssetId(midgardPool.asset);
63
64
  if (!assetId || !this.buySupportedChainIds[(0, caip_1.fromAssetId)(assetId).chainId])
@@ -65,6 +66,7 @@ class ThorchainSwapper {
65
66
  acc.push(assetId);
66
67
  return acc;
67
68
  }, []);
69
+ this.supportedBuyAssetIds.push(caip_1.thorchainAssetId);
68
70
  }
69
71
  catch (e) {
70
72
  throw new api_1.SwapError('[thorchainInitialize]: initialize failed to set supportedAssetIds', {
@@ -163,8 +165,11 @@ class ThorchainSwapper {
163
165
  ? tradeResult.tradeId.slice(2)
164
166
  : tradeResult.tradeId;
165
167
  const { data: responseData } = await thorService_1.thorService.get(`${this.deps.midgardUrl}/actions?txid=${midgardTxid}`);
168
+ // https://gitlab.com/thorchain/thornode/-/blob/develop/common/tx.go#L22
169
+ // responseData?.actions[0].out[0].txID should be the txId for consistency, but the outbound Tx for Thor rune swaps is actually a BlankTxId
170
+ // so we use the buyTxId for completion detection
166
171
  const buyTxid = ((_a = responseData === null || responseData === void 0 ? void 0 : responseData.actions[0]) === null || _a === void 0 ? void 0 : _a.status) === 'success' && ((_b = responseData === null || responseData === void 0 ? void 0 : responseData.actions[0]) === null || _b === void 0 ? void 0 : _b.type) === 'swap'
167
- ? responseData === null || responseData === void 0 ? void 0 : responseData.actions[0].out[0].txID
172
+ ? midgardTxid
168
173
  : '';
169
174
  // This will detect all the errors I have seen.
170
175
  if (((_c = responseData === null || responseData === void 0 ? void 0 : responseData.actions[0]) === null || _c === void 0 ? void 0 : _c.status) === 'success' &&
@@ -12,7 +12,7 @@ const makeTradeTx_1 = require("../utils/ethereum/makeTradeTx");
12
12
  const buildTrade = async ({ deps, input, }) => {
13
13
  var _a, _b, _c, _d;
14
14
  try {
15
- const { buyAsset, sellAsset, sellAssetAccountNumber, sellAmount, wallet, slippage: slippageTolerance = constants_1.DEFAULT_SLIPPAGE, receiveAddress: destinationAddress, } = input;
15
+ const { buyAsset, receiveAddress: destinationAddress, sellAmount, sellAsset, bip44Params, slippage: slippageTolerance = constants_1.DEFAULT_SLIPPAGE, wallet, } = input;
16
16
  const quote = await (0, getTradeQuote_1.getThorTradeQuote)({ deps, input });
17
17
  const sellAdapter = deps.adapterManager.get(sellAsset.chainId);
18
18
  if (!sellAdapter)
@@ -23,13 +23,10 @@ const buildTrade = async ({ deps, input, }) => {
23
23
  });
24
24
  const { chainNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
25
25
  if (chainNamespace === caip_1.CHAIN_NAMESPACE.Evm) {
26
- const sellAssetBip44Params = sellAdapter.buildBIP44Params({
27
- accountNumber: sellAssetAccountNumber,
28
- });
29
26
  const ethTradeTx = await (0, makeTradeTx_1.makeTradeTx)({
30
27
  wallet,
31
28
  slippageTolerance,
32
- bip44Params: sellAssetBip44Params,
29
+ bip44Params,
33
30
  sellAsset,
34
31
  buyAsset,
35
32
  adapter: sellAdapter,
@@ -78,7 +75,11 @@ const buildTrade = async ({ deps, input, }) => {
78
75
  };
79
76
  }
80
77
  else if (chainNamespace === caip_1.CHAIN_NAMESPACE.CosmosSdk) {
78
+ if (!bip44Params) {
79
+ throw new Error('bip44Params required as input');
80
+ }
81
81
  const txData = await (0, cosmosTxData_1.cosmosTxData)({
82
+ bip44Params,
82
83
  deps,
83
84
  sellAdapter: sellAdapter,
84
85
  sellAmount,
@@ -111,6 +112,7 @@ const buildTrade = async ({ deps, input, }) => {
111
112
  throw new api_1.SwapError('[buildTrade]: error building trade', {
112
113
  code: api_1.SwapErrorTypes.BUILD_TRADE_FAILED,
113
114
  fn: 'buildTrade',
115
+ cause: e,
114
116
  });
115
117
  }
116
118
  };
@@ -15,9 +15,12 @@ const getBtcTxFees_1 = require("../utils/txFeeHelpers/btcTxFees/getBtcTxFees");
15
15
  const getEthTxFees_1 = require("../utils/txFeeHelpers/ethTxFees/getEthTxFees");
16
16
  const MINIMUM_USD_TRADE_AMOUNT = (0, bignumber_1.bn)(1);
17
17
  const getThorTradeQuote = async ({ deps, input }) => {
18
- const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber, chainId, receiveAddress } = input;
18
+ const { sellAsset, buyAsset, sellAmount, bip44Params, chainId, receiveAddress } = input;
19
+ if (!bip44Params) {
20
+ throw new Error('bip44Params required in getThorTradeQuote');
21
+ }
19
22
  try {
20
- const { assetReference: sellAssetErc20Address } = (0, caip_1.fromAssetId)(sellAsset.assetId);
23
+ const { assetReference: sellAssetReference } = (0, caip_1.fromAssetId)(sellAsset.assetId);
21
24
  const sellAdapter = deps.adapterManager.get(chainId);
22
25
  if (!sellAdapter)
23
26
  throw new api_1.SwapError(`[getThorTradeQuote] - No chain adapter found for ${chainId}.`, {
@@ -44,7 +47,7 @@ const getThorTradeQuote = async ({ deps, input }) => {
44
47
  sources: [{ name: 'thorchain', proportion: '1' }],
45
48
  buyAsset,
46
49
  sellAsset,
47
- sellAssetAccountNumber,
50
+ bip44Params,
48
51
  minimum,
49
52
  };
50
53
  const { chainNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
@@ -62,7 +65,7 @@ const getThorTradeQuote = async ({ deps, input }) => {
62
65
  });
63
66
  const feeData = await (0, getEthTxFees_1.getEthTxFees)({
64
67
  adapterManager: deps.adapterManager,
65
- sellAssetReference: sellAssetErc20Address,
68
+ sellAssetReference,
66
69
  tradeFee,
67
70
  });
68
71
  return {
@@ -10,13 +10,12 @@ const thorTradeApprovalNeeded = async ({ deps, input, }) => {
10
10
  var _a;
11
11
  try {
12
12
  const { quote, wallet } = input;
13
- const { sellAsset } = quote;
13
+ const { sellAsset, bip44Params } = quote;
14
14
  const { adapterManager, web3 } = deps;
15
15
  const { assetReference: sellAssetErc20Address } = (0, caip_1.fromAssetId)(sellAsset.assetId);
16
16
  const { chainNamespace } = (0, caip_1.fromChainId)(sellAsset.chainId);
17
17
  if (chainNamespace !== caip_1.CHAIN_NAMESPACE.Evm)
18
18
  return { approvalNeeded: false };
19
- const accountNumber = quote.sellAssetAccountNumber;
20
19
  const adapter = adapterManager.get(sellAsset.chainId);
21
20
  if (!adapter)
22
21
  throw new api_1.SwapError(`[thorTradeApprovalNeeded] - no chain adapter found for chain Id: ${sellAsset.chainId}`, {
@@ -27,7 +26,6 @@ const thorTradeApprovalNeeded = async ({ deps, input, }) => {
27
26
  if (sellAsset.assetId === adapter.getFeeAssetId()) {
28
27
  return { approvalNeeded: false };
29
28
  }
30
- const bip44Params = adapter.buildBIP44Params({ accountNumber });
31
29
  const receiveAddress = await adapter.getAddress({ wallet, bip44Params });
32
30
  if (!quote.allowanceContract) {
33
31
  throw new api_1.SwapError('[thorTradeApprovalNeeded] - allowanceTarget is required', {
@@ -3,9 +3,11 @@ import { ChainId } from '@shapeshiftoss/caip';
3
3
  import { ChainAdapter } from '@shapeshiftoss/chain-adapters';
4
4
  import { HDWallet } from '@shapeshiftoss/hdwallet-core';
5
5
  import { KnownChainIds } from '@shapeshiftoss/types';
6
+ import { BIP44Params } from '@shapeshiftoss/types';
6
7
  import { TradeQuote } from '../../../../api';
7
8
  import { ThorchainSwapperDeps } from '../../types';
8
9
  export declare const cosmosTxData: (input: {
10
+ bip44Params: BIP44Params;
9
11
  destinationAddress: string;
10
12
  deps: ThorchainSwapperDeps;
11
13
  sellAmount: string;
@@ -1,16 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.cosmosTxData = void 0;
4
+ const types_1 = require("@shapeshiftoss/types");
4
5
  const api_1 = require("../../../../api");
5
6
  const getLimit_1 = require("../getLimit/getLimit");
6
7
  const makeSwapMemo_1 = require("../makeSwapMemo/makeSwapMemo");
7
8
  const thorService_1 = require("../thorService");
8
9
  const cosmosTxData = async (input) => {
9
- const { deps, destinationAddress, sellAmount, sellAsset, buyAsset, slippageTolerance, quote, wallet, sellAdapter, } = input;
10
+ const { bip44Params, deps, destinationAddress, sellAmount, sellAsset, buyAsset, slippageTolerance, quote, wallet, sellAdapter, } = input;
11
+ const fromThorAsset = sellAsset.chainId == types_1.KnownChainIds.ThorchainMainnet;
10
12
  const { data: inboundAddresses } = await thorService_1.thorService.get(`${deps.midgardUrl}/thorchain/inbound_addresses`);
11
13
  const atomInboundAddresses = inboundAddresses.find((inbound) => inbound.chain === 'GAIA');
12
14
  const vault = atomInboundAddresses === null || atomInboundAddresses === void 0 ? void 0 : atomInboundAddresses.address;
13
- if (!vault)
15
+ if (!vault && !fromThorAsset)
14
16
  throw new api_1.SwapError('[buildTrade]: no vault for chain', {
15
17
  code: api_1.SwapErrorTypes.BUILD_TRADE_FAILED,
16
18
  fn: 'buildTrade',
@@ -31,7 +33,25 @@ const cosmosTxData = async (input) => {
31
33
  destinationAddress,
32
34
  limit,
33
35
  });
36
+ if (fromThorAsset) {
37
+ const buildTxResponse = await sellAdapter.buildDepositTransaction({
38
+ bip44Params,
39
+ value: sellAmount,
40
+ wallet,
41
+ memo,
42
+ gas: quote.feeData.chainSpecific.estimatedGas,
43
+ fee: quote.feeData.fee,
44
+ });
45
+ return buildTxResponse.txToSign;
46
+ }
47
+ if (!vault)
48
+ throw new api_1.SwapError('[buildTrade]: no vault for chain', {
49
+ code: api_1.SwapErrorTypes.BUILD_TRADE_FAILED,
50
+ fn: 'buildTrade',
51
+ details: { chainId: input.chainId },
52
+ });
34
53
  const buildTxResponse = await sellAdapter.buildSendTransaction({
54
+ bip44Params,
35
55
  value: sellAmount,
36
56
  wallet,
37
57
  to: vault,
@@ -5,8 +5,13 @@ const caip_1 = require("@shapeshiftoss/caip");
5
5
  const api_1 = require("../../../../api");
6
6
  const constants_1 = require("../constants");
7
7
  const getPriceRatio_1 = require("../getPriceRatio/getPriceRatio");
8
+ const isRune_1 = require("../isRune/isRune");
8
9
  const thorService_1 = require("../thorService");
10
+ // TODO rename this estimateOutboundFee or similar
9
11
  const estimateTradeFee = async (deps, buyAsset) => {
12
+ if ((0, isRune_1.isRune)(buyAsset.assetId)) {
13
+ return '0.02'; // todo - read from TC mimir/constants
14
+ }
10
15
  const thorId = caip_1.adapters.assetIdToPoolAssetId({ assetId: buyAsset.assetId });
11
16
  if (!thorId)
12
17
  throw new api_1.SwapError('[estimateTradeFee] - undefined thorId for given buyAssetId', {
@@ -4,8 +4,8 @@ exports.getTradeRate = void 0;
4
4
  const caip_1 = require("@shapeshiftoss/caip");
5
5
  const api_1 = require("../../../../api");
6
6
  const bignumber_1 = require("../../../utils/bignumber");
7
- const bignumber_2 = require("../../../utils/bignumber");
8
7
  const getPriceRatio_1 = require("../getPriceRatio/getPriceRatio");
8
+ const isRune_1 = require("../isRune/isRune");
9
9
  const thorService_1 = require("../thorService");
10
10
  const THOR_PRECISION = 8;
11
11
  const getSwapOutput = (inputAmount, poolData, toRune) => {
@@ -33,33 +33,74 @@ const getTradeRate = async (sellAsset, buyAssetId, sellAmount, deps) => {
33
33
  }
34
34
  const buyPoolId = caip_1.adapters.assetIdToPoolAssetId({ assetId: buyAssetId });
35
35
  const sellPoolId = caip_1.adapters.assetIdToPoolAssetId({ assetId: sellAsset.assetId });
36
- if (!buyPoolId || !sellPoolId)
37
- throw new api_1.SwapError(`[getPriceRatio]: No thorchain pool found`, {
36
+ if (!buyPoolId && !(0, isRune_1.isRune)(buyAssetId)) {
37
+ throw new api_1.SwapError(`[getTradeRate]: No buyPoolId for asset ${buyAssetId}`, {
38
38
  code: api_1.SwapErrorTypes.POOL_NOT_FOUND,
39
- fn: 'getPriceRatio',
40
- details: { buyPoolId, sellPoolId },
39
+ fn: 'getTradeRate',
40
+ details: { buyAssetId },
41
41
  });
42
+ }
43
+ if (!sellPoolId && !(0, isRune_1.isRune)(sellAsset.assetId)) {
44
+ throw new api_1.SwapError(`[getTradeRate]: No sellPoolId for asset ${sellAsset.assetId}`, {
45
+ code: api_1.SwapErrorTypes.POOL_NOT_FOUND,
46
+ fn: 'getTradeRate',
47
+ details: { sellAsset: sellAsset.assetId },
48
+ });
49
+ }
42
50
  const { data: responseData } = await thorService_1.thorService.get(`${deps.midgardUrl}/pools`);
43
- const buyPool = responseData.find((response) => response.asset === buyPoolId);
44
- const sellPool = responseData.find((response) => response.asset === sellPoolId);
45
- if (!buyPool || !sellPool)
46
- throw new api_1.SwapError(`[getPriceRatio]: no pools found for`, {
51
+ const buyPool = buyPoolId && responseData.find((response) => response.asset === buyPoolId);
52
+ const sellPool = sellPoolId && responseData.find((response) => response.asset === sellPoolId);
53
+ if (buyPoolId && !buyPool) {
54
+ throw new api_1.SwapError(`[getTradeRate]: No buyPool for poolId ${buyPoolId}`, {
47
55
  code: api_1.SwapErrorTypes.POOL_NOT_FOUND,
48
- fn: 'getPriceRatio',
49
- details: { buyPoolId, sellPoolId },
56
+ fn: 'getTradeRate',
57
+ details: { buyPoolId },
50
58
  });
59
+ }
60
+ if (sellPoolId && !sellPool) {
61
+ throw new api_1.SwapError(`[getTradeRate]: No sellPool for poolId ${sellPoolId}`, {
62
+ code: api_1.SwapErrorTypes.POOL_NOT_FOUND,
63
+ fn: 'getTradeRate',
64
+ details: { sellPoolId },
65
+ });
66
+ }
51
67
  // All thorchain pool amounts are base 8 regardless of token precision
52
- const sellBaseAmount = (0, bignumber_1.bn)((0, bignumber_2.toBaseUnit)((0, bignumber_2.fromBaseUnit)(sellAmount, sellAsset.precision), THOR_PRECISION));
53
- const sellAssetPoolData = {
54
- assetBalance: (0, bignumber_1.bn)(sellPool.assetDepth),
55
- runeBalance: (0, bignumber_1.bn)(sellPool.runeDepth),
56
- };
57
- const buyAssetPoolData = {
58
- assetBalance: (0, bignumber_1.bn)(buyPool.assetDepth),
59
- runeBalance: (0, bignumber_1.bn)(buyPool.runeDepth),
60
- };
61
- const outputAmountBase8 = getDoubleSwapOutput(sellBaseAmount, sellAssetPoolData, buyAssetPoolData);
62
- const outputAmount = (0, bignumber_2.fromBaseUnit)(outputAmountBase8, THOR_PRECISION);
63
- return (0, bignumber_1.bn)(outputAmount).div((0, bignumber_2.fromBaseUnit)(sellAmount, sellAsset.precision)).toString();
68
+ const sellBaseAmount = (0, bignumber_1.bn)((0, bignumber_1.toBaseUnit)((0, bignumber_1.fromBaseUnit)(sellAmount, sellAsset.precision), THOR_PRECISION));
69
+ const doubleSwap = buyPool != undefined && sellPool != undefined;
70
+ const toRune = buyAssetId === caip_1.thorchainAssetId;
71
+ const outputAmountBase8 = (() => {
72
+ if (doubleSwap && sellPool && buyPool) {
73
+ const sellAssetPoolData = {
74
+ assetBalance: (0, bignumber_1.bn)(sellPool.assetDepth),
75
+ runeBalance: (0, bignumber_1.bn)(sellPool.runeDepth),
76
+ };
77
+ const buyAssetPoolData = {
78
+ assetBalance: (0, bignumber_1.bn)(buyPool.assetDepth),
79
+ runeBalance: (0, bignumber_1.bn)(buyPool.runeDepth),
80
+ };
81
+ return getDoubleSwapOutput(sellBaseAmount, sellAssetPoolData, buyAssetPoolData);
82
+ }
83
+ else {
84
+ const poolData = sellPool
85
+ ? {
86
+ assetBalance: (0, bignumber_1.bn)(sellPool.assetDepth),
87
+ runeBalance: (0, bignumber_1.bn)(sellPool.runeDepth),
88
+ }
89
+ : buyPool && {
90
+ assetBalance: (0, bignumber_1.bn)(buyPool.assetDepth),
91
+ runeBalance: (0, bignumber_1.bn)(buyPool.runeDepth),
92
+ };
93
+ if (!poolData) {
94
+ throw new api_1.SwapError(`[getPriceRatio]: No pool data for rune swap`, {
95
+ code: api_1.SwapErrorTypes.POOL_NOT_FOUND,
96
+ fn: 'getPriceRatio',
97
+ details: { buyAssetId, sellAsset, buyPool, sellPool },
98
+ });
99
+ }
100
+ return getSwapOutput(sellBaseAmount, poolData, toRune);
101
+ }
102
+ })();
103
+ const outputAmount = (0, bignumber_1.fromBaseUnit)(outputAmountBase8, THOR_PRECISION);
104
+ return (0, bignumber_1.bn)(outputAmount).div((0, bignumber_1.fromBaseUnit)(sellAmount, sellAsset.precision)).toString();
64
105
  };
65
106
  exports.getTradeRate = getTradeRate;
@@ -3,19 +3,41 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getUsdRate = void 0;
4
4
  const caip_1 = require("@shapeshiftoss/caip");
5
5
  const api_1 = require("../../../../api");
6
+ const bignumber_1 = require("../../../utils/bignumber");
7
+ const isRune_1 = require("../isRune/isRune");
6
8
  const thorService_1 = require("../thorService");
9
+ const THOR_PRECISION = 8;
10
+ // not sure what to do for rune usd rate - inverting USDC pool rate for now
11
+ const usdcPool = 'ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48';
7
12
  const getUsdRate = async ({ deps, input, }) => {
8
13
  const { assetId } = input;
9
14
  try {
10
- const thorchainPoolId = caip_1.adapters.assetIdToPoolAssetId({ assetId });
15
+ const thorchainPoolId = (() => {
16
+ if ((0, isRune_1.isRune)(assetId)) {
17
+ return usdcPool;
18
+ }
19
+ return caip_1.adapters.assetIdToPoolAssetId({ assetId });
20
+ })();
11
21
  if (!thorchainPoolId)
12
22
  throw new api_1.SwapError(`[getUsdRate]: No thorchainPoolId found for assetId: ${assetId}`, {
13
23
  code: api_1.SwapErrorTypes.USD_RATE_FAILED,
14
24
  });
15
25
  const { data: responseData } = await thorService_1.thorService.get(`${deps.midgardUrl}/pool/${thorchainPoolId}`);
16
- const rate = responseData === null || responseData === void 0 ? void 0 : responseData.assetPriceUSD;
26
+ const rate = (() => {
27
+ if ((0, isRune_1.isRune)(assetId)) {
28
+ const bnRate = (0, bignumber_1.bnOrZero)(responseData === null || responseData === void 0 ? void 0 : responseData.assetPrice);
29
+ if (bnRate.isZero()) {
30
+ throw new api_1.SwapError('[getUsdRate]: cannot invert rate zero', {
31
+ code: api_1.SwapErrorTypes.USD_RATE_FAILED,
32
+ });
33
+ }
34
+ const inverseRate = (0, bignumber_1.bn)(1).div(bnRate);
35
+ return inverseRate.toFixed(THOR_PRECISION);
36
+ }
37
+ return responseData === null || responseData === void 0 ? void 0 : responseData.assetPriceUSD;
38
+ })();
17
39
  if (!rate)
18
- throw new api_1.SwapError(`[getUsdRate]: No rate found`, {
40
+ throw new api_1.SwapError(`[getUsdRate]: No rate for ${assetId}`, {
19
41
  code: api_1.SwapErrorTypes.USD_RATE_FAILED,
20
42
  });
21
43
  return rate;
@@ -0,0 +1,2 @@
1
+ import { AssetId } from '@shapeshiftoss/caip';
2
+ export declare const isRune: (assetId: AssetId) => boolean;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isRune = void 0;
4
+ const caip_1 = require("@shapeshiftoss/caip");
5
+ const isRune = (assetId) => assetId === caip_1.thorchainAssetId;
6
+ exports.isRune = isRune;
@@ -6,12 +6,15 @@ const api_1 = require("../../../../api");
6
6
  const constants_1 = require("../constants");
7
7
  // BTC (and likely other utxo coins) can only support up to 80 character memos
8
8
  const MAX_LENGTH = 80;
9
+ // use symbol of thor Asset?
10
+ const runeThorId = 'RUNE';
9
11
  /**
10
12
  * @returns thorchain memo shortened to a max of 80 characters as described:
11
13
  * https://dev.thorchain.org/thorchain-dev/memos#mechanism-for-transaction-intent
12
14
  */
13
15
  const makeSwapMemo = ({ buyAssetId, destinationAddress, limit, }) => {
14
- const thorId = caip_1.adapters.assetIdToPoolAssetId({ assetId: buyAssetId });
16
+ const isRune = buyAssetId === caip_1.thorchainAssetId;
17
+ const thorId = isRune ? runeThorId : caip_1.adapters.assetIdToPoolAssetId({ assetId: buyAssetId });
15
18
  if (!thorId)
16
19
  throw new api_1.SwapError('[makeSwapMemo] - undefined thorId for given buyAssetId', {
17
20
  code: api_1.SwapErrorTypes.MAKE_MEMO_FAILED,
@@ -56,8 +56,7 @@ const grantAllowance = async ({ quote, wallet, adapter, erc20Abi, web3, }) => {
56
56
  const approveTx = erc20Contract.methods
57
57
  .approve(quote.allowanceContract, quote.sellAmount)
58
58
  .encodeABI();
59
- const accountNumber = quote.sellAssetAccountNumber;
60
- const bip44Params = adapter.buildBIP44Params({ accountNumber });
59
+ const { bip44Params } = quote;
61
60
  const { txToSign } = await adapter.buildSendTransaction({
62
61
  wallet,
63
62
  to: sellAssetErc20Address,
@@ -14,8 +14,8 @@ export declare const setupBuildTrade: () => {
14
14
  buyAsset: Asset;
15
15
  sellAmount: string;
16
16
  sendMax: boolean;
17
- sellAssetAccountNumber: number;
18
17
  receiveAddress: string;
18
+ bip44Params: import("@shapeshiftoss/types").BIP44Params;
19
19
  } & {
20
20
  chainId: import("../../../api").EvmSupportedChainIds;
21
21
  } & {
@@ -12,7 +12,7 @@ const setupQuote = () => {
12
12
  sellAsset,
13
13
  buyAsset,
14
14
  allowanceContract: 'allowanceContractAddress',
15
- sellAssetAccountNumber: 0,
15
+ bip44Params: { purpose: 44, coinType: 60, accountNumber: 0 },
16
16
  minimum: '0',
17
17
  maximum: '999999999999',
18
18
  feeData: { fee: '0', tradeFee: '0', chainSpecific: {} },
@@ -24,7 +24,7 @@ const setupQuote = () => {
24
24
  sellAmount: '1000000000000000000',
25
25
  sellAsset,
26
26
  buyAsset,
27
- sellAssetAccountNumber: 0,
27
+ bip44Params: { purpose: 44, coinType: 60, accountNumber: 0 },
28
28
  sendMax: false,
29
29
  receiveAddress: '0xc770eefad204b5180df6a14ee197d99d808ee52d',
30
30
  };
@@ -39,7 +39,7 @@ const setupBuildTrade = () => {
39
39
  sellAmount: '1000000000000000000',
40
40
  buyAsset,
41
41
  sendMax: false,
42
- sellAssetAccountNumber: 0,
42
+ bip44Params: { purpose: 44, coinType: 60, accountNumber: 0 },
43
43
  sellAsset,
44
44
  wallet: {},
45
45
  receiveAddress: '',
@@ -12,7 +12,7 @@ const helpers_2 = require("../utils/helpers/helpers");
12
12
  const zrxService_1 = require("../utils/zrxService");
13
13
  async function getZrxTradeQuote(input) {
14
14
  try {
15
- const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber } = input;
15
+ const { sellAsset, buyAsset, sellAmount, bip44Params } = input;
16
16
  if (buyAsset.chainId !== input.chainId || sellAsset.chainId !== input.chainId) {
17
17
  throw new api_1.SwapError('[getZrxTradeQuote] - Both assets need to be on the same supported EVM chain to use Zrx', {
18
18
  code: api_1.SwapErrorTypes.UNSUPPORTED_PAIR,
@@ -72,7 +72,7 @@ async function getZrxTradeQuote(input) {
72
72
  allowanceContract: allowanceTarget,
73
73
  buyAsset,
74
74
  sellAsset,
75
- sellAssetAccountNumber,
75
+ bip44Params,
76
76
  };
77
77
  }
78
78
  catch (e) {
@@ -17,7 +17,11 @@ export declare const setupExecuteTrade: () => {
17
17
  buyAsset: Asset;
18
18
  sellAsset: Asset;
19
19
  sendMax: boolean;
20
- sellAssetAccountNumber: number;
20
+ bip44Params: {
21
+ purpose: number;
22
+ coinType: number;
23
+ accountNumber: number;
24
+ };
21
25
  txData: string;
22
26
  depositAddress: string;
23
27
  receiveAddress: string;
@@ -33,7 +33,7 @@ const setupExecuteTrade = () => {
33
33
  buyAsset,
34
34
  sellAsset,
35
35
  sendMax: false,
36
- sellAssetAccountNumber: 0,
36
+ bip44Params: { purpose: 44, coinType: 60, accountNumber: 0 },
37
37
  txData: '0x0',
38
38
  depositAddress: '0x0',
39
39
  receiveAddress: '0x0',
@@ -21,9 +21,7 @@ async function zrxApprovalNeeded({ adapter, web3 }, { quote, wallet }) {
21
21
  if (sellAsset.assetId === adapter.getFeeAssetId()) {
22
22
  return { approvalNeeded: false };
23
23
  }
24
- const accountNumber = quote.sellAssetAccountNumber;
25
- const bip44Params = adapter.buildBIP44Params({ accountNumber });
26
- const receiveAddress = await adapter.getAddress({ wallet, bip44Params });
24
+ const receiveAddress = await adapter.getAddress({ wallet, bip44Params: quote.bip44Params });
27
25
  if (!quote.allowanceContract) {
28
26
  throw new api_1.SwapError('[zrxApprovalNeeded] - allowanceTarget is required', {
29
27
  code: api_1.SwapErrorTypes.VALIDATION_FAILED,
@@ -37,7 +37,7 @@ const helpers_2 = require("../utils/helpers/helpers");
37
37
  const zrxService_1 = require("../utils/zrxService");
38
38
  async function zrxBuildTrade({ adapter, web3 }, input) {
39
39
  var _a, _b, _c;
40
- const { sellAsset, buyAsset, sellAmount, slippage, sellAssetAccountNumber, receiveAddress } = input;
40
+ const { sellAsset, buyAsset, sellAmount, slippage, bip44Params, receiveAddress } = input;
41
41
  try {
42
42
  const { assetReference: buyAssetErc20Address, assetNamespace: buyAssetNamespace } = (0, caip_1.fromAssetId)(buyAsset.assetId);
43
43
  const { assetReference: sellAssetErc20Address, assetNamespace: sellAssetNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
@@ -94,7 +94,7 @@ async function zrxBuildTrade({ adapter, web3 }, input) {
94
94
  const trade = {
95
95
  sellAsset,
96
96
  buyAsset,
97
- sellAssetAccountNumber,
97
+ bip44Params,
98
98
  receiveAddress,
99
99
  rate: data.price,
100
100
  depositAddress: data.to,
@@ -6,13 +6,10 @@ const api_1 = require("../../../api");
6
6
  const helpers_1 = require("../utils/helpers/helpers");
7
7
  async function zrxExecuteTrade({ adapter }, { trade, wallet }) {
8
8
  var _a, _b, _c, _d, _e, _f;
9
- const { sellAsset } = trade;
9
+ const { bip44Params, sellAsset } = trade;
10
10
  try {
11
11
  // value is 0 for erc20s
12
12
  const value = (0, helpers_1.isNativeEvmAsset)(sellAsset.assetId) ? trade.sellAmount : '0';
13
- const bip44Params = adapter.buildBIP44Params({
14
- accountNumber: trade.sellAssetAccountNumber,
15
- });
16
13
  const buildTxResponse = await adapter.buildSendTransaction({
17
14
  value,
18
15
  wallet,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshiftoss/swapper",
3
- "version": "11.1.3",
3
+ "version": "11.3.0",
4
4
  "description": "An interface and implementations to trade coins via various protocols",
5
5
  "repository": "https://github.com/shapeshift/lib",
6
6
  "license": "MIT",