@whetstone-research/doppler-sdk 0.0.1-alpha.8 → 0.0.1

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 (368) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +726 -25
  3. package/dist/DopplerSDK.d.mts +45 -7
  4. package/dist/DopplerSDK.d.ts +45 -7
  5. package/dist/DopplerSDK.js +35 -12
  6. package/dist/DopplerSDK.mjs +34 -11
  7. package/dist/abis/bytecodes.d.mts +3 -2
  8. package/dist/abis/bytecodes.d.ts +3 -2
  9. package/dist/abis/bytecodes.js +9 -6
  10. package/dist/abis/bytecodes.mjs +1 -2
  11. package/dist/abis/index.d.mts +1507 -129
  12. package/dist/abis/index.d.ts +1507 -129
  13. package/dist/abis/index.js +43 -20
  14. package/dist/abis/index.mjs +2 -3
  15. package/dist/addresses.d.mts +16 -3
  16. package/dist/addresses.d.ts +16 -3
  17. package/dist/addresses.js +13 -5
  18. package/dist/addresses.mjs +2 -2
  19. package/dist/builders/DynamicAuctionBuilder.d.mts +119 -0
  20. package/dist/builders/DynamicAuctionBuilder.d.ts +119 -0
  21. package/dist/builders/DynamicAuctionBuilder.js +29 -0
  22. package/dist/builders/DynamicAuctionBuilder.js.map +1 -0
  23. package/dist/builders/DynamicAuctionBuilder.mjs +20 -0
  24. package/dist/builders/DynamicAuctionBuilder.mjs.map +1 -0
  25. package/dist/builders/MulticurveBuilder.d.mts +132 -0
  26. package/dist/builders/MulticurveBuilder.d.ts +132 -0
  27. package/dist/builders/MulticurveBuilder.js +29 -0
  28. package/dist/builders/MulticurveBuilder.js.map +1 -0
  29. package/dist/builders/MulticurveBuilder.mjs +20 -0
  30. package/dist/builders/MulticurveBuilder.mjs.map +1 -0
  31. package/dist/builders/StaticAuctionBuilder.d.mts +124 -0
  32. package/dist/builders/StaticAuctionBuilder.d.ts +124 -0
  33. package/dist/builders/StaticAuctionBuilder.js +29 -0
  34. package/dist/builders/StaticAuctionBuilder.js.map +1 -0
  35. package/dist/builders/StaticAuctionBuilder.mjs +20 -0
  36. package/dist/builders/StaticAuctionBuilder.mjs.map +1 -0
  37. package/dist/builders/index.d.mts +8 -0
  38. package/dist/builders/index.d.ts +8 -0
  39. package/dist/builders/index.js +56 -0
  40. package/dist/builders/index.js.map +1 -0
  41. package/dist/builders/index.mjs +23 -0
  42. package/dist/builders/index.mjs.map +1 -0
  43. package/dist/builders/shared.d.mts +116 -0
  44. package/dist/builders/shared.d.ts +116 -0
  45. package/dist/builders/shared.js +39 -0
  46. package/dist/builders/shared.js.map +1 -0
  47. package/dist/builders/shared.mjs +18 -0
  48. package/dist/builders/shared.mjs.map +1 -0
  49. package/dist/builders.d.mts +8 -131
  50. package/dist/builders.d.ts +8 -131
  51. package/dist/builders.js +44 -5
  52. package/dist/builders.mjs +22 -3
  53. package/dist/chunk-3PNCB4W5.js +4 -0
  54. package/dist/{chunk-KRN3ROUE.js.map → chunk-3PNCB4W5.js.map} +1 -1
  55. package/dist/chunk-3RK7LRAA.js +282 -0
  56. package/dist/chunk-3RK7LRAA.js.map +1 -0
  57. package/dist/chunk-4HM3ERBU.js +13 -0
  58. package/dist/chunk-4HM3ERBU.js.map +1 -0
  59. package/dist/{chunk-7W72MFJO.mjs → chunk-4TROGENW.mjs} +5 -4
  60. package/dist/chunk-4TROGENW.mjs.map +1 -0
  61. package/dist/chunk-5TL5V6UX.mjs +3 -0
  62. package/dist/{chunk-AZLFJNTG.mjs.map → chunk-5TL5V6UX.mjs.map} +1 -1
  63. package/dist/chunk-64AWG57M.mjs +192 -0
  64. package/dist/chunk-64AWG57M.mjs.map +1 -0
  65. package/dist/chunk-6KWCHTK3.js +166 -0
  66. package/dist/chunk-6KWCHTK3.js.map +1 -0
  67. package/dist/chunk-6OOWOPCX.js +1708 -0
  68. package/dist/chunk-6OOWOPCX.js.map +1 -0
  69. package/dist/chunk-7BBRPWQJ.js +257 -0
  70. package/dist/chunk-7BBRPWQJ.js.map +1 -0
  71. package/dist/{chunk-FVTIDXYK.mjs → chunk-AKSEBAR7.mjs} +29 -19
  72. package/dist/chunk-AKSEBAR7.mjs.map +1 -0
  73. package/dist/chunk-AS64GWBX.js +204 -0
  74. package/dist/chunk-AS64GWBX.js.map +1 -0
  75. package/dist/chunk-AULFBXM5.mjs +331 -0
  76. package/dist/chunk-AULFBXM5.mjs.map +1 -0
  77. package/dist/chunk-AW3WR2D3.mjs +238 -0
  78. package/dist/chunk-AW3WR2D3.mjs.map +1 -0
  79. package/dist/chunk-BIQQ53O2.js +45 -0
  80. package/dist/chunk-BIQQ53O2.js.map +1 -0
  81. package/dist/chunk-C6MPV3CY.js +260 -0
  82. package/dist/chunk-C6MPV3CY.js.map +1 -0
  83. package/dist/{chunk-AYPP5JEQ.mjs → chunk-CLEQO6GU.mjs} +5 -5
  84. package/dist/chunk-CLEQO6GU.mjs.map +1 -0
  85. package/dist/chunk-CVHPLURA.js +147 -0
  86. package/dist/chunk-CVHPLURA.js.map +1 -0
  87. package/dist/chunk-D2RBCFNW.mjs +130 -0
  88. package/dist/chunk-D2RBCFNW.mjs.map +1 -0
  89. package/dist/chunk-ECD4FV3A.mjs +11 -0
  90. package/dist/chunk-ECD4FV3A.mjs.map +1 -0
  91. package/dist/chunk-EDJBZPMW.mjs +255 -0
  92. package/dist/chunk-EDJBZPMW.mjs.map +1 -0
  93. package/dist/chunk-FPAI4QYW.mjs +145 -0
  94. package/dist/chunk-FPAI4QYW.mjs.map +1 -0
  95. package/dist/chunk-HM25ZMO3.js +18 -0
  96. package/dist/chunk-HM25ZMO3.js.map +1 -0
  97. package/dist/chunk-IHC6UYKK.js +4 -0
  98. package/dist/{chunk-DRBRT57F.js.map → chunk-IHC6UYKK.js.map} +1 -1
  99. package/dist/{chunk-DMAHXBA5.mjs → chunk-J5BFFL3X.mjs} +87 -47
  100. package/dist/chunk-J5BFFL3X.mjs.map +1 -0
  101. package/dist/chunk-JIKAD4YL.js +4 -0
  102. package/dist/{chunk-KEXKKQVW.js.map → chunk-JIKAD4YL.js.map} +1 -1
  103. package/dist/{chunk-EFAPDN4J.js → chunk-JWEXGALU.js} +730 -33
  104. package/dist/chunk-JWEXGALU.js.map +1 -0
  105. package/dist/{chunk-4K5GBNQV.mjs → chunk-KDT76YQE.mjs} +52 -13
  106. package/dist/chunk-KDT76YQE.mjs.map +1 -0
  107. package/dist/chunk-LMQLMMEX.js +317 -0
  108. package/dist/chunk-LMQLMMEX.js.map +1 -0
  109. package/dist/{chunk-TOMVBPNZ.js → chunk-LS4TK6SX.js} +9 -4
  110. package/dist/chunk-LS4TK6SX.js.map +1 -0
  111. package/dist/chunk-M4WMHD3X.mjs +40 -0
  112. package/dist/chunk-M4WMHD3X.mjs.map +1 -0
  113. package/dist/chunk-MCOK3UFR.mjs +280 -0
  114. package/dist/chunk-MCOK3UFR.mjs.map +1 -0
  115. package/dist/chunk-MGQSQCFG.js +176 -0
  116. package/dist/chunk-MGQSQCFG.js.map +1 -0
  117. package/dist/chunk-MKE3BUL3.mjs +3 -0
  118. package/dist/{chunk-CYDWEPFL.mjs.map → chunk-MKE3BUL3.mjs.map} +1 -1
  119. package/dist/chunk-MNJ5OYPE.mjs +17 -0
  120. package/dist/chunk-MNJ5OYPE.mjs.map +1 -0
  121. package/dist/chunk-MNXD45J7.mjs +164 -0
  122. package/dist/chunk-MNXD45J7.mjs.map +1 -0
  123. package/dist/chunk-NGDPQC5E.js +333 -0
  124. package/dist/chunk-NGDPQC5E.js.map +1 -0
  125. package/dist/chunk-NNNCVFOH.mjs +16 -0
  126. package/dist/chunk-NNNCVFOH.mjs.map +1 -0
  127. package/dist/chunk-NZ4BJ2IC.mjs +315 -0
  128. package/dist/chunk-NZ4BJ2IC.mjs.map +1 -0
  129. package/dist/chunk-OKNM7ODQ.js +29 -0
  130. package/dist/chunk-OKNM7ODQ.js.map +1 -0
  131. package/dist/{chunk-DCFHANLR.mjs → chunk-OTG75GVH.mjs} +725 -34
  132. package/dist/chunk-OTG75GVH.mjs.map +1 -0
  133. package/dist/chunk-OZ6DGBRL.mjs +25 -0
  134. package/dist/chunk-OZ6DGBRL.mjs.map +1 -0
  135. package/dist/chunk-P25HBGP5.mjs +3 -0
  136. package/dist/chunk-P25HBGP5.mjs.map +1 -0
  137. package/dist/{chunk-XG7K4R56.js → chunk-P7KLEPVI.js} +52 -12
  138. package/dist/chunk-P7KLEPVI.js.map +1 -0
  139. package/dist/{chunk-OPKQMN46.mjs → chunk-PAPXGPJB.mjs} +9 -4
  140. package/dist/chunk-PAPXGPJB.mjs.map +1 -0
  141. package/dist/chunk-PCNXJAU5.js +19 -0
  142. package/dist/chunk-PCNXJAU5.js.map +1 -0
  143. package/dist/{chunk-5IT5OXQ5.js → chunk-PD6HWEMG.js} +40 -30
  144. package/dist/chunk-PD6HWEMG.js.map +1 -0
  145. package/dist/{chunk-ER42VG7H.js → chunk-PH2KXREH.js} +20 -3
  146. package/dist/chunk-PH2KXREH.js.map +1 -0
  147. package/dist/chunk-Q5ERW5ZW.mjs +107 -0
  148. package/dist/chunk-Q5ERW5ZW.mjs.map +1 -0
  149. package/dist/chunk-Q7YNBSVH.js +28 -0
  150. package/dist/chunk-Q7YNBSVH.js.map +1 -0
  151. package/dist/{chunk-T644D54P.mjs → chunk-QKO2FZGN.mjs} +16 -4
  152. package/dist/chunk-QKO2FZGN.mjs.map +1 -0
  153. package/dist/{chunk-CIRZKWLL.js → chunk-RVFSRYI5.js} +5 -3
  154. package/dist/chunk-RVFSRYI5.js.map +1 -0
  155. package/dist/{chunk-KPBCG4X2.js → chunk-RW37KJ77.js} +11 -11
  156. package/dist/chunk-RW37KJ77.js.map +1 -0
  157. package/dist/chunk-SD7BHT2F.mjs +3 -0
  158. package/dist/chunk-SD7BHT2F.mjs.map +1 -0
  159. package/dist/chunk-SP5M57BG.mjs +258 -0
  160. package/dist/chunk-SP5M57BG.mjs.map +1 -0
  161. package/dist/chunk-TKSHYEYA.mjs +1706 -0
  162. package/dist/chunk-TKSHYEYA.mjs.map +1 -0
  163. package/dist/chunk-WTS75RUC.js +4 -0
  164. package/dist/chunk-WTS75RUC.js.map +1 -0
  165. package/dist/{chunk-ZRDU6CIB.js → chunk-XRPIGMA2.js} +108 -68
  166. package/dist/chunk-XRPIGMA2.js.map +1 -0
  167. package/dist/chunk-XTKSM4QE.js +132 -0
  168. package/dist/chunk-XTKSM4QE.js.map +1 -0
  169. package/dist/chunk-XUE3CIJ5.mjs +174 -0
  170. package/dist/chunk-XUE3CIJ5.mjs.map +1 -0
  171. package/dist/chunk-YYUOLM6U.js +244 -0
  172. package/dist/chunk-YYUOLM6U.js.map +1 -0
  173. package/dist/chunk-ZH44DHVR.mjs +26 -0
  174. package/dist/chunk-ZH44DHVR.mjs.map +1 -0
  175. package/dist/chunk-ZPHOOG72.js +112 -0
  176. package/dist/chunk-ZPHOOG72.js.map +1 -0
  177. package/dist/constants.d.mts +7 -2
  178. package/dist/constants.d.ts +7 -2
  179. package/dist/constants.js +57 -38
  180. package/dist/constants.mjs +1 -2
  181. package/dist/deployments.generated.d.mts +2 -0
  182. package/dist/deployments.generated.d.ts +2 -0
  183. package/dist/deployments.generated.js +12 -0
  184. package/dist/deployments.generated.js.map +1 -0
  185. package/dist/deployments.generated.mjs +3 -0
  186. package/dist/deployments.generated.mjs.map +1 -0
  187. package/dist/entities/DopplerFactory.d.mts +139 -11
  188. package/dist/entities/DopplerFactory.d.ts +139 -11
  189. package/dist/entities/DopplerFactory.js +17 -7
  190. package/dist/entities/DopplerFactory.mjs +16 -6
  191. package/dist/entities/auction/DynamicAuction.d.mts +19 -4
  192. package/dist/entities/auction/DynamicAuction.d.ts +19 -4
  193. package/dist/entities/auction/DynamicAuction.js +6 -6
  194. package/dist/entities/auction/DynamicAuction.mjs +5 -5
  195. package/dist/entities/auction/MulticurvePool.d.mts +55 -0
  196. package/dist/entities/auction/MulticurvePool.d.ts +55 -0
  197. package/dist/entities/auction/MulticurvePool.js +18 -0
  198. package/dist/entities/auction/MulticurvePool.js.map +1 -0
  199. package/dist/entities/auction/MulticurvePool.mjs +9 -0
  200. package/dist/entities/auction/MulticurvePool.mjs.map +1 -0
  201. package/dist/entities/auction/StaticAuction.d.mts +6 -3
  202. package/dist/entities/auction/StaticAuction.d.ts +6 -3
  203. package/dist/entities/auction/StaticAuction.js +6 -6
  204. package/dist/entities/auction/StaticAuction.mjs +5 -5
  205. package/dist/entities/auction/index.d.mts +3 -0
  206. package/dist/entities/auction/index.d.ts +3 -0
  207. package/dist/entities/auction/index.js +16 -9
  208. package/dist/entities/auction/index.mjs +10 -7
  209. package/dist/entities/quoter/Quoter.d.mts +44 -2
  210. package/dist/entities/quoter/Quoter.d.ts +44 -2
  211. package/dist/entities/quoter/Quoter.js +6 -6
  212. package/dist/entities/quoter/Quoter.mjs +5 -5
  213. package/dist/entities/quoter/index.d.mts +3 -0
  214. package/dist/entities/quoter/index.d.ts +3 -0
  215. package/dist/entities/quoter/index.js +6 -6
  216. package/dist/entities/quoter/index.mjs +5 -5
  217. package/dist/entities/token/derc20/Derc20.d.mts +33 -7
  218. package/dist/entities/token/derc20/Derc20.d.ts +33 -7
  219. package/dist/entities/token/derc20/Derc20.js +4 -5
  220. package/dist/entities/token/derc20/Derc20.mjs +3 -4
  221. package/dist/entities/token/derc20/index.d.mts +3 -0
  222. package/dist/entities/token/derc20/index.d.ts +3 -0
  223. package/dist/entities/token/derc20/index.js +4 -5
  224. package/dist/entities/token/derc20/index.mjs +3 -4
  225. package/dist/entities/token/eth/Eth.d.mts +7 -3
  226. package/dist/entities/token/eth/Eth.d.ts +7 -3
  227. package/dist/entities/token/eth/Eth.js +2 -3
  228. package/dist/entities/token/eth/Eth.mjs +1 -2
  229. package/dist/entities/token/eth/index.d.mts +3 -0
  230. package/dist/entities/token/eth/index.d.ts +3 -0
  231. package/dist/entities/token/eth/index.js +2 -3
  232. package/dist/entities/token/eth/index.mjs +1 -2
  233. package/dist/entities/token/index.d.mts +3 -0
  234. package/dist/entities/token/index.d.ts +3 -0
  235. package/dist/entities/token/index.js +6 -7
  236. package/dist/entities/token/index.mjs +4 -5
  237. package/dist/index.d.mts +18 -6
  238. package/dist/index.d.ts +18 -6
  239. package/dist/index.js +305 -140
  240. package/dist/index.js.map +1 -1
  241. package/dist/index.mjs +32 -19
  242. package/dist/index.mjs.map +1 -1
  243. package/dist/types.d.mts +260 -22
  244. package/dist/types.d.ts +260 -22
  245. package/dist/types.js +12 -3
  246. package/dist/types.mjs +3 -2
  247. package/dist/utils/airlock.d.mts +11 -0
  248. package/dist/utils/airlock.d.ts +11 -0
  249. package/dist/utils/airlock.js +26 -0
  250. package/dist/utils/airlock.js.map +1 -0
  251. package/dist/utils/airlock.mjs +5 -0
  252. package/dist/utils/airlock.mjs.map +1 -0
  253. package/dist/utils/balanceDelta.d.mts +10 -0
  254. package/dist/utils/balanceDelta.d.ts +10 -0
  255. package/dist/utils/balanceDelta.js +12 -0
  256. package/dist/utils/balanceDelta.js.map +1 -0
  257. package/dist/utils/balanceDelta.mjs +3 -0
  258. package/dist/utils/balanceDelta.mjs.map +1 -0
  259. package/dist/utils/computeOptimalGamma.d.mts +7 -0
  260. package/dist/utils/computeOptimalGamma.d.ts +7 -0
  261. package/dist/utils/computeOptimalGamma.js +12 -0
  262. package/dist/utils/computeOptimalGamma.js.map +1 -0
  263. package/dist/utils/computeOptimalGamma.mjs +3 -0
  264. package/dist/utils/computeOptimalGamma.mjs.map +1 -0
  265. package/dist/utils/index.d.mts +11 -0
  266. package/dist/utils/index.d.ts +11 -0
  267. package/dist/utils/index.js +114 -24
  268. package/dist/utils/index.mjs +14 -4
  269. package/dist/utils/isToken0Expected.d.mts +13 -0
  270. package/dist/utils/isToken0Expected.d.ts +13 -0
  271. package/dist/utils/isToken0Expected.js +12 -0
  272. package/dist/utils/isToken0Expected.js.map +1 -0
  273. package/dist/utils/isToken0Expected.mjs +3 -0
  274. package/dist/utils/isToken0Expected.mjs.map +1 -0
  275. package/dist/utils/marketCapHelpers.d.mts +309 -0
  276. package/dist/utils/marketCapHelpers.d.ts +309 -0
  277. package/dist/utils/marketCapHelpers.js +54 -0
  278. package/dist/utils/marketCapHelpers.js.map +1 -0
  279. package/dist/utils/marketCapHelpers.mjs +5 -0
  280. package/dist/utils/marketCapHelpers.mjs.map +1 -0
  281. package/dist/utils/poolKey.d.mts +17 -0
  282. package/dist/utils/poolKey.d.ts +17 -0
  283. package/dist/utils/poolKey.js +12 -0
  284. package/dist/utils/poolKey.js.map +1 -0
  285. package/dist/utils/poolKey.mjs +3 -0
  286. package/dist/utils/poolKey.mjs.map +1 -0
  287. package/dist/utils/priceHelpers.d.mts +3 -3
  288. package/dist/utils/priceHelpers.d.ts +3 -3
  289. package/dist/utils/priceHelpers.js +10 -11
  290. package/dist/utils/priceHelpers.mjs +2 -3
  291. package/dist/utils/tickMath.d.mts +8 -1
  292. package/dist/utils/tickMath.d.ts +8 -1
  293. package/dist/utils/tickMath.js +17 -14
  294. package/dist/utils/tickMath.mjs +1 -2
  295. package/dist/utils/tokenAddressMiner.d.mts +30 -0
  296. package/dist/utils/tokenAddressMiner.d.ts +30 -0
  297. package/dist/utils/tokenAddressMiner.js +14 -0
  298. package/dist/utils/tokenAddressMiner.js.map +1 -0
  299. package/dist/utils/tokenAddressMiner.mjs +5 -0
  300. package/dist/utils/tokenAddressMiner.mjs.map +1 -0
  301. package/package.json +14 -11
  302. package/dist/__tests__/mocks/addresses.d.mts +0 -46
  303. package/dist/__tests__/mocks/addresses.d.ts +0 -46
  304. package/dist/__tests__/mocks/addresses.js +0 -53
  305. package/dist/__tests__/mocks/addresses.js.map +0 -1
  306. package/dist/__tests__/mocks/addresses.mjs +0 -44
  307. package/dist/__tests__/mocks/addresses.mjs.map +0 -1
  308. package/dist/__tests__/mocks/clients.d.mts +0 -22
  309. package/dist/__tests__/mocks/clients.d.ts +0 -22
  310. package/dist/__tests__/mocks/clients.js +0 -17036
  311. package/dist/__tests__/mocks/clients.js.map +0 -1
  312. package/dist/__tests__/mocks/clients.mjs +0 -17032
  313. package/dist/__tests__/mocks/clients.mjs.map +0 -1
  314. package/dist/chunk-2N5JZSZ4.js +0 -14
  315. package/dist/chunk-2N5JZSZ4.js.map +0 -1
  316. package/dist/chunk-3OZRDL3O.js +0 -162
  317. package/dist/chunk-3OZRDL3O.js.map +0 -1
  318. package/dist/chunk-4K5GBNQV.mjs.map +0 -1
  319. package/dist/chunk-5IT5OXQ5.js.map +0 -1
  320. package/dist/chunk-7F5IXZLH.js +0 -308
  321. package/dist/chunk-7F5IXZLH.js.map +0 -1
  322. package/dist/chunk-7VP5VR7J.js +0 -82
  323. package/dist/chunk-7VP5VR7J.js.map +0 -1
  324. package/dist/chunk-7W72MFJO.mjs.map +0 -1
  325. package/dist/chunk-AYPP5JEQ.mjs.map +0 -1
  326. package/dist/chunk-AZLFJNTG.mjs +0 -3
  327. package/dist/chunk-CIRZKWLL.js.map +0 -1
  328. package/dist/chunk-CYDWEPFL.mjs +0 -3
  329. package/dist/chunk-DCFHANLR.mjs.map +0 -1
  330. package/dist/chunk-DMAHXBA5.mjs.map +0 -1
  331. package/dist/chunk-DRBRT57F.js +0 -4
  332. package/dist/chunk-EFAPDN4J.js.map +0 -1
  333. package/dist/chunk-ER42VG7H.js.map +0 -1
  334. package/dist/chunk-FVTIDXYK.mjs.map +0 -1
  335. package/dist/chunk-IHBIBFZK.mjs +0 -12
  336. package/dist/chunk-IHBIBFZK.mjs.map +0 -1
  337. package/dist/chunk-IXSKPEHB.mjs +0 -160
  338. package/dist/chunk-IXSKPEHB.mjs.map +0 -1
  339. package/dist/chunk-KEXKKQVW.js +0 -42
  340. package/dist/chunk-KFD6U3LQ.mjs +0 -305
  341. package/dist/chunk-KFD6U3LQ.mjs.map +0 -1
  342. package/dist/chunk-KPBCG4X2.js.map +0 -1
  343. package/dist/chunk-KRN3ROUE.js +0 -4
  344. package/dist/chunk-KT7U37XS.mjs +0 -207
  345. package/dist/chunk-KT7U37XS.mjs.map +0 -1
  346. package/dist/chunk-LOROXNH3.mjs +0 -37
  347. package/dist/chunk-LOROXNH3.mjs.map +0 -1
  348. package/dist/chunk-O6GYIJ6X.mjs +0 -80
  349. package/dist/chunk-O6GYIJ6X.mjs.map +0 -1
  350. package/dist/chunk-OPKQMN46.mjs.map +0 -1
  351. package/dist/chunk-RIMM47JL.mjs +0 -176
  352. package/dist/chunk-RIMM47JL.mjs.map +0 -1
  353. package/dist/chunk-SUOMK3CU.js +0 -872
  354. package/dist/chunk-SUOMK3CU.js.map +0 -1
  355. package/dist/chunk-T644D54P.mjs.map +0 -1
  356. package/dist/chunk-TOMVBPNZ.js.map +0 -1
  357. package/dist/chunk-XEMZQHTX.mjs +0 -870
  358. package/dist/chunk-XEMZQHTX.mjs.map +0 -1
  359. package/dist/chunk-XG7K4R56.js.map +0 -1
  360. package/dist/chunk-XQ2VMR26.js +0 -180
  361. package/dist/chunk-XQ2VMR26.js.map +0 -1
  362. package/dist/chunk-ZAIP54LX.js +0 -209
  363. package/dist/chunk-ZAIP54LX.js.map +0 -1
  364. package/dist/chunk-ZRDU6CIB.js.map +0 -1
  365. package/dist/magic-string.es-CBLXTCZP.js +0 -1304
  366. package/dist/magic-string.es-CBLXTCZP.js.map +0 -1
  367. package/dist/magic-string.es-QHA47FSB.mjs +0 -1298
  368. package/dist/magic-string.es-QHA47FSB.mjs.map +0 -1
