@whetstone-research/doppler-sdk 1.0.25 → 1.0.27

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/dist/evm/index.js CHANGED
@@ -122,6 +122,33 @@ var GENERATED_DOPPLER_DEPLOYMENTS = {
122
122
  NoOpGovernanceFactory: "0xddAE8B3eD08184682f7Bc32B74d943cEEfEab638",
123
123
  NoOpMigrator: "0x233A71A7bB928b1357A1Ebf454298320989Ca5B5"
124
124
  },
125
+ "4663": {
126
+ Airlock: "0xeb7C034704eF8Dcd2D32324c1545f62fB4aD0862",
127
+ Bundler: "0xEdE0B5fae363232c396724Fa962250Fa197cc5a1",
128
+ DN404Factory: "0x37A9Fa204a4d3A429FDED7e3469ab076C854Bc9d",
129
+ DopplerCreateXDeployer: "0x103004E50Bed65DFBa30dD9c264B6BdF5e529B83",
130
+ DopplerDeployer: "0x4389AD34938B14F25cff7ED983c53f5a42A2573f",
131
+ DopplerERC20V1: "0x3Be8B97Fd0e713B5aBE0649Fa830223B6B4BC599",
132
+ DopplerERC20V1Factory: "0x1B37D3a72082029c44B35B604Ea473617580b69a",
133
+ DopplerHookInitializer: "0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544",
134
+ DopplerHookMigrator: "0x7BF319d8e969f7596B1Bc171Da9ce322f67Ae0c4",
135
+ DopplerLensQuoter: "0xf4c22465532f64777FfcD7770831AEca38F35c04",
136
+ GovernanceFactory: "0xDeb0447DAE3EB177c4dbA8bBCCCa25c8F273B7ef",
137
+ LaunchpadGovernanceFactory: "0xdb036746D65DD52126b1915f1AdF555e6C5237Cf",
138
+ LockableUniswapV3Initializer: "0xde8886A0019Ea060B8378Ee37b8A23b8117F29A3",
139
+ NoOpGovernanceFactory: "0x85f37f74Ef2478A770318bc810177a9835911aD7",
140
+ NoOpMigrator: "0xba2F330EDb16cD8056f5988d8CE19BbC63475A0e",
141
+ Quoter: "0x7232686FC954f12079cadFC5e9F755a9fEAeb3Ca",
142
+ RehypeDopplerHookInitializer: "0x6f02324d20CC679d0E585290CAa6b16baCbC0F77",
143
+ RehypeDopplerHookMigrator: "0x1a0f286bB7f5967AE89c13D3425D5ce04C34cd27",
144
+ StreamableFeesLockerV2: "0x7B6147AC3F615bdb764e7EbD5f517dac1AD163B8",
145
+ SwapRestrictorDopplerHook: "0xC16c826F75338A5Ea626f94f8992191B4ce5abA2",
146
+ TimelockFactory: "0x6076fdDFCaC0dD980e0350dfF5239feC3f86C578",
147
+ TopUpDistributor: "0x46adee7595d48b1Ec53090e9bc78e1E69Fa0eF06",
148
+ UniswapV2Locker: "0x63f6Efe03F25A8C6650b38d05C5a454051d642a5",
149
+ UniswapV2MigratorSplit: "0xB05046cEa797c993FB5b583098B1c4682e9Da333",
150
+ UniswapV4Initializer: "0x6cce158B6D1747617fc218592B4D60B239B957ea"
151
+ },
125
152
  "4801": {
126
153
  Airlock: "0x5F3bA43D44375286296Cb85F1EA2EBfa25dde731",
127
154
  GovernanceFactory: "0x136191B46478cAB023cbC01a36160C4Aad81677a",
@@ -225,6 +252,8 @@ var GENERATED_DOPPLER_DEPLOYMENTS = {
225
252
  CloneERC20VotesFactory: "0x9a497a9fB78e49984B9d260abA1F4AD6321D4D92",
226
253
  DecayMulticurveInitializer: "0xD59cE43E53D69F190E15d9822Fb4540dCcc91178",
227
254
  DecayMulticurveInitializerHook: "0xbB7784A4d481184283Ed89619A3e3ed143e1Adc0",
255
+ DN404Factory: "0x98b0Aa2e0f134dbB3eb157b5646D387E6D55243a",
256
+ DopplerCreateXDeployer: "0x0000000000f13Ab5b685F03A412A26719aB6bE60",
228
257
  DopplerDeployer: "0xb35469ee64A87Afd19B31615094fE3962d73e421",
229
258
  DopplerERC20V1: "0xDB7B520bb5C3a2C5d4871198081911359f93be87",
230
259
  DopplerERC20V1Factory: "0x89C261C05B5F9b6BcBA07C199b8DeE7cFaD45292",
@@ -373,23 +402,23 @@ var DEFAULT_OPENING_DOPPLER_NUM_PD_SLUGS = DEFAULT_PD_SLUGS;
373
402
  var DEFAULT_OPENING_DOPPLER_FEE = FEE_TIERS.HIGH;
374
403
  var DEFAULT_OPENING_DOPPLER_TICK_SPACING = DOPPLER_MAX_TICK_SPACING;
375
404
  var DEFAULT_MULTICURVE_LOWER_TICKS = [
376
- -202100,
377
- -183100,
378
- -167e3
405
+ -887200,
406
+ -222200,
407
+ -176200
379
408
  ];
380
409
  var DEFAULT_MULTICURVE_UPPER_TICKS = [
381
- -188200,
382
- -172100,
383
- -156e3
410
+ -142200,
411
+ -116300,
412
+ -84100
384
413
  ];
385
414
  var DEFAULT_MULTICURVE_NUM_POSITIONS = [11, 11, 11];
386
415
  var DEFAULT_MULTICURVE_MAX_SUPPLY_SHARES = [
387
- parseEther("0.05"),
388
- // 5% for LOW tier
389
- parseEther("0.125"),
390
- // 12.5% for MEDIUM tier
391
- parseEther("0.2")
392
- // 20% for HIGH tier
416
+ parseEther("0.5"),
417
+ // 50% for LOW tier
418
+ parseEther("0.25"),
419
+ // 25% for MEDIUM tier
420
+ parseEther("0.24")
421
+ // 24% for HIGH tier
393
422
  ];
394
423
  var BASIS_POINTS = 1e4;
395
424
  var FLAG_MASK = BigInt(16383);
@@ -433,6 +462,7 @@ var CHAIN_IDS = {
433
462
  BASE: 8453,
434
463
  BASE_SEPOLIA: 84532,
435
464
  INK: 57073,
465
+ ROBINHOOD: 4663,
436
466
  UNICHAIN: 130,
437
467
  UNICHAIN_SEPOLIA: 1301,
438
468
  MONAD_TESTNET: 10143,
@@ -704,6 +734,55 @@ var ADDRESSES = {
704
734
  weth: "0x4200000000000000000000000000000000000006",
705
735
  uniswapV4Quoter: "0x3972c00f7ed4885e145823eb7c655375d275a1c5"
706
736
  },
737
+ [CHAIN_IDS.ROBINHOOD]: {
738
+ airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].Airlock,
739
+ tokenFactory: ZERO_ADDRESS,
740
+ dopplerERC20V1Factory: getGeneratedAddress(
741
+ CHAIN_IDS.ROBINHOOD,
742
+ "DopplerERC20V1Factory"
743
+ ),
744
+ dopplerERC20V1Implementation: getGeneratedAddress(
745
+ CHAIN_IDS.ROBINHOOD,
746
+ "DopplerERC20V1"
747
+ ),
748
+ doppler404Factory: getGeneratedAddress(CHAIN_IDS.ROBINHOOD, "DN404Factory"),
749
+ v3Initializer: ZERO_ADDRESS,
750
+ v3Quoter: "0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7",
751
+ lockableV3Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].LockableUniswapV3Initializer,
752
+ v4Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].UniswapV4Initializer,
753
+ dopplerHookInitializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].DopplerHookInitializer,
754
+ rehypeDopplerHookInitializer: getRehypeDopplerHookInitializerAddress(
755
+ CHAIN_IDS.ROBINHOOD
756
+ ),
757
+ rehypeDopplerHook: getRehypeDopplerHookInitializerAddress(
758
+ CHAIN_IDS.ROBINHOOD
759
+ ),
760
+ dopplerLens: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].DopplerLensQuoter,
761
+ dopplerDeployer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].DopplerDeployer,
762
+ poolManager: "0x8366a39cc670b4001a1121b8f6a443a643e40951",
763
+ v2Migrator: ZERO_ADDRESS,
764
+ v2MigratorSplit: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].UniswapV2MigratorSplit,
765
+ v4Migrator: ZERO_ADDRESS,
766
+ dopplerHookMigrator: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].DopplerHookMigrator,
767
+ rehypeDopplerHookMigrator: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].RehypeDopplerHookMigrator,
768
+ noOpMigrator: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].NoOpMigrator,
769
+ governanceFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].GovernanceFactory,
770
+ noOpGovernanceFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].NoOpGovernanceFactory,
771
+ launchpadGovernanceFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].LaunchpadGovernanceFactory,
772
+ streamableFeesLocker: ZERO_ADDRESS,
773
+ streamableFeesLockerV2: getGeneratedAddress(
774
+ CHAIN_IDS.ROBINHOOD,
775
+ "StreamableFeesLockerV2"
776
+ ),
777
+ topUpDistributor: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].TopUpDistributor,
778
+ universalRouter: "0x8876789976decbfcbbbe364623c63652db8c0904",
779
+ permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
780
+ bundler: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].Bundler,
781
+ weth: "0x0bd7d308f8e1639fab988df18a8011f41eacad73",
782
+ uniswapV2Factory: "0x8bceaa40b9acdfaedf85adf4ff01f5ad6517937f",
783
+ uniswapV3Factory: "0x1f7d7550b1b028f7571e69a784071f0205fd2efa",
784
+ uniswapV4Quoter: "0x8dc178efb8111bb0973dd9d722ebeff267c98f94"
785
+ },
707
786
  [CHAIN_IDS.UNICHAIN]: {
708
787
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.UNICHAIN].Airlock,
709
788
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.UNICHAIN].TokenFactory,
@@ -6596,6 +6675,92 @@ function getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1) {
6596
6675
  return amount1 * Q96 / diff;
6597
6676
  }
