@shapeshiftoss/swapper 20.4.0 → 20.6.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/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/constants.js +6 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/swappers/AcrossSwapper/utils/getAcrossStepData.js +7 -15
- package/dist/cjs/swappers/AvnuSwapper/endpoints.js +17 -12
- package/dist/cjs/swappers/BebopSwapper/utils/getBebopStepData.js +17 -22
- package/dist/cjs/swappers/ButterSwap/swapperApi/getTradeQuote.test.js +1 -0
- package/dist/cjs/swappers/ButterSwap/swapperApi/getTradeRate.test.js +1 -0
- package/dist/cjs/swappers/ButterSwap/utils/getButterSwapStepData.js +3 -4
- package/dist/cjs/swappers/ButterSwap/utils/getButterSwapStepData.test.js +2 -2
- package/dist/cjs/swappers/CetusSwapper/endpoints.js +2 -3
- package/dist/cjs/swappers/CetusSwapper/swapperApi/getCetusStepData.js +13 -8
- package/dist/cjs/swappers/CetusSwapper/swapperApi/getCetusTradeContext.js +1 -2
- package/dist/cjs/swappers/CetusSwapper/utils/constants.d.ts +0 -1
- package/dist/cjs/swappers/CetusSwapper/utils/constants.js +1 -2
- package/dist/cjs/swappers/CetusSwapper/utils/helpers.d.ts +3 -3
- package/dist/cjs/swappers/CetusSwapper/utils/helpers.js +6 -17
- package/dist/cjs/swappers/DebridgeSwapper/utils/getDebridgeStepData.d.ts +0 -1
- package/dist/cjs/swappers/DebridgeSwapper/utils/getDebridgeStepData.js +9 -16
- package/dist/cjs/swappers/DebridgeSwapper/utils/getDebridgeTradeContext.js +0 -3
- package/dist/cjs/swappers/FyndSwapper/utils/getFyndStepData.js +5 -7
- package/dist/cjs/swappers/KyberSwapper/KyberSwapper.d.ts +2 -0
- package/dist/cjs/swappers/KyberSwapper/KyberSwapper.js +5 -0
- package/dist/cjs/swappers/KyberSwapper/endpoints.d.ts +2 -0
- package/dist/cjs/swappers/KyberSwapper/endpoints.js +14 -0
- package/dist/cjs/swappers/KyberSwapper/index.d.ts +2 -0
- package/dist/cjs/swappers/KyberSwapper/index.js +7 -0
- package/dist/cjs/swappers/KyberSwapper/swapperApi/getKyberTradeQuote.d.ts +4 -0
- package/dist/cjs/swappers/KyberSwapper/swapperApi/getKyberTradeQuote.js +64 -0
- package/dist/cjs/swappers/KyberSwapper/swapperApi/getKyberTradeRate.d.ts +4 -0
- package/dist/cjs/swappers/KyberSwapper/swapperApi/getKyberTradeRate.js +31 -0
- package/dist/cjs/swappers/KyberSwapper/types.d.ts +62 -0
- package/dist/cjs/swappers/KyberSwapper/types.js +2 -0
- package/dist/cjs/swappers/KyberSwapper/utils/constants.d.ts +22 -0
- package/dist/cjs/swappers/KyberSwapper/utils/constants.js +25 -0
- package/dist/cjs/swappers/KyberSwapper/utils/fetchFromKyber.d.ts +23 -0
- package/dist/cjs/swappers/KyberSwapper/utils/fetchFromKyber.js +38 -0
- package/dist/cjs/swappers/KyberSwapper/utils/getKyberStepData.d.ts +27 -0
- package/dist/cjs/swappers/KyberSwapper/utils/getKyberStepData.js +47 -0
- package/dist/cjs/swappers/KyberSwapper/utils/getKyberStepData.test.d.ts +1 -0
- package/dist/cjs/swappers/KyberSwapper/utils/getKyberStepData.test.js +92 -0
- package/dist/cjs/swappers/KyberSwapper/utils/getKyberTradeContext.d.ts +20 -0
- package/dist/cjs/swappers/KyberSwapper/utils/getKyberTradeContext.js +63 -0
- package/dist/cjs/swappers/KyberSwapper/utils/helpers.d.ts +27 -0
- package/dist/cjs/swappers/KyberSwapper/utils/helpers.js +172 -0
- package/dist/cjs/swappers/KyberSwapper/utils/helpers.test.d.ts +1 -0
- package/dist/cjs/swappers/KyberSwapper/utils/helpers.test.js +110 -0
- package/dist/cjs/swappers/KyberSwapper/utils/kyberService.d.ts +5 -0
- package/dist/cjs/swappers/KyberSwapper/utils/kyberService.js +9 -0
- package/dist/cjs/swappers/NearIntentsSwapper/NearIntentsSwapper.js +1 -0
- package/dist/cjs/swappers/NearIntentsSwapper/endpoints.js +13 -14
- package/dist/cjs/swappers/NearIntentsSwapper/swapperApi/getTradeRate.js +1 -1
- package/dist/cjs/swappers/NearIntentsSwapper/types.d.ts +4 -4
- package/dist/cjs/swappers/NearIntentsSwapper/types.js +2 -0
- package/dist/cjs/swappers/NearIntentsSwapper/utils/getNearIntentsStepData.js +28 -0
- package/dist/cjs/swappers/NearIntentsSwapper/utils/helpers.js +2 -2
- package/dist/cjs/swappers/PortalsSwapper/utils/getPortalsStepData.js +36 -55
- package/dist/cjs/swappers/PortalsSwapper/utils/getPortalsStepData.test.js +2 -2
- package/dist/cjs/swappers/RelaySwapper/constant.js +1 -0
- package/dist/cjs/swappers/RelaySwapper/utils/getRelayStepData.js +7 -15
- package/dist/cjs/swappers/RelaySwapper/utils/relayTokenToAssetId.js +5 -0
- package/dist/cjs/swappers/ThorchainSwapper/generated/generatedThorLongtailTokens.json +1 -0
- package/dist/cjs/swappers/ThorchainSwapper/getTradeQuote/getTradeQuote.test.js +2 -2
- package/dist/cjs/swappers/ZrxSwapper/getZrxTradeQuote/getZrxTradeQuote.js +3 -1
- package/dist/cjs/swappers/ZrxSwapper/types.d.ts +1 -1
- package/dist/cjs/swappers/ZrxSwapper/types.js +1 -0
- package/dist/cjs/swappers/ZrxSwapper/utils/constants.js +1 -0
- package/dist/cjs/swappers/ZrxSwapper/utils/getZrxStepData.d.ts +3 -1
- package/dist/cjs/swappers/ZrxSwapper/utils/getZrxStepData.js +29 -10
- package/dist/cjs/swappers/ZrxSwapper/utils/helpers.d.ts +1 -1
- package/dist/cjs/swappers/ZrxSwapper/utils/helpers.js +5 -0
- package/dist/cjs/types.d.ts +36 -8
- package/dist/cjs/types.js +1 -0
- package/dist/cjs/utils/aptos/constants.d.ts +2 -0
- package/dist/cjs/utils/aptos/constants.js +7 -0
- package/dist/cjs/utils/aptos/getAptosTransactionFees.d.ts +2 -0
- package/dist/cjs/utils/aptos/getAptosTransactionFees.js +13 -0
- package/dist/cjs/utils/aptos/getUnsignedAptosTransaction.d.ts +2 -0
- package/dist/cjs/utils/aptos/getUnsignedAptosTransaction.js +16 -0
- package/dist/cjs/utils/aptos/index.d.ts +3 -0
- package/dist/cjs/utils/aptos/index.js +19 -0
- package/dist/cjs/utils/evm/getEvmNetworkFeeCryptoBaseUnit.d.ts +19 -6
- package/dist/cjs/utils/evm/getEvmNetworkFeeCryptoBaseUnit.js +45 -35
- package/dist/cjs/utils/evm/getEvmNetworkFeeCryptoBaseUnit.test.d.ts +1 -0
- package/dist/cjs/utils/evm/getEvmNetworkFeeCryptoBaseUnit.test.js +103 -0
- package/dist/cjs/utils/evm/stateOverride.d.ts +3 -0
- package/dist/cjs/utils/evm/stateOverride.js +10 -4
- package/dist/cjs/utils/helpers.js +2 -0
- package/dist/cjs/utils/helpers.test.js +2 -0
- package/dist/cjs/utils/index.d.ts +3 -2
- package/dist/cjs/utils/index.js +11 -27
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/constants.js +6 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/swappers/AcrossSwapper/utils/getAcrossStepData.js +8 -16
- package/dist/esm/swappers/AvnuSwapper/endpoints.js +18 -13
- package/dist/esm/swappers/BebopSwapper/utils/getBebopStepData.js +18 -23
- package/dist/esm/swappers/ButterSwap/swapperApi/getTradeQuote.test.js +1 -0
- package/dist/esm/swappers/ButterSwap/swapperApi/getTradeRate.test.js +1 -0
- package/dist/esm/swappers/ButterSwap/utils/getButterSwapStepData.js +4 -5
- package/dist/esm/swappers/ButterSwap/utils/getButterSwapStepData.test.js +2 -2
- package/dist/esm/swappers/CetusSwapper/endpoints.js +3 -4
- package/dist/esm/swappers/CetusSwapper/swapperApi/getCetusStepData.js +13 -8
- package/dist/esm/swappers/CetusSwapper/swapperApi/getCetusTradeContext.js +2 -3
- package/dist/esm/swappers/CetusSwapper/utils/constants.d.ts +0 -1
- package/dist/esm/swappers/CetusSwapper/utils/constants.js +0 -1
- package/dist/esm/swappers/CetusSwapper/utils/helpers.d.ts +3 -3
- package/dist/esm/swappers/CetusSwapper/utils/helpers.js +4 -15
- package/dist/esm/swappers/DebridgeSwapper/utils/getDebridgeStepData.d.ts +0 -1
- package/dist/esm/swappers/DebridgeSwapper/utils/getDebridgeStepData.js +9 -16
- package/dist/esm/swappers/DebridgeSwapper/utils/getDebridgeTradeContext.js +0 -3
- package/dist/esm/swappers/FyndSwapper/utils/getFyndStepData.js +6 -8
- package/dist/esm/swappers/KyberSwapper/KyberSwapper.d.ts +2 -0
- package/dist/esm/swappers/KyberSwapper/KyberSwapper.js +2 -0
- package/dist/esm/swappers/KyberSwapper/endpoints.d.ts +2 -0
- package/dist/esm/swappers/KyberSwapper/endpoints.js +11 -0
- package/dist/esm/swappers/KyberSwapper/index.d.ts +2 -0
- package/dist/esm/swappers/KyberSwapper/index.js +2 -0
- package/dist/esm/swappers/KyberSwapper/swapperApi/getKyberTradeQuote.d.ts +4 -0
- package/dist/esm/swappers/KyberSwapper/swapperApi/getKyberTradeQuote.js +60 -0
- package/dist/esm/swappers/KyberSwapper/swapperApi/getKyberTradeRate.d.ts +4 -0
- package/dist/esm/swappers/KyberSwapper/swapperApi/getKyberTradeRate.js +27 -0
- package/dist/esm/swappers/KyberSwapper/types.d.ts +62 -0
- package/dist/esm/swappers/KyberSwapper/types.js +1 -0
- package/dist/esm/swappers/KyberSwapper/utils/constants.d.ts +22 -0
- package/dist/esm/swappers/KyberSwapper/utils/constants.js +22 -0
- package/dist/esm/swappers/KyberSwapper/utils/fetchFromKyber.d.ts +23 -0
- package/dist/esm/swappers/KyberSwapper/utils/fetchFromKyber.js +33 -0
- package/dist/esm/swappers/KyberSwapper/utils/getKyberStepData.d.ts +27 -0
- package/dist/esm/swappers/KyberSwapper/utils/getKyberStepData.js +43 -0
- package/dist/esm/swappers/KyberSwapper/utils/getKyberStepData.test.d.ts +1 -0
- package/dist/esm/swappers/KyberSwapper/utils/getKyberStepData.test.js +90 -0
- package/dist/esm/swappers/KyberSwapper/utils/getKyberTradeContext.d.ts +20 -0
- package/dist/esm/swappers/KyberSwapper/utils/getKyberTradeContext.js +59 -0
- package/dist/esm/swappers/KyberSwapper/utils/helpers.d.ts +27 -0
- package/dist/esm/swappers/KyberSwapper/utils/helpers.js +158 -0
- package/dist/esm/swappers/KyberSwapper/utils/helpers.test.d.ts +1 -0
- package/dist/esm/swappers/KyberSwapper/utils/helpers.test.js +108 -0
- package/dist/esm/swappers/KyberSwapper/utils/kyberService.d.ts +5 -0
- package/dist/esm/swappers/KyberSwapper/utils/kyberService.js +3 -0
- package/dist/esm/swappers/NearIntentsSwapper/NearIntentsSwapper.js +2 -1
- package/dist/esm/swappers/NearIntentsSwapper/endpoints.js +13 -14
- package/dist/esm/swappers/NearIntentsSwapper/swapperApi/getTradeRate.js +1 -1
- package/dist/esm/swappers/NearIntentsSwapper/types.d.ts +4 -4
- package/dist/esm/swappers/NearIntentsSwapper/types.js +2 -0
- package/dist/esm/swappers/NearIntentsSwapper/utils/getNearIntentsStepData.js +29 -1
- package/dist/esm/swappers/NearIntentsSwapper/utils/helpers.js +2 -2
- package/dist/esm/swappers/PortalsSwapper/utils/getPortalsStepData.js +34 -53
- package/dist/esm/swappers/PortalsSwapper/utils/getPortalsStepData.test.js +2 -2
- package/dist/esm/swappers/RelaySwapper/constant.js +2 -1
- package/dist/esm/swappers/RelaySwapper/utils/getRelayStepData.js +9 -17
- package/dist/esm/swappers/RelaySwapper/utils/relayTokenToAssetId.js +5 -0
- package/dist/esm/swappers/ThorchainSwapper/generated/generatedThorLongtailTokens.json +1 -0
- package/dist/esm/swappers/ThorchainSwapper/getTradeQuote/getTradeQuote.test.js +2 -2
- package/dist/esm/swappers/ZrxSwapper/getZrxTradeQuote/getZrxTradeQuote.js +3 -1
- package/dist/esm/swappers/ZrxSwapper/types.d.ts +1 -1
- package/dist/esm/swappers/ZrxSwapper/types.js +1 -0
- package/dist/esm/swappers/ZrxSwapper/utils/constants.js +1 -0
- package/dist/esm/swappers/ZrxSwapper/utils/getZrxStepData.d.ts +3 -1
- package/dist/esm/swappers/ZrxSwapper/utils/getZrxStepData.js +31 -12
- package/dist/esm/swappers/ZrxSwapper/utils/helpers.d.ts +1 -1
- package/dist/esm/swappers/ZrxSwapper/utils/helpers.js +5 -0
- package/dist/esm/types.d.ts +36 -8
- package/dist/esm/types.js +1 -0
- package/dist/esm/utils/aptos/constants.d.ts +2 -0
- package/dist/esm/utils/aptos/constants.js +4 -0
- package/dist/esm/utils/aptos/getAptosTransactionFees.d.ts +2 -0
- package/dist/esm/utils/aptos/getAptosTransactionFees.js +9 -0
- package/dist/esm/utils/aptos/getUnsignedAptosTransaction.d.ts +2 -0
- package/dist/esm/utils/aptos/getUnsignedAptosTransaction.js +12 -0
- package/dist/esm/utils/aptos/index.d.ts +3 -0
- package/dist/esm/utils/aptos/index.js +3 -0
- package/dist/esm/utils/evm/getEvmNetworkFeeCryptoBaseUnit.d.ts +19 -6
- package/dist/esm/utils/evm/getEvmNetworkFeeCryptoBaseUnit.js +42 -35
- package/dist/esm/utils/evm/getEvmNetworkFeeCryptoBaseUnit.test.d.ts +1 -0
- package/dist/esm/utils/evm/getEvmNetworkFeeCryptoBaseUnit.test.js +101 -0
- package/dist/esm/utils/evm/stateOverride.d.ts +3 -0
- package/dist/esm/utils/evm/stateOverride.js +8 -3
- package/dist/esm/utils/helpers.js +3 -1
- package/dist/esm/utils/helpers.test.js +2 -0
- package/dist/esm/utils/index.d.ts +3 -2
- package/dist/esm/utils/index.js +9 -26
- package/package.json +10 -11
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { fromAssetId } from '@shapeshiftoss/caip';
|
|
2
|
+
import { BigNumber, bn, bnOrZero } from '@shapeshiftoss/utils';
|
|
3
|
+
import { Err, Ok } from '@sniptt/monads';
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
import { getAddress, isAddress, isAddressEqual } from 'viem';
|
|
6
|
+
import { TradeQuoteError } from '../../../types.js';
|
|
7
|
+
import { getInputOutputRate, makeSwapErrorRight } from '../../../utils/index.js';
|
|
8
|
+
import { buildAffiliateFee } from '../../../utils/affiliateFee.js';
|
|
9
|
+
import { getTreasuryAddressFromChainId, isNativeEvmAsset } from '../../../utils/helpers.js';
|
|
10
|
+
import { KYBER_CHAINS, KYBER_NATIVE_TOKEN, KYBER_ROUTER_ADDRESS } from './constants.js';
|
|
11
|
+
const isKyberSupportedChainId = (chainId) => chainId in KYBER_CHAINS;
|
|
12
|
+
const invalidResponse = (message, details) => makeSwapErrorRight({ message, details, code: TradeQuoteError.InvalidResponse });
|
|
13
|
+
export const assertValidTrade = ({ sellAsset, buyAsset, }) => {
|
|
14
|
+
if (sellAsset.chainId !== buyAsset.chainId) {
|
|
15
|
+
return Err(makeSwapErrorRight({
|
|
16
|
+
message: 'KyberSwap does not support cross-chain trades',
|
|
17
|
+
code: TradeQuoteError.CrossChainNotSupported,
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
if (!isKyberSupportedChainId(sellAsset.chainId)) {
|
|
21
|
+
return Err(makeSwapErrorRight({
|
|
22
|
+
message: 'KyberSwap only supports configured EVM chains',
|
|
23
|
+
code: TradeQuoteError.UnsupportedChain,
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
return Ok(sellAsset.chainId);
|
|
27
|
+
};
|
|
28
|
+
export const assetIdToKyberToken = (assetId) => isNativeEvmAsset(assetId) ? KYBER_NATIVE_TOKEN : getAddress(fromAssetId(assetId).assetReference);
|
|
29
|
+
export const getKyberFeeParams = ({ chainId, affiliateBps, }) => {
|
|
30
|
+
if (bnOrZero(affiliateBps).lte(0))
|
|
31
|
+
return undefined;
|
|
32
|
+
return {
|
|
33
|
+
feeAmount: affiliateBps,
|
|
34
|
+
chargeFeeBy: 'currency_out',
|
|
35
|
+
isInBps: true,
|
|
36
|
+
feeReceiver: getAddress(getTreasuryAddressFromChainId(chainId)),
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
// Kyber only returns the post-fee amountOut; the inverse is at most one base unit off
|
|
40
|
+
export const getKyberBuyAmountBeforeFees = ({ buyAmountAfterFeesCryptoBaseUnit, affiliateBps, }) => {
|
|
41
|
+
if (bnOrZero(affiliateBps).lte(0))
|
|
42
|
+
return buyAmountAfterFeesCryptoBaseUnit;
|
|
43
|
+
return bn(buyAmountAfterFeesCryptoBaseUnit)
|
|
44
|
+
.times(10_000)
|
|
45
|
+
.div(bn(10_000).minus(affiliateBps))
|
|
46
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
47
|
+
.toFixed();
|
|
48
|
+
};
|
|
49
|
+
export const getKyberTradeAmounts = ({ input, amountOut, }) => {
|
|
50
|
+
const { sellAsset, buyAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit, affiliateBps } = input;
|
|
51
|
+
const buyAmountAfterFeesCryptoBaseUnit = amountOut;
|
|
52
|
+
const buyAmountBeforeFeesCryptoBaseUnit = getKyberBuyAmountBeforeFees({
|
|
53
|
+
buyAmountAfterFeesCryptoBaseUnit,
|
|
54
|
+
affiliateBps,
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
rate: getInputOutputRate({
|
|
58
|
+
sellAmountCryptoBaseUnit: sellAmountIncludingProtocolFeesCryptoBaseUnit,
|
|
59
|
+
buyAmountCryptoBaseUnit: buyAmountAfterFeesCryptoBaseUnit,
|
|
60
|
+
sellAsset,
|
|
61
|
+
buyAsset,
|
|
62
|
+
}),
|
|
63
|
+
buyAmountBeforeFeesCryptoBaseUnit,
|
|
64
|
+
buyAmountAfterFeesCryptoBaseUnit,
|
|
65
|
+
affiliateFee: buildAffiliateFee({
|
|
66
|
+
strategy: 'buy_asset',
|
|
67
|
+
affiliateBps,
|
|
68
|
+
sellAsset,
|
|
69
|
+
buyAsset,
|
|
70
|
+
sellAmountCryptoBaseUnit: sellAmountIncludingProtocolFeesCryptoBaseUnit,
|
|
71
|
+
buyAmountCryptoBaseUnit: buyAmountBeforeFeesCryptoBaseUnit,
|
|
72
|
+
}),
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
const getKyberCodeError = ({ code, message, requestId }) => {
|
|
76
|
+
const tradeQuoteError = (() => {
|
|
77
|
+
switch (code) {
|
|
78
|
+
case 4008:
|
|
79
|
+
case 4009:
|
|
80
|
+
case 4010:
|
|
81
|
+
return TradeQuoteError.NoRouteFound;
|
|
82
|
+
case 4011:
|
|
83
|
+
case 4221:
|
|
84
|
+
return TradeQuoteError.UnsupportedTradePair;
|
|
85
|
+
case 4005:
|
|
86
|
+
case 4007:
|
|
87
|
+
return TradeQuoteError.SellAmountBelowTradeFee;
|
|
88
|
+
default:
|
|
89
|
+
return TradeQuoteError.QueryFailed;
|
|
90
|
+
}
|
|
91
|
+
})();
|
|
92
|
+
return makeSwapErrorRight({
|
|
93
|
+
message: `KyberSwap request failed: ${message}`,
|
|
94
|
+
code: tradeQuoteError,
|
|
95
|
+
details: { code, requestId },
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const isKyberErrorResponse = (value) => typeof value === 'object' &&
|
|
99
|
+
value !== null &&
|
|
100
|
+
'code' in value &&
|
|
101
|
+
typeof value.code === 'number' &&
|
|
102
|
+
'message' in value &&
|
|
103
|
+
typeof value.message === 'string';
|
|
104
|
+
export const getKyberRequestError = (error) => {
|
|
105
|
+
const { cause } = error;
|
|
106
|
+
if (!axios.isAxiosError(cause))
|
|
107
|
+
return error;
|
|
108
|
+
const status = cause.response?.status;
|
|
109
|
+
if (status === 429) {
|
|
110
|
+
return makeSwapErrorRight({
|
|
111
|
+
message: 'KyberSwap rate limit exceeded',
|
|
112
|
+
code: TradeQuoteError.RateLimitExceeded,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (status === 404) {
|
|
116
|
+
return makeSwapErrorRight({
|
|
117
|
+
message: 'KyberSwap does not serve this chain',
|
|
118
|
+
code: TradeQuoteError.UnsupportedChain,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const body = cause.response?.data;
|
|
122
|
+
if (isKyberErrorResponse(body))
|
|
123
|
+
return getKyberCodeError(body);
|
|
124
|
+
return makeSwapErrorRight({
|
|
125
|
+
message: `KyberSwap request failed with status ${status}`,
|
|
126
|
+
code: TradeQuoteError.QueryFailed,
|
|
127
|
+
cause,
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
const isPinnedRouter = (routerAddress) => isAddress(routerAddress) && isAddressEqual(routerAddress, KYBER_ROUTER_ADDRESS);
|
|
131
|
+
const unpinnedRouterError = (routerAddress) => invalidResponse(`KyberSwap router ${routerAddress} is not the pinned router`);
|
|
132
|
+
export const validateKyberRoute = (response, feeParams) => {
|
|
133
|
+
if (response.code !== 0)
|
|
134
|
+
return Err(getKyberCodeError(response));
|
|
135
|
+
if (!response.data)
|
|
136
|
+
return Err(invalidResponse('KyberSwap returned no route'));
|
|
137
|
+
const { routeSummary, routerAddress } = response.data;
|
|
138
|
+
if (!isPinnedRouter(routerAddress))
|
|
139
|
+
return Err(unpinnedRouterError(routerAddress));
|
|
140
|
+
// Kyber skips the integrator fee on wrap and unwrap routes, so reject them rather than swap fee-free
|
|
141
|
+
if (feeParams && routeSummary.extraFee.feeAmount === '') {
|
|
142
|
+
return Err(makeSwapErrorRight({
|
|
143
|
+
message: 'Wrapping or unwrapping the native asset is not supported through KyberSwap',
|
|
144
|
+
code: TradeQuoteError.UnsupportedTradePair,
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
return Ok(routeSummary);
|
|
148
|
+
};
|
|
149
|
+
export const validateKyberBuild = (response) => {
|
|
150
|
+
if (response.code !== 0)
|
|
151
|
+
return Err(getKyberCodeError(response));
|
|
152
|
+
if (!response.data)
|
|
153
|
+
return Err(invalidResponse('KyberSwap returned no transaction'));
|
|
154
|
+
const { routerAddress } = response.data;
|
|
155
|
+
if (!isPinnedRouter(routerAddress))
|
|
156
|
+
return Err(unpinnedRouterError(routerAddress));
|
|
157
|
+
return Ok(response.data);
|
|
158
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { KnownChainIds } from '@shapeshiftoss/types';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { TradeQuoteError } from '../../../types.js';
|
|
4
|
+
import { KYBER_ROUTER_ADDRESS } from './constants.js';
|
|
5
|
+
import { getKyberBuyAmountBeforeFees, getKyberFeeParams, validateKyberBuild, validateKyberRoute, } from './helpers.js';
|
|
6
|
+
const TREASURY = '0xF5AA59151bE6515C4Ca68A0282CF68B3eA4846fC';
|
|
7
|
+
const UNPINNED_ROUTER = '0x1111111111111111111111111111111111111111';
|
|
8
|
+
const EMPTY_EXTRA_FEE = {
|
|
9
|
+
feeAmount: '',
|
|
10
|
+
chargeFeeBy: '',
|
|
11
|
+
isInBps: false,
|
|
12
|
+
feeReceiver: '',
|
|
13
|
+
};
|
|
14
|
+
const hyperEvmFeeParams = getKyberFeeParams({
|
|
15
|
+
chainId: KnownChainIds.HyperEvmMainnet,
|
|
16
|
+
affiliateBps: '60',
|
|
17
|
+
});
|
|
18
|
+
const ROUTE = {
|
|
19
|
+
amountOut: '255332541',
|
|
20
|
+
gas: '679101',
|
|
21
|
+
gasPrice: '100000000',
|
|
22
|
+
extraFee: {
|
|
23
|
+
feeAmount: '60',
|
|
24
|
+
chargeFeeBy: 'currency_out',
|
|
25
|
+
isInBps: true,
|
|
26
|
+
feeReceiver: TREASURY.toLowerCase(),
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
const ROUTES_RESPONSE = {
|
|
30
|
+
code: 0,
|
|
31
|
+
message: 'successfully',
|
|
32
|
+
data: { routeSummary: ROUTE, routerAddress: KYBER_ROUTER_ADDRESS },
|
|
33
|
+
requestId: 'route-request',
|
|
34
|
+
};
|
|
35
|
+
const BUILD_RESPONSE = {
|
|
36
|
+
code: 0,
|
|
37
|
+
message: 'successfully',
|
|
38
|
+
data: {
|
|
39
|
+
amountOut: '255332539',
|
|
40
|
+
gas: '679101',
|
|
41
|
+
data: '0xe21fd0e9',
|
|
42
|
+
routerAddress: KYBER_ROUTER_ADDRESS,
|
|
43
|
+
transactionValue: '3000000000000000000',
|
|
44
|
+
},
|
|
45
|
+
requestId: 'build-request',
|
|
46
|
+
};
|
|
47
|
+
describe('getKyberFeeParams', () => {
|
|
48
|
+
it('sends no fee for a fee-free swap', () => {
|
|
49
|
+
expect(getKyberFeeParams({ chainId: KnownChainIds.HyperEvmMainnet, affiliateBps: '0' })).toBeUndefined();
|
|
50
|
+
});
|
|
51
|
+
it('charges the output in bps to the chain treasury', () => {
|
|
52
|
+
expect(hyperEvmFeeParams).toEqual({
|
|
53
|
+
feeAmount: '60',
|
|
54
|
+
chargeFeeBy: 'currency_out',
|
|
55
|
+
isInBps: true,
|
|
56
|
+
feeReceiver: TREASURY,
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('getKyberBuyAmountBeforeFees', () => {
|
|
61
|
+
it.each([
|
|
62
|
+
['255332541', '60', '256873783'],
|
|
63
|
+
['54334339666759063267443', '60', '54662313548047347351552'],
|
|
64
|
+
['123', '0', '123'],
|
|
65
|
+
])('grosses up %s at %s bps to %s', (buyAmountAfterFeesCryptoBaseUnit, affiliateBps, gross) => {
|
|
66
|
+
expect(getKyberBuyAmountBeforeFees({ buyAmountAfterFeesCryptoBaseUnit, affiliateBps })).toBe(gross);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('validateKyberRoute', () => {
|
|
70
|
+
const validate = (summaryOverrides, dataOverrides = {}, feeParams = hyperEvmFeeParams) => validateKyberRoute({
|
|
71
|
+
...ROUTES_RESPONSE,
|
|
72
|
+
data: {
|
|
73
|
+
...ROUTES_RESPONSE.data,
|
|
74
|
+
routeSummary: { ...ROUTE, ...summaryOverrides },
|
|
75
|
+
...dataOverrides,
|
|
76
|
+
},
|
|
77
|
+
}, feeParams);
|
|
78
|
+
it('returns the route summary', () => {
|
|
79
|
+
expect(validateKyberRoute(ROUTES_RESPONSE, hyperEvmFeeParams).unwrap()).toBe(ROUTE);
|
|
80
|
+
});
|
|
81
|
+
it('rejects an unpinned router', () => {
|
|
82
|
+
expect(validate({}, { routerAddress: UNPINNED_ROUTER }).unwrapErr().code).toBe(TradeQuoteError.InvalidResponse);
|
|
83
|
+
});
|
|
84
|
+
it('rejects a route that dropped the requested fee', () => {
|
|
85
|
+
expect(validate({ extraFee: EMPTY_EXTRA_FEE }).unwrapErr().code).toBe(TradeQuoteError.UnsupportedTradePair);
|
|
86
|
+
});
|
|
87
|
+
it('accepts a fee-free route when no fee was requested', () => {
|
|
88
|
+
expect(validateKyberRoute({
|
|
89
|
+
...ROUTES_RESPONSE,
|
|
90
|
+
data: {
|
|
91
|
+
...ROUTES_RESPONSE.data,
|
|
92
|
+
routeSummary: { ...ROUTE, extraFee: EMPTY_EXTRA_FEE },
|
|
93
|
+
},
|
|
94
|
+
}, undefined).isOk()).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe('validateKyberBuild', () => {
|
|
98
|
+
it('returns the build data', () => {
|
|
99
|
+
expect(validateKyberBuild(BUILD_RESPONSE).unwrap()).toBe(BUILD_RESPONSE.data);
|
|
100
|
+
});
|
|
101
|
+
it('rejects an unpinned router', () => {
|
|
102
|
+
const result = validateKyberBuild({
|
|
103
|
+
...BUILD_RESPONSE,
|
|
104
|
+
data: { ...BUILD_RESPONSE.data, routerAddress: UNPINNED_ROUTER },
|
|
105
|
+
});
|
|
106
|
+
expect(result.unwrapErr().code).toBe(TradeQuoteError.InvalidResponse);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const kyberService: {
|
|
2
|
+
get: <T = any>(url: string, config?: import("axios").AxiosRequestConfig<any> | undefined) => Promise<import("@sniptt/monads").Result<import("axios").AxiosResponse<T, any, {}>, import("../../../index.js").SwapErrorRight>>;
|
|
3
|
+
post: <T_1 = any>(url: string, data: any, config?: import("axios").AxiosRequestConfig<any> | undefined) => Promise<import("@sniptt/monads").Result<import("axios").AxiosResponse<T_1, any, {}>, import("../../../index.js").SwapErrorRight>>;
|
|
4
|
+
delete: <T_2 = any>(url: string, data: any, config?: import("axios").AxiosRequestConfig<any> | undefined) => Promise<import("@sniptt/monads").Result<import("axios").AxiosResponse<T_2, any, {}>, import("../../../index.js").SwapErrorRight>>;
|
|
5
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { executeEvmTransaction, executeNearTransaction, executeSolanaTransaction, executeStarknetTransaction, executeSuiTransaction, executeTonTransaction, executeTronTransaction, } from '../../utils/index.js';
|
|
1
|
+
import { executeAptosTransaction, executeEvmTransaction, executeNearTransaction, executeSolanaTransaction, executeStarknetTransaction, executeSuiTransaction, executeTonTransaction, executeTronTransaction, } from '../../utils/index.js';
|
|
2
2
|
export const nearIntentsSwapper = {
|
|
3
3
|
supportsExternalPayment: true,
|
|
4
4
|
executeEvmTransaction,
|
|
@@ -8,6 +8,7 @@ export const nearIntentsSwapper = {
|
|
|
8
8
|
executeSuiTransaction,
|
|
9
9
|
executeNearTransaction,
|
|
10
10
|
executeTonTransaction,
|
|
11
|
+
executeAptosTransaction,
|
|
11
12
|
executeUtxoTransaction: (txToSign, { signAndBroadcastTransaction }) => {
|
|
12
13
|
return signAndBroadcastTransaction(txToSign);
|
|
13
14
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { contractAddressOrUndefined } from '@shapeshiftoss/utils';
|
|
2
2
|
import { createDefaultStatusResponse, getExecutableTradeStep, getSwapMetadata, isExecutableTradeQuote, } from '../../utils/index.js';
|
|
3
|
+
import { getAptosTransactionFees, getUnsignedAptosTransaction } from '../../utils/aptos/index.js';
|
|
3
4
|
import { getEvmTransactionFees, getUnsignedEvmTransaction } from '../../utils/evm/index.js';
|
|
4
5
|
import { getSolanaTransactionFees, getUnsignedSolanaTransaction } from '../../utils/solana/index.js';
|
|
5
6
|
import { getTronTransactionFees, getUnsignedTronTransaction } from '../../utils/tron/index.js';
|
|
@@ -84,7 +85,7 @@ export const nearIntentsApi = {
|
|
|
84
85
|
}
|
|
85
86
|
return Promise.resolve(step.feeData.networkFeeCryptoBaseUnit);
|
|
86
87
|
},
|
|
87
|
-
getUnsignedStarknetTransaction: async ({ stepIndex, tradeQuote, from, assertGetStarknetChainAdapter, }) => {
|
|
88
|
+
getUnsignedStarknetTransaction: async ({ stepIndex, tradeQuote, from, callsOnly, assertGetStarknetChainAdapter, }) => {
|
|
88
89
|
if (!isExecutableTradeQuote(tradeQuote))
|
|
89
90
|
throw new Error('Unable to execute a trade rate quote');
|
|
90
91
|
const step = getExecutableTradeStep(tradeQuote, stepIndex);
|
|
@@ -94,24 +95,20 @@ export const nearIntentsApi = {
|
|
|
94
95
|
const to = depositAddress;
|
|
95
96
|
const value = step.sellAmountIncludingProtocolFeesCryptoBaseUnit;
|
|
96
97
|
const tokenContractAddress = contractAddressOrUndefined(sellAsset.assetId);
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
tokenContractAddress,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
});
|
|
98
|
+
const maxFee = callsOnly
|
|
99
|
+
? undefined
|
|
100
|
+
: (await adapter.getFeeData({
|
|
101
|
+
to,
|
|
102
|
+
value,
|
|
103
|
+
chainSpecific: { from, tokenContractAddress },
|
|
104
|
+
sendMax: false,
|
|
105
|
+
})).fast.chainSpecific.maxFee;
|
|
106
106
|
return adapter.buildSendApiTransaction({
|
|
107
107
|
from,
|
|
108
108
|
to,
|
|
109
109
|
value,
|
|
110
110
|
accountNumber,
|
|
111
|
-
chainSpecific: {
|
|
112
|
-
tokenContractAddress,
|
|
113
|
-
maxFee: fast.chainSpecific.maxFee,
|
|
114
|
-
},
|
|
111
|
+
chainSpecific: { tokenContractAddress, maxFee, callsOnly },
|
|
115
112
|
});
|
|
116
113
|
},
|
|
117
114
|
getStarknetTransactionFees: ({ tradeQuote, stepIndex }) => {
|
|
@@ -153,6 +150,8 @@ export const nearIntentsApi = {
|
|
|
153
150
|
}
|
|
154
151
|
return Promise.resolve(step.feeData.networkFeeCryptoBaseUnit);
|
|
155
152
|
},
|
|
153
|
+
getUnsignedAptosTransaction,
|
|
154
|
+
getAptosTransactionFees,
|
|
156
155
|
checkTradeStatus: async ({ config, swap }) => {
|
|
157
156
|
if (!swap)
|
|
158
157
|
throw new Error('Missing swap');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { KnownChainIds } from '@shapeshiftoss/types';
|
|
2
|
-
import type { GetEvmTradeQuoteInput, GetEvmTradeRateInput, GetNearTradeQuoteInput, GetNearTradeRateInput, GetSolanaTradeQuoteInput, GetSolanaTradeRateInput, GetStarknetTradeQuoteInput, GetStarknetTradeRateInput, GetSuiTradeQuoteInput, GetSuiTradeRateInput, GetTonTradeQuoteInput, GetTonTradeRateInput, GetTronTradeQuoteInput, GetTronTradeRateInput, GetUtxoTradeQuoteInput, GetUtxoTradeRateInput, WithExactBuyAmount } from '../../types.js';
|
|
3
|
-
export type NearIntentsTradeQuoteInput = GetEvmTradeQuoteInput | GetUtxoTradeQuoteInput | GetSolanaTradeQuoteInput | GetTronTradeQuoteInput | GetSuiTradeQuoteInput | GetStarknetTradeQuoteInput | GetNearTradeQuoteInput | GetTonTradeQuoteInput;
|
|
4
|
-
export type NearIntentsTradeRateInput = GetEvmTradeRateInput | GetUtxoTradeRateInput | GetSolanaTradeRateInput | GetTronTradeRateInput | GetSuiTradeRateInput | GetStarknetTradeRateInput | GetNearTradeRateInput | GetTonTradeRateInput;
|
|
2
|
+
import type { GetAptosTradeQuoteInput, GetAptosTradeRateInput, GetEvmTradeQuoteInput, GetEvmTradeRateInput, GetNearTradeQuoteInput, GetNearTradeRateInput, GetSolanaTradeQuoteInput, GetSolanaTradeRateInput, GetStarknetTradeQuoteInput, GetStarknetTradeRateInput, GetSuiTradeQuoteInput, GetSuiTradeRateInput, GetTonTradeQuoteInput, GetTonTradeRateInput, GetTronTradeQuoteInput, GetTronTradeRateInput, GetUtxoTradeQuoteInput, GetUtxoTradeRateInput, WithExactBuyAmount } from '../../types.js';
|
|
3
|
+
export type NearIntentsTradeQuoteInput = GetEvmTradeQuoteInput | GetUtxoTradeQuoteInput | GetSolanaTradeQuoteInput | GetTronTradeQuoteInput | GetSuiTradeQuoteInput | GetStarknetTradeQuoteInput | GetNearTradeQuoteInput | GetTonTradeQuoteInput | GetAptosTradeQuoteInput;
|
|
4
|
+
export type NearIntentsTradeRateInput = GetEvmTradeRateInput | GetUtxoTradeRateInput | GetSolanaTradeRateInput | GetTronTradeRateInput | GetSuiTradeRateInput | GetStarknetTradeRateInput | GetNearTradeRateInput | GetTonTradeRateInput | GetAptosTradeRateInput;
|
|
5
5
|
export type NearIntentsExactOutputTradeQuoteInput = WithExactBuyAmount<NearIntentsTradeQuoteInput>;
|
|
6
6
|
export type NearIntentsExactOutputTradeRateInput = WithExactBuyAmount<NearIntentsTradeRateInput>;
|
|
7
7
|
export type NearIntentsMetadata = {
|
|
@@ -11,6 +11,6 @@ export type NearIntentsMetadata = {
|
|
|
11
11
|
};
|
|
12
12
|
export { QuoteRequest } from '@defuse-protocol/one-click-sdk-typescript';
|
|
13
13
|
export type { GetExecutionStatusResponse, QuoteResponse, TokenResponse, } from '@defuse-protocol/one-click-sdk-typescript';
|
|
14
|
-
export declare const nearIntentsSupportedChainIds: readonly [KnownChainIds.EthereumMainnet, KnownChainIds.ArbitrumMainnet, KnownChainIds.BaseMainnet, KnownChainIds.GnosisMainnet, KnownChainIds.BnbSmartChainMainnet, KnownChainIds.PolygonMainnet, KnownChainIds.AvalancheMainnet, KnownChainIds.OptimismMainnet, KnownChainIds.BitcoinMainnet, KnownChainIds.BitcoinCashMainnet, KnownChainIds.DogecoinMainnet, KnownChainIds.ZcashMainnet, KnownChainIds.SolanaMainnet, KnownChainIds.TronMainnet, KnownChainIds.SuiMainnet, KnownChainIds.StarknetMainnet, KnownChainIds.MonadMainnet, KnownChainIds.NearMainnet, KnownChainIds.PlasmaMainnet, KnownChainIds.TonMainnet];
|
|
14
|
+
export declare const nearIntentsSupportedChainIds: readonly [KnownChainIds.EthereumMainnet, KnownChainIds.ArbitrumMainnet, KnownChainIds.BaseMainnet, KnownChainIds.GnosisMainnet, KnownChainIds.BnbSmartChainMainnet, KnownChainIds.PolygonMainnet, KnownChainIds.AvalancheMainnet, KnownChainIds.OptimismMainnet, KnownChainIds.BitcoinMainnet, KnownChainIds.BitcoinCashMainnet, KnownChainIds.DogecoinMainnet, KnownChainIds.ZcashMainnet, KnownChainIds.SolanaMainnet, KnownChainIds.TronMainnet, KnownChainIds.SuiMainnet, KnownChainIds.StarknetMainnet, KnownChainIds.MonadMainnet, KnownChainIds.NearMainnet, KnownChainIds.PlasmaMainnet, KnownChainIds.TonMainnet, KnownChainIds.AptosMainnet];
|
|
15
15
|
export type NearIntentsSupportedChainId = (typeof nearIntentsSupportedChainIds)[number];
|
|
16
16
|
export declare const chainIdToNearIntentsChain: Record<NearIntentsSupportedChainId, string>;
|
|
@@ -21,6 +21,7 @@ export const nearIntentsSupportedChainIds = [
|
|
|
21
21
|
KnownChainIds.NearMainnet,
|
|
22
22
|
KnownChainIds.PlasmaMainnet,
|
|
23
23
|
KnownChainIds.TonMainnet,
|
|
24
|
+
KnownChainIds.AptosMainnet,
|
|
24
25
|
];
|
|
25
26
|
export const chainIdToNearIntentsChain = {
|
|
26
27
|
[KnownChainIds.EthereumMainnet]: 'eth',
|
|
@@ -43,4 +44,5 @@ export const chainIdToNearIntentsChain = {
|
|
|
43
44
|
[KnownChainIds.MonadMainnet]: 'monad',
|
|
44
45
|
[KnownChainIds.NearMainnet]: 'near',
|
|
45
46
|
[KnownChainIds.TonMainnet]: 'ton',
|
|
47
|
+
[KnownChainIds.AptosMainnet]: 'aptos',
|
|
46
48
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CHAIN_NAMESPACE, fromAssetId, fromChainId } from '@shapeshiftoss/caip';
|
|
2
|
-
import { evm } from '@shapeshiftoss/chain-adapters';
|
|
2
|
+
import { aptos, evm } from '@shapeshiftoss/chain-adapters';
|
|
3
3
|
import { bn, contractAddressOrUndefined } from '@shapeshiftoss/utils';
|
|
4
4
|
import { Err, Ok } from '@sniptt/monads';
|
|
5
5
|
import { TradeQuoteError } from '../../../types.js';
|
|
6
6
|
import { makeNetworkFeeEstimationFailedErr, makeSwapErrorRight } from '../../../utils/index.js';
|
|
7
|
+
import { APTOS_PLACEHOLDER_ADDRESS, APTOS_RATE_SIMULATION_VALUE } from '../../../utils/aptos/index.js';
|
|
7
8
|
import { EVM_PLACEHOLDER_ADDRESS, getEvmNetworkFeeCryptoBaseUnit } from '../../../utils/evm/index.js';
|
|
8
9
|
import { isNativeEvmAsset } from '../../../utils/helpers.js';
|
|
9
10
|
import { ATA_RENT_LAMPORTS, getSolanaNetworkFeeCryptoBaseUnit, SOLANA_PLACEHOLDER_ADDRESS, withComputeUnitLimit, } from '../../../utils/solana/index.js';
|
|
@@ -218,6 +219,33 @@ export async function getNearIntentsStepData(args) {
|
|
|
218
219
|
const stepData = { networkFeeCryptoBaseUnit: fast.txFee };
|
|
219
220
|
return Ok(stepData);
|
|
220
221
|
}
|
|
222
|
+
case CHAIN_NAMESPACE.Aptos: {
|
|
223
|
+
const adapter = deps.assertGetAptosChainAdapter(sellAsset.chainId);
|
|
224
|
+
if (type === 'rate') {
|
|
225
|
+
const { fast } = await adapter.getFeeData({
|
|
226
|
+
to: depositAddress,
|
|
227
|
+
value: APTOS_RATE_SIMULATION_VALUE,
|
|
228
|
+
chainSpecific: { from: from ?? APTOS_PLACEHOLDER_ADDRESS, contractAddress },
|
|
229
|
+
});
|
|
230
|
+
const stepData = { networkFeeCryptoBaseUnit: fast.txFee };
|
|
231
|
+
return Ok(stepData);
|
|
232
|
+
}
|
|
233
|
+
const { fast } = await adapter.getFeeData({
|
|
234
|
+
to: depositAddress,
|
|
235
|
+
value: sellAmountCryptoBaseUnit,
|
|
236
|
+
chainSpecific: { from, contractAddress },
|
|
237
|
+
});
|
|
238
|
+
const stepData = {
|
|
239
|
+
transactionData: {
|
|
240
|
+
type: 'aptos',
|
|
241
|
+
payload: aptos.getSerializedTransferPayload(depositAddress, sellAmountCryptoBaseUnit, contractAddress),
|
|
242
|
+
gasUnitPrice: fast.chainSpecific.gasUnitPrice,
|
|
243
|
+
maxGasAmount: fast.chainSpecific.maxGasAmount,
|
|
244
|
+
},
|
|
245
|
+
networkFeeCryptoBaseUnit: fast.txFee,
|
|
246
|
+
};
|
|
247
|
+
return Ok(stepData);
|
|
248
|
+
}
|
|
221
249
|
default:
|
|
222
250
|
return Err(makeSwapErrorRight({
|
|
223
251
|
message: `[getNearIntentsStepData] unsupported chain namespace: ${chainNamespace}`,
|
|
@@ -36,7 +36,7 @@ export const getNearIntentsAsset = ({ nearNetwork, contractAddress, }) => {
|
|
|
36
36
|
return `nep141:${nearNetwork}-${contractAddress.toLowerCase()}.omft.near`;
|
|
37
37
|
};
|
|
38
38
|
const NEP245_CHAINS = ['bsc', 'pol', 'avax', 'op', 'tron', 'monad', 'plasma'];
|
|
39
|
-
const TOKEN_LOOKUP_CHAINS = ['sui', 'starknet', 'ton'];
|
|
39
|
+
const TOKEN_LOOKUP_CHAINS = ['sui', 'starknet', 'ton', 'aptos'];
|
|
40
40
|
const NEAR_CHAIN = 'near';
|
|
41
41
|
const BTC_CHAIN = 'btc';
|
|
42
42
|
const WNEAR_CONTRACT_ADDRESS = 'wrap.near';
|
|
@@ -68,7 +68,7 @@ export const assetToNearIntentsAsset = async (asset) => {
|
|
|
68
68
|
});
|
|
69
69
|
return match?.assetId ?? null;
|
|
70
70
|
}
|
|
71
|
-
// NEP-245 chains (BSC, Polygon, Avalanche, Optimism, TRON, Monad), Token lookup chains (Sui, Starknet), and Solana require token lookup
|
|
71
|
+
// NEP-245 chains (BSC, Polygon, Avalanche, Optimism, TRON, Monad), Token lookup chains (Sui, Starknet, TON, Aptos), and Solana require token lookup
|
|
72
72
|
// Asset IDs use hashed format that can't be generated from contract addresses
|
|
73
73
|
const requiresLookup = isNep245Chain(nearNetwork) || isTokenLookupChain(nearNetwork) || asset.chainId === solanaChainId;
|
|
74
74
|
if (requiresLookup) {
|
|
@@ -1,53 +1,47 @@
|
|
|
1
1
|
import { fromChainId } from '@shapeshiftoss/caip';
|
|
2
|
-
import { bnOrZero } from '@shapeshiftoss/utils';
|
|
3
2
|
import { Err, Ok } from '@sniptt/monads';
|
|
4
3
|
import { makeNetworkFeeEstimationFailedErr } from '../../../utils/index.js';
|
|
5
|
-
import {
|
|
4
|
+
import { getEvmNetworkFeeCryptoBaseUnit, getEvmRateNetworkFeeCryptoBaseUnit, } from '../../../utils/evm/index.js';
|
|
6
5
|
import { fetchPortalsTradeEstimate } from './fetchPortalsTradeOrder.js';
|
|
7
6
|
export async function getPortalsStepData(args) {
|
|
8
7
|
const { tx, sellAsset, sellAmountCryptoBaseUnit, spenderAddress, input, deps } = args;
|
|
9
8
|
const adapter = deps.assertGetEvmChainAdapter(sellAsset.chainId);
|
|
10
9
|
const supportsEIP1559 = 'supportsEIP1559' in input ? input.supportsEIP1559 : false;
|
|
10
|
+
const transactionData = {
|
|
11
|
+
type: 'evm',
|
|
12
|
+
chainId: Number(fromChainId(sellAsset.chainId).chainReference),
|
|
13
|
+
to: tx.to,
|
|
14
|
+
data: tx.data,
|
|
15
|
+
value: tx.value,
|
|
16
|
+
};
|
|
17
|
+
const stateOverride = {
|
|
18
|
+
sellAsset,
|
|
19
|
+
sellAmountCryptoBaseUnit,
|
|
20
|
+
spenderAddress,
|
|
21
|
+
};
|
|
11
22
|
if (args.type === 'rate') {
|
|
23
|
+
const getEstimateEndpointGasLimit = async () => {
|
|
24
|
+
const quoteEstimateResponse = await fetchPortalsTradeEstimate({
|
|
25
|
+
inputToken: args.inputToken,
|
|
26
|
+
outputToken: args.outputToken,
|
|
27
|
+
inputAmount: args.inputAmount,
|
|
28
|
+
slippageTolerancePercentage: args.slippageTolerancePercentage,
|
|
29
|
+
swapperConfig: deps.config,
|
|
30
|
+
});
|
|
31
|
+
return quoteEstimateResponse.context.gasLimit.toString();
|
|
32
|
+
};
|
|
12
33
|
try {
|
|
13
|
-
//
|
|
14
|
-
|
|
15
|
-
const gasLimit = await (async () => {
|
|
16
|
-
try {
|
|
17
|
-
const gasLimit = await estimateGasWithStateOverride({
|
|
18
|
-
sellAsset,
|
|
19
|
-
sellAmountCryptoBaseUnit,
|
|
20
|
-
from: tx.from,
|
|
21
|
-
spenderAddress,
|
|
22
|
-
to: tx.to,
|
|
23
|
-
data: tx.data,
|
|
24
|
-
value: tx.value,
|
|
25
|
-
});
|
|
26
|
-
return gasLimit;
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
// Portals only carry a tx gas limit on the bridge routes their estimate endpoint zeroes
|
|
30
|
-
const { gasLimit: txGasLimit } = tx;
|
|
31
|
-
if (txGasLimit && bnOrZero(txGasLimit).gt(0))
|
|
32
|
-
return txGasLimit;
|
|
33
|
-
const quoteEstimateResponse = await fetchPortalsTradeEstimate({
|
|
34
|
-
inputToken: args.inputToken,
|
|
35
|
-
outputToken: args.outputToken,
|
|
36
|
-
inputAmount: args.inputAmount,
|
|
37
|
-
slippageTolerancePercentage: args.slippageTolerancePercentage,
|
|
38
|
-
swapperConfig: deps.config,
|
|
39
|
-
});
|
|
40
|
-
const estimatedGasLimit = quoteEstimateResponse.context.gasLimit.toString();
|
|
41
|
-
if (bnOrZero(estimatedGasLimit).lte(0))
|
|
42
|
-
throw new Error('no Portals gas limit');
|
|
43
|
-
return estimatedGasLimit;
|
|
44
|
-
}
|
|
45
|
-
})();
|
|
46
|
-
const networkFeeCryptoBaseUnit = await getEvmNetworkFeeCryptoBaseUnit({
|
|
34
|
+
// Portals only set a tx gas limit on bridge routes, where their estimate endpoint is zero
|
|
35
|
+
const networkFeeCryptoBaseUnit = await getEvmRateNetworkFeeCryptoBaseUnit({
|
|
47
36
|
adapter,
|
|
48
37
|
supportsEIP1559,
|
|
49
|
-
gasLimit,
|
|
50
|
-
|
|
38
|
+
providerGasLimit: tx.gasLimit,
|
|
39
|
+
simulation: { transactionData, from: tx.from, stateOverride },
|
|
40
|
+
}).catch(async () => getEvmRateNetworkFeeCryptoBaseUnit({
|
|
41
|
+
adapter,
|
|
42
|
+
supportsEIP1559,
|
|
43
|
+
providerGasLimit: await getEstimateEndpointGasLimit(),
|
|
44
|
+
}));
|
|
51
45
|
const stepData = { networkFeeCryptoBaseUnit };
|
|
52
46
|
return Ok(stepData);
|
|
53
47
|
}
|
|
@@ -55,27 +49,14 @@ export async function getPortalsStepData(args) {
|
|
|
55
49
|
return Err(makeNetworkFeeEstimationFailedErr('getPortalsStepData', error));
|
|
56
50
|
}
|
|
57
51
|
}
|
|
58
|
-
const transactionData = {
|
|
59
|
-
type: 'evm',
|
|
60
|
-
chainId: Number(fromChainId(sellAsset.chainId).chainReference),
|
|
61
|
-
to: tx.to,
|
|
62
|
-
data: tx.data,
|
|
63
|
-
value: tx.value,
|
|
64
|
-
// Portals simulate and pad their gas limit when the order was validated, so no additional
|
|
65
|
-
// buffer - an unvalidated order carries no gas limit and estimates below instead
|
|
66
|
-
gasLimit: tx.gasLimit,
|
|
67
|
-
};
|
|
68
52
|
try {
|
|
69
53
|
const networkFeeCryptoBaseUnit = await getEvmNetworkFeeCryptoBaseUnit({
|
|
70
54
|
adapter,
|
|
71
55
|
transactionData,
|
|
72
56
|
from: args.from,
|
|
73
57
|
supportsEIP1559,
|
|
74
|
-
stateOverride
|
|
75
|
-
|
|
76
|
-
sellAmountCryptoBaseUnit,
|
|
77
|
-
spenderAddress,
|
|
78
|
-
},
|
|
58
|
+
stateOverride,
|
|
59
|
+
providerGasLimit: tx.gasLimit,
|
|
79
60
|
});
|
|
80
61
|
const stepData = { transactionData, networkFeeCryptoBaseUnit };
|
|
81
62
|
return Ok(stepData);
|
|
@@ -45,11 +45,11 @@ const estimateEndpointGasLimit = (gasLimit) => vi.mocked(fetchPortalsTradeEstima
|
|
|
45
45
|
});
|
|
46
46
|
describe('getPortalsStepData rate gas limit', () => {
|
|
47
47
|
beforeEach(() => vi.clearAllMocks());
|
|
48
|
-
it('
|
|
49
|
-
vi.mocked(estimateGasWithStateOverride).mockRejectedValue(new Error('execution reverted'));
|
|
48
|
+
it('prices the order gas limit on bridge routes without simulating', async () => {
|
|
50
49
|
estimateEndpointGasLimit(0);
|
|
51
50
|
const actual = await rate(tx('76384'));
|
|
52
51
|
expect(actual.unwrap()).toEqual({ networkFeeCryptoBaseUnit: '76384000000000' });
|
|
52
|
+
expect(estimateGasWithStateOverride).not.toHaveBeenCalled();
|
|
53
53
|
expect(fetchPortalsTradeEstimate).not.toHaveBeenCalled();
|
|
54
54
|
});
|
|
55
55
|
it('falls back to the estimate endpoint when the order carries no gas limit', async () => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { abstractChainId, arbitrumChainId, avalancheChainId, baseChainId, berachainChainId, blastChainId, bobChainId, bscChainId, btcChainId, celoChainId, cronosChainId, ethChainId, etherealChainId, flowEvmChainId, gnosisChainId, hemiChainId, hyperEvmChainId, inkChainId, katanaChainId, lineaChainId, mantleChainId, megaethChainId, modeChainId, monadChainId, optimismChainId, plasmaChainId, plumeChainId, polygonChainId, robinhoodChainId, scrollChainId, seiChainId, solanaChainId, soneiumChainId, sonicChainId, storyChainId, tronChainId, unichainChainId, worldChainChainId, zkSyncEraChainId, } from '@shapeshiftoss/caip';
|
|
1
|
+
import { abstractChainId, arbitrumChainId, avalancheChainId, baseChainId, berachainChainId, blastChainId, bobChainId, bscChainId, btcChainId, celoChainId, cronosChainId, elysiumChainId, ethChainId, etherealChainId, flowEvmChainId, gnosisChainId, hemiChainId, hyperEvmChainId, inkChainId, katanaChainId, lineaChainId, mantleChainId, megaethChainId, modeChainId, monadChainId, optimismChainId, plasmaChainId, plumeChainId, polygonChainId, robinhoodChainId, scrollChainId, seiChainId, solanaChainId, soneiumChainId, sonicChainId, storyChainId, tronChainId, unichainChainId, worldChainChainId, zkSyncEraChainId, } from '@shapeshiftoss/caip';
|
|
2
2
|
import invert from 'lodash/invert';
|
|
3
3
|
import { zeroAddress } from 'viem';
|
|
4
4
|
import { abstract, arbitrum, avalanche, base, berachain, blast, bob, bsc, celo, cronos, flowMainnet, gnosis, hemi, hyperEvm, ink, katana, linea, mainnet as ethereum, mantle, megaeth, mode, monad, optimism, plasma, plumeMainnet, polygon, robinhood, scroll, sei, soneium, sonic, story, tron, unichain, worldchain, zksync, } from 'viem/chains';
|
|
@@ -45,6 +45,7 @@ export const chainIdToRelayChainId = {
|
|
|
45
45
|
[seiChainId]: sei.id,
|
|
46
46
|
[abstractChainId]: abstract.id,
|
|
47
47
|
[robinhoodChainId]: robinhood.id,
|
|
48
|
+
[elysiumChainId]: 99901,
|
|
48
49
|
};
|
|
49
50
|
export var RelayStatusMessage;
|
|
50
51
|
(function (RelayStatusMessage) {
|