openttt 0.1.2 → 0.1.3

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 (43) hide show
  1. package/README.md +4 -4
  2. package/dist/adaptive_switch.d.ts +22 -7
  3. package/dist/adaptive_switch.js +52 -15
  4. package/dist/auto_mint.d.ts +22 -7
  5. package/dist/auto_mint.js +107 -30
  6. package/dist/ct_log.d.ts +47 -0
  7. package/dist/ct_log.js +107 -0
  8. package/dist/dynamic_fee.d.ts +13 -2
  9. package/dist/dynamic_fee.js +62 -11
  10. package/dist/errors.d.ts +44 -25
  11. package/dist/errors.js +58 -42
  12. package/dist/evm_connector.d.ts +28 -1
  13. package/dist/evm_connector.js +124 -32
  14. package/dist/index.d.ts +4 -5
  15. package/dist/index.js +4 -5
  16. package/dist/logger.d.ts +36 -4
  17. package/dist/logger.js +70 -11
  18. package/dist/networks.d.ts +21 -0
  19. package/dist/networks.js +30 -4
  20. package/dist/pool_registry.d.ts +9 -0
  21. package/dist/pool_registry.js +37 -0
  22. package/dist/pot_signer.d.ts +15 -0
  23. package/dist/pot_signer.js +28 -0
  24. package/dist/protocol_fee.d.ts +42 -26
  25. package/dist/protocol_fee.js +77 -54
  26. package/dist/revenue_tiers.d.ts +36 -0
  27. package/dist/revenue_tiers.js +83 -0
  28. package/dist/signer.d.ts +1 -2
  29. package/dist/signer.js +72 -14
  30. package/dist/time_synthesis.d.ts +38 -0
  31. package/dist/time_synthesis.js +134 -20
  32. package/dist/trust_store.d.ts +49 -0
  33. package/dist/trust_store.js +89 -0
  34. package/dist/ttt_builder.d.ts +1 -1
  35. package/dist/ttt_builder.js +2 -2
  36. package/dist/ttt_client.d.ts +24 -29
  37. package/dist/ttt_client.js +97 -28
  38. package/dist/types.d.ts +46 -3
  39. package/dist/v4_hook.d.ts +10 -2
  40. package/dist/v4_hook.js +10 -2
  41. package/dist/x402_enforcer.d.ts +17 -2
  42. package/dist/x402_enforcer.js +27 -2
  43. package/package.json +1 -1
@@ -14,14 +14,22 @@ class EVMConnector {
14
14
  eventListeners = []; // P2-6: Track listeners for cleanup
15
15
  // P1-7: Timeout wrapper for gas estimation
16
16
  static GAS_TIMEOUT_MS = 5000;
17
- constructor() { }
17
+ primaryRpcUrl = "";
18
+ fallbackRpcUrls = [];
19
+ signerOrKey = null;
20
+ maxReconnectAttempts;
21
+ connected = false;
22
+ constructor(options) {
23
+ this.fallbackRpcUrls = options?.fallbackRpcUrls ?? [];
24
+ this.maxReconnectAttempts = options?.maxReconnectAttempts ?? 3;
25
+ }
18
26
  /**
19
27
  * P1-7: Race estimateGas against timeout to prevent DoS
20
28
  */
21
29
  async withTimeout(promise, ms = EVMConnector.GAS_TIMEOUT_MS) {
22
30
  return Promise.race([
23
31
  promise,
24
- new Promise((_, reject) => setTimeout(() => reject(new errors_1.TTTNetworkError(`[EVM] Operation timed out`, `RPC did not respond within ${ms}ms`, `Check your RPC provider status or increase timeout.`)), ms))
32
+ new Promise((_, reject) => setTimeout(() => reject(new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_CONNECTION_FAILED, `[EVM] Operation timed out`, `RPC did not respond within ${ms}ms`, `Check your RPC provider status or increase timeout.`)), ms))
25
33
  ]);
26
34
  }
27
35
  /**
@@ -29,36 +37,116 @@ class EVMConnector {
29
37
  */
