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.
- package/README.md +4 -4
- 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/index.d.ts +4 -5
- package/dist/index.js +4 -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 +134 -20
- 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 +24 -29
- package/dist/ttt_client.js +97 -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 +1 -1
package/dist/evm_connector.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 "
|
|
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("
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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["
|
|
8
|
-
LogLevel["
|
|
9
|
-
LogLevel["
|
|
10
|
-
LogLevel["
|
|
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
|
-
|
|
90
|
+
this.emit(LogLevel.INFO, message);
|
|
30
91
|
}
|
|
31
92
|
warn(message) {
|
|
32
|
-
|
|
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
|
-
|
|
103
|
+
this.emit(LogLevel.ERROR, msg);
|
|
43
104
|
}
|
|
44
105
|
debug(message) {
|
|
45
|
-
|
|
46
|
-
console.debug(this.formatMessage(LogLevel.DEBUG, message));
|
|
47
|
-
}
|
|
106
|
+
this.emit(LogLevel.DEBUG, message);
|
|
48
107
|
}
|
|
49
108
|
}
|
|
50
109
|
exports.Logger = Logger;
|
package/dist/networks.d.ts
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
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.
|
|
47
|
+
sepolia: exports.ETH_SEPOLIA,
|
|
48
|
+
baseSepolia: exports.BASE_SEPOLIA,
|
|
23
49
|
};
|
package/dist/pool_registry.d.ts
CHANGED
|
@@ -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
|
}
|