openttt 0.2.11 → 0.2.13

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.
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ /**
3
+ * tls_binding.ts — RFC 5705 TLS Exporter binding for TTTPS
4
+ *
5
+ * Implements Section 7.1 of draft-helmprotocol-tttps-02:
6
+ * binding_key = TLS-Exporter("EXPORTER-tttps-pot-binding",
7
+ * pot_record_without_sig, 32)
8
+ *
9
+ * Both client and server derive the same 32-byte key from the
10
+ * shared TLS session master secret. A PoT frame generated in
11
+ * session A cannot be replayed into session B.
12
+ *
13
+ * Node.js API: tls.TLSSocket.exportKeyingMaterial()
14
+ * Available since Node.js 13.x (LTS 14+)
15
+ * RFC 5705 compliant.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.TLSBindingError = exports.TTTPS_BINDING_KEY_LENGTH = exports.TTTPS_EXPORTER_LABEL = void 0;
19
+ exports.computeBindingKey = computeBindingKey;
20
+ exports.verifyBindingKey = verifyBindingKey;
21
+ /** Label defined in draft-helmprotocol-tttps-02 Section 7.1 */
22
+ exports.TTTPS_EXPORTER_LABEL = "EXPORTER-tttps-pot-binding";
23
+ exports.TTTPS_BINDING_KEY_LENGTH = 32; // octets per RFC 5705
24
+ class TLSBindingError extends Error {
25
+ constructor(message) {
26
+ super(message);
27
+ this.name = "TLSBindingError";
28
+ }
29
+ }
30
+ exports.TLSBindingError = TLSBindingError;
31
+ /**
32
+ * Derive the 32-byte binding key from a TLS session and a PoT record.
33
+ *
34
+ * @param socket - Active TLS socket (must be in CONNECTED state)
35
+ * @param potWithoutSig - PoT record bytes WITHOUT the Ed25519 signature
36
+ * (first 79 bytes of the 143-byte record:
37
+ * Version[1] + Tier[1] + Reserved[1] +
38
+ * Timestamp[8] + Confidence[4] +
39
+ * Nonce[32] + GRGCommit[32])
40
+ * @returns 32-byte binding key
41
+ */
42
+ function computeBindingKey(socket, potWithoutSig) {
43
+ if (!socket.encrypted) {
44
+ throw new TLSBindingError("Socket is not a TLS socket");
45
+ }
46
+ // exportKeyingMaterial(length, label, context, useContextFlag?)
47
+ // context = pot_record_without_sig per RFC 5705 Section 4
48
+ const bindingKey = socket.exportKeyingMaterial(exports.TTTPS_BINDING_KEY_LENGTH, exports.TTTPS_EXPORTER_LABEL, potWithoutSig // context bound to this specific PoT record
49
+ );
50
+ const sessionId = socket.getSession?.()?.toString("hex").slice(0, 16) ?? "unknown";
51
+ return {
52
+ bindingKey: Buffer.from(bindingKey),
53
+ sessionId,
54
+ };
55
+ }
56
+ /**
57
+ * Verify that a received binding_key matches the expected value
58
+ * for this TLS session and PoT record.
59
+ *
60
+ * This is the normative check from draft-helmprotocol-tttps-02 Section 7.1:
61
+ * "The verifier MUST recompute expected_key via TLS-Exporter
62
+ * and verify it matches the binding_key in the PoT frame header."
63
+ *
64
+ * @param socket - Active TLS socket (same session as sender)
65
+ * @param potWithoutSig - PoT record bytes WITHOUT signature (79 bytes)
66
+ * @param receivedBindingKey - 32-byte binding_key from the received PoT frame
67
+ * @returns true if binding is valid, false if cross-session replay detected
68
+ */
69
+ function verifyBindingKey(socket, potWithoutSig, receivedBindingKey) {
70
+ if (receivedBindingKey.length !== exports.TTTPS_BINDING_KEY_LENGTH) {
71
+ return false;
72
+ }
73
+ const { bindingKey: expected } = computeBindingKey(socket, potWithoutSig);
74
+ // Constant-time comparison (prevents timing attacks)
75
+ return timingSafeEqual(expected, receivedBindingKey);
76
+ }
77
+ /**
78
+ * Constant-time Buffer comparison.
79
+ * Node.js crypto.timingSafeEqual requires equal-length buffers.
80
+ */
81
+ function timingSafeEqual(a, b) {
82
+ if (a.length !== b.length)
83
+ return false;
84
+ const { timingSafeEqual } = require("crypto");
85
+ return timingSafeEqual(a, b);
86
+ }
package/dist/v4_hook.d.ts CHANGED
@@ -1,7 +1,12 @@
1
1
  import { EVMConnector } from "./evm_connector";
