@shapeshiftoss/swapper 20.3.0 → 20.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/constants.js +15 -0
  3. package/dist/cjs/index.d.ts +2 -0
  4. package/dist/cjs/index.js +2 -0
  5. package/dist/cjs/swappers/ArbitrumBridgeSwapper/getTradeQuote/getTradeQuote.js +0 -2
  6. package/dist/cjs/swappers/AvnuSwapper/swapperApi/getTradeQuote.js +1 -2
  7. package/dist/cjs/swappers/BebopSwapper/utils/fetchFromBebop.d.ts +2 -1
  8. package/dist/cjs/swappers/BebopSwapper/utils/fetchFromBebop.js +21 -15
  9. package/dist/cjs/swappers/BebopSwapper/utils/getBebopSolanaTradeContext.js +1 -0
  10. package/dist/cjs/swappers/BobGatewaySwapper/swapperApi/getTradeQuote.js +0 -2
  11. package/dist/cjs/swappers/ButterSwap/swapperApi/getTradeQuote.js +0 -2
  12. package/dist/cjs/swappers/CetusSwapper/swapperApi/getTradeQuote.js +0 -2
  13. package/dist/cjs/swappers/ChainflipSwapper/swapperApi/getTradeQuote.js +1 -2
  14. package/dist/cjs/swappers/ChainflipSwapper/types.d.ts +1 -0
  15. package/dist/cjs/swappers/DebridgeSwapper/getTradeQuote/getTradeQuote.js +0 -2
  16. package/dist/cjs/swappers/FyndSwapper/FyndSwapper.d.ts +2 -0
  17. package/dist/cjs/swappers/FyndSwapper/FyndSwapper.js +5 -0
  18. package/dist/cjs/swappers/FyndSwapper/endpoints.d.ts +2 -0
  19. package/dist/cjs/swappers/FyndSwapper/endpoints.js +14 -0
  20. package/dist/cjs/swappers/FyndSwapper/getTradeQuote/getTradeQuote.d.ts +4 -0
  21. package/dist/cjs/swappers/FyndSwapper/getTradeQuote/getTradeQuote.js +43 -0
  22. package/dist/cjs/swappers/FyndSwapper/getTradeRate/getTradeRate.d.ts +4 -0
  23. package/dist/cjs/swappers/FyndSwapper/getTradeRate/getTradeRate.js +34 -0
  24. package/dist/cjs/swappers/FyndSwapper/index.d.ts +2 -0
  25. package/dist/cjs/swappers/FyndSwapper/index.js +7 -0
  26. package/dist/cjs/swappers/FyndSwapper/types.d.ts +41 -0
  27. package/dist/cjs/swappers/FyndSwapper/types.js +2 -0
  28. package/dist/cjs/swappers/FyndSwapper/utils/constants.d.ts +33 -0
  29. package/dist/cjs/swappers/FyndSwapper/utils/constants.js +38 -0
  30. package/dist/cjs/swappers/FyndSwapper/utils/fetchFromFynd.d.ts +13 -0
  31. package/dist/cjs/swappers/FyndSwapper/utils/fetchFromFynd.js +42 -0
  32. package/dist/cjs/swappers/FyndSwapper/utils/fyndService.d.ts +5 -0
  33. package/dist/cjs/swappers/FyndSwapper/utils/fyndService.js +9 -0
  34. package/dist/cjs/swappers/FyndSwapper/utils/getFyndStepData.d.ts +25 -0
  35. package/dist/cjs/swappers/FyndSwapper/utils/getFyndStepData.js +48 -0
  36. package/dist/cjs/swappers/FyndSwapper/utils/getFyndTradeContext.d.ts +18 -0
  37. package/dist/cjs/swappers/FyndSwapper/utils/getFyndTradeContext.js +94 -0
  38. package/dist/cjs/swappers/FyndSwapper/utils/helpers.d.ts +24 -0
  39. package/dist/cjs/swappers/FyndSwapper/utils/helpers.js +174 -0
  40. package/dist/cjs/swappers/FyndSwapper/utils/helpers.test.d.ts +1 -0
  41. package/dist/cjs/swappers/FyndSwapper/utils/helpers.test.js +101 -0
  42. package/dist/cjs/swappers/MayachainSwapper/generated/generatedTradableAssetMap.json +0 -1
  43. package/dist/cjs/swappers/PortalsSwapper/endpoints.js +4 -1
  44. package/dist/cjs/swappers/PortalsSwapper/getPortalsTradeQuote/getPortalsTradeQuote.js +1 -1
  45. package/dist/cjs/swappers/RelaySwapper/getTradeQuote/getTradeQuote.js +2 -3
  46. package/dist/cjs/swappers/RelaySwapper/utils/getRelayTradeContext.d.ts +1 -0
  47. package/dist/cjs/swappers/RelaySwapper/utils/getRelayTradeContext.js +4 -0
  48. package/dist/cjs/swappers/RelaySwapper/utils/relayStatus.js +3 -3
  49. package/dist/cjs/swappers/RelaySwapper/utils/types.d.ts +9 -4
  50. package/dist/cjs/swappers/SymbiosisSwapper/SymbiosisSwapper.d.ts +2 -0
  51. package/dist/cjs/swappers/SymbiosisSwapper/SymbiosisSwapper.js +8 -0
  52. package/dist/cjs/swappers/SymbiosisSwapper/endpoints.d.ts +2 -0
  53. package/dist/cjs/swappers/SymbiosisSwapper/endpoints.js +66 -0
  54. package/dist/cjs/swappers/SymbiosisSwapper/getTradeQuote/getTradeQuote.d.ts +4 -0
  55. package/dist/cjs/swappers/SymbiosisSwapper/getTradeQuote/getTradeQuote.js +42 -0
  56. package/dist/cjs/swappers/SymbiosisSwapper/getTradeRate/getTradeRate.d.ts +4 -0
  57. package/dist/cjs/swappers/SymbiosisSwapper/getTradeRate/getTradeRate.js +34 -0
  58. package/dist/cjs/swappers/SymbiosisSwapper/index.d.ts +2 -0
  59. package/dist/cjs/swappers/SymbiosisSwapper/index.js +7 -0
  60. package/dist/cjs/swappers/SymbiosisSwapper/utils/constants.d.ts +19 -0
  61. package/dist/cjs/swappers/SymbiosisSwapper/utils/constants.js +64 -0
  62. package/dist/cjs/swappers/SymbiosisSwapper/utils/getSymbiosisStepData.d.ts +26 -0
  63. package/dist/cjs/swappers/SymbiosisSwapper/utils/getSymbiosisStepData.js +106 -0
  64. package/dist/cjs/swappers/SymbiosisSwapper/utils/getSymbiosisStepData.test.d.ts +1 -0
  65. package/dist/cjs/swappers/SymbiosisSwapper/utils/getSymbiosisStepData.test.js +161 -0
  66. package/dist/cjs/swappers/SymbiosisSwapper/utils/getSymbiosisTradeContext.d.ts +17 -0
  67. package/dist/cjs/swappers/SymbiosisSwapper/utils/getSymbiosisTradeContext.js +146 -0
  68. package/dist/cjs/swappers/SymbiosisSwapper/utils/helpers.d.ts +38 -0
  69. package/dist/cjs/swappers/SymbiosisSwapper/utils/helpers.js +172 -0
  70. package/dist/cjs/swappers/SymbiosisSwapper/utils/helpers.test.d.ts +1 -0
  71. package/dist/cjs/swappers/SymbiosisSwapper/utils/helpers.test.js +151 -0
  72. package/dist/cjs/swappers/SymbiosisSwapper/utils/symbiosisService.d.ts +5 -0
  73. package/dist/cjs/swappers/SymbiosisSwapper/utils/symbiosisService.js +18 -0
  74. package/dist/cjs/swappers/SymbiosisSwapper/utils/types.d.ts +83 -0
  75. package/dist/cjs/swappers/SymbiosisSwapper/utils/types.js +11 -0
  76. package/dist/cjs/swappers/ThorchainSwapper/generated/generatedThorLongtailTokens.json +1 -0
  77. package/dist/cjs/swappers/ThorchainSwapper/generated/generatedTradableAssetMap.json +1 -0
  78. package/dist/cjs/swappers/ThorchainSwapper/utils/getLongtailQuote.js +1 -1
  79. package/dist/cjs/swappers/ZrxSwapper/getZrxTradeQuote/getZrxTradeQuote.js +24 -1
  80. package/dist/cjs/swappers/ZrxSwapper/getZrxTradeQuote/getZrxTradeQuote.test.d.ts +1 -0
  81. package/dist/cjs/swappers/ZrxSwapper/getZrxTradeQuote/getZrxTradeQuote.test.js +110 -0
  82. package/dist/cjs/swappers/ZrxSwapper/types.d.ts +2 -1
  83. package/dist/cjs/swappers/ZrxSwapper/utils/getZrxNativeCheckDeadline.d.ts +1 -0
  84. package/dist/cjs/swappers/ZrxSwapper/utils/getZrxNativeCheckDeadline.js +26 -0
  85. package/dist/cjs/types.d.ts +6 -5
  86. package/dist/cjs/types.js +2 -0
  87. package/dist/cjs/utils/helpers.d.ts +1 -2
  88. package/dist/cjs/utils/helpers.js +8 -32
  89. package/dist/cjs/utils/helpers.test.js +6 -2
  90. package/dist/esm/.tsbuildinfo +1 -1
  91. package/dist/esm/constants.js +15 -0
  92. package/dist/esm/index.d.ts +2 -0
  93. package/dist/esm/index.js +2 -0
  94. package/dist/esm/swappers/ArbitrumBridgeSwapper/getTradeQuote/getTradeQuote.js +0 -2
  95. package/dist/esm/swappers/AvnuSwapper/swapperApi/getTradeQuote.js +1 -2
  96. package/dist/esm/swappers/BebopSwapper/utils/fetchFromBebop.d.ts +2 -1
  97. package/dist/esm/swappers/BebopSwapper/utils/fetchFromBebop.js +21 -15
  98. package/dist/esm/swappers/BebopSwapper/utils/getBebopSolanaTradeContext.js +1 -0
  99. package/dist/esm/swappers/BobGatewaySwapper/swapperApi/getTradeQuote.js +0 -2
  100. package/dist/esm/swappers/ButterSwap/swapperApi/getTradeQuote.js +0 -2
  101. package/dist/esm/swappers/CetusSwapper/swapperApi/getTradeQuote.js +0 -2
  102. package/dist/esm/swappers/ChainflipSwapper/swapperApi/getTradeQuote.js +1 -2
  103. package/dist/esm/swappers/ChainflipSwapper/types.d.ts +1 -0
  104. package/dist/esm/swappers/DebridgeSwapper/getTradeQuote/getTradeQuote.js +0 -2
  105. package/dist/esm/swappers/FyndSwapper/FyndSwapper.d.ts +2 -0
  106. package/dist/esm/swappers/FyndSwapper/FyndSwapper.js +2 -0
  107. package/dist/esm/swappers/FyndSwapper/endpoints.d.ts +2 -0
  108. package/dist/esm/swappers/FyndSwapper/endpoints.js +11 -0
  109. package/dist/esm/swappers/FyndSwapper/getTradeQuote/getTradeQuote.d.ts +4 -0
  110. package/dist/esm/swappers/FyndSwapper/getTradeQuote/getTradeQuote.js +39 -0
  111. package/dist/esm/swappers/FyndSwapper/getTradeRate/getTradeRate.d.ts +4 -0
  112. package/dist/esm/swappers/FyndSwapper/getTradeRate/getTradeRate.js +30 -0
  113. package/dist/esm/swappers/FyndSwapper/index.d.ts +2 -0
  114. package/dist/esm/swappers/FyndSwapper/index.js +2 -0
  115. package/dist/esm/swappers/FyndSwapper/types.d.ts +41 -0
  116. package/dist/esm/swappers/FyndSwapper/types.js +1 -0
  117. package/dist/esm/swappers/FyndSwapper/utils/constants.d.ts +33 -0
  118. package/dist/esm/swappers/FyndSwapper/utils/constants.js +35 -0
  119. package/dist/esm/swappers/FyndSwapper/utils/fetchFromFynd.d.ts +13 -0
  120. package/dist/esm/swappers/FyndSwapper/utils/fetchFromFynd.js +38 -0
  121. package/dist/esm/swappers/FyndSwapper/utils/fyndService.d.ts +5 -0
  122. package/dist/esm/swappers/FyndSwapper/utils/fyndService.js +3 -0
  123. package/dist/esm/swappers/FyndSwapper/utils/getFyndStepData.d.ts +25 -0
  124. package/dist/esm/swappers/FyndSwapper/utils/getFyndStepData.js +44 -0
  125. package/dist/esm/swappers/FyndSwapper/utils/getFyndTradeContext.d.ts +18 -0
  126. package/dist/esm/swappers/FyndSwapper/utils/getFyndTradeContext.js +90 -0
  127. package/dist/esm/swappers/FyndSwapper/utils/helpers.d.ts +24 -0
  128. package/dist/esm/swappers/FyndSwapper/utils/helpers.js +162 -0
  129. package/dist/esm/swappers/FyndSwapper/utils/helpers.test.d.ts +1 -0
  130. package/dist/esm/swappers/FyndSwapper/utils/helpers.test.js +99 -0
  131. package/dist/esm/swappers/MayachainSwapper/generated/generatedTradableAssetMap.json +0 -1
  132. package/dist/esm/swappers/PortalsSwapper/endpoints.js +4 -1
  133. package/dist/esm/swappers/PortalsSwapper/getPortalsTradeQuote/getPortalsTradeQuote.js +2 -2
  134. package/dist/esm/swappers/RelaySwapper/getTradeQuote/getTradeQuote.js +2 -3
  135. package/dist/esm/swappers/RelaySwapper/utils/getRelayTradeContext.d.ts +1 -0
  136. package/dist/esm/swappers/RelaySwapper/utils/getRelayTradeContext.js +5 -1
  137. package/dist/esm/swappers/RelaySwapper/utils/relayStatus.js +3 -3
  138. package/dist/esm/swappers/RelaySwapper/utils/types.d.ts +9 -4
  139. package/dist/esm/swappers/SymbiosisSwapper/SymbiosisSwapper.d.ts +2 -0
  140. package/dist/esm/swappers/SymbiosisSwapper/SymbiosisSwapper.js +5 -0
  141. package/dist/esm/swappers/SymbiosisSwapper/endpoints.d.ts +2 -0
  142. package/dist/esm/swappers/SymbiosisSwapper/endpoints.js +63 -0
  143. package/dist/esm/swappers/SymbiosisSwapper/getTradeQuote/getTradeQuote.d.ts +4 -0
  144. package/dist/esm/swappers/SymbiosisSwapper/getTradeQuote/getTradeQuote.js +38 -0
  145. package/dist/esm/swappers/SymbiosisSwapper/getTradeRate/getTradeRate.d.ts +4 -0
  146. package/dist/esm/swappers/SymbiosisSwapper/getTradeRate/getTradeRate.js +30 -0
  147. package/dist/esm/swappers/SymbiosisSwapper/index.d.ts +2 -0
  148. package/dist/esm/swappers/SymbiosisSwapper/index.js +2 -0
  149. package/dist/esm/swappers/SymbiosisSwapper/utils/constants.d.ts +19 -0
  150. package/dist/esm/swappers/SymbiosisSwapper/utils/constants.js +61 -0
  151. package/dist/esm/swappers/SymbiosisSwapper/utils/getSymbiosisStepData.d.ts +26 -0
  152. package/dist/esm/swappers/SymbiosisSwapper/utils/getSymbiosisStepData.js +102 -0
  153. package/dist/esm/swappers/SymbiosisSwapper/utils/getSymbiosisStepData.test.d.ts +1 -0
  154. package/dist/esm/swappers/SymbiosisSwapper/utils/getSymbiosisStepData.test.js +159 -0
  155. package/dist/esm/swappers/SymbiosisSwapper/utils/getSymbiosisTradeContext.d.ts +17 -0
  156. package/dist/esm/swappers/SymbiosisSwapper/utils/getSymbiosisTradeContext.js +139 -0
  157. package/dist/esm/swappers/SymbiosisSwapper/utils/helpers.d.ts +38 -0
  158. package/dist/esm/swappers/SymbiosisSwapper/utils/helpers.js +156 -0
  159. package/dist/esm/swappers/SymbiosisSwapper/utils/helpers.test.d.ts +1 -0
  160. package/dist/esm/swappers/SymbiosisSwapper/utils/helpers.test.js +149 -0
  161. package/dist/esm/swappers/SymbiosisSwapper/utils/symbiosisService.d.ts +5 -0
  162. package/dist/esm/swappers/SymbiosisSwapper/utils/symbiosisService.js +12 -0
  163. package/dist/esm/swappers/SymbiosisSwapper/utils/types.d.ts +83 -0
  164. package/dist/esm/swappers/SymbiosisSwapper/utils/types.js +8 -0
  165. package/dist/esm/swappers/ThorchainSwapper/generated/generatedThorLongtailTokens.json +1 -0
  166. package/dist/esm/swappers/ThorchainSwapper/generated/generatedTradableAssetMap.json +1 -0
  167. package/dist/esm/swappers/ThorchainSwapper/utils/getLongtailQuote.js +1 -1
  168. package/dist/esm/swappers/ZrxSwapper/getZrxTradeQuote/getZrxTradeQuote.js +25 -2
  169. package/dist/esm/swappers/ZrxSwapper/getZrxTradeQuote/getZrxTradeQuote.test.d.ts +1 -0
  170. package/dist/esm/swappers/ZrxSwapper/getZrxTradeQuote/getZrxTradeQuote.test.js +108 -0
  171. package/dist/esm/swappers/ZrxSwapper/types.d.ts +2 -1
  172. package/dist/esm/swappers/ZrxSwapper/utils/getZrxNativeCheckDeadline.d.ts +1 -0
  173. package/dist/esm/swappers/ZrxSwapper/utils/getZrxNativeCheckDeadline.js +22 -0
  174. package/dist/esm/types.d.ts +6 -5
  175. package/dist/esm/types.js +2 -0
  176. package/dist/esm/utils/helpers.d.ts +1 -2
  177. package/dist/esm/utils/helpers.js +9 -33
  178. package/dist/esm/utils/helpers.test.js +6 -2
  179. package/package.json +7 -7
