@clonegod/ttd-bsc-common 3.1.66 → 3.1.67

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.
@@ -11,5 +11,9 @@ export interface AmmDepthResult {
11
11
  amountOutWei: bigint;
12
12
  amountOut: number;
13
13
  outputDecimals: number;
14
+ amountInWei: bigint;
15
+ amountIn: number;
16
+ inputDecimals: number;
17
+ targetPrice: number;
14
18
  }
15
19
  export declare function calculateAmmDepth(input: AmmDepthInput): AmmDepthResult;
@@ -7,32 +7,49 @@ function calculateAmmDepth(input) {
7
7
  const R0 = BigInt(input.reserve0);
8
8
  const R1 = BigInt(input.reserve1);
9
9
  if (R0 === 0n || R1 === 0n) {
10
- return { amountOutWei: 0n, amountOut: 0, outputDecimals: 0 };
10
+ return { amountOutWei: 0n, amountOut: 0, outputDecimals: 0, amountInWei: 0n, amountIn: 0, inputDecimals: 0, targetPrice: 0 };
11
11
  }
12
12
  const k = R0 * R1;
13
13
  const bps = BigInt(targetBps);
14
14
  const PRECISION = 10n ** 18n;
15
15
  let amountOutWei;
16
+ let amountInWei;
16
17
  let outputDecimals;
18
+ let inputDecimals;
17
19
  if (isBuy) {
18
20
  const [baseReserve, quoteReserve] = baseIsToken0 ? [R0, R1] : [R1, R0];
19
21
  outputDecimals = baseIsToken0 ? token0Decimals : token1Decimals;
20
- const numerator = k * 10000n * PRECISION;
21
- const denominator = (10000n + bps) * quoteReserve;
22
+ inputDecimals = baseIsToken0 ? token1Decimals : token0Decimals;
22
23
  const baseReserveNew = baseReserve * (0, clmm_depth_calculator_1.bigIntSqrt)(10000n * PRECISION) / (0, clmm_depth_calculator_1.bigIntSqrt)((10000n + bps) * PRECISION);
24
+ const quoteReserveNew = quoteReserve * (0, clmm_depth_calculator_1.bigIntSqrt)((10000n + bps) * PRECISION) / (0, clmm_depth_calculator_1.bigIntSqrt)(10000n * PRECISION);
23
25
  amountOutWei = baseReserve - baseReserveNew;
26
+ amountInWei = quoteReserveNew - quoteReserve;
24
27
  }
25
28
  else {
26
29
  const [baseReserve, quoteReserve] = baseIsToken0 ? [R0, R1] : [R1, R0];
27
30
  outputDecimals = baseIsToken0 ? token1Decimals : token0Decimals;
31
+ inputDecimals = baseIsToken0 ? token0Decimals : token1Decimals;
28
32
  if (bps >= 10000n) {
29
33
  amountOutWei = quoteReserve;
34
+ amountInWei = baseReserve;
30
35
  }
31
36
  else {
32
37
  const quoteReserveNew = quoteReserve * (0, clmm_depth_calculator_1.bigIntSqrt)((10000n - bps) * PRECISION) / (0, clmm_depth_calculator_1.bigIntSqrt)(10000n * PRECISION);
38
+ const baseReserveNew = baseReserve * (0, clmm_depth_calculator_1.bigIntSqrt)(10000n * PRECISION) / (0, clmm_depth_calculator_1.bigIntSqrt)((10000n - bps) * PRECISION);
33
39
  amountOutWei = quoteReserve - quoteReserveNew;
40
+ amountInWei = baseReserveNew - baseReserve;
34
41
  }
35
42
  }
36
43
  const amountOut = Number(amountOutWei) / Math.pow(10, outputDecimals);
37
- return { amountOutWei, amountOut, outputDecimals };
44
+ const amountIn = Number(amountInWei) / Math.pow(10, inputDecimals);
45
+ const baseDec = baseIsToken0 ? token0Decimals : token1Decimals;
46
+ const quoteDec = baseIsToken0 ? token1Decimals : token0Decimals;
47
+ const baseReserveUi = Number(baseIsToken0 ? R0 : R1) / Math.pow(10, baseDec);
48
+ const quoteReserveUi = Number(baseIsToken0 ? R1 : R0) / Math.pow(10, quoteDec);
49
+ const midPrice = quoteReserveUi / baseReserveUi;
50
+ const bpsNum = Number(targetBps);
51
+ const targetPrice = isBuy
52
+ ? midPrice * (10000 + bpsNum) / 10000
53
+ : midPrice * (10000 - bpsNum) / 10000;
54
+ return { amountOutWei, amountOut, outputDecimals, amountInWei, amountIn, inputDecimals, targetPrice };
38
55
  }
@@ -19,8 +19,10 @@ export interface DepthResult {
19
19
  amountOut: number;
20
20
  currentTick: number;
21
21
  targetTick: number;
22
+ targetSqrtPriceX96: bigint;
22
23
  }
23
24
  export declare function calculateClmmDepth(input: ClmmDepthInput): DepthResult;
25
+ export declare function priceFromSqrtX96(sqrtPriceX96: bigint, baseDecimals: number, quoteDecimals: number, baseIsToken0: boolean): number;
24
26
  declare function computeTargetSqrtPrice(currentSqrtPriceX96: bigint, bps: number, zeroForOne: boolean): bigint;
25
27
  declare function bigIntSqrt(n: bigint): bigint;
26
28
  export { getSqrtRatioAtTick, computeTargetSqrtPrice, bigIntSqrt };
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.calculateClmmDepth = calculateClmmDepth;
4
+ exports.priceFromSqrtX96 = priceFromSqrtX96;
4
5
  exports.getSqrtRatioAtTick = getSqrtRatioAtTick;
5
6
  exports.computeTargetSqrtPrice = computeTargetSqrtPrice;
6
7
  exports.bigIntSqrt = bigIntSqrt;