package/README.md CHANGED
@@ -10,6 +10,7 @@ The Doppler SDK consolidates functionality from the previous `doppler-v3-sdk` an
10
10
 
11
11
  - **Static Auctions**: Fixed price range liquidity bootstrapping using Uniswap V3
12
12
  - **Dynamic Auctions**: Gradual Dutch auctions using Uniswap V4 hooks
13
+ - **Multicurve Initializer**: Seed Uniswap V4 pools across multiple curves
13
14
  - **Flexible Migration**: Support for migrating to Uniswap V2, V3, or V4
14
15
  - **Token Management**: Built-in support for DERC20 tokens with vesting
15
16
  - **Type Safety**: Full TypeScript support with discriminated unions
@@ -64,8 +65,13 @@ import { StaticAuctionBuilder } from '@whetstone-research/doppler-sdk'
64
65
  const params = new StaticAuctionBuilder()
65
66
  .tokenConfig({ name: 'My Token', symbol: 'MTK', tokenURI: 'https://example.com/metadata.json' })
66
67
  .saleConfig({ initialSupply: parseEther('1000000000'), numTokensToSell: parseEther('900000000'), numeraire: '0x...' })
67
- .poolByTicks({ startTick: -92103, endTick: -69080, fee: 10000, numPositions: 15 })
68
- .withVesting({ duration: BigInt(365 * 24 * 60 * 60) })
68
+ .poolByTicks({ startTick: -92200, endTick: -69000, fee: 10000, numPositions: 15 })
69
+ .withVesting({
70
+ duration: BigInt(365 * 24 * 60 * 60),
71
+ // Optional: specify multiple recipients and amounts
72
+ // recipients: ['0xTeam...', '0xAdvisor...'],
73
+ // amounts: [parseEther('50000000'), parseEther('50000000')]
74
+ })
69
75
  .withMigration({ type: 'uniswapV2' })
