@shapeshiftoss/swapper 11.1.3 → 11.2.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/dist/adapters.d.ts +2 -0
- package/dist/adapters.js +94 -0
- package/dist/api.d.ts +2 -1
- package/dist/swappercli.js +83 -50
- package/dist/swappers/thorchain/ThorchainSwapper.js +6 -1
- package/dist/swappers/thorchain/buildThorTrade/buildThorTrade.js +6 -1
- package/dist/swappers/thorchain/getThorTradeQuote/getTradeQuote.js +2 -2
- package/dist/swappers/thorchain/utils/cosmos/cosmosTxData.d.ts +2 -0
- package/dist/swappers/thorchain/utils/cosmos/cosmosTxData.js +22 -2
- package/dist/swappers/thorchain/utils/estimateTradeFee/estimateTradeFee.js +5 -0
- package/dist/swappers/thorchain/utils/getTradeRate/getTradeRate.js +64 -23
- package/dist/swappers/thorchain/utils/getUsdRate/getUsdRate.js +25 -3
- package/dist/swappers/thorchain/utils/isRune/isRune.d.ts +2 -0
- package/dist/swappers/thorchain/utils/isRune/isRune.js +6 -0
- package/dist/swappers/thorchain/utils/makeSwapMemo/makeSwapMemo.js +4 -1
- package/dist/swappers/utils/test-data/setupSwapQuote.d.ts +1 -0
- package/package.json +1 -1
package/dist/adapters.js
ADDED
|
@@ -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
|
@@ -74,6 +74,7 @@ export declare type SupportedSellAssetsInput = {
|
|
|
74
74
|
assetIds: AssetId[];
|
|
75
75
|
};
|
|
76
76
|
declare type CommonTradeInput = {
|
|
77
|
+
bip44Params?: BIP44Params;
|
|
77
78
|
sellAsset: Asset;
|
|
78
79
|
buyAsset: Asset;
|
|
79
80
|
sellAmount: string;
|
|
@@ -82,7 +83,7 @@ declare type CommonTradeInput = {
|
|
|
82
83
|
receiveAddress: string;
|
|
83
84
|
};
|
|
84
85
|
export declare type EvmSupportedChainIds = KnownChainIds.EthereumMainnet | KnownChainIds.AvalancheMainnet;
|
|
85
|
-
export declare type CosmosSdkSupportedChainIds = KnownChainIds.CosmosMainnet | KnownChainIds.OsmosisMainnet;
|
|
86
|
+
export declare type CosmosSdkSupportedChainIds = KnownChainIds.CosmosMainnet | KnownChainIds.OsmosisMainnet | KnownChainIds.ThorchainMainnet;
|
|
86
87
|
export declare type EvmSupportedChainAdapters = ethereum.ChainAdapter | avalanche.ChainAdapter;
|
|
87
88
|
export declare type CosmosSdkSupportedChainAdapters = cosmos.ChainAdapter | osmosis.ChainAdapter;
|
|
88
89
|
export declare type UtxoSupportedChainIds = KnownChainIds.BitcoinMainnet | KnownChainIds.DogecoinMainnet | KnownChainIds.LitecoinMainnet | KnownChainIds.BitcoinCashMainnet;
|
package/dist/swappercli.js
CHANGED
|
@@ -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 {
|
|
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(`
|
|
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,119 @@ 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 = {
|
|
99
|
-
|
|
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
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
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:
|
|
138
|
+
chainId: sellAsset.chainId,
|
|
113
139
|
sellAsset,
|
|
114
140
|
buyAsset,
|
|
115
141
|
sellAmount: sellAmountBase,
|
|
116
142
|
sellAssetAccountNumber: 0,
|
|
117
143
|
sendMax: false,
|
|
118
|
-
|
|
144
|
+
accountType: utxoAccountType || chain_adapters_1.bitcoin.ChainAdapter.defaultUtxoAccountType,
|
|
145
|
+
bip44Params,
|
|
146
|
+
xpub: (publicKey === null || publicKey === void 0 ? void 0 : publicKey.xpub) || '',
|
|
147
|
+
receiveAddress: buyAssetReceiveAddr,
|
|
119
148
|
});
|
|
120
149
|
}
|
|
121
150
|
catch (e) {
|
|
122
151
|
console.error(e);
|
|
152
|
+
return;
|
|
123
153
|
}
|
|
124
154
|
if (!quote) {
|
|
155
|
+
console.warn('no quote returned');
|
|
125
156
|
return;
|
|
126
157
|
}
|
|
127
|
-
console.info('quote = ', JSON.stringify(quote));
|
|
128
158
|
const buyAmount = fromBaseUnit(quote.buyAmount || '0', buyAsset.precision);
|
|
129
159
|
const answer = readline_sync_1.default.question(`Swap ${sellAmount} ${sellAsset.symbol} for ${buyAmount} ${buyAsset.symbol} on ${swapper.getType()}? (y/n): `);
|
|
130
160
|
if (answer === 'y') {
|
|
131
161
|
const trade = await swapper.buildTrade({
|
|
132
|
-
chainId:
|
|
162
|
+
chainId: sellAsset.chainId,
|
|
133
163
|
wallet,
|
|
134
164
|
buyAsset,
|
|
135
165
|
sendMax: false,
|
|
136
166
|
sellAmount: sellAmountBase,
|
|
137
167
|
sellAsset,
|
|
138
168
|
sellAssetAccountNumber: 0,
|
|
139
|
-
receiveAddress:
|
|
169
|
+
receiveAddress: buyAssetReceiveAddr,
|
|
170
|
+
accountType: utxoAccountType || chain_adapters_1.bitcoin.ChainAdapter.defaultUtxoAccountType,
|
|
171
|
+
bip44Params,
|
|
172
|
+
xpub: (publicKey === null || publicKey === void 0 ? void 0 : publicKey.xpub) || '',
|
|
140
173
|
});
|
|
141
|
-
const
|
|
142
|
-
console.info('broadcast tx with id: ',
|
|
174
|
+
const tradeResult = await swapper.executeTrade({ trade, wallet });
|
|
175
|
+
console.info('broadcast tx with id: ', tradeResult.tradeId);
|
|
143
176
|
}
|
|
144
177
|
};
|
|
145
178
|
main().then(() => console.info('Done'));
|
|
@@ -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
|
-
?
|
|
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 {
|
|
15
|
+
const { bip44Params, buyAsset, receiveAddress: destinationAddress, sellAmount, sellAsset, sellAssetAccountNumber, 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)
|
|
@@ -78,7 +78,11 @@ const buildTrade = async ({ deps, input, }) => {
|
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
else if (chainNamespace === caip_1.CHAIN_NAMESPACE.CosmosSdk) {
|
|
81
|
+
if (!bip44Params) {
|
|
82
|
+
throw new Error('bip44Params required as input');
|
|
83
|
+
}
|
|
81
84
|
const txData = await (0, cosmosTxData_1.cosmosTxData)({
|
|
85
|
+
bip44Params,
|
|
82
86
|
deps,
|
|
83
87
|
sellAdapter: sellAdapter,
|
|
84
88
|
sellAmount,
|
|
@@ -111,6 +115,7 @@ const buildTrade = async ({ deps, input, }) => {
|
|
|
111
115
|
throw new api_1.SwapError('[buildTrade]: error building trade', {
|
|
112
116
|
code: api_1.SwapErrorTypes.BUILD_TRADE_FAILED,
|
|
113
117
|
fn: 'buildTrade',
|
|
118
|
+
cause: e,
|
|
114
119
|
});
|
|
115
120
|
}
|
|
116
121
|
};
|
|
@@ -17,7 +17,7 @@ const MINIMUM_USD_TRADE_AMOUNT = (0, bignumber_1.bn)(1);
|
|
|
17
17
|
const getThorTradeQuote = async ({ deps, input }) => {
|
|
18
18
|
const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber, chainId, receiveAddress } = input;
|
|
19
19
|
try {
|
|
20
|
-
const { assetReference:
|
|
20
|
+
const { assetReference: sellAssetReference } = (0, caip_1.fromAssetId)(sellAsset.assetId);
|
|
21
21
|
const sellAdapter = deps.adapterManager.get(chainId);
|
|
22
22
|
if (!sellAdapter)
|
|
23
23
|
throw new api_1.SwapError(`[getThorTradeQuote] - No chain adapter found for ${chainId}.`, {
|
|
@@ -62,7 +62,7 @@ const getThorTradeQuote = async ({ deps, input }) => {
|
|
|
62
62
|
});
|
|
63
63
|
const feeData = await (0, getEthTxFees_1.getEthTxFees)({
|
|
64
64
|
adapterManager: deps.adapterManager,
|
|
65
|
-
sellAssetReference
|
|
65
|
+
sellAssetReference,
|
|
66
66
|
tradeFee,
|
|
67
67
|
});
|
|
68
68
|
return {
|
|
@@ -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
|
|
37
|
-
throw new api_1.SwapError(`[
|
|
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: '
|
|
40
|
-
details: {
|
|
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 (
|
|
46
|
-
throw new api_1.SwapError(`[
|
|
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: '
|
|
49
|
-
details: { buyPoolId
|
|
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,
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
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;
|
|
@@ -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
|
|
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,
|
package/package.json
CHANGED