30
38
  async connect(rpcUrl, signerOrKey) {
31
39
  if (!rpcUrl || typeof rpcUrl !== "string")
32
- throw new errors_1.TTTNetworkError("[EVM] Invalid RPC URL", "The provided RPC URL is empty or not a string", "Pass a valid RPC URL (e.g., https://mainnet.base.org)");
40
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_INVALID_RPC, "[EVM] Invalid RPC URL", "The provided RPC URL is empty or not a string", "Pass a valid RPC URL (e.g., https://mainnet.base.org)");
41
+ this.primaryRpcUrl = rpcUrl;
42
+ this.signerOrKey = signerOrKey;
33
43
  try {
34
44
  this.provider = new ethers_1.JsonRpcProvider(rpcUrl);
35
45
  if (typeof signerOrKey === "string") {
36
46
  if (!signerOrKey.startsWith("0x") || signerOrKey.length !== 66) {
37
- throw new errors_1.TTTContractError("[EVM] Invalid Private Key format", "Private key must be 0x + 64 hex characters", "Provide a valid 32-byte hex private key.");
47
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_INVALID_KEY_FORMAT, "[EVM] Invalid Private Key format", "Private key must be 0x + 64 hex characters", "Provide a valid 32-byte hex private key.");
38
48
  }
39
49
  this.signer = new ethers_1.ethers.Wallet(signerOrKey, this.provider);
40
50
  }
41
51
  else {
42
- // Signer might already be connected to a provider, but we ensure it's linked to ours
43
52
  this.signer = signerOrKey.connect ? signerOrKey.connect(this.provider) : signerOrKey;
44
53
  }
45
54
  const network = await this.provider.getNetwork();
55
+ this.connected = true;
46
56
  logger_1.logger.info(`[EVM] Connected to Chain ID: ${network.chainId}`);
47
57
  }
48
58
  catch (error) {
49
59
  if (error instanceof errors_1.TTTContractError || error instanceof errors_1.TTTNetworkError)
50
60
  throw error;
51
- throw new errors_1.TTTNetworkError(`[EVM] Connection failed`, error instanceof Error ? error.message : String(error), `Verify your RPC URL and network connectivity.`);
61
+ // Try fallback RPCs before giving up
62
+ for (const fallback of this.fallbackRpcUrls) {
63
+ try {
64
+ logger_1.logger.warn(`[EVM] Primary RPC failed, trying fallback: ${fallback}`);
65
+ this.provider = new ethers_1.JsonRpcProvider(fallback);
66
+ if (typeof signerOrKey === "string") {
67
+ this.signer = new ethers_1.ethers.Wallet(signerOrKey, this.provider);
68
+ }
69
+ else {
70
+ this.signer = signerOrKey.connect ? signerOrKey.connect(this.provider) : signerOrKey;
71
+ }
72
+ const network = await this.provider.getNetwork();
73
+ this.connected = true;
74
+ logger_1.logger.info(`[EVM] Connected via fallback to Chain ID: ${network.chainId}`);
75
+ return;
76
+ }
77
+ catch {
78
+ continue;
79
+ }
80
+ }
81
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_CONNECTION_FAILED, `[EVM] Connection failed`, error instanceof Error ? error.message : String(error), `Verify your RPC URL and network connectivity.`);
82
+ }
83
+ }
84
+ /**
85
+ * Reconnect using stored credentials. Tries primary first, then fallbacks.
86
+ */
87
+ async reconnect() {
88
+ if (!this.signerOrKey)
89
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_CANNOT_RECONNECT, "[EVM] Cannot reconnect", "No previous connection credentials stored", "Call connect() first.");
90
+ this.disconnect();
91
+ const allUrls = [this.primaryRpcUrl, ...this.fallbackRpcUrls].filter(Boolean);
92
+ for (let attempt = 0; attempt < Math.min(this.maxReconnectAttempts, allUrls.length); attempt++) {
93
+ try {
94
+ const url = allUrls[attempt % allUrls.length];
95
+ logger_1.logger.info(`[EVM] Reconnect attempt ${attempt + 1}/${this.maxReconnectAttempts} → ${url}`);
96
+ this.provider = new ethers_1.JsonRpcProvider(url);
97
+ if (typeof this.signerOrKey === "string") {
98
+ this.signer = new ethers_1.ethers.Wallet(this.signerOrKey, this.provider);
99
+ }
100
+ else {
101
+ this.signer = this.signerOrKey.connect ? this.signerOrKey.connect(this.provider) : this.signerOrKey;
102
+ }
103
+ await this.provider.getNetwork();
104
+ this.connected = true;
105
+ logger_1.logger.info(`[EVM] Reconnected successfully`);
106
+ return;
107
+ }
108
+ catch {
109
+ logger_1.logger.warn(`[EVM] Reconnect attempt ${attempt + 1} failed`);
110
+ }
111
+ }
112
+ this.connected = false;
113
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_RECONNECTION_EXHAUSTED, "[EVM] Reconnection failed", `All ${this.maxReconnectAttempts} attempts exhausted`, "Check RPC provider status and network connectivity.");
114
+ }
115
+ /**
116
+ * Disconnect and release all resources.
117
+ */
118
+ disconnect() {
119
+ this.unsubscribeAll();
120
+ if (this.provider) {
121
+ this.provider.destroy();
52
122
  }
123
+ this.provider = null;
124
+ this.signer = null;
125
+ this.tttContract = null;
126
+ this.protocolFeeContract = null;
127
+ this.connected = false;
128
+ logger_1.logger.info("[EVM] Disconnected and resources released");
129
+ }
130
+ /**
131
+ * Check if the connector is currently connected.
132
+ */
133
+ isConnected() {
134
+ return this.connected && this.provider !== null;
53
135
  }