70
76
  .withUserAddress('0x...')
71
77
  .build()
@@ -75,19 +81,68 @@ console.log('Pool address:', result.poolAddress)
75
81
  console.log('Token address:', result.tokenAddress)
76
82
  ```
77
83
 
84
+ > **Tick spacing reminder:** When you provide ticks manually via `poolByTicks`, make sure both `startTick` and `endTick` are exact multiples of the fee tier's tick spacing (100→1, 500→10, 3000→60, 10000→200). The SDK now validates this locally and will fail fast if the ticks are misaligned.
85
+
86
+ ### Static Auction with Lockable Beneficiaries (V3)
87
+
88
+ When you want fee revenue to flow to specific addresses without migrating liquidity, use lockable beneficiaries. The pool enters a "Locked" state where trading fees are collected and distributed to beneficiaries:
89
+
90
+ ```typescript
91
+ import { StaticAuctionBuilder, WAD, getAirlockOwner } from '@whetstone-research/doppler-sdk'
92
+ import { parseEther } from 'viem'
93
+
94
+ // Get the protocol owner (required beneficiary with min 5%)
95
+ const protocolOwner = await getAirlockOwner(publicClient)
96
+
97
+ // Define beneficiaries - shares must sum to WAD (1e18 = 100%)
98
+ const beneficiaries = [
99
+ { beneficiary: protocolOwner, shares: parseEther('0.05') }, // 5% (minimum required)
100
+ { beneficiary: '0xTeamWallet...', shares: parseEther('0.45') }, // 45%
101
+ { beneficiary: '0xDAOTreasury...', shares: parseEther('0.50') }, // 50%
102
+ ]
103
+
104
+ const params = new StaticAuctionBuilder(chainId)
105
+ .tokenConfig({ name: 'My Token', symbol: 'MTK', tokenURI: 'https://example.com/metadata.json' })
106
+ .saleConfig({ initialSupply: parseEther('1000000000'), numTokensToSell: parseEther('900000000'), numeraire: wethAddress })
107
+ .poolByTicks({
108
+ startTick: 174960, // Must be multiple of 60 for fee 3000
109
+ endTick: 225000,
110
+ fee: 3000, // Set > 0 to accumulate fees for beneficiaries
111
+ })
112
+ .withBeneficiaries(beneficiaries) // Lock pool and enable fee streaming
113
+ .withMigration({ type: 'noOp' }) // Use NoOp since pool is locked
114
+ .withGovernance({ type: 'default' })
115
+ .withUserAddress('0x...')
116
+ .build()
117
+
118
+ const result = await sdk.factory.createStaticAuction(params)
119
+ console.log('Pool address:', result.poolAddress) // SAVE THIS - needed to collect fees!
120
+ ```
121
+
122
+ **Important Notes:**
123
+ - **Shares must sum to exactly WAD (1e18 = 100%)**
124
+ - **Protocol owner must receive at least 5%** of fees
125
+ - **SDK automatically sorts beneficiaries** by address (ascending)
126
+ - **Use `withMigration({ type: 'noOp' })`** - locked pools cannot migrate
127
+ - **Set fee > 0** (e.g., 3000 for 0.3%) to accumulate trading fees
128
+ - **Pool status = "Locked"** - liquidity stays permanently in the V3 pool
129
+ - **Anyone can call `collectFees()`** to trigger distribution to beneficiaries
130
+
131
+ See [examples/static-auction-lockable-beneficiaries.ts](./examples/static-auction-lockable-beneficiaries.ts) for a complete example.
132
+
78
133
  ### Dynamic Auction (Dutch Auction)
79
134
 
80
135
  Dynamic auctions use Uniswap V4 hooks to implement gradual Dutch auctions where the price moves over time.
81
136
 
82
137
  ```typescript