6598
6677
 
6678
+ // src/evm/utils/multicurveLiquidity.ts
6679
+ var MAX_UINT128 = (1n << 128n) - 1n;
6680
+ function getMaxLiquiditySafeMulticurveTickUpper(params) {
6681
+ if (params.tickUpper <= params.tickLower) {
6682
+ throw new Error(
6683
+ `Unable to find a uint128-safe multicurve max tick below ${params.tickUpper}`
6684
+ );
6685
+ }
6686
+ if (isCanonicalCurveLiquiditySafe(params)) return params.tickUpper;
6687
+ for (let candidate = params.tickUpper - params.tickSpacing; candidate > params.tickLower; candidate -= params.tickSpacing) {
6688
+ if (isCanonicalCurveLiquiditySafe({ ...params, tickUpper: candidate })) {
6689
+ return candidate;
6690
+ }
6691
+ }
6692
+ throw new Error(
6693
+ `Unable to find a uint128-safe multicurve max tick below ${params.tickUpper}`
6694
+ );
6695
+ }
6696
+ function isCanonicalCurveLiquiditySafe(params) {
6697
+ return isAdjustedCurveLiquiditySafe({
6698
+ ...params,
6699
+ isToken0: true
6700
+ }) && isAdjustedCurveLiquiditySafe({
6701
+ ...params,
6702
+ tickLower: -params.tickUpper,
6703
+ tickUpper: -params.tickLower,
6704
+ isToken0: false
6705
+ });
6706
+ }
6707
+ function isAdjustedCurveLiquiditySafe(params) {
6708
+ if (params.numPositions <= 0 || params.tickSpacing <= 0) {
6709
+ throw new Error("Multicurve positions and tick spacing must be positive");
6710
+ }
6711
+ const amountPerPosition = params.curveSupply / BigInt(params.numPositions);
6712
+ if (amountPerPosition <= 1n) return true;
6713
+ const amount = amountPerPosition - 1n;
6714
+ const maxLiquidityPerTick = getMaxLiquidityPerTick(params.tickSpacing);
6715
+ const liquidityByTick = /* @__PURE__ */ new Map();
6716
+ const farTick = params.isToken0 ? params.tickUpper : params.tickLower;
6717
+ const closeTick = params.isToken0 ? params.tickLower : params.tickUpper;
6718
+ const spread = params.tickUpper - params.tickLower;
6719
+ const farSqrtPriceX96 = getSqrtRatioAtTick(farTick);
6720
+ for (let i = 0; i < params.numPositions; i++) {
6721
+ const tickDelta = Number(
6722
+ BigInt(i) * BigInt(spread) / BigInt(params.numPositions)
6723
+ );
6724
+ const unalignedTick = params.isToken0 ? closeTick + tickDelta : closeTick - tickDelta;
6725
+ const startingTick = alignMulticurveTick(
6726
+ params.isToken0,
6727
+ unalignedTick,
6728
+ params.tickSpacing
6729
+ );
6730
+ if (startingTick === farTick) continue;
6731
+ const startingSqrtPriceX96 = getSqrtRatioAtTick(startingTick);
6732
+ const liquidity = params.isToken0 ? getLiquidityForAmount0(startingSqrtPriceX96, farSqrtPriceX96, amount) : getLiquidityForAmount1(farSqrtPriceX96, startingSqrtPriceX96, amount);
6733
+ if (liquidity > maxLiquidityPerTick) return false;
6734
+ const tickA = Math.min(farTick, startingTick);
6735
+ const tickB = Math.max(farTick, startingTick);
6736
+ if (!addTickLiquidity(liquidityByTick, tickA, liquidity, maxLiquidityPerTick)) {
6737
+ return false;
6738
+ }
6739
+ if (!addTickLiquidity(liquidityByTick, tickB, liquidity, maxLiquidityPerTick)) {
6740
+ return false;
6741
+ }
6742
+ }
6743
+ return true;
6744
+ }
6745
+ function getMaxLiquidityPerTick(tickSpacing) {
6746
+ const minTick = Math.trunc(MIN_TICK / tickSpacing) * tickSpacing;
6747
+ const maxTick = Math.trunc(MAX_TICK / tickSpacing) * tickSpacing;
6748
+ const numTicks = BigInt((maxTick - minTick) / tickSpacing + 1);
6749
+ return MAX_UINT128 / numTicks;
6750
+ }
6751
+ function addTickLiquidity(liquidityByTick, tick, liquidity, maxLiquidityPerTick) {
6752
+ const updatedLiquidity = (liquidityByTick.get(tick) ?? 0n) + liquidity;
6753
+ if (updatedLiquidity > maxLiquidityPerTick) return false;
6754
+ liquidityByTick.set(tick, updatedLiquidity);
6755
+ return true;
6756
+ }
6757
+ function alignMulticurveTick(isToken0, tick, tickSpacing) {
6758
+ if (isToken0) {
6759
+ return tick < 0 ? Math.trunc((tick - tickSpacing + 1) / tickSpacing) * tickSpacing : Math.trunc(tick / tickSpacing) * tickSpacing;
6760
+ }
6761
+ return tick < 0 ? Math.trunc(tick / tickSpacing) * tickSpacing : Math.trunc((tick + tickSpacing - 1) / tickSpacing) * tickSpacing;
6762
+ }
6763
+
6599
6764
  // src/evm/utils/computeOptimalGamma.ts
