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.
@@ -1,199 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ProtocolFeeCollector = exports.InMemoryReplayCache = void 0;
4
- const ethers_1 = require("ethers");
5
- const logger_1 = require("./logger");
6
- /**
7
- * Default in-memory replay cache with bounded size and TTL eviction.
8
- * Suitable for single-process deployments; use a distributed ReplayCache
9
- * implementation (e.g., Redis) for multi-node setups.
10
- */
11
- class InMemoryReplayCache {
12
- entries = new Map();
13
- maxEntries;
14
- defaultTtlMs;
15
- lastPruneTime = 0;
16
- static PRUNE_INTERVAL_MS = 60000;
17
- constructor(maxEntries = 10000, defaultTtlMs = 3600000) {
18
- this.maxEntries = maxEntries;
19
- this.defaultTtlMs = defaultTtlMs;
20
- }
21
- async has(key) {
22
- this.pruneIfNeeded();
23
- const ts = this.entries.get(key);
24
- if (ts === undefined)
25
- return false;
26
- if (Date.now() - ts > this.defaultTtlMs) {
27
- this.entries.delete(key);
28
- return false;
29
- }
30
- return true;
31
- }
32
- async set(key, ttlMs) {
33
- this.pruneIfNeeded();
34
- this.entries.set(key, Date.now());
35
- }
36
- pruneIfNeeded() {
37
- const now = Date.now();
38
- if (now - this.lastPruneTime < InMemoryReplayCache.PRUNE_INTERVAL_MS &&
39
- this.entries.size <= this.maxEntries) {
40
- return;
41
- }
42
- this.lastPruneTime = now;
43
- for (const [sig, ts] of this.entries) {
44
- if (now - ts > this.defaultTtlMs) {
45
- this.entries.delete(sig);
46
- }
47
- }
48
- // If still over limit, remove oldest entries
49
- if (this.entries.size > this.maxEntries) {
50
- const sorted = [...this.entries.entries()].sort((a, b) => a[1] - b[1]);
51
- const toRemove = sorted.slice(0, sorted.length - this.maxEntries);
52
- for (const [sig] of toRemove) {
53
- this.entries.delete(sig);
54
- }
55
- }
56
- }
57
- }
58
- exports.InMemoryReplayCache = InMemoryReplayCache;
59
- /**
60
- * ProtocolFeeCollector - Handles Helm protocol fee collection and verification.
61
- * Includes EIP-712 signature verification for x402 compliance.
62
- */
63
- class ProtocolFeeCollector {
64
- totalCollected = 0n;
65
- chainId;
66
- verifyingContract;
67
- replayCache;
68
- evmConnector;
69
- protocolFeeRecipient;
70
- feeContract = null;
71
- constructor(chainId, verifyingContract, evmConnector, protocolFeeRecipient, replayCache) {
72
- // R3-P0-2: Validate chainId is a positive integer to prevent cross-chain replay
73
- if (!Number.isInteger(chainId) || chainId <= 0) {
74
- throw new Error(`[ProtocolFee] Invalid chainId: ${chainId}. Must be a positive integer.`);
75
- }
76
- this.chainId = chainId;
77
- this.verifyingContract = ethers_1.ethers.getAddress(verifyingContract);
78
- this.evmConnector = evmConnector;
79
- this.protocolFeeRecipient = ethers_1.ethers.getAddress(protocolFeeRecipient);
80
- this.replayCache = replayCache ?? new InMemoryReplayCache();
81
- }
82
- /**
83
- * R3-P0-2: Verify chainId matches the actual connected network.
84
- * Must be called after EVMConnector.connect() to prevent cross-chain signature replay.
85
- */
86
- async validateChainId() {
87
- const provider = this.evmConnector.getProvider();
88
- const network = await provider.getNetwork();
89
- if (Number(network.chainId) !== this.chainId) {
90
- throw new Error(`[ProtocolFee] Chain ID mismatch: configured ${this.chainId}, network reports ${network.chainId}. Cross-chain replay risk!`);
91
- }
92
- }
93
- getFeeContract() {
94
- if (this.feeContract)
95
- return this.feeContract;
96
- const abi = [
97
- "function collectFee(address token, uint256 amount, bytes calldata signature, uint256 nonce, uint256 deadline) external"
98
- ];
99
- // ProtocolFeeCollector uses verifyingContract as the ProtocolFee.sol address
100
- this.feeContract = new ethers_1.ethers.Contract(this.verifyingContract, abi, this.evmConnector.getSigner());
101
- return this.feeContract;
102
- }
103
- /**
104
- * Collect minting fee (Stablecoin).
105
- * @param feeCalc - Fee calculation result from DynamicFeeEngine.
106
- * @param signature - EIP-712 signature (required, for x402 verification).
107
- * @param user - Signer address.
108
- * @param nonce - Anti-replay nonce.
109
- * @param deadline - Signature expiration timestamp.
110
- */
111
- async collectMintFee(feeCalc, signature, user, nonce, deadline) {
112
- try {
113
- await this.verifySignature(feeCalc, signature, user, nonce, deadline);
114
- // Actual on-chain collection
115
- const contract = this.getFeeContract();
116
- const tx = await contract.collectFee(ethers_1.ethers.getAddress(feeCalc.feeTokenAddress), feeCalc.protocolFeeUsd, signature, nonce, deadline);
117
- await tx.wait();
118
- this.totalCollected += feeCalc.protocolFeeUsd;
119
- logger_1.logger.info(`[ProtocolFee] Mint fee collected on-chain: ${feeCalc.protocolFeeUsd} ${feeCalc.feeToken}. TX: ${tx.hash}`);
120
- }
121
- catch (error) {
122
- throw new Error(`[ProtocolFee] Mint fee collection failed: ${(error instanceof Error ? error.message : String(error))}`);
123
- }
124
- }
125
- /**
126
- * Collect burn fee.
127
- * @param feeCalc - Fee calculation result from DynamicFeeEngine.
128
- * @param signature - EIP-712 signature (required).
129
- * @param user - Signer address.
130
- * @param nonce - Anti-replay nonce.
131
- * @param deadline - Signature expiration timestamp.
132
- */
133
- async collectBurnFee(feeCalc, signature, user, nonce, deadline) {
134
- try {
135
- await this.verifySignature(feeCalc, signature, user, nonce, deadline);
136
- // Actual on-chain collection
137
- const contract = this.getFeeContract();
138
- const tx = await contract.collectFee(ethers_1.ethers.getAddress(feeCalc.feeTokenAddress), feeCalc.protocolFeeUsd, signature, nonce, deadline);
139
- await tx.wait();
140
- this.totalCollected += feeCalc.protocolFeeUsd;
141
- logger_1.logger.info(`[ProtocolFee] Burn fee collected on-chain: ${feeCalc.protocolFeeUsd} ${feeCalc.feeToken}. TX: ${tx.hash}`);
142
- }
143
- catch (error) {
144
- throw new Error(`[ProtocolFee] Burn fee collection failed: ${(error instanceof Error ? error.message : String(error))}`);
145
- }
146
- }
147
- /**
148
- * Return total fees collected so far.
149
- */
150
- async getCollectedFees() {
151
- return this.totalCollected;
152
- }
153
- /**
154
- * EIP-712 signature verification (x402 compliance).
155
- */
156
- async verifySignature(feeCalc, signature, user, nonce, deadline) {
157
- // B1-2 + P1-2: Replay protection via pluggable cache
158
- if (await this.replayCache.has(signature)) {
159
- throw new Error("Signature already used (replay protection)");
160
- }
161
- // B1-2: Deadline check
162
- const now = Math.floor(Date.now() / 1000);
163
- if (deadline < now) {
164
- throw new Error("Signature deadline expired");
165
- }
166
- const normalizedUser = ethers_1.ethers.getAddress(user);
167
- const domain = {
168
- name: "OpenTTT_ProtocolFee",
169
- version: "1",
170
- chainId: this.chainId,
171
- verifyingContract: this.verifyingContract
172
- };
173
- const types = {
174
- CollectFee: [
175
- { name: "token", type: "address" },
176
- { name: "amount", type: "uint256" },
177
- { name: "nonce", type: "uint256" },
178
- { name: "deadline", type: "uint256" }
179
- ]
180
- };
181
- const value = {
182
- token: ethers_1.ethers.getAddress(feeCalc.feeTokenAddress),
183
- amount: feeCalc.protocolFeeUsd,
184
- nonce: nonce,
185
- deadline: deadline
186
- };
187
- try {
188
- const recoveredAddress = ethers_1.ethers.verifyTypedData(domain, types, value, signature);
189
- if (ethers_1.ethers.getAddress(recoveredAddress) !== normalizedUser) {
190
- throw new Error("Invalid EIP-712 signature: signer mismatch");
191
- }
192
- await this.replayCache.set(signature, 3600000); // Mark as used with 1h TTL
193
- }
194
- catch (error) {
195
- throw new Error(`[ProtocolFee] Signature verification failed: ${(error instanceof Error ? error.message : String(error))}`);
196
- }
197
- }
198
- }
199
- exports.ProtocolFeeCollector = ProtocolFeeCollector;
@@ -1,36 +0,0 @@
1
- /**
2
- * Revenue Tier Configuration
3
- * Reflects the TTT Labs pricing strategy: Free/Sponsor-backed T0 up to Institutional T3.
4
- */
5
- export declare enum RevenueTier {
6
- T0_EPOCH = "T0_EPOCH",
7
- T1_BLOCK = "T1_BLOCK",
8
- T2_SLOT = "T2_SLOT",
9
- T3_MICRO = "T3_MICRO"
10
- }
11
- export interface TierConfig {
12
- tier: RevenueTier;
13
- name: string;
14
- interval: string;
15
- pricePerTick: number;
16
- currency: string;
17
- model: string;
18
- target: string;
19
- sponsorEligible: boolean;
20
- }
21
- export interface SponsorConfig {
22
- sponsor: string;
23
- tier: RevenueTier;
24
- monthlyBudgetUsd: number;
25
- startDate: string;
26
- endDate: string;
27
- }
28
- export declare const REVENUE_TIERS: Record<RevenueTier, TierConfig>;
29
- /**
30
- * Calculate projected monthly cost based on tier and throughput.
31
- */
32
- export declare function calculateMonthlyCost(tier: RevenueTier, ticksPerDay: number): number;
33
- /**
34
- * Determine the appropriate tier based on a usage description.
35
- */
36
- export declare function getTierForUseCase(useCase: string): RevenueTier;
@@ -1,83 +0,0 @@
1
- "use strict";
2
- /**
3
- * Revenue Tier Configuration
4
- * Reflects the TTT Labs pricing strategy: Free/Sponsor-backed T0 up to Institutional T3.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.REVENUE_TIERS = exports.RevenueTier = void 0;
8
- exports.calculateMonthlyCost = calculateMonthlyCost;
9
- exports.getTierForUseCase = getTierForUseCase;
10
- var RevenueTier;
11
- (function (RevenueTier) {
12
- RevenueTier["T0_EPOCH"] = "T0_EPOCH";
13
- RevenueTier["T1_BLOCK"] = "T1_BLOCK";
14
- RevenueTier["T2_SLOT"] = "T2_SLOT";
15
- RevenueTier["T3_MICRO"] = "T3_MICRO";
16
- })(RevenueTier || (exports.RevenueTier = RevenueTier = {}));
17
- exports.REVENUE_TIERS = {
18
- [RevenueTier.T0_EPOCH]: {
19
- tier: RevenueTier.T0_EPOCH,
20
- name: "Standard Epoch",
21
- interval: "6.4 min",
22
- pricePerTick: 0,
23
- currency: "USDC",
24
- model: "sponsor", // Let's Encrypt model: free to user, sponsor-backed
25
- target: "Standard L1 Swaps / LP Integration",
26
- sponsorEligible: true
27
- },
28
- [RevenueTier.T1_BLOCK]: {
29
- tier: RevenueTier.T1_BLOCK,
30
- name: "Fast Block",
31
- interval: "2 sec",
32
- pricePerTick: 0.01,
33
- currency: "USDC",
34
- model: "sdk_license",
35
- target: "L2 Sequencer / Standard DeFi",
36
- sponsorEligible: false
37
- },
38
- [RevenueTier.T2_SLOT]: {
39
- tier: RevenueTier.T2_SLOT,
40
- name: "High-Frequency Slot",
41
- interval: "12 sec",
42
- pricePerTick: 0.05,
43
- currency: "USDC",
44
- model: "sdk_license",
45
- target: "Active Traders / Arbitrage",
46
- sponsorEligible: false
47
- },
48
- [RevenueTier.T3_MICRO]: {
49
- tier: RevenueTier.T3_MICRO,
50
- name: "Institutional Micro-Tick",
51
- interval: "100 ms",
52
- pricePerTick: 0.10,
53
- currency: "USDC",
54
- model: "enterprise",
55
- target: "Institutional / HFT Pipelines",
56
- sponsorEligible: false
57
- }
58
- };
59
- /**
60
- * Calculate projected monthly cost based on tier and throughput.
61
- */
62
- function calculateMonthlyCost(tier, ticksPerDay) {
63
- const config = exports.REVENUE_TIERS[tier];
64
- if (config.pricePerTick === 0)
65
- return 0;
66
- return config.pricePerTick * ticksPerDay * 30;
67
- }
68
- /**
69
- * Determine the appropriate tier based on a usage description.
70
- */
71
- function getTierForUseCase(useCase) {
72
- const lowerCase = useCase.toLowerCase();
73
- if (lowerCase.includes("institutional") || lowerCase.includes("hft") || lowerCase.includes("micro")) {
74
- return RevenueTier.T3_MICRO;
75
- }
76
- if (lowerCase.includes("arbitrage") || lowerCase.includes("trader") || lowerCase.includes("slot")) {
77
- return RevenueTier.T2_SLOT;
78
- }
79
- if (lowerCase.includes("l2") || lowerCase.includes("block") || lowerCase.includes("sequencer")) {
80
- return RevenueTier.T1_BLOCK;
81
- }
82
- return RevenueTier.T0_EPOCH;
83
- }
@@ -1,44 +0,0 @@
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 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)
30
- */
31
- static deductTick(feeEngine: DynamicFeeEngine, swap: SwapDetails, balance: bigint, tier: number, mode: AdaptiveMode, verifyOnChain?: boolean, connector?: EVMConnector, tokenId?: bigint): Promise<{
32
- success: boolean;
33
- remaining: bigint;
34
- mode: AdaptiveMode;
35
- }>;
36
- /**
37
- * Executes on-chain TTT burn via EVMConnector.
38
- */
39
- static deductOnChain(connector: EVMConnector, feeEngine: DynamicFeeEngine, swap: SwapDetails, grgHash: string, tier: number, feeCollector?: ProtocolFeeCollector, burnFeeCalc?: FeeCalculation, signature?: string, nonce?: bigint, deadline?: number): Promise<string>;
40
- /**
41
- * Static validation rule.
42
- */
43
- static enforcePool(feeEngine: DynamicFeeEngine, swap: SwapDetails, tttBalance: bigint, tier: number): Promise<boolean>;
44
- }
@@ -1,92 +0,0 @@
1
- "use strict";
2
- // sdk/src/x402_enforcer.ts — x402 Micropayment Enforcer (Expanded)
3
- // Governs TTT tick consumption and on-chain settlement.
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.X402Enforcer = void 0;
6
- const logger_1 = require("./logger");
7
- const TIER_MAP = {
8
- 0: "T0_epoch",
9
- 1: "T1_block",
10
- 2: "T2_slot",
11
- 3: "T3_micro"
12
- };
13
- class X402Enforcer {
14
- static async getCost(feeEngine, tier) {
15
- const tierKey = TIER_MAP[tier] || "T0_epoch";
16
- const feeCalc = await feeEngine.calculateMintFee(tierKey);
17
- return feeCalc.tttAmount;
18
- }
19
- /**
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)
36
- */
37
- static async deductTick(feeEngine, swap, balance, tier, mode, verifyOnChain = false, connector, tokenId) {
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
- }
49
- if (balance < cost) {
50
- throw new Error(`[x402] Insufficient TTT ticks for user ${swap.user}. Required: ${cost}, Have: ${balance}.`);
51
- }
52
- const newBalance = balance - cost;
53
- logger_1.logger.info(`[x402] Deducted ${cost} ticks for swap. User: ${swap.user}, New Balance: ${newBalance}`);
54
- return {
55
- success: true,
56
- remaining: newBalance,
57
- mode
58
- };
59
- }
60
- /**
61
- * Executes on-chain TTT burn via EVMConnector.
62
- */
63
- static async deductOnChain(connector, feeEngine, swap, grgHash, tier, feeCollector, burnFeeCalc, signature, nonce, deadline) {
64
- logger_1.logger.info(`[x402] Enforcing on-chain settlement for user ${swap.user}...`);
65
- const cost = await this.getCost(feeEngine, tier);
66
- try {
67
- const receipt = await connector.burnTTT(cost, grgHash, tier);
68
- // Collect protocol burn fee if feeCollector and required params are provided
69
- if (feeCollector && burnFeeCalc && signature && nonce !== undefined && deadline !== undefined) {
70
- try {
71
- await feeCollector.collectBurnFee(burnFeeCalc, signature, swap.user, nonce, deadline);
72
- }
73
- catch (feeError) {
74
- logger_1.logger.error(`[x402] Burn fee collection failed but burn was successful: ${feeError instanceof Error ? feeError.message : feeError}`);
75
- }
76
- }
77
- return receipt.hash;
78
- }
79
- catch (error) {
80
- logger_1.logger.error(`[x402] On-chain enforcement failed: ${error instanceof Error ? error.message : error}`);
81
- throw error;
82
- }
83
- }
84
- /**
85
- * Static validation rule.
86
- */
87
- static async enforcePool(feeEngine, swap, tttBalance, tier) {
88
- const cost = await this.getCost(feeEngine, tier);
89
- return tttBalance >= cost;
90
- }
91
- }
92
- exports.X402Enforcer = X402Enforcer;