83
- import { DynamicAuctionBuilder } from '@whetstone-research/doppler-sdk'
138
+ import { DynamicAuctionBuilder, DAY_SECONDS } from '@whetstone-research/doppler-sdk'
84
139
 
85
140
  const params = new DynamicAuctionBuilder()
86
141
  .tokenConfig({ name: 'My Token', symbol: 'MTK', tokenURI: 'https://example.com/metadata.json' })
87
142
  .saleConfig({ initialSupply: parseEther('1000000'), numTokensToSell: parseEther('900000'), numeraire: '0x...' })
88
143
  .poolConfig({ fee: 3000, tickSpacing: 60 })
89
144
  .auctionByTicks({
90
- durationDays: 7,
145
+ duration: 7 * DAY_SECONDS,
91
146
  epochLength: 3600,
92
147
  startTick: -92103,
93
148
  endTick: -69080,
@@ -95,7 +150,12 @@ const params = new DynamicAuctionBuilder()
95
150
  maxProceeds: parseEther('1000'),
96
151
  numPdSlugs: 5,
97
152
  })
98
- .withVesting({ duration: BigInt(365 * 24 * 60 * 60) })
153
+ .withVesting({
154
+ duration: BigInt(365 * 24 * 60 * 60),
155
+ // Optional: specify multiple recipients and amounts
156
+ // recipients: ['0xTeam...', '0xAdvisor...'],
157
+ // amounts: [parseEther('50000'), parseEther('50000')]
158
+ })
99
159
  .withMigration({
100
160
  type: 'uniswapV4',
101
161
  fee: 3000,
@@ -103,11 +163,21 @@ const params = new DynamicAuctionBuilder()
103
163
  streamableFees: {
104
164
  lockDuration: 365 * 24 * 60 * 60,
105
165
  beneficiaries: [
106
- { address: '0x...', percentage: 5000 },
107
- { address: '0x...', percentage: 5000 },
166
+ { beneficiary: '0x...', shares: parseEther('0.5') }, // 50%
167
+ { beneficiary: '0x...', shares: parseEther('0.5') }, // 50%
108
168
  ],
109
169
  },
110
170
  })
171
+ // Optional: override module addresses instead of chain defaults
172
+ .withAirlock('0xAirlock...')
173
+ .withPoolManager('0xPoolMgr...')
174
+ .withDopplerDeployer('0xDeployer...')
175
+ .withTokenFactory('0xFactory...')
176
+ .withV4Initializer('0xInitializer...')
177
+ .withGovernanceFactory('0xGovFactory...') // used for both standard and no‑op governance
178
+ // .withV2Migrator('0xV2Migrator...')
179
+ // .withV3Migrator('0xV3Migrator...')
180
+ // .withV4Migrator('0xV4Migrator...')
111
181
  .withUserAddress('0x...')
112
182
  .build()
113
183
 
@@ -116,6 +186,160 @@ console.log('Hook address:', result.hookAddress)
116
186
  console.log('Token address:', result.tokenAddress)
