@whetstone-research/doppler-sdk 1.0.26 → 1.0.28

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
@@ -1,5 +1,5 @@
1
1
  import '../chunk-PZ5AY32C.js';
2
- import { parseEther, formatEther, getAddress, encodeAbiParameters, keccak256, decodeAbiParameters, encodePacked, decodeEventLog, toHex, zeroAddress, zeroHash, encodeFunctionData, BaseError, ContractFunctionRevertedError, ContractFunctionZeroDataError, multicall3Abi, decodeFunctionResult, decodeErrorResult } from 'viem';
2
+ import { parseEther, formatEther, getAddress, encodeAbiParameters, keccak256, decodeAbiParameters, encodePacked, decodeEventLog, toHex, zeroAddress, zeroHash, encodeFunctionData, isAddress, BaseError, ContractFunctionRevertedError, ContractFunctionZeroDataError, isHex, multicall3Abi, decodeFunctionResult, decodeErrorResult } from 'viem';
3
3
 
4
4
  // src/evm/deployments.generated.ts
5
5
  var GENERATED_DOPPLER_DEPLOYMENTS = {
@@ -402,23 +402,23 @@ var DEFAULT_OPENING_DOPPLER_NUM_PD_SLUGS = DEFAULT_PD_SLUGS;
402
402
  var DEFAULT_OPENING_DOPPLER_FEE = FEE_TIERS.HIGH;
403
403
  var DEFAULT_OPENING_DOPPLER_TICK_SPACING = DOPPLER_MAX_TICK_SPACING;
404
404
  var DEFAULT_MULTICURVE_LOWER_TICKS = [
405
- -202100,
406
- -183100,
407
- -167e3
405
+ -887200,
406
+ -222200,
407
+ -176200
408
408
  ];
409
409
  var DEFAULT_MULTICURVE_UPPER_TICKS = [
410
- -188200,
411
- -172100,
412
- -156e3
410
+ -142200,
411
+ -116300,
412
+ -84100
413
413
  ];
414
414
  var DEFAULT_MULTICURVE_NUM_POSITIONS = [11, 11, 11];
415
415
  var DEFAULT_MULTICURVE_MAX_SUPPLY_SHARES = [
416
- parseEther("0.05"),
417
- // 5% for LOW tier
418
- parseEther("0.125"),
419
- // 12.5% for MEDIUM tier
420
- parseEther("0.2")
421
- // 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
422
422
  ];
423
423
  var BASIS_POINTS = 1e4;
424
424
  var FLAG_MASK = BigInt(16383);
@@ -462,7 +462,7 @@ var CHAIN_IDS = {
462
462
  BASE: 8453,
463
463
  BASE_SEPOLIA: 84532,
464
464
  INK: 57073,
465
- TEMP: 4663,
465
+ ROBINHOOD: 4663,
466
466
  UNICHAIN: 130,
467
467
  UNICHAIN_SEPOLIA: 1301,
468
468
  MONAD_TESTNET: 10143,
@@ -734,48 +734,50 @@ var ADDRESSES = {
734
734
  weth: "0x4200000000000000000000000000000000000006",
735
735
  uniswapV4Quoter: "0x3972c00f7ed4885e145823eb7c655375d275a1c5"
736
736
  },
737
- [CHAIN_IDS.TEMP]: {
738
- airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].Airlock,
737
+ [CHAIN_IDS.ROBINHOOD]: {
738
+ airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].Airlock,
739
739
  tokenFactory: ZERO_ADDRESS,
740
740
  dopplerERC20V1Factory: getGeneratedAddress(
741
- CHAIN_IDS.TEMP,
741
+ CHAIN_IDS.ROBINHOOD,
742
742
  "DopplerERC20V1Factory"
743
743
  ),
744
744
  dopplerERC20V1Implementation: getGeneratedAddress(
745
- CHAIN_IDS.TEMP,
745
+ CHAIN_IDS.ROBINHOOD,
746
746
  "DopplerERC20V1"
747
747
  ),
748
- doppler404Factory: getGeneratedAddress(CHAIN_IDS.TEMP, "DN404Factory"),
748
+ doppler404Factory: getGeneratedAddress(CHAIN_IDS.ROBINHOOD, "DN404Factory"),
749
749
  v3Initializer: ZERO_ADDRESS,
750
750
  v3Quoter: "0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7",
751
- lockableV3Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].LockableUniswapV3Initializer,
752
- v4Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].UniswapV4Initializer,
753
- dopplerHookInitializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].DopplerHookInitializer,
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
754
  rehypeDopplerHookInitializer: getRehypeDopplerHookInitializerAddress(
755
- CHAIN_IDS.TEMP
755
+ CHAIN_IDS.ROBINHOOD
756
756
  ),
757
- rehypeDopplerHook: getRehypeDopplerHookInitializerAddress(CHAIN_IDS.TEMP),
758
- dopplerLens: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].DopplerLensQuoter,
759
- dopplerDeployer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].DopplerDeployer,
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,
760
762
  poolManager: "0x8366a39cc670b4001a1121b8f6a443a643e40951",
761
763
  v2Migrator: ZERO_ADDRESS,
762
- v2MigratorSplit: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].UniswapV2MigratorSplit,
764
+ v2MigratorSplit: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].UniswapV2MigratorSplit,
763
765
  v4Migrator: ZERO_ADDRESS,
764
- dopplerHookMigrator: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].DopplerHookMigrator,
765
- rehypeDopplerHookMigrator: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].RehypeDopplerHookMigrator,
766
- noOpMigrator: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].NoOpMigrator,
767
- governanceFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].GovernanceFactory,
768
- noOpGovernanceFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].NoOpGovernanceFactory,
769
- launchpadGovernanceFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].LaunchpadGovernanceFactory,
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,
770
772
  streamableFeesLocker: ZERO_ADDRESS,
771
773
  streamableFeesLockerV2: getGeneratedAddress(
772
- CHAIN_IDS.TEMP,
774
+ CHAIN_IDS.ROBINHOOD,
773
775
  "StreamableFeesLockerV2"
774
776
  ),
775
- topUpDistributor: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].TopUpDistributor,
777
+ topUpDistributor: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].TopUpDistributor,
776
778
  universalRouter: "0x8876789976decbfcbbbe364623c63652db8c0904",
777
779
  permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
