@eth-optimism/actions-sdk 0.2.0 → 0.3.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 (271) hide show
  1. package/dist/__mocks__/MockAssets.d.ts.map +1 -1
  2. package/dist/__mocks__/MockAssets.js +2 -0
  3. package/dist/__mocks__/MockAssets.js.map +1 -1
  4. package/dist/__tests__/actions.test.js +0 -4
  5. package/dist/__tests__/actions.test.js.map +1 -1
  6. package/dist/actions.d.ts +20 -1
  7. package/dist/actions.d.ts.map +1 -1
  8. package/dist/actions.js +37 -13
  9. package/dist/actions.js.map +1 -1
  10. package/dist/constants/assets.d.ts +4 -0
  11. package/dist/constants/assets.d.ts.map +1 -1
  12. package/dist/constants/assets.js +15 -0
  13. package/dist/constants/assets.js.map +1 -1
  14. package/dist/constants/contracts.d.ts +4 -0
  15. package/dist/constants/contracts.d.ts.map +1 -0
  16. package/dist/constants/contracts.js +3 -0
  17. package/dist/constants/contracts.js.map +1 -0
  18. package/dist/index.d.ts +4 -3
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +3 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/lend/core/LendProvider.d.ts +0 -6
  23. package/dist/lend/core/LendProvider.d.ts.map +1 -1
  24. package/dist/lend/core/LendProvider.js +6 -15
  25. package/dist/lend/core/LendProvider.js.map +1 -1
  26. package/dist/lend/core/__tests__/LendProvider.test.js +2 -4
  27. package/dist/lend/core/__tests__/LendProvider.test.js.map +1 -1
  28. package/dist/lend/providers/morpho/__tests__/sdk.test.js +3 -2
  29. package/dist/lend/providers/morpho/__tests__/sdk.test.js.map +1 -1
  30. package/dist/lend/providers/morpho/api.d.ts +4 -0
  31. package/dist/lend/providers/morpho/api.d.ts.map +1 -1
  32. package/dist/lend/providers/morpho/api.js.map +1 -1
  33. package/dist/lend/providers/morpho/sdk.d.ts.map +1 -1
  34. package/dist/lend/providers/morpho/sdk.js +10 -1
  35. package/dist/lend/providers/morpho/sdk.js.map +1 -1
  36. package/dist/supported/tokens.d.ts.map +1 -1
  37. package/dist/supported/tokens.js +9 -2
  38. package/dist/supported/tokens.js.map +1 -1
  39. package/dist/swap/__mocks__/MockSwapProvider.d.ts +38 -0
  40. package/dist/swap/__mocks__/MockSwapProvider.d.ts.map +1 -0
  41. package/dist/swap/__mocks__/MockSwapProvider.js +138 -0
  42. package/dist/swap/__mocks__/MockSwapProvider.js.map +1 -0
  43. package/dist/swap/core/SwapProvider.d.ts +56 -0
  44. package/dist/swap/core/SwapProvider.d.ts.map +1 -0
  45. package/dist/swap/core/SwapProvider.js +177 -0
  46. package/dist/swap/core/SwapProvider.js.map +1 -0
  47. package/dist/swap/core/__tests__/SwapProvider.test.d.ts +2 -0
  48. package/dist/swap/core/__tests__/SwapProvider.test.d.ts.map +1 -0
  49. package/dist/swap/core/__tests__/SwapProvider.test.js +329 -0
  50. package/dist/swap/core/__tests__/SwapProvider.test.js.map +1 -0
  51. package/dist/swap/index.d.ts +7 -0
  52. package/dist/swap/index.d.ts.map +1 -0
  53. package/dist/swap/index.js +8 -0
  54. package/dist/swap/index.js.map +1 -0
  55. package/dist/swap/namespaces/ActionsSwapNamespace.d.ts +8 -0
  56. package/dist/swap/namespaces/ActionsSwapNamespace.d.ts.map +1 -0
  57. package/dist/swap/namespaces/ActionsSwapNamespace.js +8 -0
  58. package/dist/swap/namespaces/ActionsSwapNamespace.js.map +1 -0
  59. package/dist/swap/namespaces/BaseSwapNamespace.d.ts +33 -0
  60. package/dist/swap/namespaces/BaseSwapNamespace.d.ts.map +1 -0
  61. package/dist/swap/namespaces/BaseSwapNamespace.js +58 -0
  62. package/dist/swap/namespaces/BaseSwapNamespace.js.map +1 -0
  63. package/dist/swap/namespaces/WalletSwapNamespace.d.ts +22 -0
  64. package/dist/swap/namespaces/WalletSwapNamespace.d.ts.map +1 -0
  65. package/dist/swap/namespaces/WalletSwapNamespace.js +60 -0
  66. package/dist/swap/namespaces/WalletSwapNamespace.js.map +1 -0
  67. package/dist/swap/namespaces/__tests__/BaseSwapNamespace.spec.d.ts +2 -0
  68. package/dist/swap/namespaces/__tests__/BaseSwapNamespace.spec.d.ts.map +1 -0
  69. package/dist/swap/namespaces/__tests__/BaseSwapNamespace.spec.js +106 -0
  70. package/dist/swap/namespaces/__tests__/BaseSwapNamespace.spec.js.map +1 -0
  71. package/dist/swap/namespaces/__tests__/WalletSwapNamespace.spec.d.ts +2 -0
  72. package/dist/swap/namespaces/__tests__/WalletSwapNamespace.spec.d.ts.map +1 -0
  73. package/dist/swap/namespaces/__tests__/WalletSwapNamespace.spec.js +132 -0
  74. package/dist/swap/namespaces/__tests__/WalletSwapNamespace.spec.js.map +1 -0
  75. package/dist/swap/providers/uniswap/UniswapSwapProvider.d.ts +68 -0
  76. package/dist/swap/providers/uniswap/UniswapSwapProvider.d.ts.map +1 -0
  77. package/dist/swap/providers/uniswap/UniswapSwapProvider.js +206 -0
  78. package/dist/swap/providers/uniswap/UniswapSwapProvider.js.map +1 -0
  79. package/dist/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.d.ts +2 -0
  80. package/dist/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.d.ts.map +1 -0
  81. package/dist/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.js +257 -0
  82. package/dist/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.js.map +1 -0
  83. package/dist/swap/providers/uniswap/__tests__/sdk.test.d.ts +2 -0
  84. package/dist/swap/providers/uniswap/__tests__/sdk.test.d.ts.map +1 -0
  85. package/dist/swap/providers/uniswap/__tests__/sdk.test.js +312 -0
  86. package/dist/swap/providers/uniswap/__tests__/sdk.test.js.map +1 -0
  87. package/dist/swap/providers/uniswap/abis.d.ts +227 -0
  88. package/dist/swap/providers/uniswap/abis.d.ts.map +1 -0
  89. package/dist/swap/providers/uniswap/abis.js +138 -0
  90. package/dist/swap/providers/uniswap/abis.js.map +1 -0
  91. package/dist/swap/providers/uniswap/addresses.d.ts +21 -0
  92. package/dist/swap/providers/uniswap/addresses.d.ts.map +1 -0
  93. package/dist/swap/providers/uniswap/addresses.js +81 -0
  94. package/dist/swap/providers/uniswap/addresses.js.map +1 -0
  95. package/dist/swap/providers/uniswap/encoding.d.ts +77 -0
  96. package/dist/swap/providers/uniswap/encoding.d.ts.map +1 -0
  97. package/dist/swap/providers/uniswap/encoding.js +233 -0
  98. package/dist/swap/providers/uniswap/encoding.js.map +1 -0
  99. package/dist/swap/providers/uniswap/types.d.ts +20 -0
  100. package/dist/swap/providers/uniswap/types.d.ts.map +1 -0
  101. package/dist/swap/providers/uniswap/types.js +2 -0
  102. package/dist/swap/providers/uniswap/types.js.map +1 -0
  103. package/dist/types/actions.d.ts +19 -5
  104. package/dist/types/actions.d.ts.map +1 -1
  105. package/dist/types/index.d.ts +2 -0
  106. package/dist/types/index.d.ts.map +1 -1
  107. package/dist/types/index.js +2 -0
  108. package/dist/types/index.js.map +1 -1
  109. package/dist/types/lend/base.d.ts +3 -13
  110. package/dist/types/lend/base.d.ts.map +1 -1
  111. package/dist/types/lend/base.js.map +1 -1
  112. package/dist/types/swap/base.d.ts +238 -0
  113. package/dist/types/swap/base.d.ts.map +1 -0
  114. package/dist/types/swap/base.js +4 -0
  115. package/dist/types/swap/base.js.map +1 -0
  116. package/dist/types/swap/index.d.ts +2 -0
  117. package/dist/types/swap/index.d.ts.map +1 -0
  118. package/dist/types/swap/index.js +2 -0
  119. package/dist/types/swap/index.js.map +1 -0
  120. package/dist/types/transaction.d.ts +14 -0
  121. package/dist/types/transaction.d.ts.map +1 -0
  122. package/dist/types/transaction.js +2 -0
  123. package/dist/types/transaction.js.map +1 -0
  124. package/dist/utils/assets.d.ts +4 -5
  125. package/dist/utils/assets.d.ts.map +1 -1
  126. package/dist/utils/assets.js +4 -11
  127. package/dist/utils/assets.js.map +1 -1
  128. package/dist/utils/assets.test.js +13 -1
  129. package/dist/utils/assets.test.js.map +1 -1
  130. package/dist/utils/permit2.d.ts +46 -0
  131. package/dist/utils/permit2.d.ts.map +1 -0
  132. package/dist/utils/permit2.js +100 -0
  133. package/dist/utils/permit2.js.map +1 -0
  134. package/dist/utils/permit2.test.d.ts +2 -0
  135. package/dist/utils/permit2.test.d.ts.map +1 -0
  136. package/dist/utils/permit2.test.js +110 -0
  137. package/dist/utils/permit2.test.js.map +1 -0
  138. package/dist/utils/validation.d.ts +12 -0
  139. package/dist/utils/validation.d.ts.map +1 -0
  140. package/dist/utils/validation.js +44 -0
  141. package/dist/utils/validation.js.map +1 -0
  142. package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.d.ts +7 -1
  143. package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.d.ts.map +1 -1
  144. package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.js +2 -1
  145. package/dist/wallet/core/providers/hosted/abstract/HostedWalletProvider.js.map +1 -1
  146. package/dist/wallet/core/providers/hosted/types/index.d.ts +5 -1
  147. package/dist/wallet/core/providers/hosted/types/index.d.ts.map +1 -1
  148. package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.d.ts +7 -1
  149. package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.d.ts.map +1 -1
  150. package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.js +5 -1
  151. package/dist/wallet/core/providers/smart/default/DefaultSmartWalletProvider.js.map +1 -1
  152. package/dist/wallet/core/providers/smart/default/__tests__/DefaultSmartWalletProvider.spec.js +2 -2
  153. package/dist/wallet/core/providers/smart/default/__tests__/DefaultSmartWalletProvider.spec.js.map +1 -1
  154. package/dist/wallet/core/wallets/abstract/Wallet.d.ts +13 -2
  155. package/dist/wallet/core/wallets/abstract/Wallet.d.ts.map +1 -1
  156. package/dist/wallet/core/wallets/abstract/Wallet.js +7 -1
  157. package/dist/wallet/core/wallets/abstract/Wallet.js.map +1 -1
  158. package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.d.ts +7 -2
  159. package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.d.ts.map +1 -1
  160. package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.js +6 -5
  161. package/dist/wallet/core/wallets/smart/default/DefaultSmartWallet.js.map +1 -1
  162. package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.d.ts +6 -1
  163. package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.d.ts.map +1 -1
  164. package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.js +3 -1
  165. package/dist/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.js.map +1 -1
  166. package/dist/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.d.ts.map +1 -1
  167. package/dist/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.js +4 -3
  168. package/dist/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.js.map +1 -1
  169. package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts +5 -1
  170. package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts.map +1 -1
  171. package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js +4 -2
  172. package/dist/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js.map +1 -1
  173. package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.d.ts +6 -1
  174. package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.d.ts.map +1 -1
  175. package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.js +4 -3
  176. package/dist/wallet/node/wallets/hosted/privy/PrivyWallet.js.map +1 -1
  177. package/dist/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.d.ts +5 -1
  178. package/dist/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.d.ts.map +1 -1
  179. package/dist/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.js +2 -2
  180. package/dist/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.js.map +1 -1
  181. package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.d.ts +7 -1
  182. package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.d.ts.map +1 -1
  183. package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.js +6 -2
  184. package/dist/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.js.map +1 -1
  185. package/dist/wallet/react/providers/hosted/dynamic/__tests__/DynamicHostedWalletProvider.spec.js +1 -0
  186. package/dist/wallet/react/providers/hosted/dynamic/__tests__/DynamicHostedWalletProvider.spec.js.map +1 -1
  187. package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.d.ts +6 -1
  188. package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.d.ts.map +1 -1
  189. package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.js +5 -2
  190. package/dist/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.js.map +1 -1
  191. package/dist/wallet/react/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.js +1 -0
  192. package/dist/wallet/react/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.js.map +1 -1
  193. package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts +6 -3
  194. package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.d.ts.map +1 -1
  195. package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js +5 -4
  196. package/dist/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.js.map +1 -1
  197. package/dist/wallet/react/providers/registry/ReactHostedWalletProviderRegistry.d.ts.map +1 -1
  198. package/dist/wallet/react/providers/registry/ReactHostedWalletProviderRegistry.js +6 -6
  199. package/dist/wallet/react/providers/registry/ReactHostedWalletProviderRegistry.js.map +1 -1
  200. package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.d.ts +7 -1
  201. package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.d.ts.map +1 -1
  202. package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.js +5 -3
  203. package/dist/wallet/react/wallets/hosted/dynamic/DynamicWallet.js.map +1 -1
  204. package/dist/wallet/react/wallets/hosted/privy/PrivyWallet.d.ts +5 -1
  205. package/dist/wallet/react/wallets/hosted/privy/PrivyWallet.d.ts.map +1 -1
  206. package/dist/wallet/react/wallets/hosted/privy/PrivyWallet.js +3 -3
  207. package/dist/wallet/react/wallets/hosted/privy/PrivyWallet.js.map +1 -1
  208. package/dist/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.d.ts +5 -1
  209. package/dist/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.d.ts.map +1 -1
  210. package/dist/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.js +2 -2
  211. package/dist/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.js.map +1 -1
  212. package/package.json +2 -2
  213. package/src/__mocks__/MockAssets.ts +2 -0
  214. package/src/__tests__/actions.test.ts +0 -4
  215. package/src/actions.ts +57 -19
  216. package/src/constants/assets.ts +16 -0
  217. package/src/constants/contracts.ts +5 -0
  218. package/src/index.ts +30 -2
  219. package/src/lend/core/LendProvider.ts +6 -18
  220. package/src/lend/core/__tests__/LendProvider.test.ts +2 -5
  221. package/src/lend/providers/morpho/__tests__/sdk.test.ts +3 -2
  222. package/src/lend/providers/morpho/api.ts +4 -0
  223. package/src/lend/providers/morpho/sdk.ts +10 -1
  224. package/src/supported/tokens.ts +16 -2
  225. package/src/swap/__mocks__/MockSwapProvider.ts +216 -0
  226. package/src/swap/core/SwapProvider.ts +319 -0
  227. package/src/swap/core/__tests__/SwapProvider.test.ts +478 -0
  228. package/src/swap/index.ts +14 -0
  229. package/src/swap/namespaces/ActionsSwapNamespace.ts +7 -0
  230. package/src/swap/namespaces/BaseSwapNamespace.ts +77 -0
  231. package/src/swap/namespaces/WalletSwapNamespace.ts +82 -0
  232. package/src/swap/namespaces/__tests__/BaseSwapNamespace.spec.ts +138 -0
  233. package/src/swap/namespaces/__tests__/WalletSwapNamespace.spec.ts +162 -0
  234. package/src/swap/providers/uniswap/UniswapSwapProvider.ts +304 -0
  235. package/src/swap/providers/uniswap/__tests__/UniswapSwapProvider.test.ts +299 -0
  236. package/src/swap/providers/uniswap/__tests__/sdk.test.ts +370 -0
  237. package/src/swap/providers/uniswap/abis.ts +144 -0
  238. package/src/swap/providers/uniswap/addresses.ts +108 -0
  239. package/src/swap/providers/uniswap/encoding.ts +406 -0
  240. package/src/swap/providers/uniswap/types.ts +24 -0
  241. package/src/types/actions.ts +22 -6
  242. package/src/types/index.ts +2 -0
  243. package/src/types/lend/base.ts +4 -14
  244. package/src/types/swap/base.ts +259 -0
  245. package/src/types/swap/index.ts +1 -0
  246. package/src/types/transaction.ts +14 -0
  247. package/src/utils/assets.test.ts +16 -1
  248. package/src/utils/assets.ts +13 -10
  249. package/src/utils/permit2.test.ts +142 -0
  250. package/src/utils/permit2.ts +144 -0
  251. package/src/utils/validation.ts +76 -0
  252. package/src/wallet/core/providers/hosted/abstract/HostedWalletProvider.ts +9 -1
  253. package/src/wallet/core/providers/hosted/types/index.ts +5 -1
  254. package/src/wallet/core/providers/smart/default/DefaultSmartWalletProvider.ts +13 -1
  255. package/src/wallet/core/providers/smart/default/__tests__/DefaultSmartWalletProvider.spec.ts +2 -0
  256. package/src/wallet/core/wallets/abstract/Wallet.ts +18 -2
  257. package/src/wallet/core/wallets/smart/default/DefaultSmartWallet.ts +14 -5
  258. package/src/wallet/node/providers/hosted/privy/PrivyHostedWalletProvider.ts +13 -2
  259. package/src/wallet/node/providers/hosted/registry/NodeHostedWalletProviderRegistry.ts +10 -2
  260. package/src/wallet/node/providers/hosted/turnkey/TurnkeyHostedWalletProvider.ts +8 -2
  261. package/src/wallet/node/wallets/hosted/privy/PrivyWallet.ts +11 -2
  262. package/src/wallet/node/wallets/hosted/turnkey/TurnkeyWallet.ts +10 -2
  263. package/src/wallet/react/providers/hosted/dynamic/DynamicHostedWalletProvider.ts +10 -2
  264. package/src/wallet/react/providers/hosted/dynamic/__tests__/DynamicHostedWalletProvider.spec.ts +1 -0
  265. package/src/wallet/react/providers/hosted/privy/PrivyHostedWalletProvider.ts +9 -2
  266. package/src/wallet/react/providers/hosted/privy/__tests__/PrivyHostedWalletProvider.spec.ts +1 -0
  267. package/src/wallet/react/providers/hosted/turnkey/TurnkeyHostedWalletProvider.ts +9 -4
  268. package/src/wallet/react/providers/registry/ReactHostedWalletProviderRegistry.ts +18 -6
  269. package/src/wallet/react/wallets/hosted/dynamic/DynamicWallet.ts +12 -2
  270. package/src/wallet/react/wallets/hosted/privy/PrivyWallet.ts +10 -2
  271. package/src/wallet/react/wallets/hosted/turnkey/TurnkeyWallet.ts +10 -2