117
187
  ```
118
188
 
189
+ ### Multicurve Auction (V4 Multicurve Initializer)
190
+
191
+ Multicurve auctions use a Uniswap V4-style initializer that seeds liquidity across multiple curves in a single pool. This enables richer distributions and can be combined with any supported migration path (V2, V3, V4, or NoOp).
192
+
193
+ **Standard Multicurve with Migration:**
194
+ ```typescript
195
+ import { MulticurveBuilder } from '@whetstone-research/doppler-sdk'
196
+ import { parseEther } from 'viem'
197
+ import { base } from 'viem/chains'
198
+
199
+ const params = new MulticurveBuilder(base.id)
200
+ .tokenConfig({ name: 'My Token', symbol: 'MTK', tokenURI: 'https://example.com/metadata.json' })
201
+ .saleConfig({ initialSupply: parseEther('1000000'), numTokensToSell: parseEther('900000'), numeraire: '0x...' })
202
+ .poolConfig({
203
+ fee: 0,
204
+ tickSpacing: 8,
205
+ curves: [
206
+ { tickLower: 0, tickUpper: 240000, numPositions: 10, shares: parseEther('0.5') },
207
+ { tickLower: 16000, tickUpper: 240000, numPositions: 10, shares: parseEther('0.5') },
208
+ ],
209
+ })
210
+ .withGovernance({ type: 'default' })
211
+ // Choose a migration path (V2, V3, or V4)
212
+ .withMigration({ type: 'uniswapV2' })
213
+ .withUserAddress('0x...')
214
+ .build()
215
+
216
+ const result = await sdk.factory.createMulticurve(params)
217
+ console.log('Pool address:', result.poolAddress)
218
+ console.log('Token address:', result.tokenAddress)
219
+ ```
220
+
221
+ **Market Cap Presets (Low / Medium / High):**
222
+ ```typescript
223
+ import { MulticurveBuilder, FEE_TIERS } from '@whetstone-research/doppler-sdk'
224
+ import { parseEther } from 'viem'
225
+ import { base } from 'viem/chains'
226
+
227
+ const presetParams = new MulticurveBuilder(base.id)
228
+ .tokenConfig({ name: 'Preset Launch', symbol: 'PRST', tokenURI: 'ipfs://preset.json' })
229
+ .saleConfig({ initialSupply: parseEther('1000000'), numTokensToSell: parseEther('900000'), numeraire: '0x...' })
230
+ .withMarketCapPresets({
231
+ fee: FEE_TIERS.LOW, // defaults to 0.05% fee tier (tick spacing 10)
232
+ presets: ['low', 'medium', 'high'], // defaults to all tiers
233
+ // overrides: { high: { shares: parseEther('0.25') } }, // optional per-tier tweaks
234
+ })
235
+ .withGovernance({ type: 'default' })
236
+ .withMigration({ type: 'uniswapV2' })
237
+ .withUserAddress('0x...')
238
+ .build()
239
+
240
+ const presetResult = await sdk.factory.createMulticurve(presetParams)
241
+ console.log('Pool address:', presetResult.poolAddress)
242
+ console.log('Token address:', presetResult.tokenAddress)
243
+ ```
244
+
245
+ The preset helper seeds three curated curve buckets sized for ~1B token supply targets:
246
+ - `low`: ~5% of the sale allocated to a $7.5k-$30k market cap window.
247
+ - `medium`: ~12.5% targeting roughly $50k-$150k market caps.
248
+ - `high`: ~20% aimed at $250k-$750k market caps.
249
+
250
+ Pass `presets` to pick a subset (e.g. `['medium', 'high']`) or provide `overrides` to adjust ticks, positions, or shares for a specific tier. When the selected presets sum to less than 100%, the builder automatically appends a filler curve (using the highest selected tier's shape) so liquidity always covers the full sale. Shares must stay within 0-1e18 and the helper will throw if the total ever exceeds 100%.
251
+
252
+ **Scheduled Multicurve Launch:**
253
+ ```typescript
254
+ import { MulticurveBuilder } from '@whetstone-research/doppler-sdk'
255
+ import { parseEther } from 'viem'
256
+ import { base } from 'viem/chains'
257
+
258
+ const startTime = Math.floor(Date.now() / 1000) + 3600 // one hour from now
259
+
260
+ const scheduled = new MulticurveBuilder(base.id)
261
+ .tokenConfig({ name: 'My Token', symbol: 'MTK', tokenURI: 'ipfs://scheduled.json' })
262
+ .saleConfig({ initialSupply: parseEther('1000000'), numTokensToSell: parseEther('900000'), numeraire: '0x4200000000000000000000000000000000000006' })
263
+ .poolConfig({
264
+ fee: 0,
265
+ tickSpacing: 8,
266
+ curves: [
267
+ { tickLower: 0, tickUpper: 240000, numPositions: 12, shares: parseEther('0.5') },
268
+ { tickLower: 16000, tickUpper: 240000, numPositions: 12, shares: parseEther('0.5') },
269
+ ],
270
+ })
271
+ .withSchedule({ startTime })
272
+ .withGovernance({ type: 'default' })
273
+ .withMigration({ type: 'uniswapV2' })
274
+ .withUserAddress('0x...')
275
+ .build()
276
+
277
+ const scheduledResult = await sdk.factory.createMulticurve(scheduled)
278
+ console.log('Pool address:', scheduledResult.poolAddress)
279
+ console.log('Token address:', scheduledResult.tokenAddress)
280
+ ```
281
+
282
+ Ensure the target chain has the scheduled multicurve initializer whitelisted. If you are targeting a custom deployment, override it via `.withV4ScheduledMulticurveInitializer('0x...')`.
283
+
284
+ **Multicurve with Lockable Beneficiaries (NoOp Migration):**
285
+
286
+ When you want fee revenue to flow to specific addresses without migrating liquidity after the auction, use lockable beneficiaries with NoOp migration:
287
+
288
+ ```typescript
289
+ import { WAD } from '@whetstone-research/doppler-sdk'
290
+
291
+ // Define beneficiaries with shares that sum to WAD (1e18 = 100%)
292
+ // IMPORTANT: Protocol owner must be included with at least 5% shares
293
+ const lockableBeneficiaries = [
294
+ { beneficiary: '0xProtocolOwner...', shares: WAD / 10n }, // 10% to protocol (>= 5% required)
295
+ { beneficiary: '0xYourAddress...', shares: (WAD * 4n) / 10n }, // 40%
296
+ { beneficiary: '0xOtherAddress...', shares: WAD / 2n }, // 50%
297
+ ]
298
+
299
+ const params = new MulticurveBuilder(base.id)
300
+ .tokenConfig({ name: 'My Token', symbol: 'MTK', tokenURI: 'https://example.com/metadata.json' })
301
+ .saleConfig({ initialSupply: parseEther('1000000'), numTokensToSell: parseEther('900000'), numeraire: '0x...' })
302
+ .poolConfig({
303
+ fee: 3000, // 0.3% fee tier - set > 0 to accumulate fees for beneficiaries
304
+ tickSpacing: 8,
305
+ curves: [
306
+ { tickLower: 0, tickUpper: 240000, numPositions: 10, shares: parseEther('0.5') },
307
+ { tickLower: 16000, tickUpper: 240000, numPositions: 10, shares: parseEther('0.5') },
308
+ ],
309
+ beneficiaries: lockableBeneficiaries, // Add beneficiaries for fee streaming
310
+ })
311
+ .withGovernance({ type: 'default' })
312
+ .withMigration({ type: 'noOp' }) // Use NoOp migration with lockable beneficiaries
313
+ .withUserAddress('0x...')
314
+ .build()
315
+
316
+ const result = await sdk.factory.createMulticurve(params)
317
+ const assetAddress = result.tokenAddress // SAVE THIS - you'll need it to collect fees!
318
+ console.log('Asset address:', assetAddress)
319
+
320
+ // Later, to collect fees (works before and after migration):
321
+ // const pool = await sdk.getMulticurvePool(assetAddress)
322
+ // await pool.collectFees()
323
+ ```
324
+
325
+ **Important Notes:**
326
+ - Set `fee` > 0 (e.g., 3000 for 0.3%) to accumulate trading fees for beneficiaries
327
+ - **Save the asset address** (token address) returned from creation - you need it to collect fees later
328
+ - Beneficiaries receive fees proportional to their shares when `collectFees()` is called
329
+ - Pool enters "Locked" status (status = 2) and liquidity cannot be migrated
330
+ - Beneficiaries are immutable and set at pool creation time
331
+ - The SDK automatically handles PoolKey construction and PoolId computation for you
332
+
333
+ See [examples/multicurve-lockable-beneficiaries.ts](./examples/multicurve-lockable-beneficiaries.ts) for a complete example.
334
+
335
+ #### Transaction gas override
336
+ - You can pass a gas limit to factory create calls via the `gas` field on `CreateStaticAuctionParams` / `CreateDynamicAuctionParams` / `CreateMulticurveParams`.
337
+ - If omitted, the SDK uses the simulation's gas estimate when available, falling back to 13,500,000 gas for the `create()` transaction.
338
+ - `simulateCreate*` helpers now return `gasEstimate` so you can tune overrides before sending.
339
+ - Builders expose `.withGasLimit(gas: bigint)` so you can set overrides fluently.
340
+
341
+
342
+
119
343
  ### Builder Pattern (Recommended)
120
344
 
121
345
  Prefer using the builders to construct `CreateStaticAuctionParams` and `CreateDynamicAuctionParams` fluently and safely. Builders apply sensible defaults and can compute ticks and gamma for you.
@@ -222,6 +446,65 @@ const hasEndedEarly = await auction.hasEndedEarly();
222
446
  const currentEpoch = await auction.getCurrentEpoch();
223
447
  ```
224
448
 