778
- bundler: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.TEMP].Bundler,
780
+ bundler: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].Bundler,
779
781
  weth: "0x0bd7d308f8e1639fab988df18a8011f41eacad73",
780
782
  uniswapV2Factory: "0x8bceaa40b9acdfaedf85adf4ff01f5ad6517937f",
781
783
  uniswapV3Factory: "0x1f7d7550b1b028f7571e69a784071f0205fd2efa",
@@ -6673,6 +6675,92 @@ function getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1) {
6673
6675
  return amount1 * Q96 / diff;
6674
6676
  }
6675
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
+
6676
6764
  // src/evm/utils/computeOptimalGamma.ts
6677
6765
  function computeOptimalGamma(startTick, endTick, duration, epochLength, tickSpacing) {
6678
6766
  const totalEpochs = duration / epochLength;
@@ -6689,11 +6777,14 @@ function computeOptimalGamma(startTick, endTick, duration, epochLength, tickSpac
6689
6777
 
6690
6778
  // src/evm/utils/gasEstimate.ts
6691
6779
  async function resolveGasEstimate(request, fallback) {
6692
- if (typeof request?.gas === "bigint") {
6780
+ if (isGasEstimateRequest(request)) {
6693
6781
  return request.gas;
6694
6782
  }
6695
6783
  return await fallback();
6696
6784
  }
6785
+ function isGasEstimateRequest(request) {
6786
+ return typeof request === "object" && request !== null && "gas" in request && typeof request.gas === "bigint";
6787
+ }
6697
6788
 
6698
6789
  // src/evm/utils/isToken0Expected.ts
6699
6790
  function isToken0Expected(numeraire) {
@@ -6708,6 +6799,23 @@ function isToken0Expected(numeraire) {
6708
6799
  }
6709
6800
  }
6710
6801
 
6802
+ // src/evm/utils/beneficiaries.ts
6803
+ function sortBeneficiaries(beneficiaries) {
6804
+ const sorted = [...beneficiaries].sort((a, b) => {
6805
+ const aAddr = a.beneficiary.toLowerCase();
6806
+ const bAddr = b.beneficiary.toLowerCase();
6807
+ return aAddr < bAddr ? -1 : aAddr > bAddr ? 1 : 0;
6808
+ });
6809
+ for (let i = 1; i < sorted.length; i++) {
6810
+ if (sorted[i].beneficiary.toLowerCase() === sorted[i - 1].beneficiary.toLowerCase()) {
6811
+ throw new Error(
6812
+ `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.`
6813
+ );
6814
+ }
6815
+ }
6816
+ return sorted;
6817
+ }
6818
+
6711
6819
  // src/evm/types.ts
6712
6820
  var NO_OP_ENABLED_CHAIN_IDS = [
6713
6821
  CHAIN_IDS.MAINNET,
@@ -6716,7 +6824,7 @@ var NO_OP_ENABLED_CHAIN_IDS = [
6716
6824
  CHAIN_IDS.BASE_SEPOLIA,
6717
6825
  CHAIN_IDS.UNICHAIN,
6718
6826
  CHAIN_IDS.UNICHAIN_SEPOLIA,
6719
- CHAIN_IDS.TEMP,
6827
+ CHAIN_IDS.ROBINHOOD,
6720
6828
  CHAIN_IDS.MONAD_TESTNET,
6721
6829
  CHAIN_IDS.MONAD_MAINNET
6722
6830
  ];
@@ -6727,7 +6835,7 @@ var LAUNCHPAD_ENABLED_CHAIN_IDS = [
6727
6835
  CHAIN_IDS.MAINNET,
6728
6836
  CHAIN_IDS.BASE,
6729
6837
  CHAIN_IDS.BASE_SEPOLIA,
6730
- CHAIN_IDS.TEMP,
6838
+ CHAIN_IDS.ROBINHOOD,
6731
6839
  CHAIN_IDS.MONAD_MAINNET
6732
6840
  ];
6733
6841
  function isLaunchpadEnabledChain(chainId) {
@@ -7312,7 +7420,7 @@ function buildCurvesFromPresets(params) {
7312
7420
  }
7313
7421
 
7314
7422
  // src/evm/entities/DopplerFactory.ts
7315
- var MAX_UINT128 = (1n << 128n) - 1n;
7423
+ var MAX_UINT1282 = (1n << 128n) - 1n;
7316
7424
  var MAX_PROCEEDS_SPLIT_SHARE = WAD / 2n;
7317
7425
  var DERC20_V1_MAX_PREMINT_WAD = WAD * 8n / 10n;
7318
7426
  var ONE_MILLION = 1000000n;
@@ -8008,11 +8116,7 @@ var DopplerFactory = class {
8008
8116
  const hasBeneficiaries = params.pool.beneficiaries && params.pool.beneficiaries.length > 0;
8009
8117
  let poolInitializerData;
8010
8118
  if (hasBeneficiaries) {
8011
- const sortedBeneficiaries = params.pool.beneficiaries.slice().sort((a, b) => {
8012
- const aAddr = a.beneficiary.toLowerCase();
8013
- const bAddr = b.beneficiary.toLowerCase();
8014
- return aAddr < bAddr ? -1 : aAddr > bAddr ? 1 : 0;
8015
- });
8119
+ const sortedBeneficiaries = sortBeneficiaries(params.pool.beneficiaries);
8016
8120
  poolInitializerData = encodeAbiParameters(
8017
8121
  [
8018
8122
  {
@@ -8092,14 +8196,20 @@ var DopplerFactory = class {
8092
8196
  const poolInitializerAddress = (() => {
8093
8197
  if (hasBeneficiaries) {
8094
8198
  const lockableInitializer = params.modules?.lockableV3Initializer ?? addresses.lockableV3Initializer;
8095
- if (!lockableInitializer) {
8199
+ if (!lockableInitializer || lockableInitializer === ZERO_ADDRESS) {
8096
8200
  throw new Error(
8097
8201
  "Lockable V3 initializer address not configured on this chain. Required when using beneficiaries."
8098
8202
  );
8099
8203
  }
8100
8204
  return lockableInitializer;
8101
8205
  }
8102
- return params.modules?.v3Initializer ?? addresses.v3Initializer;
8206
+ const standardInitializer = params.modules?.v3Initializer ?? addresses.v3Initializer;
8207
+ if (!standardInitializer || standardInitializer === ZERO_ADDRESS) {
8208
+ throw new Error(
8209
+ "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."
8210
+ );
8211
+ }
8212
+ return standardInitializer;
8103
8213
  })();
8104
8214
  const liquidityMigratorAddress = this.getMigratorAddress(
8105
8215
  params.migration,
@@ -8514,6 +8624,11 @@ var DopplerFactory = class {
8514
8624
  addresses
8515
8625
  });
8516
8626
  const poolInitializerAddress = params.modules?.v4Initializer ?? addresses.v4Initializer;
8627
+ if (!poolInitializerAddress || poolInitializerAddress === ZERO_ADDRESS) {
8628
+ throw new Error(
8629
+ "UniswapV4Initializer address not configured on this chain. Provide an override via builder.withV4Initializer(...) or use a chain with dynamic auction support."
8630
+ );
8631
+ }
8517
8632
  const liquidityMigratorAddress = this.getMigratorAddress(
8518
8633
  params.migration,
8519
8634
  params.modules
@@ -9844,13 +9959,7 @@ var DopplerFactory = class {
9844
9959
  if (!streamableFees) {
9845
9960
  return "0x";
9846
9961
  }
9847
- const beneficiaryData = [...streamableFees.beneficiaries].sort(
9848
- (a, b) => {
9849
- const addrA = a.beneficiary.toLowerCase();
9850
- const addrB = b.beneficiary.toLowerCase();
9851
- return addrA < addrB ? -1 : addrA > addrB ? 1 : 0;
9852
- }
9853
- );
9962
+ const beneficiaryData = sortBeneficiaries(streamableFees.beneficiaries);
9854
9963
  return encodeAbiParameters(
9855
9964
  [
9856
9965
  { type: "uint24" },
@@ -9875,12 +9984,8 @@ var DopplerFactory = class {
9875
9984
  ]
9876
9985
  );
9877
9986
  case "uniswapV4Split": {
9878
- const beneficiaryData2 = [...config.streamableFees.beneficiaries].sort(
9879
- (a, b) => {
9880
- const addrA = a.beneficiary.toLowerCase();
9881
- const addrB = b.beneficiary.toLowerCase();
9882
- return addrA < addrB ? -1 : addrA > addrB ? 1 : 0;
9883
- }
9987
+ const beneficiaryData2 = sortBeneficiaries(
9988
+ config.streamableFees.beneficiaries
9884
9989
  );
9885
9990
  const proceedsRecipient = config.proceedsSplit?.recipient ?? ZERO_ADDRESS;
9886
9991
  const proceedsShare = config.proceedsSplit?.share ?? 0n;
@@ -9916,12 +10021,8 @@ var DopplerFactory = class {
9916
10021
  "dopplerHook migration cannot set both hook and rehype config. Use exactly one hook mode."
9917
10022
  );
9918
10023
  }
9919
- const beneficiaries = [...dopplerHookConfig.beneficiaries].sort(
9920
- (a, b) => {
9921
- const addrA = a.beneficiary.toLowerCase();
9922
- const addrB = b.beneficiary.toLowerCase();
9923
- return addrA < addrB ? -1 : addrA > addrB ? 1 : 0;
9924
- }
10024
+ const beneficiaries = sortBeneficiaries(
10025
+ dopplerHookConfig.beneficiaries
9925
10026
  );
9926
10027
  let dopplerHookAddress = ZERO_ADDRESS;
9927
10028
  let onInitializationCalldata = "0x";
@@ -10324,15 +10425,12 @@ var DopplerFactory = class {
10324
10425
  }
10325
10426
  const normalizedCurves = this.normalizeMulticurveCurves(
10326
10427
  params.pool.curves,
10327
- params.pool.tickSpacing
10428
+ params.pool.tickSpacing,
10429
+ params.sale.numTokensToSell
10328
10430
  );
10329
10431
  const addresses = getAddresses(this.chainId);
10330
- const sortedBeneficiaries = (params.pool.beneficiaries ?? []).slice().sort(
10331
- (a, b) => {
10332
- const aAddr = a.beneficiary.toLowerCase();
10333
- const bAddr = b.beneficiary.toLowerCase();
10334
- return aAddr < bAddr ? -1 : aAddr > bAddr ? 1 : 0;
10335
- }
10432
+ const sortedBeneficiaries = sortBeneficiaries(
10433
+ params.pool.beneficiaries ?? []
10336
10434
  );
10337
10435
  const initializerMode = this.resolveMulticurveInitializerMode(params);
10338
10436
  const useScheduledInitializer = initializerMode.type === "scheduled";
@@ -10807,7 +10905,7 @@ var DopplerFactory = class {
10807
10905
  /**
10808
10906
  * Normalize user-provided multicurve positions and ensure they satisfy SDK constraints
10809
10907
  */
10810
- normalizeMulticurveCurves(curves, tickSpacing) {
10908
+ normalizeMulticurveCurves(curves, tickSpacing, numTokensToSell) {
10811
10909
  if (tickSpacing <= 0) {
10812
10910
  throw new Error("Tick spacing must be positive");
10813
10911
  }
@@ -10854,25 +10952,19 @@ var DopplerFactory = class {
10854
10952
  if (fallbackTickLower === void 0) {
10855
10953
  throw new Error("Unable to determine fallback multicurve tick range");
10856
10954
  }
10857
- const fallbackTickUpper = this.roundMaxTickDown(tickSpacing);
10858
- if (fallbackTickLower >= fallbackTickUpper) {
10859
- const adjustedLower = fallbackTickUpper - tickSpacing;
10860
- if (adjustedLower < fallbackTickLower) {
10861
- return sanitizedCurves;
10862
- }
10863
- const fallbackCurve2 = {
10864
- tickLower: adjustedLower,
10865
- tickUpper: fallbackTickUpper,
10866
- numPositions: sanitizedCurves[sanitizedCurves.length - 1]?.numPositions ?? 1,
10867
- shares: missingShare
10868
- };
10869
- return [...sanitizedCurves, fallbackCurve2];
10870
- }
10955
+ const fallbackNumPositions = sanitizedCurves[sanitizedCurves.length - 1]?.numPositions ?? 1;
10956
+ const fallbackTickUpper = getMaxLiquiditySafeMulticurveTickUpper({
10957
+ tickLower: fallbackTickLower,
10958
+ tickUpper: this.roundMaxTickDown(tickSpacing),
10959
+ tickSpacing,
10960
+ numPositions: fallbackNumPositions,
10961
+ curveSupply: numTokensToSell * missingShare / WAD
10962
+ });
10871
10963
  const fallbackCurve = {
10872
10964
  // Extend from the most positive user tick out to the maximum supported tick bucket
10873
10965
  tickLower: fallbackTickLower,
10874
10966
  tickUpper: fallbackTickUpper,
10875
- numPositions: sanitizedCurves[sanitizedCurves.length - 1]?.numPositions ?? 1,
10967
+ numPositions: fallbackNumPositions,
10876
10968
  shares: missingShare
10877
10969
  };
10878
10970
  return [...sanitizedCurves, fallbackCurve];
@@ -11392,8 +11484,15 @@ var DopplerFactory = class {
11392
11484
  getMigratorAddress(config, overrides) {
11393
11485
  const addresses = getAddresses(this.chainId);
11394
11486
  switch (config.type) {
11395
- case "uniswapV2":
11396
- return overrides?.v2Migrator ?? addresses.v2Migrator;
11487
+ case "uniswapV2": {
11488
+ const v2Address = overrides?.v2Migrator ?? addresses.v2Migrator;
11489
+ if (!v2Address || v2Address === ZERO_ADDRESS) {
11490
+ throw new Error(
11491
+ "UniswapV2Migrator not deployed on this chain. Use uniswapV2Split migration or provide override via modules.v2Migrator."
11492
+ );
11493
+ }
11494
+ return v2Address;
11495
+ }
11397
11496
  case "uniswapV2Split": {
11398
11497
  const v2SplitAddress = overrides?.v2MigratorSplit ?? addresses.v2MigratorSplit;
11399
11498
  if (!v2SplitAddress || v2SplitAddress === ZERO_ADDRESS) {
@@ -11405,7 +11504,7 @@ var DopplerFactory = class {
11405
11504
  }
11406
11505
  case "uniswapV4": {
11407
11506
  const v4Address = overrides?.v4Migrator ?? addresses.v4Migrator;
11408
- if (v4Address === "0x0000000000000000000000000000000000000000") {
11507
+ if (!v4Address || v4Address === ZERO_ADDRESS) {
11409
11508
  throw new Error(
11410
11509
  "UniswapV4Migrator not deployed on this chain. Use uniswapV2 migration or provide override via modules.v4Migrator."
11411
11510
  );
@@ -11571,7 +11670,7 @@ var DopplerFactory = class {
11571
11670
  if (!allowZero && value === 0n) {
11572
11671
  throw new Error(`${paramName} must be greater than zero`);
11573
11672
  }
11574
- if (value > MAX_UINT128) {
11673
+ if (value > MAX_UINT1282) {
11575
11674
  throw new Error(`${paramName} exceeds uint128 range`);
11576
11675
  }
11577
11676
  }
@@ -12030,6 +12129,214 @@ var DopplerFactory = class {
12030
12129
  }
12031
12130
  };
12032
12131
  var MULTICURVE_BUNDLER_SELECTORS = ["0xe2e9faa1", "0x07087b06"];
12132
+ function parseAirlockPoolOrHook(rawAssetData, context = "Airlock getAssetData") {
12133
+ const rawPoolOrHook = readContractResultField(
12134
+ rawAssetData,
12135
+ ["poolOrHook", "pool"],
12136
+ 5,
12137
+ context
12138
+ );
12139
+ return parseAddress(rawPoolOrHook, context, "poolOrHook");
12140
+ }
12141
+ function parseAirlockLiquidityMigrator(rawAssetData, context = "Airlock getAssetData") {
12142
+ const rawLiquidityMigrator = readContractResultField(
12143
+ rawAssetData,
12144
+ ["liquidityMigrator"],
12145
+ 3,
12146
+ context
12147
+ );
12148
+ return parseAddress(rawLiquidityMigrator, context, "liquidityMigrator");
12149
+ }
12150
+ function normalizeDynamicHookState(rawState, context = "DopplerHook state") {
12151
+ return {
12152
+ totalTokensSold: parseBigIntField(rawState, "totalTokensSold", 2, context),
12153
+ totalProceeds: parseBigIntField(rawState, "totalProceeds", 3, context)
12154
+ };
12155
+ }
12156
+ function normalizeRehypeFeeDistributionInfo(rawInfo, context = "Rehype getFeeDistributionInfo") {
12157
+ return {
12158
+ assetFeesToAssetBuybackWad: parseBigIntField(
12159
+ rawInfo,
12160
+ "assetFeesToAssetBuybackWad",
12161
+ 0,
12162
+ context
12163
+ ),
12164
+ assetFeesToNumeraireBuybackWad: parseBigIntField(
12165
+ rawInfo,
12166
+ "assetFeesToNumeraireBuybackWad",
12167
+ 1,
12168
+ context
12169
+ ),
12170
+ assetFeesToBeneficiaryWad: parseBigIntField(
12171
+ rawInfo,
12172
+ "assetFeesToBeneficiaryWad",
12173
+ 2,
12174
+ context
12175
+ ),
12176
+ assetFeesToLpWad: parseBigIntField(rawInfo, "assetFeesToLpWad", 3, context),
12177
+ numeraireFeesToAssetBuybackWad: parseBigIntField(
12178
+ rawInfo,
12179
+ "numeraireFeesToAssetBuybackWad",
12180
+ 4,
12181
+ context
12182
+ ),
12183
+ numeraireFeesToNumeraireBuybackWad: parseBigIntField(
12184
+ rawInfo,
12185
+ "numeraireFeesToNumeraireBuybackWad",
12186
+ 5,
12187
+ context
12188
+ ),
12189
+ numeraireFeesToBeneficiaryWad: parseBigIntField(
12190
+ rawInfo,
12191
+ "numeraireFeesToBeneficiaryWad",
12192
+ 6,
12193
+ context
12194
+ ),
12195
+ numeraireFeesToLpWad: parseBigIntField(
12196
+ rawInfo,
12197
+ "numeraireFeesToLpWad",
12198
+ 7,
12199
+ context
12200
+ )
12201
+ };
12202
+ }
12203
+ function normalizeRehypeFeeSchedule(rawSchedule, context = "Rehype getFeeSchedule") {
12204
+ return {
12205
+ startingTime: parseNumberField(rawSchedule, "startingTime", 0, context),
12206
+ startFee: parseNumberField(rawSchedule, "startFee", 1, context),
12207
+ endFee: parseNumberField(rawSchedule, "endFee", 2, context),
12208
+ lastFee: parseNumberField(rawSchedule, "lastFee", 3, context),
12209
+ durationSeconds: parseNumberField(
12210
+ rawSchedule,
12211
+ "durationSeconds",
12212
+ 4,
12213
+ context
12214
+ )
12215
+ };
12216
+ }
12217
+ function normalizeRehypeHookFees(rawFees, context = "Rehype getHookFees") {
12218
+ return {
12219
+ fees0: parseBigIntField(rawFees, "fees0", 0, context),
12220
+ fees1: parseBigIntField(rawFees, "fees1", 1, context),
12221
+ beneficiaryFees0: parseBigIntField(rawFees, "beneficiaryFees0", 2, context),
12222
+ beneficiaryFees1: parseBigIntField(rawFees, "beneficiaryFees1", 3, context),
12223
+ airlockOwnerFees0: parseBigIntField(
12224
+ rawFees,
12225
+ "airlockOwnerFees0",
12226
+ 4,
12227
+ context
12228
+ ),
12229
+ airlockOwnerFees1: parseBigIntField(
12230
+ rawFees,
12231
+ "airlockOwnerFees1",
12232
+ 5,
12233
+ context
12234
+ ),
12235
+ customFee: parseNumberField(rawFees, "customFee", 6, context)
12236
+ };
12237
+ }
12238
+ function normalizeRehypePoolInfo(rawInfo, context = "Rehype getPoolInfo") {
12239
+ return {
12240
+ asset: parseAddressField(rawInfo, "asset", 0, context),
12241
+ numeraire: parseAddressField(rawInfo, "numeraire", 1, context),
12242
+ buybackDst: parseAddressField(rawInfo, "buybackDst", 2, context)
12243
+ };
12244
+ }
12245
+ function normalizeRehypePosition(rawPosition, context = "Rehype getPosition") {
12246
+ return {
12247
+ tickLower: parseNumberField(rawPosition, "tickLower", 0, context),
12248
+ tickUpper: parseNumberField(rawPosition, "tickUpper", 1, context),
12249
+ liquidity: parseBigIntField(rawPosition, "liquidity", 2, context),
12250
+ salt: parseHexField(rawPosition, "salt", 3, context)
12251
+ };
12252
+ }
12253
+ function parseAddressField(rawResult, fieldName, tupleIndex, context) {
12254
+ const rawField = readContractResultField(
12255
+ rawResult,
12256
+ [fieldName],
12257
+ tupleIndex,
12258
+ context
12259
+ );
12260
+ return parseAddress(rawField, context, fieldName);
12261
+ }
12262
+ function parseBigIntField(rawResult, fieldName, tupleIndex, context) {
12263
+ const rawField = readContractResultField(
12264
+ rawResult,
12265
+ [fieldName],
12266
+ tupleIndex,
12267
+ context
12268
+ );
12269
+ if (typeof rawField === "bigint") {
12270
+ return rawField;
12271
+ }
12272
+ if (typeof rawField === "number" && Number.isSafeInteger(rawField)) {
12273
+ return BigInt(rawField);
12274
+ }
12275
+ if (typeof rawField === "string" && rawField.trim() !== "") {
12276
+ try {
12277
+ return BigInt(rawField);
12278
+ } catch {
12279
+ throw new Error(`${context}: ${fieldName} must be bigint-compatible`);
12280
+ }
12281
+ }
12282
+ throw new Error(`${context}: ${fieldName} must be bigint-compatible`);
12283
+ }
12284
+ function parseNumberField(rawResult, fieldName, tupleIndex, context) {
12285
+ const rawField = readContractResultField(
12286
+ rawResult,
12287
+ [fieldName],
12288
+ tupleIndex,
12289
+ context
12290
+ );
12291
+ const numericField = typeof rawField === "bigint" || typeof rawField === "number" ? Number(rawField) : Number.NaN;
12292
+ if (!Number.isSafeInteger(numericField)) {
12293
+ throw new Error(`${context}: ${fieldName} must be a safe integer`);
12294
+ }
12295
+ return numericField;
12296
+ }
12297
+ function parseHexField(rawResult, fieldName, tupleIndex, context) {
12298
+ const rawField = readContractResultField(
12299
+ rawResult,
12300
+ [fieldName],
12301
+ tupleIndex,
12302
+ context
12303
+ );
12304
+ if (typeof rawField === "string" && isHex(rawField)) {
12305
+ return rawField;
12306
+ }
12307
+ throw new Error(`${context}: ${fieldName} must be hex`);
12308
+ }
12309
+ function parseAddress(rawField, context, fieldName) {
12310
+ if (typeof rawField === "string" && isAddress(rawField, { strict: false })) {
12311
+ return rawField;
12312
+ }
12313
+ throw new Error(`${context}: ${fieldName} must be an address`);
12314
+ }
12315
+ function readContractResultField(rawResult, fieldNames, tupleIndex, context) {
12316
+ if (Array.isArray(rawResult)) {
12317
+ if (tupleIndex < rawResult.length && rawResult[tupleIndex] !== void 0) {
12318
+ return rawResult[tupleIndex];
12319
+ }
12320
+ throw new Error(
12321
+ `${context}: missing tuple field ${fieldNames.join("/")} at index ${tupleIndex}`
12322
+ );
12323
+ }
12324
+ if (isRecord(rawResult)) {
12325
+ for (const fieldName of fieldNames) {
12326
+ const rawField = rawResult[fieldName];
12327
+ if (rawField !== void 0) {
12328
+ return rawField;
12329
+ }
12330
+ }
12331
+ throw new Error(`${context}: missing field ${fieldNames.join("/")}`);
12332
+ }
12333
+ throw new Error(`${context}: expected tuple or object result`);
12334
+ }
12335
+ function isRecord(rawResult) {
12336
+ return typeof rawResult === "object" && rawResult !== null;
12337
+ }
12338
+
12339
+ // src/evm/entities/auction/StaticAuction.ts
12033
12340
  var StaticAuction = class {
12034
12341
  client;
12035
12342
  poolAddress;
@@ -12085,13 +12392,7 @@ var StaticAuction = class {
12085
12392
  functionName: "getAssetData",
12086
12393
  args: [token0]
12087
12394
  });
12088
- let poolOrHook0;
12089
- if (Array.isArray(assetData)) {
12090
- poolOrHook0 = assetData[5];
12091
- } else if (assetData && typeof assetData === "object") {
12092
- poolOrHook0 = assetData.poolOrHook ?? assetData.pool;
12093
- }
12094
- const isToken0AuctionToken = poolOrHook0 && poolOrHook0 !== zeroAddress;
12395
+ const isToken0AuctionToken = this.isRegisteredAirlockAsset(assetData);
12095
12396
  return {
12096
12397
  address: this.poolAddress,
12097
12398
  tokenAddress: isToken0AuctionToken ? token0 : token1,
@@ -12122,7 +12423,7 @@ var StaticAuction = class {
12122
12423
  functionName: "getAssetData",
12123
12424
  args: [tokenAddress]
12124
12425
  });
12125
- const liquidityMigrator = Array.isArray(assetData) ? assetData[3] : assetData?.liquidityMigrator;
12426
+ const liquidityMigrator = parseAirlockLiquidityMigrator(assetData);
12126
12427
  return liquidityMigrator === zeroAddress;
12127
12428
  }
12128
12429
  /**
@@ -12131,18 +12432,11 @@ var StaticAuction = class {
12131
12432
  */
12132
12433
  async getCurrentPrice() {
12133
12434
  const poolInfo = await this.getPoolInfo();
12134
- const [token0] = await Promise.all([
12135
- this.rpc.readContract({
12136
- address: this.poolAddress,
12137
- abi: uniswapV3PoolAbi,
12138
- functionName: "token0"
12139
- }),
12140
- this.rpc.readContract({
12141
- address: this.poolAddress,
12142
- abi: uniswapV3PoolAbi,
12143
- functionName: "token1"
12144
- })
12145
- ]);
12435
+ const token0 = await this.rpc.readContract({
12436
+ address: this.poolAddress,
12437
+ abi: uniswapV3PoolAbi,
12438
+ functionName: "token0"
12439
+ });
12146
12440
  const sqrtPriceX96 = poolInfo.sqrtPriceX96;
12147
12441
  const Q962 = BigInt(2) ** BigInt(96);
12148
12442
  const sqrtPriceX96Squared = sqrtPriceX96 * sqrtPriceX96;
@@ -12164,6 +12458,13 @@ var StaticAuction = class {
12164
12458
  functionName: "liquidity"
12165
12459
  });
12166
12460
  }
12461
+ isRegisteredAirlockAsset(assetData) {
12462
+ try {
12463
+ return parseAirlockPoolOrHook(assetData) !== zeroAddress;
12464
+ } catch {
12465
+ return false;
12466
+ }
12467
+ }
12167
12468
  };
12168
12469
  var DynamicAuction = class {
12169
12470
  client;
@@ -12249,11 +12550,11 @@ var DynamicAuction = class {
12249
12550
  const currentTime = BigInt(Math.floor(Date.now() / 1e3));
12250
12551
  const elapsedTime = currentTime > startingTime ? currentTime - startingTime : BigInt(0);
12251
12552
  const currentEpoch = epochLength > 0n ? Number(elapsedTime / epochLength) : 0;
12252
- const poolKey = this.normalizePoolKey(poolKeyRaw);
12553
+ const poolKey = normalizePoolKey(poolKeyRaw);
12253
12554
  const isToken0 = poolKey.currency0 !== zeroAddress;
12254
12555
  const tokenAddress = isToken0 ? poolKey.currency0 : poolKey.currency1;
12255
12556
  const numeraireAddress = isToken0 ? poolKey.currency1 : poolKey.currency0;
12256
- const poolId = this.computePoolId(poolKey);
12557
+ const poolId = computePoolId(poolKey);
12257
12558
  return {
12258
12559
  hookAddress: this.hookAddress,
12259
12560
  tokenAddress,
@@ -12280,7 +12581,7 @@ var DynamicAuction = class {
12280
12581
  abi: dopplerHookAbi,
12281
12582
  functionName: "poolKey"
12282
12583
  });
12283
- const poolKey = this.normalizePoolKey(poolKeyRaw);
12584
+ const poolKey = normalizePoolKey(poolKeyRaw);
12284
12585
  const isToken0 = await this.rpc.readContract({
12285
12586
  address: this.hookAddress,
12286
12587
  abi: dopplerHookAbi,
@@ -12297,8 +12598,8 @@ var DynamicAuction = class {
12297
12598
  abi: dopplerHookAbi,
12298
12599
  functionName: "poolKey"
12299
12600
  });
12300
- const poolKey = this.normalizePoolKey(poolKeyRaw);
12301
- return this.computePoolId(poolKey);
12601
+ const poolKey = normalizePoolKey(poolKeyRaw);
12602
+ return computePoolId(poolKey);
12302
12603
  }
12303
12604
  /**
12304
12605
  * Check if the auction has graduated (ready for migration)
@@ -12313,7 +12614,7 @@ var DynamicAuction = class {
12313
12614
  functionName: "getAssetData",
12314
12615
  args: [tokenAddress]
12315
12616
  });
12316
- const liquidityMigrator = Array.isArray(assetData) ? assetData[3] : assetData?.liquidityMigrator;
12617
+ const liquidityMigrator = parseAirlockLiquidityMigrator(assetData);
12317
12618
  return liquidityMigrator === zeroAddress;
12318
12619
  }
12319
12620
  /**
@@ -12341,8 +12642,7 @@ var DynamicAuction = class {
12341
12642
  * Returns the current tick based on the epoch and gamma parameters
12342
12643
  */
12343
12644
  async getCurrentPrice() {
12344
- const [_state, startingTick, endingTick, gamma, startingTime, epochLength] = await Promise.all([
12345
- this.readHookState(),
12645
+ const [startingTick, endingTick, gamma, startingTime, epochLength] = await Promise.all([
12346
12646
  this.rpc.readContract({
12347
12647
  address: this.hookAddress,
12348
12648
  abi: dopplerHookAbi,
@@ -12394,64 +12694,13 @@ var DynamicAuction = class {
12394
12694
  functionName: "earlyExit"
12395
12695
  });
12396
12696
  }
12397
- /**
12398
- * Compute V4 pool ID from pool key components
12399
- */
12400
- computePoolId(poolKey) {
12401
- const encoded = encodeAbiParameters(
12402
- [
12403
- { type: "address" },
12404
- { type: "address" },
12405
- { type: "uint24" },
12406
- { type: "int24" },
12407
- { type: "address" }
12408
- ],
12409
- [
12410
- poolKey.currency0,
12411
- poolKey.currency1,
12412
- poolKey.fee,
12413
- poolKey.tickSpacing,
12414
- poolKey.hooks
12415
- ]
12416
- );
12417
- return keccak256(encoded);
12418
- }
12419
- /**
12420
- * Read hook state with backward-compatible decoding.
12421
- * Falls back to legacy state() ABI if the latest ABI fails to decode.
12422
- */
12423
12697
  async readHookState() {
12424
- const result = await this.rpc.readContract({
12698
+ const rawState = await this.rpc.readContract({
12425
12699
  address: this.hookAddress,
12426
12700
  abi: dopplerHookAbi,
12427
12701
  functionName: "state"
12428
12702
  });
12429
- if (Array.isArray(result)) {
12430
- const [
12431
- lastEpoch,
12432
- tickAccumulator,
12433
- totalTokensSold,
12434
- totalProceeds,
12435
- totalTokensSoldLastEpoch,
12436
- feesAccrued
12437
- ] = result;
12438
- return {
12439
- lastEpoch,
12440
- tickAccumulator,
12441
- totalTokensSold,
12442
- totalProceeds,
12443
- totalTokensSoldLastEpoch,
12444
- feesAccrued
12445
- };
12446
- }
12447
- return result;
12448
- }
12449
- normalizePoolKey(value) {
12450
- if (Array.isArray(value)) {
12451
- const [currency0, currency1, fee, tickSpacing, hooks] = value;
12452
- return { currency0, currency1, fee, tickSpacing, hooks };
12453
- }
12454
- return value;
12703
+ return normalizeDynamicHookState(rawState);
12455
12704
  }
12456
12705
  };
12457
12706
  var ABSENT_POOL_ERROR_ABI = [
@@ -13206,29 +13455,7 @@ var RehypeDopplerHook = class {
13206
13455
  functionName: "getFeeDistributionInfo",
13207
13456
  args: [poolId]
13208
13457
  });
13209
- const info = result;
13210
- return {
13211
- assetFeesToAssetBuybackWad: BigInt(
13212
- info.assetFeesToAssetBuybackWad ?? info[0]
13213
- ),
13214
- assetFeesToNumeraireBuybackWad: BigInt(
13215
- info.assetFeesToNumeraireBuybackWad ?? info[1]
13216
- ),
13217
- assetFeesToBeneficiaryWad: BigInt(
13218
- info.assetFeesToBeneficiaryWad ?? info[2]
13219
- ),
13220
- assetFeesToLpWad: BigInt(info.assetFeesToLpWad ?? info[3]),
13221
- numeraireFeesToAssetBuybackWad: BigInt(
13222
- info.numeraireFeesToAssetBuybackWad ?? info[4]
13223
- ),
13224
- numeraireFeesToNumeraireBuybackWad: BigInt(
13225
- info.numeraireFeesToNumeraireBuybackWad ?? info[5]
13226
- ),
13227
- numeraireFeesToBeneficiaryWad: BigInt(
13228
- info.numeraireFeesToBeneficiaryWad ?? info[6]
13229
- ),
13230
- numeraireFeesToLpWad: BigInt(info.numeraireFeesToLpWad ?? info[7])
13231
- };
13458
+ return normalizeRehypeFeeDistributionInfo(result);
13232
13459
  }
13233
13460
  async getFeeRoutingMode(poolId) {
13234
13461
  const mode = await this.rpc.readContract({
@@ -13246,14 +13473,7 @@ var RehypeDopplerHook = class {
13246
13473
  functionName: "getFeeSchedule",
13247
13474
  args: [poolId]
13248
13475
  });
13249
- const schedule = result;
13250
- return {
13251
- startingTime: Number(schedule.startingTime ?? schedule[0] ?? 0),
13252
- startFee: Number(schedule.startFee ?? schedule[1] ?? 0),
13253
- endFee: Number(schedule.endFee ?? schedule[2] ?? 0),
13254
- lastFee: Number(schedule.lastFee ?? schedule[3] ?? 0),
13255
- durationSeconds: Number(schedule.durationSeconds ?? schedule[4] ?? 0)
13256
- };
13476
+ return normalizeRehypeFeeSchedule(result);
13257
13477
  }
13258
13478
  async getHookFees(poolId) {
13259
13479
  const result = await this.rpc.readContract({
@@ -13262,16 +13482,7 @@ var RehypeDopplerHook = class {
13262
13482
  functionName: "getHookFees",
13263
13483
  args: [poolId]
13264
13484
  });
13265
- const fees = result;
13266
- return {
13267
- fees0: BigInt(fees.fees0 ?? fees[0] ?? 0),
13268
- fees1: BigInt(fees.fees1 ?? fees[1] ?? 0),
13269
- beneficiaryFees0: BigInt(fees.beneficiaryFees0 ?? fees[2] ?? 0),
13270
- beneficiaryFees1: BigInt(fees.beneficiaryFees1 ?? fees[3] ?? 0),
13271
- airlockOwnerFees0: BigInt(fees.airlockOwnerFees0 ?? fees[4] ?? 0),
13272
- airlockOwnerFees1: BigInt(fees.airlockOwnerFees1 ?? fees[5] ?? 0),
13273
- customFee: Number(fees.customFee ?? fees[6] ?? 0)
13274
- };
13485
+ return normalizeRehypeHookFees(result);
13275
13486
  }
13276
13487
  async getPoolInfo(poolId) {
13277
13488
  const result = await this.rpc.readContract({
@@ -13280,12 +13491,7 @@ var RehypeDopplerHook = class {
13280
13491
  functionName: "getPoolInfo",
13281
13492
  args: [poolId]
13282
13493
  });
13283
- const info = result;
13284
- return {
13285
- asset: info.asset ?? info[0],
13286
- numeraire: info.numeraire ?? info[1],
13287
- buybackDst: info.buybackDst ?? info[2]
13288
- };
13494
+ return normalizeRehypePoolInfo(result);
13289
13495
  }
13290
13496
  };
13291
13497
 
@@ -13373,29 +13579,7 @@ var RehypeDopplerHookMigrator = class {
13373
13579
  functionName: "getFeeDistributionInfo",
13374
13580
  args: [poolId]
13375
13581
  });
13376
- const info = result;
13377
- return {
13378
- assetFeesToAssetBuybackWad: BigInt(
13379
- info.assetFeesToAssetBuybackWad ?? info[0]
13380
- ),
13381
- assetFeesToNumeraireBuybackWad: BigInt(
13382
- info.assetFeesToNumeraireBuybackWad ?? info[1]
13383
- ),
13384
- assetFeesToBeneficiaryWad: BigInt(
13385
- info.assetFeesToBeneficiaryWad ?? info[2]
13386
- ),
13387
- assetFeesToLpWad: BigInt(info.assetFeesToLpWad ?? info[3]),
13388
- numeraireFeesToAssetBuybackWad: BigInt(
13389
- info.numeraireFeesToAssetBuybackWad ?? info[4]
13390
- ),
13391
- numeraireFeesToNumeraireBuybackWad: BigInt(
13392
- info.numeraireFeesToNumeraireBuybackWad ?? info[5]
13393
- ),
13394
- numeraireFeesToBeneficiaryWad: BigInt(
13395
- info.numeraireFeesToBeneficiaryWad ?? info[6]
13396
- ),
13397
- numeraireFeesToLpWad: BigInt(info.numeraireFeesToLpWad ?? info[7])
13398
- };
13582
+ return normalizeRehypeFeeDistributionInfo(result);
13399
13583
  }
13400
13584
  async getFeeRoutingMode(poolId) {
13401
13585
  const mode = await this.rpc.readContract({
@@ -13413,16 +13597,7 @@ var RehypeDopplerHookMigrator = class {
13413
13597
  functionName: "getHookFees",
13414
13598
  args: [poolId]
13415
13599
  });
13416
- const fees = result;
13417
- return {
13418
- fees0: BigInt(fees.fees0 ?? fees[0] ?? 0),
13419
- fees1: BigInt(fees.fees1 ?? fees[1] ?? 0),
13420
- beneficiaryFees0: BigInt(fees.beneficiaryFees0 ?? fees[2] ?? 0),
13421
- beneficiaryFees1: BigInt(fees.beneficiaryFees1 ?? fees[3] ?? 0),
13422
- airlockOwnerFees0: BigInt(fees.airlockOwnerFees0 ?? fees[4] ?? 0),
13423
- airlockOwnerFees1: BigInt(fees.airlockOwnerFees1 ?? fees[5] ?? 0),
13424
- customFee: Number(fees.customFee ?? fees[6] ?? 0)
13425
- };
13600
+ return normalizeRehypeHookFees(result);
13426
13601
  }
13427
13602
  async getPoolInfo(poolId) {
13428
13603
  const result = await this.rpc.readContract({
@@ -13431,12 +13606,7 @@ var RehypeDopplerHookMigrator = class {
13431
13606
  functionName: "getPoolInfo",
13432
13607
  args: [poolId]
13433
13608
  });
13434
- const info = result;
13435
- return {
13436
- asset: info.asset ?? info[0],
13437
- numeraire: info.numeraire ?? info[1],
13438
- buybackDst: info.buybackDst ?? info[2]
13439
- };
13609
+ return normalizeRehypePoolInfo(result);
13440
13610
  }
13441
13611
  async getPosition(poolId) {
13442
13612
  const result = await this.rpc.readContract({
@@ -13445,13 +13615,7 @@ var RehypeDopplerHookMigrator = class {
13445
13615
  functionName: "getPosition",
13446
13616
  args: [poolId]
13447
13617
  });
13448
- const position = result;
13449
- return {
13450
- tickLower: Number(position.tickLower ?? position[0] ?? 0),
13451
- tickUpper: Number(position.tickUpper ?? position[1] ?? 0),
13452
- liquidity: BigInt(position.liquidity ?? position[2] ?? 0),
13453
- salt: position.salt ?? position[3]
13454
- };
13618
+ return normalizeRehypePosition(result);
13455
13619
  }
13456
13620
  };
13457
13621
  var OpeningAuctionPositionManager = class _OpeningAuctionPositionManager {
@@ -18568,9 +18732,16 @@ var MulticurveBuilder = class _MulticurveBuilder {
18568
18732
  tokenDecimals: config.tokenDecimals ?? 18,
18569
18733
  numeraireDecimals: config.numeraireDecimals ?? 18
18570
18734
  });
18735
+ const curveSupply = this.sale.numTokensToSell * curve.shares / WAD;
18736
+ const tickUpper = curve.marketCap.end === "max" ? getMaxLiquiditySafeMulticurveTickUpper({
18737
+ ...curveTicks,
18738
+ tickSpacing,
18739
+ numPositions: curve.numPositions,
18740
+ curveSupply
18741
+ }) : curveTicks.tickUpper;
18571
18742
  curves.push({
18572
18743
  tickLower: curveTicks.tickLower,
18573
- tickUpper: curveTicks.tickUpper,
18744
+ tickUpper,
18574
18745
  numPositions: curve.numPositions,
18575
18746
  shares: curve.shares
18576
18747
  });
@@ -18631,7 +18802,7 @@ var MulticurveBuilder = class _MulticurveBuilder {
18631
18802
  }
18632
18803
  dopplerHook = { ...dopplerHook, farTick };
18633
18804
  }
18634
- const initializer = this.initializer ?? (dopplerHook ? { type: "rehype", config: dopplerHook } : this.schedule ? { type: "scheduled", startTime: this.schedule.startTime } : { type: "standard" });
18805
+ 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" });
18635
18806
  if (initializer.type === "scheduled" && dopplerHook) {
18636
18807
  throw new Error(
18637
18808
  "Cannot combine scheduled multicurve with rehype initializer. Use exactly one initializer mode."
@@ -19318,6 +19489,6 @@ var DopplerSDK = class {
19318
19489
  // src/evm/index.ts
19319
19490
  var VERSION = "1.0.0";
19320
19491
 
19321
- 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 };
19492
+ 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 };
19322
19493
  //# sourceMappingURL=index.js.map
19323
19494
  //# sourceMappingURL=index.js.map