@steerprotocol/sdk 3.7.2 → 3.7.4

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/index.cjs CHANGED
@@ -17327,58 +17327,420 @@ var SubgraphClient = class {
17327
17327
  }
17328
17328
  };
17329
17329
  //#endregion
17330
- //#region src/base/vault/utils.ts
17331
- const GLOBAL_STATE_ABI = [{
17332
- inputs: [],
17333
- name: "globalState",
17334
- outputs: [
17335
- {
17336
- internalType: "uint160",
17337
- name: "price",
17338
- type: "uint160"
17339
- },
17330
+ //#region src/pool-lifecycle/abis/v4.ts
17331
+ /** Minimal authoritative IPoolManager surface used by the V4 lifecycle adapter. */
17332
+ const v4PoolManagerAbi = (0, viem.parseAbi)(["function initialize((address currency0,address currency1,uint24 fee,int24 tickSpacing,address hooks) key, uint160 sqrtPriceX96) returns (int24 tick)", "event Initialize(bytes32 indexed id, address indexed currency0, address indexed currency1, uint24 fee, int24 tickSpacing, address hooks, uint160 sqrtPriceX96, int24 tick)"]);
17333
+ /** Minimal StateView/ImmutableState surface used for deployment and state checks. */
17334
+ const v4StateViewAbi = (0, viem.parseAbi)(["function poolManager() view returns (address)", "function getSlot0(bytes32 poolId) view returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee)"]);
17335
+ //#endregion
17336
+ //#region src/pool-lifecycle/math.ts
17337
+ /** The smallest sqrt price accepted by Uniswap TickMath, inclusive. */
17338
+ const MIN_SQRT_RATIO = 4295128739n;
17339
+ /** The largest TickMath sqrt-price boundary, which is not itself valid. */
17340
+ const MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342n;
17341
+ const ZERO_ADDRESS$3 = "0x0000000000000000000000000000000000000000";
17342
+ const MAX_ERC20_DECIMALS = 255;
17343
+ function greatestCommonDivisor(a, b) {
17344
+ let left = a;
17345
+ let right = b;
17346
+ while (right !== 0n) {
17347
+ const remainder = left % right;
17348
+ left = right;
17349
+ right = remainder;
17350
+ }
17351
+ return left;
17352
+ }
17353
+ function checksumAddress(value, label, allowZero) {
17354
+ if (typeof value !== "string" || !(0, viem.isAddress)(value, { strict: true })) throw new TypeError(`${label} must be a valid EVM address`);
17355
+ const address = (0, viem.getAddress)(value);
17356
+ if (!allowZero && address === ZERO_ADDRESS$3) throw new RangeError(`${label} must not be the zero address`);
17357
+ return address;
17358
+ }
17359
+ function assertErc20Decimals(value, label) {
17360
+ if (!Number.isSafeInteger(value) || value < 0 || value > MAX_ERC20_DECIMALS) throw new RangeError(`${label} must be an integer from 0 through 255`);
17361
+ }
17362
+ function assertPositiveFraction(value) {
17363
+ if (typeof value?.numerator !== "bigint" || typeof value?.denominator !== "bigint") throw new TypeError("quotePerBase must contain bigint numerator and denominator values");
17364
+ if (value.numerator <= 0n) throw new RangeError("quotePerBase numerator must be greater than zero");
17365
+ if (value.denominator <= 0n) throw new RangeError("quotePerBase denominator must be greater than zero");
17366
+ }
17367
+ /**
17368
+ * Parses an unsigned, fixed-point decimal string without converting through a
17369
+ * JavaScript number. Signs, exponent notation, whitespace, and omitted whole
17370
+ * or fractional digits are rejected. The returned fraction is reduced.
17371
+ */
17372
+ function parseExactDecimal(value) {
17373
+ if (typeof value !== "string") throw new TypeError("Decimal value must be provided as a string");
17374
+ const match = /^([0-9]+)(?:\.([0-9]+))?$/.exec(value);
17375
+ if (match === null || match[0] !== value) throw new TypeError("Decimal value must use unsigned fixed-point notation, for example \"123.45\"");
17376
+ const wholeDigits = match[1];
17377
+ const fractionalDigits = match[2] ?? "";
17378
+ const numerator = BigInt(`${wholeDigits}${fractionalDigits}`);
17379
+ if (numerator === 0n) return {
17380
+ numerator: 0n,
17381
+ denominator: 1n
17382
+ };
17383
+ const denominator = 10n ** BigInt(fractionalDigits.length);
17384
+ const divisor = greatestCommonDivisor(numerator, denominator);
17385
+ return {
17386
+ numerator: numerator / divisor,
17387
+ denominator: denominator / divisor
17388
+ };
17389
+ }
17390
+ /**
17391
+ * Validates, checksums, and sorts two distinct non-zero ERC20 addresses.
17392
+ */
17393
+ function sortErc20Pair(tokenA, tokenB) {
17394
+ const normalizedTokenA = checksumAddress(tokenA, "tokenA", false);
17395
+ const normalizedTokenB = checksumAddress(tokenB, "tokenB", false);
17396
+ if (normalizedTokenA === normalizedTokenB) throw new RangeError("ERC20 pair tokens must be different");
17397
+ return BigInt(normalizedTokenA) < BigInt(normalizedTokenB) ? {
17398
+ token0: normalizedTokenA,
17399
+ token1: normalizedTokenB
17400
+ } : {
17401
+ token0: normalizedTokenB,
17402
+ token1: normalizedTokenA
17403
+ };
17404
+ }
17405
+ /**
17406
+ * Validates, checksums, and sorts two distinct EVM currencies. The zero
17407
+ * address is allowed and, when present, necessarily sorts as currency0.
17408
+ */
17409
+ function sortEvmCurrencyPair(currencyA, currencyB) {
17410
+ const normalizedCurrencyA = checksumAddress(currencyA, "currencyA", true);
17411
+ const normalizedCurrencyB = checksumAddress(currencyB, "currencyB", true);
17412
+ if (normalizedCurrencyA === normalizedCurrencyB) throw new RangeError("EVM pair currencies must be different");
17413
+ return BigInt(normalizedCurrencyA) < BigInt(normalizedCurrencyB) ? {
17414
+ currency0: normalizedCurrencyA,
17415
+ currency1: normalizedCurrencyB
17416
+ } : {
17417
+ currency0: normalizedCurrencyB,
17418
+ currency1: normalizedCurrencyA
17419
+ };
17420
+ }
17421
+ /**
17422
+ * Returns floor(sqrt(value)) using bigint arithmetic only.
17423
+ */
17424
+ function integerSqrt(value) {
17425
+ if (typeof value !== "bigint") throw new TypeError("Square-root input must be a bigint");
17426
+ if (value < 0n) throw new RangeError("Square-root input must not be negative");
17427
+ if (value < 2n) return value;
17428
+ let estimate = value;
17429
+ let nextEstimate = estimate + 1n >> 1n;
17430
+ while (nextEstimate < estimate) {
17431
+ estimate = nextEstimate;
17432
+ nextEstimate = estimate + value / estimate >> 1n;
17433
+ }
17434
+ return estimate;
17435
+ }
17436
+ /**
17437
+ * Enforces the Uniswap TickMath interval: MIN is inclusive and MAX exclusive.
17438
+ * Returns the input so it can be composed with transaction builders.
17439
+ */
17440
+ function validateSqrtPriceX96(sqrtPriceX96) {
17441
+ if (typeof sqrtPriceX96 !== "bigint") throw new TypeError("sqrtPriceX96 must be a bigint");
17442
+ if (sqrtPriceX96 < 4295128739n || sqrtPriceX96 >= 1461446703485210103287273052203988822378723970342n) throw new RangeError(`sqrtPriceX96 must be in [${MIN_SQRT_RATIO}, ${MAX_SQRT_RATIO})`);
17443
+ return sqrtPriceX96;
17444
+ }
17445
+ /**
17446
+ * Encode an exact raw token1/token0 amount ratio without token metadata.
17447
+ * The result matches the canonical V3 floor-rounding operation.
17448
+ */
17449
+ function encodeSqrtRatioX96(amount1Raw, amount0Raw) {
17450
+ if (typeof amount0Raw !== "bigint" || typeof amount1Raw !== "bigint") throw new TypeError("Raw ratio amounts must be bigint values");
17451
+ if (amount0Raw <= 0n || amount1Raw <= 0n) throw new RangeError("Raw ratio amounts must be greater than zero");
17452
+ return validateSqrtPriceX96(integerSqrt((amount1Raw << 192n) / amount0Raw));
17453
+ }
17454
+ /**
17455
+ * Converts an exact quote-per-base human price into the canonical raw-token
17456
+ * ratio and sqrtPriceX96 expected by concentrated-liquidity initializers.
17457
+ *
17458
+ * Address sorting and reciprocal orientation happen before the only lossy
17459
+ * operation. The final encoding is exactly:
17460
+ *
17461
+ * floor(sqrt((amount1Raw << 192) / amount0Raw))
17462
+ */
17463
+ function encodeInitialSqrtPriceX96(price) {
17464
+ const pair = sortErc20Pair(price.baseToken, price.quoteToken);
17465
+ const baseToken = checksumAddress(price.baseToken, "baseToken", false);
17466
+ assertErc20Decimals(price.baseTokenDecimals, "baseTokenDecimals");
17467
+ assertErc20Decimals(price.quoteTokenDecimals, "quoteTokenDecimals");
17468
+ assertPositiveFraction(price.quotePerBase);
17469
+ const baseScale = 10n ** BigInt(price.baseTokenDecimals);
17470
+ const quoteScale = 10n ** BigInt(price.quoteTokenDecimals);
17471
+ const baseTokenIsToken0 = baseToken === pair.token0;
17472
+ const amount0Raw = baseTokenIsToken0 ? price.quotePerBase.denominator * baseScale : price.quotePerBase.numerator * quoteScale;
17473
+ const amount1Raw = baseTokenIsToken0 ? price.quotePerBase.numerator * quoteScale : price.quotePerBase.denominator * baseScale;
17474
+ const sqrtPriceX96 = encodeSqrtRatioX96(amount1Raw, amount0Raw);
17475
+ return {
17476
+ ...pair,
17477
+ amount0Raw,
17478
+ amount1Raw,
17479
+ sqrtPriceX96,
17480
+ baseTokenIsToken0
17481
+ };
17482
+ }
17483
+ /**
17484
+ * Currency-aware counterpart to {@link encodeInitialSqrtPriceX96}. It keeps
17485
+ * the same exact orientation and floor-rounding rules while permitting the
17486
+ * native zero-address currency required by Uniswap V4.
17487
+ */
17488
+ function encodeCurrencyInitialSqrtPriceX96(price) {
17489
+ const pair = sortEvmCurrencyPair(price.baseCurrency, price.quoteCurrency);
17490
+ const baseCurrency = checksumAddress(price.baseCurrency, "baseCurrency", true);
17491
+ assertErc20Decimals(price.baseCurrencyDecimals, "baseCurrencyDecimals");
17492
+ assertErc20Decimals(price.quoteCurrencyDecimals, "quoteCurrencyDecimals");
17493
+ assertPositiveFraction(price.quotePerBase);
17494
+ const baseScale = 10n ** BigInt(price.baseCurrencyDecimals);
17495
+ const quoteScale = 10n ** BigInt(price.quoteCurrencyDecimals);
17496
+ const baseCurrencyIsCurrency0 = baseCurrency === pair.currency0;
17497
+ const amount0Raw = baseCurrencyIsCurrency0 ? price.quotePerBase.denominator * baseScale : price.quotePerBase.numerator * quoteScale;
17498
+ const amount1Raw = baseCurrencyIsCurrency0 ? price.quotePerBase.numerator * quoteScale : price.quotePerBase.denominator * baseScale;
17499
+ return {
17500
+ ...pair,
17501
+ amount0Raw,
17502
+ amount1Raw,
17503
+ sqrtPriceX96: encodeSqrtRatioX96(amount1Raw, amount0Raw),
17504
+ baseCurrencyIsCurrency0
17505
+ };
17506
+ }
17507
+ //#endregion
17508
+ //#region src/pool-lifecycle/errors.ts
17509
+ /** Error thrown when a pool lifecycle primitive cannot safely continue. */
17510
+ var PoolLifecycleError = class extends Error {
17511
+ constructor(code, message, causeValue) {
17512
+ super(message);
17513
+ this.name = "PoolLifecycleError";
17514
+ this.code = code;
17515
+ this.causeValue = causeValue;
17516
+ }
17517
+ };
17518
+ //#endregion
17519
+ //#region src/pool-lifecycle/v4/key.ts
17520
+ const V4_DYNAMIC_FEE_FLAG = 8388608;
17521
+ const V4_MAX_STATIC_FEE = 1e6;
17522
+ const V4_MAX_TICK_SPACING = 32767;
17523
+ const V4_ALL_HOOK_MASK = (1n << 14n) - 1n;
17524
+ const V4_ZERO_ADDRESS = (0, viem.getAddress)("0x0000000000000000000000000000000000000000");
17525
+ const BEFORE_SWAP_FLAG = 1n << 7n;
17526
+ const AFTER_SWAP_FLAG = 1n << 6n;
17527
+ const AFTER_ADD_LIQUIDITY_FLAG = 1n << 10n;
17528
+ const AFTER_REMOVE_LIQUIDITY_FLAG = 1n << 8n;
17529
+ const BEFORE_SWAP_RETURNS_DELTA_FLAG = 1n << 3n;
17530
+ const AFTER_SWAP_RETURNS_DELTA_FLAG = 1n << 2n;
17531
+ const AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = 1n << 1n;
17532
+ const AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = 1n;
17533
+ const POOL_KEY_ABI_PARAMETER = {
17534
+ type: "tuple",
17535
+ components: [
17340
17536
  {
17341
- internalType: "int24",
17342
- name: "tick",
17343
- type: "int24"
17537
+ name: "currency0",
17538
+ type: "address"
17344
17539
  },
17345
17540
  {
17346
- internalType: "int24",
17347
- name: "prevInitializedTick",
17348
- type: "int24"
17541
+ name: "currency1",
17542
+ type: "address"
17349
17543
  },
17350
17544
  {
17351
- internalType: "uint16",
17352
17545
  name: "fee",
17353
- type: "uint16"
17354
- },
17355
- {
17356
- internalType: "uint16",
17357
- name: "timepointIndex",
17358
- type: "uint16"
17546
+ type: "uint24"
17359
17547
  },
17360
17548
  {
17361
- internalType: "uint8",
17362
- name: "communityFee",
17363
- type: "uint8"
17549
+ name: "tickSpacing",
17550
+ type: "int24"
17364
17551
  },
17365
17552
  {
17366
- internalType: "bool",
17367
- name: "unlocked",
17368
- type: "bool"
17553
+ name: "hooks",
17554
+ type: "address"
17369
17555
  }
17370
- ],
17371
- stateMutability: "view",
17372
- type: "function"
17373
- }];
17374
- const GLOBAL_STATE_ABI_INTEGRAL_V_1 = [{
17375
- inputs: [],
17376
- name: "globalState",
17377
- outputs: [
17378
- {
17379
- internalType: "uint160",
17380
- name: "price",
17381
- type: "uint160"
17556
+ ]
17557
+ };
17558
+ function invalidInput(message, cause) {
17559
+ throw new PoolLifecycleError("INVALID_INPUT", message, cause);
17560
+ }
17561
+ function normalizeAddress(value, label) {
17562
+ if (typeof value !== "string" || !(0, viem.isAddress)(value, { strict: true })) return invalidInput(`${label} must be a valid EVM address.`);
17563
+ return (0, viem.getAddress)(value);
17564
+ }
17565
+ function validateFee(fee) {
17566
+ if (!Number.isSafeInteger(fee) || Number(fee) < 0 || Number(fee) > 1e6 && Number(fee) !== 8388608) return invalidInput("V4 fee must be an integer from 0 through 1000000 or the dynamic fee flag 0x800000.");
17567
+ return Number(fee);
17568
+ }
17569
+ function validateTickSpacing(tickSpacing) {
17570
+ if (!Number.isSafeInteger(tickSpacing) || Number(tickSpacing) < 1 || Number(tickSpacing) > 32767) return invalidInput("V4 tickSpacing must be an integer from 1 through 32767.");
17571
+ return Number(tickSpacing);
17572
+ }
17573
+ function validateHookAddress(hooksAddress, fee) {
17574
+ const hooks = BigInt(hooksAddress);
17575
+ const hasFlag = (flag) => (hooks & flag) !== 0n;
17576
+ if (!hasFlag(BEFORE_SWAP_FLAG) && hasFlag(BEFORE_SWAP_RETURNS_DELTA_FLAG) || !hasFlag(AFTER_SWAP_FLAG) && hasFlag(AFTER_SWAP_RETURNS_DELTA_FLAG) || !hasFlag(AFTER_ADD_LIQUIDITY_FLAG) && hasFlag(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG) || !hasFlag(AFTER_REMOVE_LIQUIDITY_FLAG) && hasFlag(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)) invalidInput("V4 hook return-delta flags require their corresponding action flags.");
17577
+ const dynamicFee = fee === V4_DYNAMIC_FEE_FLAG;
17578
+ if (!(hooks === 0n ? !dynamicFee : (hooks & V4_ALL_HOOK_MASK) !== 0n || dynamicFee)) invalidInput("V4 hooks address is incompatible with its fee and permission flags.");
17579
+ }
17580
+ /** Validate a complete PoolKey whose currencies are already canonically ordered. */
17581
+ function validateV4PoolKey(value) {
17582
+ const currency0 = normalizeAddress(value?.currency0, "currency0");
17583
+ const currency1 = normalizeAddress(value?.currency1, "currency1");
17584
+ const fee = validateFee(value?.fee);
17585
+ const tickSpacing = validateTickSpacing(value?.tickSpacing);
17586
+ const hooks = normalizeAddress(value?.hooks, "hooks");
17587
+ if (BigInt(currency0) >= BigInt(currency1)) invalidInput("V4 currencies must be distinct and canonically ordered.");
17588
+ validateHookAddress(hooks, fee);
17589
+ return {
17590
+ currency0,
17591
+ currency1,
17592
+ fee,
17593
+ tickSpacing,
17594
+ hooks
17595
+ };
17596
+ }
17597
+ /**
17598
+ * Validate and sort two currencies. Address zero is deliberately accepted and
17599
+ * sorts first because V4 represents the native currency as address(0).
17600
+ */
17601
+ function canonicalizeV4PoolKey(value) {
17602
+ const currencyA = normalizeAddress(value?.currencyA, "currencyA");
17603
+ const currencyB = normalizeAddress(value?.currencyB, "currencyB");
17604
+ if (currencyA === currencyB) return invalidInput("V4 pool currencies must be different.");
17605
+ const [currency0, currency1] = BigInt(currencyA) < BigInt(currencyB) ? [currencyA, currencyB] : [currencyB, currencyA];
17606
+ return validateV4PoolKey({
17607
+ currency0,
17608
+ currency1,
17609
+ fee: value?.fee,
17610
+ tickSpacing: value?.tickSpacing,
17611
+ hooks: value?.hooks
17612
+ });
17613
+ }
17614
+ /** Return the exact PoolId used by PoolIdLibrary.toId. */
17615
+ function getV4PoolId(key) {
17616
+ const validated = validateV4PoolKey(key);
17617
+ return (0, viem.keccak256)((0, viem.encodeAbiParameters)([POOL_KEY_ABI_PARAMETER], [validated]));
17618
+ }
17619
+ function v4PoolKeysEqual(left, right) {
17620
+ try {
17621
+ const a = validateV4PoolKey(left);
17622
+ const b = validateV4PoolKey(right);
17623
+ return a.currency0 === b.currency0 && a.currency1 === b.currency1 && a.fee === b.fee && a.tickSpacing === b.tickSpacing && a.hooks === b.hooks;
17624
+ } catch {
17625
+ return false;
17626
+ }
17627
+ }
17628
+ /** Validate price bounds and bind the price to the canonical PoolKey order. */
17629
+ function assertV4InitialPrice(key, value) {
17630
+ const currency0 = normalizeAddress(value?.currency0, "initialPrice.currency0");
17631
+ const currency1 = normalizeAddress(value?.currency1, "initialPrice.currency1");
17632
+ if (currency0 !== key.currency0 || currency1 !== key.currency1) return invalidInput("V4 initial price currencies must match the canonical PoolKey order.");
17633
+ try {
17634
+ return {
17635
+ currency0,
17636
+ currency1,
17637
+ sqrtPriceX96: validateSqrtPriceX96(value?.sqrtPriceX96)
17638
+ };
17639
+ } catch (error) {
17640
+ return invalidInput(error instanceof Error ? error.message : "V4 sqrtPriceX96 is invalid.", error);
17641
+ }
17642
+ }
17643
+ //#endregion
17644
+ //#region src/base/vault/utils.ts
17645
+ function asV4Uint24(value, label) {
17646
+ if (typeof value !== "number" && typeof value !== "bigint" || !Number.isSafeInteger(Number(value)) || Number(value) < 0 || Number(value) > 16777215) throw new Error(`V4 StateView returned an invalid ${label}.`);
17647
+ return Number(value);
17648
+ }
17649
+ /** Read a V4 PoolId through its configured StateView at one block. */
17650
+ async function getV4PoolState(publicClient, params) {
17651
+ if (!/^0x[0-9a-fA-F]{64}$/.test(params.poolId)) throw new Error("V4 poolId must be a bytes32 hex value.");
17652
+ const chain = chainIdToName(params.chainId);
17653
+ const config = getAmmConfig("")[Protocol.UniswapV4];
17654
+ const manager = chain && config?.PoolManager?.[chain];
17655
+ const view = chain && config?.StateView?.[chain];
17656
+ if (!manager || !view || !(0, viem.isAddress)(manager) || !(0, viem.isAddress)(view)) throw new Error(`Uniswap V4 PoolManager or StateView is missing for chain ${params.chainId}.`);
17657
+ const actualChainId = await publicClient.getChainId();
17658
+ if (actualChainId !== params.chainId) throw new Error(`Public client chain ${actualChainId} does not match V4 chain ${params.chainId}.`);
17659
+ const blockNumber = params.blockNumber ?? await publicClient.getBlockNumber();
17660
+ if (typeof blockNumber !== "bigint" || blockNumber < 0n) throw new Error("V4 blockNumber must be a non-negative bigint.");
17661
+ const stateView = (0, viem.getAddress)(view);
17662
+ const [boundManager, slot0] = await Promise.all([publicClient.readContract({
17663
+ address: stateView,
17664
+ abi: v4StateViewAbi,
17665
+ functionName: "poolManager",
17666
+ blockNumber
17667
+ }), publicClient.readContract({
17668
+ address: stateView,
17669
+ abi: v4StateViewAbi,
17670
+ functionName: "getSlot0",
17671
+ args: [params.poolId],
17672
+ blockNumber
17673
+ })]);
17674
+ if ((0, viem.getAddress)(boundManager) !== (0, viem.getAddress)(manager)) throw new Error("Configured Uniswap V4 StateView is bound to a different PoolManager.");
17675
+ if (!Array.isArray(slot0) || slot0.length !== 4) throw new Error("V4 StateView returned malformed slot0 state.");
17676
+ const [sqrtPriceX96, rawTick, rawProtocolFee, rawLpFee] = slot0;
17677
+ if (typeof sqrtPriceX96 !== "bigint" || sqrtPriceX96 === 0n) throw new Error(sqrtPriceX96 === 0n ? "Uniswap V4 pool is not initialized." : "V4 StateView returned malformed sqrtPriceX96.");
17678
+ validateSqrtPriceX96(sqrtPriceX96);
17679
+ const tick = Number(rawTick);
17680
+ if (typeof rawTick !== "number" && typeof rawTick !== "bigint" || !Number.isSafeInteger(tick) || tick < -887272 || tick > 887272) throw new Error("V4 StateView returned an invalid tick.");
17681
+ const protocolFee = asV4Uint24(rawProtocolFee, "protocol fee");
17682
+ if (asV4Uint24(rawLpFee, "LP fee") > 1e6) throw new Error("V4 StateView returned an invalid LP fee.");
17683
+ return {
17684
+ sqrtPriceX96,
17685
+ tick,
17686
+ observationIndex: 0,
17687
+ observationCardinality: 0,
17688
+ observationCardinalityNext: 0,
17689
+ feeProtocol: protocolFee,
17690
+ unlocked: true
17691
+ };
17692
+ }
17693
+ const GLOBAL_STATE_ABI = [{
17694
+ inputs: [],
17695
+ name: "globalState",
17696
+ outputs: [
17697
+ {
17698
+ internalType: "uint160",
17699
+ name: "price",
17700
+ type: "uint160"
17701
+ },
17702
+ {
17703
+ internalType: "int24",
17704
+ name: "tick",
17705
+ type: "int24"
17706
+ },
17707
+ {
17708
+ internalType: "int24",
17709
+ name: "prevInitializedTick",
17710
+ type: "int24"
17711
+ },
17712
+ {
17713
+ internalType: "uint16",
17714
+ name: "fee",
17715
+ type: "uint16"
17716
+ },
17717
+ {
17718
+ internalType: "uint16",
17719
+ name: "timepointIndex",
17720
+ type: "uint16"
17721
+ },
17722
+ {
17723
+ internalType: "uint8",
17724
+ name: "communityFee",
17725
+ type: "uint8"
17726
+ },
17727
+ {
17728
+ internalType: "bool",
17729
+ name: "unlocked",
17730
+ type: "bool"
17731
+ }
17732
+ ],
17733
+ stateMutability: "view",
17734
+ type: "function"
17735
+ }];
17736
+ const GLOBAL_STATE_ABI_INTEGRAL_V_1 = [{
17737
+ inputs: [],
17738
+ name: "globalState",
17739
+ outputs: [
17740
+ {
17741
+ internalType: "uint160",
17742
+ name: "price",
17743
+ type: "uint160"
17382
17744
  },
17383
17745
  {
17384
17746
  internalType: "int24",
@@ -17965,10 +18327,23 @@ async function getGlobalStateAlgebraIntegral(publicClient, poolAddress, isDirect
17965
18327
  * poolAddress: '0x...',
17966
18328
  * isPoolSharkPool: true
17967
18329
  * });
18330
+ *
18331
+ * // For Uniswap V4, supply the pool ID and the expected chain explicitly.
18332
+ * const v4State = await getPoolState(publicClient, {
18333
+ * protocol: Protocol.UniswapV4,
18334
+ * poolId: '0x...',
18335
+ * chainId: 8453
18336
+ * });
17968
18337
  * ```
17969
18338
  */
17970
18339
  async function getPoolState(publicClient, params) {
17971
18340
  try {
18341
+ if (params.protocol === Protocol.UniswapV4) return {
18342
+ data: await getV4PoolState(publicClient, params),
18343
+ status: 200,
18344
+ success: true
18345
+ };
18346
+ if ("protocol" in params || !/^0x[0-9a-fA-F]{40}$/.test(params.poolAddress)) throw new Error("An address-based pool read requires a valid pool address and supported protocol.");
17972
18347
  let stateResponse;
17973
18348
  if (params.isAlgebraIntegralPool) stateResponse = await getGlobalStateAlgebraIntegral(publicClient, params.poolAddress, params.isAlgebraDirectionPool || false);
17974
18349
  else if (params.isPoolSharkPool) {
@@ -18077,7 +18452,7 @@ async function getPoolStateWithPrice(publicClient, params) {
18077
18452
  success: false,
18078
18453
  error: stateResponse.error || "Failed to get pool state"
18079
18454
  };
18080
- const price = getPoolPrice(stateResponse.data, params);
18455
+ const price = getPoolPrice(stateResponse.data, params.protocol === Protocol.UniswapV4 ? {} : params);
18081
18456
  return {
18082
18457
  data: {
18083
18458
  state: stateResponse.data,
@@ -19830,320 +20205,6 @@ var VaultWithdrawClient = class {
19830
20205
  }
19831
20206
  };
19832
20207
  //#endregion
19833
- //#region src/pool-lifecycle/abis/v4.ts
19834
- /** Minimal authoritative IPoolManager surface used by the V4 lifecycle adapter. */
19835
- const v4PoolManagerAbi = (0, viem.parseAbi)(["function initialize((address currency0,address currency1,uint24 fee,int24 tickSpacing,address hooks) key, uint160 sqrtPriceX96) returns (int24 tick)", "event Initialize(bytes32 indexed id, address indexed currency0, address indexed currency1, uint24 fee, int24 tickSpacing, address hooks, uint160 sqrtPriceX96, int24 tick)"]);
19836
- /** Minimal StateView/ImmutableState surface used for deployment and state checks. */
19837
- const v4StateViewAbi = (0, viem.parseAbi)(["function poolManager() view returns (address)", "function getSlot0(bytes32 poolId) view returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee)"]);
19838
- //#endregion
19839
- //#region src/pool-lifecycle/errors.ts
19840
- /** Error thrown when a pool lifecycle primitive cannot safely continue. */
19841
- var PoolLifecycleError = class extends Error {
19842
- constructor(code, message, causeValue) {
19843
- super(message);
19844
- this.name = "PoolLifecycleError";
19845
- this.code = code;
19846
- this.causeValue = causeValue;
19847
- }
19848
- };
19849
- //#endregion
19850
- //#region src/pool-lifecycle/math.ts
19851
- /** The smallest sqrt price accepted by Uniswap TickMath, inclusive. */
19852
- const MIN_SQRT_RATIO = 4295128739n;
19853
- /** The largest TickMath sqrt-price boundary, which is not itself valid. */
19854
- const MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342n;
19855
- const ZERO_ADDRESS$3 = "0x0000000000000000000000000000000000000000";
19856
- const MAX_ERC20_DECIMALS = 255;
19857
- function greatestCommonDivisor(a, b) {
19858
- let left = a;
19859
- let right = b;
19860
- while (right !== 0n) {
19861
- const remainder = left % right;
19862
- left = right;
19863
- right = remainder;
19864
- }
19865
- return left;
19866
- }
19867
- function checksumAddress(value, label, allowZero) {
19868
- if (typeof value !== "string" || !(0, viem.isAddress)(value, { strict: true })) throw new TypeError(`${label} must be a valid EVM address`);
19869
- const address = (0, viem.getAddress)(value);
19870
- if (!allowZero && address === ZERO_ADDRESS$3) throw new RangeError(`${label} must not be the zero address`);
19871
- return address;
19872
- }
19873
- function assertErc20Decimals(value, label) {
19874
- if (!Number.isSafeInteger(value) || value < 0 || value > MAX_ERC20_DECIMALS) throw new RangeError(`${label} must be an integer from 0 through 255`);
19875
- }
19876
- function assertPositiveFraction(value) {
19877
- if (typeof value?.numerator !== "bigint" || typeof value?.denominator !== "bigint") throw new TypeError("quotePerBase must contain bigint numerator and denominator values");
19878
- if (value.numerator <= 0n) throw new RangeError("quotePerBase numerator must be greater than zero");
19879
- if (value.denominator <= 0n) throw new RangeError("quotePerBase denominator must be greater than zero");
19880
- }
19881
- /**
19882
- * Parses an unsigned, fixed-point decimal string without converting through a
19883
- * JavaScript number. Signs, exponent notation, whitespace, and omitted whole
19884
- * or fractional digits are rejected. The returned fraction is reduced.
19885
- */
19886
- function parseExactDecimal(value) {
19887
- if (typeof value !== "string") throw new TypeError("Decimal value must be provided as a string");
19888
- const match = /^([0-9]+)(?:\.([0-9]+))?$/.exec(value);
19889
- if (match === null || match[0] !== value) throw new TypeError("Decimal value must use unsigned fixed-point notation, for example \"123.45\"");
19890
- const wholeDigits = match[1];
19891
- const fractionalDigits = match[2] ?? "";
19892
- const numerator = BigInt(`${wholeDigits}${fractionalDigits}`);
19893
- if (numerator === 0n) return {
19894
- numerator: 0n,
19895
- denominator: 1n
19896
- };
19897
- const denominator = 10n ** BigInt(fractionalDigits.length);
19898
- const divisor = greatestCommonDivisor(numerator, denominator);
19899
- return {
19900
- numerator: numerator / divisor,
19901
- denominator: denominator / divisor
19902
- };
19903
- }
19904
- /**
19905
- * Validates, checksums, and sorts two distinct non-zero ERC20 addresses.
19906
- */
19907
- function sortErc20Pair(tokenA, tokenB) {
19908
- const normalizedTokenA = checksumAddress(tokenA, "tokenA", false);
19909
- const normalizedTokenB = checksumAddress(tokenB, "tokenB", false);
19910
- if (normalizedTokenA === normalizedTokenB) throw new RangeError("ERC20 pair tokens must be different");
19911
- return BigInt(normalizedTokenA) < BigInt(normalizedTokenB) ? {
19912
- token0: normalizedTokenA,
19913
- token1: normalizedTokenB
19914
- } : {
19915
- token0: normalizedTokenB,
19916
- token1: normalizedTokenA
19917
- };
19918
- }
19919
- /**
19920
- * Validates, checksums, and sorts two distinct EVM currencies. The zero
19921
- * address is allowed and, when present, necessarily sorts as currency0.
19922
- */
19923
- function sortEvmCurrencyPair(currencyA, currencyB) {
19924
- const normalizedCurrencyA = checksumAddress(currencyA, "currencyA", true);
19925
- const normalizedCurrencyB = checksumAddress(currencyB, "currencyB", true);
19926
- if (normalizedCurrencyA === normalizedCurrencyB) throw new RangeError("EVM pair currencies must be different");
19927
- return BigInt(normalizedCurrencyA) < BigInt(normalizedCurrencyB) ? {
19928
- currency0: normalizedCurrencyA,
19929
- currency1: normalizedCurrencyB
19930
- } : {
19931
- currency0: normalizedCurrencyB,
19932
- currency1: normalizedCurrencyA
19933
- };
19934
- }
19935
- /**
19936
- * Returns floor(sqrt(value)) using bigint arithmetic only.
19937
- */
19938
- function integerSqrt(value) {
19939
- if (typeof value !== "bigint") throw new TypeError("Square-root input must be a bigint");
19940
- if (value < 0n) throw new RangeError("Square-root input must not be negative");
19941
- if (value < 2n) return value;
19942
- let estimate = value;
19943
- let nextEstimate = estimate + 1n >> 1n;
19944
- while (nextEstimate < estimate) {
19945
- estimate = nextEstimate;
19946
- nextEstimate = estimate + value / estimate >> 1n;
19947
- }
19948
- return estimate;
19949
- }
19950
- /**
19951
- * Enforces the Uniswap TickMath interval: MIN is inclusive and MAX exclusive.
19952
- * Returns the input so it can be composed with transaction builders.
19953
- */
19954
- function validateSqrtPriceX96(sqrtPriceX96) {
19955
- if (typeof sqrtPriceX96 !== "bigint") throw new TypeError("sqrtPriceX96 must be a bigint");
19956
- if (sqrtPriceX96 < 4295128739n || sqrtPriceX96 >= 1461446703485210103287273052203988822378723970342n) throw new RangeError(`sqrtPriceX96 must be in [${MIN_SQRT_RATIO}, ${MAX_SQRT_RATIO})`);
19957
- return sqrtPriceX96;
19958
- }
19959
- /**
19960
- * Encode an exact raw token1/token0 amount ratio without token metadata.
19961
- * The result matches the canonical V3 floor-rounding operation.
19962
- */
19963
- function encodeSqrtRatioX96(amount1Raw, amount0Raw) {
19964
- if (typeof amount0Raw !== "bigint" || typeof amount1Raw !== "bigint") throw new TypeError("Raw ratio amounts must be bigint values");
19965
- if (amount0Raw <= 0n || amount1Raw <= 0n) throw new RangeError("Raw ratio amounts must be greater than zero");
19966
- return validateSqrtPriceX96(integerSqrt((amount1Raw << 192n) / amount0Raw));
19967
- }
19968
- /**
19969
- * Converts an exact quote-per-base human price into the canonical raw-token
19970
- * ratio and sqrtPriceX96 expected by concentrated-liquidity initializers.
19971
- *
19972
- * Address sorting and reciprocal orientation happen before the only lossy
19973
- * operation. The final encoding is exactly:
19974
- *
19975
- * floor(sqrt((amount1Raw << 192) / amount0Raw))
19976
- */
19977
- function encodeInitialSqrtPriceX96(price) {
19978
- const pair = sortErc20Pair(price.baseToken, price.quoteToken);
19979
- const baseToken = checksumAddress(price.baseToken, "baseToken", false);
19980
- assertErc20Decimals(price.baseTokenDecimals, "baseTokenDecimals");
19981
- assertErc20Decimals(price.quoteTokenDecimals, "quoteTokenDecimals");
19982
- assertPositiveFraction(price.quotePerBase);
19983
- const baseScale = 10n ** BigInt(price.baseTokenDecimals);
19984
- const quoteScale = 10n ** BigInt(price.quoteTokenDecimals);
19985
- const baseTokenIsToken0 = baseToken === pair.token0;
19986
- const amount0Raw = baseTokenIsToken0 ? price.quotePerBase.denominator * baseScale : price.quotePerBase.numerator * quoteScale;
19987
- const amount1Raw = baseTokenIsToken0 ? price.quotePerBase.numerator * quoteScale : price.quotePerBase.denominator * baseScale;
19988
- const sqrtPriceX96 = encodeSqrtRatioX96(amount1Raw, amount0Raw);
19989
- return {
19990
- ...pair,
19991
- amount0Raw,
19992
- amount1Raw,
19993
- sqrtPriceX96,
19994
- baseTokenIsToken0
19995
- };
19996
- }
19997
- /**
19998
- * Currency-aware counterpart to {@link encodeInitialSqrtPriceX96}. It keeps
19999
- * the same exact orientation and floor-rounding rules while permitting the
20000
- * native zero-address currency required by Uniswap V4.
20001
- */
20002
- function encodeCurrencyInitialSqrtPriceX96(price) {
20003
- const pair = sortEvmCurrencyPair(price.baseCurrency, price.quoteCurrency);
20004
- const baseCurrency = checksumAddress(price.baseCurrency, "baseCurrency", true);
20005
- assertErc20Decimals(price.baseCurrencyDecimals, "baseCurrencyDecimals");
20006
- assertErc20Decimals(price.quoteCurrencyDecimals, "quoteCurrencyDecimals");
20007
- assertPositiveFraction(price.quotePerBase);
20008
- const baseScale = 10n ** BigInt(price.baseCurrencyDecimals);
20009
- const quoteScale = 10n ** BigInt(price.quoteCurrencyDecimals);
20010
- const baseCurrencyIsCurrency0 = baseCurrency === pair.currency0;
20011
- const amount0Raw = baseCurrencyIsCurrency0 ? price.quotePerBase.denominator * baseScale : price.quotePerBase.numerator * quoteScale;
20012
- const amount1Raw = baseCurrencyIsCurrency0 ? price.quotePerBase.numerator * quoteScale : price.quotePerBase.denominator * baseScale;
20013
- return {
20014
- ...pair,
20015
- amount0Raw,
20016
- amount1Raw,
20017
- sqrtPriceX96: encodeSqrtRatioX96(amount1Raw, amount0Raw),
20018
- baseCurrencyIsCurrency0
20019
- };
20020
- }
20021
- //#endregion
20022
- //#region src/pool-lifecycle/v4/key.ts
20023
- const V4_DYNAMIC_FEE_FLAG = 8388608;
20024
- const V4_MAX_STATIC_FEE = 1e6;
20025
- const V4_MAX_TICK_SPACING = 32767;
20026
- const V4_ALL_HOOK_MASK = (1n << 14n) - 1n;
20027
- const V4_ZERO_ADDRESS = (0, viem.getAddress)("0x0000000000000000000000000000000000000000");
20028
- const BEFORE_SWAP_FLAG = 1n << 7n;
20029
- const AFTER_SWAP_FLAG = 1n << 6n;
20030
- const AFTER_ADD_LIQUIDITY_FLAG = 1n << 10n;
20031
- const AFTER_REMOVE_LIQUIDITY_FLAG = 1n << 8n;
20032
- const BEFORE_SWAP_RETURNS_DELTA_FLAG = 1n << 3n;
20033
- const AFTER_SWAP_RETURNS_DELTA_FLAG = 1n << 2n;
20034
- const AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = 1n << 1n;
20035
- const AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = 1n;
20036
- const POOL_KEY_ABI_PARAMETER = {
20037
- type: "tuple",
20038
- components: [
20039
- {
20040
- name: "currency0",
20041
- type: "address"
20042
- },
20043
- {
20044
- name: "currency1",
20045
- type: "address"
20046
- },
20047
- {
20048
- name: "fee",
20049
- type: "uint24"
20050
- },
20051
- {
20052
- name: "tickSpacing",
20053
- type: "int24"
20054
- },
20055
- {
20056
- name: "hooks",
20057
- type: "address"
20058
- }
20059
- ]
20060
- };
20061
- function invalidInput(message, cause) {
20062
- throw new PoolLifecycleError("INVALID_INPUT", message, cause);
20063
- }
20064
- function normalizeAddress(value, label) {
20065
- if (typeof value !== "string" || !(0, viem.isAddress)(value, { strict: true })) return invalidInput(`${label} must be a valid EVM address.`);
20066
- return (0, viem.getAddress)(value);
20067
- }
20068
- function validateFee(fee) {
20069
- if (!Number.isSafeInteger(fee) || Number(fee) < 0 || Number(fee) > 1e6 && Number(fee) !== 8388608) return invalidInput("V4 fee must be an integer from 0 through 1000000 or the dynamic fee flag 0x800000.");
20070
- return Number(fee);
20071
- }
20072
- function validateTickSpacing(tickSpacing) {
20073
- if (!Number.isSafeInteger(tickSpacing) || Number(tickSpacing) < 1 || Number(tickSpacing) > 32767) return invalidInput("V4 tickSpacing must be an integer from 1 through 32767.");
20074
- return Number(tickSpacing);
20075
- }
20076
- function validateHookAddress(hooksAddress, fee) {
20077
- const hooks = BigInt(hooksAddress);
20078
- const hasFlag = (flag) => (hooks & flag) !== 0n;
20079
- if (!hasFlag(BEFORE_SWAP_FLAG) && hasFlag(BEFORE_SWAP_RETURNS_DELTA_FLAG) || !hasFlag(AFTER_SWAP_FLAG) && hasFlag(AFTER_SWAP_RETURNS_DELTA_FLAG) || !hasFlag(AFTER_ADD_LIQUIDITY_FLAG) && hasFlag(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG) || !hasFlag(AFTER_REMOVE_LIQUIDITY_FLAG) && hasFlag(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)) invalidInput("V4 hook return-delta flags require their corresponding action flags.");
20080
- const dynamicFee = fee === V4_DYNAMIC_FEE_FLAG;
20081
- if (!(hooks === 0n ? !dynamicFee : (hooks & V4_ALL_HOOK_MASK) !== 0n || dynamicFee)) invalidInput("V4 hooks address is incompatible with its fee and permission flags.");
20082
- }
20083
- /** Validate a complete PoolKey whose currencies are already canonically ordered. */
20084
- function validateV4PoolKey(value) {
20085
- const currency0 = normalizeAddress(value?.currency0, "currency0");
20086
- const currency1 = normalizeAddress(value?.currency1, "currency1");
20087
- const fee = validateFee(value?.fee);
20088
- const tickSpacing = validateTickSpacing(value?.tickSpacing);
20089
- const hooks = normalizeAddress(value?.hooks, "hooks");
20090
- if (BigInt(currency0) >= BigInt(currency1)) invalidInput("V4 currencies must be distinct and canonically ordered.");
20091
- validateHookAddress(hooks, fee);
20092
- return {
20093
- currency0,
20094
- currency1,
20095
- fee,
20096
- tickSpacing,
20097
- hooks
20098
- };
20099
- }
20100
- /**
20101
- * Validate and sort two currencies. Address zero is deliberately accepted and
20102
- * sorts first because V4 represents the native currency as address(0).
20103
- */
20104
- function canonicalizeV4PoolKey(value) {
20105
- const currencyA = normalizeAddress(value?.currencyA, "currencyA");
20106
- const currencyB = normalizeAddress(value?.currencyB, "currencyB");
20107
- if (currencyA === currencyB) return invalidInput("V4 pool currencies must be different.");
20108
- const [currency0, currency1] = BigInt(currencyA) < BigInt(currencyB) ? [currencyA, currencyB] : [currencyB, currencyA];
20109
- return validateV4PoolKey({
20110
- currency0,
20111
- currency1,
20112
- fee: value?.fee,
20113
- tickSpacing: value?.tickSpacing,
20114
- hooks: value?.hooks
20115
- });
20116
- }
20117
- /** Return the exact PoolId used by PoolIdLibrary.toId. */
20118
- function getV4PoolId(key) {
20119
- const validated = validateV4PoolKey(key);
20120
- return (0, viem.keccak256)((0, viem.encodeAbiParameters)([POOL_KEY_ABI_PARAMETER], [validated]));
20121
- }
20122
- function v4PoolKeysEqual(left, right) {
20123
- try {
20124
- const a = validateV4PoolKey(left);
20125
- const b = validateV4PoolKey(right);
20126
- return a.currency0 === b.currency0 && a.currency1 === b.currency1 && a.fee === b.fee && a.tickSpacing === b.tickSpacing && a.hooks === b.hooks;
20127
- } catch {
20128
- return false;
20129
- }
20130
- }
20131
- /** Validate price bounds and bind the price to the canonical PoolKey order. */
20132
- function assertV4InitialPrice(key, value) {
20133
- const currency0 = normalizeAddress(value?.currency0, "initialPrice.currency0");
20134
- const currency1 = normalizeAddress(value?.currency1, "initialPrice.currency1");
20135
- if (currency0 !== key.currency0 || currency1 !== key.currency1) return invalidInput("V4 initial price currencies must match the canonical PoolKey order.");
20136
- try {
20137
- return {
20138
- currency0,
20139
- currency1,
20140
- sqrtPriceX96: validateSqrtPriceX96(value?.sqrtPriceX96)
20141
- };
20142
- } catch (error) {
20143
- return invalidInput(error instanceof Error ? error.message : "V4 sqrtPriceX96 is invalid.", error);
20144
- }
20145
- }
20146
- //#endregion
20147
20208
  //#region src/base/vault/execution-context.ts
20148
20209
  const VAULT_REGISTRY_ABI = (0, viem.parseAbi)(["function getVaultDetails(address vault) view returns ((uint8 state,uint256 tokenId,uint256 vaultID,string payloadIpfs,address vaultAddress,string beaconName) details)", "function beaconAddresses(string beaconName) view returns (address)"]);
20149
20210
  const VAULT_EXECUTION_ABI = (0, viem.parseAbi)([
@@ -23013,7 +23074,6 @@ var PoolClient = class extends SubgraphClient {
23013
23074
  return data.data;
23014
23075
  };
23015
23076
  this.apiCallCount++;
23016
- console.log("Total API calls:", this.apiCallCount);
23017
23077
  const timeoutPromise = new Promise((_, reject) => {
23018
23078
  setTimeout(() => reject(/* @__PURE__ */ new Error("GraphQL query timeout")), this.defaultTimeout);
23019
23079
  });
@@ -29082,6 +29142,8 @@ exports.getNFTManagerAddress = getNFTManagerAddress;
29082
29142
  exports.getNetworkByChainId = getNetworkByChainId;
29083
29143
  exports.getPoolHelperByChainId = getPoolHelperByChainId;
29084
29144
  exports.getPoolSlot0 = getPoolSlot0;
29145
+ exports.getPoolState = getPoolState;
29146
+ exports.getPoolStateWithPrice = getPoolStateWithPrice;
29085
29147
  exports.getProtcolTypeByAmmType = getProtcolTypeByAmmType;
29086
29148
  exports.getProtocolBySubgraph = getProtocolBySubgraph;
29087
29149
  exports.getProtocolConfigByBeacon = getProtocolConfigByBeacon;