@@ -60,7 +61,7 @@ function calculateClmmDepth(input) {
60
61
  const currentSqrtPriceX96 = BigInt(input.sqrtPriceX96);
61
62
  let liquidity = BigInt(input.liquidity);
62
63
  if (liquidity === 0n) {
63
- return { amountInWei: 0n, amountIn: 0, amountOutWei: 0n, amountOut: 0, currentTick, targetTick: currentTick };
64
+ return { amountInWei: 0n, amountIn: 0, amountOutWei: 0n, amountOut: 0, currentTick, targetTick: currentTick, targetSqrtPriceX96: currentSqrtPriceX96 };
64
65
  }
65
66
  const targetSqrtPriceX96 = computeTargetSqrtPrice(currentSqrtPriceX96, targetBps, zeroForOne);
66
67
  const allTicks = tickCache.getCachedTickIndices(poolAddress);
@@ -94,7 +95,17 @@ function calculateClmmDepth(input) {
94
95
  const amountOut = Number(totalOutput) / Math.pow(10, outputDecimals);
95
96
  const sqrtPriceFloat = Number(targetSqrtPriceX96) / Number(Q96);
96
97
  const targetTick = Math.floor(Math.log(sqrtPriceFloat * sqrtPriceFloat) / Math.log(1.0001));
97
- return { amountInWei: totalInput, amountIn, amountOutWei: totalOutput, amountOut, currentTick, targetTick };
98
+ return { amountInWei: totalInput, amountIn, amountOutWei: totalOutput, amountOut, currentTick, targetTick, targetSqrtPriceX96 };
99
+ }
100
+ function priceFromSqrtX96(sqrtPriceX96, baseDecimals, quoteDecimals, baseIsToken0) {
101
+ const sp = Number(sqrtPriceX96) / Number(Q96);
102
+ const priceToken1PerToken0 = sp * sp;
103
+ if (baseIsToken0) {
104
+ return priceToken1PerToken0 * Math.pow(10, baseDecimals - quoteDecimals);
105
+ }
106
+ else {
107
+ return (1 / priceToken1PerToken0) * Math.pow(10, baseDecimals - quoteDecimals);
108
+ }
98
109
  }
99
110
  function computeTargetSqrtPrice(currentSqrtPriceX96, bps, zeroForOne) {
100
111
  const PRECISION = 10n ** 18n;
@@ -1,14 +1,14 @@
1
+ import { QuoteDepthOutput } from '@clonegod/ttd-core';
1
2
  import { ClmmTickCache } from '../tick/clmm_tick_cache';
2
- export { calculateClmmDepth, getSqrtRatioAtTick, computeTargetSqrtPrice, bigIntSqrt } from './clmm_depth_calculator';
3
+ export { calculateClmmDepth, getSqrtRatioAtTick, computeTargetSqrtPrice, bigIntSqrt, priceFromSqrtX96 } from './clmm_depth_calculator';
3
4
  export type { ClmmDepthInput, DepthResult } from './clmm_depth_calculator';
4
5
  export { calculateAmmDepth } from './amm_depth_calculator';
5
6
  export type { AmmDepthInput, AmmDepthResult } from './amm_depth_calculator';
6
7
  export { buildTickLiquiditySnapshot } from './tick_liquidity_snapshot';
7
8
  export type { TickLiquiditySnapshot, TickLiquiditySnapshotInput, TickDataPoint } from './tick_liquidity_snapshot';
8
9
  import { TickLiquiditySnapshot } from './tick_liquidity_snapshot';
9
- import { PoolDepthData } from '@clonegod/ttd-core';
10
- export type { PoolDepthData } from '@clonegod/ttd-core';
11
- export declare function getDepthBps(): number[];
10
+ export declare function logFeeChainConfigOnce(poolName: string, poolAddress: string, configFeeBps: number, chainFeeBps: number, dexId?: string, pair?: string): void;
11
+ export declare function clearFeeMatchLogged(poolAddress: string): void;
12
12
  export interface BuildClmmDepthInput {
13
13
  poolInfo: {
14
14
  pool_name: string;
@@ -27,9 +27,10 @@ export interface BuildClmmDepthInput {
27
27
  };
28
28
  basePriceUsd: number;
29
29
  quotePriceUsd: number;
30
+ feeRateBps: number;
30
31
  }
31
32
  export interface ClmmDepthResult {
32
- depth: PoolDepthData;
33
+ depth: QuoteDepthOutput;
33
34
  tickLiquidity?: TickLiquiditySnapshot;
34
35
  }
35
36
  export declare function buildClmmDepth(input: BuildClmmDepthInput): ClmmDepthResult | undefined;
@@ -45,5 +46,6 @@ export interface BuildAmmDepthInput {
45
46
  token0Address: string;
46
47
  basePriceUsd: number;
47
48
  quotePriceUsd: number;
49
+ feeRateBps: number;
48
50
  }
49
- export declare function buildAmmDepth(input: BuildAmmDepthInput): PoolDepthData | undefined;
51
+ export declare function buildAmmDepth(input: BuildAmmDepthInput): QuoteDepthOutput | undefined;
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildTickLiquiditySnapshot = exports.calculateAmmDepth = exports.bigIntSqrt = exports.computeTargetSqrtPrice = exports.getSqrtRatioAtTick = exports.calculateClmmDepth = void 0;
4
- exports.getDepthBps = getDepthBps;
3
+ exports.buildTickLiquiditySnapshot = exports.calculateAmmDepth = exports.priceFromSqrtX96 = exports.bigIntSqrt = exports.computeTargetSqrtPrice = exports.getSqrtRatioAtTick = exports.calculateClmmDepth = void 0;
4
+ exports.logFeeChainConfigOnce = logFeeChainConfigOnce;
5
+ exports.clearFeeMatchLogged = clearFeeMatchLogged;
5
6
  exports.buildClmmDepth = buildClmmDepth;
6
7
  exports.buildAmmDepth = buildAmmDepth;
7
8
  const ttd_core_1 = require("@clonegod/ttd-core");
9
+ const ttd_core_2 = require("@clonegod/ttd-core");
8
10
  const clmm_depth_calculator_1 = require("./clmm_depth_calculator");
9
11
  const amm_depth_calculator_1 = require("./amm_depth_calculator");
10
12
  const trade_direction_1 = require("../../utils/trade_direction");
@@ -13,39 +15,85 @@ Object.defineProperty(exports, "calculateClmmDepth", { enumerable: true, get: fu
13
15
  Object.defineProperty(exports, "getSqrtRatioAtTick", { enumerable: true, get: function () { return clmm_depth_calculator_2.getSqrtRatioAtTick; } });
14
16
  Object.defineProperty(exports, "computeTargetSqrtPrice", { enumerable: true, get: function () { return clmm_depth_calculator_2.computeTargetSqrtPrice; } });
15
17
  Object.defineProperty(exports, "bigIntSqrt", { enumerable: true, get: function () { return clmm_depth_calculator_2.bigIntSqrt; } });
18
+ Object.defineProperty(exports, "priceFromSqrtX96", { enumerable: true, get: function () { return clmm_depth_calculator_2.priceFromSqrtX96; } });
16
19
  var amm_depth_calculator_2 = require("./amm_depth_calculator");
17
20
  Object.defineProperty(exports, "calculateAmmDepth", { enumerable: true, get: function () { return amm_depth_calculator_2.calculateAmmDepth; } });
18
21
  var tick_liquidity_snapshot_1 = require("./tick_liquidity_snapshot");
19
22
  Object.defineProperty(exports, "buildTickLiquiditySnapshot", { enumerable: true, get: function () { return tick_liquidity_snapshot_1.buildTickLiquiditySnapshot; } });
20
23
  const tick_liquidity_snapshot_2 = require("./tick_liquidity_snapshot");
21
24
  const clmm_tick_cache_1 = require("../tick/clmm_tick_cache");
22
- let _depthBpsLogged = false;
23
- const DEFAULT_BPS = 20;
24
- function getDepthBps() {
25
- const raw = process.env.DEPTH_BPS_LEVELS;
26
- const levels = raw
27
- ? raw.split(',').map(s => parseInt(s.trim(), 10)).filter(n => !isNaN(n) && n > 0)
28
- : [DEFAULT_BPS];
29
- const cexBps = parseInt(process.env.DEPTH_CEX_BPS || String(DEFAULT_BPS));
30
- if (!levels.includes(cexBps))
31
- levels.push(cexBps);
32
- if (!levels.includes(DEFAULT_BPS))
33
- levels.push(DEFAULT_BPS);
34
- levels.sort((a, b) => a - b);
35
- if (!_depthBpsLogged) {
36
- _depthBpsLogged = true;
37
- (0, ttd_core_1.log_info)(`[Depth] bpsLevels=${JSON.stringify(levels)}, cexBps=${cexBps}`);
25
+ let _depthPctLogged = false;
26
+ function logDepthLevelsOnce() {
27
+ if (_depthPctLogged)
28
+ return;
29
+ _depthPctLogged = true;
30
+ const pcts = (0, ttd_core_2.getDepthPricePctLevels)();
31
+ (0, ttd_core_1.log_info)(`[Depth] pctLevels=${JSON.stringify(pcts)}, default=${ttd_core_2.DEFAULT_TIER_PCT}`);
32
+ }
33
+ const _feeMatchLoggedPools = new Set();
34
+ function logFeeChainConfigOnce(poolName, poolAddress, configFeeBps, chainFeeBps, dexId, pair) {
35
+ if (_feeMatchLoggedPools.has(poolAddress))
36
+ return;
37
+ _feeMatchLoggedPools.add(poolAddress);
38
+ const diff = Math.abs(configFeeBps - chainFeeBps);
39
+ const drifted = diff >= 0.01;
40
+ if (drifted) {
41
+ (0, ttd_core_1.log_warn)(`[Fee] ${poolName} 配置漂移: config=${configFeeBps}bps ≠ chain=${chainFeeBps}bps (差 ${diff.toFixed(2)}bps) — 已用链上值,请运维检查池子配置`);
42
+ }
43
+ else {
44
+ (0, ttd_core_1.log_info)(`[Fee] ${poolName} config=${configFeeBps}bps == chain=${chainFeeBps}bps ✓`);
38
45
  }
39
- return levels;
46
+ const addrLower = poolAddress.toLowerCase();
47
+ ttd_core_2.ALERT_TYPES.QUOTE_FEE_CHAIN_DRIFT.reportIfChanged(addrLower, drifted, () => ({
48
+ identity: addrLower,
49
+ scope: { dex_id: dexId, pool_address: addrLower, pair },
50
+ title: `${poolName} fee 漂移 cfg=${configFeeBps}bps chain=${chainFeeBps}bps`,
51
+ detail: {
52
+ pool_name: poolName,
53
+ config_fee_bps: configFeeBps,
54
+ chain_fee_bps: chainFeeBps,
55
+ diff_bps: diff,
56
+ },
57
+ }));
58
+ }
59
+ function clearFeeMatchLogged(poolAddress) {
60
+ _feeMatchLoggedPools.delete(poolAddress);
61
+ }
62
+ function grossUpFee(amountInNet, feeRateBps) {
63
+ if (feeRateBps <= 0 || amountInNet <= 0) {
64
+ return { amountInGross: amountInNet, feeAmount: 0 };
65
+ }
66
+ const feeRatio = feeRateBps / 10000;
67
+ const amountInGross = amountInNet / (1 - feeRatio);
68
+ const feeAmount = amountInGross - amountInNet;
69
+ return { amountInGross, feeAmount };
40
70
  }
41
71
  const _tickLiquidityLastBuild = new Map();
72
+ function assembleEntry(tiers) {
73
+ const defaultTier = tiers.find(t => t.pct === ttd_core_2.DEFAULT_TIER_PCT) ?? tiers[0];
74
+ return {
75
+ price: defaultTier.price,
76
+ amount: defaultTier.amount,
77
+ amount_in: defaultTier.amount_in,
78
+ amount_in_usd: defaultTier.amount_in_usd,
79
+ fee: defaultTier.fee,
80
+ fee_usd: defaultTier.fee_usd,
81
+ tick_move: defaultTier.tick_move,
82
+ tiers,
83
+ };
84
+ }
42
85
  function buildClmmDepth(input) {
43
- const bpsLevels = getDepthBps();
44
- if (bpsLevels.length === 0)
86
+ logDepthLevelsOnce();
87
+ const pctLevels = (0, ttd_core_2.getDepthPricePctLevels)();
88
+ if (pctLevels.length === 0)
45
89
  return undefined;
46
- const { poolInfo, poolAddress, tickCache, poolState, basePriceUsd, quotePriceUsd } = input;
90
+ const { poolInfo, poolAddress, tickCache, poolState, basePriceUsd, quotePriceUsd, feeRateBps } = input;
47
91
  if (BigInt(poolState.liquidity) === 0n)
48
92
  return undefined;
93
+ if (feeRateBps == null || feeRateBps < 0) {
94
+ (0, ttd_core_1.log_debug)(`[Depth] ${poolInfo.pool_name} CLMM: invalid feeRateBps=${feeRateBps}, skip`, '');
95
+ return undefined;
96
+ }
49
97
  try {
50
98
  const askDirection = (0, trade_direction_1.resolveTradeDirection)(poolInfo, true);
51
99
  const bidDirection = (0, trade_direction_1.resolveTradeDirection)(poolInfo, false);
@@ -53,8 +101,12 @@ function buildClmmDepth(input) {
53
101
  const bidZeroForOne = bidDirection.inputToken.address.toLowerCase() === poolState.token0.toLowerCase();
54
102
  const baseToken = askDirection.baseToken;
55
103
  const quoteToken = askDirection.quoteToken;
56
- const depth = { ask: {}, bid: {} };
57
- for (const bps of bpsLevels) {
104
+ const baseIsToken0 = baseToken.address.toLowerCase() === poolState.token0.toLowerCase();
105
+ const midPrice = (0, clmm_depth_calculator_1.priceFromSqrtX96)(BigInt(poolState.sqrtPriceX96), baseToken.decimals, quoteToken.decimals, baseIsToken0);
106
+ const askTiers = [];
107
+ const bidTiers = [];
108
+ for (const pct of pctLevels) {
109
+ const bps = Math.round(pct * 100);
58
110
  const askResult = (0, clmm_depth_calculator_1.calculateClmmDepth)({
59
111
  poolAddress, tickCache,
60
112
  currentTick: poolState.tick, sqrtPriceX96: poolState.sqrtPriceX96,
@@ -69,15 +121,43 @@ function buildClmmDepth(input) {
69
121
  zeroForOne: bidZeroForOne, targetBps: bps,
70
122
  inputDecimals: baseToken.decimals, outputDecimals: quoteToken.decimals,
71
123
  });
124
+ const askTargetPrice = (0, clmm_depth_calculator_1.priceFromSqrtX96)(askResult.targetSqrtPriceX96, baseToken.decimals, quoteToken.decimals, baseIsToken0);
125
+ const bidTargetPrice = (0, clmm_depth_calculator_1.priceFromSqrtX96)(bidResult.targetSqrtPriceX96, baseToken.decimals, quoteToken.decimals, baseIsToken0);
126
+ const askGross = grossUpFee(askResult.amountIn, feeRateBps);
127
+ const bidGross = grossUpFee(bidResult.amountIn, feeRateBps);
72
128
  const askTickMove = askResult.targetTick < askResult.currentTick
73
129
  ? `${askResult.targetTick} <- ${askResult.currentTick}`
74
130
  : `${askResult.currentTick} -> ${askResult.targetTick}`;
75
131
  const bidTickMove = bidResult.targetTick > bidResult.currentTick
76
132
  ? `${bidResult.currentTick} -> ${bidResult.targetTick}`
77
133
  : `${bidResult.targetTick} <- ${bidResult.currentTick}`;
78
- depth.ask[bps] = { amount: askResult.amountOut, amountUsd: askResult.amountOut * basePriceUsd, amountIn: askResult.amountIn, amountInUsd: askResult.amountIn * quotePriceUsd, tickMove: askTickMove };
79
- depth.bid[bps] = { amount: bidResult.amountOut, amountUsd: bidResult.amountOut * quotePriceUsd, amountIn: bidResult.amountIn, amountInUsd: bidResult.amountIn * basePriceUsd, tickMove: bidTickMove };
134
+ askTiers.push({
135
+ pct,
136
+ price: askTargetPrice,
137
+ amount: askResult.amountOut,
138
+ amount_in: askGross.amountInGross,
139
+ amount_in_usd: askGross.amountInGross * quotePriceUsd,
140
+ fee: askGross.feeAmount,
141
+ fee_usd: askGross.feeAmount * quotePriceUsd,
142
+ tick_move: askTickMove,
143
+ });
144
+ bidTiers.push({
145
+ pct,
146
+ price: bidTargetPrice,
147
+ amount: bidResult.amountOut,
148
+ amount_in: bidGross.amountInGross,
149
+ amount_in_usd: bidGross.amountInGross * basePriceUsd,
150
+ fee: bidGross.feeAmount,
151
+ fee_usd: bidGross.feeAmount * basePriceUsd,
152
+ tick_move: bidTickMove,
153
+ });
80
154
  }
155
+ const depth = {
156
+ mid_price: midPrice,
157
+ fee_rate_bps: feeRateBps,
158
+ ask: assembleEntry(askTiers),
159
+ bid: assembleEntry(bidTiers),
160
+ };
81
161
  let tickLiquidity;
82
162
  const now = Date.now();
83
163
  const lastBuild = _tickLiquidityLastBuild.get(poolAddress) || 0;
@@ -86,7 +166,6 @@ function buildClmmDepth(input) {
86
166
  }
87
167
  _tickLiquidityLastBuild.set(poolAddress, now);
88
168
  try {
89
- const baseIsToken0 = baseToken.address.toLowerCase() === poolState.token0.toLowerCase();
90
169
  const tokenAIsToken0 = poolInfo.tokenA?.address?.toLowerCase() === poolState.token0.toLowerCase();
91
170
  const token0Info = tokenAIsToken0 ? poolInfo.tokenA : poolInfo.tokenB;
92
171
  const token1Info = tokenAIsToken0 ? poolInfo.tokenB : poolInfo.tokenA;
@@ -117,17 +196,29 @@ function buildClmmDepth(input) {
117
196
  }
118
197
  }
119
198
  function buildAmmDepth(input) {
120
- const bpsLevels = getDepthBps();
121
- if (bpsLevels.length === 0)
199
+ logDepthLevelsOnce();
200
+ const pctLevels = (0, ttd_core_2.getDepthPricePctLevels)();
201
+ if (pctLevels.length === 0)
202
+ return undefined;
203
+ const { poolInfo, reserve0, reserve1, token0Address, basePriceUsd, quotePriceUsd, feeRateBps } = input;
204
+ if (feeRateBps == null || feeRateBps < 0) {
205
+ (0, ttd_core_1.log_debug)(`[Depth] ${poolInfo.pool_name} AMM: invalid feeRateBps=${feeRateBps}, skip`, '');
122
206
  return undefined;
123
- const { poolInfo, reserve0, reserve1, token0Address, basePriceUsd, quotePriceUsd } = input;
207
+ }
124
208
  try {
125
209
  const askDirection = (0, trade_direction_1.resolveTradeDirection)(poolInfo, true);
126
210
  const baseToken = askDirection.baseToken;
127
211
  const quoteToken = askDirection.quoteToken;
128
212
  const baseIsToken0 = baseToken.address.toLowerCase() === token0Address.toLowerCase();
129
- const depth = { ask: {}, bid: {} };
130
- for (const bps of bpsLevels) {
213
+ const baseDec = baseIsToken0 ? baseToken.decimals : quoteToken.decimals;
214
+ const quoteDec = baseIsToken0 ? quoteToken.decimals : baseToken.decimals;
215
+ const baseReserveUi = Number(BigInt(baseIsToken0 ? reserve0 : reserve1)) / Math.pow(10, baseToken.decimals);
216
+ const quoteReserveUi = Number(BigInt(baseIsToken0 ? reserve1 : reserve0)) / Math.pow(10, quoteToken.decimals);
217
+ const midPrice = quoteReserveUi / baseReserveUi;
218
+ const askTiers = [];
219
+ const bidTiers = [];
220
+ for (const pct of pctLevels) {
221
+ const bps = Math.round(pct * 100);
131
222
  const askResult = (0, amm_depth_calculator_1.calculateAmmDepth)({
132
223
  reserve0, reserve1, targetBps: bps, isBuy: true, baseIsToken0,
133
224
  token0Decimals: baseIsToken0 ? baseToken.decimals : quoteToken.decimals,
@@ -138,10 +229,33 @@ function buildAmmDepth(input) {
138
229
  token0Decimals: baseIsToken0 ? baseToken.decimals : quoteToken.decimals,
139
230
  token1Decimals: baseIsToken0 ? quoteToken.decimals : baseToken.decimals,
140
231
  });
141
- depth.ask[bps] = { amount: askResult.amountOut, amountUsd: askResult.amountOut * basePriceUsd, amountIn: 0, amountInUsd: 0 };
142
- depth.bid[bps] = { amount: bidResult.amountOut, amountUsd: bidResult.amountOut * quotePriceUsd, amountIn: 0, amountInUsd: 0 };
232
+ const askGross = grossUpFee(askResult.amountIn, feeRateBps);
233
+ const bidGross = grossUpFee(bidResult.amountIn, feeRateBps);
234
+ askTiers.push({
235
+ pct,
236
+ price: askResult.targetPrice,
237
+ amount: askResult.amountOut,
238
+ amount_in: askGross.amountInGross,
239
+ amount_in_usd: askGross.amountInGross * quotePriceUsd,
240
+ fee: askGross.feeAmount,
241
+ fee_usd: askGross.feeAmount * quotePriceUsd,
242
+ });
243
+ bidTiers.push({
244
+ pct,
245
+ price: bidResult.targetPrice,
246
+ amount: bidResult.amountOut,
247
+ amount_in: bidGross.amountInGross,
248
+ amount_in_usd: bidGross.amountInGross * basePriceUsd,
249
+ fee: bidGross.feeAmount,
250
+ fee_usd: bidGross.feeAmount * basePriceUsd,
251
+ });
143
252
  }
144
- return depth;
253
+ return {
254
+ mid_price: midPrice,
255
+ fee_rate_bps: feeRateBps,
256
+ ask: assembleEntry(askTiers),
257
+ bid: assembleEntry(bidTiers),
258
+ };
145
259
  }
146
260
  catch (error) {
147
261
  (0, ttd_core_1.log_debug)(`[Depth] ${poolInfo.pool_name} AMM depth failed: ${error.message}`, '');
@@ -0,0 +1,10 @@
1
+ export declare function reportHookFeeChangeIfChanged(opts: {
2
+ pool_address: string;
3
+ dex_id: string;
4
+ pool_name?: string;
5
+ block_number: number;
6
+ prevLpFee: number | undefined;
7
+ prevProtocolFee: number | undefined;
8
+ newLpFee: number;
9
+ newProtocolFee: number;
10
+ }): void;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reportHookFeeChangeIfChanged = reportHookFeeChangeIfChanged;
4
+ const ttd_core_1 = require("@clonegod/ttd-core");
5
+ function reportHookFeeChangeIfChanged(opts) {
6
+ const { pool_address, dex_id, pool_name, block_number, prevLpFee, prevProtocolFee, newLpFee, newProtocolFee } = opts;
7
+ if (prevLpFee == null)
8
+ return;
9
+ const prevTotal = prevLpFee + (prevProtocolFee ?? 0);
10
+ const newTotal = newLpFee + newProtocolFee;
11
+ if (prevTotal === newTotal)
12
+ return;
13
+ const addr = pool_address.toLowerCase();
14
+ const prevBps = (prevTotal / 100).toFixed(2);
15
+ const newBps = (newTotal / 100).toFixed(2);
16
+ ttd_core_1.ALERT_TYPES.QUOTE_HOOK_FEE_CHANGE.reportIfChanged(addr, true, () => ({
17
+ identity: addr,
18
+ scope: { dex_id, pool_address: addr },
19
+ title: `${pool_name || addr.slice(0, 10)} hook fee ${prevBps}bps → ${newBps}bps`,
20
+ detail: {
21
+ pool_name: pool_name || '',
22
+ block_number,
23
+ prev_lp_fee_ppm: prevLpFee,
24
+ prev_protocol_fee_ppm: prevProtocolFee ?? 0,
25
+ prev_total_ppm: prevTotal,
26
+ new_lp_fee_ppm: newLpFee,
27
+ new_protocol_fee_ppm: newProtocolFee,
28
+ new_total_ppm: newTotal,
29
+ delta_ppm: newTotal - prevTotal,
30
+ },
31
+ }));
32
+ }
@@ -6,3 +6,4 @@ export * from './verify';
6
6
  export * from './price_feed_handler';
7
7
  export * from './quote_amount';
8
8
  export * from './preload_token_prices';
9
+ export * from './hook_fee_monitor';
@@ -22,3 +22,4 @@ __exportStar(require("./verify"), exports);
22
22
  __exportStar(require("./price_feed_handler"), exports);
23
23
  __exportStar(require("./quote_amount"), exports);
24
24
  __exportStar(require("./preload_token_prices"), exports);
25
+ __exportStar(require("./hook_fee_monitor"), exports);
@@ -1,4 +1,6 @@
1
1
  import { AmmPoolState, ClmmPoolState, InfinityPoolState } from "../../types/pool_state";
2
+ declare function withInitRetry<T>(fn: () => Promise<T>, label: string): Promise<T>;
3
+ export { withInitRetry };
2
4
  export declare class PoolStateInitializer {
3
5
  static initAmmPool(provider: any, poolAddress: string, dexId: string, ethersLib: any): Promise<AmmPoolState>;
4
6
  static initClmmPool(provider: any, poolAddress: string, ethersLib: any, poolAbi?: any[]): Promise<ClmmPoolState>;
@@ -1,7 +1,32 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PoolStateInitializer = void 0;
4
+ exports.withInitRetry = withInitRetry;
4
5
  const ttd_core_1 = require("@clonegod/ttd-core");
6
+ async function withInitRetry(fn, label) {
7
+ try {
8
+ return await fn();
9
+ }
10
+ catch (err) {
11
+ (0, ttd_core_1.log_warn)(`[PoolStateInitializer] ${label} attempt 1 failed: ${err?.message || err}, retrying once...`);
12
+ try {
13
+ return await fn();
14
+ }
15
+ catch (err2) {
16
+ (0, ttd_core_1.log_error)(`[PoolStateInitializer] ${label} retry also failed`, err2 instanceof Error ? err2 : new Error(String(err2)));
17
+ const addrMatch = label.match(/0x[0-9a-fA-F]+/);
18
+ const identity = (addrMatch?.[0] || label).toLowerCase();
19
+ ttd_core_1.ALERT_TYPES.QUOTE_POOL_INIT_FAILED.report({
20
+ severity: 'critical',
21
+ identity,
22
+ scope: { pool_address: addrMatch ? identity : undefined },
23
+ title: `Pool init failed: ${label} — ${err2?.message || err2}`,
24
+ detail: { label, error: String(err2?.message || err2), stack: err2?.stack },
25
+ });
26
+ throw err2;
27
+ }
28
+ }
29
+ }
5
30
  const V2_PAIR_ABI = [
6
31
  'function token0() view returns (address)',
7
32
  'function token1() view returns (address)',
@@ -30,17 +55,17 @@ class PoolStateInitializer {
30
55
  poolContract.token0(),
31
56
  poolContract.token1(),
32
57
  ]);
33
- const fee = AMM_FEE_MAP[dexId] || AMM_FEE_MAP[dexId.replace('-', '_')] || 30;
58
+ const feeRateBps = AMM_FEE_MAP[dexId] || AMM_FEE_MAP[dexId.replace('-', '_')] || 30;
34
59
  const state = {
35
60
  address: poolAddress,
36
61
  token0: token0.toLowerCase(),
37
62
  token1: token1.toLowerCase(),
38
- fee,
63
+ feeRateBps,
39
64
  reserve0: reserves[0].toString(),
40
65
  reserve1: reserves[1].toString(),
41
66
  };
42
67
  (0, ttd_core_1.log_info)(`[PoolStateInitializer] AMM pool initialized: ${poolAddress}`, {
43
- token0: state.token0, token1: state.token1, fee: state.fee,
68
+ token0: state.token0, token1: state.token1, feeRateBps: state.feeRateBps,
44
69
  });
45
70
  return state;
46
71
  }
@@ -62,11 +87,13 @@ class PoolStateInitializer {
62
87
  poolContract.liquidity(),
63
88
  ]);
64
89
  const [sqrtPriceX96, tick] = slot0;
90
+ const feeRatePpm = Number(fee);
65
91
  const state = {
66
92
  address: poolAddress,
67
93
  token0: token0.toLowerCase(),
68
94
  token1: token1.toLowerCase(),
69
- fee: Number(fee),
95
+ feeRateBps: feeRatePpm / 100,
96
+ feeRatePpm,
70
97
  tickSpacing: Number(tickSpacing),
71
98
  tick: Number(tick),
72
99
  sqrtPriceX96: sqrtPriceX96.toString(),
@@ -74,7 +101,8 @@ class PoolStateInitializer {
74
101
  };
75
102
  (0, ttd_core_1.log_info)(`[PoolStateInitializer] CLMM pool initialized: ${poolAddress}`, {
76
103
  token0: state.token0, token1: state.token1,
77
- fee: state.fee, tickSpacing: state.tickSpacing, tick: state.tick,
104
+ feeRateBps: state.feeRateBps, feeRatePpm: state.feeRatePpm,
105
+ tickSpacing: state.tickSpacing, tick: state.tick,
78
106
  });
79
107
  return state;
80
108
  }
@@ -98,7 +126,8 @@ class PoolStateInitializer {
98
126
  address: poolKey,
99
127
  token0: currency0.toLowerCase ? currency0.toLowerCase() : currency0,
100
128
  token1: currency1.toLowerCase ? currency1.toLowerCase() : currency1,
101
- fee: Number(fee),
129
+ feeRateBps: (Number(lpFee) + Number(protocolFee)) / 100,
130
+ feeRatePpm: Number(fee),
102
131
  tickSpacing,
103
132
  tick: Number(tick),
104
133
  sqrtPriceX96: sqrtPriceX96.toString(),
@@ -113,7 +142,8 @@ class PoolStateInitializer {
113
142
  };
114
143
  (0, ttd_core_1.log_info)(`[PoolStateInitializer] Infinity pool initialized: ${poolKey}`, {
115
144
  currency0: state.currency0, currency1: state.currency1,
116
- fee: state.fee, tickSpacing: state.tickSpacing, tick: state.tick,
145
+ feeRateBps: state.feeRateBps, feeRatePpm: state.feeRatePpm,
146
+ tickSpacing: state.tickSpacing, tick: state.tick,
117
147
  lpFee: state.lpFee, protocolFee: state.protocolFee,
118
148
  });
119
149
  return state;
@@ -1,3 +1,4 @@
1
+ import { QuoteTier } from '@clonegod/ttd-core';
1
2
  export interface CheckSwapParams {
2
3
  poolAddress: string;
3
4
  poolName: string;
@@ -19,7 +20,10 @@ export interface CheckSwapParams {
19
20
  export declare class QuotePriceVerify {
20
21
  private quoteCache;
21
22
  private get enabled();
22
- cacheQuote(poolAddress: string, priceId: string, source: string, askPrice: number, bidPrice: number, blockNumber: number, quoteAmountUsd: number, token0PriceUsd?: number, token1PriceUsd?: number): void;
23
+ cacheQuote(poolAddress: string, priceId: string, source: string, askPrice: number, bidPrice: number, blockNumber: number, quoteAmountUsd: number, token0PriceUsd?: number, token1PriceUsd?: number, tiers?: {
24
+ askTiers?: QuoteTier[];
25
+ bidTiers?: QuoteTier[];
26
+ }): void;
23
27
  checkSwap(params: CheckSwapParams): void;
24
28
  private deriveSwapDirection;
25
29
  private compareAndLog;
@@ -3,6 +3,48 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.QuotePriceVerify = void 0;
4
4
  const trade_direction_1 = require("../../utils/trade_direction");
5
5
  const ttd_core_1 = require("@clonegod/ttd-core");
6
+ function pickMatchingTier(tiers, actualAmountIn) {
7
+ if (!tiers || tiers.length === 0)
8
+ return null;
9
+ if (tiers.length === 1)
10
+ return { tier: tiers[0], mode: 'single_tier' };
11
+ const sorted = [...tiers].sort((a, b) => a.amount_in - b.amount_in);
12
+ const top = sorted[sorted.length - 1];
13
+ if (actualAmountIn < sorted[0].amount_in) {
14
+ return { tier: sorted[0], mode: 'extrapolated_low' };
15
+ }
16
+ if (actualAmountIn > top.amount_in) {
17
+ return { tier: top, mode: 'extrapolated_high' };
18
+ }
19
+ for (let i = 0; i < sorted.length - 1; i++) {
20
+ const lower = sorted[i];
21
+ const upper = sorted[i + 1];
22
+ if (actualAmountIn >= lower.amount_in && actualAmountIn <= upper.amount_in) {
23
+ if (actualAmountIn === lower.amount_in)
24
+ return { tier: lower, mode: 'exact' };
25
+ if (actualAmountIn === upper.amount_in)
26
+ return { tier: upper, mode: 'exact' };
27
+ const span = upper.amount_in - lower.amount_in;
28
+ if (span <= 0)
29
+ return { tier: lower, mode: 'exact' };
30
+ const ratio = (actualAmountIn - lower.amount_in) / span;
31
+ const lerp = (a, b) => a + ratio * (b - a);
32
+ return {
33
+ tier: {
34
+ pct: lerp(lower.pct, upper.pct),
35
+ price: lerp(lower.price, upper.price),
36
+ amount: lerp(lower.amount, upper.amount),
37
+ amount_in: actualAmountIn,
38
+ amount_in_usd: lerp(lower.amount_in_usd, upper.amount_in_usd),
39
+ fee: lerp(lower.fee, upper.fee),
40
+ fee_usd: lerp(lower.fee_usd, upper.fee_usd),
41
+ },
42
+ mode: 'interpolated',
43
+ };
44
+ }
45
+ }
46
+ return { tier: top, mode: 'extrapolated_high' };
47
+ }
6
48
  class QuotePriceVerify {
7
49
  constructor() {
8
50
  this.quoteCache = new Map();
@@ -10,7 +52,7 @@ class QuotePriceVerify {
10
52
  get enabled() {
11
53
  return process.env.VERIFY_QUOTE_PRICE === 'true';
12
54
  }
13
- cacheQuote(poolAddress, priceId, source, askPrice, bidPrice, blockNumber, quoteAmountUsd, token0PriceUsd = 0, token1PriceUsd = 0) {
55
+ cacheQuote(poolAddress, priceId, source, askPrice, bidPrice, blockNumber, quoteAmountUsd, token0PriceUsd = 0, token1PriceUsd = 0, tiers) {
14
56
  if (!this.enabled)
15
57
  return;
16
58
  if (!source)
@@ -26,6 +68,8 @@ class QuotePriceVerify {
26
68
  : 0;
27
69
  sourceMap.set(source, {
28
70
  priceId, source, askPrice, bidPrice,
71
+ askTiers: tiers?.askTiers,
72
+ bidTiers: tiers?.bidTiers,
29
73
  referenceBlock: blockNumber,
30
74
  verifiedReferenceBlock,
31
75
  quoteAmountUsd,
@@ -55,12 +99,28 @@ class QuotePriceVerify {
55
99
  continue;
56
100
  if (cached.verifiedReferenceBlock === cached.referenceBlock)
57
101
  continue;
58
- const refPrice = isBuy ? cached.askPrice : cached.bidPrice;
102
+ const tiers = isBuy ? cached.askTiers : cached.bidTiers;
103
+ let refPrice;
104
+ let tierInfo;
105
+ if (tiers && tiers.length > 0) {
106
+ const match = pickMatchingTier(tiers, swapData.inputAmountUi);
107
+ if (!match)
108
+ continue;
109
+ refPrice = match.tier.price;
110
+ tierInfo = {
111
+ matched_pct: parseFloat(match.tier.pct.toFixed(4)),
112
+ mode: match.mode,
113
+ tier_amount_in: match.tier.amount_in,
114
+ };
115
+ }
116
+ else {
117
+ refPrice = isBuy ? cached.askPrice : cached.bidPrice;
118
+ }
59
119
  if (refPrice <= 0)
60
120
  continue;
61
121
  cached.verifiedReferenceBlock = cached.referenceBlock;
62
122
  const diff_bps = (refPrice - execPrice) / refPrice * 10000;
63
- verifiable.push({ source, cached, refPrice, diff_bps });
123
+ verifiable.push({ source, cached, refPrice, diff_bps, tierInfo });
64
124
  }
65
125
  if (verifiable.length === 0)
66
126
  return;
@@ -73,9 +133,14 @@ class QuotePriceVerify {
73
133
  bid: r.cached.bidPrice,
74
134
  diff_bps: parseFloat(r.diff_bps.toFixed(1)),
75
135
  quote_block: r.cached.referenceBlock,
136
+ ...(r.tierInfo && {
137
+ matched_pct: r.tierInfo.matched_pct,
138
+ tier_mode: r.tierInfo.mode,
139
+ tier_amount_in: r.tierInfo.tier_amount_in,
140
+ }),
76
141
  };
77
142
  }
78
- this.compareAndLog(poolAddress, params.poolName, poolInfo, primary.cached, swapData.inputTokenAddress, swapData.outputTokenAddress, swapData.inputAmountUi, swapData.outputAmountUi, primary.cached.token0PriceUsd, primary.cached.token1PriceUsd, token0Address, blockNumber, txHash, sources);
143
+ this.compareAndLog(poolAddress, params.poolName, poolInfo, primary.cached, swapData.inputTokenAddress, swapData.outputTokenAddress, swapData.inputAmountUi, swapData.outputAmountUi, primary.refPrice, execPrice, primary.cached.token0PriceUsd, primary.cached.token1PriceUsd, token0Address, blockNumber, txHash, sources, primary.tierInfo);
79
144
  }
80
145
  deriveSwapDirection(params) {
81
146
  const { amount0, amount1, token0Address, token1Address, token0Decimals, token1Decimals } = params;
@@ -102,7 +167,7 @@ class QuotePriceVerify {
102
167
  }
103
168
  return null;
104
169
  }
105
- compareAndLog(poolAddress, poolName, poolInfo, cached, inputTokenAddress, outputTokenAddress, inputAmountUi, outputAmountUi, token0PriceUsd, token1PriceUsd, token0Address, swapBlockNumber, txHash, sources) {
170
+ compareAndLog(poolAddress, poolName, poolInfo, cached, inputTokenAddress, outputTokenAddress, inputAmountUi, outputAmountUi, refPrice, execPriceNum, token0PriceUsd, token1PriceUsd, token0Address, swapBlockNumber, txHash, sources, primaryTierInfo) {
106
171
  if (inputAmountUi <= 0 || outputAmountUi <= 0)
107
172
  return;
108
173
  let swapUsd = 0;
@@ -117,9 +182,6 @@ class QuotePriceVerify {
117
182
  const quoteToken = direction.quoteToken;
118
183
  const inputIsQuoteToken = inputTokenAddress.toLowerCase() === quoteToken.address.toLowerCase();
119
184
  const isBuy = inputIsQuoteToken;
120
- const execPrice = (0, trade_direction_1.calculateStandardPrice)(inputAmountUi, outputAmountUi, isBuy);
121
- const execPriceNum = Number(execPrice);
122
- const refPrice = isBuy ? cached.askPrice : cached.bidPrice;
123
185
  const side = isBuy ? 'BUY' : 'SELL';
124
186
  if (refPrice <= 0 || execPriceNum <= 0)
125
187
  return;
@@ -164,6 +226,11 @@ class QuotePriceVerify {
164
226
  status,
165
227
  time: Date.now(),
166
228
  sources: sources || undefined,
229
+ ...(primaryTierInfo && {
230
+ matched_tier_pct: primaryTierInfo.matched_pct,
231
+ matched_tier_mode: primaryTierInfo.mode,
232
+ matched_tier_amount_in: primaryTierInfo.tier_amount_in,
233
+ }),
167
234
  });
168
235
  }
169
236
  catch (_) {
@@ -238,6 +238,13 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
238
238
  if (!txid) {
239
239
  trace.markError('exhaust', `failed after ${maxAttempts} attempts`);
240
240
  trace.flush();
241
+ const groupId = this.appConfig.trade_runtime?.group?.id;
242
+ ttd_core_1.ALERT_TYPES.TRADE_BUILDER_REJECTED.report({
243
+ identity: caller.address.toLowerCase(),
244
+ scope: { caller_address: caller.address.toLowerCase(), group_id: groupId },
245
+ title: `Trade execution exhausted after ${maxAttempts} attempts (order ${order_trace_id})`,
246
+ detail: { order_trace_id, attempts: maxAttempts, last_nonce: nonce, last_error_nonce: nonce_from_error },
247
+ });
241
248
  throw new Error(`交易执行失败,已重试 ${maxAttempts} 次,orderId: ${order_trace_id}`);
242
249
  }
243
250
  return txid;
@@ -117,6 +117,12 @@ class AbstractTxResultChecker extends trade_1.AbstractTransactionResultCheck {
117
117
  }
118
118
  else {
119
119
  clearInterval(intervalId);
120
+ ttd_core_1.ALERT_TYPES.TRADE_TX_PENDING_TOO_LONG.report({
121
+ identity: String(this.txid).toLowerCase(),
122
+ scope: { pool_address: this.pool_info?.pool_address?.toLowerCase() },
123
+ title: `Tx pending > ${check_timeout}ms: ${this.txid}`,
124
+ detail: { txid: this.txid, timeout_ms: check_timeout, checks: this.check_count },
125
+ });
120
126
  }
121
127
  }
122
128
  catch (err) {
@@ -155,6 +161,23 @@ class AbstractTxResultChecker extends trade_1.AbstractTransactionResultCheck {
155
161
  }
156
162
  else {
157
163
  this.event_emitter.emit(ttd_core_1.TRANSACTION_STATE_FAILED, trade_result);
164
+ const status = txReceipt?.status;
165
+ if (status === 0) {
166
+ ttd_core_1.ALERT_TYPES.TRADE_VAULT_REVERT.report({
167
+ identity: String(this.txid).toLowerCase(),
168
+ scope: { pool_address: this.pool_info?.pool_address?.toLowerCase() },
169
+ title: `Vault revert: tx=${this.txid}`,
170
+ detail: { txid: this.txid, status, source, gas_used: txReceipt?.gasUsed?.toString?.() },
171
+ });
172
+ }
173
+ else {
174
+ ttd_core_1.ALERT_TYPES.TRADE_RESULT_MISSING.report({
175
+ identity: String(this.txid).toLowerCase(),
176
+ scope: { pool_address: this.pool_info?.pool_address?.toLowerCase() },
177
+ title: `TradeResult event missing: tx=${this.txid}`,
178
+ detail: { txid: this.txid, status, source, parse_result: trade_result },
179
+ });
180
+ }
158
181
  }
159
182
  if (source === 'interval') {
160
183
  console.log('--------------------- Transaction Result from Polling ---------------------');
@@ -2,7 +2,7 @@ export interface OnchainPoolData {
2
2
  address: string;
3
3
  token0: string;
4
4
  token1: string;
5
- fee: number;
5
+ feeRateBps: number;
6
6
  tickSpacing: number;
7
7
  reserve0: string;
8
8
  reserve1: string;
@@ -14,7 +14,7 @@ export interface AmmPoolState {
14
14
  address: string;
15
15
  token0: string;
16
16
  token1: string;
17
- fee: number;
17
+ feeRateBps: number;
18
18
  reserve0: string;
19
19
  reserve1: string;
20
20
  }
@@ -22,7 +22,8 @@ export interface ClmmPoolState {
22
22
  address: string;
23
23
  token0: string;
24
24
  token1: string;
25
- fee: number;
25
+ feeRateBps: number;
26
+ feeRatePpm: number;
26
27
  tickSpacing: number;
27
28
  tick: number;
28
29
  sqrtPriceX96: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clonegod/ttd-bsc-common",
3
- "version": "3.1.66",
3
+ "version": "3.1.67",
4
4
  "description": "BSC common library",
5
5
  "license": "UNLICENSED",
6
6
  "main": "dist/index.js",
@@ -14,7 +14,7 @@
14
14
  "push": "npm run build && npm publish"
15
15
  },
16
16
  "dependencies": {
17
- "@clonegod/ttd-core": "3.1.55",
17
+ "@clonegod/ttd-core": "3.1.57",
18
18
  "axios": "1.15.0",
19
19
  "dotenv": "^16.4.7",
20
20
  "ethers": "^5.8.0",