@@ -0,0 +1,144 @@
1
+ /**
2
+ * PoolKey tuple components (shared across V4 ABI definitions)
3
+ */
4
+ const POOL_KEY_COMPONENTS = [
5
+ { name: 'currency0', type: 'address' },
6
+ { name: 'currency1', type: 'address' },
7
+ { name: 'fee', type: 'uint24' },
8
+ { name: 'tickSpacing', type: 'int24' },
9
+ { name: 'hooks', type: 'address' },
10
+ ] as const
11
+
12
+ /**
13
+ * V4 Quoter ABI (subset for quoting)
14
+ * @see https://docs.uniswap.org/contracts/v4/reference/periphery/interfaces/IQuoter
15
+ */
16
+ export const QUOTER_ABI = [
17
+ {
18
+ name: 'quoteExactInputSingle',
19
+ type: 'function',
20
+ stateMutability: 'nonpayable',
21
+ inputs: [
22
+ {
23
+ name: 'params',
24
+ type: 'tuple',
25
+ components: [
26
+ { name: 'poolKey', type: 'tuple', components: POOL_KEY_COMPONENTS },
27
+ { name: 'zeroForOne', type: 'bool' },
28
+ { name: 'exactAmount', type: 'uint128' },
29
+ { name: 'hookData', type: 'bytes' },
30
+ ],
31
+ },
32
+ ],
33
+ outputs: [
34
+ { name: 'amountOut', type: 'uint256' },
35
+ { name: 'gasEstimate', type: 'uint256' },
36
+ ],
37
+ },
38
+ {
39
+ name: 'quoteExactOutputSingle',
40
+ type: 'function',
41
+ stateMutability: 'nonpayable',
42
+ inputs: [
43
+ {
44
+ name: 'params',
45
+ type: 'tuple',
46
+ components: [
47
+ { name: 'poolKey', type: 'tuple', components: POOL_KEY_COMPONENTS },
48
+ { name: 'zeroForOne', type: 'bool' },
49
+ { name: 'exactAmount', type: 'uint128' },
50
+ { name: 'hookData', type: 'bytes' },
51
+ ],
52
+ },
53
+ ],
54
+ outputs: [
55
+ { name: 'amountIn', type: 'uint256' },
56
+ { name: 'gasEstimate', type: 'uint256' },
57
+ ],
58
+ },
59
+ ] as const
60
+
61
+ /**
62
+ * Universal Router ABI (subset for swaps)
63
+ * @see https://docs.uniswap.org/contracts/v4/reference/periphery/UniversalRouter
64
+ */
65
+ export const UNIVERSAL_ROUTER_ABI = [
66
+ {
67
+ name: 'execute',
68
+ type: 'function',
69
+ stateMutability: 'payable',
70
+ inputs: [
71
+ { name: 'commands', type: 'bytes' },
72
+ { name: 'inputs', type: 'bytes[]' },
73
+ { name: 'deadline', type: 'uint256' },
74
+ ],
75
+ outputs: [],
76
+ },
77
+ ] as const
78
+
79
+ /** ABI type for ExactInputSingleParams */
80
+ export const EXACT_INPUT_SINGLE_PARAMS = [
81
+ {
82
+ type: 'tuple',
83
+ components: [
84
+ {
85
+ name: 'poolKey',
86
+ type: 'tuple',
87
+ components: [...POOL_KEY_COMPONENTS],
88
+ },
89
+ { name: 'zeroForOne', type: 'bool' },
90
+ { name: 'amountIn', type: 'uint128' },
91
+ { name: 'amountOutMinimum', type: 'uint128' },
92
+ { name: 'hookData', type: 'bytes' },
93
+ ],
94
+ },
95
+ ] as const
96
+
97
+ /** ABI type for ExactOutputSingleParams */
98
+ export const EXACT_OUTPUT_SINGLE_PARAMS = [
99
+ {
100
+ type: 'tuple',
101
+ components: [
102
+ {
103
+ name: 'poolKey',
104
+ type: 'tuple',
105
+ components: [...POOL_KEY_COMPONENTS],
106
+ },
107
+ { name: 'zeroForOne', type: 'bool' },
108
+ { name: 'amountOut', type: 'uint128' },
109
+ { name: 'amountInMaximum', type: 'uint128' },
110
+ { name: 'hookData', type: 'bytes' },
111
+ ],
112
+ },
113
+ ] as const
114
+
115
+ /** ABI type for SETTLE_ALL / TAKE_ALL params */
116
+ export const CURRENCY_AMOUNT_PARAMS = [
117
+ { type: 'address' },
118
+ { type: 'uint256' },
119
+ ] as const
120
+
121
+ /**
122
+ * PoolManager extsload ABI — reads arbitrary storage slots via SLOAD
123
+ * @see https://docs.uniswap.org/contracts/v4/guides/read-pool-state
124
+ */
125
+ export const EXTSLOAD_ABI = [
126
+ {
127
+ name: 'extsload',
128
+ type: 'function',
129
+ stateMutability: 'view',
130
+ inputs: [{ name: 'slot', type: 'bytes32' }],
131
+ outputs: [{ type: 'bytes32' }],
132
+ },
133
+ ] as const
134
+
135
+ /**
136
+ * PoolKey ABI encoding type for computing PoolId
137
+ */
138
+ export const POOL_KEY_ABI_TYPE = [
139
+ { name: 'currency0', type: 'address' },
140
+ { name: 'currency1', type: 'address' },
141
+ { name: 'fee', type: 'uint24' },
142
+ { name: 'tickSpacing', type: 'int24' },
143
+ { name: 'hooks', type: 'address' },
144
+ ] as const
@@ -0,0 +1,108 @@
1
+ import type { Address } from 'viem'
2
+ import {
3
+ base,
4
+ baseSepolia,
5
+ mainnet,
6
+ optimism,
7
+ sepolia,
8
+ unichain,
9
+ unichainSepolia,
10
+ worldchain,
11
+ } from 'viem/chains'
12
+
13
+ import { PERMIT2_ADDRESS } from '@/constants/contracts.js'
14
+ import type { SupportedChainId } from '@/constants/supportedChains.js'
15
+
16
+ /**
17
+ * Uniswap contract addresses
18
+ */
19
+ export interface UniswapAddresses {
20
+ poolManager: Address
21
+ positionManager: Address
22
+ universalRouter: Address
23
+ quoter: Address
24
+ permit2: Address
25
+ }
26
+
27
+ /**
28
+ * Uniswap V4 contract addresses per chain
29
+ * @see https://docs.uniswap.org/contracts/v4/deployments
30
+ */
31
+ const UNISWAP_ADDRESSES: Partial<Record<SupportedChainId, UniswapAddresses>> = {
32
+ [mainnet.id]: {
33
+ poolManager: '0x000000000004444c5dc75cB358380D2e3dE08A90',
34
+ positionManager: '0xbd216513d74c8cf14cf4747e6aaa6420ff64ee9e',
35
+ universalRouter: '0x66a9893cc07d91d95644aedd05d03f95e1dba8af',
36
+ quoter: '0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203',
37
+ permit2: PERMIT2_ADDRESS,
38
+ },
39
+ [optimism.id]: {
40
+ poolManager: '0x9a13f98cb987694c9f086b1f5eb990eea8264ec3',
41
+ positionManager: '0x3c3ea4b57a46241e54610e5f022e5c45859a1017',
42
+ universalRouter: '0x851116d9223fabed8e56c0e6b8ad0c31d98b3507',
43
+ quoter: '0x1f3131a13296fb91c90870043742c3cdbff1a8d7',
44
+ permit2: PERMIT2_ADDRESS,
45
+ },
46
+ [base.id]: {
47
+ poolManager: '0x498581ff718922c3f8e6a244956af099b2652b2b',
48
+ positionManager: '0x7c5f5a4bbd8fd63184577525326123b519429bdc',
49
+ universalRouter: '0x6ff5693b99212da76ad316178a184ab56d299b43',
50
+ quoter: '0x0d5e0f971ed27fbff6c2837bf31316121532048d',
51
+ permit2: PERMIT2_ADDRESS,
52
+ },
53
+ [unichain.id]: {
54
+ poolManager: '0x1f98400000000000000000000000000000000004',
55
+ positionManager: '0x4529a01c7a0410167c5740c487a8de60232617bf',
56
+ universalRouter: '0xef740bf23acae26f6492b10de645d6b98dc8eaf3',
57
+ quoter: '0x333e3c607b141b18ff6de9f258db6e77fe7491e0',
58
+ permit2: PERMIT2_ADDRESS,
59
+ },
60
+ [worldchain.id]: {
61
+ poolManager: '0xb1860d529182ac3bc1f51fa2abd56662b7d13f33',
62
+ positionManager: '0xc585e0f504613b5fbf874f21af14c65260fb41fa',
63
+ universalRouter: '0x8ac7bee993bb44dab564ea4bc9ea67bf9eb5e743',
64
+ quoter: '0x55d235b3ff2daf7c3ede0defc9521f1d6fe6c5c0',
65
+ permit2: PERMIT2_ADDRESS,
66
+ },
67
+ [sepolia.id]: {
68
+ poolManager: '0xE03A1074c86CFeDd5C142C4F04F1a1536e203543',
69
+ positionManager: '0x429ba70129df741B2Ca2a85BC3A2a3328e5c09b4',
70
+ universalRouter: '0x3A9D48AB9751398BbFa63ad67599Bb04e4BdF98b',
71
+ quoter: '0x61b3f2011a92d183c7dbadbda940a7555ccf9227',
72
+ permit2: PERMIT2_ADDRESS,
73
+ },
74
+ [baseSepolia.id]: {
75
+ poolManager: '0x05E73354cFDd6745C338b50BcFDfA3Aa6fA03408',
76
+ positionManager: '0x4b2c77d209d3405f41a037ec6c77f7f5b8e2ca80',
77
+ universalRouter: '0x492e6456d9528771018deb9e87ef7750ef184104',
78
+ quoter: '0x4a6513c898fe1b2d0e78d3b0e0a4a151589b1cba',
79
+ permit2: PERMIT2_ADDRESS,
80
+ },
81
+ [unichainSepolia.id]: {
82
+ poolManager: '0x00b036b58a818b1bc34d502d3fe730db729e62ac',
83
+ positionManager: '0xf969aee60879c54baaed9f3ed26147db216fd664',
84
+ universalRouter: '0xf70536b3bcc1bd1a972dc186a2cf84cc6da6be5d',
85
+ quoter: '0x56dcd40a3f2d466f48e7f48bdbe5cc9b92ae4472',
86
+ permit2: PERMIT2_ADDRESS,
87
+ },
88
+ }
89
+
90
+ /**
91
+ * Get Uniswap contract addresses for a chain
92
+ */
93
+ export function getUniswapAddresses(
94
+ chainId: SupportedChainId,
95
+ ): UniswapAddresses {
96
+ const addresses = UNISWAP_ADDRESSES[chainId]
97
+ if (!addresses) {
98
+ throw new Error(`Uniswap not supported on chain ${chainId}`)
99
+ }
100
+ return addresses
101
+ }
102
+
103
+ /**
104
+ * Get supported chain IDs for Uniswap
105
+ */
106
+ export function getSupportedChainIds(): SupportedChainId[] {
107
+ return Object.keys(UNISWAP_ADDRESSES).map(Number) as SupportedChainId[]
108
+ }
@@ -0,0 +1,406 @@
1
+ import type { Address, Hex, PublicClient } from 'viem'
2
+ import {
3
+ encodeAbiParameters,
4
+ encodeFunctionData,
5
+ formatUnits,
6
+ keccak256,
7
+ zeroAddress,
8
+ } from 'viem'
9
+
10
+ import type { SupportedChainId } from '@/constants/supportedChains.js'
11
+ import {
12
+ CURRENCY_AMOUNT_PARAMS,
13
+ EXACT_INPUT_SINGLE_PARAMS,
14
+ EXACT_OUTPUT_SINGLE_PARAMS,
15
+ EXTSLOAD_ABI,
16
+ POOL_KEY_ABI_TYPE,
17
+ QUOTER_ABI,
18
+ UNIVERSAL_ROUTER_ABI,
19
+ } from '@/swap/providers/uniswap/abis.js'
20
+ import type { Asset } from '@/types/asset.js'
21
+ import type { SwapPrice, SwapRoute } from '@/types/swap/index.js'
22
+ import { getAssetAddress, isNativeAsset } from '@/utils/assets.js'
23
+
24
+ /**
25
+ * V4 represents native ETH as address(0) in pool keys and settle/take params,
26
+ * unlike V3 which required WETH. Named for clarity at call sites.
27
+ * @see https://github.com/Uniswap/v4-core/blob/main/src/types/Currency.sol
28
+ */
29
+ const NATIVE_CURRENCY = zeroAddress
30
+
31
+ /**
32
+ * Resolved V4 pool parameters
33
+ */
34
+ interface ResolvedPoolParams {
35
+ tokenIn: Address
36
+ tokenOut: Address
37
+ zeroForOne: boolean
38
+ poolKey: {
39
+ currency0: Address
40
+ currency1: Address
41
+ fee: number
42
+ tickSpacing: number
43
+ hooks: Address
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Resolve token addresses, currency sorting, and pool key for a V4 swap
49
+ */
50
+ function resolvePoolParams(
51
+ assetIn: Asset,
52
+ assetOut: Asset,
53
+ chainId: SupportedChainId,
54
+ fee: number,
55
+ tickSpacing: number,
56
+ ): ResolvedPoolParams {
57
+ const tokenIn = isNativeAsset(assetIn)
58
+ ? NATIVE_CURRENCY
59
+ : getAssetAddress(assetIn, chainId)
60
+
61
+ const tokenOut = isNativeAsset(assetOut)
62
+ ? NATIVE_CURRENCY
63
+ : getAssetAddress(assetOut, chainId)
64
+
65
+ // V4 requires sorted tokens: currency0 < currency1
66
+ const [currency0, currency1] =
67
+ tokenIn.toLowerCase() < tokenOut.toLowerCase()
68
+ ? [tokenIn, tokenOut]
69
+ : [tokenOut, tokenIn]
70
+ const zeroForOne = tokenIn.toLowerCase() === currency0.toLowerCase()
71
+
72
+ const poolKey = {
73
+ currency0,
74
+ currency1,
75
+ fee,
76
+ tickSpacing,
77
+ hooks: '0x0000000000000000000000000000000000000000' as Address,
78
+ }
79
+
80
+ return { tokenIn, tokenOut, zeroForOne, poolKey }
81
+ }
82
+
83
+ export interface GetQuoteParams {
84
+ assetIn: Asset
85
+ assetOut: Asset
86
+ amountInWei?: bigint
87
+ amountOutWei?: bigint
88
+ chainId: SupportedChainId
89
+ publicClient: PublicClient
90
+ quoterAddress: Address
91
+ poolManagerAddress: Address
92
+ /** Fee tier in pips (e.g. 100 = 0.01%) */
93
+ fee: number
94
+ /** Tick spacing for the pool */
95
+ tickSpacing: number
96
+ }
97
+
98
+ /**
99
+ * Get a swap quote from the Quoter contract
100
+ */
101
+ export async function getQuote(params: GetQuoteParams): Promise<SwapPrice> {
102
+ const {
103
+ assetIn,
104
+ assetOut,
105
+ amountInWei,
106
+ amountOutWei,
107
+ chainId,
108
+ publicClient,
109
+ quoterAddress,
110
+ poolManagerAddress,
111
+ fee,
112
+ tickSpacing,
113
+ } = params
114
+
115
+ const { tokenIn, zeroForOne, poolKey } = resolvePoolParams(
116
+ assetIn,
117
+ assetOut,
118
+ chainId,
119
+ fee,
120
+ tickSpacing,
121
+ )
122
+
123
+ const isExactInput = amountInWei !== undefined
124
+
125
+ // Read pool mid-price and quote in parallel — no extra sequential RPC call
126
+ const [sqrtPriceX96, quoteResult] = await Promise.all([
127
+ getPoolSqrtPrice({ publicClient, poolManagerAddress, poolKey }),
128
+ isExactInput
129
+ ? publicClient.simulateContract({
130
+ address: quoterAddress,
131
+ abi: QUOTER_ABI,
132
+ functionName: 'quoteExactInputSingle',
133
+ args: [
134
+ {
135
+ poolKey,
136
+ zeroForOne,
137
+ exactAmount: amountInWei,
138
+ hookData: '0x' as `0x${string}`,
139
+ },
140
+ ],
141
+ })
142
+ : publicClient.simulateContract({
143
+ address: quoterAddress,
144
+ abi: QUOTER_ABI,
145
+ functionName: 'quoteExactOutputSingle',
146
+ args: [
147
+ {
148
+ poolKey,
149
+ zeroForOne,
150
+ exactAmount: amountOutWei!,
151
+ hookData: '0x' as `0x${string}`,
152
+ },
153
+ ],
154
+ }),
155
+ ])
156
+
157
+ const amountIn = isExactInput ? amountInWei : quoteResult.result[0]
158
+ const amountOut = isExactInput ? quoteResult.result[0] : amountOutWei!
159
+ const gasEstimate = quoteResult.result[1]
160
+
161
+ const price = calculatePrice(amountIn, amountOut, assetIn, assetOut)
162
+ const priceInverse = calculatePrice(amountOut, amountIn, assetOut, assetIn)
163
+ const priceImpact = calculatePriceImpact({
164
+ sqrtPriceX96,
165
+ amountIn,
166
+ amountOut,
167
+ zeroForOne,
168
+ })
169
+
170
+ const route: SwapRoute = {
171
+ path: [assetIn, assetOut],
172
+ pools: [
173
+ {
174
+ address: tokenIn,
175
+ fee,
176
+ version: 'v4',
177
+ },
178
+ ],
179
+ }
180
+
181
+ return {
182
+ price,
183
+ priceInverse,
184
+ amountIn: parseFloat(formatUnits(amountIn, assetIn.metadata.decimals)),
185
+ amountOut: parseFloat(formatUnits(amountOut, assetOut.metadata.decimals)),
186
+ amountInWei: amountIn,
187
+ amountOutWei: amountOut,
188
+ priceImpact,
189
+ route,
190
+ gasEstimate,
191
+ }
192
+ }
193
+
194
+ export interface EncodeSwapParams {
195
+ amountInWei?: bigint
196
+ amountOutWei?: bigint
197
+ assetIn: Asset
198
+ assetOut: Asset
199
+ slippage: number
200
+ deadline: number
201
+ recipient: Address
202
+ chainId: SupportedChainId
203
+ quote: SwapPrice
204
+ universalRouterAddress: Address
205
+ /** Fee tier in pips (e.g. 100 = 0.01%) */
206
+ fee: number
207
+ /** Tick spacing for the pool */
208
+ tickSpacing: number
209
+ }
210
+
211
+ // V4 Universal Router command
212
+ const V4_SWAP = 0x10
213
+
214
+ // V4 action types
215
+ const SWAP_EXACT_IN_SINGLE = 0x06
216
+ const SWAP_EXACT_OUT_SINGLE = 0x07
217
+ const SETTLE_ALL = 0x0c
218
+ const TAKE_ALL = 0x0f
219
+
220
+ /**
221
+ * Encode Universal Router V4 swap calldata
222
+ * @description Builds calldata for executing a V4 swap through Universal Router
223
+ */
224
+ export function encodeUniversalRouterSwap(params: EncodeSwapParams): Hex {
225
+ const {
226
+ amountInWei,
227
+ assetIn,
228
+ assetOut,
229
+ slippage,
230
+ deadline,
231
+ chainId,
232
+ quote,
233
+ fee,
234
+ tickSpacing,
235
+ } = params
236
+
237
+ const { tokenIn, tokenOut, zeroForOne, poolKey } = resolvePoolParams(
238
+ assetIn,
239
+ assetOut,
240
+ chainId,
241
+ fee,
242
+ tickSpacing,
243
+ )
244
+
245
+ const isExactInput = amountInWei !== undefined
246
+
247
+ let actions: Hex
248
+ let actionParams: Hex[]
249
+
250
+ if (isExactInput) {
251
+ const minAmountOut =
252
+ (quote.amountOutWei * BigInt(Math.round((1 - slippage) * 10000))) / 10000n
253
+
254
+ actions =
255
+ `0x${[SWAP_EXACT_IN_SINGLE, SETTLE_ALL, TAKE_ALL].map((a) => a.toString(16).padStart(2, '0')).join('')}` as Hex
256
+
257
+ actionParams = [
258
+ encodeAbiParameters(EXACT_INPUT_SINGLE_PARAMS, [
259
+ {
260
+ poolKey,
261
+ zeroForOne,
262
+ amountIn: amountInWei,
263
+ amountOutMinimum: minAmountOut,
264
+ hookData: '0x',
265
+ },
266
+ ]),
267
+ encodeAbiParameters(CURRENCY_AMOUNT_PARAMS, [tokenIn, amountInWei]),
268
+ encodeAbiParameters(CURRENCY_AMOUNT_PARAMS, [tokenOut, minAmountOut]),
269
+ ]
270
+ } else {
271
+ const maxAmountIn =
272
+ quote.amountInWei +
273
+ (quote.amountInWei * BigInt(Math.round(slippage * 10000))) / 10000n
274
+
275
+ actions =
276
+ `0x${[SWAP_EXACT_OUT_SINGLE, SETTLE_ALL, TAKE_ALL].map((a) => a.toString(16).padStart(2, '0')).join('')}` as Hex
277
+
278
+ actionParams = [
279
+ encodeAbiParameters(EXACT_OUTPUT_SINGLE_PARAMS, [
280
+ {
281
+ poolKey,
282
+ zeroForOne,
283
+ amountOut: quote.amountOutWei,
284
+ amountInMaximum: maxAmountIn,
285
+ hookData: '0x',
286
+ },
287
+ ]),
288
+ encodeAbiParameters(CURRENCY_AMOUNT_PARAMS, [tokenIn, maxAmountIn]),
289
+ encodeAbiParameters(CURRENCY_AMOUNT_PARAMS, [
290
+ tokenOut,
291
+ quote.amountOutWei,
292
+ ]),
293
+ ]
294
+ }
295
+
296
+ // Encode V4_SWAP input: abi.encode(bytes actions, bytes[] params)
297
+ const v4SwapInput = encodeAbiParameters(
298
+ [{ type: 'bytes' }, { type: 'bytes[]' }],
299
+ [actions, actionParams],
300
+ )
301
+
302
+ return encodeFunctionData({
303
+ abi: UNIVERSAL_ROUTER_ABI,
304
+ functionName: 'execute',
305
+ args: [
306
+ `0x${V4_SWAP.toString(16).padStart(2, '0')}` as Hex,
307
+ [v4SwapInput],
308
+ BigInt(deadline),
309
+ ],
310
+ })
311
+ }
312
+
313
+ function calculatePrice(
314
+ amountIn: bigint,
315
+ amountOut: bigint,
316
+ assetIn: Asset,
317
+ assetOut: Asset,
318
+ ): string {
319
+ const inDecimals = assetIn.metadata.decimals
320
+ const outDecimals = assetOut.metadata.decimals
321
+
322
+ const normalizedIn = parseFloat(formatUnits(amountIn, inDecimals))
323
+ const normalizedOut = parseFloat(formatUnits(amountOut, outDecimals))
324
+
325
+ return (normalizedOut / normalizedIn).toFixed(6)
326
+ }
327
+
328
+ // ─────────────────────────────────────────────────────────────────────────────
329
+ // Price impact via pool mid-price read from PoolManager storage (extsload)
330
+ // Formula mirrors Uniswap SDK's computePriceImpact:
331
+ // (quotedOutput - actualOutput) / quotedOutput
332
+ // @see https://github.com/Uniswap/sdks/blob/main/sdks/sdk-core/src/utils/computePriceImpact.ts
333
+ // ─────────────────────────────────────────────────────────────────────────────
334
+
335
+ /** @see https://docs.uniswap.org/contracts/v4/reference/core/libraries/StateLibrary */
336
+ const POOLS_SLOT = 6n
337
+
338
+ /**
339
+ * Read sqrtPriceX96 from a V4 pool via PoolManager.extsload (single SLOAD)
340
+ */
341
+ export async function getPoolSqrtPrice(params: {
342
+ publicClient: PublicClient
343
+ poolManagerAddress: Address
344
+ poolKey: ResolvedPoolParams['poolKey']
345
+ }): Promise<bigint> {
346
+ const { publicClient, poolManagerAddress, poolKey } = params
347
+
348
+ const poolId = keccak256(
349
+ encodeAbiParameters(POOL_KEY_ABI_TYPE, [
350
+ poolKey.currency0,
351
+ poolKey.currency1,
352
+ poolKey.fee,
353
+ poolKey.tickSpacing,
354
+ poolKey.hooks,
355
+ ]),
356
+ )
357
+
358
+ // pools[poolId].slot0 — slot0 is at offset 0 from the mapping base
359
+ const slot = keccak256(
360
+ encodeAbiParameters(
361
+ [{ type: 'bytes32' }, { type: 'uint256' }],
362
+ [poolId, POOLS_SLOT],
363
+ ),
364
+ )
365
+
366
+ const result = await publicClient.readContract({
367
+ address: poolManagerAddress,
368
+ abi: EXTSLOAD_ABI,
369
+ functionName: 'extsload',
370
+ args: [slot],
371
+ })
372
+
373
+ // sqrtPriceX96 is packed in the lower 160 bits of slot0
374
+ return BigInt(result) & ((1n << 160n) - 1n)
375
+ }
376
+
377
+ /**
378
+ * Price impact as a decimal (0.03 = 3%). Returns 0 if unavailable.
379
+ */
380
+ export function calculatePriceImpact(params: {
381
+ sqrtPriceX96: bigint
382
+ amountIn: bigint
383
+ amountOut: bigint
384
+ zeroForOne: boolean
385
+ }): number {
386
+ const { sqrtPriceX96, amountIn, amountOut, zeroForOne } = params
387
+
388
+ if (sqrtPriceX96 === 0n) return 0
389
+
390
+ // price(currency0→currency1) = sqrtPriceX96² / 2¹⁹² (raw wei units)
391
+ const Q192 = 1n << 192n
392
+ const sqrtPriceSq = sqrtPriceX96 * sqrtPriceX96
393
+
394
+ // What you'd receive at mid-price
395
+ const quotedOutput = zeroForOne
396
+ ? (amountIn * sqrtPriceSq) / Q192
397
+ : (amountIn * Q192) / sqrtPriceSq
398
+
399
+ if (quotedOutput === 0n) return 0
400
+
401
+ const SCALE = 10n ** 18n
402
+ const impactScaled = ((quotedOutput - amountOut) * SCALE) / quotedOutput
403
+ const impact = Number(impactScaled) / Number(SCALE)
404
+
405
+ return Math.max(0, impact)
406
+ }
@@ -0,0 +1,24 @@
1
+ import type {
2
+ SwapMarketConfig,
3
+ SwapProviderConfig,
4
+ } from '@/types/swap/index.js'
5
+
6
+ /**
7
+ * Uniswap-specific market config with V4 pool parameters
8
+ */
9
+ export interface UniswapMarketConfig extends SwapMarketConfig {
10
+ /** Fee tier in pips (e.g. 100 = 0.01%) */
11
+ fee?: number
12
+ /** Tick spacing for the pool */
13
+ tickSpacing?: number
14
+ }
15
+
16
+ /**
17
+ * Uniswap swap provider configuration
18
+ */
19
+ export interface UniswapSwapProviderConfig extends SwapProviderConfig {
20
+ marketAllowlist?: UniswapMarketConfig[]
21
+ marketBlocklist?: UniswapMarketConfig[]
22
+ /** Permit2 approval expiry in seconds from now. Defaults to 30 days. */
23
+ permit2ExpirySeconds?: number
24
+ }