@lawrenceliang-btc/atel-sdk 0.8.7

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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +221 -0
  3. package/bin/atel.mjs +2692 -0
  4. package/bin/tunnel-manager.mjs +171 -0
  5. package/dist/anchor/base.d.ts +21 -0
  6. package/dist/anchor/base.js +26 -0
  7. package/dist/anchor/bsc.d.ts +20 -0
  8. package/dist/anchor/bsc.js +25 -0
  9. package/dist/anchor/evm.d.ts +99 -0
  10. package/dist/anchor/evm.js +262 -0
  11. package/dist/anchor/index.d.ts +173 -0
  12. package/dist/anchor/index.js +165 -0
  13. package/dist/anchor/mock.d.ts +43 -0
  14. package/dist/anchor/mock.js +100 -0
  15. package/dist/anchor/solana.d.ts +95 -0
  16. package/dist/anchor/solana.js +298 -0
  17. package/dist/auditor/index.d.ts +54 -0
  18. package/dist/auditor/index.js +141 -0
  19. package/dist/collaboration/index.d.ts +146 -0
  20. package/dist/collaboration/index.js +237 -0
  21. package/dist/crypto/index.d.ts +162 -0
  22. package/dist/crypto/index.js +231 -0
  23. package/dist/endpoint/index.d.ts +147 -0
  24. package/dist/endpoint/index.js +390 -0
  25. package/dist/envelope/index.d.ts +104 -0
  26. package/dist/envelope/index.js +156 -0
  27. package/dist/executor/index.d.ts +71 -0
  28. package/dist/executor/index.js +398 -0
  29. package/dist/gateway/index.d.ts +278 -0
  30. package/dist/gateway/index.js +520 -0
  31. package/dist/graph/index.d.ts +215 -0
  32. package/dist/graph/index.js +524 -0
  33. package/dist/handshake/index.d.ts +166 -0
  34. package/dist/handshake/index.js +287 -0
  35. package/dist/identity/index.d.ts +155 -0
  36. package/dist/identity/index.js +250 -0
  37. package/dist/index.d.ts +23 -0
  38. package/dist/index.js +28 -0
  39. package/dist/negotiation/index.d.ts +133 -0
  40. package/dist/negotiation/index.js +160 -0
  41. package/dist/network/index.d.ts +78 -0
  42. package/dist/network/index.js +207 -0
  43. package/dist/orchestrator/index.d.ts +190 -0
  44. package/dist/orchestrator/index.js +297 -0
  45. package/dist/policy/index.d.ts +100 -0
  46. package/dist/policy/index.js +206 -0
  47. package/dist/proof/index.d.ts +220 -0
  48. package/dist/proof/index.js +541 -0
  49. package/dist/registry/index.d.ts +98 -0
  50. package/dist/registry/index.js +129 -0
  51. package/dist/rollback/index.d.ts +76 -0
  52. package/dist/rollback/index.js +91 -0
  53. package/dist/schema/capability-schema.json +52 -0
  54. package/dist/schema/index.d.ts +128 -0
  55. package/dist/schema/index.js +163 -0
  56. package/dist/schema/task-schema.json +69 -0
  57. package/dist/score/index.d.ts +174 -0
  58. package/dist/score/index.js +275 -0
  59. package/dist/service/index.d.ts +34 -0
  60. package/dist/service/index.js +273 -0
  61. package/dist/service/server.d.ts +7 -0
  62. package/dist/service/server.js +22 -0
  63. package/dist/trace/index.d.ts +217 -0
  64. package/dist/trace/index.js +446 -0
  65. package/dist/trust/index.d.ts +84 -0
  66. package/dist/trust/index.js +107 -0
  67. package/dist/trust-sync/index.d.ts +30 -0
  68. package/dist/trust-sync/index.js +57 -0
  69. package/package.json +71 -0
  70. package/skill/SKILL.md +363 -0
  71. package/skill/references/commercial.md +184 -0
  72. package/skill/references/executor.md +356 -0
  73. package/skill/references/networking.md +64 -0
  74. package/skill/references/onchain.md +73 -0
  75. package/skill/references/security.md +96 -0