449
+ ### Multicurve Pool Interactions
450
+
451
+ Multicurve pools support fee collection and distribution to beneficiaries when configured with `lockableBeneficiaries`.
452
+
453
+ ```typescript
454
+ // Get a multicurve pool instance using the asset address (token address)
455
+ const pool = await sdk.getMulticurvePool(assetAddress);
456
+
457
+ // Get pool state
458
+ const state = await pool.getState();
459
+ console.log('Asset:', state.asset);
460
+ console.log('Numeraire:', state.numeraire);
461
+ console.log('Fee tier:', state.fee);
462
+ console.log('Tick spacing:', state.tickSpacing);
463
+ console.log('Hook address:', state.poolKey.hooks);
464
+ console.log('Far tick threshold:', state.farTick);
465
+ console.log('Pool status:', state.status); // 0=Uninitialized, 1=Initialized, 2=Locked, 3=Exited
466
+
467
+ // Collect and distribute fees to beneficiaries
468
+ // This can be called by anyone, but only beneficiaries receive fees
469
+ const { fees0, fees1, transactionHash } = await pool.collectFees();
470
+ console.log('Fees collected (token0):', fees0);
471
+ console.log('Fees collected (token1):', fees1);
472
+ console.log('Transaction:', transactionHash);
473
+
474
+ // Get token addresses
475
+ const tokenAddress = await pool.getTokenAddress();
476
+ const numeraireAddress = await pool.getNumeraireAddress();
477
+ ```
478
+
479
+ **Fee Collection Technical Details:**
480
+
481
+ The SDK handles the complexity of fee collection by:
482
+ 1. **Retrieving pool configuration** from the multicurve initializer contract
483
+ 2. **Detecting migration status** and, if the pool has migrated, resolving the shared `StreamableFeesLockerV2`
484
+ address via the multicurve migrator (no manual lookup required)
485
+ 3. **Computing the PoolId** from the PoolKey using `keccak256(abi.encode(poolKey))`
486
+ 4. **Calling the correct contract** (initializer while locked, locker after migration) with the computed PoolId
487
+ 5. **Distributing fees** proportionally to all configured beneficiaries
488
+
489
+ **Important Notes:**
490
+ - Fees accumulate from swap activity on the pool (only if fee tier > 0)
491
+ - Anyone can call `collectFees()`, but fees are distributed to beneficiaries only
492
+ - Fees are automatically split according to configured beneficiary shares
493
+ - The function returns the total amount collected for both tokens in the pair
494
+ - Works exclusively with pools created using `lockableBeneficiaries` in the multicurve configuration
495
+ - Pools in "Locked" status (status = 2) use the multicurve initializer for collection
496
+ - Pools in "Exited" status (status = 3) automatically stream fees through `StreamableFeesLockerV2`; the SDK
497
+ resolves the locker address and stream data for you
498
+ - Beneficiaries must be configured at pool creation time and cannot be changed
499
+
500
+ **Common Use Cases:**
501
+ - Set up periodic fee collection (e.g., daily or weekly)
502
+ - Integrate with a bot that automatically collects fees when threshold is reached
503
+ - Allow any beneficiary to trigger collection after significant trading activity
504
+ - Monitor swap events to determine optimal collection timing
505
+
506
+ See [examples/multicurve-collect-fees.ts](./examples/multicurve-collect-fees.ts) for a complete example.
507
+
225
508
  ## Token Management
226
509
 
227
510
  ### DERC20 Tokens
@@ -229,9 +512,8 @@ const currentEpoch = await auction.getCurrentEpoch();
229
512
  The SDK includes full support for DERC20 tokens with vesting functionality:
230
513
 
231
514
  ```typescript
232
- import { Derc20 } from '@whetstone-research/doppler-sdk';
233
-
234
- const token = new Derc20(publicClient, walletClient, tokenAddress);
515
+ // Get a DERC20 instance from the SDK (uses its clients)
516
+ const token = sdk.getDerc20(tokenAddress);
235
517
 
236
518
  // Read token information
237
519
  const name = await token.getName();
@@ -243,10 +525,100 @@ const vestingData = await token.getVestingData(address);
243
525
  console.log('Total vested:', vestingData.totalAmount);
244
526
  console.log('Released:', vestingData.releasedAmount);
245
527
 
246
- // Release vested tokens
247
- await token.release(amountToRelease);
528
+ // Release currently available vested tokens
529
+ await token.release();
530
+ ```
531
+
532
+ Alternatively, you can instantiate directly if needed:
533
+ ```typescript
534
+ import { Derc20 } from '@whetstone-research/doppler-sdk'
535
+ const tokenDirect = new Derc20(publicClient, walletClient, tokenAddress)
536
+ ```
537
+
538
+ ### Governance Delegation (ERC20Votes)
539
+
540
+ DERC20 extends OpenZeppelin's ERC20Votes. Voting power is tracked via checkpoints and only updates once an address delegates voting power (typically to itself). The SDK exposes simple read/write helpers for delegation.
541
+
542
+ Basics:
543
+ ```ts
544
+ import { Derc20 } from '@whetstone-research/doppler-sdk'
545
+
546
+ const token = sdk.getDerc20(tokenAddress)
547
+
548
+ // Read: who an account delegates to, and current voting power
549
+ const currentDelegate = await token.getDelegates(userAddress)
550
+ const votes = await token.getVotes(userAddress)
551
+
552
+ // Self‑delegate to activate vote tracking
553
+ await token.delegate(userAddress)
554
+
555
+ // Or delegate to another address
556
+ await token.delegate('0xDelegatee...')
557
+ ```
558
+
559
+ Historical votes:
560
+ ```ts
561
+ // OZ v5 uses timepoints (block numbers for block‑based clocks)
562
+ const blockNumber = await publicClient.getBlockNumber()
563
+ const pastVotes = await token.getPastVotes(userAddress, blockNumber - 1n)
248
564
  ```
249
565
 
566
+ Signature‑based delegation (delegateBySig):
567
+ ```ts
568
+ // Signs an EIP‑712 message and submits a transaction calling delegateBySig
569
+ // Note: This still submits a transaction from the connected wallet.
570
+ const expiry = BigInt(Math.floor(Date.now() / 1000) + 3600) // 1h
571
+ await token.delegateBySig('0xDelegatee...', expiry)
572
+ ```
573
+
574
+ Advanced: gasless delegation via relayer
575
+ - The token supports `delegateBySig(delegatee, nonce, expiry, v, r, s)`. A relayer can submit this on behalf of the user if it holds ETH for gas.
576
+ - To do this, have the user sign typed data, then send the signature to your backend that calls the contract.
577
+
578
+ Client (sign only):
579
+ ```ts
580
+ const [nonce, name] = await Promise.all([
581
+ publicClient.readContract({ address: tokenAddress, abi: derc20Abi, functionName: 'nonces', args: [userAddress] }),
582
+ token.getName(),
583
+ ])
584
+ const chainId = await publicClient.getChainId()
585
+ const domain = { name, version: '1', chainId, verifyingContract: tokenAddress } as const
586
+ const types = { Delegation: [
587
+ { name: 'delegatee', type: 'address' },
588
+ { name: 'nonce', type: 'uint256' },
589
+ { name: 'expiry', type: 'uint256' },
590
+ ] } as const
591
+ const message = { delegatee: '0xDelegatee...', nonce, expiry } as const
592
+
593
+ const signature = await walletClient.signTypedData({
594
+ domain, types, primaryType: 'Delegation', message, account: userAddress,
595
+ })
596
+ // POST { signature, delegatee, nonce, expiry } to your relayer
597
+ ```
598
+
599
+ Relayer (submit tx):
600
+ ```ts
601
+ function splitSig(sig: `0x${string}`) {
602
+ const r = `0x${sig.slice(2, 66)}` as `0x${string}`
603
+ const s = `0x${sig.slice(66, 130)}` as `0x${string}`
604
+ let v = parseInt(sig.slice(130, 132), 16); if (v < 27) v += 27
605
+ return { v, r, s }
606
+ }
607
+
608
+ const { v, r, s } = splitSig(signature)
609
+ await relayerWallet.writeContract({
610
+ address: tokenAddress,
611
+ abi: derc20Abi,
612
+ functionName: 'delegateBySig',
613
+ args: ['0xDelegatee...', nonce, expiry, v, r, s],
614
+ })
615
+ ```
616
+
617
+ Notes
618
+ - Users must delegate (even to themselves) before votes appear in `getVotes`.
619
+ - `getPastVotes`/`getPastTotalSupply` expect a timepoint; for block‑based clocks, pass a block number that has already been mined.
620
+ - Events you may track: `DelegateChanged` and `DelegateVotesChanged` for live updates.
621
+
250
622
  ### Native ETH
251
623
 
252
624
  The SDK also provides an ETH wrapper with ERC20-like interface:
@@ -278,6 +650,47 @@ console.log('Expected output:', quote.amountOut);
278
650
  console.log('Price after swap:', quote.sqrtPriceX96After);