136
+ /**
137
+ * CT Log Equivalent: PoTAnchored event ABI fragment.
138
+ * Every Proof-of-Time anchor is publicly auditable on-chain,
139
+ * analogous to Certificate Transparency logs in TLS.
140
+ */
141
+ static POT_ANCHORED_EVENT_ABI = "event PoTAnchored(uint64 indexed timestamp, bytes32 grgHash, uint8 stratum, bytes32 potHash)";
54
142
  /**
55
143
  * Attach the TTT Token contract.
56
144
  */
57
145
  attachContract(address, abi) {
58
146
  if (!this.signer)
59
- throw new errors_1.TTTContractError("Not connected to signer", "EVMConnector.connect() must be called first", "Initialize connection before attaching contracts.");
147
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_SIGNER_NOT_CONNECTED, "Not connected to signer", "EVMConnector.connect() must be called first", "Initialize connection before attaching contracts.");
60
148
  if (!address || !ethers_1.ethers.isAddress(address))
61
- throw new errors_1.TTTContractError(`[EVM] Invalid contract address`, `Address '${address}' is not a valid EVM address`, `Check your config and provide a valid checksummed address.`);
149
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_INVALID_ADDRESS, `[EVM] Invalid contract address`, `Address '${address}' is not a valid EVM address`, `Check your config and provide a valid checksummed address.`);
62
150
  this.tttContract = new ethers_1.Contract(address, abi, this.signer);
63
151
  }
64
152
  /**
@@ -66,9 +154,9 @@ class EVMConnector {
66
154
  */
67
155
  attachProtocolFeeContract(address, abi) {
68
156
  if (!this.signer)
69
- throw new errors_1.TTTContractError("Not connected to signer", "EVMConnector.connect() must be called first", "Initialize connection before attaching contracts.");
157
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_SIGNER_NOT_CONNECTED, "Not connected to signer", "EVMConnector.connect() must be called first", "Initialize connection before attaching contracts.");
70
158
  if (!address || !ethers_1.ethers.isAddress(address))
71
- throw new errors_1.TTTContractError(`[EVM] Invalid contract address`, `Address '${address}' is not a valid EVM address`, `Check your config and provide a valid checksummed address.`);
159
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_INVALID_ADDRESS, `[EVM] Invalid contract address`, `Address '${address}' is not a valid EVM address`, `Check your config and provide a valid checksummed address.`);
72
160
  this.protocolFeeContract = new ethers_1.Contract(address, abi, this.signer);
73
161
  }
74
162
  /**
@@ -76,7 +164,7 @@ class EVMConnector {
76
164
  */
77
165
  async submitTTTRecord(record, amount, tier) {
78
166
  if (!this.tttContract)
79
- throw new errors_1.TTTContractError("Contract not attached", "TTT contract instance is null", "Call attachContract() with valid TTT address before burning.");
167
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_NOT_ATTACHED, "Contract not attached", "TTT contract instance is null", "Call attachContract() with valid TTT address before burning.");
80
168
  const grgHash = ethers_1.ethers.keccak256(ethers_1.ethers.concat(record.grgPayload));
81
169
  try {
82
170
  // P1-7: Gas estimation with timeout
@@ -88,14 +176,14 @@ class EVMConnector {
88
176
  const receipt = await tx.wait();
89
177
  // P2-5: Null check for dropped transactions
90
178
  if (!receipt)
91
- throw new errors_1.TTTNetworkError(`[EVM] Transaction failed`, `Transaction was dropped from mempool or null receipt`, `Check block explorer for tx status.`);
179
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_TX_DROPPED, `[EVM] Transaction failed`, `Transaction was dropped from mempool or null receipt`, `Check block explorer for tx status.`);
92
180
  return receipt;
93
181
  }
94
182
  catch (error) {
95
183
  if (error instanceof errors_1.TTTNetworkError || error instanceof errors_1.TTTContractError)
96
184
  throw error;
97
185
  const reason = this.extractRevertReason(error);
98
- throw new errors_1.TTTContractError(`[EVM] Burn failed`, reason, `Verify your TTT balance and tier parameters.`);
186
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_BURN_FAILED, `[EVM] Burn failed`, reason, `Verify your TTT balance and tier parameters.`);
99
187
  }