@@ -2,11 +2,13 @@ import { Err, Ok } from '@sniptt/monads';
2
2
  import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants.js';
3
3
  import { SwapperName, TradeQuoteError } from '../../../types.js';
4
4
  import { assertQuoteAddresses, makeSwapErrorRight } from '../../../utils/index.js';
5
- import { FALLBACK_QUOTE_DEADLINE_MS, isNativeEvmAsset } from '../../../utils/helpers.js';
5
+ import { isNativeEvmAsset } from '../../../utils/helpers.js';
6
6
  import { fetchZrxQuote } from '../utils/fetchFromZrx.js';
7
+ import { getZrxNativeCheckDeadline } from '../utils/getZrxNativeCheckDeadline.js';
7
8
  import { getZrxStepData } from '../utils/getZrxStepData.js';
8
9
  import { getZrxTradeContext } from '../utils/getZrxTradeContext.js';
9
10
  import { assertValidTrade, isWrappedNativeSell } from '../utils/helpers.js';
11
+ const isValidDeadlineSeconds = (deadline) => Number.isSafeInteger(deadline) && deadline > 0 && Number.isSafeInteger(deadline * 1000);
10
12
  export const getZrxTradeQuote = async (input, deps) => {
11
13
  const { sellAsset, buyAsset, accountNumber, affiliateBps, sellAmountIncludingProtocolFeesCryptoBaseUnit, } = input;
12
14
  const maybeAddresses = assertQuoteAddresses(input);
@@ -39,6 +41,16 @@ export const getZrxTradeQuote = async (input, deps) => {
39
41
  return Err(maybeZrxQuoteResponse.unwrapErr());
40
42
  const { sellAmount, buyAmount, fees, permit2, transaction, route } = maybeZrxQuoteResponse.unwrap();
41
43
  const permit2Eip712 = permit2?.eip712;
44
+ const permit2Deadline = permit2Eip712 ? Number(permit2Eip712.message.deadline) : undefined;
45
+ if (permit2Deadline !== undefined &&
46
+ ((typeof permit2Eip712?.message.deadline !== 'string' &&
47
+ typeof permit2Eip712?.message.deadline !== 'number') ||
48
+ !isValidDeadlineSeconds(permit2Deadline))) {
49
+ return Err(makeSwapErrorRight({
50
+ message: 'Invalid Permit2 deadline from 0x response',
51
+ code: TradeQuoteError.InvalidResponse,
52
+ }));
53
+ }
42
54
  if (!isNativeEvmAsset(sellAsset.assetId) && !isWrappedNativeSell(route) && !permit2Eip712) {
43
55
  return Err(makeSwapErrorRight({
44
56
  message: 'Missing required Permit2 metadata from 0x response',
@@ -53,6 +65,17 @@ export const getZrxTradeQuote = async (input, deps) => {
53
65
  details: { transaction, permit2Eip712 },
54
66
  }));
55
67
  }
68
+ // Permit2 calldata is not decodable until the signature is spliced in, so only native sells are read
69
+ const nativeCheckDeadline = permit2Eip712
70
+ ? undefined
71
+ : getZrxNativeCheckDeadline(transaction.data);
72
+ if (nativeCheckDeadline !== undefined && !isValidDeadlineSeconds(nativeCheckDeadline)) {
73
+ return Err(makeSwapErrorRight({
74
+ message: 'Invalid NATIVE_CHECK deadline in 0x calldata',
75
+ code: TradeQuoteError.InvalidResponse,
76
+ }));
77
+ }
78
+ const deadlineSeconds = permit2Deadline ?? nativeCheckDeadline;
56
79
  const maybeContext = getZrxTradeContext({
57
80
  input,
58
81
  deps,
@@ -76,7 +99,7 @@ export const getZrxTradeQuote = async (input, deps) => {
76
99
  const tradeQuote = {
77
100
  ...tradeCommon,
78
101
  quoteOrRate: 'quote',
79
- deadline: Date.now() + FALLBACK_QUOTE_DEADLINE_MS,
102
+ deadline: deadlineSeconds === undefined ? undefined : deadlineSeconds * 1000,
80
103
  receiveAddress,
81
104
  steps: [
82
105
  {
@@ -0,0 +1,108 @@
1
+ import { KnownChainIds } from '@shapeshiftoss/types';
2
+ import { Ok } from '@sniptt/monads';
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+ import { TradeQuoteError } from '../../../types.js';
5
+ import { ETH, USDC_MAINNET, WETH } from '../../../utils/test-data/assets.js';
6
+ import { fetchZrxQuote } from '../utils/fetchFromZrx.js';
7
+ import { getZrxTradeQuote } from './getZrxTradeQuote.js';
8
+ vi.mock('../utils/fetchFromZrx', () => ({ fetchZrxQuote: vi.fn() }));
9
+ vi.mock('../utils/getZrxStepData', () => ({
10
+ getZrxStepData: vi.fn(({ permit2Eip712 }) => Promise.resolve(Ok({
11
+ transactionData: {
12
+ type: 'evm',
13
+ chainId: 1,
14
+ to: '0x1111111111111111111111111111111111111111',
15
+ data: '0x1234',
16
+ value: '0',
17
+ ...(permit2Eip712 && {
18
+ signatureRequired: { type: 'permit2', eip712: permit2Eip712 },
19
+ }),
20
+ },
21
+ networkFeeCryptoBaseUnit: '100000',
22
+ }))),
23
+ }));
24
+ const input = {
25
+ sellAsset: WETH,
26
+ buyAsset: USDC_MAINNET,
27
+ sellAmountIncludingProtocolFeesCryptoBaseUnit: '1000000000000000000',
28
+ sendAddress: '0x1111111111111111111111111111111111111111',
29
+ receiveAddress: '0x1111111111111111111111111111111111111111',
30
+ accountNumber: 0,
31
+ affiliateBps: '0',
32
+ allowMultiHop: false,
33
+ quoteOrRate: 'quote',
34
+ chainId: KnownChainIds.EthereumMainnet,
35
+ supportsEIP1559: true,
36
+ };
37
+ const deps = {
38
+ assetsById: {},
39
+ config: { VITE_ZRX_BASE_URL: 'https://example.com' },
40
+ };
41
+ const typedData = (deadline) => ({
42
+ domain: { name: 'Permit2', chainId: 1 },
43
+ types: { PermitTransferFrom: [{ name: 'deadline', type: 'uint256' }] },
44
+ primaryType: 'PermitTransferFrom',
45
+ message: { deadline },
46
+ });
47
+ // Live Settler calldata for an ETH -> USDC sell, NATIVE_CHECK deadline 1791997786
48
+ const nativeSellCalldata = '0x1fff991f000000000000000000000000ea8eb5ba11a3ea66f417ae29abf70c6fb4ba9626000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000e750ef800000000000000000000000000000000000000000000000000000000000000a0939d83c32b72441d72643cf60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000044bd01c226000000000000000000000000000000000000000000000000000000006acfb75a000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010438c9c147000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000024d0e30db00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e48d68a156000000000000000000000000666fedd4cdd4e890a5ad20e7b60975409435a64a00000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040c02aaa39b223fe8d0a0e5c4f27ead9083c756cc201000064fffd8963efd1fc6a506488495d951d5263988d25a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008434ee90ca000000000000000000000000f5c4f3dc02c3fb9279495a8fef7b0741da956157000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000e9a9ab900000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000000000000';
49
+ const quoteResponse = (eip712, data = '0x1234') => ({
50
+ blockNumber: '1',
51
+ buyAmount: '1000000',
52
+ buyToken: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
53
+ sellAmount: input.sellAmountIncludingProtocolFeesCryptoBaseUnit,
54
+ sellToken: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
55
+ fees: { integratorFee: null, zeroExFee: null, gasFee: null },
56
+ issues: { allowance: null, balance: null, simulationIncomplete: false, invalidSourcesPassed: [] },
57
+ liquidityAvailable: true,
58
+ minBuyAmount: '990000',
59
+ route: { fills: [], tokens: [] },
60
+ tokenMetadata: {
61
+ buyToken: { buyTaxBps: null, sellTaxBps: null },
62
+ sellToken: { buyTaxBps: null, sellTaxBps: null },
63
+ },
64
+ totalNetworkFee: null,
65
+ zid: 'test',
66
+ permit2: eip712 ? { type: 'Permit2', hash: '0x1234', eip712 } : null,
67
+ transaction: {
68
+ to: '0x1111111111111111111111111111111111111111',
69
+ data,
70
+ gas: '100000',
71
+ gasPrice: '1000000000',
72
+ value: '0',
73
+ },
74
+ });
75
+ describe('getZrxTradeQuote Permit2 deadline', () => {
76
+ beforeEach(() => {
77
+ vi.mocked(fetchZrxQuote).mockResolvedValue(Ok(quoteResponse(typedData('1791934983'))));
78
+ });
79
+ it.each(['1791934983', 1791934983])('uses the provider deadline in milliseconds (%s)', async (deadline) => {
80
+ const eip712 = typedData(deadline);
81
+ vi.mocked(fetchZrxQuote).mockResolvedValue(Ok(quoteResponse(eip712)));
82
+ const result = await getZrxTradeQuote(input, deps);
83
+ expect(result.isOk()).toBe(true);
84
+ const [quote] = result.unwrap();
85
+ expect(quote.deadline).toBe(1791934983000);
86
+ expect(quote.steps[0].transactionData).toMatchObject({
87
+ signatureRequired: { eip712 },
88
+ });
89
+ });
90
+ it.each([undefined, null, true, '', 'invalid', '-1', '1.5', '9007199254740991'])('rejects an invalid Permit2 deadline (%s)', async (deadline) => {
91
+ vi.mocked(fetchZrxQuote).mockResolvedValue(Ok(quoteResponse(typedData(deadline))));
92
+ const result = await getZrxTradeQuote(input, deps);
93
+ expect(result.isErr()).toBe(true);
94
+ expect(result.unwrapErr().code).toBe(TradeQuoteError.InvalidResponse);
95
+ });
96
+ it('reads the NATIVE_CHECK deadline from native-token sell calldata', async () => {
97
+ vi.mocked(fetchZrxQuote).mockResolvedValue(Ok(quoteResponse(null, nativeSellCalldata)));
98
+ const result = await getZrxTradeQuote({ ...input, sellAsset: ETH }, deps);
99
+ expect(result.isOk()).toBe(true);
100
+ expect(result.unwrap()[0].deadline).toBe(1791997786000);
101
+ });
102
+ it('leaves native-token quotes without a NATIVE_CHECK action free of a fabricated deadline', async () => {
103
+ vi.mocked(fetchZrxQuote).mockResolvedValue(Ok(quoteResponse(null)));
104
+ const result = await getZrxTradeQuote({ ...input, sellAsset: ETH }, deps);
105
+ expect(result.isOk()).toBe(true);
106
+ expect(result.unwrap()[0].deadline).toBeUndefined();
107
+ });
108
+ });
@@ -1,5 +1,6 @@
1
1
  import { KnownChainIds } from '@shapeshiftoss/types';
2
- import type { Address, TypedData } from 'viem';
2
+ import type { TypedData } from 'eip-712';
3
+ import type { Address } from 'viem';
3
4
  import type { GetEvmTradeQuoteInput, GetEvmTradeRateInput } from '../../types.js';
4
5
  export type ZrxTradeQuoteInput = GetEvmTradeQuoteInput;
5
6
  export type ZrxTradeRateInput = GetEvmTradeRateInput;
@@ -0,0 +1 @@
1
+ export declare const getZrxNativeCheckDeadline: (data: string) => number | undefined;
@@ -0,0 +1,22 @@
1
+ import { decodeFunctionData, parseAbi, toFunctionSelector } from 'viem';
2
+ const settlerAbi = parseAbi([
3
+ 'function execute((address recipient, address buyToken, uint256 minAmountOut) slippage, bytes[] actions, bytes32 zid)',
4
+ 'function NATIVE_CHECK(uint256 deadline, uint256 msgValue)',
5
+ ]);
6
+ const NATIVE_CHECK_SELECTOR = toFunctionSelector('function NATIVE_CHECK(uint256,uint256)');
7
+ // Native sells carry no Permit2, but Settler reverts with SignatureExpired past any NATIVE_CHECK deadline
8
+ export const getZrxNativeCheckDeadline = (data) => {
9
+ try {
10
+ const { functionName, args } = decodeFunctionData({ abi: settlerAbi, data: data });
11
+ if (functionName !== 'execute')
12
+ return undefined;
13
+ const deadlines = args[1]
14
+ .filter(action => action.startsWith(NATIVE_CHECK_SELECTOR))
15
+ .map(action => decodeFunctionData({ abi: settlerAbi, data: action }))
16
+ .flatMap(decoded => decoded.functionName === 'NATIVE_CHECK' ? [Number(decoded.args[0])] : []);
17
+ return deadlines.length ? Math.min(...deadlines) : undefined;
18
+ }
19
+ catch {
20
+ return undefined;
21
+ }
22
+ };
@@ -43,6 +43,7 @@ export type SwapperConfig = {
43
43
  VITE_COWSWAP_BASE_URL: string;
44
44
  VITE_PORTALS_BASE_URL: string;
45
45
  VITE_ZRX_BASE_URL: string;
46
+ VITE_FYND_BASE_URL: string;
46
47
  VITE_CHAINFLIP_API_KEY: string;
47
48
  VITE_CHAINFLIP_API_URL: string;
48
49
  VITE_FEATURE_CHAINFLIP_SWAP_DCA: boolean;
@@ -56,6 +57,7 @@ export type SwapperConfig = {
56
57
  VITE_ACROSS_API_KEY: string;
57
58
  VITE_DEBRIDGE_API_URL: string;
58
59
  VITE_BOB_GATEWAY_API_KEY: string;
60
+ VITE_SYMBIOSIS_API_URL: string;
59
61
  };
60
62
  export declare enum SwapperName {
61
63
  Thorchain = "THORChain",
@@ -76,7 +78,9 @@ export declare enum SwapperName {
76
78
  Stonfi = "STON.fi",
77
79
  Across = "Across",
78
80
  Debridge = "deBridge",
79
- BobGateway = "BOB Gateway"
81
+ BobGateway = "BOB Gateway",
82
+ Symbiosis = "Symbiosis",
83
+ Fynd = "Fynd"
80
84
  }
81
85
  export type SwapSource = SwapperName | `${SwapperName} • ${string}`;
82
86
  export type SwapErrorRight = {
@@ -343,9 +347,6 @@ export type TradeStepCommon = {
343
347
  estimatedExecutionTimeMs: number | undefined;
344
348
  swapperMetadata?: SwapperMetadata;
345
349
  stonfiTransactionData?: StonfiTransactionData;
346
- chainflipSpecific?: {
347
- depositAddress?: string;
348
- };
349
350
  affiliateFee?: AffiliateFee;
350
351
  };
351
352
  export type TradeQuoteStep = TradeStepCommon & {
@@ -452,7 +453,7 @@ export type TradeQuote = TradeQuoteBase & {
452
453
  } & {
453
454
  quoteOrRate: 'quote';
454
455
  receiveAddress: string;
455
- deadline: number;
456
+ deadline?: number;
456
457
  };
457
458
  export type MultiHopTradeQuote = TradeQuote & {
458
459
  steps: MultiHopTradeQuoteSteps;
package/dist/esm/types.js CHANGED
@@ -19,6 +19,8 @@ export var SwapperName;
19
19
  SwapperName["Across"] = "Across";
20
20
  SwapperName["Debridge"] = "deBridge";
21
21
  SwapperName["BobGateway"] = "BOB Gateway";
22
+ SwapperName["Symbiosis"] = "Symbiosis";
23
+ SwapperName["Fynd"] = "Fynd";
22
24
  })(SwapperName || (SwapperName = {}));
23
25
  export var TradeQuoteError;
24
26
  (function (TradeQuoteError) {
@@ -1,7 +1,6 @@
1
1
  import type { AssetId, ChainId } from '@shapeshiftoss/caip';
2
2
  import type { TradeAmount, TradeStepCommon } from '../types.js';
3
3
  import { SwapperName } from '../types.js';
4
- export declare const FALLBACK_QUOTE_DEADLINE_MS = 60000;
5
4
  export declare const getTradeAmount: (input: {
6
5
  sellAmountIncludingProtocolFeesCryptoBaseUnit: string;
7
6
  } | {
@@ -10,5 +9,5 @@ export declare const getTradeAmount: (input: {
10
9
  export declare const normalizeEpochToMs: (value: number) => number;
11
10
  export declare const isNativeEvmAsset: (assetId: AssetId) => boolean;
12
11
  export declare const getTreasuryAddressFromChainId: (chainId: ChainId) => string;
13
- export type DepositAddressStep = Pick<TradeStepCommon, 'chainflipSpecific' | 'swapperMetadata'>;
12
+ export type DepositAddressStep = Pick<TradeStepCommon, 'swapperMetadata'>;
14
13
  export declare const getDepositAddress: (step: DepositAddressStep, swapperName: SwapperName) => string | undefined;
@@ -1,9 +1,7 @@
1
- import { arbitrumAssetId, avalancheAssetId, baseAssetId, bscAssetId, ethAssetId, fromAssetId, gnosisAssetId, katanaAssetId, monadAssetId, optimismAssetId, plasmaAssetId, polygonAssetId, } from '@shapeshiftoss/caip';
1
+ import { CHAIN_NAMESPACE, fromAssetId } from '@shapeshiftoss/caip';
2
2
  import { KnownChainIds } from '@shapeshiftoss/types';
3
- import { DAO_TREASURY_ARBITRUM, DAO_TREASURY_AVALANCHE, DAO_TREASURY_BASE, DAO_TREASURY_BITCOIN, DAO_TREASURY_BOB, DAO_TREASURY_BSC, DAO_TREASURY_ETHEREUM_MAINNET, DAO_TREASURY_GNOSIS, DAO_TREASURY_HYPEREVM, DAO_TREASURY_MEGAETH, DAO_TREASURY_MONAD, DAO_TREASURY_OPTIMISM, DAO_TREASURY_PLASMA, DAO_TREASURY_POLYGON, DAO_TREASURY_ROBINHOOD, DAO_TREASURY_SOLANA, DAO_TREASURY_STARKNET, DAO_TREASURY_TON, isTreasuryChainId, } from '@shapeshiftoss/utils';
3
+ import { chainIdToFeeAssetId, DAO_TREASURY_ARBITRUM, DAO_TREASURY_AVALANCHE, DAO_TREASURY_BASE, DAO_TREASURY_BITCOIN, DAO_TREASURY_BOB, DAO_TREASURY_BSC, DAO_TREASURY_ETHEREUM_MAINNET, DAO_TREASURY_GNOSIS, DAO_TREASURY_HYPEREVM, DAO_TREASURY_MEGAETH, DAO_TREASURY_MONAD, DAO_TREASURY_OPTIMISM, DAO_TREASURY_PLASMA, DAO_TREASURY_POLYGON, DAO_TREASURY_ROBINHOOD, DAO_TREASURY_SOLANA, DAO_TREASURY_STARKNET, DAO_TREASURY_TON, isTreasuryChainId, } from '@shapeshiftoss/utils';
4
4
  import { SwapperName } from '../types.js';
5
- // Deadline for providers without their own expiry - short enough to keep priced amounts honest
6
- export const FALLBACK_QUOTE_DEADLINE_MS = 60_000;
7
5
  export const getTradeAmount = (input) => 'buyAmountCryptoBaseUnit' in input
8
6
  ? { direction: 'exactOut', cryptoBaseUnit: input.buyAmountCryptoBaseUnit }
9
7
  : { direction: 'exactIn', cryptoBaseUnit: input.sellAmountIncludingProtocolFeesCryptoBaseUnit };
@@ -18,33 +16,8 @@ export const normalizeEpochToMs = (value) => {
18
16
  return Math.floor(value / 1e6);
19
17
  };
20
18
  export const isNativeEvmAsset = (assetId) => {
21
- const { chainId } = fromAssetId(assetId);
22
- switch (chainId) {
23
- case KnownChainIds.EthereumMainnet:
24
- return assetId === ethAssetId;
25
- case KnownChainIds.AvalancheMainnet:
26
- return assetId === avalancheAssetId;
27
- case KnownChainIds.OptimismMainnet:
28
- return assetId === optimismAssetId;
29
- case KnownChainIds.BnbSmartChainMainnet:
30
- return assetId === bscAssetId;
31
- case KnownChainIds.PolygonMainnet:
32
- return assetId === polygonAssetId;
33
- case KnownChainIds.GnosisMainnet:
34
- return assetId === gnosisAssetId;
35
- case KnownChainIds.ArbitrumMainnet:
36
- return assetId === arbitrumAssetId;
37
- case KnownChainIds.BaseMainnet:
38
- return assetId === baseAssetId;
39
- case KnownChainIds.MonadMainnet:
40
- return assetId === monadAssetId;
41
- case KnownChainIds.PlasmaMainnet:
42
- return assetId === plasmaAssetId;
43
- case KnownChainIds.KatanaMainnet:
44
- return assetId === katanaAssetId;
45
- default:
46
- return false;
47
- }
19
+ const { chainId, chainNamespace } = fromAssetId(assetId);
20
+ return chainNamespace === CHAIN_NAMESPACE.Evm && assetId === chainIdToFeeAssetId(chainId);
48
21
  };
49
22
  const DAO_TREASURY_BY_CHAIN_ID = {
50
23
  [KnownChainIds.EthereumMainnet]: DAO_TREASURY_ETHEREUM_MAINNET,
@@ -77,8 +50,11 @@ export const getTreasuryAddressFromChainId = (chainId) => {
77
50
  };
78
51
  export const getDepositAddress = (step, swapperName) => {
79
52
  switch (swapperName) {
80
- case SwapperName.Chainflip:
81
- return step.chainflipSpecific?.depositAddress || undefined;
53
+ case SwapperName.Chainflip: {
54
+ if (step.swapperMetadata?.name !== 'chainflip')
55
+ return;
56
+ return step.swapperMetadata.depositAddress || undefined;
57
+ }
82
58
  case SwapperName.NearIntents: {
83
59
  if (step.swapperMetadata?.name !== 'nearIntents')
84
60
  return;
@@ -55,7 +55,9 @@ describe('normalizeEpochToMs', () => {
55
55
  const makeStep = (step) => step;
56
56
  describe('getDepositAddress', () => {
57
57
  it('reads the chainflip deposit address', () => {
58
- const step = makeStep({ chainflipSpecific: { depositAddress: 'bc1qdeposit' } });
58
+ const step = makeStep({
59
+ swapperMetadata: { name: 'chainflip', swapId: 1, depositAddress: 'bc1qdeposit' },
60
+ });
59
61
  expect(getDepositAddress(step, SwapperName.Chainflip)).toBe('bc1qdeposit');
60
62
  });
61
63
  it('returns undefined when chainflip has no deposit address', () => {
@@ -78,7 +80,9 @@ describe('getDepositAddress', () => {
78
80
  expect(getDepositAddress(step, SwapperName.NearIntents)).toBeUndefined();
79
81
  });
80
82
  it('returns undefined for swappers that do not use deposit addresses', () => {
81
- const step = makeStep({ chainflipSpecific: { depositAddress: 'bc1qdeposit' } });
83
+ const step = makeStep({
84
+ swapperMetadata: { name: 'chainflip', swapId: 1, depositAddress: 'bc1qdeposit' },
85
+ });
82
86
  expect(getDepositAddress(step, SwapperName.Relay)).toBeUndefined();
83
87
  });
84
88
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshiftoss/swapper",
3
- "version": "20.3.0",
3
+ "version": "20.4.0",
4
4
  "repository": "https://github.com/shapeshift/web",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -50,13 +50,13 @@
50
50
  "retry-axios": "^2.6.0",
51
51
  "uuid": "^9.0.0",
52
52
  "viem": "2.55.11",
53
- "@shapeshiftoss/caip": "^8.17.1",
54
- "@shapeshiftoss/chain-adapters": "^11.6.0",
55
- "@shapeshiftoss/hdwallet-core": "^1.62.41",
56
- "@shapeshiftoss/contracts": "^1.1.0",
53
+ "@shapeshiftoss/chain-adapters": "^11.7.0",
54
+ "@shapeshiftoss/caip": "^8.17.2",
57
55
  "@shapeshiftoss/types": "^9.1.0",
58
- "@shapeshiftoss/utils": "^1.3.1",
59
- "@shapeshiftoss/unchained-client": "^10.15.0"
56
+ "@shapeshiftoss/contracts": "^1.1.0",
57
+ "@shapeshiftoss/utils": "^1.4.0",
58
+ "@shapeshiftoss/hdwallet-core": "^1.62.41",
59
+ "@shapeshiftoss/unchained-client": "^10.16.0"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/lodash": "^4.14.178",