openttt 0.1.0

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.
Files changed (46) hide show
  1. package/README.md +391 -0
  2. package/dist/adaptive_switch.d.ts +44 -0
  3. package/dist/adaptive_switch.js +108 -0
  4. package/dist/auto_mint.d.ts +45 -0
  5. package/dist/auto_mint.js +244 -0
  6. package/dist/dynamic_fee.d.ts +64 -0
  7. package/dist/dynamic_fee.js +203 -0
  8. package/dist/errors.d.ts +45 -0
  9. package/dist/errors.js +74 -0
  10. package/dist/evm_connector.d.ts +88 -0
  11. package/dist/evm_connector.js +297 -0
  12. package/dist/golay.d.ts +6 -0
  13. package/dist/golay.js +166 -0
  14. package/dist/grg_forward.d.ts +6 -0
  15. package/dist/grg_forward.js +59 -0
  16. package/dist/grg_inverse.d.ts +7 -0
  17. package/dist/grg_inverse.js +97 -0
  18. package/dist/grg_pipeline.d.ts +13 -0
  19. package/dist/grg_pipeline.js +64 -0
  20. package/dist/index.d.ts +21 -0
  21. package/dist/index.js +38 -0
  22. package/dist/logger.d.ts +18 -0
  23. package/dist/logger.js +51 -0
  24. package/dist/networks.d.ts +13 -0
  25. package/dist/networks.js +23 -0
  26. package/dist/pool_registry.d.ts +58 -0
  27. package/dist/pool_registry.js +129 -0
  28. package/dist/protocol_fee.d.ts +56 -0
  29. package/dist/protocol_fee.js +176 -0
  30. package/dist/reed_solomon.d.ts +12 -0
  31. package/dist/reed_solomon.js +179 -0
  32. package/dist/signer.d.ts +76 -0
  33. package/dist/signer.js +329 -0
  34. package/dist/time_synthesis.d.ts +49 -0
  35. package/dist/time_synthesis.js +372 -0
  36. package/dist/ttt_builder.d.ts +32 -0
  37. package/dist/ttt_builder.js +84 -0
  38. package/dist/ttt_client.d.ts +118 -0
  39. package/dist/ttt_client.js +352 -0
  40. package/dist/types.d.ts +141 -0
  41. package/dist/types.js +9 -0
  42. package/dist/v4_hook.d.ts +43 -0
  43. package/dist/v4_hook.js +115 -0
  44. package/dist/x402_enforcer.d.ts +29 -0
  45. package/dist/x402_enforcer.js +67 -0
  46. package/package.json +51 -0
