@shapeshiftoss/swapper 17.7.3 → 17.8.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.
Files changed (124) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/constants.js +35 -26
  3. package/dist/cjs/index.d.ts +1 -0
  4. package/dist/cjs/index.js +1 -0
  5. package/dist/cjs/swappers/ArbitrumBridgeSwapper/getTradeQuote/getTradeQuote.test.js +12 -4
  6. package/dist/cjs/swappers/BebopSwapper/getBebopSolanaTradeRate/getBebopSolanaTradeRate.js +9 -5
  7. package/dist/cjs/swappers/BebopSwapper/getBebopTradeQuote/getBebopTradeQuote.js +1 -9
  8. package/dist/cjs/swappers/BebopSwapper/getBebopTradeRate/getBebopTradeRate.js +9 -13
  9. package/dist/cjs/swappers/BebopSwapper/types.d.ts +64 -78
  10. package/dist/cjs/swappers/BebopSwapper/utils/fetchFromBebop.d.ts +0 -16
  11. package/dist/cjs/swappers/BebopSwapper/utils/fetchFromBebop.js +49 -82
  12. package/dist/cjs/swappers/BobGatewaySwapper/BobGatewaySwapper.d.ts +2 -0
  13. package/dist/cjs/swappers/BobGatewaySwapper/BobGatewaySwapper.js +8 -0
  14. package/dist/cjs/swappers/BobGatewaySwapper/endpoints.d.ts +2 -0
  15. package/dist/cjs/swappers/BobGatewaySwapper/endpoints.js +143 -0
  16. package/dist/cjs/swappers/BobGatewaySwapper/index.d.ts +3 -0
  17. package/dist/cjs/swappers/BobGatewaySwapper/index.js +22 -0
  18. package/dist/cjs/swappers/BobGatewaySwapper/swapperApi/getTradeQuote.d.ts +3 -0
  19. package/dist/cjs/swappers/BobGatewaySwapper/swapperApi/getTradeQuote.js +90 -0
  20. package/dist/cjs/swappers/BobGatewaySwapper/swapperApi/getTradeRate.d.ts +3 -0
  21. package/dist/cjs/swappers/BobGatewaySwapper/swapperApi/getTradeRate.js +73 -0
  22. package/dist/cjs/swappers/BobGatewaySwapper/types.d.ts +20 -0
  23. package/dist/cjs/swappers/BobGatewaySwapper/types.js +2 -0
  24. package/dist/cjs/swappers/BobGatewaySwapper/utils/constants.d.ts +13 -0
  25. package/dist/cjs/swappers/BobGatewaySwapper/utils/constants.js +31 -0
  26. package/dist/cjs/swappers/BobGatewaySwapper/utils/helpers.d.ts +49 -0
  27. package/dist/cjs/swappers/BobGatewaySwapper/utils/helpers.js +314 -0
  28. package/dist/cjs/swappers/ChainflipSwapper/ChainflipSwapper.js +1 -0
  29. package/dist/cjs/swappers/ChainflipSwapper/constants.d.ts +1 -1
  30. package/dist/cjs/swappers/ChainflipSwapper/constants.js +3 -0
  31. package/dist/cjs/swappers/ChainflipSwapper/endpoints.js +20 -0
  32. package/dist/cjs/swappers/ChainflipSwapper/types.d.ts +2 -1
  33. package/dist/cjs/swappers/ChainflipSwapper/types.js +1 -0
  34. package/dist/cjs/swappers/ChainflipSwapper/utils/getQuoteOrRate.js +23 -3
  35. package/dist/cjs/swappers/ChainflipSwapper/utils/helpers.d.ts +2 -2
  36. package/dist/cjs/swappers/ChainflipSwapper/utils/helpers.js +2 -1
  37. package/dist/cjs/swappers/CowSwapper/utils/helpers/helpers.test.js +3 -3
  38. package/dist/cjs/swappers/RelaySwapper/constant.js +1 -1
  39. package/dist/cjs/swappers/SunioSwapper/endpoints.js +19 -36
  40. package/dist/cjs/swappers/SunioSwapper/utils/buildSwapContractCall.d.ts +6 -0
  41. package/dist/cjs/swappers/SunioSwapper/utils/buildSwapContractCall.js +33 -0
  42. package/dist/cjs/swappers/SunioSwapper/utils/buildSwapRouteParameters.js +6 -6
  43. package/dist/cjs/swappers/SunioSwapper/utils/constants.d.ts +2 -0
  44. package/dist/cjs/swappers/SunioSwapper/utils/constants.js +7 -1
  45. package/dist/cjs/swappers/SunioSwapper/utils/estimateSunioNetworkFee.d.ts +12 -0
  46. package/dist/cjs/swappers/SunioSwapper/utils/estimateSunioNetworkFee.js +78 -0
  47. package/dist/cjs/swappers/SunioSwapper/utils/getQuoteOrRate.js +16 -74
  48. package/dist/cjs/swappers/SunioSwapper/utils/getSunioTransactionFees.d.ts +2 -0
  49. package/dist/cjs/swappers/SunioSwapper/utils/getSunioTransactionFees.js +36 -0
  50. package/dist/cjs/swappers/utils/helpers/helpers.js +1 -0
  51. package/dist/cjs/thorchain-utils/getL1RateOrQuote.js +5 -2
  52. package/dist/cjs/thorchain-utils/getQuote.js +27 -29
  53. package/dist/cjs/thorchain-utils/tron/getTronTransactionFees.js +8 -5
  54. package/dist/cjs/thorchain-utils/types.d.ts +1 -1
  55. package/dist/cjs/types.d.ts +10 -3
  56. package/dist/cjs/types.js +5 -0
  57. package/dist/esm/.tsbuildinfo +1 -1
  58. package/dist/esm/constants.js +9 -0
  59. package/dist/esm/index.d.ts +1 -0
  60. package/dist/esm/index.js +1 -0
  61. package/dist/esm/swappers/ArbitrumBridgeSwapper/getTradeQuote/getTradeQuote.test.js +12 -4
  62. package/dist/esm/swappers/BebopSwapper/getBebopSolanaTradeRate/getBebopSolanaTradeRate.js +10 -6
  63. package/dist/esm/swappers/BebopSwapper/getBebopTradeQuote/getBebopTradeQuote.js +1 -9
  64. package/dist/esm/swappers/BebopSwapper/getBebopTradeRate/getBebopTradeRate.js +10 -14
  65. package/dist/esm/swappers/BebopSwapper/types.d.ts +64 -78
  66. package/dist/esm/swappers/BebopSwapper/utils/fetchFromBebop.d.ts +0 -16
  67. package/dist/esm/swappers/BebopSwapper/utils/fetchFromBebop.js +45 -76
  68. package/dist/esm/swappers/BobGatewaySwapper/BobGatewaySwapper.d.ts +2 -0
  69. package/dist/esm/swappers/BobGatewaySwapper/BobGatewaySwapper.js +5 -0
  70. package/dist/esm/swappers/BobGatewaySwapper/endpoints.d.ts +2 -0
  71. package/dist/esm/swappers/BobGatewaySwapper/endpoints.js +140 -0
  72. package/dist/esm/swappers/BobGatewaySwapper/index.d.ts +3 -0
  73. package/dist/esm/swappers/BobGatewaySwapper/index.js +3 -0
  74. package/dist/esm/swappers/BobGatewaySwapper/swapperApi/getTradeQuote.d.ts +3 -0
  75. package/dist/esm/swappers/BobGatewaySwapper/swapperApi/getTradeQuote.js +86 -0
  76. package/dist/esm/swappers/BobGatewaySwapper/swapperApi/getTradeRate.d.ts +3 -0
  77. package/dist/esm/swappers/BobGatewaySwapper/swapperApi/getTradeRate.js +69 -0
  78. package/dist/esm/swappers/BobGatewaySwapper/types.d.ts +20 -0
  79. package/dist/esm/swappers/BobGatewaySwapper/utils/constants.d.ts +13 -0
  80. package/dist/esm/swappers/BobGatewaySwapper/utils/constants.js +27 -0
  81. package/dist/esm/swappers/BobGatewaySwapper/utils/helpers.d.ts +49 -0
  82. package/dist/esm/swappers/BobGatewaySwapper/utils/helpers.js +299 -0
  83. package/dist/esm/swappers/ChainflipSwapper/ChainflipSwapper.js +2 -1
  84. package/dist/esm/swappers/ChainflipSwapper/constants.d.ts +1 -1
  85. package/dist/esm/swappers/ChainflipSwapper/constants.js +4 -1
  86. package/dist/esm/swappers/ChainflipSwapper/endpoints.js +20 -0
  87. package/dist/esm/swappers/ChainflipSwapper/types.d.ts +2 -1
  88. package/dist/esm/swappers/ChainflipSwapper/types.js +1 -0
  89. package/dist/esm/swappers/ChainflipSwapper/utils/getQuoteOrRate.js +24 -4
  90. package/dist/esm/swappers/ChainflipSwapper/utils/helpers.d.ts +2 -2
  91. package/dist/esm/swappers/ChainflipSwapper/utils/helpers.js +2 -1
  92. package/dist/esm/swappers/CowSwapper/utils/helpers/helpers.test.js +3 -3
  93. package/dist/esm/swappers/RelaySwapper/constant.js +1 -1
  94. package/dist/esm/swappers/SunioSwapper/endpoints.js +19 -36
  95. package/dist/esm/swappers/SunioSwapper/utils/buildSwapContractCall.d.ts +6 -0
  96. package/dist/esm/swappers/SunioSwapper/utils/buildSwapContractCall.js +29 -0
  97. package/dist/esm/swappers/SunioSwapper/utils/buildSwapRouteParameters.js +6 -6
  98. package/dist/esm/swappers/SunioSwapper/utils/constants.d.ts +2 -0
  99. package/dist/esm/swappers/SunioSwapper/utils/constants.js +6 -0
  100. package/dist/esm/swappers/SunioSwapper/utils/estimateSunioNetworkFee.d.ts +12 -0
  101. package/dist/esm/swappers/SunioSwapper/utils/estimateSunioNetworkFee.js +74 -0
  102. package/dist/esm/swappers/SunioSwapper/utils/getQuoteOrRate.js +16 -74
  103. package/dist/esm/swappers/SunioSwapper/utils/getSunioTransactionFees.d.ts +2 -0
  104. package/dist/esm/swappers/SunioSwapper/utils/getSunioTransactionFees.js +32 -0
  105. package/dist/esm/swappers/utils/helpers/helpers.js +2 -1
  106. package/dist/esm/thorchain-utils/getL1RateOrQuote.js +5 -2
  107. package/dist/esm/thorchain-utils/getQuote.js +27 -29
  108. package/dist/esm/thorchain-utils/tron/getTronTransactionFees.js +8 -5
  109. package/dist/esm/thorchain-utils/types.d.ts +1 -1
  110. package/dist/esm/types.d.ts +10 -3
  111. package/dist/esm/types.js +5 -0
  112. package/package.json +8 -7
  113. package/dist/cjs/swappers/SunioSwapper/utils/buildSwapTransaction.d.ts +0 -11
  114. package/dist/cjs/swappers/SunioSwapper/utils/buildSwapTransaction.js +0 -57
  115. package/dist/cjs/thorchain-utils/getThresholdedAffiliateBps/getThresholdedAffiliateBps.d.ts +0 -12
  116. package/dist/cjs/thorchain-utils/getThresholdedAffiliateBps/getThresholdedAffiliateBps.js +0 -47
  117. package/dist/cjs/thorchain-utils/getThresholdedAffiliateBps/getThresholdedAffiliateBps.test.js +0 -100
  118. package/dist/esm/swappers/SunioSwapper/utils/buildSwapTransaction.d.ts +0 -11
  119. package/dist/esm/swappers/SunioSwapper/utils/buildSwapTransaction.js +0 -53
  120. package/dist/esm/thorchain-utils/getThresholdedAffiliateBps/getThresholdedAffiliateBps.d.ts +0 -12
  121. package/dist/esm/thorchain-utils/getThresholdedAffiliateBps/getThresholdedAffiliateBps.js +0 -41
  122. package/dist/esm/thorchain-utils/getThresholdedAffiliateBps/getThresholdedAffiliateBps.test.d.ts +0 -1
  123. package/dist/esm/thorchain-utils/getThresholdedAffiliateBps/getThresholdedAffiliateBps.test.js +0 -98
  124. /package/dist/{cjs/thorchain-utils/getThresholdedAffiliateBps/getThresholdedAffiliateBps.test.d.ts → esm/swappers/BobGatewaySwapper/types.js} +0 -0