6600
6765
  function computeOptimalGamma(startTick, endTick, duration, epochLength, tickSpacing) {
6601
6766
  const totalEpochs = duration / epochLength;
@@ -6631,6 +6796,23 @@ function isToken0Expected(numeraire) {
6631
6796
  }
6632
6797
  }
6633
6798
 
6799
+ // src/evm/utils/beneficiaries.ts
6800
+ function sortBeneficiaries(beneficiaries) {
6801
+ const sorted = [...beneficiaries].sort((a, b) => {
6802
+ const aAddr = a.beneficiary.toLowerCase();
6803
+ const bAddr = b.beneficiary.toLowerCase();
6804
+ return aAddr < bAddr ? -1 : aAddr > bAddr ? 1 : 0;
6805
+ });
6806
+ for (let i = 1; i < sorted.length; i++) {
6807
+ if (sorted[i].beneficiary.toLowerCase() === sorted[i - 1].beneficiary.toLowerCase()) {
6808
+ throw new Error(
6809
+ `Duplicate beneficiary address: ${sorted[i].beneficiary}. Each beneficiary address must be unique \u2014 the contract requires strictly ascending addresses and reverts with UnorderedBeneficiaries() otherwise. Merge the entries into a single beneficiary with the combined shares.`
6810
+ );
6811
+ }
6812
+ }
6813
+ return sorted;
6814
+ }
6815
+
6634
6816
  // src/evm/types.ts
