@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
@@ -7,6 +7,8 @@ import { avnuSwapper } from './swappers/AvnuSwapper/AvnuSwapper.js';
7
7
  import { avnuApi } from './swappers/AvnuSwapper/endpoints.js';
8
8
  import { bebopSwapper } from './swappers/BebopSwapper/BebopSwapper.js';
9
9
  import { bebopApi } from './swappers/BebopSwapper/endpoints.js';
10
+ import { bobGatewaySwapper } from './swappers/BobGatewaySwapper/BobGatewaySwapper.js';
11
+ import { bobGatewayApi } from './swappers/BobGatewaySwapper/endpoints.js';
10
12
  import { butterSwap } from './swappers/ButterSwap/ButterSwap.js';
11
13
  import { butterSwapApi } from './swappers/ButterSwap/endpoints.js';
12
14
  import { cetusSwapper } from './swappers/CetusSwapper/CetusSwapper.js';
@@ -111,6 +113,10 @@ export const swappers = {
111
113
  ...debridgeSwapper,
112
114
  ...debridgeApi,
113
115
  },
116
+ [SwapperName.BobGateway]: {
117
+ ...bobGatewaySwapper,
118
+ ...bobGatewayApi,
119
+ },
114
120
  [SwapperName.Test]: undefined,
115
121
  };
116
122
  const DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE = '0.002';
@@ -129,6 +135,7 @@ const DEFAULT_AVNU_SLIPPAGE_DECIMAL_PERCENTAGE = '0.02';
129
135
  const DEFAULT_STONFI_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01';
130
136
  // deBridge API off-chain simulation overestimates output on some chains (e.g. SEI ~2.4%), so auto slippage (1%) is insufficient
131
137
  const DEFAULT_DEBRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE = '0.03';
138
+ const DEFAULT_BOB_GATEWAY_SLIPPAGE_DECIMAL_PERCENTAGE = '0.03';
132
139
  export const getDefaultSlippageDecimalPercentageForSwapper = (swapperName) => {
133
140
  if (swapperName === undefined)
134
141
  return DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE;
@@ -167,6 +174,8 @@ export const getDefaultSlippageDecimalPercentageForSwapper = (swapperName) => {
167
174
  return DEFAULT_AVNU_SLIPPAGE_DECIMAL_PERCENTAGE;
168
175
  case SwapperName.Stonfi:
169
176
  return DEFAULT_STONFI_SLIPPAGE_DECIMAL_PERCENTAGE;
177
+ case SwapperName.BobGateway:
178
+ return DEFAULT_BOB_GATEWAY_SLIPPAGE_DECIMAL_PERCENTAGE;
170
179
  default:
171
180
  return assertUnreachable(swapperName);
172
181
  }
@@ -3,6 +3,7 @@ export * from './cowswap-utils/index.js';
3
3
  export * from './safe-utils/index.js';
4
4
  export * from './swapper.js';
5
5
  export * from './swappers/ArbitrumBridgeSwapper/index.js';
6
+ export * from './swappers/BobGatewaySwapper/index.js';
6
7
  export * from './swappers/AvnuSwapper/index.js';
7
8
  export * from './swappers/BebopSwapper/index.js';
8
9
  export * from './swappers/CetusSwapper/index.js';
package/dist/esm/index.js CHANGED
@@ -3,6 +3,7 @@ export * from './cowswap-utils/index.js';
3
3
  export * from './safe-utils/index.js';
4
4
  export * from './swapper.js';
5
5
  export * from './swappers/ArbitrumBridgeSwapper/index.js';
6
+ export * from './swappers/BobGatewaySwapper/index.js';
6
7
  export * from './swappers/AvnuSwapper/index.js';
7
8
  export * from './swappers/BebopSwapper/index.js';
8
9
  export * from './swappers/CetusSwapper/index.js';
@@ -51,7 +51,9 @@ describe('getTradeQuote', () => {
51
51
  },
52
52
  }),
53
53
  };