279
651
  ```
280
652
 
653
+ ## Atomic Create + Pre‑Buy (Bundle)
654
+
655
+ For static auctions, you can create the pool and execute a pre‑buy in a single transaction via the Bundler.
656
+
657
+ High‑level flow:
658
+ - Simulate create to get `CreateParams` and the predicted token address
659
+ - Decide `amountOut` to buy, simulate `amountIn` with `simulateBundleExactOutput(...)`
660
+ - Build Universal Router commands (e.g., via `doppler-router`)
661
+ - Call `factory.bundle(createParams, commands, inputs, { value })`
662
+
663
+ See docs/quotes-and-swaps.md for a full example.
664
+
665
+ ### Multicurve Bundler Helpers
666
+
667
+ Multicurve auctions expose similar helpers that work with the Doppler Bundler once it has been upgraded
668
+ with multicurve support (selector check added in `0.0.1-alpha.47`). The SDK now verifies the bundler bytecode
669
+ before attempting these flows; if you see
670
+ `Bundler at <address> does not support multicurve bundling`, deploy or point at the latest bundler release.
671
+
672
+ ```ts
673
+ // Prepare multicurve CreateParams up front
674
+ const createParams = sdk.factory.encodeCreateMulticurveParams(multicurveConfig)
675
+
676
+ // Quote an exact-out bundle
677
+ const exactOutQuote = await sdk.factory.simulateMulticurveBundleExactOut(createParams, {
678
+ exactAmountOut: parseEther('100'),
679
+ })
680
+
681
+ // Quote an exact-in bundle
682
+ const exactInQuote = await sdk.factory.simulateMulticurveBundleExactIn(createParams, {
683
+ exactAmountIn: parseEther('25'),
684
+ })
685
+
686
+ console.log('Predicted asset:', exactOutQuote.asset)
687
+ console.log('PoolKey:', exactOutQuote.poolKey)
688
+ console.log('Input required:', exactOutQuote.amountIn)
689
+ ```
690
+
691
+ The multicurve helpers automatically normalise the returned PoolKey to maintain canonical token ordering and
692
+ hash the result when collecting fees, so consumers no longer need to manually assemble the PoolId.
693
+
281
694
  ## Migration Configuration
282
695
 
283
696
  The SDK supports flexible migration paths after auction completion:
@@ -307,18 +720,74 @@ migration: {
307
720
  streamableFees: {
308
721
  lockDuration: 365 * 24 * 60 * 60, // 1 year
309
722
  beneficiaries: [
310
- { address: '0x...', percentage: 10000 }, // 100%
723
+ { beneficiary: '0x...', shares: parseEther('1') }, // 100%
311
724
  ],
312
725
  },
313
726
  }
314
727
  ```
315
728
 
729
+ To make configuring the first beneficiary simpler, the SDK now exposes helpers for resolving the
730
+ airlock owner and creating the default 5% entry:
731
+
732
+ ```ts
733
+ import { DopplerSDK, createAirlockBeneficiary, getAirlockOwner } from '@whetstone-research/doppler-sdk'
734
+ import { parseEther } from 'viem'
735
+
736
+ const sdk = new DopplerSDK({ publicClient, chainId })
737
+
738
+ // Get the owner and construct the beneficiary entry (5% by default)
739
+ const airlockBeneficiary = await sdk.getAirlockBeneficiary()
740
+
741
+ // Or build the entry manually if you do not have an SDK instance handy
742
+ // (airlockEntry will be equivalent to airlockBeneficiary above)
743
+ const owner = await getAirlockOwner(publicClient)
744
+ const airlockEntry = createAirlockBeneficiary(owner) // defaults to 5% shares
745
+
746
+ const migration = {
747
+ type: 'uniswapV4' as const,
748
+ fee: 3000,
749
+ tickSpacing: 60,
750
+ streamableFees: {
751
+ lockDuration: 365 * 24 * 60 * 60,
752
+ beneficiaries: [
753
+ airlockEntry, // or airlockBeneficiary (5%)
754
+ { beneficiary: '0xYourDAO...', shares: parseEther('0.95') }, // 95%
755
+ ],
756
+ },
757
+ }
758
+ ```
759
+
760
+
761
+
316
762
  ## Supported Chains
317
763
 
318
- The SDK currently supports:
319
- - Base (8453)
320
- - Unichain (1301)
321
- - Ink Sepolia (763373)
764
+ The SDK exposes runtime constants and TypeScript types for supported chains:
765
+
766
+ ```ts
767
+ import {
768
+ CHAIN_IDS,
769
+ SUPPORTED_CHAIN_IDS,
770
+ getAddresses,
771
+ isSupportedChainId,
772
+ type SupportedChainId,
773
+ type ChainAddresses,
774
+ } from '@whetstone-research/doppler-sdk'
775
+
776
+ // Validate and narrow a chain ID
777
+ function ensureSupported(id: number): SupportedChainId {
778
+ if (!isSupportedChainId(id)) throw new Error('Unsupported chain')
779
+ return id
780
+ }
781
+
782
+ const chainId = ensureSupported(CHAIN_IDS.BASE)
783
+ const addresses: ChainAddresses = getAddresses(chainId)
784
+ console.log('Airlock for Base:', addresses.airlock)
785
+
786
+ // Iterate supported chains
787
+ for (const id of SUPPORTED_CHAIN_IDS) {
788
+ console.log('Supported chain id:', id)
789
+ }
790
+ ```
322
791
 
323
792
  ## Advanced Usage
324
793
 
@@ -334,18 +803,221 @@ vesting: {
334
803
  }
335
804
  ```
336
805
 
337
- ### Hook Address Mining (V4)
806
+ ### Vanity Address Mining
338
807
 
339
- For optimal gas efficiency with Uniswap V4, you can mine hook addresses:
808
+ The Doppler protocol uses CREATE2 for deterministic deployments, enabling you to find vanity addresses for both tokens and hooks before submitting transactions. The SDK provides a `mineTokenAddress` utility that mirrors on-chain calculations.
809
+
810
+ #### Mining Token Addresses (Static Auctions)
811
+
812
+ For static auctions (V3 pools), you can mine vanity token addresses:
340
813
 
341
814
  ```typescript
