openttt 0.1.2 → 0.2.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.
- package/README.md +52 -30
- package/dist/adaptive_switch.d.ts +22 -7
- package/dist/adaptive_switch.js +52 -15
- package/dist/auto_mint.d.ts +22 -7
- package/dist/auto_mint.js +107 -30
- package/dist/ct_log.d.ts +47 -0
- package/dist/ct_log.js +107 -0
- package/dist/dynamic_fee.d.ts +13 -2
- package/dist/dynamic_fee.js +62 -11
- package/dist/errors.d.ts +44 -25
- package/dist/errors.js +58 -42
- package/dist/evm_connector.d.ts +28 -1
- package/dist/evm_connector.js +124 -32
- package/dist/grg_api_client.d.ts +41 -0
- package/dist/grg_api_client.js +116 -0
- package/dist/http_client.d.ts +98 -0
- package/dist/http_client.js +252 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/logger.d.ts +36 -4
- package/dist/logger.js +70 -11
- package/dist/networks.d.ts +21 -0
- package/dist/networks.js +30 -4
- package/dist/pool_registry.d.ts +9 -0
- package/dist/pool_registry.js +37 -0
- package/dist/pot_signer.d.ts +15 -0
- package/dist/pot_signer.js +28 -0
- package/dist/protocol_fee.d.ts +42 -26
- package/dist/protocol_fee.js +77 -54
- package/dist/revenue_tiers.d.ts +36 -0
- package/dist/revenue_tiers.js +83 -0
- package/dist/signer.d.ts +1 -2
- package/dist/signer.js +72 -14
- package/dist/time_synthesis.d.ts +38 -0
- package/dist/time_synthesis.js +131 -21
- package/dist/trust_store.d.ts +49 -0
- package/dist/trust_store.js +89 -0
- package/dist/ttt_builder.d.ts +1 -1
- package/dist/ttt_builder.js +2 -2
- package/dist/ttt_client.d.ts +42 -29
- package/dist/ttt_client.js +117 -28
- package/dist/types.d.ts +46 -3
- package/dist/v4_hook.d.ts +10 -2
- package/dist/v4_hook.js +10 -2
- package/dist/x402_enforcer.d.ts +17 -2
- package/dist/x402_enforcer.js +27 -2
- package/package.json +6 -2
- package/dist/golay.d.ts +0 -6
- package/dist/golay.js +0 -166
- package/dist/grg_forward.d.ts +0 -11
- package/dist/grg_forward.js +0 -74
- package/dist/grg_inverse.d.ts +0 -7
- package/dist/grg_inverse.js +0 -100
- package/dist/grg_pipeline.d.ts +0 -13
- package/dist/grg_pipeline.js +0 -64
- package/dist/reed_solomon.d.ts +0 -12
- package/dist/reed_solomon.js +0 -179
- package/vendor/helm-crypto/golay.d.ts +0 -6
- package/vendor/helm-crypto/golay.js +0 -167
- package/vendor/helm-crypto/golay.js.map +0 -1
- package/vendor/helm-crypto/grg_forward.d.ts +0 -22
- package/vendor/helm-crypto/grg_forward.js +0 -89
- package/vendor/helm-crypto/grg_forward.js.map +0 -1
- package/vendor/helm-crypto/grg_inverse.d.ts +0 -16
- package/vendor/helm-crypto/grg_inverse.js +0 -118
- package/vendor/helm-crypto/grg_inverse.js.map +0 -1
- package/vendor/helm-crypto/grg_pipeline.d.ts +0 -13
- package/vendor/helm-crypto/grg_pipeline.js +0 -66
- package/vendor/helm-crypto/grg_pipeline.js.map +0 -1
- package/vendor/helm-crypto/index.d.ts +0 -5
- package/vendor/helm-crypto/index.js +0 -17
- package/vendor/helm-crypto/index.js.map +0 -1
- package/vendor/helm-crypto/logger.d.ts +0 -6
- package/vendor/helm-crypto/logger.js +0 -11
- package/vendor/helm-crypto/logger.js.map +0 -1
- package/vendor/helm-crypto/reed_solomon.d.ts +0 -37
- package/vendor/helm-crypto/reed_solomon.js +0 -210
- package/vendor/helm-crypto/reed_solomon.js.map +0 -1
package/dist/ttt_client.d.ts
CHANGED
|
@@ -1,32 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { AutoMintConfig, TTTClientConfig, MintResult, HealthStatus } from "./types";
|
|
3
|
+
import { HttpOnlyClient, HttpOnlyClientOptions } from "./http_client";
|
|
4
|
+
export { HealthStatus } from "./types";
|
|
2
5
|
/**
|
|
3
|
-
*
|
|
6
|
+
* Typed event map for TTTClient EventEmitter.
|
|
4
7
|
*/
|
|
5
|
-
export interface
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
balanceSufficient: boolean;
|
|
12
|
-
ntpSourcesOk: boolean;
|
|
13
|
-
};
|
|
14
|
-
metrics: {
|
|
15
|
-
mintCount: number;
|
|
16
|
-
mintFailures: number;
|
|
17
|
-
successRate: number;
|
|
18
|
-
totalFeesPaid: string;
|
|
19
|
-
avgMintLatencyMs: number;
|
|
20
|
-
lastMintAt: string | null;
|
|
21
|
-
uptimeMs: number;
|
|
22
|
-
};
|
|
23
|
-
alerts: string[];
|
|
8
|
+
export interface TTTClientEvents {
|
|
9
|
+
mint: [result: MintResult];
|
|
10
|
+
error: [error: Error];
|
|
11
|
+
alert: [alert: string];
|
|
12
|
+
latency: [ms: number];
|
|
13
|
+
modeSwitch: [mode: string];
|
|
24
14
|
}
|
|
25
15
|
/**
|
|
26
|
-
* TTTClient -
|
|
27
|
-
*
|
|
16
|
+
* TTTClient - SDK entry point for DEX operators.
|
|
17
|
+
* Initializes all internal modules and manages the auto-minting process.
|
|
28
18
|
*/
|
|
29
|
-
export declare class TTTClient {
|
|
19
|
+
export declare class TTTClient extends EventEmitter {
|
|
30
20
|
private config;
|
|
31
21
|
private autoMintEngine;
|
|
32
22
|
private poolRegistry;
|
|
@@ -37,10 +27,10 @@ export declare class TTTClient {
|
|
|
37
27
|
private signer;
|
|
38
28
|
private lastTokenId;
|
|
39
29
|
private mintLatencies;
|
|
30
|
+
private maxLatencyHistory;
|
|
40
31
|
private lastMintAt;
|
|
41
32
|
private startedAt;
|
|
42
33
|
private minBalanceWei;
|
|
43
|
-
private onAlertCallback?;
|
|
44
34
|
constructor(config: AutoMintConfig);
|
|
45
35
|
/**
|
|
46
36
|
* Static factory for Base Mainnet
|
|
@@ -50,6 +40,23 @@ export declare class TTTClient {
|
|
|
50
40
|
* Static factory for Base Sepolia
|
|
51
41
|
*/
|
|
52
42
|
static forSepolia(config: Omit<TTTClientConfig, 'network'>): Promise<TTTClient>;
|
|
43
|
+
/**
|
|
44
|
+
* Zero-friction sandbox mode — no ETH, no signer, no on-chain interaction.
|
|
45
|
+
*
|
|
46
|
+
* Returns an HttpOnlyClient that fetches verified time from NIST, Apple,
|
|
47
|
+
* Google, and Cloudflare HTTPS endpoints and produces HMAC-signed PoTs.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // Zero-friction: no wallet, no RPC, no gas
|
|
51
|
+
* const client = TTTClient.httpOnly();
|
|
52
|
+
* const pot = await client.generatePoT();
|
|
53
|
+
* console.log(pot.timestamp, pot.confidence);
|
|
54
|
+
*
|
|
55
|
+
* // Verify locally (no on-chain check needed)
|
|
56
|
+
* const result = client.verifyPoT(pot);
|
|
57
|
+
* console.log(result.valid); // true
|
|
58
|
+
*/
|
|
59
|
+
static httpOnly(options?: HttpOnlyClientOptions): HttpOnlyClient;
|
|
53
60
|
/**
|
|
54
61
|
* Universal factory to create and initialize a client
|
|
55
62
|
*/
|
|
@@ -59,17 +66,22 @@ export declare class TTTClient {
|
|
|
59
66
|
*/
|
|
60
67
|
destroy(): Promise<void>;
|
|
61
68
|
/**
|
|
62
|
-
* SDK
|
|
69
|
+
* Initialize the SDK: RPC connection, time sources, fee engine wiring.
|
|
63
70
|
*/
|
|
64
71
|
initialize(): Promise<void>;
|
|
65
72
|
/**
|
|
66
|
-
*
|
|
73
|
+
* Start the auto-minting process.
|
|
67
74
|
*/
|
|
68
75
|
startAutoMint(): void;
|
|
69
76
|
/**
|
|
70
|
-
*
|
|
77
|
+
* Stop the auto-minting process.
|
|
71
78
|
*/
|
|
72
79
|
stopAutoMint(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Resume auto-minting after a circuit breaker trip.
|
|
82
|
+
* Resets consecutive failure count and restarts the engine.
|
|
83
|
+
*/
|
|
84
|
+
resume(): void;
|
|
73
85
|
/**
|
|
74
86
|
* List registered pools.
|
|
75
87
|
*/
|
|
@@ -87,6 +99,7 @@ export declare class TTTClient {
|
|
|
87
99
|
setMinBalance(weiAmount: bigint): void;
|
|
88
100
|
/**
|
|
89
101
|
* Register alert callback for real-time notifications.
|
|
102
|
+
* Backward compatible: delegates to EventEmitter 'alert' event.
|
|
90
103
|
*/
|
|
91
104
|
onAlert(callback: (alert: string) => void): void;
|
|
92
105
|
private emitAlert;
|
|
@@ -104,7 +117,7 @@ export declare class TTTClient {
|
|
|
104
117
|
*/
|
|
105
118
|
getHealth(): Promise<HealthStatus>;
|
|
106
119
|
/**
|
|
107
|
-
*
|
|
120
|
+
* Return current SDK status and statistics (balance, mint count, fees, etc.)
|
|
108
121
|
*/
|
|
109
122
|
getStatus(): Promise<{
|
|
110
123
|
isInitialized: boolean;
|
package/dist/ttt_client.js
CHANGED
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TTTClient = void 0;
|
|
4
4
|
const ethers_1 = require("ethers");
|
|
5
|
+
const events_1 = require("events");
|
|
5
6
|
const auto_mint_1 = require("./auto_mint");
|
|
7
|
+
const types_1 = require("./types");
|
|
6
8
|
const logger_1 = require("./logger");
|
|
7
9
|
const pool_registry_1 = require("./pool_registry");
|
|
8
10
|
const networks_1 = require("./networks");
|
|
9
11
|
const signer_1 = require("./signer");
|
|
12
|
+
const http_client_1 = require("./http_client");
|
|
10
13
|
/**
|
|
11
|
-
* TTTClient -
|
|
12
|
-
*
|
|
14
|
+
* TTTClient - SDK entry point for DEX operators.
|
|
15
|
+
* Initializes all internal modules and manages the auto-minting process.
|
|
13
16
|
*/
|
|
14
|
-
class TTTClient {
|
|
17
|
+
class TTTClient extends events_1.EventEmitter {
|
|
15
18
|
config;
|
|
16
19
|
autoMintEngine;
|
|
17
20
|
poolRegistry;
|
|
@@ -22,15 +25,17 @@ class TTTClient {
|
|
|
22
25
|
signer = null;
|
|
23
26
|
lastTokenId = null;
|
|
24
27
|
mintLatencies = [];
|
|
28
|
+
maxLatencyHistory;
|
|
25
29
|
lastMintAt = null;
|
|
26
30
|
startedAt = new Date();
|
|
27
31
|
minBalanceWei = ethers_1.ethers.parseEther("0.01"); // 0.01 ETH alert threshold
|
|
28
|
-
onAlertCallback;
|
|
29
32
|
constructor(config) {
|
|
33
|
+
super();
|
|
30
34
|
this.config = config;
|
|
35
|
+
this.maxLatencyHistory = config.maxLatencyHistory ?? 100;
|
|
31
36
|
this.autoMintEngine = new auto_mint_1.AutoMintEngine(config);
|
|
32
37
|
this.poolRegistry = new pool_registry_1.PoolRegistry();
|
|
33
|
-
//
|
|
38
|
+
// Wire callbacks to update stats + emit events
|
|
34
39
|
this.autoMintEngine.setOnMint((result) => {
|
|
35
40
|
this.mintCount++;
|
|
36
41
|
this.totalFeesPaid += result.protocolFeePaid;
|
|
@@ -38,16 +43,20 @@ class TTTClient {
|
|
|
38
43
|
this.lastMintAt = new Date();
|
|
39
44
|
// Record in registry
|
|
40
45
|
this.poolRegistry.recordMint(this.config.poolAddress, 1n);
|
|
46
|
+
// Emit typed 'mint' event
|
|
47
|
+
this.emit('mint', result);
|
|
41
48
|
});
|
|
42
|
-
//
|
|
43
|
-
this.autoMintEngine.setOnFailure((
|
|
49
|
+
// Wire failure/latency metrics from AutoMint loop to TTTClient
|
|
50
|
+
this.autoMintEngine.setOnFailure((error) => {
|
|
44
51
|
this.mintFailures++;
|
|
52
|
+
this.emit('error', error);
|
|
45
53
|
});
|
|
46
54
|
this.autoMintEngine.setOnLatency((ms) => {
|
|
47
55
|
this.mintLatencies.push(ms);
|
|
48
|
-
if (this.mintLatencies.length >
|
|
56
|
+
if (this.mintLatencies.length > this.maxLatencyHistory) {
|
|
49
57
|
this.mintLatencies.shift();
|
|
50
58
|
}
|
|
59
|
+
this.emit('latency', ms);
|
|
51
60
|
});
|
|
52
61
|
}
|
|
53
62
|
/**
|
|
@@ -62,14 +71,59 @@ class TTTClient {
|
|
|
62
71
|
static async forSepolia(config) {
|
|
63
72
|
return this.create({ ...config, network: 'sepolia' });
|
|
64
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Zero-friction sandbox mode — no ETH, no signer, no on-chain interaction.
|
|
76
|
+
*
|
|
77
|
+
* Returns an HttpOnlyClient that fetches verified time from NIST, Apple,
|
|
78
|
+
* Google, and Cloudflare HTTPS endpoints and produces HMAC-signed PoTs.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* // Zero-friction: no wallet, no RPC, no gas
|
|
82
|
+
* const client = TTTClient.httpOnly();
|
|
83
|
+
* const pot = await client.generatePoT();
|
|
84
|
+
* console.log(pot.timestamp, pot.confidence);
|
|
85
|
+
*
|
|
86
|
+
* // Verify locally (no on-chain check needed)
|
|
87
|
+
* const result = client.verifyPoT(pot);
|
|
88
|
+
* console.log(result.valid); // true
|
|
89
|
+
*/
|
|
90
|
+
static httpOnly(options) {
|
|
91
|
+
return new http_client_1.HttpOnlyClient(options);
|
|
92
|
+
}
|
|
65
93
|
/**
|
|
66
94
|
* Universal factory to create and initialize a client
|
|
67
95
|
*/
|
|
68
96
|
static async create(config) {
|
|
97
|
+
// 0. Shorthand: privateKey string -> SignerConfig
|
|
98
|
+
if (config.privateKey && !config.signer) {
|
|
99
|
+
const key = config.privateKey.startsWith('0x') ? config.privateKey : '0x' + config.privateKey;
|
|
100
|
+
config = { ...config, signer: { type: 'privateKey', key } };
|
|
101
|
+
}
|
|
102
|
+
// 0.5. Validation: require either signer or privateKey
|
|
103
|
+
if (!config.signer) {
|
|
104
|
+
throw new Error('TTTClient requires either `signer` or `privateKey`. Simplest: TTTClient.forBase({ privateKey: process.env.OPERATOR_PK! })');
|
|
105
|
+
}
|
|
106
|
+
// 0.7. Validate tier — CRITICAL: invalid tier causes setInterval(fn, undefined) = 1ms loop = wallet drain
|
|
107
|
+
const tier = config.tier || "T1_block";
|
|
108
|
+
if (!types_1.TierIntervals[tier]) {
|
|
109
|
+
const validTiers = Object.keys(types_1.TierIntervals).join(', ');
|
|
110
|
+
throw new Error(`[TTTClient] Invalid tier "${tier}". Valid tiers: ${validTiers}`);
|
|
111
|
+
}
|
|
112
|
+
// 0.8. Validate fee rate bounds
|
|
113
|
+
if (config.protocolFeeRate !== undefined) {
|
|
114
|
+
if (config.protocolFeeRate < 0 || config.protocolFeeRate > 1) {
|
|
115
|
+
throw new Error(`[TTTClient] protocolFeeRate must be 0-1 (got ${config.protocolFeeRate}). Example: 0.05 = 5%`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// 0.9. Validate network string
|
|
119
|
+
if (typeof config.network === 'string' && !networks_1.NETWORKS[config.network]) {
|
|
120
|
+
const validNets = Object.keys(networks_1.NETWORKS).join(', ');
|
|
121
|
+
throw new Error(`[TTTClient] Unknown network "${config.network}". Valid: ${validNets}. Or pass a custom NetworkConfig object.`);
|
|
122
|
+
}
|
|
69
123
|
// 1. Resolve network defaults
|
|
70
124
|
let net;
|
|
71
125
|
if (typeof config.network === 'string') {
|
|
72
|
-
net = networks_1.NETWORKS[config.network]
|
|
126
|
+
net = networks_1.NETWORKS[config.network];
|
|
73
127
|
}
|
|
74
128
|
else if (config.network) {
|
|
75
129
|
net = config.network;
|
|
@@ -92,12 +146,25 @@ class TTTClient {
|
|
|
92
146
|
signer: signer,
|
|
93
147
|
contractAddress: config.contractAddress || net.tttAddress,
|
|
94
148
|
feeCollectorAddress: net.protocolFeeAddress,
|
|
95
|
-
poolAddress:
|
|
149
|
+
poolAddress: (() => {
|
|
150
|
+
const addr = config.poolAddress;
|
|
151
|
+
if (!addr || addr === "0x0000000000000000000000000000000000000000") {
|
|
152
|
+
throw new Error("[TTTClient] poolAddress is required. Provide a valid DEX pool address.");
|
|
153
|
+
}
|
|
154
|
+
return addr;
|
|
155
|
+
})(),
|
|
96
156
|
tier: config.tier || "T1_block",
|
|
97
|
-
timeSources: config.timeSources || ["nist", "
|
|
157
|
+
timeSources: config.timeSources || ["nist", "google", "cloudflare", "apple"],
|
|
98
158
|
protocolFeeRate: config.protocolFeeRate || 0.05,
|
|
99
|
-
protocolFeeRecipient:
|
|
159
|
+
protocolFeeRecipient: (() => {
|
|
160
|
+
const addr = config.protocolFeeRecipient;
|
|
161
|
+
if (!addr || addr === "0x0000000000000000000000000000000000000000") {
|
|
162
|
+
throw new Error("[TTTClient] protocolFeeRecipient is required. Provide a valid fee recipient address.");
|
|
163
|
+
}
|
|
164
|
+
return addr;
|
|
165
|
+
})(),
|
|
100
166
|
fallbackPriceUsd: config.fallbackPriceUsd || 10000n,
|
|
167
|
+
maxLatencyHistory: config.maxLatencyHistory,
|
|
101
168
|
};
|
|
102
169
|
// 4. Instantiate and initialize
|
|
103
170
|
const client = new TTTClient(autoMintConfig);
|
|
@@ -128,7 +195,7 @@ class TTTClient {
|
|
|
128
195
|
logger_1.logger.info("[TTTClient] Client destroyed successfully.");
|
|
129
196
|
}
|
|
130
197
|
/**
|
|
131
|
-
* SDK
|
|
198
|
+
* Initialize the SDK: RPC connection, time sources, fee engine wiring.
|
|
132
199
|
*/
|
|
133
200
|
async initialize() {
|
|
134
201
|
if (this.isInitialized)
|
|
@@ -140,7 +207,7 @@ class TTTClient {
|
|
|
140
207
|
this.signer = connector.getSigner();
|
|
141
208
|
// Register initial pool
|
|
142
209
|
await this.poolRegistry.registerPool(this.config.chainId, this.config.poolAddress);
|
|
143
|
-
//
|
|
210
|
+
// Validate feeCollectorAddress early before use
|
|
144
211
|
if (this.config.feeCollectorAddress && !ethers_1.ethers.isAddress(this.config.feeCollectorAddress)) {
|
|
145
212
|
throw new Error(`[TTTClient] Invalid feeCollectorAddress: ${this.config.feeCollectorAddress}`);
|
|
146
213
|
}
|
|
@@ -179,7 +246,7 @@ class TTTClient {
|
|
|
179
246
|
}
|
|
180
247
|
}
|
|
181
248
|
/**
|
|
182
|
-
*
|
|
249
|
+
* Start the auto-minting process.
|
|
183
250
|
*/
|
|
184
251
|
startAutoMint() {
|
|
185
252
|
if (!this.isInitialized) {
|
|
@@ -189,11 +256,20 @@ class TTTClient {
|
|
|
189
256
|
logger_1.logger.info(`[TTTClient] Auto-minting started for tier ${this.config.tier}`);
|
|
190
257
|
}
|
|
191
258
|
/**
|
|
192
|
-
*
|
|
259
|
+
* Stop the auto-minting process.
|
|
193
260
|
*/
|
|
194
261
|
stopAutoMint() {
|
|
195
262
|
this.autoMintEngine.stop();
|
|
196
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Resume auto-minting after a circuit breaker trip.
|
|
266
|
+
* Resets consecutive failure count and restarts the engine.
|
|
267
|
+
*/
|
|
268
|
+
resume() {
|
|
269
|
+
this.autoMintEngine.resume();
|
|
270
|
+
this.emit('modeSwitch', 'resumed');
|
|
271
|
+
logger_1.logger.info(`[TTTClient] Auto-minting resumed`);
|
|
272
|
+
}
|
|
197
273
|
/**
|
|
198
274
|
* List registered pools.
|
|
199
275
|
*/
|
|
@@ -214,18 +290,14 @@ class TTTClient {
|
|
|
214
290
|
}
|
|
215
291
|
/**
|
|
216
292
|
* Register alert callback for real-time notifications.
|
|
293
|
+
* Backward compatible: delegates to EventEmitter 'alert' event.
|
|
217
294
|
*/
|
|
218
295
|
onAlert(callback) {
|
|
219
|
-
this.
|
|
296
|
+
this.on('alert', callback);
|
|
220
297
|
}
|
|
221
298
|
emitAlert(alert) {
|
|
222
299
|
logger_1.logger.warn(`[TTTClient] ALERT: ${alert}`);
|
|
223
|
-
|
|
224
|
-
try {
|
|
225
|
-
this.onAlertCallback(alert);
|
|
226
|
-
}
|
|
227
|
-
catch (_) { /* swallow */ }
|
|
228
|
-
}
|
|
300
|
+
this.emit('alert', alert);
|
|
229
301
|
}
|
|
230
302
|
/**
|
|
231
303
|
* Record a mint failure (called internally or externally).
|
|
@@ -238,8 +310,7 @@ class TTTClient {
|
|
|
238
310
|
*/
|
|
239
311
|
recordMintLatency(ms) {
|
|
240
312
|
this.mintLatencies.push(ms);
|
|
241
|
-
|
|
242
|
-
if (this.mintLatencies.length > 100) {
|
|
313
|
+
if (this.mintLatencies.length > this.maxLatencyHistory) {
|
|
243
314
|
this.mintLatencies.shift();
|
|
244
315
|
}
|
|
245
316
|
}
|
|
@@ -251,7 +322,7 @@ class TTTClient {
|
|
|
251
322
|
const alerts = [];
|
|
252
323
|
let rpcConnected = false;
|
|
253
324
|
let balanceSufficient = false;
|
|
254
|
-
let ntpSourcesOk =
|
|
325
|
+
let ntpSourcesOk = false;
|
|
255
326
|
// 1. RPC connectivity check
|
|
256
327
|
if (this.isInitialized && this.signer?.provider) {
|
|
257
328
|
try {
|
|
@@ -277,7 +348,25 @@ class TTTClient {
|
|
|
277
348
|
alerts.push("Balance check failed");
|
|
278
349
|
}
|
|
279
350
|
}
|
|
280
|
-
// 3.
|
|
351
|
+
// 3. NTP/time source health check via quick synthesis with timeout
|
|
352
|
+
try {
|
|
353
|
+
const synthResult = await Promise.race([
|
|
354
|
+
this.autoMintEngine.getTimeSynthesis().synthesize(),
|
|
355
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("Time synthesis health check timed out")), 3000)),
|
|
356
|
+
]);
|
|
357
|
+
if (synthResult && synthResult.sources >= 2 && synthResult.confidence >= 0.5) {
|
|
358
|
+
ntpSourcesOk = true;
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
ntpSourcesOk = false;
|
|
362
|
+
alerts.push(`Time sources degraded: ${synthResult?.sources ?? 0} source(s), confidence ${synthResult?.confidence?.toFixed(2) ?? "N/A"}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
ntpSourcesOk = false;
|
|
367
|
+
alerts.push("Time source health check failed");
|
|
368
|
+
}
|
|
369
|
+
// 4. Consecutive failure check
|
|
281
370
|
const total = this.mintCount + this.mintFailures;
|
|
282
371
|
const successRate = total > 0 ? this.mintCount / total : 1;
|
|
283
372
|
if (this.mintFailures > 5 && successRate < 0.8) {
|
|
@@ -316,7 +405,7 @@ class TTTClient {
|
|
|
316
405
|
};
|
|
317
406
|
}
|
|
318
407
|
/**
|
|
319
|
-
*
|
|
408
|
+
* Return current SDK status and statistics (balance, mint count, fees, etc.)
|
|
320
409
|
*/
|
|
321
410
|
async getStatus() {
|
|
322
411
|
if (!this.isInitialized || !this.signer) {
|
package/dist/types.d.ts
CHANGED
|
@@ -9,9 +9,19 @@ export declare const TierIntervals: Record<TierType, number>;
|
|
|
9
9
|
*/
|
|
10
10
|
export interface TTTClientConfig {
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Signer configuration (PrivateKey, Turnkey, Privy, KMS).
|
|
13
|
+
* Required unless `privateKey` shorthand is provided.
|
|
13
14
|
*/
|
|
14
|
-
signer
|
|
15
|
+
signer?: SignerConfig;
|
|
16
|
+
/**
|
|
17
|
+
* Shorthand: pass a raw private key string directly.
|
|
18
|
+
* If provided (and `signer` is not), auto-converts to { type: 'privateKey', key: ... }.
|
|
19
|
+
* Accepts with or without '0x' prefix.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* TTTClient.forBase({ privateKey: process.env.OPERATOR_PK! })
|
|
23
|
+
*/
|
|
24
|
+
privateKey?: string;
|
|
15
25
|
/**
|
|
16
26
|
* Optional: Network selection (preset "base", "sepolia" or custom NetworkConfig)
|
|
17
27
|
* Default: "base" (Base Mainnet)
|
|
@@ -28,7 +38,7 @@ export interface TTTClientConfig {
|
|
|
28
38
|
rpcUrl?: string;
|
|
29
39
|
/**
|
|
30
40
|
* Optional: Overwrite default NTP/KTSat sources
|
|
31
|
-
* Default: ["nist", "
|
|
41
|
+
* Default: ["nist", "google", "cloudflare", "apple"]
|
|
32
42
|
*/
|
|
33
43
|
timeSources?: string[];
|
|
34
44
|
/**
|
|
@@ -57,6 +67,12 @@ export interface TTTClientConfig {
|
|
|
57
67
|
* Optional: Automatically register SIGINT handler for graceful shutdown
|
|
58
68
|
*/
|
|
59
69
|
enableGracefulShutdown?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Optional: Maximum number of mint latency samples to keep in the ring buffer.
|
|
72
|
+
* Used for avgMintLatencyMs calculation in health checks.
|
|
73
|
+
* Default: 100
|
|
74
|
+
*/
|
|
75
|
+
maxLatencyHistory?: number;
|
|
60
76
|
}
|
|
61
77
|
/**
|
|
62
78
|
* Internal configuration used by engines.
|
|
@@ -75,6 +91,8 @@ export interface AutoMintConfig {
|
|
|
75
91
|
protocolFeeRate: number;
|
|
76
92
|
protocolFeeRecipient: string;
|
|
77
93
|
fallbackPriceUsd?: bigint;
|
|
94
|
+
maxLatencyHistory?: number;
|
|
95
|
+
potSignerKeyPath?: string;
|
|
78
96
|
}
|
|
79
97
|
export interface MintResult {
|
|
80
98
|
tokenId: string;
|
|
@@ -138,9 +156,34 @@ export interface ProofOfTime {
|
|
|
138
156
|
source: string;
|
|
139
157
|
timestamp: bigint;
|
|
140
158
|
uncertainty: number;
|
|
159
|
+
stratum?: number;
|
|
141
160
|
}[];
|
|
142
161
|
nonce: string;
|
|
143
162
|
expiresAt: bigint;
|
|
144
163
|
issuerSignature?: PotSignature;
|
|
145
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Health status returned by TTTClient.getHealth().
|
|
167
|
+
* Provides liveness, readiness, and operational metrics.
|
|
168
|
+
*/
|
|
169
|
+
export interface HealthStatus {
|
|
170
|
+
healthy: boolean;
|
|
171
|
+
checks: {
|
|
172
|
+
initialized: boolean;
|
|
173
|
+
rpcConnected: boolean;
|
|
174
|
+
signerAvailable: boolean;
|
|
175
|
+
balanceSufficient: boolean;
|
|
176
|
+
ntpSourcesOk: boolean;
|
|
177
|
+
};
|
|
178
|
+
metrics: {
|
|
179
|
+
mintCount: number;
|
|
180
|
+
mintFailures: number;
|
|
181
|
+
successRate: number;
|
|
182
|
+
totalFeesPaid: string;
|
|
183
|
+
avgMintLatencyMs: number;
|
|
184
|
+
lastMintAt: string | null;
|
|
185
|
+
uptimeMs: number;
|
|
186
|
+
};
|
|
187
|
+
alerts: string[];
|
|
188
|
+
}
|
|
146
189
|
export type { PotSignature } from "./pot_signer";
|
package/dist/v4_hook.d.ts
CHANGED
|
@@ -3,8 +3,16 @@ import { ProtocolFeeCollector } from "./protocol_fee";
|
|
|
3
3
|
import { FeeCalculation } from "./dynamic_fee";
|
|
4
4
|
import { BeforeSwapParams, AfterSwapParams } from "./types";
|
|
5
5
|
/**
|
|
6
|
-
* UniswapV4Hook - TTT-based Uniswap V4 Hook Simulation
|
|
7
|
-
*
|
|
6
|
+
* UniswapV4Hook - TTT-based Uniswap V4 Hook Simulation (SDK-side)
|
|
7
|
+
*
|
|
8
|
+
* This is a simulation/SDK-side hook that mirrors the logic of a Uniswap V4 hook
|
|
9
|
+
* for off-chain validation and testing. It is NOT the actual Solidity on-chain hook.
|
|
10
|
+
*
|
|
11
|
+
* The actual V4 hook contract should implement IHooks from @uniswap/v4-core
|
|
12
|
+
* (see: https://github.com/Uniswap/v4-core/blob/main/src/interfaces/IHooks.sol).
|
|
13
|
+
*
|
|
14
|
+
* Provides TTT balance verification and fee management logic that can be used
|
|
15
|
+
* to validate swap eligibility before submitting on-chain transactions.
|
|
8
16
|
*/
|
|
9
17
|
export declare class UniswapV4Hook {
|
|
10
18
|
private evmConnector;
|
package/dist/v4_hook.js
CHANGED
|
@@ -4,8 +4,16 @@ exports.UniswapV4Hook = void 0;
|
|
|
4
4
|
const ethers_1 = require("ethers");
|
|
5
5
|
const logger_1 = require("./logger");
|
|
6
6
|
/**
|
|
7
|
-
* UniswapV4Hook - TTT-based Uniswap V4 Hook Simulation
|
|
8
|
-
*
|
|
7
|
+
* UniswapV4Hook - TTT-based Uniswap V4 Hook Simulation (SDK-side)
|
|
8
|
+
*
|
|
9
|
+
* This is a simulation/SDK-side hook that mirrors the logic of a Uniswap V4 hook
|
|
10
|
+
* for off-chain validation and testing. It is NOT the actual Solidity on-chain hook.
|
|
11
|
+
*
|
|
12
|
+
* The actual V4 hook contract should implement IHooks from @uniswap/v4-core
|
|
13
|
+
* (see: https://github.com/Uniswap/v4-core/blob/main/src/interfaces/IHooks.sol).
|
|
14
|
+
*
|
|
15
|
+
* Provides TTT balance verification and fee management logic that can be used
|
|
16
|
+
* to validate swap eligibility before submitting on-chain transactions.
|
|
9
17
|
*/
|
|
10
18
|
class UniswapV4Hook {
|
|
11
19
|
evmConnector;
|
package/dist/x402_enforcer.d.ts
CHANGED
|
@@ -11,9 +11,24 @@ export interface SwapDetails {
|
|
|
11
11
|
export declare class X402Enforcer {
|
|
12
12
|
private static getCost;
|
|
13
13
|
/**
|
|
14
|
-
* Deducts TTT ticks from
|
|
14
|
+
* Deducts TTT ticks from the provided balance and determines Adaptive Mode.
|
|
15
|
+
*
|
|
16
|
+
* **Important:** By default, the `balance` parameter is an SDK-local value
|
|
17
|
+
* (tracked in-memory by the caller). It is NOT verified against the on-chain
|
|
18
|
+
* TTT token balance. This is sufficient for hot-path tick accounting where
|
|
19
|
+
* on-chain settlement happens separately via `deductOnChain()`.
|
|
20
|
+
*
|
|
21
|
+
* @param feeEngine - Dynamic fee engine for cost calculation
|
|
22
|
+
* @param swap - Swap details (user, tokens, amount)
|
|
23
|
+
* @param balance - SDK-local TTT balance (not on-chain unless verifyOnChain=true)
|
|
24
|
+
* @param tier - Stratum tier (0-3)
|
|
25
|
+
* @param mode - Current adaptive mode (Turbo/Full)
|
|
26
|
+
* @param verifyOnChain - If true, checks on-chain TTT balance via EVMConnector
|
|
27
|
+
* before deducting. Requires `connector` and `tokenId`. Default: false.
|
|
28
|
+
* @param connector - EVMConnector instance (required when verifyOnChain=true)
|
|
29
|
+
* @param tokenId - Token ID for on-chain balance lookup (required when verifyOnChain=true)
|
|
15
30
|
*/
|
|
16
|
-
static deductTick(feeEngine: DynamicFeeEngine, swap: SwapDetails, balance: bigint, tier: number, mode: AdaptiveMode): Promise<{
|
|
31
|
+
static deductTick(feeEngine: DynamicFeeEngine, swap: SwapDetails, balance: bigint, tier: number, mode: AdaptiveMode, verifyOnChain?: boolean, connector?: EVMConnector, tokenId?: bigint): Promise<{
|
|
17
32
|
success: boolean;
|
|
18
33
|
remaining: bigint;
|
|
19
34
|
mode: AdaptiveMode;
|
package/dist/x402_enforcer.js
CHANGED
|
@@ -17,10 +17,35 @@ class X402Enforcer {
|
|
|
17
17
|
return feeCalc.tttAmount;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* Deducts TTT ticks from
|
|
20
|
+
* Deducts TTT ticks from the provided balance and determines Adaptive Mode.
|
|
21
|
+
*
|
|
22
|
+
* **Important:** By default, the `balance` parameter is an SDK-local value
|
|
23
|
+
* (tracked in-memory by the caller). It is NOT verified against the on-chain
|
|
24
|
+
* TTT token balance. This is sufficient for hot-path tick accounting where
|
|
25
|
+
* on-chain settlement happens separately via `deductOnChain()`.
|
|
26
|
+
*
|
|
27
|
+
* @param feeEngine - Dynamic fee engine for cost calculation
|
|
28
|
+
* @param swap - Swap details (user, tokens, amount)
|
|
29
|
+
* @param balance - SDK-local TTT balance (not on-chain unless verifyOnChain=true)
|
|
30
|
+
* @param tier - Stratum tier (0-3)
|
|
31
|
+
* @param mode - Current adaptive mode (Turbo/Full)
|
|
32
|
+
* @param verifyOnChain - If true, checks on-chain TTT balance via EVMConnector
|
|
33
|
+
* before deducting. Requires `connector` and `tokenId`. Default: false.
|
|
34
|
+
* @param connector - EVMConnector instance (required when verifyOnChain=true)
|
|
35
|
+
* @param tokenId - Token ID for on-chain balance lookup (required when verifyOnChain=true)
|
|
21
36
|
*/
|
|
22
|
-
static async deductTick(feeEngine, swap, balance, tier, mode) {
|
|
37
|
+
static async deductTick(feeEngine, swap, balance, tier, mode, verifyOnChain = false, connector, tokenId) {
|
|
23
38
|
const cost = await this.getCost(feeEngine, tier);
|
|
39
|
+
// Optional on-chain balance verification before deducting
|
|
40
|
+
if (verifyOnChain) {
|
|
41
|
+
if (!connector || tokenId === undefined) {
|
|
42
|
+
throw new Error("[x402] verifyOnChain requires both connector and tokenId parameters");
|
|
43
|
+
}
|
|
44
|
+
const onChainBalance = await connector.getTTTBalance(swap.user, tokenId);
|
|
45
|
+
if (onChainBalance < cost) {
|
|
46
|
+
throw new Error(`[x402] On-chain balance insufficient for user ${swap.user}. Required: ${cost}, On-chain: ${onChainBalance}.`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
24
49
|
if (balance < cost) {
|
|
25
50
|
throw new Error(`[x402] Insufficient TTT ticks for user ${swap.user}. Required: ${cost}, Have: ${balance}.`);
|
|
26
51
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openttt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "OpenTTT — TLS-grade transaction ordering for DeFi. Time + Logic + Sync.",
|
|
5
5
|
"license": "BSL-1.1",
|
|
6
6
|
"repository": {
|
|
@@ -31,7 +31,11 @@
|
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"dist",
|
|
34
|
-
"
|
|
34
|
+
"!dist/golay.*",
|
|
35
|
+
"!dist/grg_forward.*",
|
|
36
|
+
"!dist/grg_inverse.*",
|
|
37
|
+
"!dist/grg_pipeline.*",
|
|
38
|
+
"!dist/reed_solomon.*",
|
|
35
39
|
"README.md"
|
|
36
40
|
],
|
|
37
41
|
"scripts": {
|