@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.
- package/dist/adapters.d.ts +2 -0
- package/dist/adapters.js +94 -0
- package/dist/api.d.ts +3 -3
- package/dist/swappercli.js +83 -52
- package/dist/swappers/cow/cowBuildTrade/cowBuildTrade.js +2 -2
- package/dist/swappers/cow/getCowSwapTradeQuote/getCowSwapTradeQuote.js +2 -2
- package/dist/swappers/osmosis/OsmosisSwapper.js +7 -13
- package/dist/swappers/thorchain/ThorchainSwapper.js +6 -1
- package/dist/swappers/thorchain/buildThorTrade/buildThorTrade.js +7 -5
- package/dist/swappers/thorchain/getThorTradeQuote/getTradeQuote.js +7 -4
- package/dist/swappers/thorchain/thorTradeApprovalNeeded/thorTradeApprovalNeeded.js +1 -3
- 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/helpers/helpers.js +1 -2
- package/dist/swappers/utils/test-data/setupSwapQuote.d.ts +1 -1
- package/dist/swappers/utils/test-data/setupSwapQuote.js +3 -3
- package/dist/swappers/zrx/getZrxTradeQuote/getZrxTradeQuote.js +2 -2
- package/dist/swappers/zrx/utils/test-data/setupZrxSwapQuote.d.ts +5 -1
- package/dist/swappers/zrx/utils/test-data/setupZrxSwapQuote.js +1 -1
- package/dist/swappers/zrx/zrxApprovalNeeded/zrxApprovalNeeded.js +1 -3
- package/dist/swappers/zrx/zrxBuildTrade/zrxBuildTrade.js +2 -2
- package/dist/swappers/zrx/zrxExecuteTrade/zrxExecuteTrade.js +1 -4
- 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
|
@@ -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
|
-
|
|
114
|
+
bip44Params: BIP44Params;
|
|
115
115
|
}
|
|
116
116
|
export interface TradeQuote<C extends ChainId> extends TradeBase<C> {
|
|
117
117
|
allowanceContract: string;
|
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,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 = {
|
|
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
|
-
sellAssetAccountNumber: 0,
|
|
117
142
|
sendMax: false,
|
|
118
|
-
|
|
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:
|
|
161
|
+
chainId: sellAsset.chainId,
|
|
133
162
|
wallet,
|
|
134
163
|
buyAsset,
|
|
135
164
|
sendMax: false,
|
|
136
165
|
sellAmount: sellAmountBase,
|
|
137
166
|
sellAsset,
|
|
138
|
-
|
|
139
|
-
|
|
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
|
|
142
|
-
console.info('broadcast tx with id: ',
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
?
|
|
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,
|
|
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
|
|
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,
|
|
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:
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
20
|
+
bip44Params: {
|
|
21
|
+
purpose: number;
|
|
22
|
+
coinType: number;
|
|
23
|
+
accountNumber: number;
|
|
24
|
+
};
|
|
21
25
|
txData: string;
|
|
22
26
|
depositAddress: string;
|
|
23
27
|
receiveAddress: string;
|
|
@@ -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
|
|
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,
|
|
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
|
-
|
|
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