@@ -0,0 +1,49 @@
1
+ import type { GatewayOrderStatusV2, GatewayQuoteV2, GetQuoteParams } from '@gobob/bob-sdk';
2
+ import { GatewaySDK } from '@gobob/bob-sdk';
3
+ import type { AssetId } from '@shapeshiftoss/caip';
4
+ import type { Asset, AssetsByIdPartial } from '@shapeshiftoss/types';
5
+ import { TxStatus } from '@shapeshiftoss/unchained-client';
6
+ import type { Result } from '@sniptt/monads';
7
+ import type { GetTradeQuoteInput, QuoteFeeData, SwapErrorRight, SwapperConfig, SwapperDeps } from '../../../types';
8
+ import type { BobGatewayMetadata } from '../types';
9
+ import type { BobGatewayChainName } from './constants';
10
+ export declare const getBobGatewayClient: (config: SwapperConfig) => GatewaySDK;
11
+ export declare const assetIdToBobGatewayToken: (assetId: string) => string;
12
+ export declare const getBobGatewayAffiliates: (affiliateBps: string) => GetQuoteParams['affiliates'];
13
+ export declare const getBobGatewayQuote: ({ config, sellAsset, buyAsset, sellChainName, buyChainName, sender, recipient, amount, affiliateBps, slippageTolerancePercentageDecimal, }: {
14
+ config: SwapperConfig;
15
+ sellAsset: Asset;
16
+ buyAsset: Asset;
17
+ sellChainName: BobGatewayChainName;
18
+ buyChainName: BobGatewayChainName;
19
+ sender: string | undefined;
20
+ recipient: string;
21
+ amount: string;
22
+ affiliateBps: string;
23
+ slippageTolerancePercentageDecimal: string | undefined;
24
+ }) => Promise<Result<GatewayQuoteV2, SwapErrorRight>>;
25
+ export declare const createBobGatewayOrderMetadata: (config: SwapperConfig, gatewayQuote: GatewayQuoteV2) => Promise<Result<BobGatewayMetadata, SwapErrorRight>>;
26
+ export declare const registerBobGatewayTx: ({ config, orderId, txHash, sellAsset, buyAsset, }: {
27
+ config: SwapperConfig;
28
+ orderId: string;
29
+ txHash: string;
30
+ sellAsset: Asset;
31
+ buyAsset: Asset;
32
+ }) => Promise<void>;
33
+ export declare const getBobGatewayQuoteFeeData: (input: GetTradeQuoteInput, { assertGetUtxoChainAdapter, assertGetEvmChainAdapter }: SwapperDeps, orderMetadata: BobGatewayMetadata) => Promise<Result<Omit<QuoteFeeData, 'protocolFees'>, SwapErrorRight>>;
34
+ export declare const getBobGatewayRateNetworkFeeCryptoBaseUnit: (quote: GatewayQuoteV2, sellAsset: Asset, { assertGetEvmChainAdapter, assertGetUtxoChainAdapter }: SwapperDeps) => Promise<string | undefined>;
35
+ export declare const mapBobGatewayOrderStatusToTxStatus: (status: GatewayOrderStatusV2) => TxStatus;
36
+ export declare const parseBobGatewayQuote: (quote: GatewayQuoteV2, buyAsset: Asset, assetsById: AssetsByIdPartial) => {
37
+ buyAmountBeforeFeesCryptoBaseUnit: string;
38
+ buyAmountAfterFeesCryptoBaseUnit: string;
39
+ protocolFees: Partial<Record<AssetId, import("../../../types").ProtocolFee>>;
40
+ estimatedExecutionTimeMs: number | undefined;
41
+ };
42
+ export declare const getBobGatewayAllowanceContract: (quote: GatewayQuoteV2, sellAsset: Asset) => string;
43
+ export declare const assertValidTrade: ({ sellAsset, buyAsset, }: {
44
+ sellAsset: Asset;
45
+ buyAsset: Asset;
46
+ }) => Result<{
47
+ sellChainName: BobGatewayChainName;
48
+ buyChainName: BobGatewayChainName;
49
+ }, SwapErrorRight>;
@@ -0,0 +1,314 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertValidTrade = exports.getBobGatewayAllowanceContract = exports.parseBobGatewayQuote = exports.mapBobGatewayOrderStatusToTxStatus = exports.getBobGatewayRateNetworkFeeCryptoBaseUnit = exports.getBobGatewayQuoteFeeData = exports.registerBobGatewayTx = exports.createBobGatewayOrderMetadata = exports.getBobGatewayQuote = exports.getBobGatewayAffiliates = exports.assetIdToBobGatewayToken = exports.getBobGatewayClient = void 0;
4
+ const bob_sdk_1 = require("@gobob/bob-sdk");
5
+ const caip_1 = require("@shapeshiftoss/caip");
6
+ const chain_adapters_1 = require("@shapeshiftoss/chain-adapters");
7
+ const unchained_client_1 = require("@shapeshiftoss/unchained-client");
8
+ const utils_1 = require("@shapeshiftoss/utils");
9
+ const monads_1 = require("@sniptt/monads");
10
+ const viem_1 = require("viem");
11
+ const constants_1 = require("../../../constants");
12
+ const types_1 = require("../../../types");
13
+ const utils_2 = require("../../../utils");
14
+ const helpers_1 = require("../../utils/helpers/helpers");
15
+ const constants_2 = require("./constants");
16
+ const getBobGatewayClient = (config) => {
17
+ return new bob_sdk_1.GatewaySDK({ basePath: constants_2.BOB_GATEWAY_BASE_URL, apiKey: config.VITE_BOB_GATEWAY_API_KEY });
18
+ };
19
+ exports.getBobGatewayClient = getBobGatewayClient;
20
+ const assetIdToBobGatewayToken = (assetId) => {
21
+ // BOB Gateway uses the zero address as the token address for native assets
22
+ if (!(0, utils_1.isToken)(assetId))
23
+ return viem_1.zeroAddress;
24
+ return (0, caip_1.fromAssetId)(assetId).assetReference;
25
+ };
26
+ exports.assetIdToBobGatewayToken = assetIdToBobGatewayToken;
27
+ const getBobGatewayAffiliates = (affiliateBps) => {
28
+ const bps = (0, utils_1.bnOrZero)(affiliateBps);
29
+ if (!bps.isFinite() || bps.lte(0))
30
+ return undefined;
31
+ const affiliateAddress = (0, helpers_1.getTreasuryAddressFromChainId)(caip_1.ethChainId);
32
+ return [{ address: (0, viem_1.getAddress)(affiliateAddress), bps: bps.toNumber() }];
33
+ };
34
+ exports.getBobGatewayAffiliates = getBobGatewayAffiliates;
35
+ const getBobGatewayQuote = async ({ config, sellAsset, buyAsset, sellChainName, buyChainName, sender, recipient, amount, affiliateBps, slippageTolerancePercentageDecimal, }) => {
36
+ const slippage = (0, constants_2.decimalSlippageToBobBps)(slippageTolerancePercentageDecimal ??
37
+ (0, constants_1.getDefaultSlippageDecimalPercentageForSwapper)(types_1.SwapperName.BobGateway));
38
+ try {
39
+ const quote = await (0, exports.getBobGatewayClient)(config).getQuote({
40
+ fromChain: sellChainName,
41
+ toChain: buyChainName,
42
+ fromToken: (0, exports.assetIdToBobGatewayToken)(sellAsset.assetId),
43
+ toToken: (0, exports.assetIdToBobGatewayToken)(buyAsset.assetId),
44
+ fromUserAddress: sender,
45
+ toUserAddress: recipient,
46
+ amount,
47
+ maxSlippage: Number(slippage),
48
+ affiliates: (0, exports.getBobGatewayAffiliates)(affiliateBps),
49
+ });
50
+ return (0, monads_1.Ok)(quote);
51
+ }
52
+ catch (err) {
53
+ if ((0, bob_sdk_1.isGatewayError)(err)) {
54
+ switch (err.code) {
55
+ case bob_sdk_1.GatewayErrorCode.QuoteAmountTooLow:
56
+ return (0, monads_1.Err)((0, utils_2.createTradeAmountTooSmallErr)({
57
+ minAmountCryptoBaseUnit: err.details.minimum,
58
+ assetId: sellAsset.assetId,
59
+ }));
60
+ case bob_sdk_1.GatewayErrorCode.UnableToCoverFees:
61
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
62
+ message: '[BobGateway] sell amount does not cover fees',
63
+ code: types_1.TradeQuoteError.SellAmountBelowTradeFee,
64
+ cause: err,
65
+ }));
66
+ case bob_sdk_1.GatewayErrorCode.NoRoute:
67
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
68
+ message: '[BobGateway] no route found for trade pair',
69
+ code: types_1.TradeQuoteError.NoRouteFound,
70
+ cause: err,
71
+ }));
72
+ case bob_sdk_1.GatewayErrorCode.DisabledChain:
73
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
74
+ message: '[BobGateway] trading is temporarily halted for this chain',
75
+ code: types_1.TradeQuoteError.TradingHalted,
76
+ cause: err,
77
+ }));
78
+ default:
79
+ break;
80
+ }
81
+ }
82
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
83
+ message: '[BobGateway] failed to fetch quote',
84
+ code: types_1.TradeQuoteError.QueryFailed,
85
+ cause: err,
86
+ }));
87
+ }
88
+ };
89
+ exports.getBobGatewayQuote = getBobGatewayQuote;
90
+ const createBobGatewayOrderMetadata = async (config, gatewayQuote) => {
91
+ try {
92
+ const orderResponse = await (0, exports.getBobGatewayClient)(config).api.createOrderV2({
93
+ gatewayQuoteV2: gatewayQuote,
94
+ });
95
+ // onramp (BTC→EVM)
96
+ if ('onramp' in orderResponse) {
97
+ return (0, monads_1.Ok)({
98
+ orderId: orderResponse.onramp.orderId,
99
+ utxoTx: {
100
+ depositAddress: orderResponse.onramp.address,
101
+ opReturnData: orderResponse.onramp.opReturnData ?? undefined,
102
+ },
103
+ });
104
+ }
105
+ // offramp (EVM→BTC) and tokenSwap (EVM→EVM) orders share the same tx shape
106
+ const order = 'offramp' in orderResponse ? orderResponse.offramp : orderResponse.tokenSwap;
107
+ return (0, monads_1.Ok)({
108
+ orderId: order.orderId,
109
+ evmTx: {
110
+ to: order.tx.to,
111
+ data: order.tx.data,
112
+ value: order.tx.value,
113
+ chain: order.tx.chain,
114
+ },
115
+ });
116
+ }
117
+ catch (err) {
118
+ if ((0, bob_sdk_1.isGatewayError)(err) && err.code === bob_sdk_1.GatewayErrorCode.InsufficientConfirmedFunds) {
119
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
120
+ message: '[BobGateway] insufficient confirmed balance',
121
+ code: types_1.TradeQuoteError.InsufficientFundsUnconfirmed,
122
+ cause: err,
123
+ }));
124
+ }
125
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
126
+ message: '[BobGateway] failed to create order',
127
+ code: types_1.TradeQuoteError.QueryFailed,
128
+ cause: err,
129
+ }));
130
+ }
131
+ };
132
+ exports.createBobGatewayOrderMetadata = createBobGatewayOrderMetadata;
133
+ const registerBobGatewayTx = async ({ config, orderId, txHash, sellAsset, buyAsset, }) => {
134
+ const registerTxV2 = (() => {
135
+ // BTC→EVM
136
+ if (constants_2.chainIdToBobGatewayChainName[sellAsset.chainId] === 'bitcoin') {
137
+ return { onramp: { orderId, bitcoinTxid: txHash } };
138
+ }
139
+ // EVM→BTC
140
+ if (constants_2.chainIdToBobGatewayChainName[buyAsset.chainId] === 'bitcoin') {
141
+ return { offramp: { orderId, evmTxhash: txHash } };
142
+ }
143
+ // EVM→EVM
144
+ return { tokenSwap: { orderId, evmTxhash: txHash } };
145
+ })();
146
+ await (0, exports.getBobGatewayClient)(config).api.registerTxV2({ registerTxV2 });
147
+ };
148
+ exports.registerBobGatewayTx = registerBobGatewayTx;
149
+ const getBobGatewayQuoteFeeData = async (input, { assertGetUtxoChainAdapter, assertGetEvmChainAdapter }, orderMetadata) => {
150
+ const { sellAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit } = input;
151
+ try {
152
+ if (orderMetadata.utxoTx && 'xpub' in input) {
153
+ const { depositAddress, opReturnData } = orderMetadata.utxoTx;
154
+ const { fast } = await assertGetUtxoChainAdapter(sellAsset.chainId).getFeeData({
155
+ to: depositAddress,
156
+ value: sellAmountIncludingProtocolFeesCryptoBaseUnit,
157
+ chainSpecific: { pubkey: input.xpub, opReturnData },
158
+ sendMax: false,
159
+ });
160
+ return (0, monads_1.Ok)({
161
+ networkFeeCryptoBaseUnit: fast.txFee,
162
+ chainSpecific: { satsPerByte: fast.chainSpecific.satoshiPerByte },
163
+ });
164
+ }
165
+ if (orderMetadata.evmTx && input.sendAddress && 'supportsEIP1559' in input) {
166
+ const { to, data, value } = orderMetadata.evmTx;
167
+ const { networkFeeCryptoBaseUnit } = await chain_adapters_1.evm.getFees({
168
+ adapter: assertGetEvmChainAdapter(sellAsset.chainId),
169
+ to,
170
+ data,
171
+ value,
172
+ from: input.sendAddress,
173
+ supportsEIP1559: input.supportsEIP1559,
174
+ });
175
+ return (0, monads_1.Ok)({ networkFeeCryptoBaseUnit });
176
+ }
177
+ throw new Error('[BobGateway] invalid quote');
178
+ }
179
+ catch (err) {
180
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
181
+ message: '[BobGateway] failed to estimate network fee',
182
+ code: types_1.TradeQuoteError.NetworkFeeEstimationFailed,
183
+ cause: err,
184
+ }));
185
+ }
186
+ };
187
+ exports.getBobGatewayQuoteFeeData = getBobGatewayQuoteFeeData;
188
+ const getBobGatewayRateNetworkFeeCryptoBaseUnit = async (quote, sellAsset, { assertGetEvmChainAdapter, assertGetUtxoChainAdapter }) => {
189
+ try {
190
+ if ('onramp' in quote) {
191
+ const adapter = assertGetUtxoChainAdapter(sellAsset.chainId);
192
+ const { fast } = await adapter.httpProvider.getNetworkFees();
193
+ if (!fast?.satsPerKiloByte)
194
+ return undefined;
195
+ const satsPerByte = Math.max(1, Math.ceil(fast.satsPerKiloByte / 1000));
196
+ return (0, utils_1.bnOrZero)(satsPerByte).times(constants_2.BOB_GATEWAY_ONRAMP_DEFAULT_TX_VSIZE).toFixed(0);
197
+ }
198
+ const defaultGasLimit = 'offramp' in quote
199
+ ? constants_2.BOB_GATEWAY_OFFRAMP_DEFAULT_GAS_LIMIT
200
+ : constants_2.BOB_GATEWAY_TOKENSWAP_DEFAULT_GAS_LIMIT;
201
+ const { average } = await assertGetEvmChainAdapter(sellAsset.chainId).getGasFeeData();
202
+ const feePerGas = (0, utils_1.bnOrZero)(average.maxFeePerGas).gt(0) ? average.maxFeePerGas : average.gasPrice;
203
+ return (0, utils_1.bnOrZero)(defaultGasLimit).times((0, utils_1.bnOrZero)(feePerGas)).toFixed(0);
204
+ }
205
+ catch {
206
+ return undefined;
207
+ }
208
+ };
209
+ exports.getBobGatewayRateNetworkFeeCryptoBaseUnit = getBobGatewayRateNetworkFeeCryptoBaseUnit;
210
+ const mapBobGatewayOrderStatusToTxStatus = (status) => {
211
+ if ('inProgress' in status)
212
+ return unchained_client_1.TxStatus.Pending;
213
+ if ('success' in status)
214
+ return unchained_client_1.TxStatus.Confirmed;
215
+ if ('failed' in status)
216
+ return unchained_client_1.TxStatus.Failed;
217
+ if ('refunded' in status)
218
+ return unchained_client_1.TxStatus.Failed;
219
+ return unchained_client_1.TxStatus.Unknown;
220
+ };
221
+ exports.mapBobGatewayOrderStatusToTxStatus = mapBobGatewayOrderStatusToTxStatus;
222
+ const bobGatewayFeeToAssetId = (fee) => {
223
+ const chainId = constants_2.bobGatewayChainNameToChainId[fee.chain];
224
+ if (!chainId)
225
+ return;
226
+ if (fee.address.toLowerCase() === viem_1.zeroAddress)
227
+ return (0, utils_1.chainIdToFeeAssetId)(chainId);
228
+ return (0, caip_1.toAssetId)({
229
+ chainId,
230
+ assetNamespace: caip_1.ASSET_NAMESPACE.erc20,
231
+ assetReference: fee.address,
232
+ });
233
+ };
234
+ const parseBobGatewayQuote = (quote, buyAsset, assetsById) => {
235
+ const { outputAmount, estimatedTimeInSecs, fees } = (() => {
236
+ if ('onramp' in quote) {
237
+ const { outputAmount, estimatedTimeInSecs, fees } = quote.onramp;
238
+ return { outputAmount, estimatedTimeInSecs, fees: [fees] };
239
+ }
240
+ if ('offramp' in quote) {
241
+ const { outputAmount, estimatedTimeInSecs, feeBreakdown } = quote.offramp;
242
+ const { affiliateFee, inclusionFee, protocolFee, solverFee } = feeBreakdown;
243
+ return {
244
+ outputAmount,
245
+ estimatedTimeInSecs,
246
+ fees: [affiliateFee, inclusionFee, protocolFee, solverFee],
247
+ };
248
+ }
249
+ const { outputAmount, estimatedTimeInSecs, fees } = quote.tokenSwap;
250
+ return { outputAmount, estimatedTimeInSecs, fees: [fees] };
251
+ })();
252
+ const protocolFees = fees.reduce((acc, fee) => {
253
+ const amountCryptoBaseUnit = (0, utils_1.bnOrZero)(fee.amount);
254
+ if (amountCryptoBaseUnit.lte(0))
255
+ return acc;
256
+ const assetId = bobGatewayFeeToAssetId(fee);
257
+ if (!assetId)
258
+ return acc;
259
+ const asset = assetId === buyAsset.assetId ? buyAsset : assetsById[assetId];
260
+ if (!asset)
261
+ return acc;
262
+ acc[assetId] = {
263
+ amountCryptoBaseUnit: (0, utils_1.bnOrZero)(acc[assetId]?.amountCryptoBaseUnit)
264
+ .plus(amountCryptoBaseUnit)
265
+ .toFixed(),
266
+ asset,
267
+ requiresBalance: false,
268
+ };
269
+ return acc;
270
+ }, {});
271
+ // buyAmountBeforeFees is denominated in the buy asset, so only add back buy-asset-denominated fees
272
+ const buyAssetFeeCryptoBaseUnit = (0, utils_1.bnOrZero)(protocolFees[buyAsset.assetId]?.amountCryptoBaseUnit);
273
+ return {
274
+ buyAmountBeforeFeesCryptoBaseUnit: buyAssetFeeCryptoBaseUnit
275
+ .plus((0, utils_1.bnOrZero)(outputAmount.amount))
276
+ .toFixed(),
277
+ buyAmountAfterFeesCryptoBaseUnit: outputAmount.amount,
278
+ protocolFees,
279
+ estimatedExecutionTimeMs: typeof estimatedTimeInSecs === 'number' ? estimatedTimeInSecs * 1000 : undefined,
280
+ };
281
+ };
282
+ exports.parseBobGatewayQuote = parseBobGatewayQuote;
283
+ const getBobGatewayAllowanceContract = (quote, sellAsset) => {
284
+ if (!(0, chain_adapters_1.isEvmChainId)(sellAsset.chainId))
285
+ return '';
286
+ if (!(0, utils_1.contractAddressOrUndefined)(sellAsset.assetId))
287
+ return '';
288
+ if ('offramp' in quote)
289
+ return quote.offramp.txTo;
290
+ if ('tokenSwap' in quote)
291
+ return quote.tokenSwap.txTo;
292
+ return '';
293
+ };
294
+ exports.getBobGatewayAllowanceContract = getBobGatewayAllowanceContract;
295
+ const assertValidTrade = ({ sellAsset, buyAsset, }) => {
296
+ const sellChainName = constants_2.chainIdToBobGatewayChainName[sellAsset.chainId];
297
+ const buyChainName = constants_2.chainIdToBobGatewayChainName[buyAsset.chainId];
298
+ if (!sellChainName) {
299
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
300
+ message: `[BobGateway] unsupported sell chain: ${sellAsset.chainId}`,
301
+ code: types_1.TradeQuoteError.UnsupportedChain,
302
+ details: { chainId: sellAsset.chainId },
303
+ }));
304
+ }
305
+ if (!buyChainName) {
306
+ return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
307
+ message: `[BobGateway] unsupported buy chain: ${buyAsset.chainId}`,
308
+ code: types_1.TradeQuoteError.UnsupportedChain,
309
+ details: { chainId: buyAsset.chainId },
310
+ }));
311
+ }
312
+ return (0, monads_1.Ok)({ sellChainName, buyChainName });
313
+ };
314
+ exports.assertValidTrade = assertValidTrade;
@@ -5,6 +5,7 @@ const utils_1 = require("../../utils");
5
5
  exports.chainflipSwapper = {
6
6
  executeEvmTransaction: utils_1.executeEvmTransaction,
7
7
  executeSolanaTransaction: utils_1.executeSolanaTransaction,
8
+ executeTronTransaction: utils_1.executeTronTransaction,
8
9
  executeUtxoTransaction: (txToSign, { signAndBroadcastTransaction }) => {
9
10
  return signAndBroadcastTransaction(txToSign);
10
11
  },
@@ -5,7 +5,7 @@ import type { SwapSource } from '../../types';
5
5
  import { ChainflipNetwork } from './types';
6
6
  export declare const CHAINFLIP_REGULAR_QUOTE: "regular";
7
7
  export declare const CHAINFLIP_DCA_QUOTE: "dca";
8
- export declare const ChainflipSupportedChainIds: readonly [KnownChainIds.EthereumMainnet, KnownChainIds.ArbitrumMainnet, KnownChainIds.BitcoinMainnet, KnownChainIds.SolanaMainnet];
8
+ export declare const ChainflipSupportedChainIds: readonly [KnownChainIds.EthereumMainnet, KnownChainIds.ArbitrumMainnet, KnownChainIds.BitcoinMainnet, KnownChainIds.SolanaMainnet, KnownChainIds.TronMainnet];
9
9
  export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[number];
10
10
  export declare const ChainflipSupportedAssetIdsByChainId: Partial<Record<KnownChainIds, AssetId[]>>;
11
11
  export declare const chainIdToChainflipNetwork: Partial<Record<ChainId, ChainflipNetwork>>;
@@ -12,6 +12,7 @@ exports.ChainflipSupportedChainIds = [
12
12
  types_1.KnownChainIds.ArbitrumMainnet,
13
13
  types_1.KnownChainIds.BitcoinMainnet,
14
14
  types_1.KnownChainIds.SolanaMainnet,
15
+ types_1.KnownChainIds.TronMainnet,
15
16
  ];
16
17
  exports.ChainflipSupportedAssetIdsByChainId = {
17
18
  [types_1.KnownChainIds.EthereumMainnet]: [caip_1.ethAssetId, caip_1.flipAssetId, caip_1.usdcAssetId, caip_1.usdtAssetId, caip_1.wbtcAssetId],
@@ -22,12 +23,14 @@ exports.ChainflipSupportedAssetIdsByChainId = {
22
23
  ],
23
24
  [types_1.KnownChainIds.BitcoinMainnet]: [caip_1.btcAssetId],
24
25
  [types_1.KnownChainIds.SolanaMainnet]: [caip_1.solAssetId, caip_1.usdcOnSolanaAssetId, caip_1.usdtOnSolanaAssetId],
26
+ [types_1.KnownChainIds.TronMainnet]: [caip_1.tronAssetId, caip_1.usdtOnTronAssetId],
25
27
  };
26
28
  exports.chainIdToChainflipNetwork = {
27
29
  [types_1.KnownChainIds.EthereumMainnet]: types_3.ChainflipNetwork.Ethereum,
28
30
  [types_1.KnownChainIds.ArbitrumMainnet]: types_3.ChainflipNetwork.Arbitrum,
29
31
  [types_1.KnownChainIds.BitcoinMainnet]: types_3.ChainflipNetwork.Bitcoin,
30
32
  [types_1.KnownChainIds.SolanaMainnet]: types_3.ChainflipNetwork.Solana,
33
+ [types_1.KnownChainIds.TronMainnet]: types_3.ChainflipNetwork.Tron,
31
34
  };
32
35
  exports.CHAINFLIP_SWAP_SOURCE = types_2.SwapperName.Chainflip;
33
36
  exports.CHAINFLIP_BOOST_SWAP_SOURCE = `${types_2.SwapperName.Chainflip} • Boost`;
@@ -4,6 +4,7 @@ exports.chainflipApi = void 0;
4
4
  const chain_adapters_1 = require("@shapeshiftoss/chain-adapters");
5
5
  const unchained_client_1 = require("@shapeshiftoss/unchained-client");
6
6
  const utils_1 = require("@shapeshiftoss/utils");
7
+ const getTronTransactionFees_1 = require("../../tron-utils/getTronTransactionFees");
7
8
  const utils_2 = require("../../utils");
8
9
  const helpers_1 = require("../utils/helpers/helpers");
9
10
  const constants_1 = require("./constants");
@@ -166,6 +167,25 @@ exports.chainflipApi = {
166
167
  const ratio = simulatedUnits > 0 ? boostedUnits / simulatedUnits : 1;
167
168
  return String(Math.ceil(Number(fast.txFee) * ratio));
168
169
  },
170
+ getUnsignedTronTransaction: ({ stepIndex, tradeQuote, from, assertGetTronChainAdapter }) => {
171
+ if (!(0, utils_2.isExecutableTradeQuote)(tradeQuote))
172
+ throw new Error('Unable to execute a trade rate quote');
173
+ const step = (0, utils_2.getExecutableTradeStep)(tradeQuote, stepIndex);
174
+ const { accountNumber, chainflipSpecific, sellAsset } = step;
175
+ if (!chainflipSpecific?.chainflipDepositAddress)
176
+ throw Error('Missing deposit address');
177
+ if (!chainflipSpecific?.chainflipSwapId)
178
+ throw Error('Missing swap id');
179
+ const adapter = assertGetTronChainAdapter(sellAsset.chainId);
180
+ return adapter.buildSendApiTransaction({
181
+ to: chainflipSpecific.chainflipDepositAddress,
182
+ from,
183
+ value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit,
184
+ accountNumber,
185
+ chainSpecific: { contractAddress: (0, utils_1.contractAddressOrUndefined)(sellAsset.assetId) },
186
+ });
187
+ },
188
+ getTronTransactionFees: getTronTransactionFees_1.getTronTransactionFees,
169
189
  checkTradeStatus: async ({ config, swap }) => {
170
190
  const chainflipSwapId = swap?.metadata.chainflipSwapId;
171
191
  if (chainflipSwapId == null)
@@ -12,5 +12,6 @@ export declare enum ChainflipNetwork {
12
12
  Bitcoin = "Bitcoin",
13
13
  Ethereum = "Ethereum",
14
14
  Arbitrum = "Arbitrum",
15
- Solana = "Solana"
15
+ Solana = "Solana",
16
+ Tron = "Tron"
16
17
  }
@@ -7,4 +7,5 @@ var ChainflipNetwork;
7
7
  ChainflipNetwork["Ethereum"] = "Ethereum";
8
8
  ChainflipNetwork["Arbitrum"] = "Arbitrum";
9
9
  ChainflipNetwork["Solana"] = "Solana";
10
+ ChainflipNetwork["Tron"] = "Tron";
10
11
  })(ChainflipNetwork || (exports.ChainflipNetwork = ChainflipNetwork = {}));
