@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.
- package/LICENSE +21 -0
- package/README.md +726 -25
- package/dist/DopplerSDK.d.mts +45 -7
- package/dist/DopplerSDK.d.ts +45 -7
- package/dist/DopplerSDK.js +35 -12
- package/dist/DopplerSDK.mjs +34 -11
- package/dist/abis/bytecodes.d.mts +3 -2
- package/dist/abis/bytecodes.d.ts +3 -2
- package/dist/abis/bytecodes.js +9 -6
- package/dist/abis/bytecodes.mjs +1 -2
- package/dist/abis/index.d.mts +1507 -129
- package/dist/abis/index.d.ts +1507 -129
- package/dist/abis/index.js +43 -20
- package/dist/abis/index.mjs +2 -3
- package/dist/addresses.d.mts +16 -3
- package/dist/addresses.d.ts +16 -3
- package/dist/addresses.js +13 -5
- package/dist/addresses.mjs +2 -2
- package/dist/builders/DynamicAuctionBuilder.d.mts +119 -0
- package/dist/builders/DynamicAuctionBuilder.d.ts +119 -0
- package/dist/builders/DynamicAuctionBuilder.js +29 -0
- package/dist/builders/DynamicAuctionBuilder.js.map +1 -0
- package/dist/builders/DynamicAuctionBuilder.mjs +20 -0
- package/dist/builders/DynamicAuctionBuilder.mjs.map +1 -0
- package/dist/builders/MulticurveBuilder.d.mts +132 -0
- package/dist/builders/MulticurveBuilder.d.ts +132 -0
- package/dist/builders/MulticurveBuilder.js +29 -0
- package/dist/builders/MulticurveBuilder.js.map +1 -0
- package/dist/builders/MulticurveBuilder.mjs +20 -0
- package/dist/builders/MulticurveBuilder.mjs.map +1 -0
- package/dist/builders/StaticAuctionBuilder.d.mts +124 -0
- package/dist/builders/StaticAuctionBuilder.d.ts +124 -0
- package/dist/builders/StaticAuctionBuilder.js +29 -0
- package/dist/builders/StaticAuctionBuilder.js.map +1 -0
- package/dist/builders/StaticAuctionBuilder.mjs +20 -0
- package/dist/builders/StaticAuctionBuilder.mjs.map +1 -0
- package/dist/builders/index.d.mts +8 -0
- package/dist/builders/index.d.ts +8 -0
- package/dist/builders/index.js +56 -0
- package/dist/builders/index.js.map +1 -0
- package/dist/builders/index.mjs +23 -0
- package/dist/builders/index.mjs.map +1 -0
- package/dist/builders/shared.d.mts +116 -0
- package/dist/builders/shared.d.ts +116 -0
- package/dist/builders/shared.js +39 -0
- package/dist/builders/shared.js.map +1 -0
- package/dist/builders/shared.mjs +18 -0
- package/dist/builders/shared.mjs.map +1 -0
- package/dist/builders.d.mts +8 -131
- package/dist/builders.d.ts +8 -131
- package/dist/builders.js +44 -5
- package/dist/builders.mjs +22 -3
- package/dist/chunk-3PNCB4W5.js +4 -0
- package/dist/{chunk-KRN3ROUE.js.map → chunk-3PNCB4W5.js.map} +1 -1
- package/dist/chunk-3RK7LRAA.js +282 -0
- package/dist/chunk-3RK7LRAA.js.map +1 -0
- package/dist/chunk-4HM3ERBU.js +13 -0
- package/dist/chunk-4HM3ERBU.js.map +1 -0
- package/dist/{chunk-7W72MFJO.mjs → chunk-4TROGENW.mjs} +5 -4
- package/dist/chunk-4TROGENW.mjs.map +1 -0
- package/dist/chunk-5TL5V6UX.mjs +3 -0
- package/dist/{chunk-AZLFJNTG.mjs.map → chunk-5TL5V6UX.mjs.map} +1 -1
- package/dist/chunk-64AWG57M.mjs +192 -0
- package/dist/chunk-64AWG57M.mjs.map +1 -0
- package/dist/chunk-6KWCHTK3.js +166 -0
- package/dist/chunk-6KWCHTK3.js.map +1 -0
- package/dist/chunk-6OOWOPCX.js +1708 -0
- package/dist/chunk-6OOWOPCX.js.map +1 -0
- package/dist/chunk-7BBRPWQJ.js +257 -0
- package/dist/chunk-7BBRPWQJ.js.map +1 -0
- package/dist/{chunk-FVTIDXYK.mjs → chunk-AKSEBAR7.mjs} +29 -19
- package/dist/chunk-AKSEBAR7.mjs.map +1 -0
- package/dist/chunk-AS64GWBX.js +204 -0
- package/dist/chunk-AS64GWBX.js.map +1 -0
- package/dist/chunk-AULFBXM5.mjs +331 -0
- package/dist/chunk-AULFBXM5.mjs.map +1 -0
- package/dist/chunk-AW3WR2D3.mjs +238 -0
- package/dist/chunk-AW3WR2D3.mjs.map +1 -0
- package/dist/chunk-BIQQ53O2.js +45 -0
- package/dist/chunk-BIQQ53O2.js.map +1 -0
- package/dist/chunk-C6MPV3CY.js +260 -0
- package/dist/chunk-C6MPV3CY.js.map +1 -0
- package/dist/{chunk-AYPP5JEQ.mjs → chunk-CLEQO6GU.mjs} +5 -5
- package/dist/chunk-CLEQO6GU.mjs.map +1 -0
- package/dist/chunk-CVHPLURA.js +147 -0
- package/dist/chunk-CVHPLURA.js.map +1 -0
- package/dist/chunk-D2RBCFNW.mjs +130 -0
- package/dist/chunk-D2RBCFNW.mjs.map +1 -0
- package/dist/chunk-ECD4FV3A.mjs +11 -0
- package/dist/chunk-ECD4FV3A.mjs.map +1 -0
- package/dist/chunk-EDJBZPMW.mjs +255 -0
- package/dist/chunk-EDJBZPMW.mjs.map +1 -0
- package/dist/chunk-FPAI4QYW.mjs +145 -0
- package/dist/chunk-FPAI4QYW.mjs.map +1 -0
- package/dist/chunk-HM25ZMO3.js +18 -0
- package/dist/chunk-HM25ZMO3.js.map +1 -0
- package/dist/chunk-IHC6UYKK.js +4 -0
- package/dist/{chunk-DRBRT57F.js.map → chunk-IHC6UYKK.js.map} +1 -1
- package/dist/{chunk-DMAHXBA5.mjs → chunk-J5BFFL3X.mjs} +87 -47
- package/dist/chunk-J5BFFL3X.mjs.map +1 -0
- package/dist/chunk-JIKAD4YL.js +4 -0
- package/dist/{chunk-KEXKKQVW.js.map → chunk-JIKAD4YL.js.map} +1 -1
- package/dist/{chunk-EFAPDN4J.js → chunk-JWEXGALU.js} +730 -33
- package/dist/chunk-JWEXGALU.js.map +1 -0
- package/dist/{chunk-4K5GBNQV.mjs → chunk-KDT76YQE.mjs} +52 -13
- package/dist/chunk-KDT76YQE.mjs.map +1 -0
- package/dist/chunk-LMQLMMEX.js +317 -0
- package/dist/chunk-LMQLMMEX.js.map +1 -0
- package/dist/{chunk-TOMVBPNZ.js → chunk-LS4TK6SX.js} +9 -4
- package/dist/chunk-LS4TK6SX.js.map +1 -0
- package/dist/chunk-M4WMHD3X.mjs +40 -0
- package/dist/chunk-M4WMHD3X.mjs.map +1 -0
- package/dist/chunk-MCOK3UFR.mjs +280 -0
- package/dist/chunk-MCOK3UFR.mjs.map +1 -0
- package/dist/chunk-MGQSQCFG.js +176 -0
- package/dist/chunk-MGQSQCFG.js.map +1 -0
- package/dist/chunk-MKE3BUL3.mjs +3 -0
- package/dist/{chunk-CYDWEPFL.mjs.map → chunk-MKE3BUL3.mjs.map} +1 -1
- package/dist/chunk-MNJ5OYPE.mjs +17 -0
- package/dist/chunk-MNJ5OYPE.mjs.map +1 -0
- package/dist/chunk-MNXD45J7.mjs +164 -0
- package/dist/chunk-MNXD45J7.mjs.map +1 -0
- package/dist/chunk-NGDPQC5E.js +333 -0
- package/dist/chunk-NGDPQC5E.js.map +1 -0
- package/dist/chunk-NNNCVFOH.mjs +16 -0
- package/dist/chunk-NNNCVFOH.mjs.map +1 -0
- package/dist/chunk-NZ4BJ2IC.mjs +315 -0
- package/dist/chunk-NZ4BJ2IC.mjs.map +1 -0
- package/dist/chunk-OKNM7ODQ.js +29 -0
- package/dist/chunk-OKNM7ODQ.js.map +1 -0
- package/dist/{chunk-DCFHANLR.mjs → chunk-OTG75GVH.mjs} +725 -34
- package/dist/chunk-OTG75GVH.mjs.map +1 -0
- package/dist/chunk-OZ6DGBRL.mjs +25 -0
- package/dist/chunk-OZ6DGBRL.mjs.map +1 -0
- package/dist/chunk-P25HBGP5.mjs +3 -0
- package/dist/chunk-P25HBGP5.mjs.map +1 -0
- package/dist/{chunk-XG7K4R56.js → chunk-P7KLEPVI.js} +52 -12
- package/dist/chunk-P7KLEPVI.js.map +1 -0
- package/dist/{chunk-OPKQMN46.mjs → chunk-PAPXGPJB.mjs} +9 -4
- package/dist/chunk-PAPXGPJB.mjs.map +1 -0
- package/dist/chunk-PCNXJAU5.js +19 -0
- package/dist/chunk-PCNXJAU5.js.map +1 -0
- package/dist/{chunk-5IT5OXQ5.js → chunk-PD6HWEMG.js} +40 -30
- package/dist/chunk-PD6HWEMG.js.map +1 -0
- package/dist/{chunk-ER42VG7H.js → chunk-PH2KXREH.js} +20 -3
- package/dist/chunk-PH2KXREH.js.map +1 -0
- package/dist/chunk-Q5ERW5ZW.mjs +107 -0
- package/dist/chunk-Q5ERW5ZW.mjs.map +1 -0
- package/dist/chunk-Q7YNBSVH.js +28 -0
- package/dist/chunk-Q7YNBSVH.js.map +1 -0
- package/dist/{chunk-T644D54P.mjs → chunk-QKO2FZGN.mjs} +16 -4
- package/dist/chunk-QKO2FZGN.mjs.map +1 -0
- package/dist/{chunk-CIRZKWLL.js → chunk-RVFSRYI5.js} +5 -3
- package/dist/chunk-RVFSRYI5.js.map +1 -0
- package/dist/{chunk-KPBCG4X2.js → chunk-RW37KJ77.js} +11 -11
- package/dist/chunk-RW37KJ77.js.map +1 -0
- package/dist/chunk-SD7BHT2F.mjs +3 -0
- package/dist/chunk-SD7BHT2F.mjs.map +1 -0
- package/dist/chunk-SP5M57BG.mjs +258 -0
- package/dist/chunk-SP5M57BG.mjs.map +1 -0
- package/dist/chunk-TKSHYEYA.mjs +1706 -0
- package/dist/chunk-TKSHYEYA.mjs.map +1 -0
- package/dist/chunk-WTS75RUC.js +4 -0
- package/dist/chunk-WTS75RUC.js.map +1 -0
- package/dist/{chunk-ZRDU6CIB.js → chunk-XRPIGMA2.js} +108 -68
- package/dist/chunk-XRPIGMA2.js.map +1 -0
- package/dist/chunk-XTKSM4QE.js +132 -0
- package/dist/chunk-XTKSM4QE.js.map +1 -0
- package/dist/chunk-XUE3CIJ5.mjs +174 -0
- package/dist/chunk-XUE3CIJ5.mjs.map +1 -0
- package/dist/chunk-YYUOLM6U.js +244 -0
- package/dist/chunk-YYUOLM6U.js.map +1 -0
- package/dist/chunk-ZH44DHVR.mjs +26 -0
- package/dist/chunk-ZH44DHVR.mjs.map +1 -0
- package/dist/chunk-ZPHOOG72.js +112 -0
- package/dist/chunk-ZPHOOG72.js.map +1 -0
- package/dist/constants.d.mts +7 -2
- package/dist/constants.d.ts +7 -2
- package/dist/constants.js +57 -38
- package/dist/constants.mjs +1 -2
- package/dist/deployments.generated.d.mts +2 -0
- package/dist/deployments.generated.d.ts +2 -0
- package/dist/deployments.generated.js +12 -0
- package/dist/deployments.generated.js.map +1 -0
- package/dist/deployments.generated.mjs +3 -0
- package/dist/deployments.generated.mjs.map +1 -0
- package/dist/entities/DopplerFactory.d.mts +139 -11
- package/dist/entities/DopplerFactory.d.ts +139 -11
- package/dist/entities/DopplerFactory.js +17 -7
- package/dist/entities/DopplerFactory.mjs +16 -6
- package/dist/entities/auction/DynamicAuction.d.mts +19 -4
- package/dist/entities/auction/DynamicAuction.d.ts +19 -4
- package/dist/entities/auction/DynamicAuction.js +6 -6
- package/dist/entities/auction/DynamicAuction.mjs +5 -5
- package/dist/entities/auction/MulticurvePool.d.mts +55 -0
- package/dist/entities/auction/MulticurvePool.d.ts +55 -0
- package/dist/entities/auction/MulticurvePool.js +18 -0
- package/dist/entities/auction/MulticurvePool.js.map +1 -0
- package/dist/entities/auction/MulticurvePool.mjs +9 -0
- package/dist/entities/auction/MulticurvePool.mjs.map +1 -0
- package/dist/entities/auction/StaticAuction.d.mts +6 -3
- package/dist/entities/auction/StaticAuction.d.ts +6 -3
- package/dist/entities/auction/StaticAuction.js +6 -6
- package/dist/entities/auction/StaticAuction.mjs +5 -5
- package/dist/entities/auction/index.d.mts +3 -0
- package/dist/entities/auction/index.d.ts +3 -0
- package/dist/entities/auction/index.js +16 -9
- package/dist/entities/auction/index.mjs +10 -7
- package/dist/entities/quoter/Quoter.d.mts +44 -2
- package/dist/entities/quoter/Quoter.d.ts +44 -2
- package/dist/entities/quoter/Quoter.js +6 -6
- package/dist/entities/quoter/Quoter.mjs +5 -5
- package/dist/entities/quoter/index.d.mts +3 -0
- package/dist/entities/quoter/index.d.ts +3 -0
- package/dist/entities/quoter/index.js +6 -6
- package/dist/entities/quoter/index.mjs +5 -5
- package/dist/entities/token/derc20/Derc20.d.mts +33 -7
- package/dist/entities/token/derc20/Derc20.d.ts +33 -7
- package/dist/entities/token/derc20/Derc20.js +4 -5
- package/dist/entities/token/derc20/Derc20.mjs +3 -4
- package/dist/entities/token/derc20/index.d.mts +3 -0
- package/dist/entities/token/derc20/index.d.ts +3 -0
- package/dist/entities/token/derc20/index.js +4 -5
- package/dist/entities/token/derc20/index.mjs +3 -4
- package/dist/entities/token/eth/Eth.d.mts +7 -3
- package/dist/entities/token/eth/Eth.d.ts +7 -3
- package/dist/entities/token/eth/Eth.js +2 -3
- package/dist/entities/token/eth/Eth.mjs +1 -2
- package/dist/entities/token/eth/index.d.mts +3 -0
- package/dist/entities/token/eth/index.d.ts +3 -0
- package/dist/entities/token/eth/index.js +2 -3
- package/dist/entities/token/eth/index.mjs +1 -2
- package/dist/entities/token/index.d.mts +3 -0
- package/dist/entities/token/index.d.ts +3 -0
- package/dist/entities/token/index.js +6 -7
- package/dist/entities/token/index.mjs +4 -5
- package/dist/index.d.mts +18 -6
- package/dist/index.d.ts +18 -6
- package/dist/index.js +305 -140
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +32 -19
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.mts +260 -22
- package/dist/types.d.ts +260 -22
- package/dist/types.js +12 -3
- package/dist/types.mjs +3 -2
- package/dist/utils/airlock.d.mts +11 -0
- package/dist/utils/airlock.d.ts +11 -0
- package/dist/utils/airlock.js +26 -0
- package/dist/utils/airlock.js.map +1 -0
- package/dist/utils/airlock.mjs +5 -0
- package/dist/utils/airlock.mjs.map +1 -0
- package/dist/utils/balanceDelta.d.mts +10 -0
- package/dist/utils/balanceDelta.d.ts +10 -0
- package/dist/utils/balanceDelta.js +12 -0
- package/dist/utils/balanceDelta.js.map +1 -0
- package/dist/utils/balanceDelta.mjs +3 -0
- package/dist/utils/balanceDelta.mjs.map +1 -0
- package/dist/utils/computeOptimalGamma.d.mts +7 -0
- package/dist/utils/computeOptimalGamma.d.ts +7 -0
- package/dist/utils/computeOptimalGamma.js +12 -0
- package/dist/utils/computeOptimalGamma.js.map +1 -0
- package/dist/utils/computeOptimalGamma.mjs +3 -0
- package/dist/utils/computeOptimalGamma.mjs.map +1 -0
- package/dist/utils/index.d.mts +11 -0
- package/dist/utils/index.d.ts +11 -0
- package/dist/utils/index.js +114 -24
- package/dist/utils/index.mjs +14 -4
- package/dist/utils/isToken0Expected.d.mts +13 -0
- package/dist/utils/isToken0Expected.d.ts +13 -0
- package/dist/utils/isToken0Expected.js +12 -0
- package/dist/utils/isToken0Expected.js.map +1 -0
- package/dist/utils/isToken0Expected.mjs +3 -0
- package/dist/utils/isToken0Expected.mjs.map +1 -0
- package/dist/utils/marketCapHelpers.d.mts +309 -0
- package/dist/utils/marketCapHelpers.d.ts +309 -0
- package/dist/utils/marketCapHelpers.js +54 -0
- package/dist/utils/marketCapHelpers.js.map +1 -0
- package/dist/utils/marketCapHelpers.mjs +5 -0
- package/dist/utils/marketCapHelpers.mjs.map +1 -0
- package/dist/utils/poolKey.d.mts +17 -0
- package/dist/utils/poolKey.d.ts +17 -0
- package/dist/utils/poolKey.js +12 -0
- package/dist/utils/poolKey.js.map +1 -0
- package/dist/utils/poolKey.mjs +3 -0
- package/dist/utils/poolKey.mjs.map +1 -0
- package/dist/utils/priceHelpers.d.mts +3 -3
- package/dist/utils/priceHelpers.d.ts +3 -3
- package/dist/utils/priceHelpers.js +10 -11
- package/dist/utils/priceHelpers.mjs +2 -3
- package/dist/utils/tickMath.d.mts +8 -1
- package/dist/utils/tickMath.d.ts +8 -1
- package/dist/utils/tickMath.js +17 -14
- package/dist/utils/tickMath.mjs +1 -2
- package/dist/utils/tokenAddressMiner.d.mts +30 -0
- package/dist/utils/tokenAddressMiner.d.ts +30 -0
- package/dist/utils/tokenAddressMiner.js +14 -0
- package/dist/utils/tokenAddressMiner.js.map +1 -0
- package/dist/utils/tokenAddressMiner.mjs +5 -0
- package/dist/utils/tokenAddressMiner.mjs.map +1 -0
- package/package.json +14 -11
- package/dist/__tests__/mocks/addresses.d.mts +0 -46
- package/dist/__tests__/mocks/addresses.d.ts +0 -46
- package/dist/__tests__/mocks/addresses.js +0 -53
- package/dist/__tests__/mocks/addresses.js.map +0 -1
- package/dist/__tests__/mocks/addresses.mjs +0 -44
- package/dist/__tests__/mocks/addresses.mjs.map +0 -1
- package/dist/__tests__/mocks/clients.d.mts +0 -22
- package/dist/__tests__/mocks/clients.d.ts +0 -22
- package/dist/__tests__/mocks/clients.js +0 -17036
- package/dist/__tests__/mocks/clients.js.map +0 -1
- package/dist/__tests__/mocks/clients.mjs +0 -17032
- package/dist/__tests__/mocks/clients.mjs.map +0 -1
- package/dist/chunk-2N5JZSZ4.js +0 -14
- package/dist/chunk-2N5JZSZ4.js.map +0 -1
- package/dist/chunk-3OZRDL3O.js +0 -162
- package/dist/chunk-3OZRDL3O.js.map +0 -1
- package/dist/chunk-4K5GBNQV.mjs.map +0 -1
- package/dist/chunk-5IT5OXQ5.js.map +0 -1
- package/dist/chunk-7F5IXZLH.js +0 -308
- package/dist/chunk-7F5IXZLH.js.map +0 -1
- package/dist/chunk-7VP5VR7J.js +0 -82
- package/dist/chunk-7VP5VR7J.js.map +0 -1
- package/dist/chunk-7W72MFJO.mjs.map +0 -1
- package/dist/chunk-AYPP5JEQ.mjs.map +0 -1
- package/dist/chunk-AZLFJNTG.mjs +0 -3
- package/dist/chunk-CIRZKWLL.js.map +0 -1
- package/dist/chunk-CYDWEPFL.mjs +0 -3
- package/dist/chunk-DCFHANLR.mjs.map +0 -1
- package/dist/chunk-DMAHXBA5.mjs.map +0 -1
- package/dist/chunk-DRBRT57F.js +0 -4
- package/dist/chunk-EFAPDN4J.js.map +0 -1
- package/dist/chunk-ER42VG7H.js.map +0 -1
- package/dist/chunk-FVTIDXYK.mjs.map +0 -1
- package/dist/chunk-IHBIBFZK.mjs +0 -12
- package/dist/chunk-IHBIBFZK.mjs.map +0 -1
- package/dist/chunk-IXSKPEHB.mjs +0 -160
- package/dist/chunk-IXSKPEHB.mjs.map +0 -1
- package/dist/chunk-KEXKKQVW.js +0 -42
- package/dist/chunk-KFD6U3LQ.mjs +0 -305
- package/dist/chunk-KFD6U3LQ.mjs.map +0 -1
- package/dist/chunk-KPBCG4X2.js.map +0 -1
- package/dist/chunk-KRN3ROUE.js +0 -4
- package/dist/chunk-KT7U37XS.mjs +0 -207
- package/dist/chunk-KT7U37XS.mjs.map +0 -1
- package/dist/chunk-LOROXNH3.mjs +0 -37
- package/dist/chunk-LOROXNH3.mjs.map +0 -1
- package/dist/chunk-O6GYIJ6X.mjs +0 -80
- package/dist/chunk-O6GYIJ6X.mjs.map +0 -1
- package/dist/chunk-OPKQMN46.mjs.map +0 -1
- package/dist/chunk-RIMM47JL.mjs +0 -176
- package/dist/chunk-RIMM47JL.mjs.map +0 -1
- package/dist/chunk-SUOMK3CU.js +0 -872
- package/dist/chunk-SUOMK3CU.js.map +0 -1
- package/dist/chunk-T644D54P.mjs.map +0 -1
- package/dist/chunk-TOMVBPNZ.js.map +0 -1
- package/dist/chunk-XEMZQHTX.mjs +0 -870
- package/dist/chunk-XEMZQHTX.mjs.map +0 -1
- package/dist/chunk-XG7K4R56.js.map +0 -1
- package/dist/chunk-XQ2VMR26.js +0 -180
- package/dist/chunk-XQ2VMR26.js.map +0 -1
- package/dist/chunk-ZAIP54LX.js +0 -209
- package/dist/chunk-ZAIP54LX.js.map +0 -1
- package/dist/chunk-ZRDU6CIB.js.map +0 -1
- package/dist/magic-string.es-CBLXTCZP.js +0 -1304
- package/dist/magic-string.es-CBLXTCZP.js.map +0 -1
- package/dist/magic-string.es-QHA47FSB.mjs +0 -1298
- 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: -
|
|
68
|
-
.withVesting({
|
|
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
|
-
|
|
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({
|
|
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
|
-
{
|
|
107
|
-
{
|
|
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
|
-
|
|
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(
|
|
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
|
-
{
|
|
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
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
-
###
|
|
806
|
+
### Vanity Address Mining
|
|
338
807
|
|
|
339
|
-
|
|
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
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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).
|