54
- vi.mocked(EthBridger).mockReturnValue(ethBridgerMock);
54
+ vi.mocked(EthBridger).mockImplementation(function () {
55
+ return ethBridgerMock;
56
+ });
55
57
  const maybeQuote = await getTradeQuote(commonInput, {
56
58
  assertGetEvmChainAdapter,
57
59
  getEthersV5Provider: vi.fn(),
@@ -74,7 +76,9 @@ describe('getTradeQuote', () => {
74
76
  },
75
77
  }),
76
78
  };
77
- vi.mocked(EthBridger).mockReturnValue(ethBridgerMock);
79
+ vi.mocked(EthBridger).mockImplementation(function () {
80
+ return ethBridgerMock;
81
+ });
78
82
  const withdrawInput = {
79
83
  ...commonInput,
80
84
  sellAsset: ETH_ARBITRUM,
@@ -109,7 +113,9 @@ describe('getTradeQuote', () => {
109
113
  .fn()
110
114
  .mockResolvedValue('0x0c66f315542fdec1d312c415b14eef614b0910ef'),
111
115
  };
112
- vi.mocked(Erc20Bridger).mockReturnValue(Erc20BridgerMock);
116
+ vi.mocked(Erc20Bridger).mockImplementation(function () {
117
+ return Erc20BridgerMock;
118
+ });
113
119
  const erc20DepositInput = {
114
120
  ...commonInput,
115
121
  sellAsset: FOX_MAINNET,
@@ -144,7 +150,9 @@ describe('getTradeQuote', () => {
144
150
  .fn()
145
151
  .mockResolvedValue('0x0c66f315542fdec1d312c415b14eef614b0910ef'),
146
152
  };
147
- vi.mocked(Erc20Bridger).mockReturnValue(Erc20BridgerMock);
153
+ vi.mocked(Erc20Bridger).mockImplementation(function () {
154
+ return Erc20BridgerMock;
155
+ });
148
156
  const erc20WithdrawInput = {
149
157
  ...commonInput,
150
158
  sellAsset: FOX_ARBITRUM,
@@ -3,7 +3,8 @@ import { v4 as uuid } from 'uuid';
3
3
  import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants.js';
4
4
  import { SwapperName, TradeQuoteError } from '../../../types.js';
5
5
  import { makeSwapErrorRight } from '../../../utils.js';
6
- import { fetchBebopSolanaPrice } from '../utils/fetchFromBebop.js';
6
+ import { BEBOP_SOLANA_DUMMY_ADDRESS } from '../types.js';
7
+ import { fetchBebopSolanaQuote } from '../utils/fetchFromBebop.js';
7
8
  import { assertValidTrade, calculateRate, isBebopSolanaTxSafe } from '../utils/helpers/helpers.js';
8
9
  export async function getBebopSolanaTradeRate(input, _assetsById, apiKey) {
9
10
  const { sellAsset, buyAsset, accountNumber, receiveAddress, affiliateBps, sellAmountIncludingProtocolFeesCryptoBaseUnit, } = input;
@@ -12,17 +13,20 @@ export async function getBebopSolanaTradeRate(input, _assetsById, apiKey) {
12
13
  return Err(assertion.unwrapErr());
13
14
  const slippageTolerancePercentageDecimal = input.slippageTolerancePercentageDecimal ??
14
15
  getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Bebop);
15
- const maybeBebopPriceResponse = await fetchBebopSolanaPrice({
16
+ const address = receiveAddress ?? BEBOP_SOLANA_DUMMY_ADDRESS;
17
+ const maybeBebopQuoteResponse = await fetchBebopSolanaQuote({
16
18
  buyAsset,
17
19
  sellAsset,
18
20
  sellAmountIncludingProtocolFeesCryptoBaseUnit,
19
- receiveAddress,
21
+ takerAddress: address,
22
+ receiverAddress: address,
23
+ slippageTolerancePercentageDecimal,
20
24
  affiliateBps,
21
25
  apiKey,
22
26
  });
23
- if (maybeBebopPriceResponse.isErr())
24
- return Err(maybeBebopPriceResponse.unwrapErr());
25
- const bebopPriceResponse = maybeBebopPriceResponse.unwrap();
27
+ if (maybeBebopQuoteResponse.isErr())
28
+ return Err(maybeBebopQuoteResponse.unwrapErr());
29
+ const bebopPriceResponse = maybeBebopQuoteResponse.unwrap();
26
30
  const sellTokenAddress = Object.keys(bebopPriceResponse.sellTokens)[0];
27
31
  const buyTokenAddress = Object.keys(bebopPriceResponse.buyTokens)[0];
28
32
  if (!sellTokenAddress || !buyTokenAddress) {
@@ -37,15 +37,7 @@ export async function getBebopTradeQuote(input, assertGetEvmChainAdapter, _asset
37
37
  });
38
38
  if (maybeBebopQuoteResponse.isErr())
39
39
  return Err(maybeBebopQuoteResponse.unwrapErr());
40
- const bebopQuoteResponse = maybeBebopQuoteResponse.unwrap();
41
- const bestRoute = bebopQuoteResponse.routes.find(r => r.type === bebopQuoteResponse.bestPrice);
42
- if (!bestRoute || !bestRoute.quote) {
43
- return Err(makeSwapErrorRight({
44
- message: 'No best route found',
45
- code: TradeQuoteError.NoRouteFound,
46
- }));
47
- }
48
- const quote = bestRoute.quote;
40
+ const quote = maybeBebopQuoteResponse.unwrap();
49
41
  const sellTokenAddress = Object.keys(quote.sellTokens)[0];
50
42
  const buyTokenAddress = Object.keys(quote.buyTokens)[0];
51
43
  if (!isAddress(sellTokenAddress) || !isAddress(buyTokenAddress)) {
@@ -8,7 +8,8 @@ import { SwapperName, TradeQuoteError } from '../../../types.js';
8
8
  import { makeSwapErrorRight } from '../../../utils.js';
9
9
  import { buildAffiliateFee } from '../../utils/affiliateFee.js';
10
10
  import { isNativeEvmAsset } from '../../utils/helpers/helpers.js';
11
- import { fetchBebopPrice } from '../utils/fetchFromBebop.js';
11
+ import { BEBOP_DUMMY_ADDRESS } from '../types.js';
12
+ import { fetchBebopQuote } from '../utils/fetchFromBebop.js';
12
13
  import { assertValidTrade, calculateRate } from '../utils/helpers/helpers.js';
13
14
  export async function getBebopTradeRate(input, assertGetEvmChainAdapter, _assetsById, apiKey) {
14
15
  const { sellAsset, buyAsset, accountNumber, receiveAddress, affiliateBps, sellAmountIncludingProtocolFeesCryptoBaseUnit, } = input;
@@ -17,25 +18,20 @@ export async function getBebopTradeRate(input, assertGetEvmChainAdapter, _assets
17
18
  return Err(assertion.unwrapErr());
18
19
  const slippageTolerancePercentageDecimal = input.slippageTolerancePercentageDecimal ??
19
20
  getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Bebop);
20
- const maybeBebopPriceResponse = await fetchBebopPrice({
21
+ const address = receiveAddress ?? BEBOP_DUMMY_ADDRESS;
22
+ const maybeBebopQuoteResponse = await fetchBebopQuote({
21
23
  buyAsset,
22
24
  sellAsset,
23
25
  sellAmountIncludingProtocolFeesCryptoBaseUnit,
24
- receiveAddress,
26
+ takerAddress: address,
27
+ receiverAddress: address,
28
+ slippageTolerancePercentageDecimal,
25
29
  affiliateBps,
26
30
  apiKey,
27
31
  });
28
- if (maybeBebopPriceResponse.isErr())
29
- return Err(maybeBebopPriceResponse.unwrapErr());
30
- const bebopPriceResponse = maybeBebopPriceResponse.unwrap();
31
- const bestRoute = bebopPriceResponse.routes.find(r => r.type === bebopPriceResponse.bestPrice);
32
- if (!bestRoute || !bestRoute.quote) {
33
- return Err(makeSwapErrorRight({
34
- message: 'No best route found',
35
- code: TradeQuoteError.NoRouteFound,
36
- }));
37
- }
38
- const quote = bestRoute.quote;
32
+ if (maybeBebopQuoteResponse.isErr())
33
+ return Err(maybeBebopQuoteResponse.unwrapErr());
34
+ const quote = maybeBebopQuoteResponse.unwrap();
39
35
  const sellTokenAddress = Object.keys(quote.sellTokens)[0];
40
36
  const buyTokenAddress = Object.keys(quote.buyTokens)[0];
41
37
  if (!isAddress(sellTokenAddress) || !isAddress(buyTokenAddress)) {
@@ -3,87 +3,73 @@ import type { Address, Hex } from 'viem';
3
3
  export declare const bebopSupportedEvmChainIds: readonly [KnownChainIds.EthereumMainnet, KnownChainIds.PolygonMainnet, KnownChainIds.ArbitrumMainnet, KnownChainIds.BaseMainnet, KnownChainIds.AvalancheMainnet, KnownChainIds.OptimismMainnet, KnownChainIds.BnbSmartChainMainnet];
4
4
  export declare const bebopSupportedChainIds: readonly [KnownChainIds.EthereumMainnet, KnownChainIds.PolygonMainnet, KnownChainIds.ArbitrumMainnet, KnownChainIds.BaseMainnet, KnownChainIds.AvalancheMainnet, KnownChainIds.OptimismMainnet, KnownChainIds.BnbSmartChainMainnet, KnownChainIds.SolanaMainnet];
5
5
  export type BebopSupportedChainId = (typeof bebopSupportedChainIds)[number];
6
- export type BebopQuoteRoute = {
6
+ export type BebopQuoteResponse = {
7
+ requestId: string;
7
8
  type: string;
8
- quote: {
9
- requestId: string;
10
- type: string;
11
- status: string;
12
- quoteId: string;
13
- chainId: number;
14
- approvalType: 'Standard' | 'Permit2';
15
- nativeToken: string;
16
- taker: Address;
17
- receiver: Address;
9
+ status: string;
10
+ quoteId: string;
11
+ chainId: number;
12
+ approvalType: 'Standard' | 'Permit' | 'Permit2';
13
+ nativeToken: string;
14
+ taker: Address;
15
+ receiver: Address;
16
+ expiry: number;
17
+ slippage: number;
18
+ gasFee: {
19
+ native: string;
20
+ usd: number;
21
+ };
22
+ buyTokens: Record<Address, {
23
+ amount: string;
24
+ decimals: number;
25
+ priceUsd: number;
26
+ symbol: string;
27
+ minimumAmount: string;
28
+ price: number;
29
+ priceBeforeFee: number;
30
+ amountBeforeFee: string;
31
+ deltaFromExpected: number;
32
+ }>;
33
+ sellTokens: Record<Address, {
34
+ amount: string;
35
+ decimals: number;
36
+ priceUsd: number;
37
+ symbol: string;
38
+ price: number;
39
+ priceBeforeFee: number;
40
+ }>;
41
+ settlementAddress: Address;
42
+ approvalTarget: Address;
43
+ requiredSignatures: string[];
44
+ priceImpact: number;
45
+ warnings: string[];
46
+ toSign: {
47
+ partner_id: number;
18
48
  expiry: number;
19
- slippage: number;
20
- gasFee: {
21
- native: string;
22
- usd: number;
23
- };
24
- buyTokens: Record<Address, {
25
- amount: string;
26
- decimals: number;
27
- priceUsd: number;
28
- symbol: string;
29
- minimumAmount: string;
30
- price: number;
31
- priceBeforeFee: number;
32
- amountBeforeFee: string;
33
- deltaFromExpected: number;
34
- }>;
35
- sellTokens: Record<Address, {
36
- amount: string;
37
- decimals: number;
38
- priceUsd: number;
39
- symbol: string;
40
- price: number;
41
- priceBeforeFee: number;
42
- }>;
43
- settlementAddress: Address;
44
- approvalTarget: Address;
45
- requiredSignatures: string[];
46
- priceImpact: number;
47
- warnings: string[];
48
- toSign: {
49
- partner_id: number;
50
- expiry: number;
51
- taker_address: Address;
52
- maker_address: Address;
53
- maker_nonce: string;
54
- taker_token: Address;
55
- maker_token: Address;
56
- taker_amount: string;
57
- maker_amount: string;
58
- receiver: Address;
59
- packed_commands: string;
60
- };
61
- onchainOrderType?: string;
62
- solver?: string;
63
- makers?: string[];
64
- partialFillOffset?: number;
65
- tx: {
66
- to: Address;
67
- from: Address;
68
- data: Hex;
69
- value: Hex;
70
- gas?: number;
71
- gasPrice?: number;
72
- };
73
- partnerFee?: Record<Address, string>;
74
- protocolFee?: Record<Address, string>;
49
+ taker_address: Address;
50
+ maker_address: Address;
51
+ maker_nonce: string;
52
+ taker_token: Address;
53
+ maker_token: Address;
54
+ taker_amount: string;
55
+ maker_amount: string;
56
+ receiver: Address;
57
+ packed_commands: string;
75
58
  };
76
- };
77
- export type BebopError = {
78
- errorCode: number;
79
- message: string;
80
- requestId: string;
81
- };
82
- export type BebopQuoteResponse = {
83
- routes: BebopQuoteRoute[];
84
- errors: Record<string, BebopError>;
85
- link: string;
86
- bestPrice: string;
59
+ onchainOrderType?: string;
60
+ solver?: string;
61
+ makers?: string[];
62
+ partialFillOffset?: number;
63
+ tx: {
64
+ to: Address;
65
+ from: Address;
66
+ data: Hex;
67
+ value: Hex;
68
+ gas?: number;
69
+ gasPrice?: number;
70
+ };
71
+ partnerFee?: Record<Address, string>;
72
+ protocolFee?: Record<Address, string>;
87
73
  };
88
74
  export declare const chainIdToBebopChain: Record<BebopSupportedChainId, string>;
89
75
  export declare const BEBOP_NATIVE_MARKER = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
@@ -13,14 +13,6 @@ export declare const fetchBebopQuote: ({ buyAsset, sellAsset, sellAmountIncludin
13
13
  affiliateBps?: string | undefined;
14
14
  apiKey: string;
15
15
  }) => Promise<Result<BebopQuoteResponse, SwapErrorRight>>;
16
- export declare const fetchBebopPrice: ({ buyAsset, sellAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit, receiveAddress, affiliateBps, apiKey, }: {
17
- buyAsset: Asset;
18
- sellAsset: Asset;
19
- sellAmountIncludingProtocolFeesCryptoBaseUnit: string;
20
- receiveAddress: string | undefined;
21
- affiliateBps?: string | undefined;
22
- apiKey: string;
23
- }) => Promise<Result<BebopQuoteResponse, SwapErrorRight>>;
24
16
  export declare const fetchBebopSolanaQuote: ({ buyAsset, sellAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit, takerAddress, receiverAddress, slippageTolerancePercentageDecimal, affiliateBps, apiKey, }: {
25
17
  buyAsset: Asset;
26
18
  sellAsset: Asset;
@@ -31,11 +23,3 @@ export declare const fetchBebopSolanaQuote: ({ buyAsset, sellAsset, sellAmountIn
31
23
  affiliateBps?: string | undefined;
32
24
  apiKey: string;
33
25
  }) => Promise<Result<BebopSolanaQuoteResponse, SwapErrorRight>>;
34
- export declare const fetchBebopSolanaPrice: ({ buyAsset, sellAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit, receiveAddress, affiliateBps, apiKey, }: {
35
- buyAsset: Asset;
36
- sellAsset: Asset;
37
- sellAmountIncludingProtocolFeesCryptoBaseUnit: string;
38
- receiveAddress: string | undefined;
39
- affiliateBps?: string | undefined;
40
- apiKey: string;
41
- }) => Promise<Result<BebopSolanaQuoteResponse, SwapErrorRight>>;
@@ -1,9 +1,11 @@
1
- import { bn } from '@shapeshiftoss/utils';
1
+ import { solAssetId } from '@shapeshiftoss/caip';
2
+ import { bn, bnOrZero } from '@shapeshiftoss/utils';
2
3
  import { Err, Ok } from '@sniptt/monads';
3
4
  import { getAddress } from 'viem';
4
5
  import { TradeQuoteError } from '../../../types.js';
5
6
  import { makeSwapErrorRight } from '../../../utils.js';
6
- import { BEBOP_DUMMY_ADDRESS, BEBOP_SOLANA_DUMMY_ADDRESS, chainIdToBebopChain } from '../types.js';
7
+ import { getTreasuryAddressFromChainId } from '../../utils/helpers/helpers.js';
8
+ import { chainIdToBebopChain } from '../types.js';
7
9
  import { bebopServiceFactory } from './bebopService.js';
8
10
  import { assetIdToBebopSolanaToken, assetIdToBebopToken } from './helpers/helpers.js';
9
11
  export const fetchBebopQuote = async ({ buyAsset, sellAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit, takerAddress, receiverAddress, slippageTolerancePercentageDecimal, affiliateBps, apiKey, }) => {
@@ -14,14 +16,8 @@ export const fetchBebopQuote = async ({ buyAsset, sellAsset, sellAmountIncluding
14
16
  const checksummedReceiverAddress = getAddress(receiverAddress);
15
17
  const chainName = chainIdToBebopChain[sellAsset.chainId];
16
18
  const sellAmountFormatted = bn(sellAmountIncludingProtocolFeesCryptoBaseUnit).toFixed(0);
17
- // Bebop API expects slippage as percentage (not basis points like other APIs)
18
- // e.g. 0.3% → send as 0.3, not 30
19
- // See: https://api.bebop.xyz/pmm/ethereum/docs#/v3/quote_v3_quote_get
20
- const slippagePercentage = bn(slippageTolerancePercentageDecimal ?? 0.003)
21
- .times(100)
22
- .toNumber();
23
- const url = `https://api.bebop.xyz/router/${chainName}/v1/quote`;
24
- const params = new URLSearchParams({
19
+ const slippagePercentage = bn(slippageTolerancePercentageDecimal).times(100).toNumber();
20
+ const baseParams = {
25
21
  sell_tokens: sellToken,
26
22
  buy_tokens: buyToken,
27
23
  sell_amounts: sellAmountFormatted,
@@ -32,38 +28,46 @@ export const fetchBebopQuote = async ({ buyAsset, sellAsset, sellAmountIncluding
32
28
  skip_validation: 'true',
33
29
  gasless: 'false',
34
30
  source: 'shapeshift',
35
- });
31
+ };
32
+ const jamParams = new URLSearchParams(baseParams);
33
+ const pmmParams = new URLSearchParams(baseParams);
36
34
  if (affiliateBps && affiliateBps !== '0') {
37
- params.set('fee', affiliateBps);
35
+ // JAM collects the fee on-chain and requires a recipient
36
+ jamParams.set('fee', affiliateBps);
37
+ jamParams.set('fee_recipient', getAddress(getTreasuryAddressFromChainId(buyAsset.chainId)));
38
+ // PMM attributes the fee off-chain via source
39
+ pmmParams.set('fee', affiliateBps);
38
40
  }
39
- const bebopService = bebopServiceFactory({ apiKey });
40
- const maybeResponse = await bebopService.get(`${url}?${params}`);
41
- if (maybeResponse.isErr()) {
41
+ const service = bebopServiceFactory({ apiKey });
42
+ const [maybeJam, maybePmm] = await Promise.all([
43
+ service.get(`https://api.bebop.xyz/jam/${chainName}/v2/quote`, {
44
+ params: jamParams,
45
+ }),
46
+ service.get(`https://api.bebop.xyz/pmm/${chainName}/v3/quote`, {
47
+ params: pmmParams,
48
+ }),
49
+ ]);
50
+ const maybeResponses = [maybeJam, maybePmm];
51
+ if (maybeResponses.every(maybeResponse => maybeResponse.isErr())) {
42
52
  return Err(makeSwapErrorRight({
43
53
  message: 'Failed to fetch quote from Bebop',
44
- cause: maybeResponse.unwrapErr().cause,
54
+ cause: maybeResponses[0].unwrapErr().cause,
45
55
  code: TradeQuoteError.QueryFailed,
46
56
  }));
47
57
  }
48
- const response = maybeResponse.unwrap();
49
- // Log partial route failures for debugging (these are normal and don't indicate quote failure)
50
- if (response.data.errors && Object.keys(response.data.errors).length > 0) {
51
- console.debug('[Bebop] Some routes failed (this is normal):', response.data.errors);
52
- }
53
- // Validate response has routes - only fail if there are NO valid routes
54
- if (!response.data.routes || response.data.routes.length === 0) {
58
+ const quotes = maybeResponses
59
+ .filter(maybeResponse => maybeResponse.isOk())
60
+ .map(maybeResponse => maybeResponse.unwrap().data)
61
+ .filter(quote => Boolean(quote.tx?.data));
62
+ if (!quotes.length) {
55
63
  return Err(makeSwapErrorRight({
56
- message: 'No routes available',
64
+ message: 'No route available',
57
65
  code: TradeQuoteError.NoRouteFound,
58
66
  }));
59
67
  }
60
- if (!response.data.bestPrice) {
61
- return Err(makeSwapErrorRight({
62
- message: 'No best price route specified',
63
- code: TradeQuoteError.InvalidResponse,
64
- }));
65
- }
66
- return Ok(response.data);
68
+ const getBuyAmount = (quote) => bnOrZero(Object.values(quote.buyTokens)[0]?.amount);
69
+ const bestQuote = quotes.reduce((best, quote) => getBuyAmount(quote).gt(getBuyAmount(best)) ? quote : best);
70
+ return Ok(bestQuote);
67
71
  }
68
72
  catch (error) {
69
73
  return Err(makeSwapErrorRight({
@@ -73,28 +77,20 @@ export const fetchBebopQuote = async ({ buyAsset, sellAsset, sellAmountIncluding
73
77
  }));
74
78
  }
75
79
  };
76
- export const fetchBebopPrice = ({ buyAsset, sellAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit, receiveAddress, affiliateBps, apiKey, }) => {
77
- const address = receiveAddress || BEBOP_DUMMY_ADDRESS;
78
- return fetchBebopQuote({
79
- buyAsset,
80
- sellAsset,
81
- sellAmountIncludingProtocolFeesCryptoBaseUnit,
82
- takerAddress: address,
83
- receiverAddress: address,
84
- slippageTolerancePercentageDecimal: '0.01',
85
- affiliateBps,
86
- apiKey,
87
- });
88
- };
89
80
  export const fetchBebopSolanaQuote = async ({ buyAsset, sellAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit, takerAddress, receiverAddress, slippageTolerancePercentageDecimal, affiliateBps, apiKey, }) => {
90
81
  try {
82
+ // Bebop's Solana routes don't wrap native SOL on the input side, so selling native SOL
83
+ // always fails on-chain. Reject up front instead of returning an unexecutable quote.
84
+ if (sellAsset.assetId === solAssetId) {
85
+ return Err(makeSwapErrorRight({
86
+ message: 'Bebop Solana cannot sell native SOL',
87
+ code: TradeQuoteError.NoRouteFound,
88
+ }));
89
+ }
91
90
  const sellToken = assetIdToBebopSolanaToken(sellAsset.assetId);
92
91
  const buyToken = assetIdToBebopSolanaToken(buyAsset.assetId);
93
92
  const sellAmountFormatted = bn(sellAmountIncludingProtocolFeesCryptoBaseUnit).toFixed(0);
94
- const slippagePercentage = bn(slippageTolerancePercentageDecimal ?? 0.003)
95
- .times(100)
96
- .toNumber();
97
- const url = 'https://api.bebop.xyz/pmm/solana/v3/quote';
93
+ const slippagePercentage = bn(slippageTolerancePercentageDecimal).times(100).toNumber();
98
94
  const params = new URLSearchParams({
99
95
  sell_tokens: sellToken,
100
96
  buy_tokens: buyToken,
@@ -110,8 +106,7 @@ export const fetchBebopSolanaQuote = async ({ buyAsset, sellAsset, sellAmountInc
110
106
  if (affiliateBps && affiliateBps !== '0') {
111
107
  params.set('fee', affiliateBps);
112
108
  }
113
- const bebopService = bebopServiceFactory({ apiKey });
114
- const maybeResponse = await bebopService.get(`${url}?${params}`);
109
+ const maybeResponse = await bebopServiceFactory({ apiKey }).get('https://api.bebop.xyz/pmm/solana/v3/quote', { params });
115
110
  if (maybeResponse.isErr()) {
116
111
  const err = maybeResponse.unwrapErr();
117
112
  return Err(makeSwapErrorRight({
@@ -133,19 +128,6 @@ export const fetchBebopSolanaQuote = async ({ buyAsset, sellAsset, sellAmountInc
133
128
  code: TradeQuoteError.InvalidResponse,
134
129
  }));
135
130
  }
136
- // Reject routes containing ANY AMM/CLMM makers - these produce malformed txs
137
- // (wrong signature count in wire format) and require pre-existing ATAs that
138
- // Bebop's gasless co-signed flow can't create. This includes mixed routes
139
- // like ["raydium clmm-rfqm", "🦊"] where Bebop serializes the tx with fewer
140
- // signature slots than the message header requires.
141
- // When rejected, other swappers like Jupiter will handle these pairs instead.
142
- const hasAmmRoute = response.data.makers.some(maker => maker.toLowerCase().includes('clmm') || maker.toLowerCase().includes('amm'));
143
- if (hasAmmRoute) {
144
- return Err(makeSwapErrorRight({
145
- message: `Bebop Solana quote contains AMM routing (${response.data.makers.join(', ')}), which produces malformed txs`,
146
- code: TradeQuoteError.NoRouteFound,
147
- }));
148
- }
149
131
  return Ok(response.data);
150
132
  }
151
133
  catch (error) {
@@ -156,16 +138,3 @@ export const fetchBebopSolanaQuote = async ({ buyAsset, sellAsset, sellAmountInc
156
138
  }));
157
139
  }
158
140
  };
159
- export const fetchBebopSolanaPrice = ({ buyAsset, sellAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit, receiveAddress, affiliateBps, apiKey, }) => {
160
- const address = receiveAddress || BEBOP_SOLANA_DUMMY_ADDRESS;
161
- return fetchBebopSolanaQuote({
162
- buyAsset,
163
- sellAsset,
164
- sellAmountIncludingProtocolFeesCryptoBaseUnit,
165
- takerAddress: address,
166
- receiverAddress: address,
167
- slippageTolerancePercentageDecimal: '0.01',
168
- affiliateBps,
169
- apiKey,
170
- });
171
- };
@@ -0,0 +1,2 @@
1
+ import type { Swapper } from '../../types.js';
2
+ export declare const bobGatewaySwapper: Swapper;
@@ -0,0 +1,5 @@
1
+ import { executeEvmTransaction } from '../../utils.js';
2
+ export const bobGatewaySwapper = {
3
+ executeEvmTransaction,
4
+ executeUtxoTransaction: (txToSign, { signAndBroadcastTransaction }) => signAndBroadcastTransaction(txToSign),
5
+ };
@@ -0,0 +1,2 @@
1
+ import type { SwapperApi } from '../../types.js';
2
+ export declare const bobGatewayApi: SwapperApi;