@@ -70,11 +70,14 @@ const getQuoteOrRate = async (input, deps) => {
70
70
  if (maybeQuoteResponse.isErr()) {
71
71
  const error = maybeQuoteResponse.unwrapErr();
72
72
  const cause = error.cause;
73
- if (cause?.message?.includes('code 400') &&
74
- cause?.response?.data?.detail?.includes('Amount outside asset bounds')) {
73
+ // Chainflip returns a 400 with `errors.minimalAmountNative` when the sell amount is below the
74
+ // route minimum. The `detail` wording varies ("Amount outside asset bounds", "Amount below
75
+ // minimum. Min: ..."), so key off the field rather than string-matching the message.
76
+ const minAmountCryptoBaseUnit = cause?.response?.data?.errors?.minimalAmountNative?.[0];
77
+ if (cause?.response?.status === 400 && minAmountCryptoBaseUnit !== undefined) {
75
78
  return (0, monads_1.Err)((0, utils_2.createTradeAmountTooSmallErr)({
76
79
  assetId: sellAsset.assetId,
77
- minAmountCryptoBaseUnit: cause.response?.data?.errors?.minimalAmountNative?.[0],
80
+ minAmountCryptoBaseUnit,
78
81
  }));
79
82
  }
80
83
  return (0, monads_1.Err)((0, utils_2.makeSwapErrorRight)({
@@ -122,6 +125,21 @@ const getQuoteOrRate = async (input, deps) => {
122
125
  const { fast } = await sellAdapter.getFeeData(getFeeDataInput);
123
126
  return { networkFeeCryptoBaseUnit: fast.txFee };
124
127
  }
128
+ case caip_1.CHAIN_NAMESPACE.Tron: {
129
+ if (!input.sendAddress)
130
+ return { networkFeeCryptoBaseUnit: undefined };
131
+ const sellAdapter = deps.assertGetTronChainAdapter(sellAsset.chainId);
132
+ const { fast } = await sellAdapter.getFeeData({
133
+ // Simulates a self-send, since we don't know the 'to' just yet at this stage
134
+ to: input.sendAddress,
135
+ value: sellAmountIncludingProtocolFeesCryptoBaseUnit,
136
+ chainSpecific: {
137
+ from: input.sendAddress,
138
+ contractAddress: (0, utils_1.contractAddressOrUndefined)(sellAsset.assetId),
139
+ },
140
+ });
141
+ return { networkFeeCryptoBaseUnit: fast.txFee };
142
+ }
125
143
  default:
126
144
  throw new Error('Unsupported chainNamespace');
127
145
  }
@@ -185,6 +203,8 @@ const getQuoteOrRate = async (input, deps) => {
185
203
  return 10;
186
204
  case caip_1.CHAIN_NAMESPACE.Solana:
187
205
  return 0;
206
+ case caip_1.CHAIN_NAMESPACE.Tron:
207
+ return 0;
188
208
  default:
189
209
  throw new Error('Unsupported chainNamespace');
190
210
  }
@@ -20,8 +20,8 @@ type GetChainFlipSwapArgs = ChainFlipBrokerBaseArgs & {
20
20
  numberOfChunks?: number;
21
21
  chunkIntervalBlocks?: number;
22
22
  };
23
- export declare const isSupportedChainId: (chainId: ChainId) => chainId is import("@shapeshiftoss/types").KnownChainIds.EthereumMainnet | import("@shapeshiftoss/types").KnownChainIds.ArbitrumMainnet | import("@shapeshiftoss/types").KnownChainIds.BitcoinMainnet | import("@shapeshiftoss/types").KnownChainIds.SolanaMainnet;
24
- export declare const isSupportedAssetId: (chainId: ChainId, assetId: AssetId) => chainId is import("@shapeshiftoss/types").KnownChainIds.EthereumMainnet | import("@shapeshiftoss/types").KnownChainIds.ArbitrumMainnet | import("@shapeshiftoss/types").KnownChainIds.BitcoinMainnet | import("@shapeshiftoss/types").KnownChainIds.SolanaMainnet;
23
+ export declare const isSupportedChainId: (chainId: ChainId) => chainId is import("@shapeshiftoss/types").KnownChainIds.EthereumMainnet | import("@shapeshiftoss/types").KnownChainIds.ArbitrumMainnet | import("@shapeshiftoss/types").KnownChainIds.BitcoinMainnet | import("@shapeshiftoss/types").KnownChainIds.SolanaMainnet | import("@shapeshiftoss/types").KnownChainIds.TronMainnet;
24
+ export declare const isSupportedAssetId: (chainId: ChainId, assetId: AssetId) => chainId is import("@shapeshiftoss/types").KnownChainIds.EthereumMainnet | import("@shapeshiftoss/types").KnownChainIds.ArbitrumMainnet | import("@shapeshiftoss/types").KnownChainIds.BitcoinMainnet | import("@shapeshiftoss/types").KnownChainIds.SolanaMainnet | import("@shapeshiftoss/types").KnownChainIds.TronMainnet;
25
25
  export declare const calculateChainflipMinPrice: ({ sellAmountIncludingProtocolFeesCryptoBaseUnit, buyAmountAfterFeesCryptoBaseUnit, slippageTolerancePercentageDecimal, sellAsset, buyAsset, }: {
26
26
  sellAmountIncludingProtocolFeesCryptoBaseUnit: string;
27
27
  buyAmountAfterFeesCryptoBaseUnit: string;
@@ -51,7 +51,8 @@ const getChainFlipSwap = ({ brokerUrl, apiKey, sourceAsset, destinationAsset, de
51
51
  swapUrl += `&numberOfChunks=${numberOfChunks}`;
52
52
  swapUrl += `&chunkIntervalBlocks=${chunkIntervalBlocks}`;
53
53
  }
54
- return chainflipService_1.chainflipService.get(swapUrl);
54
+ // Opening a deposit channel can spike past the default 10s timeout (notably on Tron).
55
+ return chainflipService_1.chainflipService.get(swapUrl, { timeout: 30_000 });
55
56
  };
56
57
  exports.getChainFlipSwap = getChainFlipSwap;
57
58
  const fetchChainFlipAssets = async ({ brokerUrl, }) => {
@@ -15,9 +15,9 @@ vitest_1.vi.mock('../cowService', async () => {
15
15
  const mockDay = '2020-12-31';
16
16
  const mockTime = 'T23:59:59.000Z';
17
17
  const mockDate = `${mockDay}${mockTime}`;
18
- (0, vitest_1.beforeEach)(() => vitest_1.vi
19
- .useFakeTimers()
20
- .setSystemTime(new Date(mockDate)));
18
+ (0, vitest_1.beforeEach)(() => {
19
+ vitest_1.vi.useFakeTimers().setSystemTime(new Date(mockDate));
20
+ });
21
21
  (0, vitest_1.afterEach)(() => {
22
22
  vitest_1.vi.restoreAllMocks();
23
23
  vitest_1.vi.useRealTimers();
@@ -74,7 +74,7 @@ exports.relayErrorCodeToTradeQuoteError = {
74
74
  [types_2.RelayErrorCode.ChainDisabled]: types_1.TradeQuoteError.TradingHalted,
75
75
  [types_2.RelayErrorCode.Erc20RouterAddressNotFound]: types_1.TradeQuoteError.UnsupportedTradePair,
76
76
  [types_2.RelayErrorCode.ExtraTransactionsNotSupported]: types_1.TradeQuoteError.UnsupportedTradePair,
77
- [types_2.RelayErrorCode.InsufficientFunds]: types_1.TradeQuoteError.SellAmountBelowTradeFee,
77
+ [types_2.RelayErrorCode.InsufficientFunds]: types_1.TradeQuoteError.InsufficientFunds,
78
78
  [types_2.RelayErrorCode.InsufficientLiquidity]: types_1.TradeQuoteError.SellAmountBelowTradeFee,
79
79
  [types_2.RelayErrorCode.InvalidAddress]: types_1.TradeQuoteError.UnsupportedTradePair,
80
80
  [types_2.RelayErrorCode.InvalidExtraTransactions]: types_1.TradeQuoteError.UnsupportedTradePair,