6635
6817
  var NO_OP_ENABLED_CHAIN_IDS = [
6636
6818
  CHAIN_IDS.MAINNET,
@@ -6639,6 +6821,7 @@ var NO_OP_ENABLED_CHAIN_IDS = [
6639
6821
  CHAIN_IDS.BASE_SEPOLIA,
6640
6822
  CHAIN_IDS.UNICHAIN,
6641
6823
  CHAIN_IDS.UNICHAIN_SEPOLIA,
6824
+ CHAIN_IDS.ROBINHOOD,
6642
6825
  CHAIN_IDS.MONAD_TESTNET,
6643
6826
  CHAIN_IDS.MONAD_MAINNET
6644
6827
  ];
@@ -6649,6 +6832,7 @@ var LAUNCHPAD_ENABLED_CHAIN_IDS = [
6649
6832
  CHAIN_IDS.MAINNET,
6650
6833
  CHAIN_IDS.BASE,
6651
6834
  CHAIN_IDS.BASE_SEPOLIA,
6835
+ CHAIN_IDS.ROBINHOOD,
6652
6836
  CHAIN_IDS.MONAD_MAINNET
6653
6837
  ];
6654
6838
  function isLaunchpadEnabledChain(chainId) {
@@ -7233,7 +7417,7 @@ function buildCurvesFromPresets(params) {
7233
7417
  }
7234
7418
 
7235
7419
  // src/evm/entities/DopplerFactory.ts
7236
- var MAX_UINT128 = (1n << 128n) - 1n;
7420
+ var MAX_UINT1282 = (1n << 128n) - 1n;
7237
7421
  var MAX_PROCEEDS_SPLIT_SHARE = WAD / 2n;
7238
7422
  var DERC20_V1_MAX_PREMINT_WAD = WAD * 8n / 10n;
7239
7423
  var ONE_MILLION = 1000000n;
@@ -7929,11 +8113,7 @@ var DopplerFactory = class {
7929
8113
  const hasBeneficiaries = params.pool.beneficiaries && params.pool.beneficiaries.length > 0;
7930
8114
  let poolInitializerData;
7931
8115
  if (hasBeneficiaries) {
7932
- const sortedBeneficiaries = params.pool.beneficiaries.slice().sort((a, b) => {
7933
- const aAddr = a.beneficiary.toLowerCase();
7934
- const bAddr = b.beneficiary.toLowerCase();
7935
- return aAddr < bAddr ? -1 : aAddr > bAddr ? 1 : 0;
7936
- });
8116
+ const sortedBeneficiaries = sortBeneficiaries(params.pool.beneficiaries);
7937
8117
  poolInitializerData = encodeAbiParameters(
7938
8118
  [
7939
8119
  {
@@ -8013,14 +8193,20 @@ var DopplerFactory = class {
8013
8193
  const poolInitializerAddress = (() => {
8014
8194
  if (hasBeneficiaries) {
8015
8195
  const lockableInitializer = params.modules?.lockableV3Initializer ?? addresses.lockableV3Initializer;
8016
- if (!lockableInitializer) {
8196
+ if (!lockableInitializer || lockableInitializer === ZERO_ADDRESS) {
8017
8197
  throw new Error(
8018
8198
  "Lockable V3 initializer address not configured on this chain. Required when using beneficiaries."
8019
8199
  );
8020
8200
  }
8021
8201
  return lockableInitializer;
8022
8202
  }
8023
- return params.modules?.v3Initializer ?? addresses.v3Initializer;
8203
+ const standardInitializer = params.modules?.v3Initializer ?? addresses.v3Initializer;
8204
+ if (!standardInitializer || standardInitializer === ZERO_ADDRESS) {
8205
+ throw new Error(
8206
+ "UniswapV3Initializer address not configured on this chain. Use beneficiaries for lockable V3 support, provide an override via builder.withV3Initializer(...), or use a chain with standard V3 initializer support."
8207
+ );
8208
+ }
8209
+ return standardInitializer;
8024
8210
  })();
8025
8211
  const liquidityMigratorAddress = this.getMigratorAddress(
8026
8212
  params.migration,
@@ -8435,6 +8621,11 @@ var DopplerFactory = class {
8435
8621
  addresses
8436
8622
  });
8437
8623
  const poolInitializerAddress = params.modules?.v4Initializer ?? addresses.v4Initializer;
8624
+ if (!poolInitializerAddress || poolInitializerAddress === ZERO_ADDRESS) {
8625
+ throw new Error(
8626
+ "UniswapV4Initializer address not configured on this chain. Provide an override via builder.withV4Initializer(...) or use a chain with dynamic auction support."
8627
+ );
8628
+ }
8438
8629
  const liquidityMigratorAddress = this.getMigratorAddress(
8439
8630
  params.migration,
8440
8631
  params.modules
@@ -9765,13 +9956,7 @@ var DopplerFactory = class {
9765
9956
  if (!streamableFees) {
9766
9957
  return "0x";
9767
9958
  }
9768
- const beneficiaryData = [...streamableFees.beneficiaries].sort(
9769
- (a, b) => {
9770
- const addrA = a.beneficiary.toLowerCase();
9771
- const addrB = b.beneficiary.toLowerCase();
9772
- return addrA < addrB ? -1 : addrA > addrB ? 1 : 0;
9773
- }
9774
- );
9959
+ const beneficiaryData = sortBeneficiaries(streamableFees.beneficiaries);
9775
9960
  return encodeAbiParameters(
9776
9961
  [
9777
9962
  { type: "uint24" },
@@ -9796,12 +9981,8 @@ var DopplerFactory = class {
9796
9981
  ]
9797
9982
  );
9798
9983
  case "uniswapV4Split": {
9799
- const beneficiaryData2 = [...config.streamableFees.beneficiaries].sort(
9800
- (a, b) => {
9801
- const addrA = a.beneficiary.toLowerCase();
9802
- const addrB = b.beneficiary.toLowerCase();
9803
- return addrA < addrB ? -1 : addrA > addrB ? 1 : 0;
9804
- }
9984
+ const beneficiaryData2 = sortBeneficiaries(
9985
+ config.streamableFees.beneficiaries
9805
9986
  );
9806
9987
  const proceedsRecipient = config.proceedsSplit?.recipient ?? ZERO_ADDRESS;
9807
9988
  const proceedsShare = config.proceedsSplit?.share ?? 0n;
@@ -9837,12 +10018,8 @@ var DopplerFactory = class {
9837
10018
  "dopplerHook migration cannot set both hook and rehype config. Use exactly one hook mode."
9838
10019
  );
9839
10020
  }
9840
- const beneficiaries = [...dopplerHookConfig.beneficiaries].sort(
9841
- (a, b) => {
9842
- const addrA = a.beneficiary.toLowerCase();
9843
- const addrB = b.beneficiary.toLowerCase();
9844
- return addrA < addrB ? -1 : addrA > addrB ? 1 : 0;
9845
- }
10021
+ const beneficiaries = sortBeneficiaries(
10022
+ dopplerHookConfig.beneficiaries
9846
10023
  );
9847
10024
  let dopplerHookAddress = ZERO_ADDRESS;
9848
10025
  let onInitializationCalldata = "0x";
@@ -10245,15 +10422,12 @@ var DopplerFactory = class {
10245
10422
  }
10246
10423
  const normalizedCurves = this.normalizeMulticurveCurves(
10247
10424
  params.pool.curves,
10248
- params.pool.tickSpacing
10425
+ params.pool.tickSpacing,
10426
+ params.sale.numTokensToSell
10249
10427
  );
10250
10428
  const addresses = getAddresses(this.chainId);
10251
- const sortedBeneficiaries = (params.pool.beneficiaries ?? []).slice().sort(
10252
- (a, b) => {
10253
- const aAddr = a.beneficiary.toLowerCase();
10254
- const bAddr = b.beneficiary.toLowerCase();
10255
- return aAddr < bAddr ? -1 : aAddr > bAddr ? 1 : 0;
10256
- }
10429
+ const sortedBeneficiaries = sortBeneficiaries(
10430
+ params.pool.beneficiaries ?? []
10257
10431
  );
10258
10432
  const initializerMode = this.resolveMulticurveInitializerMode(params);
10259
10433
  const useScheduledInitializer = initializerMode.type === "scheduled";
@@ -10728,7 +10902,7 @@ var DopplerFactory = class {
10728
10902
  /**
10729
10903
  * Normalize user-provided multicurve positions and ensure they satisfy SDK constraints
10730
10904
  */
10731
- normalizeMulticurveCurves(curves, tickSpacing) {
10905
+ normalizeMulticurveCurves(curves, tickSpacing, numTokensToSell) {
10732
10906
  if (tickSpacing <= 0) {
10733
10907
  throw new Error("Tick spacing must be positive");
10734
10908
  }
@@ -10775,25 +10949,19 @@ var DopplerFactory = class {
10775
10949
  if (fallbackTickLower === void 0) {
10776
10950
  throw new Error("Unable to determine fallback multicurve tick range");
10777
10951
  }
10778
- const fallbackTickUpper = this.roundMaxTickDown(tickSpacing);
10779
- if (fallbackTickLower >= fallbackTickUpper) {
10780
- const adjustedLower = fallbackTickUpper - tickSpacing;
10781
- if (adjustedLower < fallbackTickLower) {
10782
- return sanitizedCurves;
10783
- }
10784
- const fallbackCurve2 = {
10785
- tickLower: adjustedLower,
10786
- tickUpper: fallbackTickUpper,
10787
- numPositions: sanitizedCurves[sanitizedCurves.length - 1]?.numPositions ?? 1,
10788
- shares: missingShare
10789
- };
10790
- return [...sanitizedCurves, fallbackCurve2];
10791
- }
10952
+ const fallbackNumPositions = sanitizedCurves[sanitizedCurves.length - 1]?.numPositions ?? 1;
10953
+ const fallbackTickUpper = getMaxLiquiditySafeMulticurveTickUpper({
10954
+ tickLower: fallbackTickLower,
10955
+ tickUpper: this.roundMaxTickDown(tickSpacing),
10956
+ tickSpacing,
10957
+ numPositions: fallbackNumPositions,
10958
+ curveSupply: numTokensToSell * missingShare / WAD
10959
+ });
10792
10960
  const fallbackCurve = {
10793
10961
  // Extend from the most positive user tick out to the maximum supported tick bucket
10794
10962
  tickLower: fallbackTickLower,
10795
10963
  tickUpper: fallbackTickUpper,
10796
- numPositions: sanitizedCurves[sanitizedCurves.length - 1]?.numPositions ?? 1,
10964
+ numPositions: fallbackNumPositions,
10797
10965
  shares: missingShare
10798
10966
  };
10799
10967
  return [...sanitizedCurves, fallbackCurve];
@@ -11313,8 +11481,15 @@ var DopplerFactory = class {
11313
11481
  getMigratorAddress(config, overrides) {
11314
11482
  const addresses = getAddresses(this.chainId);
11315
11483
  switch (config.type) {
11316
- case "uniswapV2":
11317
- return overrides?.v2Migrator ?? addresses.v2Migrator;
11484
+ case "uniswapV2": {
11485
+ const v2Address = overrides?.v2Migrator ?? addresses.v2Migrator;
11486
+ if (!v2Address || v2Address === ZERO_ADDRESS) {
11487
+ throw new Error(
11488
+ "UniswapV2Migrator not deployed on this chain. Use uniswapV2Split migration or provide override via modules.v2Migrator."
11489
+ );
11490
+ }
11491
+ return v2Address;
11492
+ }
11318
11493
  case "uniswapV2Split": {
11319
11494
  const v2SplitAddress = overrides?.v2MigratorSplit ?? addresses.v2MigratorSplit;
11320
11495
  if (!v2SplitAddress || v2SplitAddress === ZERO_ADDRESS) {
@@ -11326,7 +11501,7 @@ var DopplerFactory = class {
11326
11501
  }
11327
11502
  case "uniswapV4": {
11328
11503
  const v4Address = overrides?.v4Migrator ?? addresses.v4Migrator;
11329
- if (v4Address === "0x0000000000000000000000000000000000000000") {
11504
+ if (!v4Address || v4Address === ZERO_ADDRESS) {
11330
11505
  throw new Error(
11331
11506
  "UniswapV4Migrator not deployed on this chain. Use uniswapV2 migration or provide override via modules.v4Migrator."
11332
11507
  );
@@ -11492,7 +11667,7 @@ var DopplerFactory = class {
11492
11667
  if (!allowZero && value === 0n) {
11493
11668
  throw new Error(`${paramName} must be greater than zero`);
11494
11669
  }
11495
- if (value > MAX_UINT128) {
11670
+ if (value > MAX_UINT1282) {
11496
11671
  throw new Error(`${paramName} exceeds uint128 range`);
11497
11672
  }
11498
11673
  }
@@ -18489,9 +18664,16 @@ var MulticurveBuilder = class _MulticurveBuilder {
18489
18664
  tokenDecimals: config.tokenDecimals ?? 18,
18490
18665
  numeraireDecimals: config.numeraireDecimals ?? 18
18491
18666
  });
18667
+ const curveSupply = this.sale.numTokensToSell * curve.shares / WAD;
18668
+ const tickUpper = curve.marketCap.end === "max" ? getMaxLiquiditySafeMulticurveTickUpper({
18669
+ ...curveTicks,
18670
+ tickSpacing,
18671
+ numPositions: curve.numPositions,
18672
+ curveSupply
18673
+ }) : curveTicks.tickUpper;
18492
18674
  curves.push({
18493
18675
  tickLower: curveTicks.tickLower,
18494
- tickUpper: curveTicks.tickUpper,
18676
+ tickUpper,
18495
18677
  numPositions: curve.numPositions,
18496
18678
  shares: curve.shares
18497
18679
  });
@@ -18552,7 +18734,7 @@ var MulticurveBuilder = class _MulticurveBuilder {
18552
18734
  }
18553
18735
  dopplerHook = { ...dopplerHook, farTick };
18554
18736
  }
18555
- const initializer = this.initializer ?? (dopplerHook ? { type: "rehype", config: dopplerHook } : this.schedule ? { type: "scheduled", startTime: this.schedule.startTime } : { type: "standard" });
18737
+ const initializer = this.initializer?.type === "rehype" && dopplerHook ? { type: "rehype", config: dopplerHook } : this.initializer ?? (dopplerHook ? { type: "rehype", config: dopplerHook } : this.schedule ? { type: "scheduled", startTime: this.schedule.startTime } : { type: "standard" });
18556
18738
  if (initializer.type === "scheduled" && dopplerHook) {
18557
18739
  throw new Error(
18558
18740
  "Cannot combine scheduled multicurve with rehype initializer. Use exactly one initializer mode."
@@ -19239,6 +19421,6 @@ var DopplerSDK = class {
19239
19421
  // src/evm/index.ts
19240
19422
  var VERSION = "1.0.0";
19241
19423
 
19242
- export { ADDRESSES, BASIS_POINTS, CHAIN_IDS, DAY_SECONDS, DEAD_ADDRESS, DECAY_MAX_START_FEE, DEFAULT_AIRLOCK_BENEFICIARY_SHARES, DEFAULT_AUCTION_DURATION, DEFAULT_EPOCH_LENGTH, DEFAULT_LOCK_DURATION, DEFAULT_MULTICURVE_LOWER_TICKS, DEFAULT_MULTICURVE_MAX_SUPPLY_SHARES, DEFAULT_MULTICURVE_NUM_POSITIONS, DEFAULT_MULTICURVE_UPPER_TICKS, DEFAULT_OPENING_AUCTION_DURATION, DEFAULT_OPENING_AUCTION_FEE, DEFAULT_OPENING_AUCTION_INCENTIVE_SHARE_BPS, DEFAULT_OPENING_AUCTION_MIN_ACCEPTABLE_TICK_TOKEN0, DEFAULT_OPENING_AUCTION_MIN_ACCEPTABLE_TICK_TOKEN1, DEFAULT_OPENING_AUCTION_MIN_LIQUIDITY, DEFAULT_OPENING_AUCTION_SHARE_TO_AUCTION_BPS, DEFAULT_OPENING_DOPPLER_DURATION, DEFAULT_OPENING_DOPPLER_EPOCH_LENGTH, DEFAULT_OPENING_DOPPLER_FEE, DEFAULT_OPENING_DOPPLER_NUM_PD_SLUGS, DEFAULT_OPENING_DOPPLER_TICK_SPACING, DEFAULT_PD_SLUGS, DEFAULT_V3_END_TICK, DEFAULT_V3_FEE, DEFAULT_V3_INITIAL_PROPOSAL_THRESHOLD, DEFAULT_V3_INITIAL_SUPPLY, DEFAULT_V3_INITIAL_VOTING_DELAY, DEFAULT_V3_INITIAL_VOTING_PERIOD, DEFAULT_V3_MAX_SHARE_TO_BE_SOLD, DEFAULT_V3_NUM_POSITIONS, DEFAULT_V3_NUM_TOKENS_TO_SELL, DEFAULT_V3_PRE_MINT, DEFAULT_V3_START_TICK, DEFAULT_V3_VESTING_DURATION, DEFAULT_V3_YEARLY_MINT_RATE, DEFAULT_V4_INITIAL_PROPOSAL_THRESHOLD, DEFAULT_V4_INITIAL_VOTING_DELAY, DEFAULT_V4_INITIAL_VOTING_PERIOD, DEFAULT_V4_YEARLY_MINT_RATE, derc2080_default as DERC2080Bytecode, derc20_default as DERC20Bytecode, DOPPLER_FLAGS, DOPPLER_MAX_TICK_SPACING, DYNAMIC_FEE_FLAG, Derc20, Derc20V2, doppler_default as DopplerBytecode, dopplerDN404_default as DopplerDN404Bytecode, DopplerERC20V1, DopplerFactory, DopplerSDK, DynamicAuction, DynamicAuctionBuilder, Eth, FEE_AMOUNT_MASK, FEE_TIERS, FLAG_MASK, INT24_MAX, INT24_MIN, LAUNCHPAD_ENABLED_CHAIN_IDS, LockablePoolStatus, MAX_SQRT_RATIO, MAX_TICK, MIN_SQRT_RATIO, MIN_TICK, MulticurveBuilder, MulticurveFees, MulticurvePool, NO_OP_ENABLED_CHAIN_IDS, OPENING_AUCTION_FLAGS, OPENING_AUCTION_PHASE_ACTIVE, OPENING_AUCTION_PHASE_CLOSED, OPENING_AUCTION_PHASE_NOT_STARTED, OPENING_AUCTION_PHASE_SETTLED, OPENING_AUCTION_STATUS_ACTIVE, OPENING_AUCTION_STATUS_DOPPLER_ACTIVE, OPENING_AUCTION_STATUS_EXITED, OPENING_AUCTION_STATUS_UNINITIALIZED, OpeningAuction, OpeningAuctionBidManager, OpeningAuctionBuilder, openingAuction_default as OpeningAuctionBytecode, OpeningAuctionLifecycle, OpeningAuctionPhase, OpeningAuctionPositionManager, OpeningAuctionStatus, Q96, Quoter, RehypeDopplerHook, RehypeDopplerHookMigrator, RehypeFeeRoutingMode, SECONDS_PER_DAY, SECONDS_PER_YEAR, SUPPORTED_CHAIN_IDS, stateView_default as StateViewBytecode, StaticAuction, StaticAuctionBuilder, TICK_SPACINGS, TopUpDistributor, V3_FEE_TIERS, V4_MAX_FEE, VALID_FEE_TIERS, VERSION, WAD, ZERO_ADDRESS, airlockAbi, applyTickOffsets, bundlerAbi, calculateFDV, calculateGamma, calculateMarketCap, calculateTickRange, calculateTokensToSell, computeOptimalGamma, computePoolId, createAirlockBeneficiary, decayMulticurveInitializerHookAbi, decodeBalanceDelta, derc20Abi, derc20V2Abi, dopplerERC20V1Abi, dopplerHookAbi, dopplerHookInitializerAbi, dopplerLensAbi, encodeRehypeDopplerHookMigratorCalldata, estimatePriceAtEpoch, estimateSlippage, feeClaimsInitializerAbi, formatTickAsPrice, getAddresses, getAirlockBeneficiary, getAirlockOwner, getAmount0ForLiquidity, getAmount1ForLiquidity, getLiquidityForAmount0, getLiquidityForAmount1, getMaxTickRounded, getNearestUsableTick, getSqrtRatioAtTick, getTickAtSqrtRatio, isLaunchpadEnabledChain, isNoOpEnabledChain, isSupportedChainId, isToken0Expected, isToken1, lockableUniswapV3InitializerAbi, marketCapToTickForMulticurve, marketCapToTicksForDynamicAuction, marketCapToTicksForMulticurve, marketCapToTicksForStaticAuction, marketCapToTokenPrice, mineTokenAddress, normalizePoolKey, openingAuctionAbi, openingAuctionInitializerAbi, openingAuctionPositionManagerAbi, poolManagerAbi, priceToSqrtPriceX96, priceToTick, quoterV2Abi, ratioToTick, rehypeDopplerHookAbi, rehypeDopplerHookMigratorAbi, resolveGasEstimate, sqrtPriceX96ToPrice, streamableFeesLockerAbi, streamableFeesLockerV2Abi, tickToMarketCap, tickToPrice, tokenPriceToRatio, topUpDistributorAbi, uniswapV2Router02Abi, uniswapV3InitializerAbi, uniswapV3PoolAbi, uniswapV4InitializerAbi, v2MigratorAbi, v3MigratorAbi, v4MigratorAbi, v4MulticurveInitializerAbi, v4MulticurveMigratorAbi, v4QuoterAbi, validateMarketCapParameters, weth9Abi };
19424
+ export { ADDRESSES, BASIS_POINTS, CHAIN_IDS, DAY_SECONDS, DEAD_ADDRESS, DECAY_MAX_START_FEE, DEFAULT_AIRLOCK_BENEFICIARY_SHARES, DEFAULT_AUCTION_DURATION, DEFAULT_EPOCH_LENGTH, DEFAULT_LOCK_DURATION, DEFAULT_MULTICURVE_LOWER_TICKS, DEFAULT_MULTICURVE_MAX_SUPPLY_SHARES, DEFAULT_MULTICURVE_NUM_POSITIONS, DEFAULT_MULTICURVE_UPPER_TICKS, DEFAULT_OPENING_AUCTION_DURATION, DEFAULT_OPENING_AUCTION_FEE, DEFAULT_OPENING_AUCTION_INCENTIVE_SHARE_BPS, DEFAULT_OPENING_AUCTION_MIN_ACCEPTABLE_TICK_TOKEN0, DEFAULT_OPENING_AUCTION_MIN_ACCEPTABLE_TICK_TOKEN1, DEFAULT_OPENING_AUCTION_MIN_LIQUIDITY, DEFAULT_OPENING_AUCTION_SHARE_TO_AUCTION_BPS, DEFAULT_OPENING_DOPPLER_DURATION, DEFAULT_OPENING_DOPPLER_EPOCH_LENGTH, DEFAULT_OPENING_DOPPLER_FEE, DEFAULT_OPENING_DOPPLER_NUM_PD_SLUGS, DEFAULT_OPENING_DOPPLER_TICK_SPACING, DEFAULT_PD_SLUGS, DEFAULT_V3_END_TICK, DEFAULT_V3_FEE, DEFAULT_V3_INITIAL_PROPOSAL_THRESHOLD, DEFAULT_V3_INITIAL_SUPPLY, DEFAULT_V3_INITIAL_VOTING_DELAY, DEFAULT_V3_INITIAL_VOTING_PERIOD, DEFAULT_V3_MAX_SHARE_TO_BE_SOLD, DEFAULT_V3_NUM_POSITIONS, DEFAULT_V3_NUM_TOKENS_TO_SELL, DEFAULT_V3_PRE_MINT, DEFAULT_V3_START_TICK, DEFAULT_V3_VESTING_DURATION, DEFAULT_V3_YEARLY_MINT_RATE, DEFAULT_V4_INITIAL_PROPOSAL_THRESHOLD, DEFAULT_V4_INITIAL_VOTING_DELAY, DEFAULT_V4_INITIAL_VOTING_PERIOD, DEFAULT_V4_YEARLY_MINT_RATE, derc2080_default as DERC2080Bytecode, derc20_default as DERC20Bytecode, DOPPLER_FLAGS, DOPPLER_MAX_TICK_SPACING, DYNAMIC_FEE_FLAG, Derc20, Derc20V2, doppler_default as DopplerBytecode, dopplerDN404_default as DopplerDN404Bytecode, DopplerERC20V1, DopplerFactory, DopplerSDK, DynamicAuction, DynamicAuctionBuilder, Eth, FEE_AMOUNT_MASK, FEE_TIERS, FLAG_MASK, INT24_MAX, INT24_MIN, LAUNCHPAD_ENABLED_CHAIN_IDS, LockablePoolStatus, MAX_SQRT_RATIO, MAX_TICK, MIN_SQRT_RATIO, MIN_TICK, MulticurveBuilder, MulticurveFees, MulticurvePool, NO_OP_ENABLED_CHAIN_IDS, OPENING_AUCTION_FLAGS, OPENING_AUCTION_PHASE_ACTIVE, OPENING_AUCTION_PHASE_CLOSED, OPENING_AUCTION_PHASE_NOT_STARTED, OPENING_AUCTION_PHASE_SETTLED, OPENING_AUCTION_STATUS_ACTIVE, OPENING_AUCTION_STATUS_DOPPLER_ACTIVE, OPENING_AUCTION_STATUS_EXITED, OPENING_AUCTION_STATUS_UNINITIALIZED, OpeningAuction, OpeningAuctionBidManager, OpeningAuctionBuilder, openingAuction_default as OpeningAuctionBytecode, OpeningAuctionLifecycle, OpeningAuctionPhase, OpeningAuctionPositionManager, OpeningAuctionStatus, Q96, Quoter, RehypeDopplerHook, RehypeDopplerHookMigrator, RehypeFeeRoutingMode, SECONDS_PER_DAY, SECONDS_PER_YEAR, SUPPORTED_CHAIN_IDS, stateView_default as StateViewBytecode, StaticAuction, StaticAuctionBuilder, TICK_SPACINGS, TopUpDistributor, V3_FEE_TIERS, V4_MAX_FEE, VALID_FEE_TIERS, VERSION, WAD, ZERO_ADDRESS, airlockAbi, applyTickOffsets, bundlerAbi, calculateFDV, calculateGamma, calculateMarketCap, calculateTickRange, calculateTokensToSell, computeOptimalGamma, computePoolId, createAirlockBeneficiary, decayMulticurveInitializerHookAbi, decodeBalanceDelta, derc20Abi, derc20V2Abi, dopplerERC20V1Abi, dopplerHookAbi, dopplerHookInitializerAbi, dopplerLensAbi, encodeRehypeDopplerHookMigratorCalldata, estimatePriceAtEpoch, estimateSlippage, feeClaimsInitializerAbi, formatTickAsPrice, getAddresses, getAirlockBeneficiary, getAirlockOwner, getAmount0ForLiquidity, getAmount1ForLiquidity, getLiquidityForAmount0, getLiquidityForAmount1, getMaxLiquiditySafeMulticurveTickUpper, getMaxTickRounded, getNearestUsableTick, getSqrtRatioAtTick, getTickAtSqrtRatio, isLaunchpadEnabledChain, isNoOpEnabledChain, isSupportedChainId, isToken0Expected, isToken1, lockableUniswapV3InitializerAbi, marketCapToTickForMulticurve, marketCapToTicksForDynamicAuction, marketCapToTicksForMulticurve, marketCapToTicksForStaticAuction, marketCapToTokenPrice, mineTokenAddress, normalizePoolKey, openingAuctionAbi, openingAuctionInitializerAbi, openingAuctionPositionManagerAbi, poolManagerAbi, priceToSqrtPriceX96, priceToTick, quoterV2Abi, ratioToTick, rehypeDopplerHookAbi, rehypeDopplerHookMigratorAbi, resolveGasEstimate, sortBeneficiaries, sqrtPriceX96ToPrice, streamableFeesLockerAbi, streamableFeesLockerV2Abi, tickToMarketCap, tickToPrice, tokenPriceToRatio, topUpDistributorAbi, uniswapV2Router02Abi, uniswapV3InitializerAbi, uniswapV3PoolAbi, uniswapV4InitializerAbi, v2MigratorAbi, v3MigratorAbi, v4MigratorAbi, v4MulticurveInitializerAbi, v4MulticurveMigratorAbi, v4QuoterAbi, validateMarketCapParameters, weth9Abi };
19243
19425
  //# sourceMappingURL=index.js.map
19244
19426
  //# sourceMappingURL=index.js.map