342
- // This feature is coming soon
343
- const minedAddress = await sdk.mineHookAddress({
344
- prefix: '0x00', // Target prefix for gas optimization
345
- deployer: '0x...', // Doppler deployer address
346
- });
815
+ import {
816
+ StaticAuctionBuilder,
817
+ mineTokenAddress,
818
+ getAddresses,
819
+ } from '@whetstone-research/doppler-sdk'
820
+ import { parseEther } from 'viem'
821
+ import { base } from 'viem/chains'
822
+
823
+ const builder = new StaticAuctionBuilder(base.id)
824
+ .tokenConfig({ name: 'Vanity Token', symbol: 'VNY', tokenURI: 'https://example.com/token.json' })
825
+ .saleConfig({
826
+ initialSupply: parseEther('1000000'),
827
+ numTokensToSell: parseEther('750000'),
828
+ numeraire: '0x...',
829
+ })
830
+ .poolByTicks({ startTick: -92100, endTick: -69060, fee: 3000 })
831
+ .withGovernance({ type: 'default' })
832
+ .withMigration({ type: 'uniswapV3', fee: 3000, tickSpacing: 60 })
833
+ .withUserAddress('0x...')
834
+
835
+ const staticParams = builder.build()
836
+ // Fetch the encoded create() payload without sending the transaction
837
+ const createParams = await sdk.factory.encodeCreateStaticAuctionParams(staticParams)
838
+ const addresses = getAddresses(base.id)
839
+
840
+ const { salt, tokenAddress, iterations } = mineTokenAddress({
841
+ prefix: 'dead', // omit 0x prefix
842
+ tokenFactory: createParams.tokenFactory,
843
+ initialSupply: createParams.initialSupply,
844
+ recipient: addresses.airlock,
845
+ owner: addresses.airlock,
846
+ tokenData: createParams.tokenFactoryData,
847
+ maxIterations: 1_000_000, // optional safety cap
848
+ })
849
+
850
+ console.log(`Vanity token ${tokenAddress} found after ${iterations} iterations`)
851
+ // Now submit airlock.create({ ...createParams, salt }) when ready to deploy
347
852
  ```
348
853
 
854
+ #### Mining Hook and Token Addresses (Dynamic Auctions)
855
+
856
+ For dynamic auctions (V4 pools), you can mine both hook and token addresses simultaneously. The miner ensures proper Uniswap V4 hook flags and correct token ordering relative to the numeraire:
857
+
858
+ ```typescript
859
+ import {
860
+ DynamicAuctionBuilder,
861
+ mineTokenAddress,
862
+ getAddresses,
863
+ DopplerBytecode,
864
+ DAY_SECONDS,
865
+ } from '@whetstone-research/doppler-sdk'
866
+ import { parseEther, keccak256, encodePacked, encodeAbiParameters } from 'viem'
867
+ import { base } from 'viem/chains'
868
+
869
+ const builder = new DynamicAuctionBuilder()
870
+ .tokenConfig({ name: 'My Token', symbol: 'MTK', tokenURI: 'https://example.com/token.json' })
871
+ .saleConfig({
872
+ initialSupply: parseEther('1000000'),
873
+ numTokensToSell: parseEther('900000'),
874
+ numeraire: '0x...',
875
+ })
876
+ .poolConfig({ fee: 3000, tickSpacing: 60 })
877
+ .auctionByTicks({
878
+ duration: 7 * DAY_SECONDS,
879
+ epochLength: 3600,
880
+ startTick: -92103,
881
+ endTick: -69080,
882
+ minProceeds: parseEther('100'),
883
+ maxProceeds: parseEther('1000'),
884
+ })
885
+ .withMigration({ type: 'uniswapV4', fee: 3000, tickSpacing: 60 })
886
+ .withUserAddress('0x...')
887
+
888
+ const dynamicParams = builder.build()
889
+ const { createParams } = await sdk.factory.encodeCreateDynamicAuctionParams(dynamicParams)
890
+ const addresses = getAddresses(base.id)
891
+
892
+ // Compute hook init code hash (required for hook mining)
893
+ const hookInitHashData = encodeAbiParameters(
894
+ [
895
+ { type: 'address' }, { type: 'uint256' }, { type: 'uint256' },
896
+ { type: 'uint256' }, { type: 'uint256' }, { type: 'uint256' },
897
+ { type: 'int24' }, { type: 'int24' }, { type: 'uint256' },
898
+ { type: 'int24' }, { type: 'bool' }, { type: 'uint256' },
899
+ { type: 'address' }, { type: 'uint24' },
900
+ ],
901
+ [
902
+ addresses.poolManager,
903
+ dynamicParams.sale.numTokensToSell,
904
+ dynamicParams.auction.minProceeds,
905
+ dynamicParams.auction.maxProceeds,
906
+ /* startingTime, endingTime, startTick, endTick, epochLength, gamma, isToken0, numPDSlugs */
907
+ /* poolInitializer, fee - extract from createParams */
908
+ ]
909
+ )
910
+
911
+ const hookInitHash = keccak256(
912
+ encodePacked(['bytes', 'bytes'], [DopplerBytecode, hookInitHashData])
913
+ )
914
+
915
+ const result = mineTokenAddress({
916
+ prefix: 'cafe', // Token prefix
917
+ tokenFactory: createParams.tokenFactory,
918
+ initialSupply: createParams.initialSupply,
919
+ recipient: addresses.airlock,
920
+ owner: addresses.airlock,
921
+ tokenData: createParams.tokenFactoryData,
922
+ tokenVariant: 'standard', // or 'doppler404'
923
+ maxIterations: 1_000_000,
924
+ // Optional: mine hook address with specific prefix too
925
+ hook: {
926
+ deployer: addresses.dopplerDeployer,
927
+ initCodeHash: hookInitHash,
928
+ prefix: '00', // Hook prefix for gas optimization
929
+ },
930
+ })
931
+
932
+ console.log('Token address:', result.tokenAddress)
933
+ console.log('Hook address:', result.hookAddress) // only if hook config provided
934
+ console.log(`Found after ${result.iterations} iterations`)
935
+ ```
936
+
937
+ #### Mining Token Addresses (Multicurve Auctions)
938
+
939
+ For multicurve auctions, you can mine vanity token addresses by computing the `CreateParams` manually with your mined salt. Unlike static and dynamic auctions, multicurve doesn't automatically mine token addresses:
940
+
941
+ ```typescript
942
+ import {
943
+ MulticurveBuilder,
944
+ mineTokenAddress,
945
+ getAddresses,
946
+ } from '@whetstone-research/doppler-sdk'
947
+ import { parseEther } from 'viem'
948
+ import { base } from 'viem/chains'
949
+
950
+ const builder = new MulticurveBuilder(base.id)
951
+ .tokenConfig({ name: 'Vanity Multicurve', symbol: 'VMC', tokenURI: 'https://example.com/token.json' })
952
+ .saleConfig({
953
+ initialSupply: parseEther('1000000'),
954
+ numTokensToSell: parseEther('900000'),
955
+ numeraire: '0x...',
956
+ })
957
+ .poolConfig({
958
+ fee: 3000,
959
+ tickSpacing: 60,
960
+ curves: [
961
+ { tickLower: 0, tickUpper: 240000, numPositions: 10, shares: parseEther('0.5') },
962
+ { tickLower: 16000, tickUpper: 240000, numPositions: 10, shares: parseEther('0.5') },
963
+ ],
964
+ })
965
+ .withGovernance({ type: 'default' })
966
+ .withMigration({ type: 'uniswapV2' })
967
+ .withUserAddress('0x...')
968
+
969
+ const multicurveParams = builder.build()
970
+ const addresses = getAddresses(base.id)
971
+
972
+ // Get CreateParams without calling create
973
+ const createParams = sdk.factory.encodeCreateMulticurveParams(multicurveParams)
974
+
975
+ // Mine a vanity token address
976
+ const { salt, tokenAddress, iterations } = mineTokenAddress({
977
+ prefix: 'feed',
978
+ tokenFactory: createParams.tokenFactory,
979
+ initialSupply: createParams.initialSupply,
980
+ recipient: addresses.airlock,
981
+ owner: addresses.airlock,
982
+ tokenData: createParams.tokenFactoryData,
983
+ maxIterations: 500_000,
984
+ })
985
+
986
+ console.log(`Vanity token ${tokenAddress} found after ${iterations} iterations`)
987
+
988
+ // Use the mined salt in createParams
989
+ const vanityCreateParams = { ...createParams, salt }
990
+
991
+ // Now submit the transaction manually with the vanity salt
992
+ await publicClient.writeContract({
993
+ address: addresses.airlock,
994
+ abi: airlockAbi,
995
+ functionName: 'create',
996
+ args: [vanityCreateParams],
997
+ account: walletClient.account,
998
+ })
999
+ ```
1000
+
1001
+ **Important**: Since `encodeCreateMulticurveParams` generates a random salt internally, you must construct the final `CreateParams` manually with your mined salt. The high-level `createMulticurve` method will replace any provided salt.
1002
+
1003
+ #### Dual-Prefix Mining
1004
+
1005
+ When you provide both a token prefix AND a hook configuration with its own prefix, the miner will search for a salt that satisfies **both** requirements simultaneously. This is useful for V4 deployments where you want:
1006
+
1007
+ - A vanity token address (e.g., starting with `cafe`)
1008
+ - An optimized hook address (e.g., starting with `00` for gas savings)
1009
+
1010
+ Note: Dual-prefix mining takes significantly longer than single-prefix mining. Consider using shorter prefixes or higher iteration limits.
1011
+
1012
+ #### Mining Notes
1013
+
1014
+ - **Prefix format**: Omit the `0x` prefix (e.g., use `'dead'` not `'0x dead'`)
1015
+ - **Case insensitive**: `'DEAD'`, `'dead'`, and `'DeAd'` are equivalent
1016
+ - **Iteration limit**: Longer prefixes require more iterations. A 4-character hex prefix takes ~65,000 attempts on average.
1017
+ - **Token variants**: Set `tokenVariant: 'doppler404'` for DN404-style tokens
1018
+ - **Salt preservation**: High-level helpers like `createStaticAuction` and `createDynamicAuction` recompute salts internally to ensure proper token ordering. To use a mined salt, call `encodeCreate*Params` and submit the transaction manually via `publicClient.writeContract`
1019
+ - **Hook flags**: The miner automatically ensures V4 hooks have the correct permission flags for Doppler operations
1020
+
349
1021
  ## API Reference
350
1022
 
351
1023
  ### DopplerSDK
@@ -363,6 +1035,8 @@ class DopplerSDK {
363
1035
  // Methods
364
1036
  getStaticAuction(poolAddress: Address): Promise<StaticAuction>
365
1037
  getDynamicAuction(hookAddress: Address): Promise<DynamicAuction>
1038
+ // Multicurve helper
1039
+ buildMulticurveAuction(): MulticurveBuilder
366
1040
  getPoolInfo(poolAddress: Address): Promise<PoolInfo>
367
1041
  getHookInfo(hookAddress: Address): Promise<HookInfo>
368
1042
  }
@@ -376,6 +1050,7 @@ Key types are exported for use in your applications:
376
1050
  import type {
377
1051
  CreateStaticAuctionParams,
378
1052
  CreateDynamicAuctionParams,
1053
+ CreateMulticurveParams,
379
1054
  MigrationConfig,
380
1055
  PoolInfo,
381
1056
  HookInfo,
@@ -392,13 +1067,39 @@ pnpm install
392
1067
  # Build the SDK
393
1068
  pnpm build
394
1069
 
395
- # Run tests
1070
+ # Run all tests
396
1071
  pnpm test
397
1072
 
1073
+ # Run specific test suite
1074
+ pnpm test airlock-whitelisting
1075
+
1076
+ # Run tests in watch mode
1077
+ pnpm test:watch
1078
+
398
1079
  # Development mode with watch
399
1080
  pnpm dev
400
1081
  ```
401
1082
 
1083
+ ### Testing
1084
+
1085
+ The SDK includes comprehensive tests covering:
1086
+
1087
+ - **Airlock Whitelisting**: Verifies that all modules are properly whitelisted on deployed Airlock contracts across all chains
1088
+ - **Multicurve Functionality**: Tests multicurve auction creation and quoting
1089
+ - **Token Address Mining**: Tests for generating optimized token addresses
1090
+
1091
+ See [`test/README.md`](./test/README.md) for detailed testing documentation.
1092
+
1093
+ To run whitelisting tests:
1094
+
1095
+ ```bash
1096
+ # Uses default public RPCs
1097
+ pnpm test airlock-whitelisting
1098
+
1099
+ # Or with Alchemy (faster and more reliable)
1100
+ ALCHEMY_API_KEY=your_key_here pnpm test airlock-whitelisting
1101
+ ```
1102
+
402
1103
  ## Migration from Previous SDKs
403
1104
 
404
1105
  If you're migrating from `doppler-v3-sdk` or `doppler-v4-sdk`, see our [Migration Guide](./docs/migration-guide.md).