100
188
  }
101
189
  /**
@@ -103,22 +191,26 @@ class EVMConnector {
103
191
  */
104
192
  async mintTTT(to, amount, grgHash, potHash) {
105
193
  if (!this.tttContract)
106
- throw new errors_1.TTTContractError("Contract not attached", "TTT contract instance is null", "Call attachContract() before minting.");
194
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_NOT_ATTACHED, "Contract not attached", "TTT contract instance is null", "Call attachContract() before minting.");
107
195
  if (!to || !ethers_1.ethers.isAddress(to))
108
- throw new errors_1.TTTContractError(`[EVM] Invalid recipient address`, `Address '${to}' is not a valid EVM address`, `Provide a valid destination address.`);
196
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_INVALID_ADDRESS, `[EVM] Invalid recipient address`, `Address '${to}' is not a valid EVM address`, `Provide a valid destination address.`);
109
197
  try {
110
198
  if (potHash) {
111
199
  logger_1.logger.info(`[EVM] Recording PoT fingerprint: ${potHash}`);
112
200
  }
113
- const tx = await this.tttContract.mint(to, amount, grgHash);
201
+ // Gas estimation with 20% buffer and timeout (matching burnTTT pattern)
202
+ const gasLimit = await this.withTimeout(this.tttContract.mint.estimateGas(to, amount, grgHash));
203
+ const tx = await this.tttContract.mint(to, amount, grgHash, {
204
+ gasLimit: (gasLimit * 120n) / 100n
205
+ });
114
206
  const receipt = await tx.wait();
115
207
  if (!receipt)
116
- throw new errors_1.TTTNetworkError(`[EVM] Mint TX dropped`, `Transaction was dropped from mempool`, `Check operator account for nonce collisions.`);
208
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_TX_DROPPED, `[EVM] Mint TX dropped`, `Transaction was dropped from mempool`, `Check operator account for nonce collisions.`);
117
209
  return receipt;
118
210
  }
119
211
  catch (error) {
120
212
  const reason = this.extractRevertReason(error);
121
- throw new errors_1.TTTContractError(`[EVM] Mint failed`, reason, `Ensure operator has minter role and sufficient gas.`);
213
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_MINT_FAILED, `[EVM] Mint failed`, reason, `Ensure operator has minter role and sufficient gas.`);
122
214
  }
123
215
  }
124
216
  /**
@@ -126,17 +218,17 @@ class EVMConnector {
126
218
  */
127
219
  async burnTTT(amount, grgHash, tierLevel) {
128
220
  if (!this.tttContract)
129
- throw new errors_1.TTTContractError("Contract not attached", "TTT contract instance is null", "Call attachContract() before burning.");
221
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_NOT_ATTACHED, "Contract not attached", "TTT contract instance is null", "Call attachContract() before burning.");
130
222
  try {
131
223
  const tx = await this.tttContract.burn(amount, grgHash, tierLevel);
132
224
  const receipt = await tx.wait();
133
225
  if (!receipt)
134
- throw new errors_1.TTTNetworkError(`[EVM] Burn TX dropped`, `Transaction was dropped from mempool`, `Verify account balance.`);
226
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_TX_DROPPED, `[EVM] Burn TX dropped`, `Transaction was dropped from mempool`, `Verify account balance.`);
135
227
  return { hash: receipt.hash };
136
228
  }
137
229
  catch (error) {
138
230
  const reason = this.extractRevertReason(error);
139
- throw new errors_1.TTTContractError(`[EVM] Burn failed`, reason, `Check TTT balance.`);
231
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_BURN_FAILED, `[EVM] Burn failed`, reason, `Check TTT balance.`);
140
232
  }
141
233
  }
142
234
  /**
@@ -144,13 +236,13 @@ class EVMConnector {
144
236
  */
145
237
  async getTTTBalance(user, tokenId) {
146
238
  if (!this.tttContract)
147
- throw new errors_1.TTTContractError("Contract not attached", "TTT contract instance is null", "Call attachContract() before querying balance.");
239
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_NOT_ATTACHED, "Contract not attached", "TTT contract instance is null", "Call attachContract() before querying balance.");
148
240
  try {
149
241
  return await this.tttContract.balanceOf(user, tokenId);
150
242
  }
