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
@@ -0,0 +1,352 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TTTClient = void 0;
4
+ const ethers_1 = require("ethers");
5
+ const auto_mint_1 = require("./auto_mint");
6
+ const logger_1 = require("./logger");
7
+ const pool_registry_1 = require("./pool_registry");
8
+ const networks_1 = require("./networks");
9
+ const signer_1 = require("./signer");
10
+ /**
11
+ * TTTClient - DEX 운영자용 SDK 진입점
12
+ * 모든 내부 모듈을 초기화하고 자동 민팅 프로세스를 관리
13
+ */
14
+ class TTTClient {
15
+ config;
16
+ autoMintEngine;
17
+ poolRegistry;
18
+ isInitialized = false;
19
+ mintCount = 0;
20
+ mintFailures = 0;
21
+ totalFeesPaid = 0n;
22
+ signer = null;
23
+ lastTokenId = null;
24
+ mintLatencies = [];
25
+ lastMintAt = null;
26
+ startedAt = new Date();
27
+ minBalanceWei = ethers_1.ethers.parseEther("0.01"); // 0.01 ETH alert threshold
28
+ onAlertCallback;
29
+ constructor(config) {
30
+ this.config = config;
31
+ this.autoMintEngine = new auto_mint_1.AutoMintEngine(config);
32
+ this.poolRegistry = new pool_registry_1.PoolRegistry();
33
+ // Set up callback to update stats + metrics
34
+ this.autoMintEngine.setOnMint((result) => {
35
+ this.mintCount++;
36
+ this.totalFeesPaid += result.protocolFeePaid;
37
+ this.lastTokenId = result.tokenId;
38
+ this.lastMintAt = new Date();
39
+ // Record in registry
40
+ this.poolRegistry.recordMint(this.config.poolAddress, 1n);
41
+ });
42
+ // H2: Wire failure/latency metrics from AutoMint loop to TTTClient
43
+ this.autoMintEngine.setOnFailure((_error) => {
44
+ this.mintFailures++;
45
+ });
46
+ this.autoMintEngine.setOnLatency((ms) => {
47
+ this.mintLatencies.push(ms);
48
+ if (this.mintLatencies.length > 100) {
49
+ this.mintLatencies.shift();
50
+ }
51
+ });
52
+ }
53
+ /**
54
+ * Static factory for Base Mainnet
55
+ */
56
+ static async forBase(config) {
57
+ return this.create({ ...config, network: 'base' });
58
+ }
59
+ /**
60
+ * Static factory for Base Sepolia
61
+ */
62
+ static async forSepolia(config) {
63
+ return this.create({ ...config, network: 'sepolia' });
64
+ }
65
+ /**
66
+ * Universal factory to create and initialize a client
67
+ */
68
+ static async create(config) {
69
+ // 1. Resolve network defaults
70
+ let net;
71
+ if (typeof config.network === 'string') {
72
+ net = networks_1.NETWORKS[config.network] || networks_1.NETWORKS.base;
73
+ }
74
+ else if (config.network) {
75
+ net = config.network;
76
+ }
77
+ else {
78
+ net = networks_1.NETWORKS.base;
79
+ }
80
+ // 2. Create signer via abstraction
81
+ const abstractSigner = await (0, signer_1.createSigner)(config.signer);
82
+ const signer = abstractSigner.inner;
83
+ // 2.5. Validate addresses — prevent accidental mainnet zero-address usage
84
+ const contractAddr = config.contractAddress || net.tttAddress;
85
+ if (contractAddr === "0x0000000000000000000000000000000000000000") {
86
+ throw new Error("[TTTClient] TTT contract address is zero address. On Base Mainnet, you must provide contractAddress in config (contracts not yet deployed).");
87
+ }
88
+ // 3. Build AutoMintConfig from TTTClientConfig + defaults
89
+ const autoMintConfig = {
90
+ chainId: net.chainId,
91
+ rpcUrl: config.rpcUrl || net.rpcUrl,
92
+ signer: signer,
93
+ contractAddress: config.contractAddress || net.tttAddress,
94
+ feeCollectorAddress: net.protocolFeeAddress,
95
+ poolAddress: config.poolAddress || "0x0000000000000000000000000000000000000000",
96
+ tier: config.tier || "T1_block",
97
+ timeSources: config.timeSources || ["nist", "kriss", "google"],
98
+ protocolFeeRate: config.protocolFeeRate || 0.05,
99
+ protocolFeeRecipient: config.protocolFeeRecipient || "0x0000000000000000000000000000000000000000",
100
+ fallbackPriceUsd: config.fallbackPriceUsd || 10000n,
101
+ };
102
+ // 4. Instantiate and initialize
103
+ const client = new TTTClient(autoMintConfig);
104
+ await client.initialize();
105
+ if (config.enableGracefulShutdown) {
106
+ process.on('SIGINT', async () => {
107
+ logger_1.logger.info("[TTTClient] SIGINT received, shutting down gracefully...");
108
+ await client.destroy();
109
+ process.exit(0);
110
+ });
111
+ }
112
+ return client;
113
+ }
114
+ /**
115
+ * Gracefully shuts down the SDK, stopping all background processes and listeners.
116
+ */
117
+ async destroy() {
118
+ if (!this.isInitialized)
119
+ return;
120
+ logger_1.logger.info("[TTTClient] Destroying client...");
121
+ // 1. Stop auto-mint engine
122
+ this.autoMintEngine.stop();
123
+ // 2. Unsubscribe all event listeners
124
+ this.autoMintEngine.getEvmConnector().unsubscribeAll();
125
+ // 3. Clear local state
126
+ this.isInitialized = false;
127
+ this.signer = null;
128
+ logger_1.logger.info("[TTTClient] Client destroyed successfully.");
129
+ }
130
+ /**
131
+ * SDK 초기화: RPC 연결, 시간 소스 설정, 수수료 엔진 연결
132
+ */
133
+ async initialize() {
134
+ if (this.isInitialized)
135
+ return;
136
+ try {
137
+ logger_1.logger.info(`[TTTClient] Initializing for chain ${this.config.chainId}...`);
138
+ await this.autoMintEngine.initialize();
139
+ const connector = this.autoMintEngine.getEvmConnector();
140
+ this.signer = connector.getSigner();
141
+ // Register initial pool
142
+ await this.poolRegistry.registerPool(this.config.chainId, this.config.poolAddress);
143
+ // R2-P2-2: Validate feeCollectorAddress early before use
144
+ if (this.config.feeCollectorAddress && !ethers_1.ethers.isAddress(this.config.feeCollectorAddress)) {
145
+ throw new Error(`[TTTClient] Invalid feeCollectorAddress: ${this.config.feeCollectorAddress}`);
146
+ }
147
+ // Attach ProtocolFee contract if address is provided
148
+ if (this.config.feeCollectorAddress) {
149
+ const protocolFeeAbi = [
150
+ "event FeeCollected(address indexed payer, uint256 amount, uint256 nonce)"
151
+ ];
152
+ connector.attachProtocolFeeContract(this.config.feeCollectorAddress, protocolFeeAbi);
153
+ }
154
+ // Subscribe to events
155
+ await connector.subscribeToEvents({
156
+ onMinted: async (to, tokenId, amount) => {
157
+ logger_1.logger.info(`[TTTClient] Event: TTTMinted to ${to}, tokenId: ${tokenId}, amount: ${amount}`);
158
+ const myAddr = await this.signer?.getAddress();
159
+ if (to.toLowerCase() === myAddr?.toLowerCase()) {
160
+ // Logic could go here to update local state
161
+ }
162
+ },
163
+ onBurned: (from, tokenId, amount, tier) => {
164
+ logger_1.logger.info(`[TTTClient] Event: TTTBurned from ${from}, tokenId: ${tokenId}, amount: ${amount}, tier: ${tier}`);
165
+ this.poolRegistry.recordBurn(this.config.poolAddress, amount);
166
+ },
167
+ onFeeCollected: (payer, amount, nonce) => {
168
+ logger_1.logger.info(`[TTTClient] Event: FeeCollected from ${payer}, amount: ${amount}, nonce: ${nonce}`);
169
+ }
170
+ });
171
+ this.isInitialized = true;
172
+ logger_1.logger.info(`[TTTClient] SDK initialized successfully`);
173
+ }
174
+ catch (error) {
175
+ this.isInitialized = false;
176
+ this.signer = null;
177
+ logger_1.logger.error(`[TTTClient] Initialization failed, state rolled back: ${error}`);
178
+ throw error;
179
+ }
180
+ }
181
+ /**
182
+ * 자동 민팅 프로세스 시작
183
+ */
184
+ startAutoMint() {
185
+ if (!this.isInitialized) {
186
+ throw new Error("SDK must be initialized before starting auto-mint");
187
+ }
188
+ this.autoMintEngine.start();
189
+ logger_1.logger.info(`[TTTClient] Auto-minting started for tier ${this.config.tier}`);
190
+ }
191
+ /**
192
+ * 자동 민팅 프로세스 정지
193
+ */
194
+ stopAutoMint() {
195
+ this.autoMintEngine.stop();
196
+ }
197
+ /**
198
+ * List registered pools.
199
+ */
200
+ listPools() {
201
+ return this.poolRegistry.listPools();
202
+ }
203
+ /**
204
+ * Get stats for a specific pool.
205
+ */
206
+ getPoolStats(poolAddress) {
207
+ return this.poolRegistry.getPoolStats(poolAddress);
208
+ }
209
+ /**
210
+ * Set minimum ETH balance threshold for health alerts.
211
+ */
212
+ setMinBalance(weiAmount) {
213
+ this.minBalanceWei = weiAmount;
214
+ }
215
+ /**
216
+ * Register alert callback for real-time notifications.
217
+ */
218
+ onAlert(callback) {
219
+ this.onAlertCallback = callback;
220
+ }
221
+ emitAlert(alert) {
222
+ logger_1.logger.warn(`[TTTClient] ALERT: ${alert}`);
223
+ if (this.onAlertCallback) {
224
+ try {
225
+ this.onAlertCallback(alert);
226
+ }
227
+ catch (_) { /* swallow */ }
228
+ }
229
+ }
230
+ /**
231
+ * Record a mint failure (called internally or externally).
232
+ */
233
+ recordMintFailure() {
234
+ this.mintFailures++;
235
+ }
236
+ /**
237
+ * Record mint latency in ms (called from auto-mint wrapper).
238
+ */
239
+ recordMintLatency(ms) {
240
+ this.mintLatencies.push(ms);
241
+ // Keep last 100 entries
242
+ if (this.mintLatencies.length > 100) {
243
+ this.mintLatencies.shift();
244
+ }
245
+ }
246
+ /**
247
+ * Production health check — liveness + readiness + metrics.
248
+ * No exceptions: always returns a HealthStatus object.
249
+ */
250
+ async getHealth() {
251
+ const alerts = [];
252
+ let rpcConnected = false;
253
+ let balanceSufficient = false;
254
+ let ntpSourcesOk = true; // Assume ok unless we can verify
255
+ // 1. RPC connectivity check
256
+ if (this.isInitialized && this.signer?.provider) {
257
+ try {
258
+ const blockNumber = await this.signer.provider.getBlockNumber();
259
+ rpcConnected = blockNumber > 0;
260
+ }
261
+ catch {
262
+ rpcConnected = false;
263
+ alerts.push("RPC connection failed");
264
+ }
265
+ }
266
+ // 2. Balance check
267
+ if (this.isInitialized && this.signer?.provider) {
268
+ try {
269
+ const address = await this.signer.getAddress();
270
+ const balance = await this.signer.provider.getBalance(address);
271
+ balanceSufficient = balance >= this.minBalanceWei;
272
+ if (!balanceSufficient) {
273
+ alerts.push(`ETH balance low: ${ethers_1.ethers.formatEther(balance)} ETH (min: ${ethers_1.ethers.formatEther(this.minBalanceWei)})`);
274
+ }
275
+ }
276
+ catch {
277
+ alerts.push("Balance check failed");
278
+ }
279
+ }
280
+ // 3. Consecutive failure check
281
+ const total = this.mintCount + this.mintFailures;
282
+ const successRate = total > 0 ? this.mintCount / total : 1;
283
+ if (this.mintFailures > 5 && successRate < 0.8) {
284
+ alerts.push(`High mint failure rate: ${this.mintFailures} failures, ${(successRate * 100).toFixed(1)}% success`);
285
+ }
286
+ // 4. Avg latency
287
+ const avgLatency = this.mintLatencies.length > 0
288
+ ? this.mintLatencies.reduce((a, b) => a + b, 0) / this.mintLatencies.length
289
+ : 0;
290
+ // 5. Uptime
291
+ const uptimeMs = Date.now() - this.startedAt.getTime();
292
+ // Emit alerts
293
+ for (const alert of alerts) {
294
+ this.emitAlert(alert);
295
+ }
296
+ const healthy = this.isInitialized && rpcConnected && balanceSufficient && alerts.length === 0;
297
+ return {
298
+ healthy,
299
+ checks: {
300
+ initialized: this.isInitialized,
301
+ rpcConnected,
302
+ signerAvailable: this.signer !== null,
303
+ balanceSufficient,
304
+ ntpSourcesOk,
305
+ },
306
+ metrics: {
307
+ mintCount: this.mintCount,
308
+ mintFailures: this.mintFailures,
309
+ successRate: Math.round(successRate * 1000) / 1000,
310
+ totalFeesPaid: this.totalFeesPaid.toString(),
311
+ avgMintLatencyMs: Math.round(avgLatency),
312
+ lastMintAt: this.lastMintAt?.toISOString() ?? null,
313
+ uptimeMs,
314
+ },
315
+ alerts,
316
+ };
317
+ }
318
+ /**
319
+ * 현재 SDK 상태 및 통계 반환 (잔고, 민팅 수, 수수료 등)
320
+ */
321
+ async getStatus() {
322
+ if (!this.isInitialized || !this.signer) {
323
+ throw new Error("SDK must be initialized before getting status");
324
+ }
325
+ const provider = this.signer.provider;
326
+ if (!provider) {
327
+ throw new Error("Signer provider is not available");
328
+ }
329
+ const address = await this.signer.getAddress();
330
+ const balance = await provider.getBalance(address);
331
+ const formattedBalance = ethers_1.ethers.formatEther(balance);
332
+ let tttBalance = 0n;
333
+ if (this.lastTokenId) {
334
+ try {
335
+ tttBalance = await this.autoMintEngine.getEvmConnector().getTTTBalance(address, BigInt(this.lastTokenId));
336
+ }
337
+ catch (e) {
338
+ logger_1.logger.error(`[TTTClient] Failed to fetch TTT balance: ${e}`);
339
+ }
340
+ }
341
+ return {
342
+ isInitialized: this.isInitialized,
343
+ tier: this.config.tier,
344
+ mintCount: this.mintCount,
345
+ totalFeesPaid: this.totalFeesPaid.toString(),
346
+ balance: formattedBalance,
347
+ tttBalance: tttBalance.toString(),
348
+ lastTokenId: this.lastTokenId
349
+ };
350
+ }
351
+ }
352
+ exports.TTTClient = TTTClient;
@@ -0,0 +1,141 @@
1
+ import { Signer } from "ethers";
2
+ import { SignerConfig } from "./signer";
3
+ import { NetworkConfig } from "./networks";
4
+ export type TierType = "T0_epoch" | "T1_block" | "T2_slot" | "T3_micro";
5
+ export declare const TierIntervals: Record<TierType, number>;
6
+ /**
7
+ * High-level configuration for TTTClient
8
+ */
9
+ export interface TTTClientConfig {
10
+ /**
11
+ * Required: Signer configuration (PrivateKey, Turnkey, Privy, KMS)
12
+ */
13
+ signer: SignerConfig;
14
+ /**
15
+ * Optional: Network selection (preset "base", "sepolia" or custom NetworkConfig)
16
+ * Default: "base" (Base Mainnet)
17
+ */
18
+ network?: string | NetworkConfig;
19
+ /**
20
+ * Optional: Tier resolution (T0 to T3)
21
+ * Default: "T1_block"
22
+ */
23
+ tier?: TierType;
24
+ /**
25
+ * Optional: Override RPC URL provided by network default
26
+ */
27
+ rpcUrl?: string;
28
+ /**
29
+ * Optional: Overwrite default NTP/KTSat sources
30
+ * Default: ["nist", "kriss", "google"]
31
+ */
32
+ timeSources?: string[];
33
+ /**
34
+ * Optional: Override contract address for TTT token
35
+ */
36
+ contractAddress?: string;
37
+ /**
38
+ * Optional: Override protocol fee rate (0.01 ~ 0.10)
39
+ * Default: 0.05
40
+ */
41
+ protocolFeeRate?: number;
42
+ /**
43
+ * Optional: Fallback price for TTT tokens in USD (scaled 1e6)
44
+ * Default: 10000n ($0.01)
45
+ */
46
+ fallbackPriceUsd?: bigint;
47
+ /**
48
+ * Optional: Pool address for DEX operations
49
+ */
50
+ poolAddress?: string;
51
+ /**
52
+ * Optional: Recipient for protocol fees
53
+ */
54
+ protocolFeeRecipient?: string;
55
+ /**
56
+ * Optional: Automatically register SIGINT handler for graceful shutdown
57
+ */
58
+ enableGracefulShutdown?: boolean;
59
+ }
60
+ /**
61
+ * Internal configuration used by engines.
62
+ * Kept for backwards compatibility.
63
+ */
64
+ export interface AutoMintConfig {
65
+ chainId: number;
66
+ poolAddress: string;
67
+ rpcUrl: string;
68
+ privateKey?: string;
69
+ signer?: Signer;
70
+ contractAddress: string;
71
+ feeCollectorAddress?: string;
72
+ tier: TierType;
73
+ timeSources: string[];
74
+ protocolFeeRate: number;
75
+ protocolFeeRecipient: string;
76
+ fallbackPriceUsd?: bigint;
77
+ }
78
+ export interface MintResult {
79
+ tokenId: string;
80
+ grgHash: string;
81
+ timestamp: bigint;
82
+ txHash: string;
83
+ protocolFeePaid: bigint;
84
+ proofOfTime?: ProofOfTime;
85
+ }
86
+ export interface TimeReading {
87
+ timestamp: bigint;
88
+ uncertainty: number;
89
+ stratum: number;
90
+ source: string;
91
+ }
92
+ export interface SynthesizedTime {
93
+ timestamp: bigint;
94
+ confidence: number;
95
+ uncertainty: number;
96
+ sources: number;
97
+ stratum: number;
98
+ }
99
+ export interface PoolKey {
100
+ currency0: string;
101
+ currency1: string;
102
+ fee: number;
103
+ tickSpacing: number;
104
+ hooks: string;
105
+ }
106
+ export interface BeforeSwapParams {
107
+ sender: string;
108
+ key: PoolKey;
109
+ params: {
110
+ zeroForOne: boolean;
111
+ amountSpecified: bigint;
112
+ sqrtPriceLimitX96: bigint;
113
+ };
114
+ hookData: string;
115
+ }
116
+ export interface AfterSwapParams {
117
+ sender: string;
118
+ key: PoolKey;
119
+ params: {
120
+ zeroForOne: boolean;
121
+ amountSpecified: bigint;
122
+ sqrtPriceLimitX96: bigint;
123
+ };
124
+ delta: {
125
+ amount0: bigint;
126
+ amount1: bigint;
127
+ };
128
+ hookData: string;
129
+ }
130
+ export interface ProofOfTime {
131
+ timestamp: bigint;
132
+ uncertainty: number;
133
+ sources: number;
134
+ stratum: number;
135
+ confidence: number;
136
+ signatures: {
137
+ source: string;
138
+ timestamp: bigint;
139
+ uncertainty: number;
140
+ }[];
141
+ }
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TierIntervals = void 0;
4
+ exports.TierIntervals = {
5
+ T0_epoch: 384000, // 6.4 min
6
+ T1_block: 2000, // 2 sec (Base L2)
7
+ T2_slot: 12000, // 12 sec (Ethereum)
8
+ T3_micro: 100, // 100 ms (IoT)
9
+ };
@@ -0,0 +1,43 @@
1
+ import { EVMConnector } from "./evm_connector";
2
+ import { ProtocolFeeCollector } from "./protocol_fee";
3
+ import { FeeCalculation } from "./dynamic_fee";
4
+ import { BeforeSwapParams, AfterSwapParams } from "./types";
5
+ /**
6
+ * UniswapV4Hook - TTT-based Uniswap V4 Hook Simulation
7
+ * Provides actual logic for TTT balance verification and fee management.
8
+ */
9
+ export declare class UniswapV4Hook {
10
+ private evmConnector;
11
+ private hookAddress;
12
+ private tttTokenAddress;
13
+ private minTTTBalance;
14
+ private swapFeeTTT;
15
+ private tttContract;
16
+ private feeCollector?;
17
+ private stats;
18
+ constructor(evmConnector: EVMConnector, hookAddress: string, tttTokenAddress: string, minTTTBalance?: bigint, swapFeeTTT?: bigint, feeCollector?: ProtocolFeeCollector);
19
+ /**
20
+ * beforeSwap(params: BeforeSwapParams): Promise<void>
21
+ * Check TTT balance and deduct fees before a swap.
22
+ */
23
+ beforeSwap(params: BeforeSwapParams): Promise<void>;
24
+ /**
25
+ * afterSwap(params: AfterSwapParams): Promise<void>
26
+ * Record results and update statistics after a swap.
27
+ */
28
+ afterSwap(params: AfterSwapParams, burnFeeCalc?: FeeCalculation, signature?: string, nonce?: bigint, deadline?: number): Promise<void>;
29
+ /**
30
+ * getHookAddress(): string
31
+ * Return the hook contract address.
32
+ */
33
+ getHookAddress(): string;
34
+ /**
35
+ * Return current statistics for the hook.
36
+ */
37
+ getStats(): {
38
+ totalSwaps: number;
39
+ totalFeesCollected: string;
40
+ lastSwapTimestamp: number;
41
+ failedBurns: number;
42
+ };
43
+ }
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UniswapV4Hook = void 0;
4
+ const ethers_1 = require("ethers");
5
+ const logger_1 = require("./logger");
6
+ /**
7
+ * UniswapV4Hook - TTT-based Uniswap V4 Hook Simulation
8
+ * Provides actual logic for TTT balance verification and fee management.
9
+ */
10
+ class UniswapV4Hook {
11
+ evmConnector;
12
+ hookAddress;
13
+ tttTokenAddress;
14
+ minTTTBalance;
15
+ swapFeeTTT;
16
+ tttContract = null;
17
+ feeCollector;
18
+ stats = {
19
+ totalSwaps: 0,
20
+ totalFeesCollected: 0n,
21
+ lastSwapTimestamp: 0,
22
+ failedBurns: 0
23
+ };
24
+ constructor(evmConnector, hookAddress, tttTokenAddress, minTTTBalance = ethers_1.ethers.parseEther("1.0"), swapFeeTTT = ethers_1.ethers.parseEther("0.1"), feeCollector) {
25
+ this.evmConnector = evmConnector;
26
+ this.hookAddress = hookAddress;
27
+ this.tttTokenAddress = tttTokenAddress;
28
+ this.minTTTBalance = minTTTBalance;
29
+ this.swapFeeTTT = swapFeeTTT;
30
+ this.feeCollector = feeCollector;
31
+ }
32
+ /**
33
+ * beforeSwap(params: BeforeSwapParams): Promise<void>
34
+ * Check TTT balance and deduct fees before a swap.
35
+ */
36
+ async beforeSwap(params) {
37
+ logger_1.logger.info(`[UniswapV4Hook] beforeSwap called for sender: ${params.sender}`);
38
+ const provider = this.evmConnector.getProvider();
39
+ // ABI for TTT balance check
40
+ if (!this.tttContract) {
41
+ const tttAbi = ["function balanceOf(address, uint256) view returns (uint256)"];
42
+ this.tttContract = new ethers_1.ethers.Contract(this.tttTokenAddress, tttAbi, provider);
43
+ }
44
+ // 1. Check TTT balance of the sender
45
+ try {
46
+ // ERC-1155: balanceOf(address, uint256) — tokenId 0 = default TTT token
47
+ const balance = await this.tttContract.balanceOf(params.sender, 0);
48
+ if (balance < this.minTTTBalance) {
49
+ throw new Error(`[UniswapV4Hook] Insufficient TTT balance for ${params.sender}. ` +
50
+ `Required: ${ethers_1.ethers.formatEther(this.minTTTBalance)}, Actual: ${ethers_1.ethers.formatEther(balance)}`);
51
+ }
52
+ logger_1.logger.info(`[UniswapV4Hook] TTT balance verified: ${ethers_1.ethers.formatEther(balance)} TTT`);
53
+ }
54
+ catch (error) {
55
+ if ((error instanceof Error ? error.message : String(error)).includes("Insufficient TTT balance"))
56
+ throw error;
57
+ throw new Error(`[UniswapV4Hook] Failed to check TTT balance: ${(error instanceof Error ? error.message : String(error))}`);
58
+ }
59
+ // 2. Deduct fees (Simulated record-keeping)
60
+ // In a production hook, this would be an on-chain state update or burn.
61
+ this.stats.totalFeesCollected += this.swapFeeTTT;
62
+ logger_1.logger.info(`[UniswapV4Hook] TTT fee deducted: ${ethers_1.ethers.formatEther(this.swapFeeTTT)} TTT`);
63
+ }
64
+ /**
65
+ * afterSwap(params: AfterSwapParams): Promise<void>
66
+ * Record results and update statistics after a swap.
67
+ */
68
+ async afterSwap(params, burnFeeCalc, signature, nonce, deadline) {
69
+ logger_1.logger.info(`[UniswapV4Hook] afterSwap called for sender: ${params.sender}`);
70
+ // Implement actual fee burn/transfer logic using EVMConnector
71
+ try {
72
+ const grgHash = ethers_1.ethers.keccak256(ethers_1.ethers.toUtf8Bytes(`burn-${params.sender}-${Date.now()}`));
73
+ // Assuming tier 1 for simplicity in this hook
74
+ await this.evmConnector.burnTTT(this.swapFeeTTT, grgHash, 1);
75
+ logger_1.logger.info(`[UniswapV4Hook] Fee burn executed on-chain for ${ethers_1.ethers.formatEther(this.swapFeeTTT)} TTT`);
76
+ // Collect protocol burn fee if feeCollector and required params are provided
77
+ if (this.feeCollector && burnFeeCalc && signature && nonce !== undefined && deadline !== undefined) {
78
+ try {
79
+ await this.feeCollector.collectBurnFee(burnFeeCalc, signature, params.sender, nonce, deadline);
80
+ }
81
+ catch (feeError) {
82
+ logger_1.logger.error(`[UniswapV4Hook] Burn fee collection failed but burn was successful: ${feeError instanceof Error ? feeError.message : feeError}`);
83
+ }
84
+ }
85
+ }
86
+ catch (error) {
87
+ this.stats.failedBurns += 1;
88
+ logger_1.logger.error(`[UniswapV4Hook] Failed to execute fee burn: ${(error instanceof Error ? error.message : String(error))}`);
89
+ }
90
+ this.stats.totalSwaps += 1;
91
+ this.stats.lastSwapTimestamp = Math.floor(Date.now() / 1000);
92
+ // Log swap results
93
+ const { amount0, amount1 } = params.delta;
94
+ logger_1.logger.info(`[UniswapV4Hook] Swap recorded: Delta0=${amount0}, Delta1=${amount1}`);
95
+ }
96
+ /**
97
+ * getHookAddress(): string
98
+ * Return the hook contract address.
99
+ */
100
+ getHookAddress() {
101
+ return this.hookAddress;
102
+ }
103
+ /**
104
+ * Return current statistics for the hook.
105
+ */
106
+ getStats() {
107
+ return {
108
+ totalSwaps: this.stats.totalSwaps,
109
+ totalFeesCollected: ethers_1.ethers.formatEther(this.stats.totalFeesCollected),
110
+ lastSwapTimestamp: this.stats.lastSwapTimestamp,
111
+ failedBurns: this.stats.failedBurns
112
+ };
113
+ }
114
+ }
115
+ exports.UniswapV4Hook = UniswapV4Hook;
@@ -0,0 +1,29 @@
1
+ import { AdaptiveMode } from "./adaptive_switch";
2
+ import { EVMConnector } from "./evm_connector";
3
+ import { ProtocolFeeCollector } from "./protocol_fee";
4
+ import { DynamicFeeEngine, FeeCalculation } from "./dynamic_fee";
5
+ export interface SwapDetails {
6
+ user: string;
7
+ tokenIn: string;
8
+ tokenOut: string;
9
+ amount: bigint;
10
+ }
11
+ export declare class X402Enforcer {
12
+ private static getCost;
13
+ /**
14
+ * Deducts TTT ticks from local balance and determines Adaptive Mode.
15
+ */
16
+ static deductTick(feeEngine: DynamicFeeEngine, swap: SwapDetails, balance: bigint, tier: number, mode: AdaptiveMode): Promise<{
17
+ success: boolean;
18
+ remaining: bigint;
19
+ mode: AdaptiveMode;
20
+ }>;
21
+ /**
22
+ * Executes on-chain TTT burn via EVMConnector.
23
+ */
24
+ static deductOnChain(connector: EVMConnector, feeEngine: DynamicFeeEngine, swap: SwapDetails, grgHash: string, tier: number, feeCollector?: ProtocolFeeCollector, burnFeeCalc?: FeeCalculation, signature?: string, nonce?: bigint, deadline?: number): Promise<string>;
25
+ /**
26
+ * Static validation rule.
27
+ */
28
+ static enforcePool(feeEngine: DynamicFeeEngine, swap: SwapDetails, tttBalance: bigint, tier: number): Promise<boolean>;
29
+ }