package/README.md ADDED
@@ -0,0 +1,391 @@
1
+ # OpenTTT
2
+
3
+ **OpenSSL for Transaction Ordering** -- TLS-grade Proof of Time for DeFi.
4
+
5
+ OpenTTT brings cryptographic time verification to blockchain transaction ordering. Where TLS made HTTP trustworthy, OpenTTT makes transaction sequencing verifiable. No trust assumptions. No gentleman's agreements. Physics.
6
+
7
+ [![npm](https://img.shields.io/npm/v/openttt)](https://www.npmjs.com/package/openttt)
8
+ [![License: BSL-1.1](https://img.shields.io/badge/License-BSL--1.1-blue.svg)](LICENSE)
9
+ [![Tests](https://img.shields.io/badge/tests-104%20passing%20%C2%B7%2018%20suites-brightgreen)]()
10
+
11
+ ```
12
+ npm install openttt
13
+ ```
14
+
15
+ ---
16
+
17
+ ## Why OpenTTT
18
+
19
+ Current MEV protection relies on **trust**: builders promise fair ordering, protocols ask nicely, and everyone hopes for the best. Flashbots asks builders to behave. OpenTTT proves whether they did.
20
+
21
+ | | Flashbots | OpenTTT |
22
+ |---|---|---|
23
+ | **Mechanism** | Social contract (request) | Physical verification (proof) |
24
+ | **Enforcement** | Reputation, exclusion | Economic natural selection |
25
+ | **Bad actors** | Must be identified and removed | Naturally unprofitable, self-selecting out |
26
+ | **Time source** | Block timestamp (miner-controlled) | Multi-source NTP synthesis (NIST, KRISS, Google) |
27
+
28
+ **The core insight**: Rollups generate precise timestamps and deliver them to builders with a receipt. The Adaptive GRG pipeline then verifies whether the builder respected that ordering:
29
+
30
+ - **Honest builder**: Sequence matches -> **Turbo mode** (50ms verification) -> faster -> more profitable
31
+ - **Dishonest builder**: Sequence mismatch -> **Full mode** (127ms verification) -> slower -> less profitable -> leaves
32
+
33
+ No governance vote. No slashing committee. Cheating is simply bad business.
34
+
35
+ ---
36
+
37
+ ## Quick Start
38
+
39
+ Three lines to start minting TimeTokens:
40
+
41
+ ```typescript
42
+ import { TTTClient } from "openttt";
43
+
44
+ const ttt = await TTTClient.forBase({
45
+ signer: { type: "privateKey", envVar: "OPERATOR_PK" },
46
+ });
47
+ ttt.startAutoMint();
48
+ ```
49
+
50
+ That is it. The SDK connects to Base Mainnet, synthesizes time from three atomic clock sources, and begins minting Proof-of-Time tokens at your configured tier interval.
51
+
52
+ ---
53
+
54
+ ## Progressive Disclosure
55
+
56
+ OpenTTT is designed around progressive disclosure. Start simple, add control as you need it.
57
+
58
+ ### Level 1 -- Just Works
59
+
60
+ ```typescript
61
+ import { TTTClient } from "openttt";
62
+
63
+ const ttt = await TTTClient.forBase({
64
+ signer: { type: "privateKey", envVar: "OPERATOR_PK" },
65
+ });
66
+ ttt.startAutoMint();
67
+ ```
68
+
69
+ ### Level 2 -- Custom Network and Tier
70
+
71
+ ```typescript
72
+ const ttt = await TTTClient.forSepolia({
73
+ signer: { type: "privateKey", key: process.env.OPERATOR_PK! },
74
+ rpcUrl: "https://my-rpc.example.com",
75
+ tier: "T2_slot",
76
+ });
77
+ ttt.startAutoMint();
78
+ ```
79
+
80
+ ### Level 3 -- Full Control
81
+
82
+ ```typescript
83
+ const ttt = await TTTClient.create({
84
+ signer: {
85
+ type: "turnkey",
86
+ apiBaseUrl: "https://api.turnkey.com",
87
+ organizationId: "org-...",
88
+ privateKeyId: "pk-...",
89
+ apiPublicKey: "...",
90
+ apiPrivateKey: "...",
91
+ },
92
+ network: "base",
93
+ tier: "T1_block",
94
+ contractAddress: "0x...",
95
+ poolAddress: "0x...",
96
+ timeSources: ["nist", "kriss", "google"],
97
+ protocolFeeRate: 0.05,
98
+ enableGracefulShutdown: true,
99
+ });
100
+
101
+ ttt.startAutoMint();
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Signer Options
107
+
108
+ OpenTTT abstracts away signer complexity. Use a raw private key for development, TEE-backed keys for production, or cloud HSMs for institutional deployments.
109
+
110
+ | Type | Use Case | Config |
111
+ |---|---|---|
112
+ | `privateKey` | Development, small operators | `{ type: "privateKey", key: "0x..." }` or `{ type: "privateKey", envVar: "OPERATOR_PK" }` |
113
+ | `turnkey` | Production, TEE-backed institutional custody | `{ type: "turnkey", apiBaseUrl, organizationId, privateKeyId, apiPublicKey, apiPrivateKey }` |
114
+ | `privy` | Embedded wallets, consumer-facing apps | `{ type: "privy", appId, appSecret }` |
115
+ | `kms` | Cloud HSM (AWS KMS or GCP Cloud KMS) | `{ type: "kms", provider: "aws"\|"gcp", keyId, ... }` |
116
+
117
+ **AWS KMS** requires `@aws-sdk/client-kms`. **GCP KMS** requires `@google-cloud/kms`. Both are optional peer dependencies -- install only what you use.
118
+
119
+ ---
120
+
121
+ ## Tiers
122
+
123
+ Tiers control the minting interval. Choose based on your protocol's ordering resolution requirements.
124
+
125
+ | Tier | Interval | Use Case |
126
+ |---|---|---|
127
+ | `T0_epoch` | 6.4 minutes | Epoch-level ordering (validator sets, beacon chain) |
128
+ | `T1_block` | 2 seconds | Block-level ordering on Base L2 **(default)** |
129
+ | `T2_slot` | 12 seconds | Slot-level ordering on Ethereum L1 |
130
+ | `T3_micro` | 100 milliseconds | High-frequency ordering (IoT, sub-block) |
131
+
132
+ ```typescript
133
+ const ttt = await TTTClient.forBase({
134
+ signer: { type: "privateKey", envVar: "OPERATOR_PK" },
135
+ tier: "T2_slot",
136
+ });
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Health Monitoring
142
+
143
+ Production deployments need observability. `getHealth()` returns a comprehensive status object covering connectivity, balance, and mint performance.
144
+
145
+ ```typescript
146
+ const health = await ttt.getHealth();
147
+
148
+ console.log(health);
149
+ // {
150
+ // healthy: true,
151
+ // checks: {
152
+ // initialized: true,
153
+ // rpcConnected: true,
154
+ // signerAvailable: true,
155
+ // balanceSufficient: true,
156
+ // ntpSourcesOk: true
157
+ // },
158
+ // metrics: {
159
+ // mintCount: 142,
160
+ // mintFailures: 0,
161
+ // successRate: 1.0,
162
+ // totalFeesPaid: "71000000000000",
163
+ // avgMintLatencyMs: 1847,
164
+ // lastMintAt: "2026-03-14T10:30:00.000Z",
165
+ // uptimeMs: 86400000
166
+ // },
167
+ // alerts: []
168
+ // }
169
+ ```
170
+
171
+ **Alerts** are emitted automatically when:
172
+ - RPC connection is lost
173
+ - ETH balance drops below threshold (default: 0.01 ETH)
174
+ - Mint success rate falls below 80%
175
+
176
+ Register a callback for real-time alerting:
177
+
178
+ ```typescript
179
+ ttt.onAlert((alert) => {
180
+ // Send to PagerDuty, Slack, Telegram, etc.
181
+ console.error(`[OpenTTT Alert] ${alert}`);
182
+ });
183
+
184
+ ttt.setMinBalance(ethers.parseEther("0.05")); // Custom threshold
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Networks
190
+
191
+ | Network | Chain ID | Factory Method |
192
+ |---|---|---|
193
+ | Base Mainnet | 8453 | `TTTClient.forBase(config)` |
194
+ | Base Sepolia | 84532 | `TTTClient.forSepolia(config)` |
195
+
196
+ Custom networks can be provided via the `network` field in `TTTClient.create()`:
197
+
198
+ ```typescript
199
+ const ttt = await TTTClient.create({
200
+ signer: { type: "privateKey", envVar: "OPERATOR_PK" },
201
+ network: {
202
+ chainId: 8453,
203
+ rpcUrl: "https://my-custom-rpc.example.com",
204
+ tttAddress: "0x...",
205
+ protocolFeeAddress: "0x...",
206
+ usdcAddress: "0x...",
207
+ },
208
+ });
209
+ ```
210
+
211
+ ---
212
+
213
+ ## API Reference
214
+
215
+ ### TTTClient
216
+
217
+ | Method | Description |
218
+ |---|---|
219
+ | `TTTClient.create(config)` | Create and initialize a client with full configuration |
220
+ | `TTTClient.forBase(config)` | Factory for Base Mainnet (chain ID 8453) |
221
+ | `TTTClient.forSepolia(config)` | Factory for Base Sepolia testnet (chain ID 84532) |
222
+ | `ttt.startAutoMint()` | Start automatic TimeToken minting at the configured tier interval |
223
+ | `ttt.stopAutoMint()` | Stop the auto-mint loop |
224
+ | `ttt.getHealth()` | Returns `HealthStatus` with connectivity, balance, and performance checks |
225
+ | `ttt.getStatus()` | Returns current tier, mint count, fees paid, and token balances |
226
+ | `ttt.listPools()` | List all registered pool addresses |
227
+ | `ttt.getPoolStats(address)` | Get mint/burn statistics for a specific pool |
228
+ | `ttt.onAlert(callback)` | Register a callback for health alerts |
229
+ | `ttt.setMinBalance(wei)` | Set minimum ETH balance threshold for alerts |
230
+ | `ttt.destroy()` | Gracefully shut down: stops minting, unsubscribes events, clears state |
231
+
232
+ ### TimeSynthesis
233
+
234
+ | Method | Description |
235
+ |---|---|
236
+ | `synthesize()` | Query all configured NTP sources and return a median-synthesized timestamp |
237
+ | `generateProofOfTime()` | Generate a verifiable Proof of Time with source signatures |
238
+ | `verifyProofOfTime(pot)` | Verify that all source readings are within tolerance of the median |
239
+ | `TimeSynthesis.getOnChainHash(pot)` | Keccak256 hash of a PoT for on-chain submission |
240
+ | `TimeSynthesis.serializeToBinary(pot)` | Compact binary serialization for network transport |
241
+ | `TimeSynthesis.deserializeFromBinary(buf)` | Deserialize from binary format |
242
+
243
+ ### GrgPipeline
244
+
245
+ | Method | Description |
246
+ |---|---|
247
+ | `GrgPipeline.processForward(data)` | Encode: Golomb compression -> Reed-Solomon erasure coding -> Golay verification |
248
+ | `GrgPipeline.processInverse(shards, length)` | Decode: Golay verify -> Reed-Solomon reconstruct -> Golomb decompress |
249
+
250
+ ### AdaptiveSwitch
251
+
252
+ | Method | Description |
253
+ |---|---|
254
+ | `verifyBlock(block, tttRecord)` | Verify block ordering against TTT record; returns `TURBO` or `FULL` mode |
255
+ | `getCurrentMode()` | Current adaptive mode |
256
+ | `getFeeDiscount()` | Fee discount for current mode (20% in TURBO, 0% in FULL) |
257
+
258
+ ---
259
+
260
+ ## Architecture
261
+
262
+ ```
263
+ TTTClient (entry point)
264
+ |-- AutoMintEngine Periodic minting loop
265
+ | |-- TimeSynthesis NTP multi-source median synthesis (NIST, KRISS, Google)
266
+ | |-- DynamicFeeEngine Oracle-based pricing
267
+ | |-- EVMConnector On-chain mint/burn/events (ethers v6)
268
+ | '-- ProtocolFee EIP-712 signed fee collection
269
+ |-- AdaptiveSwitch TURBO/FULL mode state machine
270
+ |-- GRG Pipeline Golomb + Reed-Solomon + Golay error correction
271
+ |-- PoolRegistry Multi-pool statistics tracking
272
+ '-- Signer Abstraction PrivateKey | Turnkey | Privy | KMS
273
+ ```
274
+
275
+ ### The GRG Pipeline
276
+
277
+ GRG (Golomb-Reed-Golay) is the data integrity backbone of OpenTTT, analogous to how the TLS record protocol protects HTTP payloads.
278
+
279
+ ```
280
+ FORWARD (Encode)
281
+ Raw Data --> Golomb-Rice Compression
282
+ --> Reed-Solomon Erasure Coding
283
+ --> Golay(24,12) Verification Codes
284
+ --> Shards
285
+
286
+ INVERSE (Decode)
287
+ Shards --> Golay(24,12) Error Detection
288
+ --> Reed-Solomon Reconstruction
289
+ --> Golomb-Rice Decompression
290
+ --> Raw Data
291
+ ```
292
+
293
+ **Golomb-Rice** compresses timestamp deltas efficiently (small integers compress well).
294
+ **Reed-Solomon** adds erasure coding so data survives shard loss.
295
+ **Golay(24,12)** detects and corrects up to 3-bit errors per 24-bit codeword.
296
+
297
+ ### Adaptive Mode Switching
298
+
299
+ The economic enforcement mechanism uses a sliding window (20 blocks) with hysteresis:
300
+
301
+ - **Entry to Turbo**: 95% ordering match rate over 20+ blocks
302
+ - **Maintain Turbo**: 85% match rate (relaxed to prevent flapping)
303
+ - **Integrity failure in Turbo**: Exponential backoff penalty (20, 40, 80, 160, 320 blocks)
304
+
305
+ This asymmetry is deliberate: it is hard to earn trust and easy to lose it.
306
+
307
+ ### Time Synthesis
308
+
309
+ OpenTTT queries multiple atomic clock-synchronized NTP sources in parallel and produces a median-synthesized timestamp with confidence scoring:
310
+
311
+ - **NIST** (time.nist.gov) -- US national standard
312
+ - **KRISS** (time.kriss.re.kr) -- Korean national standard
313
+ - **Google** (time.google.com) -- Leap-smeared public NTP
314
+
315
+ All readings must fall within 100ms tolerance of the synthesized median, or the Proof of Time is rejected. Single-source operation triggers a degraded-confidence warning.
316
+
317
+ ---
318
+
319
+ ## Error Handling
320
+
321
+ All SDK errors extend `TTTBaseError` and include three fields for actionable diagnostics:
322
+
323
+ ```typescript
324
+ import { TTTSignerError } from "openttt";
325
+
326
+ try {
327
+ const ttt = await TTTClient.forBase({
328
+ signer: { type: "privateKey", envVar: "MISSING_VAR" },
329
+ });
330
+ } catch (e) {
331
+ if (e instanceof TTTSignerError) {
332
+ console.error(e.message); // What happened
333
+ console.error(e.reason); // Why it happened
334
+ console.error(e.fix); // How to fix it
335
+ }
336
+ }
337
+ ```
338
+
339
+ | Error Class | Scope |
340
+ |---|---|
341
+ | `TTTConfigError` | SDK or engine configuration |
342
+ | `TTTSignerError` | Signer acquisition or usage |
343
+ | `TTTNetworkError` | RPC, chain ID, connectivity |
344
+ | `TTTContractError` | Smart contract interaction |
345
+ | `TTTTimeSynthesisError` | NTP time synthesis failures |
346
+ | `TTTFeeError` | Dynamic fee or protocol fee collection |
347
+
348
+ ---
349
+
350
+ ## Graceful Shutdown
351
+
352
+ For long-running services, enable graceful shutdown to cleanly stop minting and release resources on SIGINT:
353
+
354
+ ```typescript
355
+ const ttt = await TTTClient.create({
356
+ signer: { type: "privateKey", envVar: "OPERATOR_PK" },
357
+ network: "base",
358
+ enableGracefulShutdown: true,
359
+ });
360
+ ttt.startAutoMint();
361
+
362
+ // Or shut down manually at any time:
363
+ await ttt.destroy();
364
+ ```
365
+
366
+ ---
367
+
368
+ ## Requirements
369
+
370
+ - Node.js >= 18
371
+ - TypeScript >= 5.3 (for development)
372
+ - Network access to NTP servers (UDP port 123 outbound)
373
+
374
+ **Optional peer dependencies** (install only what you use):
375
+
376
+ | Package | Required for |
377
+ |---|---|
378
+ | `@aws-sdk/client-kms` | AWS KMS signer |
379
+ | `@google-cloud/kms` | GCP Cloud KMS signer |
380
+
381
+ ---
382
+
383
+ ## License
384
+
385
+ [Business Source License 1.1](LICENSE)
386
+
387
+ Copyright 2026 Helm Protocol.
388
+
389
+ ---
390
+
391
+ [GitHub](https://github.com/Helm-Protocol/OpenTTT) | Built by [Helm Protocol](https://github.com/Helm-Protocol)
@@ -0,0 +1,44 @@
1
+ export declare enum AdaptiveMode {
2
+ TURBO = "TURBO",// 50ms — Valid sequence, low latency
3
+ FULL = "FULL"
4
+ }
5
+ export interface TTTRecord {
6
+ time: number;
7
+ txOrder: string[];
8
+ grgPayload: Uint8Array[];
9
+ }
10
+ export interface Block {
11
+ timestamp: number;
12
+ txs: string[];
13
+ data: Uint8Array;
14
+ }
15
+ export declare class AdaptiveSwitch {
16
+ private windowSize;
17
+ private threshold;
18
+ private history;
19
+ private currentMode;
20
+ private minBlocks;
21
+ private penaltyCooldown;
22
+ private consecutiveFailures;
23
+ private turboEntryThreshold;
24
+ private turboMaintainThreshold;
25
+ /**
26
+ * TTT의 핵심 메커니즘: 타임스탬프 순서 일치율에 따른 Turbo/Full 모드 전환
27
+ */
28
+ verifyBlock(block: Block, tttRecord: TTTRecord): AdaptiveMode;
29
+ /**
30
+ * 모드에 따른 수수료 할인율 반환
31
+ * TURBO: 20% 할인 (수익 증가 유도)
32
+ * FULL: 할인 없음
33
+ */
34
+ getFeeDiscount(): number;
35
+ /**
36
+ * 현재 모드 조회
37
+ */
38
+ getCurrentMode(): AdaptiveMode;
39
+ /**
40
+ * 테스트용: 이력 초기화
41
+ */
42
+ reset(): void;
43
+ private compareTransactionOrder;
44
+ }
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ // sdk/src/adaptive_switch.ts — Adaptive Mode Switcher
3
+ // Turbo (50ms) vs Full (127ms)
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.AdaptiveSwitch = exports.AdaptiveMode = void 0;
6
+ const grg_inverse_1 = require("./grg_inverse");
7
+ const logger_1 = require("./logger");
8
+ var AdaptiveMode;
9
+ (function (AdaptiveMode) {
10
+ AdaptiveMode["TURBO"] = "TURBO";
11
+ AdaptiveMode["FULL"] = "FULL";
12
+ })(AdaptiveMode || (exports.AdaptiveMode = AdaptiveMode = {}));
13
+ const TOLERANCE = 100; // 100ms tolerance for KTSat sync
14
+ class AdaptiveSwitch {
15
+ windowSize = 20; // B1-9: Updated from 10 to 20
16
+ threshold = 0.9; // B1-9: Updated from 0.8 to 0.9
17
+ history = [];
18
+ currentMode = AdaptiveMode.FULL;
19
+ minBlocks = 20; // B1-9: Minimum blocks for TURBO transition
20
+ penaltyCooldown = 0; // B1-9: Penalty cooldown (P2-1: increased to 20 + exponential backoff)
21
+ consecutiveFailures = 0; // P2-1: Track consecutive failures for exponential backoff
22
+ turboEntryThreshold = 0.95; // P2-2: Hysteresis — stricter entry
23
+ turboMaintainThreshold = 0.85; // P2-2: Hysteresis — relaxed maintenance
24
+ /**
25
+ * TTT의 핵심 메커니즘: 타임스탬프 순서 일치율에 따른 Turbo/Full 모드 전환
26
+ */
27
+ verifyBlock(block, tttRecord) {
28
+ // 1. 타임스탬프 순서 및 시간 일치 여부 확인
29
+ const orderMatch = this.compareTransactionOrder(block.txs, tttRecord.txOrder);
30
+ const timeMatch = Math.abs(block.timestamp - tttRecord.time) < TOLERANCE;
31
+ let sequenceOk = orderMatch && timeMatch;
32
+ // B1-1: Do not skip GrgInverse.verify() in TURBO mode
33
+ // We check integrity regardless of mode
34
+ const integrityOk = grg_inverse_1.GrgInverse.verify(block.data, tttRecord.grgPayload);
35
+ if (!integrityOk) {
36
+ logger_1.logger.error(`[AdaptiveSwitch] GRG integrity check FAILED`);
37
+ sequenceOk = false; // Mark as false if integrity fails
38
+ if (this.currentMode === AdaptiveMode.TURBO) {
39
+ logger_1.logger.warn(`[AdaptiveSwitch] TURBO integrity failure: Penalty cooldown applied`);
40
+ // P2-1: Exponential backoff — 20 * 2^(consecutiveFailures), capped at 320
41
+ this.consecutiveFailures = Math.min(this.consecutiveFailures + 1, 4);
42
+ this.penaltyCooldown = 20 * Math.pow(2, this.consecutiveFailures - 1); // 20, 40, 80, 160, 320
43
+ }
44
+ }
45
+ // 2. 이력 업데이트 (Sliding Window)
46
+ this.history.push(sequenceOk);
47
+ if (this.history.length > this.windowSize) {
48
+ this.history.shift();
49
+ }
50
+ if (this.penaltyCooldown > 0) {
51
+ this.penaltyCooldown--;
52
+ }
53
+ // 3. 일치율 계산 및 모드 전환
54
+ const matchCount = this.history.filter(h => h).length;
55
+ const matchRate = this.history.length > 0 ? matchCount / this.history.length : 0;
56
+ // P2-2: Hysteresis — different thresholds for entering vs maintaining TURBO
57
+ const effectiveThreshold = this.currentMode === AdaptiveMode.TURBO
58
+ ? this.turboMaintainThreshold // 85% to stay in TURBO
59
+ : this.turboEntryThreshold; // 95% to enter TURBO
60
+ if (this.history.length >= this.minBlocks && matchRate >= effectiveThreshold && this.penaltyCooldown === 0) {
61
+ if (this.currentMode === AdaptiveMode.FULL) {
62
+ logger_1.logger.info(`[AdaptiveSwitch] Switching to TURBO mode (Match rate: ${(matchRate * 100).toFixed(1)}%, Entry threshold: ${(this.turboEntryThreshold * 100).toFixed(0)}%)`);
63
+ }
64
+ this.currentMode = AdaptiveMode.TURBO;
65
+ this.consecutiveFailures = 0; // P2-1: Reset on successful TURBO
66
+ }
67
+ else {
68
+ if (this.currentMode === AdaptiveMode.TURBO) {
69
+ logger_1.logger.warn(`[AdaptiveSwitch] Switching to FULL mode (Match rate: ${(matchRate * 100).toFixed(1)}%, Maintain threshold: ${(this.turboMaintainThreshold * 100).toFixed(0)}%, Cooldown: ${this.penaltyCooldown})`);
70
+ }
71
+ this.currentMode = AdaptiveMode.FULL;
72
+ }
73
+ return this.currentMode;
74
+ }
75
+ /**
76
+ * 모드에 따른 수수료 할인율 반환
77
+ * TURBO: 20% 할인 (수익 증가 유도)
78
+ * FULL: 할인 없음
79
+ */
80
+ getFeeDiscount() {
81
+ return this.currentMode === AdaptiveMode.TURBO ? 0.2 : 0.0;
82
+ }
83
+ /**
84
+ * 현재 모드 조회
85
+ */
86
+ getCurrentMode() {
87
+ return this.currentMode;
88
+ }
89
+ /**
90
+ * 테스트용: 이력 초기화
91
+ */
92
+ reset() {
93
+ this.history = [];
94
+ this.currentMode = AdaptiveMode.FULL;
95
+ this.penaltyCooldown = 0;
96
+ this.consecutiveFailures = 0;
97
+ }
98
+ compareTransactionOrder(blockTxs, expectedOrder) {
99
+ if (blockTxs.length !== expectedOrder.length)
100
+ return false;
101
+ for (let i = 0; i < blockTxs.length; i++) {
102
+ if (blockTxs[i] !== expectedOrder[i])
103
+ return false;
104
+ }
105
+ return true;
106
+ }
107
+ }
108
+ exports.AdaptiveSwitch = AdaptiveSwitch;
@@ -0,0 +1,45 @@
1
+ import { EVMConnector } from "./evm_connector";
2
+ import { AutoMintConfig, MintResult } from "./types";
3
+ /**
4
+ * AutoMintEngine - TTT 자동 민팅 엔진
5
+ * 시간 합성, 동적 수수료 계산, EVM 민팅을 하나의 루프로 결합
6
+ */
7
+ export declare class AutoMintEngine {
8
+ private config;
9
+ private timeSynthesis;
10
+ private feeEngine;
11
+ private evmConnector;
12
+ private feeCollector;
13
+ private timer;
14
+ private isRunning;
15
+ private isProcessing;
16
+ private onMintCallback?;
17
+ private onFailureCallback?;
18
+ private onLatencyCallback?;
19
+ private cachedSigner;
20
+ private consecutiveFailures;
21
+ private maxConsecutiveFailures;
22
+ constructor(config: AutoMintConfig);
23
+ getEvmConnector(): EVMConnector;
24
+ setOnMint(callback: (result: MintResult) => void): void;
25
+ setOnFailure(callback: (error: Error) => void): void;
26
+ setOnLatency(callback: (ms: number) => void): void;
27
+ /**
28
+ * 엔진 초기화 (RPC 연결 및 컨트랙트 설정)
29
+ */
30
+ initialize(): Promise<void>;
31
+ /**
32
+ * 자동 민팅 루프 시작
33
+ */
34
+ start(): void;
35
+ /**
36
+ * 자동 민팅 루프 정지
37
+ */
38
+ stop(): void;
39
+ /**
40
+ * 단일 민트 틱 실행
41
+ * 시간합성 → tokenId 생성 → EVM mint 호출 → 수수료 계산/차감
42
+ */
43
+ mintTick(): Promise<void>;
44
+ private signFeeMessage;
45
+ }