151
243
  catch (error) {
152
244
  const reason = this.extractRevertReason(error);
153
- throw new errors_1.TTTContractError(`[EVM] Balance query failed`, reason, `Check RPC connection and contract address.`);
245
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_BALANCE_QUERY_FAILED, `[EVM] Balance query failed`, reason, `Check RPC connection and contract address.`);
154
246
  }
155
247
  }
156
248
  /**
@@ -158,9 +250,9 @@ class EVMConnector {
158
250
  */
159
251
  async swap(routerAddress, tokenIn, tokenOut, amountIn, minAmountOut) {
160
252
  if (!this.signer)
161
- throw new errors_1.TTTContractError("Not connected to signer", "Signer is null", "Initialize connection.");
253
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_SIGNER_NOT_CONNECTED, "Not connected to signer", "Signer is null", "Initialize connection.");
162
254
  if (!routerAddress || !ethers_1.ethers.isAddress(routerAddress))
163
- throw new errors_1.TTTContractError(`[EVM] Invalid router address`, `Address '${routerAddress}' is invalid`, `Provide valid V4 SwapRouter address.`);
255
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_INVALID_ADDRESS, `[EVM] Invalid router address`, `Address '${routerAddress}' is invalid`, `Provide valid V4 SwapRouter address.`);
164
256
  logger_1.logger.info(`[EVM] Swapping ${amountIn} of ${tokenIn} for ${tokenOut} via ${routerAddress}`);
165
257
  // Realistic Uniswap V4-like SwapRouter ABI for simulation/integration
166
258
  const swapRouterAbi = [
@@ -176,14 +268,14 @@ class EVMConnector {
176
268
  logger_1.logger.info(`[EVM] Swap TX Sent: ${tx.hash}`);
177
269
  const receipt = await tx.wait();
178
270
  if (!receipt)
179
- throw new errors_1.TTTNetworkError(`[EVM] Swap TX dropped`, `Transaction dropped`, `Check gas price.`);
271
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_TX_DROPPED, `[EVM] Swap TX dropped`, `Transaction dropped`, `Check gas price.`);
180
272
  return receipt;
181
273
  }
182
274
  catch (error) {
183
275
  if (error instanceof errors_1.TTTNetworkError || error instanceof errors_1.TTTContractError)
184
276
  throw error;
185
277
  const reason = this.extractRevertReason(error);
186
- throw new errors_1.TTTContractError(`[EVM] Swap failed`, reason, `Verify slippage and token balances.`);
278
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_SWAP_FAILED, `[EVM] Swap failed`, reason, `Verify slippage and token balances.`);
187
279
  }
188
280
  }
189
281
  /**
@@ -241,10 +333,10 @@ class EVMConnector {
241
333
  */
242
334
  async verifyBlock(blockNum) {
243
335
  if (!this.provider)
244
- throw new errors_1.TTTNetworkError("Provider not connected", "RPC provider is null", "Call connect() first.");
336
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_PROVIDER_NOT_CONNECTED, "Provider not connected", "RPC provider is null", "Call connect() first.");
245
337
  const block = await this.provider.getBlock(blockNum);
246
338
  if (!block)