2
- import { ProtocolFeeCollector } from "./protocol_fee";
3
- import { FeeCalculation } from "./dynamic_fee";
4
2
  import { BeforeSwapParams, AfterSwapParams } from "./types";
3
+ export interface FeeCalculation {
4
+ feeAmount: bigint;
5
+ tier: string;
6
+ }
7
+ export interface ProtocolFeeCollector {
8
+ collectBurnFee(fee: FeeCalculation, signature: string, sender: string, nonce: bigint, deadline: number): Promise<void>;
9
+ }
5
10
  /**
6
11
  * UniswapV4Hook - TTT-based Uniswap V4 Hook Simulation (SDK-side)
7
12
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "openttt",
3
- "version": "0.2.11",
4
- "description": "OpenTTT \u2014 TLS-grade transaction ordering for DeFi. Time + Logic + Sync.",
3
+ "version": "0.2.13",
4
+ "description": "OpenTTT TLS-grade transaction ordering for DeFi. Time + Logic + Sync.",
5
5
  "license": "BSL-1.1",
6
6
  "repository": {
7
7
  "type": "git",
@@ -29,10 +29,10 @@
29
29
  }
30
30
  },
31
31
  "files": [
32
+ "dist/adaptive_switch.js",
33
+ "dist/adaptive_switch.d.ts",
32
34
  "dist/ct_log.js",
33
35
  "dist/ct_log.d.ts",
34
- "dist/dynamic_fee.js",
35
- "dist/dynamic_fee.d.ts",
36
36
  "dist/errors.js",
37
37
  "dist/errors.d.ts",
38
38
  "dist/evm_connector.js",
@@ -51,24 +51,24 @@
51
51
  "dist/osnma_source.d.ts",
52
52
  "dist/pool_registry.js",
53
53
  "dist/pool_registry.d.ts",
54
+ "dist/pot_frame.js",
55
+ "dist/pot_frame.d.ts",
54
56
  "dist/pot_signer.js",
55
57
  "dist/pot_signer.d.ts",
56
- "dist/protocol_fee.js",
57
- "dist/protocol_fee.d.ts",
58
- "dist/revenue_tiers.js",
59
- "dist/revenue_tiers.d.ts",
58
+ "dist/pot_verifier.js",
59
+ "dist/pot_verifier.d.ts",
60
60
  "dist/signer.js",
61
61
  "dist/signer.d.ts",
62
62
  "dist/time_synthesis.js",
63
63
  "dist/time_synthesis.d.ts",
64
+ "dist/tls_binding.js",
65
+ "dist/tls_binding.d.ts",
64
66
  "dist/trust_store.js",
65
67
  "dist/trust_store.d.ts",
66
68
  "dist/types.js",
67
69
  "dist/types.d.ts",
68
70
  "dist/v4_hook.js",
69
71
  "dist/v4_hook.d.ts",
70
- "dist/x402_enforcer.js",
71
- "dist/x402_enforcer.d.ts",
72
72
  "README.md"
73
73
  ],
74
74
  "scripts": {
@@ -104,5 +104,11 @@
104
104
  "ts-jest": "^29.1.2",
105
105
  "typescript": "^5.3.3"
106
106
  },
107
- "mcpName": "io.github.Helm-Protocol/openttt-pot"
107
+ "mcpName": "io.github.Helm-Protocol/openttt-pot",
108
+ "overrides": {
109
+ "defu": ">=6.1.4",
110
+ "picomatch": ">=4.0.2",
111
+ "handlebars": ">=4.7.9",
112
+ "ws": ">=8.21.0"
113
+ }
108
114
  }
@@ -1,75 +0,0 @@
1
- export declare const TIER_USD_MICRO: Record<string, bigint>;
2
- export declare const FEE_TIERS: {
3
- BOOTSTRAP: {
4
- mintFee: bigint;
5
- burnFee: bigint;
6
- threshold: bigint;
7
- };
8
- GROWTH: {
9
- mintFee: bigint;
10
- burnFee: bigint;
11
- threshold: bigint;
12
- };
13
- MATURE: {
14
- mintFee: bigint;
15
- burnFee: bigint;
16
- threshold: bigint;
17
- };
18
- PREMIUM: {
19
- mintFee: bigint;
20
- burnFee: bigint;
21
- threshold: bigint;
22
- };
23
- };
24
- export interface FeeCalculation {
25
- tttAmount: bigint;
26
- protocolFeeUsd: bigint;
27
- feeToken: string;
28
- feeTokenAddress: string;
29
- clientNet: bigint;
30
- tttPriceUsd: bigint;
31
- usdCost: bigint;
32
- feeRateMint: bigint;
33
- feeRateBurn: bigint;
34
- tier: string;
35
- }
36
- export interface PriceOracleConfig {
37
- poolAddress?: string;
38
- chainlinkFeed?: string;
39
- cacheDurationMs: number;
40
- fallbackPriceUsd: bigint;
41
- }
42
- export declare class DynamicFeeEngine {
43
- private priceCache;
44
- private provider;
45
- private rpcUrls;
46
- private config;
47
- private warnedSpotPrice;
48
- private static readonly RECOMMENDED_MAX_CACHE_MS;
49
- constructor(config: PriceOracleConfig);
50
- /**
51
- * Connect to an RPC provider. Accepts a single URL or an array of URLs
52
- * for multi-RPC fallback. On connection failure, the next URL is tried.
53
- */
54
- connect(rpcUrl: string | string[]): Promise<void>;
55
- /**
56
- * Iterate through stored RPC URLs and connect to the first one that succeeds.
57
- * Throws if all URLs fail.
58
- */
59
- private connectToNext;
60
- getTTTPriceUsd(): Promise<bigint>;
61
- /**
62
- * Force-invalidate price cache -- call when immediate price refresh is needed.
63
- */
64
- invalidateCache(): void;
65
- private fetchUniswapPrice;
66
- private fetchChainlinkPrice;
67
- getFeeRate(tttPriceUsd: bigint): {
68
- mintFee: bigint;
69
- burnFee: bigint;
70
- phase: string;
71
- };
72
- calculateMintFee(tier: string, tickCount?: number, feeToken?: string, feeTokenAddress?: string): Promise<FeeCalculation>;
73
- calculateBurnFee(tier: string, tickCount?: number, feeToken?: string, feeTokenAddress?: string): Promise<FeeCalculation>;
74
- calculateEmergencyMintFee(tier: string, tickCount?: number): Promise<FeeCalculation>;
75
- }
@@ -1,254 +0,0 @@
1
- "use strict";
2
- // sdk/src/dynamic_fee.ts — Dynamic Fee Engine
3
- // Automatically adjusts tick cost based on TTT market price
4
- // DEX operators only set tier; the SDK handles the rest automatically
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DynamicFeeEngine = exports.FEE_TIERS = exports.TIER_USD_MICRO = void 0;
7
- const ethers_1 = require("ethers");
8
- const logger_1 = require("./logger");
9
- // Target USD cost per tier (Scale: 1e6)
10
- //
11
- // PRICING (2026-03-14 감사 수정):
12
- // T2/T3 가격 하향 — 감사 결과 "트랜잭션당 1틱 소비" 구조에서
13
- // 매 틱 판매 가정은 비현실적. 볼륨 기반 수익 구조로 전환.
14
- // T2: $0.24 → $0.05 (4.8x 하향)
15
- // T3: $12.00 → $0.10 (120x 하향)
16
- //
17
- // YP discrepancies (code is authoritative in all cases):
18
- // YP5: TURBO entry threshold — YP says 90%, code uses 95% (more conservative).
19
- // YP6: BOOTSTRAP mintFee — YP says 3%, code uses 5% (500 basis points).
20
- // YP7: PoT min confidence — YP says 0.7, code uses 0.5 (auto_mint.ts).
21
- exports.TIER_USD_MICRO = {
22
- T0_epoch: 1000n, // $0.001 * 1e6
23
- T1_block: 10000n, // $0.01 * 1e6
24
- T2_slot: 50000n, // $0.05 * 1e6 — 감사 수정: 볼륨 기반 수익 구조
25
- T3_micro: 100000n, // $0.10 * 1e6 — 감사 수정: 트랜잭션당 1틱 소비 기준
26
- };
27
- // Helm protocol fee tiers (Scale: 1e4, e.g., 500 = 5%)
28
- exports.FEE_TIERS = {
29
- BOOTSTRAP: { mintFee: 500n, burnFee: 200n, threshold: 5000n }, // threshold: $0.005 * 1e6
30
- GROWTH: { mintFee: 1000n, burnFee: 300n, threshold: 50000n }, // threshold: $0.05 * 1e6
31
- MATURE: { mintFee: 1000n, burnFee: 500n, threshold: 500000n }, // threshold: $0.50 * 1e6
32
- PREMIUM: { mintFee: 800n, burnFee: 500n, threshold: -1n }, // Infinity replacement
33
- };
34
- class DynamicFeeEngine {
35
- priceCache = null;
36
- provider = null;
37
- rpcUrls = [];
38
- config;
39
- warnedSpotPrice = false;
40
- // P2-3: Recommended max cache duration for DEX price freshness
41
- static RECOMMENDED_MAX_CACHE_MS = 5000;
42
- constructor(config) {
43
- // R3-P0-1: Prevent division by zero in all fee calculations
44
- if (config.fallbackPriceUsd <= 0n) {
45
- throw new Error(`[DynamicFee] fallbackPriceUsd must be > 0, got: ${config.fallbackPriceUsd}`);
46
- }
47
- this.config = config;
48
- // P2-3: Warn if cache duration is too long for DEX pricing
49
- if (config.cacheDurationMs > DynamicFeeEngine.RECOMMENDED_MAX_CACHE_MS) {
50
- logger_1.logger.warn(`[DynamicFee] cacheDurationMs=${config.cacheDurationMs}ms exceeds recommended ${DynamicFeeEngine.RECOMMENDED_MAX_CACHE_MS}ms for DEX pricing accuracy`);
51
- }
52
- }
53
- /**
54
- * Connect to an RPC provider. Accepts a single URL or an array of URLs
55
- * for multi-RPC fallback. On connection failure, the next URL is tried.
56
- */
57
- async connect(rpcUrl) {
58
- const urls = Array.isArray(rpcUrl) ? rpcUrl : [rpcUrl];
59
- if (urls.length === 0 || urls.every(u => !u)) {
60
- throw new Error("[DynamicFee] At least one valid RPC URL is required");
61
- }
62
- this.rpcUrls = urls.filter(u => !!u);
63
- await this.connectToNext();
64
- }
65
- /**
66
- * Iterate through stored RPC URLs and connect to the first one that succeeds.
67
- * Throws if all URLs fail.
68
- */
69
- async connectToNext() {
70
- let lastError = null;
71
- for (const url of this.rpcUrls) {
72
- try {
73
- const provider = new ethers_1.JsonRpcProvider(url);
74
- // Verify connectivity by requesting the network
75
- await provider.getNetwork();
76
- this.provider = provider;
77
- logger_1.logger.info(`[DynamicFee] Connected to RPC: ${url}`);
78
- return;
79
- }
80
- catch (err) {
81
- lastError = err instanceof Error ? err : new Error(String(err));
82
- logger_1.logger.warn(`[DynamicFee] RPC connection failed for ${url}: ${lastError.message}`);
83
- }
84
- }
85
- // If all URLs failed, fall back to the first URL without connectivity check
86
- // so that subsequent calls can still attempt requests
87
- this.provider = new ethers_1.JsonRpcProvider(this.rpcUrls[0]);
88
- logger_1.logger.warn(`[DynamicFee] All RPC URLs failed connectivity check, using first URL as fallback`);
89
- }
90
- async getTTTPriceUsd() {
91
- const now = Date.now();
92
- if (this.priceCache && (now - this.priceCache.timestamp) < this.config.cacheDurationMs) {
93
- return this.priceCache.price;
94
- }
95
- try {
96
- let price;
97
- // R4-P1-2: Chainlink FIRST (resistant to flash loan), Uniswap spot as fallback only
98
- if (this.config.chainlinkFeed && this.provider) {
99
- price = await this.fetchChainlinkPrice();
100
- }
101
- else if (this.config.poolAddress && this.provider) {
102
- // To suppress this warning, set `chainlinkFeed` in PriceOracleConfig to a
103
- // Chainlink AggregatorV3 address (e.g. the TTT/USD feed on your target chain).
104
- // Chainlink TWAP prices are resistant to single-block flash loan manipulation.
105
- if (!this.warnedSpotPrice) {
106
- logger_1.logger.warn("[DynamicFee] Using Uniswap spot price — vulnerable to flash loan manipulation. Configure chainlinkFeed for production.");
107
- this.warnedSpotPrice = true;
108
- }
109
- price = await this.fetchUniswapPrice();
110
- }
111
- else {
112
- price = this.config.fallbackPriceUsd;
113
- }
114
- if (price <= 0n) {
115
- logger_1.logger.warn(`[DynamicFee] Invalid price ${price}, using fallback ${this.config.fallbackPriceUsd}`);
116
- price = this.config.fallbackPriceUsd;
117
- // R3-P0-1: Double-guard — fallback validated in constructor but belt-and-suspenders
118
- if (price <= 0n)
119
- throw new Error("[DynamicFee] FATAL: fallbackPriceUsd is zero — cannot calculate fees");
120
- }
121
- this.priceCache = { price, timestamp: now };
122
- return price;
123
- }
124
- catch (error) {
125
- logger_1.logger.warn(`[DynamicFee] Price fetch failed, using fallback`);
126
- return this.config.fallbackPriceUsd;
127
- }
128
- }
129
- /**
130
- * Force-invalidate price cache -- call when immediate price refresh is needed.
131
- */
132
- invalidateCache() {
133
- this.priceCache = null;
134
- logger_1.logger.info(`[DynamicFee] Price cache invalidated`);
135
- }
136
- async fetchUniswapPrice() {
137
- if (!this.provider || !this.config.poolAddress)
138
- return this.config.fallbackPriceUsd;
139
- const stateViewAbi = ["function getSlot0(bytes32 poolId) external view returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee)"];
140
- try {
141
- const contract = new ethers_1.Contract(this.config.poolAddress, stateViewAbi, this.provider);
142
- const poolId = ethers_1.ethers.keccak256(ethers_1.ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.config.poolAddress]));
143
- const [sqrtPriceX96] = await contract.getSlot0(poolId);
144
- // B1-7: Unified Uniswap price scaling
145
- const priceScaled = (BigInt(sqrtPriceX96) * BigInt(sqrtPriceX96) * 1000000n) >> 192n;
146
- return priceScaled;
147
- }
148
- catch (error) {
149
- logger_1.logger.warn(`[DynamicFee] Uniswap price fetch failed, using fallback: ${error instanceof Error ? error.message : error}`);
150
- return this.config.fallbackPriceUsd;
151
- }
152
- }
153
- async fetchChainlinkPrice() {
154
- if (!this.provider || !this.config.chainlinkFeed)
155
- return this.config.fallbackPriceUsd;
156
- const feedAbi = ["function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)"];
157
- const MAX_PRICE = 10n ** 12n; // B1-8: Max price 10^12n
158
- try {
159
- const contract = new ethers_1.Contract(this.config.chainlinkFeed, feedAbi, this.provider);
160
- const [, answer, , updatedAt] = await contract.latestRoundData();
161
- // B1-8: Check updatedAt (within 1 hour) and price <= MAX_PRICE
162
- const now = BigInt(Math.floor(Date.now() / 1000));
163
- // P2-4: Tightened staleness check from 3600s to 1800s (30 min)
164
- if (now - BigInt(updatedAt) > 1800n) {
165
- throw new Error("Chainlink price stale (>30min)");
166
- }
167
- const price = BigInt(answer) / 100n; // 8 decimals -> 6 decimals
168
- if (price > MAX_PRICE) {
169
- throw new Error("Chainlink price exceeds MAX_PRICE");
170
- }
171
- return price;
172
- }
173
- catch (error) {
174
- logger_1.logger.warn(`[DynamicFee] Chainlink price fetch failed, using fallback: ${error instanceof Error ? error.message : error}`);
175
- return this.config.fallbackPriceUsd;
176
- }
177
- }
178
- getFeeRate(tttPriceUsd) {
179
- if (tttPriceUsd < exports.FEE_TIERS.BOOTSTRAP.threshold) {
180
- return { ...exports.FEE_TIERS.BOOTSTRAP, phase: "BOOTSTRAP" };
181
- }
182
- else if (tttPriceUsd < exports.FEE_TIERS.GROWTH.threshold) {
183
- return { ...exports.FEE_TIERS.GROWTH, phase: "GROWTH" };
184
- }
185
- else if (tttPriceUsd < exports.FEE_TIERS.MATURE.threshold) {
186
- return { ...exports.FEE_TIERS.MATURE, phase: "MATURE" };
187
- }
188
- else {
189
- return { ...exports.FEE_TIERS.PREMIUM, phase: "PREMIUM" };
190
- }
191
- }
192
- async calculateMintFee(tier, tickCount = 1, feeToken = "USDC", feeTokenAddress = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913") {
193
- // B1-4: Throw if tickCount <= 0
194
- if (tickCount <= 0)
195
- throw new Error("[DynamicFee] tickCount must be positive");
196
- if (!exports.TIER_USD_MICRO[tier])
197
- throw new Error(`[DynamicFee] Invalid tier: ${tier}`);
198
- const tttPriceUsd = await this.getTTTPriceUsd(); // 6 decimals
199
- const usdTarget = exports.TIER_USD_MICRO[tier]; // 6 decimals
200
- const feeRate = this.getFeeRate(tttPriceUsd);
201
- const totalUsdCost = usdTarget * BigInt(tickCount); // 6 decimals
202
- // tttAmount = (totalUsdCost / tttPriceUsd) * 1e18
203
- const tttAmount = (totalUsdCost * (10n ** 18n)) / tttPriceUsd;
204
- // protocolFeeUsd = totalUsdCost * feeRate / 10000
205
- const protocolFeeUsd = (totalUsdCost * feeRate.mintFee) / 10000n;
206
- return {
207
- tttAmount,
208
- protocolFeeUsd,
209
- feeToken,
210
- feeTokenAddress,
211
- clientNet: tttAmount,
212
- tttPriceUsd,
213
- usdCost: totalUsdCost + protocolFeeUsd,
214
- feeRateMint: feeRate.mintFee,
215
- feeRateBurn: feeRate.burnFee,
216
- tier,
217
- };
218
- }
219
- async calculateBurnFee(tier, tickCount = 1, feeToken = "USDC", feeTokenAddress = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913") {
220
- // B1-4: Throw if tickCount <= 0
221
- if (tickCount <= 0)
222
- throw new Error("[DynamicFee] tickCount must be positive");
223
- if (!exports.TIER_USD_MICRO[tier])
224
- throw new Error(`[DynamicFee] Invalid tier: ${tier}`);
225
- const tttPriceUsd = await this.getTTTPriceUsd();
226
- const usdTarget = exports.TIER_USD_MICRO[tier];
227
- const feeRate = this.getFeeRate(tttPriceUsd);
228
- const totalUsdCost = usdTarget * BigInt(tickCount);
229
- const tttAmount = (totalUsdCost * (10n ** 18n)) / tttPriceUsd;
230
- const protocolFeeUsd = (totalUsdCost * feeRate.burnFee) / 10000n;
231
- return {
232
- tttAmount,
233
- protocolFeeUsd,
234
- feeToken,
235
- feeTokenAddress,
236
- clientNet: tttAmount,
237
- tttPriceUsd,
238
- usdCost: totalUsdCost + protocolFeeUsd,
239
- feeRateMint: feeRate.mintFee,
240
- feeRateBurn: feeRate.burnFee,
241
- tier,
242
- };
243
- }
244
- async calculateEmergencyMintFee(tier, tickCount = 1) {
245
- const base = await this.calculateMintFee(tier, tickCount);
246
- const emergencyFeeUsd = (base.protocolFeeUsd * 150n) / 100n;
247
- return {
248
- ...base,
249
- protocolFeeUsd: emergencyFeeUsd,
250
- usdCost: (base.usdCost * 150n) / 100n,
251
- };
252
- }
253
- }
254
- exports.DynamicFeeEngine = DynamicFeeEngine;
@@ -1,72 +0,0 @@
1
- import { FeeCalculation } from "./dynamic_fee";
2
- import { EVMConnector } from "./evm_connector";
3
- /**
4
- * Pluggable replay cache interface for signature deduplication.
5
- * Implement this to use Redis, database, or other external stores.
6
- */
7
- export interface ReplayCache {
8
- has(key: string): Promise<boolean>;
9
- set(key: string, ttlMs: number): Promise<void>;
10
- }
11
- /**
12
- * Default in-memory replay cache with bounded size and TTL eviction.
13
- * Suitable for single-process deployments; use a distributed ReplayCache
14
- * implementation (e.g., Redis) for multi-node setups.
15
- */
16
- export declare class InMemoryReplayCache implements ReplayCache {
17
- private entries;
18
- private readonly maxEntries;
19
- private readonly defaultTtlMs;
20
- private lastPruneTime;
21
- private static readonly PRUNE_INTERVAL_MS;
22
- constructor(maxEntries?: number, defaultTtlMs?: number);
23
- has(key: string): Promise<boolean>;
24
- set(key: string, ttlMs: number): Promise<void>;
25
- private pruneIfNeeded;
26
- }
27
- /**
28
- * ProtocolFeeCollector - Handles Helm protocol fee collection and verification.
29
- * Includes EIP-712 signature verification for x402 compliance.
30
- */
31
- export declare class ProtocolFeeCollector {
32
- private totalCollected;
33
- private chainId;
34
- private verifyingContract;
35
- private replayCache;
36
- private evmConnector;
37
- private protocolFeeRecipient;
38
- private feeContract;
39
- constructor(chainId: number, verifyingContract: string, evmConnector: EVMConnector, protocolFeeRecipient: string, replayCache?: ReplayCache);
40
- /**
41
- * R3-P0-2: Verify chainId matches the actual connected network.
42
- * Must be called after EVMConnector.connect() to prevent cross-chain signature replay.
43
- */
44
- validateChainId(): Promise<void>;
45
- private getFeeContract;
46
- /**
47
- * Collect minting fee (Stablecoin).
48
- * @param feeCalc - Fee calculation result from DynamicFeeEngine.
49
- * @param signature - EIP-712 signature (required, for x402 verification).
50
- * @param user - Signer address.
51
- * @param nonce - Anti-replay nonce.
52
- * @param deadline - Signature expiration timestamp.
53
- */
54
- collectMintFee(feeCalc: FeeCalculation, signature: string, user: string, nonce: bigint, deadline: number): Promise<void>;
55
- /**
56
- * Collect burn fee.
57
- * @param feeCalc - Fee calculation result from DynamicFeeEngine.
58
- * @param signature - EIP-712 signature (required).
59
- * @param user - Signer address.
60
- * @param nonce - Anti-replay nonce.
61
- * @param deadline - Signature expiration timestamp.
62
- */
63
- collectBurnFee(feeCalc: FeeCalculation, signature: string, user: string, nonce: bigint, deadline: number): Promise<void>;
64
- /**
65
- * Return total fees collected so far.
66
- */
67
- getCollectedFees(): Promise<bigint>;
68
- /**
69
- * EIP-712 signature verification (x402 compliance).
70
- */
71
- private verifySignature;
72
- }