@shapeshiftoss/swapper 17.6.9 → 17.6.10
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/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/constants.js +61 -43
- package/dist/cjs/swappers/AcrossSwapper/AcrossSwapper.d.ts +2 -0
- package/dist/cjs/swappers/AcrossSwapper/AcrossSwapper.js +8 -0
- package/dist/cjs/swappers/AcrossSwapper/constant.d.ts +9 -0
- package/dist/cjs/swappers/AcrossSwapper/constant.js +48 -0
- package/dist/cjs/swappers/AcrossSwapper/endpoints.d.ts +2 -0
- package/dist/cjs/swappers/AcrossSwapper/endpoints.js +113 -0
- package/dist/cjs/swappers/AcrossSwapper/getTradeQuote/getTradeQuote.d.ts +3 -0
- package/dist/cjs/swappers/AcrossSwapper/getTradeQuote/getTradeQuote.js +31 -0
- package/dist/cjs/swappers/AcrossSwapper/getTradeRate/getTradeRate.d.ts +3 -0
- package/dist/cjs/swappers/AcrossSwapper/getTradeRate/getTradeRate.js +19 -0
- package/dist/cjs/swappers/AcrossSwapper/index.d.ts +1 -0
- package/dist/cjs/swappers/AcrossSwapper/index.js +5 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/acrossService.d.ts +5 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/acrossService.js +17 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/fetchAcrossTrade.d.ts +19 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/fetchAcrossTrade.js +27 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/getTrade.d.ts +11 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/getTrade.js +335 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/types.d.ts +177 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/types.js +17 -0
- package/dist/cjs/swappers/AvnuSwapper/endpoints.js +42 -14
- package/dist/cjs/swappers/AvnuSwapper/swapperApi/getTradeQuote.js +10 -5
- package/dist/cjs/swappers/AvnuSwapper/swapperApi/getTradeRate.js +8 -4
- package/dist/cjs/swappers/BebopSwapper/utils/helpers/helpers.d.ts +1 -1
- package/dist/cjs/swappers/ButterSwap/ButterSwap.js +1 -0
- package/dist/cjs/swappers/ButterSwap/endpoints.js +56 -0
- package/dist/cjs/swappers/ButterSwap/swapperApi/checkTradeStatus.js +19 -0
- package/dist/cjs/swappers/ButterSwap/swapperApi/getTradeQuote.js +27 -14
- package/dist/cjs/swappers/ButterSwap/swapperApi/getTradeQuote.test.js +1 -0
- package/dist/cjs/swappers/ButterSwap/swapperApi/getTradeRate.js +23 -16
- package/dist/cjs/swappers/ButterSwap/swapperApi/getTradeRate.test.js +2 -0
- package/dist/cjs/swappers/ButterSwap/types.d.ts +1 -0
- package/dist/cjs/swappers/ButterSwap/utils/helpers.js +1 -0
- package/dist/cjs/swappers/ButterSwap/xhr.d.ts +2 -2
- package/dist/cjs/swappers/ButterSwap/xhr.js +7 -2
- package/dist/cjs/swappers/CetusSwapper/endpoints.js +3 -8
- package/dist/cjs/swappers/CetusSwapper/swapperApi/getTradeQuote.js +1 -1
- package/dist/cjs/swappers/CetusSwapper/swapperApi/getTradeRate.js +1 -1
- package/dist/cjs/swappers/ChainflipSwapper/utils/getQuoteOrRate.js +11 -5
- package/dist/cjs/swappers/ChainflipSwapper/utils/helpers.js +8 -2
- package/dist/cjs/swappers/CowSwapper/CowSwapper.js +1 -1
- package/dist/cjs/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.js +1 -1
- package/dist/cjs/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.js +5 -5
- package/dist/cjs/swappers/CowSwapper/getCowSwapTradeRate/getCowSwapTradeRate.js +1 -1
- package/dist/cjs/swappers/CowSwapper/utils/helpers/helpers.js +8 -2
- package/dist/cjs/swappers/NearIntentsSwapper/NearIntentsSwapper.js +1 -0
- package/dist/cjs/swappers/NearIntentsSwapper/endpoints.js +31 -0
- package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.js +36 -1
- package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeRate.js +61 -1
- package/dist/cjs/swappers/NearIntentsSwapper/types.d.ts +1 -1
- package/dist/cjs/swappers/NearIntentsSwapper/types.js +6 -0
- package/dist/cjs/swappers/NearIntentsSwapper/utils/helpers/helpers.js +23 -4
- package/dist/cjs/swappers/PortalsSwapper/getPortalsTradeRate/getPortalsTradeRate.js +8 -3
- package/dist/cjs/swappers/RelaySwapper/constant.js +26 -1
- package/dist/cjs/swappers/RelaySwapper/utils/getRelayDefaultUserAddress.d.ts +1 -1
- package/dist/cjs/swappers/RelaySwapper/utils/getTrade.js +13 -2
- package/dist/cjs/swappers/RelaySwapper/utils/relayTokenToAssetId.js +100 -0
- package/dist/cjs/swappers/RelaySwapper/utils/types.d.ts +15 -0
- package/dist/cjs/swappers/StonfiSwapper/StonfiSwapper.d.ts +2 -0
- package/dist/cjs/swappers/StonfiSwapper/StonfiSwapper.js +8 -0
- package/dist/cjs/swappers/StonfiSwapper/endpoints.d.ts +2 -0
- package/dist/cjs/swappers/StonfiSwapper/endpoints.js +227 -0
- package/dist/cjs/swappers/StonfiSwapper/index.d.ts +4 -0
- package/dist/cjs/swappers/StonfiSwapper/index.js +25 -0
- package/dist/cjs/swappers/StonfiSwapper/swapperApi/getTradeQuote.d.ts +2 -0
- package/dist/cjs/swappers/StonfiSwapper/swapperApi/getTradeQuote.js +119 -0
- package/dist/cjs/swappers/StonfiSwapper/swapperApi/getTradeRate.d.ts +2 -0
- package/dist/cjs/swappers/StonfiSwapper/swapperApi/getTradeRate.js +105 -0
- package/dist/cjs/swappers/StonfiSwapper/types.d.ts +60 -0
- package/dist/cjs/swappers/StonfiSwapper/types.js +5 -0
- package/dist/cjs/swappers/StonfiSwapper/utils/constants.d.ts +5 -0
- package/dist/cjs/swappers/StonfiSwapper/utils/constants.js +8 -0
- package/dist/cjs/swappers/StonfiSwapper/utils/helpers.d.ts +11 -0
- package/dist/cjs/swappers/StonfiSwapper/utils/helpers.js +135 -0
- package/dist/cjs/swappers/StonfiSwapper/utils/omnistonManager.d.ts +5 -0
- package/dist/cjs/swappers/StonfiSwapper/utils/omnistonManager.js +20 -0
- package/dist/cjs/swappers/SunioSwapper/endpoints.js +1 -1
- package/dist/cjs/swappers/SunioSwapper/utils/getQuoteOrRate.js +4 -3
- package/dist/cjs/swappers/ZrxSwapper/utils/helpers/helpers.d.ts +1 -1
- package/dist/cjs/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.js +2 -5
- package/dist/cjs/swappers/utils/helpers/helpers.js +3 -0
- package/dist/cjs/thorchain-utils/getCallDataFromQuote.d.ts +1 -1
- package/dist/cjs/thorchain-utils/getL1RateOrQuote.js +30 -5
- package/dist/cjs/thorchain-utils/getQuote.js +8 -2
- package/dist/cjs/tron-utils/getUnsignedTronTransaction.js +22 -2
- package/dist/cjs/types.d.ts +79 -8
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/utils.d.ts +4 -3
- package/dist/cjs/utils.js +35 -7
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/constants.js +31 -13
- package/dist/esm/swappers/AcrossSwapper/AcrossSwapper.d.ts +2 -0
- package/dist/esm/swappers/AcrossSwapper/AcrossSwapper.js +5 -0
- package/dist/esm/swappers/AcrossSwapper/constant.d.ts +9 -0
- package/dist/esm/swappers/AcrossSwapper/constant.js +42 -0
- package/dist/esm/swappers/AcrossSwapper/endpoints.d.ts +2 -0
- package/dist/esm/swappers/AcrossSwapper/endpoints.js +107 -0
- package/dist/esm/swappers/AcrossSwapper/getTradeQuote/getTradeQuote.d.ts +3 -0
- package/dist/esm/swappers/AcrossSwapper/getTradeQuote/getTradeQuote.js +27 -0
- package/dist/esm/swappers/AcrossSwapper/getTradeRate/getTradeRate.d.ts +3 -0
- package/dist/esm/swappers/AcrossSwapper/getTradeRate/getTradeRate.js +15 -0
- package/dist/esm/swappers/AcrossSwapper/index.d.ts +1 -0
- package/dist/esm/swappers/AcrossSwapper/index.js +1 -0
- package/dist/esm/swappers/AcrossSwapper/utils/acrossService.d.ts +5 -0
- package/dist/esm/swappers/AcrossSwapper/utils/acrossService.js +11 -0
- package/dist/esm/swappers/AcrossSwapper/utils/fetchAcrossTrade.d.ts +19 -0
- package/dist/esm/swappers/AcrossSwapper/utils/fetchAcrossTrade.js +23 -0
- package/dist/esm/swappers/AcrossSwapper/utils/getTrade.d.ts +11 -0
- package/dist/esm/swappers/AcrossSwapper/utils/getTrade.js +328 -0
- package/dist/esm/swappers/AcrossSwapper/utils/types.d.ts +177 -0
- package/dist/esm/swappers/AcrossSwapper/utils/types.js +13 -0
- package/dist/esm/swappers/AvnuSwapper/endpoints.js +43 -15
- package/dist/esm/swappers/AvnuSwapper/swapperApi/getTradeQuote.js +10 -5
- package/dist/esm/swappers/AvnuSwapper/swapperApi/getTradeRate.js +8 -4
- package/dist/esm/swappers/BebopSwapper/utils/helpers/helpers.d.ts +1 -1
- package/dist/esm/swappers/ButterSwap/ButterSwap.js +2 -1
- package/dist/esm/swappers/ButterSwap/endpoints.js +56 -0
- package/dist/esm/swappers/ButterSwap/swapperApi/checkTradeStatus.js +20 -1
- package/dist/esm/swappers/ButterSwap/swapperApi/getTradeQuote.js +29 -16
- package/dist/esm/swappers/ButterSwap/swapperApi/getTradeQuote.test.js +1 -0
- package/dist/esm/swappers/ButterSwap/swapperApi/getTradeRate.js +25 -18
- package/dist/esm/swappers/ButterSwap/swapperApi/getTradeRate.test.js +2 -0
- package/dist/esm/swappers/ButterSwap/types.d.ts +1 -0
- package/dist/esm/swappers/ButterSwap/utils/helpers.js +1 -0
- package/dist/esm/swappers/ButterSwap/xhr.d.ts +2 -2
- package/dist/esm/swappers/ButterSwap/xhr.js +8 -3
- package/dist/esm/swappers/CetusSwapper/endpoints.js +3 -8
- package/dist/esm/swappers/CetusSwapper/swapperApi/getTradeQuote.js +1 -1
- package/dist/esm/swappers/CetusSwapper/swapperApi/getTradeRate.js +1 -1
- package/dist/esm/swappers/ChainflipSwapper/utils/getQuoteOrRate.js +12 -6
- package/dist/esm/swappers/ChainflipSwapper/utils/helpers.js +9 -3
- package/dist/esm/swappers/CowSwapper/CowSwapper.js +1 -1
- package/dist/esm/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.js +1 -1
- package/dist/esm/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.js +5 -5
- package/dist/esm/swappers/CowSwapper/getCowSwapTradeRate/getCowSwapTradeRate.js +1 -1
- package/dist/esm/swappers/CowSwapper/utils/helpers/helpers.js +9 -3
- package/dist/esm/swappers/NearIntentsSwapper/NearIntentsSwapper.js +2 -1
- package/dist/esm/swappers/NearIntentsSwapper/endpoints.js +31 -0
- package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.js +36 -1
- package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeRate.js +61 -1
- package/dist/esm/swappers/NearIntentsSwapper/types.d.ts +1 -1
- package/dist/esm/swappers/NearIntentsSwapper/types.js +6 -0
- package/dist/esm/swappers/NearIntentsSwapper/utils/helpers/helpers.js +23 -4
- package/dist/esm/swappers/PortalsSwapper/getPortalsTradeRate/getPortalsTradeRate.js +8 -3
- package/dist/esm/swappers/RelaySwapper/constant.js +28 -3
- package/dist/esm/swappers/RelaySwapper/utils/getRelayDefaultUserAddress.d.ts +1 -1
- package/dist/esm/swappers/RelaySwapper/utils/getTrade.js +13 -2
- package/dist/esm/swappers/RelaySwapper/utils/relayTokenToAssetId.js +100 -0
- package/dist/esm/swappers/RelaySwapper/utils/types.d.ts +15 -0
- package/dist/esm/swappers/StonfiSwapper/StonfiSwapper.d.ts +2 -0
- package/dist/esm/swappers/StonfiSwapper/StonfiSwapper.js +5 -0
- package/dist/esm/swappers/StonfiSwapper/endpoints.d.ts +2 -0
- package/dist/esm/swappers/StonfiSwapper/endpoints.js +224 -0
- package/dist/esm/swappers/StonfiSwapper/index.d.ts +4 -0
- package/dist/esm/swappers/StonfiSwapper/index.js +4 -0
- package/dist/esm/swappers/StonfiSwapper/swapperApi/getTradeQuote.d.ts +2 -0
- package/dist/esm/swappers/StonfiSwapper/swapperApi/getTradeQuote.js +115 -0
- package/dist/esm/swappers/StonfiSwapper/swapperApi/getTradeRate.d.ts +2 -0
- package/dist/esm/swappers/StonfiSwapper/swapperApi/getTradeRate.js +101 -0
- package/dist/esm/swappers/StonfiSwapper/types.d.ts +60 -0
- package/dist/esm/swappers/StonfiSwapper/types.js +2 -0
- package/dist/esm/swappers/StonfiSwapper/utils/constants.d.ts +5 -0
- package/dist/esm/swappers/StonfiSwapper/utils/constants.js +5 -0
- package/dist/esm/swappers/StonfiSwapper/utils/helpers.d.ts +11 -0
- package/dist/esm/swappers/StonfiSwapper/utils/helpers.js +124 -0
- package/dist/esm/swappers/StonfiSwapper/utils/omnistonManager.d.ts +5 -0
- package/dist/esm/swappers/StonfiSwapper/utils/omnistonManager.js +17 -0
- package/dist/esm/swappers/SunioSwapper/endpoints.js +1 -1
- package/dist/esm/swappers/SunioSwapper/utils/getQuoteOrRate.js +5 -4
- package/dist/esm/swappers/ZrxSwapper/utils/helpers/helpers.d.ts +1 -1
- package/dist/esm/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.js +2 -5
- package/dist/esm/swappers/utils/helpers/helpers.js +4 -1
- package/dist/esm/thorchain-utils/getCallDataFromQuote.d.ts +1 -1
- package/dist/esm/thorchain-utils/getL1RateOrQuote.js +31 -6
- package/dist/esm/thorchain-utils/getQuote.js +9 -3
- package/dist/esm/tron-utils/getUnsignedTronTransaction.js +22 -2
- package/dist/esm/types.d.ts +79 -8
- package/dist/esm/types.js +2 -0
- package/dist/esm/utils.d.ts +4 -3
- package/dist/esm/utils.js +34 -7
- package/package.json +17 -15
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getTrade = void 0;
|
|
7
|
+
const caip_1 = require("@shapeshiftoss/caip");
|
|
8
|
+
const chain_adapters_1 = require("@shapeshiftoss/chain-adapters");
|
|
9
|
+
const utils_1 = require("@shapeshiftoss/utils");
|
|
10
|
+
const monads_1 = require("@sniptt/monads");
|
|
11
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
12
|
+
const axios_1 = __importDefault(require("axios"));
|
|
13
|
+
const viem_1 = require("viem");
|
|
14
|
+
const types_1 = require("../../../types");
|
|
15
|
+
const utils_2 = require("../../../utils");
|
|
16
|
+
const helpers_1 = require("../../utils/helpers/helpers");
|
|
17
|
+
const constant_1 = require("../constant");
|
|
18
|
+
const fetchAcrossTrade_1 = require("./fetchAcrossTrade");
|
|
19
|
+
const types_2 = require("./types");
|
|
20
|
+
const getAcrossAssetAddress = (assetId) => {
|
|
21
|
+
if ((0, helpers_1.isNativeEvmAsset)(assetId))
|
|
22
|
+
return constant_1.DEFAULT_ACROSS_EVM_TOKEN_ADDRESS;
|
|
23
|
+
const { chainId, assetReference } = (0, caip_1.fromAssetId)(assetId);
|
|
24
|
+
if (chainId === caip_1.solanaChainId && !(0, caip_1.isAssetReference)(assetReference))
|
|
25
|
+
return assetReference;
|
|
26
|
+
if (chainId === caip_1.solanaChainId)
|
|
27
|
+
return constant_1.ACROSS_SOLANA_TOKEN_ADDRESS;
|
|
28
|
+
return (0, caip_1.isAssetReference)(assetReference) ? viem_1.zeroAddress : assetReference;
|
|
29
|
+
};
|
|
30
|
+
const getDefaultUserAddress = (chainId) => {
|
|
31
|
+
if (chainId === caip_1.solanaChainId)
|
|
32
|
+
return constant_1.DEFAULT_ACROSS_SOLANA_USER_ADDRESS;
|
|
33
|
+
return constant_1.DEFAULT_ACROSS_EVM_USER_ADDRESS;
|
|
34
|
+
};
|
|
35
|
+
async function getTrade({ input, deps, }) {
|
|
36
|
+
const { sellAsset, buyAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit, affiliateBps } = input;
|
|
37
|
+
if (sellAsset.chainId === buyAsset.chainId) {
|
|
38
|
+
return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
|
|
39
|
+
message: 'Across does not support same-chain swaps',
|
|
40
|
+
code: types_1.TradeQuoteError.UnsupportedTradePair,
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
const sellAcrossChainId = constant_1.chainIdToAcrossChainId[sellAsset.chainId];
|
|
44
|
+
const buyAcrossChainId = constant_1.chainIdToAcrossChainId[buyAsset.chainId];
|
|
45
|
+
if (sellAcrossChainId === undefined) {
|
|
46
|
+
return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
|
|
47
|
+
message: `Sell asset chain '${sellAsset.chainId}' not supported by Across`,
|
|
48
|
+
code: types_1.TradeQuoteError.UnsupportedChain,
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
if (buyAcrossChainId === undefined) {
|
|
52
|
+
return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
|
|
53
|
+
message: `Buy asset chain '${buyAsset.chainId}' not supported by Across`,
|
|
54
|
+
code: types_1.TradeQuoteError.UnsupportedChain,
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
// Across only supports USDC as the bridgeable token on Solana destinations
|
|
58
|
+
if (buyAsset.chainId === caip_1.solanaChainId && buyAsset.assetId !== caip_1.usdcOnSolanaAssetId) {
|
|
59
|
+
return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
|
|
60
|
+
message: 'Across only supports USDC as destination token on Solana',
|
|
61
|
+
code: types_1.TradeQuoteError.UnsupportedTradePair,
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
const depositor = (() => {
|
|
65
|
+
if (input.quoteOrRate === 'rate') {
|
|
66
|
+
if (input.sendAddress)
|
|
67
|
+
return input.sendAddress;
|
|
68
|
+
return getDefaultUserAddress(sellAsset.chainId);
|
|
69
|
+
}
|
|
70
|
+
return input.sendAddress ?? getDefaultUserAddress(sellAsset.chainId);
|
|
71
|
+
})();
|
|
72
|
+
const recipient = (() => {
|
|
73
|
+
if (input.quoteOrRate === 'rate') {
|
|
74
|
+
if (input.receiveAddress)
|
|
75
|
+
return input.receiveAddress;
|
|
76
|
+
return getDefaultUserAddress(buyAsset.chainId);
|
|
77
|
+
}
|
|
78
|
+
return input.receiveAddress;
|
|
79
|
+
})();
|
|
80
|
+
const isSolanaRoute = sellAsset.chainId === caip_1.solanaChainId || buyAsset.chainId === caip_1.solanaChainId;
|
|
81
|
+
const appFee = (() => {
|
|
82
|
+
if (isSolanaRoute)
|
|
83
|
+
return undefined;
|
|
84
|
+
if (!(0, utils_1.isTreasuryChainId)(buyAsset.chainId))
|
|
85
|
+
return undefined;
|
|
86
|
+
const bps = (0, utils_1.bnOrZero)(affiliateBps);
|
|
87
|
+
if (!bps.isFinite() || bps.lte(0))
|
|
88
|
+
return undefined;
|
|
89
|
+
return bps.div(10000).toNumber();
|
|
90
|
+
})();
|
|
91
|
+
const appFeeRecipient = (() => {
|
|
92
|
+
if (appFee === undefined)
|
|
93
|
+
return undefined;
|
|
94
|
+
try {
|
|
95
|
+
return (0, helpers_1.getTreasuryAddressFromChainId)(buyAsset.chainId).toLowerCase();
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
console.error(`[getTrade] Failed to get treasury address for chainId ${buyAsset.chainId}, affiliate fee will not be applied`, e);
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
102
|
+
const slippage = input.slippageTolerancePercentageDecimal ?? 'auto';
|
|
103
|
+
const integratorId = deps.config.VITE_ACROSS_INTEGRATOR_ID || undefined;
|
|
104
|
+
const maybeQuote = await (0, fetchAcrossTrade_1.fetchAcrossTrade)({
|
|
105
|
+
tradeType: 'exactInput',
|
|
106
|
+
amount: sellAmountIncludingProtocolFeesCryptoBaseUnit,
|
|
107
|
+
inputToken: getAcrossAssetAddress(sellAsset.assetId),
|
|
108
|
+
outputToken: getAcrossAssetAddress(buyAsset.assetId),
|
|
109
|
+
originChainId: sellAcrossChainId,
|
|
110
|
+
destinationChainId: buyAcrossChainId,
|
|
111
|
+
depositor,
|
|
112
|
+
recipient,
|
|
113
|
+
appFee,
|
|
114
|
+
appFeeRecipient,
|
|
115
|
+
integratorId,
|
|
116
|
+
slippage,
|
|
117
|
+
}, deps.config);
|
|
118
|
+
if (maybeQuote.isErr()) {
|
|
119
|
+
const error = maybeQuote.unwrapErr();
|
|
120
|
+
if (!axios_1.default.isAxiosError(error.cause)) {
|
|
121
|
+
return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
|
|
122
|
+
message: 'Unknown error',
|
|
123
|
+
code: types_1.TradeQuoteError.UnknownError,
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
const acrossError = error.cause?.response?.data;
|
|
127
|
+
if (!(0, types_2.isAcrossError)(acrossError)) {
|
|
128
|
+
return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
|
|
129
|
+
message: 'Unknown error',
|
|
130
|
+
code: types_1.TradeQuoteError.UnknownError,
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
const tradeQuoteErrorCode = constant_1.acrossErrorCodeToTradeQuoteError[acrossError.code];
|
|
134
|
+
return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
|
|
135
|
+
message: acrossError.message,
|
|
136
|
+
code: tradeQuoteErrorCode ?? types_1.TradeQuoteError.UnknownError,
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
const { data: quote } = maybeQuote.unwrap();
|
|
140
|
+
const buyAmountAfterFeesCryptoBaseUnit = quote.expectedOutputAmount;
|
|
141
|
+
const rate = (0, utils_2.getInputOutputRate)({
|
|
142
|
+
sellAmountCryptoBaseUnit: sellAmountIncludingProtocolFeesCryptoBaseUnit,
|
|
143
|
+
buyAmountCryptoBaseUnit: buyAmountAfterFeesCryptoBaseUnit,
|
|
144
|
+
sellAsset,
|
|
145
|
+
buyAsset,
|
|
146
|
+
});
|
|
147
|
+
const bridgeFeeAmount = quote.fees.total.amount;
|
|
148
|
+
const bridgeFeeAsset = quote.fees.total.token;
|
|
149
|
+
const buyAssetAcrossAddress = getAcrossAssetAddress(buyAsset.assetId);
|
|
150
|
+
const isBridgeFeeInBuyAsset = bridgeFeeAsset.chainId === buyAcrossChainId &&
|
|
151
|
+
(bridgeFeeAsset.address === buyAssetAcrossAddress ||
|
|
152
|
+
((0, chain_adapters_1.isEvmChainId)(buyAsset.chainId) &&
|
|
153
|
+
bridgeFeeAsset.address.toLowerCase() === buyAssetAcrossAddress.toLowerCase()));
|
|
154
|
+
const buyAmountBeforeFeesCryptoBaseUnit = (() => {
|
|
155
|
+
if (!isBridgeFeeInBuyAsset)
|
|
156
|
+
return buyAmountAfterFeesCryptoBaseUnit;
|
|
157
|
+
const bridgeFeeInBuyAssetPrecision = utils_1.BigAmount.fromBaseUnit({
|
|
158
|
+
value: (0, utils_1.convertPrecision)({
|
|
159
|
+
value: bridgeFeeAmount,
|
|
160
|
+
inputExponent: bridgeFeeAsset.decimals,
|
|
161
|
+
outputExponent: buyAsset.precision,
|
|
162
|
+
}).toFixed(0),
|
|
163
|
+
precision: buyAsset.precision,
|
|
164
|
+
});
|
|
165
|
+
return utils_1.BigAmount.fromBaseUnit({
|
|
166
|
+
value: buyAmountAfterFeesCryptoBaseUnit,
|
|
167
|
+
precision: buyAsset.precision,
|
|
168
|
+
})
|
|
169
|
+
.plus(bridgeFeeInBuyAssetPrecision)
|
|
170
|
+
.toBaseUnit();
|
|
171
|
+
})();
|
|
172
|
+
const allowanceContract = (0, chain_adapters_1.isEvmChainId)(sellAsset.chainId) ? quote.checks.allowance.spender : '';
|
|
173
|
+
const acrossTransactionMetadata = {
|
|
174
|
+
to: quote.swapTx.to,
|
|
175
|
+
data: quote.swapTx.data,
|
|
176
|
+
value: quote.swapTx.value ?? '0',
|
|
177
|
+
gasLimit: quote.swapTx.gas,
|
|
178
|
+
ecosystem: quote.swapTx.ecosystem,
|
|
179
|
+
quoteId: quote.id,
|
|
180
|
+
};
|
|
181
|
+
// For SVM transactions, decompile the pre-built base64 blob into instructions
|
|
182
|
+
// so getUnsignedSolanaTransaction can rebuild it at execution time
|
|
183
|
+
const maybeSolanaTransactionMetadata = await (async () => {
|
|
184
|
+
if (quote.swapTx.ecosystem !== 'svm')
|
|
185
|
+
return (0, monads_1.Ok)(undefined);
|
|
186
|
+
try {
|
|
187
|
+
const versionedTransaction = web3_js_1.VersionedTransaction.deserialize(new Uint8Array(Buffer.from(quote.swapTx.data, 'base64')));
|
|
188
|
+
const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId);
|
|
189
|
+
const addressLookupTableAccountKeys = versionedTransaction.message.addressTableLookups.map(lookup => lookup.accountKey.toString());
|
|
190
|
+
const addressLookupTableAccountsInfos = await adapter.getAddressLookupTableAccounts(addressLookupTableAccountKeys);
|
|
191
|
+
const addressLookupTableAccounts = addressLookupTableAccountsInfos.map(info => new web3_js_1.AddressLookupTableAccount({
|
|
192
|
+
key: new web3_js_1.PublicKey(info.key),
|
|
193
|
+
state: web3_js_1.AddressLookupTableAccount.deserialize(new Uint8Array(info.data)),
|
|
194
|
+
}));
|
|
195
|
+
const instructions = web3_js_1.TransactionMessage.decompile(versionedTransaction.message, {
|
|
196
|
+
addressLookupTableAccounts,
|
|
197
|
+
}).instructions;
|
|
198
|
+
const computeBudgetProgramId = web3_js_1.ComputeBudgetProgram.programId.toString();
|
|
199
|
+
const instructionsWithoutComputeBudget = instructions.filter(instruction => instruction.programId.toString() !== computeBudgetProgramId);
|
|
200
|
+
return (0, monads_1.Ok)({
|
|
201
|
+
instructions: instructionsWithoutComputeBudget,
|
|
202
|
+
addressLookupTableAddresses: addressLookupTableAccountKeys,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
catch (e) {
|
|
206
|
+
return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
|
|
207
|
+
message: `[getTrade] Failed to decompile Solana transaction: ${e}`,
|
|
208
|
+
code: types_1.TradeQuoteError.UnknownError,
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
})();
|
|
212
|
+
if (maybeSolanaTransactionMetadata.isErr())
|
|
213
|
+
return (0, monads_1.Err)(maybeSolanaTransactionMetadata.unwrapErr());
|
|
214
|
+
const solanaTransactionMetadata = maybeSolanaTransactionMetadata.unwrap();
|
|
215
|
+
const networkFeeCryptoBaseUnit = await (async () => {
|
|
216
|
+
if (solanaTransactionMetadata) {
|
|
217
|
+
const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId);
|
|
218
|
+
const { fast } = await adapter.getFeeData({
|
|
219
|
+
to: '',
|
|
220
|
+
value: '0',
|
|
221
|
+
chainSpecific: {
|
|
222
|
+
from: depositor,
|
|
223
|
+
addressLookupTableAccounts: solanaTransactionMetadata.addressLookupTableAddresses,
|
|
224
|
+
instructions: solanaTransactionMetadata.instructions,
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
return fast.txFee;
|
|
228
|
+
}
|
|
229
|
+
if ((0, chain_adapters_1.isEvmChainId)(sellAsset.chainId)) {
|
|
230
|
+
const adapter = deps.assertGetEvmChainAdapter(sellAsset.chainId);
|
|
231
|
+
const { average } = await adapter.getGasFeeData();
|
|
232
|
+
const supportsEIP1559 = 'maxFeePerGas' in average;
|
|
233
|
+
if ((0, utils_1.bnOrZero)(acrossTransactionMetadata.gasLimit).gt(0)) {
|
|
234
|
+
return chain_adapters_1.evm.calcNetworkFeeCryptoBaseUnit({
|
|
235
|
+
...average,
|
|
236
|
+
supportsEIP1559,
|
|
237
|
+
gasLimit: acrossTransactionMetadata.gasLimit ?? '0',
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
try {
|
|
241
|
+
const feeData = await chain_adapters_1.evm.getFees({
|
|
242
|
+
adapter,
|
|
243
|
+
data: acrossTransactionMetadata.data,
|
|
244
|
+
to: acrossTransactionMetadata.to,
|
|
245
|
+
value: acrossTransactionMetadata.value,
|
|
246
|
+
from: depositor,
|
|
247
|
+
supportsEIP1559,
|
|
248
|
+
});
|
|
249
|
+
return feeData.networkFeeCryptoBaseUnit;
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return quote.fees.originGas.amount;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return quote.fees.originGas.amount;
|
|
256
|
+
})();
|
|
257
|
+
// Build protocol fee asset ID — Across returns its own numeric chain IDs, convert to CAIP
|
|
258
|
+
const bridgeFeeAssetCaipChainId = constant_1.acrossChainIdToChainId[bridgeFeeAsset.chainId.toString()];
|
|
259
|
+
const bridgeFeeAssetId = (() => {
|
|
260
|
+
if (!bridgeFeeAssetCaipChainId)
|
|
261
|
+
return undefined;
|
|
262
|
+
const isNativeFeeAsset = (() => {
|
|
263
|
+
if (bridgeFeeAssetCaipChainId === caip_1.solanaChainId) {
|
|
264
|
+
return (bridgeFeeAsset.address === 'So11111111111111111111111111111111111111112' ||
|
|
265
|
+
bridgeFeeAsset.address === viem_1.zeroAddress);
|
|
266
|
+
}
|
|
267
|
+
return bridgeFeeAsset.address === viem_1.zeroAddress;
|
|
268
|
+
})();
|
|
269
|
+
if (isNativeFeeAsset)
|
|
270
|
+
return (0, utils_1.chainIdToFeeAssetId)(bridgeFeeAssetCaipChainId);
|
|
271
|
+
const tokenStandard = bridgeFeeAssetCaipChainId.startsWith('solana') ? 'token' : 'erc20';
|
|
272
|
+
return `${bridgeFeeAssetCaipChainId}/${tokenStandard}:${bridgeFeeAsset.address}`;
|
|
273
|
+
})();
|
|
274
|
+
const accountNumber = input.accountNumber;
|
|
275
|
+
const step = {
|
|
276
|
+
allowanceContract,
|
|
277
|
+
rate,
|
|
278
|
+
buyAmountBeforeFeesCryptoBaseUnit,
|
|
279
|
+
buyAmountAfterFeesCryptoBaseUnit,
|
|
280
|
+
sellAmountIncludingProtocolFeesCryptoBaseUnit,
|
|
281
|
+
buyAsset,
|
|
282
|
+
sellAsset,
|
|
283
|
+
accountNumber,
|
|
284
|
+
feeData: {
|
|
285
|
+
networkFeeCryptoBaseUnit,
|
|
286
|
+
protocolFees: bridgeFeeAssetId
|
|
287
|
+
? {
|
|
288
|
+
[bridgeFeeAssetId]: {
|
|
289
|
+
amountCryptoBaseUnit: bridgeFeeAmount,
|
|
290
|
+
asset: {
|
|
291
|
+
symbol: bridgeFeeAsset.symbol,
|
|
292
|
+
chainId: bridgeFeeAssetCaipChainId,
|
|
293
|
+
precision: bridgeFeeAsset.decimals,
|
|
294
|
+
},
|
|
295
|
+
requiresBalance: false,
|
|
296
|
+
},
|
|
297
|
+
}
|
|
298
|
+
: {},
|
|
299
|
+
},
|
|
300
|
+
source: types_1.SwapperName.Across,
|
|
301
|
+
estimatedExecutionTimeMs: quote.expectedFillTime * 1000,
|
|
302
|
+
acrossTransactionMetadata,
|
|
303
|
+
solanaTransactionMetadata,
|
|
304
|
+
};
|
|
305
|
+
const baseQuoteOrRate = {
|
|
306
|
+
id: quote.id,
|
|
307
|
+
rate,
|
|
308
|
+
swapperName: types_1.SwapperName.Across,
|
|
309
|
+
affiliateBps,
|
|
310
|
+
slippageTolerancePercentageDecimal: input.slippageTolerancePercentageDecimal,
|
|
311
|
+
};
|
|
312
|
+
if (input.quoteOrRate === 'quote') {
|
|
313
|
+
if (!input.receiveAddress) {
|
|
314
|
+
return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
|
|
315
|
+
message: 'Receive address is required for quote',
|
|
316
|
+
code: types_1.TradeQuoteError.InternalError,
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
319
|
+
const tradeQuote = {
|
|
320
|
+
...baseQuoteOrRate,
|
|
321
|
+
steps: [step],
|
|
322
|
+
receiveAddress: input.receiveAddress,
|
|
323
|
+
quoteOrRate: 'quote',
|
|
324
|
+
};
|
|
325
|
+
return (0, monads_1.Ok)([tradeQuote]);
|
|
326
|
+
}
|
|
327
|
+
const tradeRate = {
|
|
328
|
+
...baseQuoteOrRate,
|
|
329
|
+
steps: [step],
|
|
330
|
+
receiveAddress: recipient,
|
|
331
|
+
quoteOrRate: 'rate',
|
|
332
|
+
};
|
|
333
|
+
return (0, monads_1.Ok)([tradeRate]);
|
|
334
|
+
}
|
|
335
|
+
exports.getTrade = getTrade;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import type { Asset } from '@shapeshiftoss/types';
|
|
2
|
+
export type AcrossTradeBaseParams = {
|
|
3
|
+
buyAsset: Asset;
|
|
4
|
+
sellAsset: Asset;
|
|
5
|
+
sellAmountIncludingProtocolFeesCryptoBaseUnit: string;
|
|
6
|
+
affiliateBps: string;
|
|
7
|
+
};
|
|
8
|
+
export type AcrossTradeInputParams<T extends 'rate' | 'quote'> = AcrossTradeBaseParams & {
|
|
9
|
+
quoteOrRate: T;
|
|
10
|
+
receiveAddress: T extends 'rate' ? string | undefined : string;
|
|
11
|
+
sendAddress: T extends 'rate' ? undefined : string;
|
|
12
|
+
accountNumber: T extends 'rate' ? undefined : number;
|
|
13
|
+
slippageTolerancePercentageDecimal?: string;
|
|
14
|
+
};
|
|
15
|
+
export type AcrossTransactionMetadata = {
|
|
16
|
+
to: string;
|
|
17
|
+
data: string;
|
|
18
|
+
value: string;
|
|
19
|
+
gasLimit?: string;
|
|
20
|
+
ecosystem: 'evm' | 'svm';
|
|
21
|
+
quoteId: string;
|
|
22
|
+
};
|
|
23
|
+
export type AcrossTokenInfo = {
|
|
24
|
+
address: string;
|
|
25
|
+
decimals: number;
|
|
26
|
+
symbol: string;
|
|
27
|
+
name: string;
|
|
28
|
+
chainId: number;
|
|
29
|
+
};
|
|
30
|
+
export type AcrossSwapStep = {
|
|
31
|
+
tokenIn: AcrossTokenInfo;
|
|
32
|
+
tokenOut: AcrossTokenInfo;
|
|
33
|
+
inputAmount: string;
|
|
34
|
+
outputAmount: string;
|
|
35
|
+
minOutputAmount: string;
|
|
36
|
+
maxInputAmount: string;
|
|
37
|
+
swapProvider: {
|
|
38
|
+
name: string;
|
|
39
|
+
sources: string[];
|
|
40
|
+
};
|
|
41
|
+
slippage: number;
|
|
42
|
+
};
|
|
43
|
+
export type AcrossFeePart = {
|
|
44
|
+
amount: string;
|
|
45
|
+
pct: string;
|
|
46
|
+
token: AcrossTokenInfo;
|
|
47
|
+
};
|
|
48
|
+
export type AcrossBridgeFeeDetails = {
|
|
49
|
+
type: 'across';
|
|
50
|
+
relayerCapital: AcrossFeePart;
|
|
51
|
+
destinationGas: AcrossFeePart;
|
|
52
|
+
lp: AcrossFeePart;
|
|
53
|
+
};
|
|
54
|
+
export type AcrossBridgeStep = {
|
|
55
|
+
inputAmount: string;
|
|
56
|
+
outputAmount: string;
|
|
57
|
+
tokenIn: AcrossTokenInfo;
|
|
58
|
+
tokenOut: AcrossTokenInfo;
|
|
59
|
+
fees: {
|
|
60
|
+
amount: string;
|
|
61
|
+
pct: string;
|
|
62
|
+
token: AcrossTokenInfo;
|
|
63
|
+
details: AcrossBridgeFeeDetails;
|
|
64
|
+
};
|
|
65
|
+
provider: string;
|
|
66
|
+
};
|
|
67
|
+
export type AcrossFeeBreakdown = {
|
|
68
|
+
amount: string;
|
|
69
|
+
amountUsd: string;
|
|
70
|
+
token: AcrossTokenInfo;
|
|
71
|
+
pct: string;
|
|
72
|
+
details: {
|
|
73
|
+
type: string;
|
|
74
|
+
swapImpact: {
|
|
75
|
+
amount: string;
|
|
76
|
+
amountUsd: string;
|
|
77
|
+
token: AcrossTokenInfo;
|
|
78
|
+
pct: string;
|
|
79
|
+
};
|
|
80
|
+
app: {
|
|
81
|
+
amount: string;
|
|
82
|
+
amountUsd: string;
|
|
83
|
+
pct: string;
|
|
84
|
+
token: AcrossTokenInfo;
|
|
85
|
+
};
|
|
86
|
+
bridge: AcrossBridgeStep['fees'];
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
export type AcrossSwapTx = {
|
|
90
|
+
simulationSuccess: boolean;
|
|
91
|
+
chainId: number;
|
|
92
|
+
to: string;
|
|
93
|
+
data: string;
|
|
94
|
+
value?: string;
|
|
95
|
+
gas?: string;
|
|
96
|
+
maxFeePerGas?: string;
|
|
97
|
+
maxPriorityFeePerGas?: string;
|
|
98
|
+
ecosystem: 'evm' | 'svm';
|
|
99
|
+
};
|
|
100
|
+
export type AcrossSwapApprovalResponse = {
|
|
101
|
+
crossSwapType: 'bridgeableToBridgeable' | 'bridgeableToBridgeableIndirect' | 'bridgeableToAny' | 'anyToBridgeable' | 'anyToAny';
|
|
102
|
+
amountType: string;
|
|
103
|
+
approvalTxns: {
|
|
104
|
+
chainId: number;
|
|
105
|
+
to: string;
|
|
106
|
+
data: string;
|
|
107
|
+
}[];
|
|
108
|
+
swapTx: AcrossSwapTx;
|
|
109
|
+
checks: {
|
|
110
|
+
allowance: {
|
|
111
|
+
token: string;
|
|
112
|
+
spender: string;
|
|
113
|
+
actual: string;
|
|
114
|
+
expected: string;
|
|
115
|
+
};
|
|
116
|
+
balance: {
|
|
117
|
+
token: string;
|
|
118
|
+
actual: string;
|
|
119
|
+
expected: string;
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
steps: {
|
|
123
|
+
originSwap?: AcrossSwapStep;
|
|
124
|
+
bridge: AcrossBridgeStep;
|
|
125
|
+
destinationSwap?: AcrossSwapStep;
|
|
126
|
+
};
|
|
127
|
+
inputToken: AcrossTokenInfo;
|
|
128
|
+
outputToken: AcrossTokenInfo;
|
|
129
|
+
refundToken: AcrossTokenInfo;
|
|
130
|
+
inputAmount: string;
|
|
131
|
+
maxInputAmount: string;
|
|
132
|
+
expectedOutputAmount: string;
|
|
133
|
+
minOutputAmount: string;
|
|
134
|
+
fees: {
|
|
135
|
+
total: AcrossFeeBreakdown;
|
|
136
|
+
totalMax: AcrossFeeBreakdown;
|
|
137
|
+
originGas: {
|
|
138
|
+
amount: string;
|
|
139
|
+
amountUsd: string;
|
|
140
|
+
token: AcrossTokenInfo;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
expectedFillTime: number;
|
|
144
|
+
quoteExpiryTimestamp: number;
|
|
145
|
+
id: string;
|
|
146
|
+
};
|
|
147
|
+
export type AcrossDepositStatus = {
|
|
148
|
+
status: 'filled' | 'pending' | 'expired' | 'refunded' | 'slowFillRequested';
|
|
149
|
+
fillTxnRef?: string;
|
|
150
|
+
destinationChainId: number;
|
|
151
|
+
originChainId: number;
|
|
152
|
+
depositId: number;
|
|
153
|
+
depositTxnRef: string;
|
|
154
|
+
depositRefundTxnRef?: string;
|
|
155
|
+
actionsSucceeded?: boolean;
|
|
156
|
+
pagination: {
|
|
157
|
+
currentIndex: number;
|
|
158
|
+
maxIndex: number;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
export type AcrossError = {
|
|
162
|
+
type: string;
|
|
163
|
+
code: string;
|
|
164
|
+
status: number;
|
|
165
|
+
message: string;
|
|
166
|
+
id: string;
|
|
167
|
+
};
|
|
168
|
+
export declare const isAcrossError: (error: unknown) => error is AcrossError;
|
|
169
|
+
export declare enum AcrossErrorCode {
|
|
170
|
+
InvalidParam = "INVALID_PARAM",
|
|
171
|
+
AmountTooLow = "AMOUNT_TOO_LOW",
|
|
172
|
+
RouteNotFound = "ROUTE_NOT_FOUND",
|
|
173
|
+
NoBridgeRoutes = "NO_BRIDGE_ROUTES",
|
|
174
|
+
UnsupportedToken = "UNSUPPORTED_TOKEN",
|
|
175
|
+
InsufficientLiquidity = "INSUFFICIENT_LIQUIDITY",
|
|
176
|
+
InternalError = "INTERNAL_ERROR"
|
|
177
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AcrossErrorCode = exports.isAcrossError = void 0;
|
|
4
|
+
const isAcrossError = (error) => {
|
|
5
|
+
return typeof error === 'object' && error !== null && 'code' in error && 'status' in error;
|
|
6
|
+
};
|
|
7
|
+
exports.isAcrossError = isAcrossError;
|
|
8
|
+
var AcrossErrorCode;
|
|
9
|
+
(function (AcrossErrorCode) {
|
|
10
|
+
AcrossErrorCode["InvalidParam"] = "INVALID_PARAM";
|
|
11
|
+
AcrossErrorCode["AmountTooLow"] = "AMOUNT_TOO_LOW";
|
|
12
|
+
AcrossErrorCode["RouteNotFound"] = "ROUTE_NOT_FOUND";
|
|
13
|
+
AcrossErrorCode["NoBridgeRoutes"] = "NO_BRIDGE_ROUTES";
|
|
14
|
+
AcrossErrorCode["UnsupportedToken"] = "UNSUPPORTED_TOKEN";
|
|
15
|
+
AcrossErrorCode["InsufficientLiquidity"] = "INSUFFICIENT_LIQUIDITY";
|
|
16
|
+
AcrossErrorCode["InternalError"] = "INTERNAL_ERROR";
|
|
17
|
+
})(AcrossErrorCode || (exports.AcrossErrorCode = AcrossErrorCode = {}));
|
|
@@ -7,6 +7,30 @@ const starknet_1 = require("starknet");
|
|
|
7
7
|
const utils_1 = require("../../utils");
|
|
8
8
|
const getTradeQuote_1 = require("./swapperApi/getTradeQuote");
|
|
9
9
|
const getTradeRate_1 = require("./swapperApi/getTradeRate");
|
|
10
|
+
/**
|
|
11
|
+
* Normalize a value to hex format for Starknet RPC
|
|
12
|
+
* Handles various input types: decimal strings, hex strings (with/without 0x), numbers, BigInts
|
|
13
|
+
*/
|
|
14
|
+
const toHexString = (value) => {
|
|
15
|
+
const strValue = String(value);
|
|
16
|
+
// Already a proper hex string with 0x prefix
|
|
17
|
+
if (strValue.startsWith('0x')) {
|
|
18
|
+
return strValue;
|
|
19
|
+
}
|
|
20
|
+
// Check if it looks like a hex string without 0x prefix (contains a-f characters)
|
|
21
|
+
// Starknet addresses and felts often come as hex without 0x prefix
|
|
22
|
+
if (/^[0-9a-fA-F]+$/.test(strValue) && /[a-fA-F]/.test(strValue)) {
|
|
23
|
+
return `0x${strValue}`;
|
|
24
|
+
}
|
|
25
|
+
// Otherwise treat as decimal and convert to hex
|
|
26
|
+
try {
|
|
27
|
+
return starknet_1.num.toHex(strValue);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// If conversion fails, assume it's already hex and add prefix
|
|
31
|
+
return `0x${strValue}`;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
10
34
|
exports.avnuApi = {
|
|
11
35
|
getTradeQuote: getTradeQuote_1.getTradeQuote,
|
|
12
36
|
getTradeRate: (input, deps) => {
|
|
@@ -22,16 +46,23 @@ exports.avnuApi = {
|
|
|
22
46
|
if (!avnuSpecific.quoteId)
|
|
23
47
|
throw new Error('quoteId is required in avnuSpecific');
|
|
24
48
|
const adapter = assertGetStarknetChainAdapter(sellAsset.chainId);
|
|
49
|
+
// Normalize the from address to ensure consistent format
|
|
50
|
+
// Starknet addresses can have different representations (with/without leading zeros)
|
|
51
|
+
const normalizedFrom = (0, starknet_1.validateAndParseAddress)(from);
|
|
25
52
|
// Convert slippage from decimal percentage string to number for AVNU format (e.g., "0.01" = 1%)
|
|
53
|
+
// Use a slightly higher default slippage (2%) to account for quote staleness
|
|
26
54
|
const slippage = slippageTolerancePercentageDecimal
|
|
27
55
|
? parseFloat(slippageTolerancePercentageDecimal)
|
|
28
|
-
: 0.
|
|
56
|
+
: 0.02;
|
|
29
57
|
// Get the swap calls from AVNU SDK
|
|
30
58
|
const { calls: avnuCalls } = await (0, avnu_sdk_1.quoteToCalls)({
|
|
31
59
|
quoteId: avnuSpecific.quoteId,
|
|
32
60
|
slippage,
|
|
33
|
-
takerAddress:
|
|
61
|
+
takerAddress: normalizedFrom,
|
|
34
62
|
});
|
|
63
|
+
if (!avnuCalls || avnuCalls.length === 0) {
|
|
64
|
+
throw new Error('No swap calls returned from AVNU - quote may have expired');
|
|
65
|
+
}
|
|
35
66
|
// Build the full invoke transaction calldata from AVNU calls
|
|
36
67
|
// Format: [call_array_length, contract1, selector1, calldata_len1, ...calldata1, ...]
|
|
37
68
|
const fullCalldata = [avnuCalls.length.toString()];
|
|
@@ -39,24 +70,21 @@ exports.avnuApi = {
|
|
|
39
70
|
const rawCalldata = call.calldata ?? [];
|
|
40
71
|
const calldataArray = Array.isArray(rawCalldata) ? rawCalldata : starknet_1.CallData.compile(rawCalldata);
|
|
41
72
|
const selector = starknet_1.hash.getSelectorFromName(call.entrypoint);
|
|
42
|
-
|
|
73
|
+
// Normalize contract address from AVNU to ensure consistent format
|
|
74
|
+
const normalizedContractAddress = (0, starknet_1.validateAndParseAddress)(call.contractAddress);
|
|
75
|
+
fullCalldata.push(normalizedContractAddress, selector, calldataArray.length.toString(), ...calldataArray.map(cd => String(cd)));
|
|
43
76
|
}
|
|
44
|
-
// Format calldata for RPC (convert
|
|
45
|
-
const formattedCalldata = fullCalldata.map(
|
|
46
|
-
if (!data.startsWith('0x')) {
|
|
47
|
-
return starknet_1.num.toHex(data);
|
|
48
|
-
}
|
|
49
|
-
return data;
|
|
50
|
-
});
|
|
77
|
+
// Format calldata for RPC (convert all values to proper hex format)
|
|
78
|
+
const formattedCalldata = fullCalldata.map(toHexString);
|
|
51
79
|
// Get nonce using adapter method (checks deployment status and returns appropriate nonce)
|
|
52
80
|
const chainIdHex = await adapter.getStarknetProvider().getChainId();
|
|
53
|
-
const nonce = await adapter.getNonce(
|
|
81
|
+
const nonce = await adapter.getNonce(normalizedFrom);
|
|
54
82
|
// Estimate fees for the multi-call swap transaction
|
|
55
83
|
const version = '0x3';
|
|
56
84
|
const estimateTx = {
|
|
57
85
|
type: 'INVOKE',
|
|
58
86
|
version,
|
|
59
|
-
sender_address:
|
|
87
|
+
sender_address: normalizedFrom,
|
|
60
88
|
calldata: formattedCalldata,
|
|
61
89
|
signature: [],
|
|
62
90
|
nonce,
|
|
@@ -115,7 +143,7 @@ exports.avnuApi = {
|
|
|
115
143
|
};
|
|
116
144
|
// Calculate transaction hash for signing
|
|
117
145
|
const invokeHashInputs = {
|
|
118
|
-
senderAddress:
|
|
146
|
+
senderAddress: normalizedFrom,
|
|
119
147
|
version,
|
|
120
148
|
compiledCalldata: formattedCalldata,
|
|
121
149
|
chainId: chainIdHex,
|
|
@@ -146,7 +174,7 @@ exports.avnuApi = {
|
|
|
146
174
|
addressNList: (0, chain_adapters_1.toAddressNList)(adapter.getBip44Params({ accountNumber })),
|
|
147
175
|
txHash,
|
|
148
176
|
_txDetails: {
|
|
149
|
-
fromAddress:
|
|
177
|
+
fromAddress: normalizedFrom,
|
|
150
178
|
calldata: formattedCalldata,
|
|
151
179
|
nonce,
|
|
152
180
|
version,
|
|
@@ -4,11 +4,12 @@ exports.getTradeQuote = void 0;
|
|
|
4
4
|
const avnu_sdk_1 = require("@avnu/avnu-sdk");
|
|
5
5
|
const utils_1 = require("@shapeshiftoss/utils");
|
|
6
6
|
const monads_1 = require("@sniptt/monads");
|
|
7
|
-
const
|
|
7
|
+
const starknet_1 = require("starknet");
|
|
8
8
|
const uuid_1 = require("uuid");
|
|
9
9
|
const constants_1 = require("../../../constants");
|
|
10
10
|
const types_1 = require("../../../types");
|
|
11
11
|
const utils_2 = require("../../../utils");
|
|
12
|
+
const helpers_1 = require("../../utils/helpers/helpers");
|
|
12
13
|
const constants_2 = require("../utils/constants");
|
|
13
14
|
const helpers_2 = require("../utils/helpers");
|
|
14
15
|
const getTradeQuote = async (input, deps) => {
|
|
@@ -46,11 +47,15 @@ const getTradeQuote = async (input, deps) => {
|
|
|
46
47
|
try {
|
|
47
48
|
const sellTokenAddress = (0, helpers_2.getTokenAddress)(sellAsset);
|
|
48
49
|
const buyTokenAddress = (0, helpers_2.getTokenAddress)(buyAsset);
|
|
50
|
+
// Normalize addresses to ensure consistent format across quote and execution
|
|
51
|
+
// Starknet addresses can have different representations (with/without leading zeros)
|
|
52
|
+
const normalizedSendAddress = (0, starknet_1.validateAndParseAddress)(sendAddress);
|
|
53
|
+
const normalizedReceiveAddress = (0, starknet_1.validateAndParseAddress)(receiveAddress);
|
|
49
54
|
const quotes = await (0, avnu_sdk_1.getQuotes)({
|
|
50
55
|
sellTokenAddress,
|
|
51
56
|
buyTokenAddress,
|
|
52
57
|
sellAmount: BigInt(sellAmount),
|
|
53
|
-
takerAddress:
|
|
58
|
+
takerAddress: normalizedSendAddress,
|
|
54
59
|
size: 1,
|
|
55
60
|
integratorFees: affiliateBps ? BigInt(affiliateBps) : undefined,
|
|
56
61
|
integratorFeeRecipient: (0, helpers_1.getTreasuryAddressFromChainId)(sellAsset.chainId),
|
|
@@ -71,10 +76,10 @@ const getTradeQuote = async (input, deps) => {
|
|
|
71
76
|
const buyAmountAfterFeesCryptoBaseUnit = bestQuote.buyAmount.toString();
|
|
72
77
|
const sellAdapter = deps.assertGetStarknetChainAdapter(sellAsset.chainId);
|
|
73
78
|
const feeData = await sellAdapter.getFeeData({
|
|
74
|
-
to:
|
|
79
|
+
to: normalizedReceiveAddress,
|
|
75
80
|
value: sellAmount,
|
|
76
81
|
chainSpecific: {
|
|
77
|
-
from:
|
|
82
|
+
from: normalizedSendAddress,
|
|
78
83
|
tokenContractAddress: sellTokenAddress,
|
|
79
84
|
},
|
|
80
85
|
sendMax: false,
|
|
@@ -99,7 +104,7 @@ const getTradeQuote = async (input, deps) => {
|
|
|
99
104
|
: {};
|
|
100
105
|
const tradeQuote = {
|
|
101
106
|
id: (0, uuid_1.v4)(),
|
|
102
|
-
receiveAddress,
|
|
107
|
+
receiveAddress: normalizedReceiveAddress,
|
|
103
108
|
affiliateBps,
|
|
104
109
|
rate,
|
|
105
110
|
slippageTolerancePercentageDecimal: slippageTolerancePercentageDecimal ??
|