247
- throw new errors_1.TTTNetworkError(`Block not found`, `RPC returned null for block ${blockNum}`, `Verify if block number exists on chain.`);
339
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_BLOCK_NOT_FOUND, `Block not found`, `RPC returned null for block ${blockNum}`, `Verify if block number exists on chain.`);
248
340
  return {
249
341
  valid: true,
250
342
  blockNumber: blockNum,
@@ -258,7 +350,7 @@ class EVMConnector {
258
350
  */
259
351
  async getPendingTransactions() {
260
352
  if (!this.provider)
261
- throw new errors_1.TTTNetworkError("Provider not connected", "RPC provider is null", "Call connect() first.");
353
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_PROVIDER_NOT_CONNECTED, "Provider not connected", "RPC provider is null", "Call connect() first.");
262
354
  const block = await this.provider.send("eth_getBlockByNumber", ["pending", false]);
263
355
  return block ? block.transactions : [];
264
356
  }
@@ -267,7 +359,7 @@ class EVMConnector {
267
359
  */
268
360
  getProvider() {
269
361
  if (!this.provider)
270
- throw new errors_1.TTTNetworkError("Provider not connected", "RPC provider is null", "Call connect() first.");
362
+ throw new errors_1.TTTNetworkError(errors_1.ERROR_CODES.NETWORK_PROVIDER_NOT_CONNECTED, "Provider not connected", "RPC provider is null", "Call connect() first.");
271
363
  return this.provider;
272
364
  }
273
365
  /**
@@ -275,7 +367,7 @@ class EVMConnector {
275
367
  */
276
368
  getSigner() {
277
369
  if (!this.signer)
278
- throw new errors_1.TTTContractError("Signer not connected", "Signer is null", "Call connect() first.");
370
+ throw new errors_1.TTTContractError(errors_1.ERROR_CODES.CONTRACT_SIGNER_NOT_CONNECTED, "Signer not connected", "Signer is null", "Call connect() first.");
279
371
  return this.signer;
280
372
  }
281
373
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- export * from "./grg_forward";
2
- export * from "./grg_inverse";
1
+ export * from "../vendor/helm-crypto";
3
2
  export * from "./adaptive_switch";
4
3
  export * from "./evm_connector";
5
4
  export * from "./x402_enforcer";
@@ -13,10 +12,10 @@ export * from "./ttt_client";
13
12
  export * from "./auto_mint";
14
13
  export * from "./time_synthesis";
15
14
  export * from "./dynamic_fee";
16
- export * from "./golay";
17
- export * from "./grg_pipeline";
18
15
  export * from "./signer";
19
16
  export * from "./networks";
20
- export * from "./reed_solomon";
21
17
  export * from "./errors";
22
18
  export * from "./pot_signer";
19
+ export * from "./ct_log";
20
+ export * from "./trust_store";
21
+ export * from "./revenue_tiers";
package/dist/index.js CHANGED
@@ -15,8 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  // sdk/src/index.ts
18
- __exportStar(require("./grg_forward"), exports);
19
- __exportStar(require("./grg_inverse"), exports);
18
+ __exportStar(require("../vendor/helm-crypto"), exports);
20
19
  __exportStar(require("./adaptive_switch"), exports);
21
20
  __exportStar(require("./evm_connector"), exports);
22
21
  __exportStar(require("./x402_enforcer"), exports);
@@ -30,10 +29,10 @@ __exportStar(require("./ttt_client"), exports);
30
29
  __exportStar(require("./auto_mint"), exports);
31
30
  __exportStar(require("./time_synthesis"), exports);
32
31
  __exportStar(require("./dynamic_fee"), exports);
33
- __exportStar(require("./golay"), exports);
34
- __exportStar(require("./grg_pipeline"), exports);
35
32
  __exportStar(require("./signer"), exports);
36
33
  __exportStar(require("./networks"), exports);
37
- __exportStar(require("./reed_solomon"), exports);
38
34
  __exportStar(require("./errors"), exports);
39
35
  __exportStar(require("./pot_signer"), exports);
36
+ __exportStar(require("./ct_log"), exports);
37
+ __exportStar(require("./trust_store"), exports);
38
+ __exportStar(require("./revenue_tiers"), exports);
package/dist/logger.d.ts CHANGED
@@ -1,18 +1,50 @@
1
1
  export declare enum LogLevel {
2
- INFO = "INFO",
3
- WARN = "WARN",
4
- ERROR = "ERROR",
5
- DEBUG = "DEBUG"
2
+ DEBUG = 0,
3
+ INFO = 1,
4
+ WARN = 2,
5
+ ERROR = 3,
6
+ SILENT = 4
7
+ }
8
+ /**
9
+ * Custom log handler function type.
10
+ * @param level - The severity level of the log message.
11
+ * @param message - The formatted log message string.
12
+ */
13
+ export type LogHandler = (level: LogLevel, message: string) => void;
14
+ interface LoggerConfig {
15
+ level?: LogLevel;
16
+ handler?: LogHandler;
6
17
  }
7
18
  export declare class Logger {
8
19
  private static instance;
20
+ private static currentLevel;
21
+ private static currentHandler;
9
22
  private namespace;
10
23
  private constructor();
11
24
  static getInstance(namespace?: string): Logger;
25
+ /**
26
+ * Configure the global logger level and/or handler.
27
+ * @param config - Configuration object with optional level and handler.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * Logger.configure({ level: LogLevel.DEBUG });
32
+ * Logger.configure({ handler: (level, msg) => myLogService.send(msg) });
33
+ * Logger.configure({ level: LogLevel.WARN, handler: customHandler });
34
+ * ```
35
+ */
36
+ static configure(config: LoggerConfig): void;
37
+ /**
38
+ * Convenience method to suppress all log output.
39
+ * Equivalent to `Logger.configure({ level: LogLevel.SILENT })`.
40
+ */
41
+ static silent(): void;
12
42
  private formatMessage;
43
+ private emit;
13
44
  info(message: string): void;
14
45
  warn(message: string): void;
15
46
  error(message: string, error?: Error): void;
16
47
  debug(message: string): void;
17
48
  }
18
49
  export declare const logger: Logger;
50
+ export {};
package/dist/logger.js CHANGED
@@ -4,13 +4,42 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.logger = exports.Logger = exports.LogLevel = void 0;
5
5
  var LogLevel;
6
6
  (function (LogLevel) {
7
- LogLevel["INFO"] = "INFO";
8
- LogLevel["WARN"] = "WARN";
9
- LogLevel["ERROR"] = "ERROR";
10
- LogLevel["DEBUG"] = "DEBUG";
7
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
8
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
9
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
10
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
11
+ LogLevel[LogLevel["SILENT"] = 4] = "SILENT";
11
12
  })(LogLevel || (exports.LogLevel = LogLevel = {}));
13
+ const LOG_LEVEL_NAMES = {
14
+ [LogLevel.DEBUG]: "DEBUG",
15
+ [LogLevel.INFO]: "INFO",
16
+ [LogLevel.WARN]: "WARN",
17
+ [LogLevel.ERROR]: "ERROR",
18
+ [LogLevel.SILENT]: "SILENT",
19
+ };
20
+ /**
21
+ * Default log handler that writes to the console.
22
+ */
23
+ const defaultHandler = (level, message) => {
24
+ switch (level) {
25
+ case LogLevel.DEBUG:
26
+ console.debug(message);
27
+ break;
28
+ case LogLevel.INFO:
29
+ console.log(message);
30
+ break;
31
+ case LogLevel.WARN:
32
+ console.warn(message);
33
+ break;
34
+ case LogLevel.ERROR:
35
+ console.error(message);
36
+ break;
37
+ }
38
+ };
12
39
  class Logger {
13
40
  static instance;
41
+ static currentLevel = LogLevel.INFO;
42
+ static currentHandler = defaultHandler;
14
43
  namespace;
15
44
  constructor(namespace = "TTT-SDK") {
16
45
  this.namespace = namespace;
@@ -21,15 +50,47 @@ class Logger {
21
50
  }
22
51
  return Logger.instance;
23
52
  }
53
+ /**
54
+ * Configure the global logger level and/or handler.
55
+ * @param config - Configuration object with optional level and handler.
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * Logger.configure({ level: LogLevel.DEBUG });
60
+ * Logger.configure({ handler: (level, msg) => myLogService.send(msg) });
61
+ * Logger.configure({ level: LogLevel.WARN, handler: customHandler });
62
+ * ```
63
+ */
64
+ static configure(config) {
65
+ if (config.level !== undefined) {
66
+ Logger.currentLevel = config.level;
67
+ }
68
+ if (config.handler !== undefined) {
69
+ Logger.currentHandler = config.handler;
70
+ }
71
+ }
72
+ /**
73
+ * Convenience method to suppress all log output.
74
+ * Equivalent to `Logger.configure({ level: LogLevel.SILENT })`.
75
+ */
76
+ static silent() {
77
+ Logger.currentLevel = LogLevel.SILENT;
78
+ }
24
79
  formatMessage(level, message) {
25
80
  const timestamp = new Date().toISOString();
26
- return `[${timestamp}] [${level}] [${this.namespace}] ${message}`;
81
+ return `[${timestamp}] [${LOG_LEVEL_NAMES[level]}] [${this.namespace}] ${message}`;
82
+ }
83
+ emit(level, message) {
84
+ if (level < Logger.currentLevel)
85
+ return;
86
+ const formatted = this.formatMessage(level, message);
87
+ Logger.currentHandler(level, formatted);
27
88
  }
28
89
  info(message) {
29
- console.log(this.formatMessage(LogLevel.INFO, message));
90
+ this.emit(LogLevel.INFO, message);
30
91
  }
31
92
  warn(message) {
32
- console.warn(this.formatMessage(LogLevel.WARN, message));
93
+ this.emit(LogLevel.WARN, message);
33
94
  }
34
95
  error(message, error) {
35
96
  let msg = message;
@@ -39,12 +100,10 @@ class Logger {
39
100
  msg += `\nStack: ${error.stack}`;
40
101
  }
41
102
  }
42
- console.error(this.formatMessage(LogLevel.ERROR, msg));
103
+ this.emit(LogLevel.ERROR, msg);
43
104
  }
44
105
  debug(message) {
45
- if (process.env.DEBUG) {
46
- console.debug(this.formatMessage(LogLevel.DEBUG, message));
47
- }
106
+ this.emit(LogLevel.DEBUG, message);
48
107
  }
49
108
  }
50
109
  exports.Logger = Logger;
@@ -8,6 +8,27 @@ export interface NetworkConfig {
8
8
  protocolFeeAddress: string;
9
9
  usdcAddress: string;
10
10
  }
11
+ /**
12
+ * Base Mainnet network preset.
13
+ *
14
+ * `tttAddress` and `protocolFeeAddress` are set to the zero address because the
15
+ * TTT contracts have not yet been deployed to Base Mainnet. These are
16
+ * placeholders only — using them without an override will cause a runtime error
17
+ * (validated in `TTTClient.create`).
18
+ *
19
+ * **Operators deploying to mainnet** must supply their own `contractAddress` and
20
+ * `feeCollectorAddress` via `TTTClientConfig` when calling `TTTClient.create()`.
21
+ * Example:
22
+ * ```ts
23
+ * const client = await TTTClient.create({
24
+ * network: "base",
25
+ * contractAddress: "0xYourDeployedTTTContract",
26
+ * feeCollectorAddress: "0xYourFeeCollector",
27
+ * // ...other config
28
+ * });
29
+ * ```
30
+ */
11
31
  export declare const BASE_MAINNET: NetworkConfig;
32
+ export declare const ETH_SEPOLIA: NetworkConfig;
12
33
  export declare const BASE_SEPOLIA: NetworkConfig;
13
34
  export declare const NETWORKS: Record<string, NetworkConfig>;
package/dist/networks.js CHANGED
@@ -1,8 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NETWORKS = exports.BASE_SEPOLIA = exports.BASE_MAINNET = void 0;
4
- // ⚠️ MAINNET ADDRESSES NOT YET DEPLOYED — must be overridden via TTTClientConfig.contractAddress
5
- // Using these defaults without override will throw at runtime (validated in TTTClient.create)
3
+ exports.NETWORKS = exports.BASE_SEPOLIA = exports.ETH_SEPOLIA = exports.BASE_MAINNET = void 0;
4
+ /**
5
+ * Base Mainnet network preset.
6
+ *
7
+ * `tttAddress` and `protocolFeeAddress` are set to the zero address because the
8
+ * TTT contracts have not yet been deployed to Base Mainnet. These are
9
+ * placeholders only — using them without an override will cause a runtime error
10
+ * (validated in `TTTClient.create`).
11
+ *
12
+ * **Operators deploying to mainnet** must supply their own `contractAddress` and
13
+ * `feeCollectorAddress` via `TTTClientConfig` when calling `TTTClient.create()`.
14
+ * Example:
15
+ * ```ts
16
+ * const client = await TTTClient.create({
17
+ * network: "base",
18
+ * contractAddress: "0xYourDeployedTTTContract",
19
+ * feeCollectorAddress: "0xYourFeeCollector",
20
+ * // ...other config
21
+ * });
22
+ * ```
23
+ */
6
24
  exports.BASE_MAINNET = {
7
25
  chainId: 8453,
8
26
  rpcUrl: "https://mainnet.base.org",
@@ -10,6 +28,13 @@ exports.BASE_MAINNET = {
10
28
  protocolFeeAddress: "0x0000000000000000000000000000000000000000",
11
29
  usdcAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
12
30
  };
31
+ exports.ETH_SEPOLIA = {
32
+ chainId: 11155111,
33
+ rpcUrl: "https://ethereum-sepolia-rpc.publicnode.com",
34
+ tttAddress: "0x291b83F605F2dA95cf843d4a53983B413ef3B929",
35
+ protocolFeeAddress: "0x6b39D96741BB4Ce6283F824CC31c2931c75AEe64",
36
+ usdcAddress: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
37
+ };
13
38
  exports.BASE_SEPOLIA = {
14
39
  chainId: 84532,
15
40
  rpcUrl: "https://sepolia.base.org",
@@ -19,5 +44,6 @@ exports.BASE_SEPOLIA = {
19
44
  };
20
45
  exports.NETWORKS = {
21
46
  base: exports.BASE_MAINNET,
22
- sepolia: exports.BASE_SEPOLIA,
47
+ sepolia: exports.ETH_SEPOLIA,
48
+ baseSepolia: exports.BASE_SEPOLIA,
23
49
  };
@@ -55,4 +55,13 @@ export declare class PoolRegistry {
55
55
  * @returns Array of pool addresses.
56
56
  */
57
57
  listPools(): string[];
58
+ /**
59
+ * Serialize registry state to JSON for persistence across restarts.
60
+ * Allows operators to restore pool registrations and stats without re-registering.
61
+ */
62
+ serialize(): string;
63
+ /**
64
+ * Reconstruct a PoolRegistry from previously serialized JSON state.
65
+ */
66
+ static deserialize(json: string): PoolRegistry;
58
67
  }