@shapeshiftoss/swapper 8.2.0 → 8.4.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/api.d.ts +2 -1
- package/dist/swappercli.js +5 -2
- package/dist/swappers/thorchain/ThorchainSwapper.js +2 -0
- package/dist/swappers/thorchain/getThorTradeQuote/getTradeQuote.d.ts +6 -2
- package/dist/swappers/thorchain/getThorTradeQuote/getTradeQuote.js +77 -47
- package/dist/swappers/thorchain/thorTradeApproveInfinite/thorTradeApproveInfinite.js +17 -6
- package/dist/swappers/thorchain/utils/bitcoin/utils/getThorTxData.d.ts +22 -0
- package/dist/swappers/thorchain/utils/bitcoin/utils/getThorTxData.js +54 -0
- package/dist/swappers/thorchain/utils/estimateTradeFee/estimateTradeFee.js +16 -3
- package/dist/swappers/thorchain/utils/ethereum/makeTradeTx.js +1 -2
- package/dist/swappers/thorchain/utils/ethereum/utils/getThorTxData.d.ts +7 -4
- package/dist/swappers/thorchain/utils/ethereum/utils/getThorTxData.js +7 -5
- package/dist/swappers/thorchain/utils/getPriceRatio/getPriceRatio.js +1 -1
- package/dist/swappers/utils/test-data/setupSwapQuote.d.ts +2 -1
- package/dist/swappers/utils/test-data/setupSwapQuote.js +5 -2
- package/dist/swappers/zrx/getZrxTradeQuote/getZrxTradeQuote.js +15 -12
- package/dist/swappers/zrx/zrxApproveInfinite/zrxApproveInfinite.js +16 -5
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -63,7 +63,8 @@ declare type CommonTradeInput = {
|
|
|
63
63
|
sellAmount: string;
|
|
64
64
|
sendMax: boolean;
|
|
65
65
|
sellAssetAccountNumber: number;
|
|
66
|
-
wallet
|
|
66
|
+
wallet: HDWallet;
|
|
67
|
+
receiveAddress: string;
|
|
67
68
|
};
|
|
68
69
|
export declare type EvmSupportedChainIds = KnownChainIds.EthereumMainnet | KnownChainIds.AvalancheMainnet;
|
|
69
70
|
export declare type EvmSupportedChainAdapters = ethereum.ChainAdapter | avalanche.ChainAdapter;
|
package/dist/swappercli.js
CHANGED
|
@@ -114,7 +114,9 @@ const main = async () => {
|
|
|
114
114
|
buyAsset,
|
|
115
115
|
sellAmount: sellAmountBase,
|
|
116
116
|
sellAssetAccountNumber: 0,
|
|
117
|
-
sendMax: false
|
|
117
|
+
sendMax: false,
|
|
118
|
+
receiveAddress: '0xc770eefad204b5180df6a14ee197d99d808ee52d',
|
|
119
|
+
wallet
|
|
118
120
|
});
|
|
119
121
|
}
|
|
120
122
|
catch (e) {
|
|
@@ -135,7 +137,8 @@ const main = async () => {
|
|
|
135
137
|
sellAmount: sellAmountBase,
|
|
136
138
|
sellAsset,
|
|
137
139
|
sellAssetAccountNumber: 0,
|
|
138
|
-
buyAssetAccountNumber: 0
|
|
140
|
+
buyAssetAccountNumber: 0,
|
|
141
|
+
receiveAddress: '0xc770eefad204b5180df6a14ee197d99d808ee52d'
|
|
139
142
|
});
|
|
140
143
|
const txid = await swapper.executeTrade({ trade, wallet });
|
|
141
144
|
console.info('broadcast tx with id: ', txid);
|
|
@@ -52,6 +52,8 @@ class ThorchainSwapper {
|
|
|
52
52
|
}
|
|
53
53
|
filterBuyAssetsBySellAssetId(args) {
|
|
54
54
|
const { assetIds = [], sellAssetId } = args;
|
|
55
|
+
if (!this.supportedAssetIds.includes(sellAssetId))
|
|
56
|
+
return [];
|
|
55
57
|
return assetIds.filter((assetId) => this.supportedAssetIds.includes(assetId) && assetId !== sellAssetId);
|
|
56
58
|
}
|
|
57
59
|
filterAssetIdsBySellable() {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { ChainId } from '@shapeshiftoss/caip';
|
|
2
2
|
import { GetTradeQuoteInput, TradeQuote } from '../../../api';
|
|
3
3
|
import { ThorchainSwapperDeps } from '../types';
|
|
4
|
-
|
|
4
|
+
declare type GetThorTradeQuoteInput = {
|
|
5
5
|
deps: ThorchainSwapperDeps;
|
|
6
6
|
input: GetTradeQuoteInput;
|
|
7
|
-
}
|
|
7
|
+
};
|
|
8
|
+
declare type GetThorTradeQuoteReturn = Promise<TradeQuote<ChainId>>;
|
|
9
|
+
declare type GetThorTradeQuote = (args: GetThorTradeQuoteInput) => GetThorTradeQuoteReturn;
|
|
10
|
+
export declare const getThorTradeQuote: GetThorTradeQuote;
|
|
11
|
+
export {};
|
|
@@ -2,61 +2,32 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getThorTradeQuote = void 0;
|
|
4
4
|
const caip_1 = require("@shapeshiftoss/caip");
|
|
5
|
+
const types_1 = require("@shapeshiftoss/types");
|
|
5
6
|
const api_1 = require("../../../api");
|
|
6
7
|
const bignumber_1 = require("../../utils/bignumber");
|
|
7
8
|
const constants_1 = require("../../utils/constants");
|
|
8
9
|
const helpers_1 = require("../../utils/helpers/helpers");
|
|
10
|
+
const getThorTxData_1 = require("../utils/bitcoin/utils/getThorTxData");
|
|
9
11
|
const constants_2 = require("../utils/constants");
|
|
10
|
-
const
|
|
12
|
+
const estimateTradeFee_1 = require("../utils/estimateTradeFee/estimateTradeFee");
|
|
13
|
+
const getThorTxData_2 = require("../utils/ethereum/utils/getThorTxData");
|
|
11
14
|
const getPriceRatio_1 = require("../utils/getPriceRatio/getPriceRatio");
|
|
15
|
+
const getBtcTxFees_1 = require("../utils/txFeeHelpers/btcTxFees/getBtcTxFees");
|
|
12
16
|
const getEthTxFees_1 = require("../utils/txFeeHelpers/ethTxFees/getEthTxFees");
|
|
13
17
|
const getThorTradeQuote = async ({ deps, input }) => {
|
|
14
|
-
const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber, wallet } = input;
|
|
18
|
+
const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber, wallet, chainId, receiveAddress } = input;
|
|
15
19
|
if (!wallet)
|
|
16
20
|
throw new api_1.SwapError('[getTradeQuote] - wallet is required', {
|
|
17
21
|
code: api_1.SwapErrorTypes.VALIDATION_FAILED
|
|
18
22
|
});
|
|
19
23
|
try {
|
|
20
|
-
const { assetReference: sellAssetErc20Address
|
|
21
|
-
const
|
|
22
|
-
const sellAssetChainId = (0, caip_1.toChainId)({ chainReference, chainNamespace });
|
|
23
|
-
const adapter = deps.adapterManager.get(sellAssetChainId);
|
|
24
|
+
const { assetReference: sellAssetErc20Address } = (0, caip_1.fromAssetId)(sellAsset.assetId);
|
|
25
|
+
const adapter = deps.adapterManager.get(chainId);
|
|
24
26
|
if (!adapter)
|
|
25
|
-
throw new api_1.SwapError(`[getThorTradeQuote] - No chain adapter found for ${
|
|
27
|
+
throw new api_1.SwapError(`[getThorTradeQuote] - No chain adapter found for ${chainId}.`, {
|
|
26
28
|
code: api_1.SwapErrorTypes.UNSUPPORTED_CHAIN,
|
|
27
|
-
details: {
|
|
29
|
+
details: { chainId }
|
|
28
30
|
});
|
|
29
|
-
const bip44Params = adapter.buildBIP44Params({ accountNumber: Number(sellAssetAccountNumber) });
|
|
30
|
-
const receiveAddress = await adapter.getAddress({ wallet, bip44Params });
|
|
31
|
-
const { data, router } = await (0, getThorTxData_1.getThorTxInfo)({
|
|
32
|
-
deps,
|
|
33
|
-
sellAsset,
|
|
34
|
-
buyAsset,
|
|
35
|
-
sellAmount,
|
|
36
|
-
slippageTolerance: constants_1.DEFAULT_SLIPPAGE,
|
|
37
|
-
destinationAddress: receiveAddress,
|
|
38
|
-
isErc20Trade
|
|
39
|
-
});
|
|
40
|
-
const feeData = await (async () => {
|
|
41
|
-
switch (sellAssetChainId) {
|
|
42
|
-
case 'eip155:1':
|
|
43
|
-
return await (0, getEthTxFees_1.getEthTxFees)({
|
|
44
|
-
deps,
|
|
45
|
-
data,
|
|
46
|
-
router,
|
|
47
|
-
buyAsset,
|
|
48
|
-
sellAmount,
|
|
49
|
-
adapterManager: deps.adapterManager,
|
|
50
|
-
receiveAddress,
|
|
51
|
-
sellAssetReference: sellAssetErc20Address
|
|
52
|
-
});
|
|
53
|
-
default:
|
|
54
|
-
throw new api_1.SwapError('[getThorTradeQuote] - Asset chainId is not supported.', {
|
|
55
|
-
code: api_1.SwapErrorTypes.UNSUPPORTED_CHAIN,
|
|
56
|
-
details: { sellAssetChainId }
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
})();
|
|
60
31
|
const sellAssetId = sellAsset.assetId;
|
|
61
32
|
const buyAssetId = buyAsset.assetId;
|
|
62
33
|
const feeAssetId = (0, caip_1.getFeeAssetIdFromAssetId)(buyAssetId);
|
|
@@ -65,26 +36,85 @@ const getThorTradeQuote = async ({ deps, input }) => {
|
|
|
65
36
|
code: api_1.SwapErrorTypes.VALIDATION_FAILED,
|
|
66
37
|
details: { buyAssetId }
|
|
67
38
|
});
|
|
68
|
-
const feeAssetRatio = await (0, getPriceRatio_1.getPriceRatio)(deps, { sellAssetId, buyAssetId: feeAssetId });
|
|
69
39
|
const priceRatio = await (0, getPriceRatio_1.getPriceRatio)(deps, { sellAssetId, buyAssetId });
|
|
70
40
|
const rate = (0, bignumber_1.bnOrZero)(1).div(priceRatio).toString();
|
|
71
41
|
const buyAmount = (0, helpers_1.normalizeAmount)((0, bignumber_1.bnOrZero)(sellAmount).times(rate));
|
|
72
|
-
const
|
|
42
|
+
const tradeFee = await (0, estimateTradeFee_1.estimateTradeFee)(deps, buyAsset.assetId);
|
|
43
|
+
const sellAssetTradeFee = (0, bignumber_1.fromBaseUnit)((0, bignumber_1.bnOrZero)(tradeFee).times((0, bignumber_1.bnOrZero)(priceRatio)), buyAsset.precision);
|
|
73
44
|
// padding minimum by 1.5 the trade fee to avoid thorchain "not enough to cover fee" errors.
|
|
74
|
-
const minimum = (0, bignumber_1.
|
|
75
|
-
|
|
45
|
+
const minimum = (0, bignumber_1.bnOrZero)(sellAssetTradeFee).times(1.5).toString();
|
|
46
|
+
const commonQuoteFields = {
|
|
76
47
|
rate,
|
|
77
|
-
minimum,
|
|
78
48
|
maximum: constants_2.MAX_THORCHAIN_TRADE,
|
|
79
|
-
feeData,
|
|
80
49
|
sellAmount,
|
|
81
50
|
buyAmount,
|
|
82
51
|
sources: [{ name: 'thorchain', proportion: '1' }],
|
|
83
|
-
allowanceContract: router,
|
|
84
52
|
buyAsset,
|
|
85
53
|
sellAsset,
|
|
86
|
-
sellAssetAccountNumber
|
|
54
|
+
sellAssetAccountNumber,
|
|
55
|
+
minimum
|
|
87
56
|
};
|
|
57
|
+
switch (chainId) {
|
|
58
|
+
case types_1.KnownChainIds.EthereumMainnet:
|
|
59
|
+
return (async () => {
|
|
60
|
+
const { data, router } = await (0, getThorTxData_2.getThorTxInfo)({
|
|
61
|
+
deps,
|
|
62
|
+
sellAsset,
|
|
63
|
+
buyAsset,
|
|
64
|
+
sellAmount,
|
|
65
|
+
slippageTolerance: constants_1.DEFAULT_SLIPPAGE,
|
|
66
|
+
destinationAddress: receiveAddress
|
|
67
|
+
});
|
|
68
|
+
const feeData = await (0, getEthTxFees_1.getEthTxFees)({
|
|
69
|
+
deps,
|
|
70
|
+
data,
|
|
71
|
+
router,
|
|
72
|
+
buyAsset,
|
|
73
|
+
sellAmount,
|
|
74
|
+
adapterManager: deps.adapterManager,
|
|
75
|
+
receiveAddress,
|
|
76
|
+
sellAssetReference: sellAssetErc20Address
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
...commonQuoteFields,
|
|
80
|
+
allowanceContract: router,
|
|
81
|
+
feeData
|
|
82
|
+
};
|
|
83
|
+
})();
|
|
84
|
+
case types_1.KnownChainIds.BitcoinMainnet:
|
|
85
|
+
return (async () => {
|
|
86
|
+
const { vault, opReturnData, pubkey } = await (0, getThorTxData_1.getThorTxInfo)({
|
|
87
|
+
deps,
|
|
88
|
+
sellAsset,
|
|
89
|
+
buyAsset,
|
|
90
|
+
sellAmount,
|
|
91
|
+
slippageTolerance: constants_1.DEFAULT_SLIPPAGE,
|
|
92
|
+
destinationAddress: receiveAddress,
|
|
93
|
+
wallet,
|
|
94
|
+
bip44Params: input.bip44Params,
|
|
95
|
+
accountType: input.accountType
|
|
96
|
+
});
|
|
97
|
+
const feeData = await (0, getBtcTxFees_1.getBtcTxFees)({
|
|
98
|
+
deps,
|
|
99
|
+
buyAsset,
|
|
100
|
+
sellAmount,
|
|
101
|
+
vault,
|
|
102
|
+
opReturnData,
|
|
103
|
+
pubkey,
|
|
104
|
+
adapterManager: deps.adapterManager
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
...commonQuoteFields,
|
|
108
|
+
allowanceContract: '0x0',
|
|
109
|
+
feeData
|
|
110
|
+
};
|
|
111
|
+
})();
|
|
112
|
+
default:
|
|
113
|
+
throw new api_1.SwapError('[getThorTradeQuote] - Asset chainId is not supported.', {
|
|
114
|
+
code: api_1.SwapErrorTypes.UNSUPPORTED_CHAIN,
|
|
115
|
+
details: { chainId }
|
|
116
|
+
});
|
|
117
|
+
}
|
|
88
118
|
}
|
|
89
119
|
catch (e) {
|
|
90
120
|
if (e instanceof api_1.SwapError)
|
|
@@ -4,13 +4,27 @@ exports.thorTradeApproveInfinite = void 0;
|
|
|
4
4
|
const types_1 = require("@shapeshiftoss/types");
|
|
5
5
|
const api_1 = require("../../../api");
|
|
6
6
|
const erc20_abi_1 = require("../../utils/abi/erc20-abi");
|
|
7
|
+
const constants_1 = require("../../utils/constants");
|
|
7
8
|
const helpers_1 = require("../../utils/helpers/helpers");
|
|
8
|
-
const
|
|
9
|
+
const constants_2 = require("../utils/constants");
|
|
9
10
|
const thorTradeApproveInfinite = async ({ deps, input }) => {
|
|
10
11
|
try {
|
|
11
12
|
const { adapterManager, web3 } = deps;
|
|
12
13
|
const { quote, wallet } = input;
|
|
13
|
-
const
|
|
14
|
+
const approvalQuote = {
|
|
15
|
+
...quote,
|
|
16
|
+
sellAmount: constants_2.MAX_ALLOWANCE,
|
|
17
|
+
feeData: {
|
|
18
|
+
...quote.feeData,
|
|
19
|
+
chainSpecific: {
|
|
20
|
+
...quote.feeData.chainSpecific,
|
|
21
|
+
// Thor approvals are cheaper than trades, but we don't have dynamic quote data for them.
|
|
22
|
+
// Instead, we use a hardcoded gasLimit estimate in place of the estimatedGas in the Thor quote response.
|
|
23
|
+
estimatedGas: constants_1.APPROVAL_GAS_LIMIT
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const sellAssetChainId = approvalQuote.sellAsset.chainId;
|
|
14
28
|
const adapter = adapterManager.get(types_1.KnownChainIds.EthereumMainnet);
|
|
15
29
|
if (!adapter)
|
|
16
30
|
throw new api_1.SwapError(`[thorTradeApproveInfinite] - No chain adapter found for ${sellAssetChainId}.`, {
|
|
@@ -18,10 +32,7 @@ const thorTradeApproveInfinite = async ({ deps, input }) => {
|
|
|
18
32
|
details: { sellAssetChainId }
|
|
19
33
|
});
|
|
20
34
|
const allowanceGrantRequired = await (0, helpers_1.grantAllowance)({
|
|
21
|
-
quote:
|
|
22
|
-
...quote,
|
|
23
|
-
sellAmount: constants_1.MAX_ALLOWANCE
|
|
24
|
-
},
|
|
35
|
+
quote: approvalQuote,
|
|
25
36
|
wallet,
|
|
26
37
|
adapter,
|
|
27
38
|
erc20Abi: erc20_abi_1.erc20Abi,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { HDWallet } from '@shapeshiftoss/hdwallet-core';
|
|
2
|
+
import { Asset, BIP44Params, UtxoAccountType } from '@shapeshiftoss/types';
|
|
3
|
+
import { ThorchainSwapperDeps } from '../../../types';
|
|
4
|
+
declare type GetBtcThorTxInfoArgs = {
|
|
5
|
+
deps: ThorchainSwapperDeps;
|
|
6
|
+
sellAsset: Asset;
|
|
7
|
+
buyAsset: Asset;
|
|
8
|
+
sellAmount: string;
|
|
9
|
+
slippageTolerance: string;
|
|
10
|
+
destinationAddress: string;
|
|
11
|
+
wallet: HDWallet;
|
|
12
|
+
bip44Params: BIP44Params;
|
|
13
|
+
accountType: UtxoAccountType;
|
|
14
|
+
};
|
|
15
|
+
declare type GetBtcThorTxInfoReturn = Promise<{
|
|
16
|
+
opReturnData: string;
|
|
17
|
+
vault: string;
|
|
18
|
+
pubkey: string;
|
|
19
|
+
}>;
|
|
20
|
+
declare type GetBtcThorTxInfo = (args: GetBtcThorTxInfoArgs) => GetBtcThorTxInfoReturn;
|
|
21
|
+
export declare const getThorTxInfo: GetBtcThorTxInfo;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getThorTxInfo = void 0;
|
|
4
|
+
const caip_1 = require("@shapeshiftoss/caip");
|
|
5
|
+
const api_1 = require("../../../../../api");
|
|
6
|
+
const bignumber_1 = require("../../../../utils/bignumber");
|
|
7
|
+
const getPriceRatio_1 = require("../../getPriceRatio/getPriceRatio");
|
|
8
|
+
const makeSwapMemo_1 = require("../../makeSwapMemo/makeSwapMemo");
|
|
9
|
+
const thorService_1 = require("../../thorService");
|
|
10
|
+
const getThorTxInfo = async ({ deps, sellAsset, buyAsset, sellAmount, slippageTolerance, destinationAddress, wallet, bip44Params, accountType }) => {
|
|
11
|
+
try {
|
|
12
|
+
const { data: inboundAddresses } = await thorService_1.thorService.get(`${deps.midgardUrl}/thorchain/inbound_addresses`);
|
|
13
|
+
const btcInboundAddresses = inboundAddresses.find((inbound) => inbound.chain === 'BTC');
|
|
14
|
+
const vault = btcInboundAddresses === null || btcInboundAddresses === void 0 ? void 0 : btcInboundAddresses.address;
|
|
15
|
+
if (!vault)
|
|
16
|
+
throw new api_1.SwapError(`[getThorTxInfo]: vault not found for BTC`, {
|
|
17
|
+
code: api_1.SwapErrorTypes.RESPONSE_ERROR,
|
|
18
|
+
details: { inboundAddresses }
|
|
19
|
+
});
|
|
20
|
+
const priceRatio = await (0, getPriceRatio_1.getPriceRatio)(deps, {
|
|
21
|
+
buyAssetId: buyAsset.assetId,
|
|
22
|
+
sellAssetId: sellAsset.assetId
|
|
23
|
+
});
|
|
24
|
+
const expectedBuyAmount = (0, bignumber_1.toBaseUnit)((0, bignumber_1.fromBaseUnit)((0, bignumber_1.bnOrZero)(sellAmount).dividedBy(priceRatio), sellAsset.precision), buyAsset.precision);
|
|
25
|
+
const isValidSlippageRange = (0, bignumber_1.bnOrZero)(slippageTolerance).gte(0) && (0, bignumber_1.bnOrZero)(slippageTolerance).lte(1);
|
|
26
|
+
if ((0, bignumber_1.bnOrZero)(expectedBuyAmount).lt(0) || !isValidSlippageRange)
|
|
27
|
+
throw new api_1.SwapError('[getThorTxInfo]: bad expected buy amount or bad slippage tolerance', {
|
|
28
|
+
code: api_1.SwapErrorTypes.BUILD_TRADE_FAILED,
|
|
29
|
+
details: { expectedBuyAmount, slippageTolerance }
|
|
30
|
+
});
|
|
31
|
+
const limit = (0, bignumber_1.bnOrZero)(expectedBuyAmount)
|
|
32
|
+
.times((0, bignumber_1.bn)(1).minus(slippageTolerance))
|
|
33
|
+
.decimalPlaces(0)
|
|
34
|
+
.toString();
|
|
35
|
+
const memo = (0, makeSwapMemo_1.makeSwapMemo)({
|
|
36
|
+
buyAssetId: buyAsset.assetId,
|
|
37
|
+
destinationAddress,
|
|
38
|
+
limit
|
|
39
|
+
});
|
|
40
|
+
const adapter = deps.adapterManager.get(caip_1.btcChainId);
|
|
41
|
+
const pubkey = await adapter.getPublicKey(wallet, bip44Params, accountType);
|
|
42
|
+
return {
|
|
43
|
+
opReturnData: memo,
|
|
44
|
+
vault,
|
|
45
|
+
pubkey: pubkey.xpub
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
if (e instanceof api_1.SwapError)
|
|
50
|
+
throw e;
|
|
51
|
+
throw new api_1.SwapError('[getThorTxInfo]', { cause: e, code: api_1.SwapErrorTypes.TRADE_QUOTE_FAILED });
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
exports.getThorTxInfo = getThorTxInfo;
|
|
@@ -4,6 +4,7 @@ exports.estimateTradeFee = 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 getPriceRatio_1 = require("../getPriceRatio/getPriceRatio");
|
|
7
8
|
const thorService_1 = require("../thorService");
|
|
8
9
|
const gweiGasPrecision = 9;
|
|
9
10
|
// https://docs.thorchain.org/how-it-works/fees#outbound-fee
|
|
@@ -31,15 +32,27 @@ const estimateTradeFee = async (deps, buyAssetId) => {
|
|
|
31
32
|
});
|
|
32
33
|
const gasRate = inboundInfo.gas_rate;
|
|
33
34
|
const { chainId, assetNamespace } = (0, caip_1.fromAssetId)(buyAssetId);
|
|
35
|
+
const feeAssetId = (0, caip_1.getFeeAssetIdFromAssetId)(buyAssetId);
|
|
36
|
+
if (!feeAssetId)
|
|
37
|
+
throw new api_1.SwapError('[estimateTradeFee] - no fee assetId', {
|
|
38
|
+
code: api_1.SwapErrorTypes.VALIDATION_FAILED,
|
|
39
|
+
details: { buyAssetId }
|
|
40
|
+
});
|
|
41
|
+
const feeAssetRatio = buyAssetId !== feeAssetId
|
|
42
|
+
? await (0, getPriceRatio_1.getPriceRatio)(deps, {
|
|
43
|
+
sellAssetId: buyAssetId,
|
|
44
|
+
buyAssetId: feeAssetId
|
|
45
|
+
})
|
|
46
|
+
: '1';
|
|
34
47
|
switch (chainId) {
|
|
35
48
|
case 'bip122:000000000019d6689c085ae165831e93':
|
|
36
|
-
return btcEstimate(gasRate);
|
|
49
|
+
return (0, bignumber_1.bnOrZero)(btcEstimate(gasRate)).times(feeAssetRatio).dp(0).toString();
|
|
37
50
|
case 'eip155:1':
|
|
38
51
|
switch (assetNamespace) {
|
|
39
52
|
case 'slip44':
|
|
40
|
-
return ethEstimate(gasRate);
|
|
53
|
+
return (0, bignumber_1.bnOrZero)(ethEstimate(gasRate)).times(feeAssetRatio).dp(0).toString();
|
|
41
54
|
case 'erc20':
|
|
42
|
-
return erc20Estimate(gasRate);
|
|
55
|
+
return (0, bignumber_1.bnOrZero)(erc20Estimate(gasRate)).times(feeAssetRatio).dp(0).toString();
|
|
43
56
|
default:
|
|
44
57
|
throw new api_1.SwapError('[estimateTradeFee] - unsupported asset namespace', {
|
|
45
58
|
code: api_1.SwapErrorTypes.VALIDATION_FAILED,
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { Asset } from '@shapeshiftoss/types';
|
|
2
2
|
import { ThorchainSwapperDeps } from '../../../types';
|
|
3
|
-
|
|
3
|
+
declare type GetBtcThorTxInfoArgs = {
|
|
4
4
|
deps: ThorchainSwapperDeps;
|
|
5
5
|
sellAsset: Asset;
|
|
6
6
|
buyAsset: Asset;
|
|
7
7
|
sellAmount: string;
|
|
8
8
|
slippageTolerance: string;
|
|
9
9
|
destinationAddress: string;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
data:
|
|
10
|
+
};
|
|
11
|
+
declare type GetBtcThorTxInfoReturn = Promise<{
|
|
12
|
+
data: string;
|
|
13
13
|
memo: string;
|
|
14
14
|
router: string;
|
|
15
15
|
}>;
|
|
16
|
+
declare type GetBtcThorTxInfo = (args: GetBtcThorTxInfoArgs) => GetBtcThorTxInfoReturn;
|
|
17
|
+
export declare const getThorTxInfo: GetBtcThorTxInfo;
|
|
18
|
+
export {};
|
|
@@ -8,9 +8,10 @@ const getPriceRatio_1 = require("../../getPriceRatio/getPriceRatio");
|
|
|
8
8
|
const makeSwapMemo_1 = require("../../makeSwapMemo/makeSwapMemo");
|
|
9
9
|
const thorService_1 = require("../../thorService");
|
|
10
10
|
const routerCalldata_1 = require("../routerCalldata");
|
|
11
|
-
const getThorTxInfo = async ({ deps, sellAsset, buyAsset, sellAmount, slippageTolerance, destinationAddress
|
|
11
|
+
const getThorTxInfo = async ({ deps, sellAsset, buyAsset, sellAmount, slippageTolerance, destinationAddress }) => {
|
|
12
12
|
try {
|
|
13
|
-
const { assetReference } = (0, caip_1.fromAssetId)(sellAsset.assetId);
|
|
13
|
+
const { assetReference, assetNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
|
|
14
|
+
const isErc20Trade = assetNamespace === 'erc20';
|
|
14
15
|
const { data: inboundAddresses } = await thorService_1.thorService.get(`${deps.midgardUrl}/thorchain/inbound_addresses`);
|
|
15
16
|
const ethInboundAddresses = inboundAddresses.find((inbound) => inbound.chain === 'ETH');
|
|
16
17
|
const vault = ethInboundAddresses === null || ethInboundAddresses === void 0 ? void 0 : ethInboundAddresses.address;
|
|
@@ -25,10 +26,11 @@ const getThorTxInfo = async ({ deps, sellAsset, buyAsset, sellAmount, slippageTo
|
|
|
25
26
|
sellAssetId: sellAsset.assetId
|
|
26
27
|
});
|
|
27
28
|
const expectedBuyAmount = (0, bignumber_1.toBaseUnit)((0, bignumber_1.fromBaseUnit)((0, bignumber_1.bnOrZero)(sellAmount).dividedBy(priceRatio), sellAsset.precision), buyAsset.precision);
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
const isValidSlippageRange = (0, bignumber_1.bnOrZero)(slippageTolerance).gte(0) && (0, bignumber_1.bnOrZero)(slippageTolerance).lte(1);
|
|
30
|
+
if ((0, bignumber_1.bnOrZero)(expectedBuyAmount).lt(0) || !isValidSlippageRange)
|
|
30
31
|
throw new api_1.SwapError('[makeTradeTx]: bad expected buy amount or bad slippage tolerance', {
|
|
31
|
-
code: api_1.SwapErrorTypes.BUILD_TRADE_FAILED
|
|
32
|
+
code: api_1.SwapErrorTypes.BUILD_TRADE_FAILED,
|
|
33
|
+
details: { expectedBuyAmount, slippageTolerance }
|
|
32
34
|
});
|
|
33
35
|
const limit = (0, bignumber_1.bnOrZero)(expectedBuyAmount)
|
|
34
36
|
.times((0, bignumber_1.bn)(1).minus(slippageTolerance))
|
|
@@ -29,7 +29,7 @@ const getPriceRatio = async (deps, input) => {
|
|
|
29
29
|
catch (e) {
|
|
30
30
|
if (e instanceof api_1.SwapError)
|
|
31
31
|
throw e;
|
|
32
|
-
throw new api_1.SwapError('[
|
|
32
|
+
throw new api_1.SwapError('[getPriceRatio]: Thorchain getPriceRatio failed', {
|
|
33
33
|
code: api_1.SwapErrorTypes.PRICE_RATIO_FAILED,
|
|
34
34
|
cause: e
|
|
35
35
|
});
|
|
@@ -14,7 +14,8 @@ export declare const setupBuildTrade: () => {
|
|
|
14
14
|
sellAmount: string;
|
|
15
15
|
sendMax: boolean;
|
|
16
16
|
sellAssetAccountNumber: number;
|
|
17
|
-
wallet
|
|
17
|
+
wallet: HDWallet;
|
|
18
|
+
receiveAddress: string;
|
|
18
19
|
} & {
|
|
19
20
|
chainId: import("../../../api").EvmSupportedChainIds;
|
|
20
21
|
} & {
|
|
@@ -25,7 +25,9 @@ const setupQuote = () => {
|
|
|
25
25
|
sellAsset,
|
|
26
26
|
buyAsset,
|
|
27
27
|
sellAssetAccountNumber: 0,
|
|
28
|
-
sendMax: false
|
|
28
|
+
sendMax: false,
|
|
29
|
+
receiveAddress: '0xc770eefad204b5180df6a14ee197d99d808ee52d',
|
|
30
|
+
wallet: {}
|
|
29
31
|
};
|
|
30
32
|
return { quoteInput, tradeQuote, buyAsset, sellAsset };
|
|
31
33
|
};
|
|
@@ -41,7 +43,8 @@ const setupBuildTrade = () => {
|
|
|
41
43
|
sellAssetAccountNumber: 0,
|
|
42
44
|
buyAssetAccountNumber: 0,
|
|
43
45
|
sellAsset,
|
|
44
|
-
wallet: {}
|
|
46
|
+
wallet: {},
|
|
47
|
+
receiveAddress: ''
|
|
45
48
|
};
|
|
46
49
|
return { buildTradeInput, buyAsset, sellAsset };
|
|
47
50
|
};
|
|
@@ -11,7 +11,6 @@ const constants_2 = require("../utils/constants");
|
|
|
11
11
|
const helpers_2 = require("../utils/helpers/helpers");
|
|
12
12
|
const zrxService_1 = require("../utils/zrxService");
|
|
13
13
|
async function getZrxTradeQuote(input) {
|
|
14
|
-
var _a;
|
|
15
14
|
try {
|
|
16
15
|
const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber } = input;
|
|
17
16
|
if (buyAsset.chainId !== input.chainId || sellAsset.chainId !== input.chainId) {
|
|
@@ -46,27 +45,31 @@ async function getZrxTradeQuote(input) {
|
|
|
46
45
|
sellAmount: normalizedSellAmount
|
|
47
46
|
}
|
|
48
47
|
});
|
|
49
|
-
const { data } = quoteResponse;
|
|
50
|
-
const estimatedGas = (0, bignumber_1.bnOrZero)(
|
|
51
|
-
const rate = useSellAmount ?
|
|
48
|
+
const { data: { estimatedGas: estimatedGasResponse, gasPrice, price, sellAmount: sellAmountResponse, buyAmount, sources, allowanceTarget } } = quoteResponse;
|
|
49
|
+
const estimatedGas = (0, bignumber_1.bnOrZero)(estimatedGasResponse).times(1.5);
|
|
50
|
+
const rate = useSellAmount ? price : (0, bignumber_1.bn)(1).div(price).toString();
|
|
51
|
+
const fee = (0, bignumber_1.bnOrZero)(estimatedGas).multipliedBy((0, bignumber_1.bnOrZero)(gasPrice)).toString();
|
|
52
|
+
// 0x approvals are cheaper than trades, but we don't have dynamic quote data for them.
|
|
53
|
+
// Instead, we use a hardcoded gasLimit estimate in place of the estimatedGas in the 0x quote response.
|
|
54
|
+
const approvalFee = sellAssetErc20Address &&
|
|
55
|
+
(0, bignumber_1.bnOrZero)(constants_1.APPROVAL_GAS_LIMIT).multipliedBy((0, bignumber_1.bnOrZero)(gasPrice)).toString();
|
|
52
56
|
return {
|
|
53
57
|
rate,
|
|
54
58
|
minimum,
|
|
55
59
|
maximum,
|
|
56
60
|
feeData: {
|
|
57
|
-
fee
|
|
61
|
+
fee,
|
|
58
62
|
chainSpecific: {
|
|
59
63
|
estimatedGas: estimatedGas.toString(),
|
|
60
|
-
gasPrice
|
|
61
|
-
approvalFee
|
|
62
|
-
(0, bignumber_1.bnOrZero)(constants_1.APPROVAL_GAS_LIMIT).multipliedBy((0, bignumber_1.bnOrZero)(data.gasPrice)).toString()
|
|
64
|
+
gasPrice,
|
|
65
|
+
approvalFee
|
|
63
66
|
},
|
|
64
67
|
tradeFee: '0'
|
|
65
68
|
},
|
|
66
|
-
sellAmount:
|
|
67
|
-
buyAmount
|
|
68
|
-
sources: (
|
|
69
|
-
allowanceContract:
|
|
69
|
+
sellAmount: sellAmountResponse,
|
|
70
|
+
buyAmount,
|
|
71
|
+
sources: (sources === null || sources === void 0 ? void 0 : sources.filter((s) => parseFloat(s.proportion) > 0)) || constants_2.DEFAULT_SOURCE,
|
|
72
|
+
allowanceContract: allowanceTarget,
|
|
70
73
|
buyAsset,
|
|
71
74
|
sellAsset,
|
|
72
75
|
sellAssetAccountNumber
|
|
@@ -3,15 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.zrxApproveInfinite = void 0;
|
|
4
4
|
const api_1 = require("../../../api");
|
|
5
5
|
const erc20_abi_1 = require("../../utils/abi/erc20-abi");
|
|
6
|
+
const constants_1 = require("../../utils/constants");
|
|
6
7
|
const helpers_1 = require("../../utils/helpers/helpers");
|
|
7
|
-
const
|
|
8
|
+
const constants_2 = require("../utils/constants");
|
|
8
9
|
async function zrxApproveInfinite({ adapter, web3 }, { quote, wallet }) {
|
|
9
10
|
try {
|
|
11
|
+
const approvalQuote = {
|
|
12
|
+
...quote,
|
|
13
|
+
sellAmount: constants_2.MAX_ALLOWANCE,
|
|
14
|
+
feeData: {
|
|
15
|
+
...quote.feeData,
|
|
16
|
+
chainSpecific: {
|
|
17
|
+
...quote.feeData.chainSpecific,
|
|
18
|
+
// 0x approvals are cheaper than trades, but we don't have dynamic quote data for them.
|
|
19
|
+
// Instead, we use a hardcoded gasLimit estimate in place of the estimatedGas in the 0x quote response.
|
|
20
|
+
estimatedGas: constants_1.APPROVAL_GAS_LIMIT
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
10
24
|
const allowanceGrantRequired = await (0, helpers_1.grantAllowance)({
|
|
11
|
-
quote:
|
|
12
|
-
...quote,
|
|
13
|
-
sellAmount: constants_1.MAX_ALLOWANCE
|
|
14
|
-
},
|
|
25
|
+
quote: approvalQuote,
|
|
15
26
|
wallet,
|
|
16
27
|
adapter,
|
|
17
28
|
erc20Abi: erc20_abi_1.erc20Abi,
|
package/package.json
CHANGED