@@ -0,0 +1,273 @@
1
+ /**
2
+ * Trust Score Network Service
3
+ *
4
+ * HTTP API wrapping TrustScoreClient and TrustGraph with
5
+ * JSON file persistence. MVP — no database required.
6
+ */
7
+ import express from 'express';
8
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
9
+ import { resolve } from 'node:path';
10
+ import { TrustScoreClient, } from '../score/index.js';
11
+ import { TrustGraph, calculateTaskWeight, } from '../graph/index.js';
12
+ // ─── Service ─────────────────────────────────────────────────────
13
+ export class TrustScoreService {
14
+ app;
15
+ scoreClient;
16
+ graph;
17
+ config;
18
+ server = null;
19
+ summaries = [];
20
+ constructor(config) {
21
+ this.config = config;
22
+ this.app = express();
23
+ this.scoreClient = new TrustScoreClient();
24
+ this.graph = new TrustGraph();
25
+ this.app.use(express.json());
26
+ this.setupRoutes();
27
+ this.app.use(this.errorHandler.bind(this));
28
+ }
29
+ // ── Lifecycle ────────────────────────────────────────────────
30
+ async start() {
31
+ this.loadData();
32
+ return new Promise((resolve) => {
33
+ this.server = this.app.listen(this.config.port, () => {
34
+ console.log(`[ATEL] Trust Score Service listening on :${this.config.port}`);
35
+ resolve();
36
+ });
37
+ });
38
+ }
39
+ async stop() {
40
+ return new Promise((resolve, reject) => {
41
+ if (!this.server)
42
+ return resolve();
43
+ this.server.close((err) => (err ? reject(err) : resolve()));
44
+ this.server = null;
45
+ });
46
+ }
47
+ // ── Persistence ──────────────────────────────────────────────
48
+ saveData() {
49
+ const dir = resolve(this.config.dataDir);
50
+ if (!existsSync(dir))
51
+ mkdirSync(dir, { recursive: true });
52
+ writeFileSync(resolve(dir, 'scores.json'), JSON.stringify(this.summaries, null, 2));
53
+ const graphExport = this.graph.exportGraph();
54
+ const graphData = {
55
+ nodes: graphExport.nodes.map((n) => ({
56
+ ...n,
57
+ scenes: [...n.scenes],
58
+ })),
59
+ edges: graphExport.edges,
60
+ };
61
+ writeFileSync(resolve(dir, 'graph.json'), JSON.stringify(graphData, null, 2));
62
+ console.log(`[ATEL] Data saved to ${dir}`);
63
+ }
64
+ loadData() {
65
+ const dir = resolve(this.config.dataDir);
66
+ // Load summaries and replay into TrustScoreClient
67
+ const scoresPath = resolve(dir, 'scores.json');
68
+ if (existsSync(scoresPath)) {
69
+ try {
70
+ const raw = readFileSync(scoresPath, 'utf-8');
71
+ const loaded = JSON.parse(raw);
72
+ this.summaries = loaded;
73
+ this.scoreClient = new TrustScoreClient();
74
+ for (const s of loaded) {
75
+ this.scoreClient.submitExecutionSummary(s);
76
+ }
77
+ console.log(`[ATEL] Loaded ${loaded.length} summaries from disk`);
78
+ }
79
+ catch (e) {
80
+ console.error('[ATEL] Failed to load scores.json:', e);
81
+ }
82
+ }
83
+ // Load graph data and replay into TrustGraph
84
+ const graphPath = resolve(dir, 'graph.json');
85
+ if (existsSync(graphPath)) {
86
+ try {
87
+ const raw = readFileSync(graphPath, 'utf-8');
88
+ const data = JSON.parse(raw);
89
+ this.graph = new TrustGraph();
90
+ // Restore nodes with metadata
91
+ for (const n of data.nodes) {
92
+ this.graph.addNode(n.agent_id, n.metadata);
93
+ }
94
+ // Replay interactions from summaries to rebuild edges properly
95
+ // (edges contain computed fields like consistency_score that need
96
+ // the running EMA, so we replay from summaries instead)
97
+ for (const s of this.summaries) {
98
+ const taskWeight = calculateTaskWeight({
99
+ tool_calls: s.tool_calls,
100
+ duration_ms: s.duration_ms,
101
+ max_cost: s.risk_level === 'critical' ? 10 : s.risk_level === 'high' ? 5 : s.risk_level === 'medium' ? 2 : 1,
102
+ risk_level: s.risk_level,
103
+ similar_task_count: 0,
104
+ });
105
+ this.graph.recordInteraction({
106
+ from: s.issuer,
107
+ to: s.executor,
108
+ scene: s.task_type,
109
+ success: s.success,
110
+ task_weight: taskWeight,
111
+ duration_ms: s.duration_ms,
112
+ });
113
+ }
114
+ console.log(`[ATEL] Loaded graph: ${data.nodes.length} nodes, ${data.edges.length} edges`);
115
+ }
116
+ catch (e) {
117
+ console.error('[ATEL] Failed to load graph.json:', e);
118
+ }
119
+ }
120
+ }
121
+ // ── Routes ───────────────────────────────────────────────────
122
+ setupRoutes() {
123
+ const r = express.Router();
124
+ // Health check
125
+ r.get('/health', (_req, res) => {
126
+ res.json({ status: 'ok', timestamp: new Date().toISOString() });
127
+ });
128
+ // Submit execution summary
129
+ r.post('/summary', (req, res, next) => {
130
+ try {
131
+ const body = req.body;
132
+ this.validateSummary(body);
133
+ // 1. Submit to TrustScoreClient
134
+ this.scoreClient.submitExecutionSummary(body);
135
+ // 2. Update TrustGraph
136
+ const taskWeight = calculateTaskWeight({
137
+ tool_calls: body.tool_calls,
138
+ duration_ms: body.duration_ms,
139
+ max_cost: body.risk_level === 'critical' ? 10 : body.risk_level === 'high' ? 5 : body.risk_level === 'medium' ? 2 : 1,
140
+ risk_level: body.risk_level,
141
+ similar_task_count: 0,
142
+ });
143
+ this.graph.recordInteraction({
144
+ from: body.issuer,
145
+ to: body.executor,
146
+ scene: body.task_type,
147
+ success: body.success,
148
+ task_weight: taskWeight,
149
+ duration_ms: body.duration_ms,
150
+ });
151
+ // 3. Persist
152
+ this.summaries.push(body);
153
+ this.saveData();
154
+ // 4. Return updated score
155
+ const report = this.scoreClient.getAgentScore(body.executor);
156
+ res.status(201).json(report);
157
+ }
158
+ catch (err) {
159
+ next(err);
160
+ }
161
+ });
162
+ // Query single agent score
163
+ r.get('/score/:agentId', (req, res) => {
164
+ const agentId = Array.isArray(req.params.agentId) ? req.params.agentId[0] : req.params.agentId;
165
+ const report = this.scoreClient.getAgentScore(agentId);
166
+ res.json(report);
167
+ });
168
+ // Query all scores
169
+ r.get('/scores', (_req, res) => {
170
+ res.json(this.scoreClient.getAllScores());
171
+ });
172
+ // ── Graph routes ───────────────────────────────────────────
173
+ // Composite trust query
174
+ r.post('/graph/trust', (req, res, next) => {
175
+ try {
176
+ const { from, to, scene } = req.body;
177
+ if (!from || !to || !scene) {
178
+ res.status(400).json({ error: 'from, to, and scene are required' });
179
+ return;
180
+ }
181
+ const result = this.graph.compositeTrust(from, to, scene);
182
+ res.json(result);
183
+ }
184
+ catch (err) {
185
+ next(err);
186
+ }
187
+ });
188
+ // Node info
189
+ r.get('/graph/node/:agentId', (req, res) => {
190
+ const agentId = Array.isArray(req.params.agentId) ? req.params.agentId[0] : req.params.agentId;
191
+ const node = this.graph.getNode(agentId);
192
+ if (!node) {
193
+ res.status(404).json({ error: 'Agent not found in graph' });
194
+ return;
195
+ }
196
+ // Serialize Set → array
197
+ res.json({ ...node, scenes: [...node.scenes] });
198
+ });
199
+ // Top partners
200
+ r.get('/graph/partners/:agentId', (req, res) => {
201
+ const agentId = Array.isArray(req.params.agentId) ? req.params.agentId[0] : req.params.agentId;
202
+ const k = parseInt(req.query.k) || 10;
203
+ const partners = this.graph.topPartners(agentId, k);
204
+ res.json(partners);
205
+ });
206
+ // Scene top agents
207
+ r.get('/graph/scene/:scene', (req, res) => {
208
+ const scene = Array.isArray(req.params.scene) ? req.params.scene[0] : req.params.scene;
209
+ const k = parseInt(req.query.k) || 10;
210
+ const agents = this.graph.topAgentsForScene(scene, k);
211
+ res.json(agents);
212
+ });
213
+ // Behavior consistency
214
+ r.get('/graph/consistency/:agentId', (req, res) => {
215
+ const agentId = Array.isArray(req.params.agentId) ? req.params.agentId[0] : req.params.agentId;
216
+ const result = this.graph.behaviorConsistencyScore(agentId);
217
+ res.json(result);
218
+ });
219
+ // Suspicious clusters
220
+ r.get('/graph/suspicious', (_req, res) => {
221
+ const clusters = this.graph.detectSuspiciousClusters();
222
+ res.json(clusters);
223
+ });
224
+ // Graph stats
225
+ r.get('/graph/stats', (_req, res) => {
226
+ res.json(this.graph.getStats());
227
+ });
228
+ this.app.use('/api/v1', r);
229
+ }
230
+ // ── Validation ───────────────────────────────────────────────
231
+ validateSummary(body) {
232
+ const required = [
233
+ 'executor', 'issuer', 'task_id', 'task_type',
234
+ 'risk_level', 'proof_id', 'timestamp',
235
+ ];
236
+ for (const field of required) {
237
+ if (!body[field]) {
238
+ throw new ValidationError(`${field} is required`);
239
+ }
240
+ }
241
+ const validRisk = ['low', 'medium', 'high', 'critical'];
242
+ if (!validRisk.includes(body.risk_level)) {
243
+ throw new ValidationError(`risk_level must be one of: ${validRisk.join(', ')}`);
244
+ }
245
+ if (typeof body.success !== 'boolean') {
246
+ throw new ValidationError('success must be a boolean');
247
+ }
248
+ if (typeof body.duration_ms !== 'number' || body.duration_ms < 0) {
249
+ throw new ValidationError('duration_ms must be a non-negative number');
250
+ }
251
+ if (typeof body.tool_calls !== 'number' || body.tool_calls < 0) {
252
+ throw new ValidationError('tool_calls must be a non-negative number');
253
+ }
254
+ if (typeof body.policy_violations !== 'number' || body.policy_violations < 0) {
255
+ throw new ValidationError('policy_violations must be a non-negative number');
256
+ }
257
+ }
258
+ // ── Error handling ───────────────────────────────────────────
259
+ errorHandler(err, _req, res, _next) {
260
+ if (err instanceof ValidationError) {
261
+ res.status(400).json({ error: err.message });
262
+ return;
263
+ }
264
+ console.error('[ATEL] Unhandled error:', err);
265
+ res.status(500).json({ error: 'Internal server error' });
266
+ }
267
+ }
268
+ class ValidationError extends Error {
269
+ constructor(message) {
270
+ super(message);
271
+ this.name = 'ValidationError';
272
+ }
273
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Standalone server entry point.
3
+ *
4
+ * Usage:
5
+ * ATEL_PORT=3100 ATEL_DATA_DIR=./data tsx src/service/server.ts
6
+ */
7
+ export {};
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Standalone server entry point.
3
+ *
4
+ * Usage:
5
+ * ATEL_PORT=3100 ATEL_DATA_DIR=./data tsx src/service/server.ts
6
+ */
7
+ import { TrustScoreService } from './index.js';
8
+ const service = new TrustScoreService({
9
+ port: parseInt(process.env.ATEL_PORT || '3100', 10),
10
+ dataDir: process.env.ATEL_DATA_DIR || './data',
11
+ });
12
+ service.start().then(() => {
13
+ console.log('ATEL Trust Score Service started');
14
+ });
15
+ // Graceful shutdown
16
+ const shutdown = async () => {
17
+ console.log('\n[ATEL] Shutting down...');
18
+ await service.stop();
19
+ process.exit(0);
20
+ };
21
+ process.on('SIGINT', shutdown);
22
+ process.on('SIGTERM', shutdown);
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Module 5: Execution Trace
3
+ *
4
+ * Tamper-evident execution trace built on a hash chain.
5
+ * Every event links to the previous event's hash, forming
6
+ * an append-only, verifiable log of agent activity.
7
+ */
8
+ import type { AgentIdentity } from '../identity/index.js';
9
+ /** All recognized trace event types */
10
+ export type TraceEventType = 'TASK_ACCEPTED' | 'TOOL_CALL' | 'TOOL_RESULT' | 'POLICY_CHECK' | 'POLICY_VIOLATION' | 'CHECKPOINT' | 'TASK_RESULT' | 'TASK_FAILED' | 'ROLLBACK';
11
+ /** A single event in the execution trace */
12
+ export interface TraceEvent {
13
+ /** Monotonically increasing sequence number (0-based) */
14
+ seq: number;
15
+ /** ISO 8601 timestamp */
16
+ ts: string;
17
+ /** Event type */
18
+ type: TraceEventType;
19
+ /** Task this event belongs to */
20
+ task_id: string;
21
+ /** Event-specific payload */
22
+ data: Record<string, unknown>;
23
+ /** Hash of the previous event ("0x00" for the first event) */
24
+ prev: string;
25
+ /** Hash of this event */
26
+ hash: string;
27
+ /** Optional signature (present on CHECKPOINT events) */
28
+ sig?: string;
29
+ }
30
+ /** Options for ExecutionTrace construction */
31
+ export interface TraceOptions {
32
+ /** Number of events between automatic checkpoints (default: 50) */
33
+ checkpointInterval?: number;
34
+ /** Persistence options */
35
+ storage?: TraceStorageOptions;
36
+ }
37
+ /** Options for trace file persistence */
38
+ export interface TraceStorageOptions {
39
+ /** Directory to store trace files */
40
+ dir: string;
41
+ /** Whether to auto-save after each append (default: false) */
42
+ autoSave: boolean;
43
+ }
44
+ /** Statistics about the trace */
45
+ export interface TraceStats {
46
+ task_id: string;
47
+ event_count: number;
48
+ tool_calls: number;
49
+ tool_results: number;
50
+ policy_checks: number;
51
+ policy_violations: number;
52
+ checkpoints: number;
53
+ first_event_ts: string | null;
54
+ last_event_ts: string | null;
55
+ duration_ms: number | null;
56
+ finalized: boolean;
57
+ failed: boolean;
58
+ }
59
+ /**
60
+ * Compute the hash of a trace event.
61
+ *
62
+ * Formula:
63
+ * ```
64
+ * SHA256( seq + "|" + ts + "|" + type + "|" + SHA256(sortedStringify(data)) + "|" + prev_hash )
65
+ * ```
66
+ *
67
+ * @param seq - Sequence number.
68
+ * @param ts - ISO 8601 timestamp.
69
+ * @param type - Event type.
70
+ * @param data - Event data payload.
71
+ * @param prev - Previous event hash.
72
+ * @returns Hex-encoded SHA-256 hash.
73
+ */
74
+ export declare function computeEventHash(seq: number, ts: string, type: string, data: Record<string, unknown>, prev: string): string;
75
+ /**
76
+ * Tamper-evident, append-only execution trace.
77
+ *
78
+ * Each event is hash-chained to the previous one. Periodic checkpoints
79
+ * include a signature from the agent identity for non-repudiation.
80
+ */
81
+ export declare class ExecutionTrace {
82
+ private readonly taskId;
83
+ private readonly identity;
84
+ private readonly checkpointInterval;
85
+ private readonly storage?;
86
+ private readonly events;
87
+ private seq;
88
+ private finalized;
89
+ private failed;
90
+ private eventsSinceCheckpoint;
91
+ /**
92
+ * @param taskId - Unique identifier for the task being traced.
93
+ * @param agentIdentity - The agent's cryptographic identity (for signing).
94
+ * @param options - Optional configuration.
95
+ */
96
+ constructor(taskId: string, agentIdentity: AgentIdentity, options?: TraceOptions);
97
+ /**
98
+ * Append a new event to the trace.
99
+ *
100
+ * Automatically triggers a checkpoint when the configured interval is reached.
101
+ *
102
+ * @param type - The event type.
103
+ * @param data - Event-specific data payload.
104
+ * @returns The created TraceEvent.
105
+ * @throws If the trace has already been finalized or failed.
106
+ */
107
+ append(type: TraceEventType, data: Record<string, unknown>): TraceEvent;
108
+ /**
109
+ * Create a checkpoint event with a signature.
110
+ *
111
+ * The checkpoint captures cumulative statistics and a Merkle root
112
+ * placeholder (full Merkle tree is built in Module 6).
113
+ *
114
+ * @returns The checkpoint TraceEvent.
115
+ */
116
+ checkpoint(): TraceEvent;
117
+ /**
118
+ * Finalize the trace with a TASK_RESULT event.
119
+ *
120
+ * @param result - The task result data.
121
+ * @returns The hash of the final event (trace_hash).
122
+ */
123
+ finalize(result: Record<string, unknown>): string;
124
+ /**
125
+ * Mark the trace as failed with a TASK_FAILED event.
126
+ *
127
+ * @param error - Error information.
128
+ * @returns The TASK_FAILED event.
129
+ */
130
+ fail(error: Record<string, unknown> | Error): TraceEvent;
131
+ /**
132
+ * Verify the integrity of the entire hash chain.
133
+ *
134
+ * Recomputes every event hash and checks it matches the stored hash,
135
+ * and that each event's `prev` matches the preceding event's hash.
136
+ *
137
+ * @returns True if the chain is intact, false otherwise.
138
+ */
139
+ verify(): {
140
+ valid: boolean;
141
+ errors: string[];
142
+ };
143
+ /**
144
+ * Export the trace as a JSONL (JSON Lines) string.
145
+ *
146
+ * @returns Each event serialized as one JSON line.
147
+ */
148
+ export(): string;
149
+ /**
150
+ * Export the trace to a file in JSONL format.
151
+ *
152
+ * @param path - File path to write to.
153
+ */
154
+ exportToFile(path: string): Promise<void>;
155
+ /**
156
+ * Return a copy of all events.
157
+ *
158
+ * @returns Array of TraceEvent objects.
159
+ */
160
+ getEvents(): ReadonlyArray<TraceEvent>;
161
+ /**
162
+ * Return statistics about the trace.
163
+ *
164
+ * @returns A TraceStats object.
165
+ */
166
+ getStats(): TraceStats;
167
+ /**
168
+ * Get the task ID for this trace.
169
+ */
170
+ getTaskId(): string;
171
+ /**
172
+ * Check whether the trace has been finalized.
173
+ */
174
+ isFinalized(): boolean;
175
+ /**
176
+ * Check whether the trace has been marked as failed.
177
+ */
178
+ isFailed(): boolean;
179
+ /**
180
+ * Save the entire trace to a JSONL file.
181
+ *
182
+ * @param filePath - Optional file path. Defaults to `{storage.dir}/{task_id}.trace.jsonl`.
183
+ * @throws If no filePath is provided and no storage options are configured.
184
+ */
185
+ saveToFile(filePath?: string): void;
186
+ /**
187
+ * Load a trace from a JSONL file.
188
+ *
189
+ * Reconstructs the ExecutionTrace with all events, preserving
190
+ * the hash chain. Requires an AgentIdentity for signature verification.
191
+ *
192
+ * @param filePath - Path to the JSONL trace file.
193
+ * @param agentIdentity - The agent identity to associate with the loaded trace.
194
+ * @returns A reconstructed ExecutionTrace.
195
+ */
196
+ static loadFromFile(filePath: string, agentIdentity: AgentIdentity): ExecutionTrace;
197
+ /**
198
+ * Get the default storage file path.
199
+ *
200
+ * @returns The file path, or undefined if no storage is configured.
201
+ */
202
+ private getStoragePath;
203
+ /**
204
+ * Append a single event to the storage file.
205
+ *
206
+ * @param event - The event to append.
207
+ */
208
+ private appendEventToFile;
209
+ /**
210
+ * Compute a simple Merkle root from a list of hex hashes.
211
+ * Used internally for checkpoint data.
212
+ *
213
+ * @param leaves - Array of hex-encoded hashes.
214
+ * @returns Hex-encoded Merkle root.
215
+ */
216
+ private simpleMerkleRoot;
217
+ }