@lawreneliang/atel-sdk 0.5.4 → 0.5.6
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/bin/atel.mjs +344 -20
- package/dist/anchor/base.js +1 -1
- package/dist/anchor/bsc.js +1 -1
- package/dist/anchor/evm.js +1 -1
- package/dist/anchor/index.js +1 -1
- package/dist/anchor/mock.js +1 -1
- package/dist/anchor/solana.js +1 -1
- package/dist/auditor/index.js +1 -1
- package/dist/collaboration/index.js +1 -1
- package/dist/crypto/index.js +1 -1
- package/dist/endpoint/index.js +1 -1
- package/dist/envelope/index.js +1 -1
- package/dist/gateway/index.js +1 -1
- package/dist/graph/index.js +1 -1
- package/dist/handshake/index.js +1 -1
- package/dist/identity/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/negotiation/index.js +1 -1
- package/dist/network/index.js +1 -1
- package/dist/orchestrator/index.js +1 -1
- package/dist/policy/index.js +1 -1
- package/dist/proof/index.js +1 -1
- package/dist/registry/index.js +1 -1
- package/dist/rollback/index.js +1 -1
- package/dist/score/index.js +1 -1
- package/dist/service/index.js +1 -1
- package/dist/service/server.js +1 -1
- package/dist/trace/index.js +1 -1
- package/dist/trust/index.js +1 -1
- package/dist/trust-sync/index.js +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +175 -8
package/bin/atel.mjs
CHANGED
|
@@ -18,12 +18,13 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync } from 'node:fs';
|
|
21
|
-
import { resolve } from 'node:path';
|
|
21
|
+
import { resolve, join } from 'node:path';
|
|
22
22
|
import {
|
|
23
23
|
AgentIdentity, AgentEndpoint, AgentClient, HandshakeManager,
|
|
24
24
|
createMessage, RegistryClient, ExecutionTrace, ProofGenerator,
|
|
25
25
|
SolanaAnchorProvider, autoNetworkSetup, collectCandidates, connectToAgent,
|
|
26
26
|
discoverPublicIP, checkReachable, ContentAuditor, TrustScoreClient,
|
|
27
|
+
RollbackManager,
|
|
27
28
|
} from '@lawreneliang/atel-sdk';
|
|
28
29
|
import { TunnelManager, HeartbeatManager } from './tunnel-manager.mjs';
|
|
29
30
|
|
|
@@ -35,8 +36,9 @@ const INBOX_FILE = resolve(ATEL_DIR, 'inbox.jsonl');
|
|
|
35
36
|
const POLICY_FILE = resolve(ATEL_DIR, 'policy.json');
|
|
36
37
|
const TASKS_FILE = resolve(ATEL_DIR, 'tasks.json');
|
|
37
38
|
const NETWORK_FILE = resolve(ATEL_DIR, 'network.json');
|
|
39
|
+
const TRACES_DIR = resolve(ATEL_DIR, 'traces');
|
|
38
40
|
|
|
39
|
-
const DEFAULT_POLICY = { rateLimit: 60, maxPayloadBytes: 1048576, maxConcurrent: 10, allowedDIDs: [], blockedDIDs: [] };
|
|
41
|
+
const DEFAULT_POLICY = { rateLimit: 60, maxPayloadBytes: 1048576, maxConcurrent: 10, allowedDIDs: [], blockedDIDs: [], trustPolicy: { minScore: 0, newAgentPolicy: 'allow_low_risk', riskThresholds: { low: 0, medium: 50, high: 75, critical: 90 } } };
|
|
40
42
|
|
|
41
43
|
// ─── Helpers ─────────────────────────────────────────────────────
|
|
42
44
|
|
|
@@ -55,6 +57,8 @@ function loadTasks() { if (!existsSync(TASKS_FILE)) return {}; try { return JSON
|
|
|
55
57
|
function saveTasks(t) { ensureDir(); writeFileSync(TASKS_FILE, JSON.stringify(t, null, 2)); }
|
|
56
58
|
function loadNetwork() { if (!existsSync(NETWORK_FILE)) return null; try { return JSON.parse(readFileSync(NETWORK_FILE, 'utf-8')); } catch { return null; } }
|
|
57
59
|
function saveNetwork(n) { ensureDir(); writeFileSync(NETWORK_FILE, JSON.stringify(n, null, 2)); }
|
|
60
|
+
function saveTrace(taskId, trace) { if (!existsSync(TRACES_DIR)) mkdirSync(TRACES_DIR, { recursive: true }); writeFileSync(resolve(TRACES_DIR, `${taskId}.jsonl`), trace.export()); }
|
|
61
|
+
function loadTrace(taskId) { const f = resolve(TRACES_DIR, `${taskId}.jsonl`); if (!existsSync(f)) return null; return readFileSync(f, 'utf-8'); }
|
|
58
62
|
|
|
59
63
|
// ─── Policy Enforcer ─────────────────────────────────────────────
|
|
60
64
|
|
|
@@ -156,6 +160,33 @@ async function cmdStart(port) {
|
|
|
156
160
|
// ── Trust Score Client ──
|
|
157
161
|
const trustScoreClient = new TrustScoreClient();
|
|
158
162
|
|
|
163
|
+
// ── Nonce Store (anti-replay) ──
|
|
164
|
+
const nonceFile = join(ATEL_DIR, 'nonces.json');
|
|
165
|
+
const usedNonces = new Set((() => { try { return JSON.parse(readFileSync(nonceFile, 'utf8')); } catch { return []; } })());
|
|
166
|
+
const saveNonces = () => { try { writeFileSync(nonceFile, JSON.stringify([...usedNonces].slice(-10000))); } catch {} };
|
|
167
|
+
|
|
168
|
+
// ── Helper: generate rejection Proof (local only, no on-chain) ──
|
|
169
|
+
function generateRejectionProof(from, action, reason, stage) {
|
|
170
|
+
const rejectId = `reject-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
171
|
+
const trace = new ExecutionTrace(rejectId, id);
|
|
172
|
+
trace.append('TASK_RECEIVED', { from, action });
|
|
173
|
+
trace.append(stage, { result: 'rejected', reason });
|
|
174
|
+
trace.fail(new Error(reason));
|
|
175
|
+
const proofGen = new ProofGenerator(trace, id);
|
|
176
|
+
const proof = proofGen.generate(capTypes.join(',') || 'no-policy', `rejected-from-${from}`, reason);
|
|
177
|
+
log({ event: 'rejection_proof', rejectId, from, action, stage, reason, proof_id: proof.proof_id, trace_root: proof.trace_root, timestamp: new Date().toISOString() });
|
|
178
|
+
return { proof_id: proof.proof_id, trace_root: proof.trace_root };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── Trace endpoint (for audit requests from other agents) ──
|
|
182
|
+
endpoint.app?.get?.('/atel/v1/trace/:taskId', (req, res) => {
|
|
183
|
+
const taskId = req.params.taskId;
|
|
184
|
+
const traceData = loadTrace(taskId);
|
|
185
|
+
if (!traceData) { res.status(404).json({ error: 'Trace not found' }); return; }
|
|
186
|
+
const events = traceData.split('\n').filter(l => l.trim()).map(l => JSON.parse(l));
|
|
187
|
+
res.json({ taskId, events, agent: id.did });
|
|
188
|
+
});
|
|
189
|
+
|
|
159
190
|
// Result callback: POST /atel/v1/result (executor calls this when done)
|
|
160
191
|
endpoint.app?.post?.('/atel/v1/result', async (req, res) => {
|
|
161
192
|
const { taskId, result, success } = req.body || {};
|
|
@@ -173,8 +204,36 @@ async function cmdStart(port) {
|
|
|
173
204
|
trace.append('CONTENT_AUDIT', { result: 'passed' });
|
|
174
205
|
trace.append('TASK_FORWARDED', { executor_url: EXECUTOR_URL, timestamp: task.acceptedAt });
|
|
175
206
|
trace.append('EXECUTOR_RESULT', { success: success !== false, duration_ms: durationMs, result_size: JSON.stringify(result).length });
|
|
176
|
-
|
|
177
|
-
|
|
207
|
+
|
|
208
|
+
// ── Rollback on failure ──
|
|
209
|
+
let rollbackReport = null;
|
|
210
|
+
if (success === false) {
|
|
211
|
+
trace.append('TASK_FAILED', { error: result?.error || 'Execution failed' });
|
|
212
|
+
const rollback = new RollbackManager();
|
|
213
|
+
// Register compensation: notify sender of failure
|
|
214
|
+
rollback.registerCompensation('Notify sender of task failure', async () => {
|
|
215
|
+
log({ event: 'rollback_notify', taskId, to: task.from, message: 'Task failed, compensating' });
|
|
216
|
+
});
|
|
217
|
+
// If executor reported side effects that need rollback
|
|
218
|
+
if (result?.sideEffects && Array.isArray(result.sideEffects)) {
|
|
219
|
+
for (const effect of result.sideEffects) {
|
|
220
|
+
rollback.registerCompensation(effect.description || 'Undo side effect', async () => {
|
|
221
|
+
if (effect.compensateUrl) {
|
|
222
|
+
await fetch(effect.compensateUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(effect.compensatePayload || {}), signal: AbortSignal.timeout(10000) });
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
rollbackReport = await rollback.rollbackAll();
|
|
228
|
+
trace.append('ROLLBACK', { total: rollbackReport.total, succeeded: rollbackReport.succeeded, failed: rollbackReport.failed });
|
|
229
|
+
trace.fail(new Error(result?.error || 'Execution failed'));
|
|
230
|
+
log({ event: 'rollback_executed', taskId, total: rollbackReport.total, succeeded: rollbackReport.succeeded, failed: rollbackReport.failed });
|
|
231
|
+
} else {
|
|
232
|
+
trace.finalize(typeof result === 'object' ? result : { result });
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ── Save Trace (for audit requests) ──
|
|
236
|
+
saveTrace(taskId, trace);
|
|
178
237
|
|
|
179
238
|
// ── Proof Generation ──
|
|
180
239
|
const proofGen = new ProofGenerator(trace, id);
|
|
@@ -253,6 +312,7 @@ async function cmdStart(port) {
|
|
|
253
312
|
proof: { proof_id: proof.proof_id, trace_root: proof.trace_root, events_count: trace.events.length },
|
|
254
313
|
anchor: anchor ? { chain: 'solana', txHash: anchor.txHash, block: anchor.blockNumber } : null,
|
|
255
314
|
execution: { duration_ms: durationMs, encrypted: task.encrypted },
|
|
315
|
+
rollback: rollbackReport ? { total: rollbackReport.total, succeeded: rollbackReport.succeeded, failed: rollbackReport.failed } : null,
|
|
256
316
|
};
|
|
257
317
|
|
|
258
318
|
if (isRelay) {
|
|
@@ -306,22 +366,41 @@ async function cmdStart(port) {
|
|
|
306
366
|
|
|
307
367
|
const action = payload.action || payload.type || 'unknown';
|
|
308
368
|
|
|
309
|
-
//
|
|
369
|
+
// ── Nonce anti-replay check ──
|
|
370
|
+
const nonce = payload.nonce || message.nonce;
|
|
371
|
+
if (nonce) {
|
|
372
|
+
if (usedNonces.has(nonce)) {
|
|
373
|
+
const rp = generateRejectionProof(message.from, action, 'Replay detected: nonce already used', 'REPLAY_REJECTED');
|
|
374
|
+
log({ event: 'task_rejected', from: message.from, action, reason: 'Replay: duplicate nonce', nonce, timestamp: new Date().toISOString() });
|
|
375
|
+
return { status: 'rejected', error: 'Replay detected: nonce already used', proof: rp };
|
|
376
|
+
}
|
|
377
|
+
usedNonces.add(nonce);
|
|
378
|
+
saveNonces();
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ── Protocol-level content audit (SDK layer) ──
|
|
310
382
|
const auditor = new ContentAuditor();
|
|
311
383
|
const auditResult = auditor.audit(payload, { action, from: message.from });
|
|
312
384
|
if (!auditResult.safe) {
|
|
385
|
+
const rp = generateRejectionProof(message.from, action, `Content audit: ${auditResult.reason}`, 'CONTENT_AUDIT_FAILED');
|
|
313
386
|
log({ event: 'task_rejected', from: message.from, action, reason: `Content audit: ${auditResult.reason}`, severity: auditResult.severity, pattern: auditResult.pattern, timestamp: new Date().toISOString() });
|
|
314
|
-
return { status: 'rejected', error: `Security: ${auditResult.reason}`, severity: auditResult.severity };
|
|
387
|
+
return { status: 'rejected', error: `Security: ${auditResult.reason}`, severity: auditResult.severity, proof: rp };
|
|
315
388
|
}
|
|
316
389
|
|
|
317
|
-
// Policy check
|
|
390
|
+
// ── Policy check ──
|
|
318
391
|
const pc = enforcer.check(message);
|
|
319
|
-
if (!pc.allowed) {
|
|
392
|
+
if (!pc.allowed) {
|
|
393
|
+
const rp = generateRejectionProof(message.from, action, pc.reason, 'POLICY_VIOLATION');
|
|
394
|
+
log({ event: 'task_rejected', from: message.from, action, reason: pc.reason, timestamp: new Date().toISOString() });
|
|
395
|
+
return { status: 'rejected', error: pc.reason, proof: rp };
|
|
396
|
+
}
|
|
320
397
|
|
|
321
|
-
// Capability check
|
|
322
|
-
if (capTypes.length > 0 && !capTypes.includes(action)
|
|
323
|
-
|
|
324
|
-
|
|
398
|
+
// ── Capability check (strict matching, no wildcards) ──
|
|
399
|
+
if (capTypes.length > 0 && !capTypes.includes(action)) {
|
|
400
|
+
const reason = `Outside capability: [${capTypes.join(',')}]`;
|
|
401
|
+
const rp = generateRejectionProof(message.from, action, reason, 'CAPABILITY_REJECTED');
|
|
402
|
+
log({ event: 'task_rejected', from: message.from, action, reason, timestamp: new Date().toISOString() });
|
|
403
|
+
return { status: 'rejected', error: `Action "${action}" outside capability boundary`, capabilities: capTypes, proof: rp };
|
|
325
404
|
}
|
|
326
405
|
|
|
327
406
|
const taskId = `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -354,6 +433,7 @@ async function cmdStart(port) {
|
|
|
354
433
|
trace.append('TASK_ACCEPTED', { from: message.from, action, payload });
|
|
355
434
|
const result = { status: 'no_executor', agent: id.agent_id, action, received_payload: payload };
|
|
356
435
|
trace.append('TASK_ECHO', { result }); trace.finalize(result);
|
|
436
|
+
saveTrace(taskId, trace);
|
|
357
437
|
const proofGen = new ProofGenerator(trace, id);
|
|
358
438
|
const proof = proofGen.generate(capTypes.join(',') || 'no-policy', `task-from-${message.from}`, JSON.stringify(result));
|
|
359
439
|
const anchor = await anchorOnChain(proof.trace_root, { proof_id: proof.proof_id, task_from: message.from, action, taskId });
|
|
@@ -517,6 +597,15 @@ async function cmdHandshake(remoteEndpoint, remoteDid) {
|
|
|
517
597
|
|
|
518
598
|
async function cmdTask(target, taskJson) {
|
|
519
599
|
const id = requireIdentity();
|
|
600
|
+
const policy = loadPolicy();
|
|
601
|
+
const tp = policy.trustPolicy || DEFAULT_POLICY.trustPolicy;
|
|
602
|
+
|
|
603
|
+
// Parse task payload and extract risk level
|
|
604
|
+
const payload = typeof taskJson === 'string' ? JSON.parse(taskJson) : taskJson;
|
|
605
|
+
const risk = payload._risk || 'low';
|
|
606
|
+
delete payload._risk;
|
|
607
|
+
const force = payload._force || false;
|
|
608
|
+
delete payload._force;
|
|
520
609
|
|
|
521
610
|
let remoteEndpoint = target;
|
|
522
611
|
let remoteDid;
|
|
@@ -526,12 +615,10 @@ async function cmdTask(target, taskJson) {
|
|
|
526
615
|
if (!target.startsWith('http')) {
|
|
527
616
|
const regClient = new RegistryClient({ registryUrl: REGISTRY_URL });
|
|
528
617
|
let entry;
|
|
529
|
-
// Try as DID first
|
|
530
618
|
try {
|
|
531
619
|
const resp = await fetch(`${REGISTRY_URL}/registry/v1/agent/${encodeURIComponent(target)}`);
|
|
532
620
|
if (resp.ok) entry = await resp.json();
|
|
533
621
|
} catch {}
|
|
534
|
-
// Try as capability search
|
|
535
622
|
if (!entry) {
|
|
536
623
|
const results = await regClient.search({ type: target, limit: 5 });
|
|
537
624
|
if (results.length > 0) entry = results[0];
|
|
@@ -540,6 +627,34 @@ async function cmdTask(target, taskJson) {
|
|
|
540
627
|
|
|
541
628
|
remoteDid = entry.did;
|
|
542
629
|
|
|
630
|
+
// ── Pre-task trust check ──
|
|
631
|
+
if (!force) {
|
|
632
|
+
const localHistoryFile = resolve(ATEL_DIR, 'trust-history.json');
|
|
633
|
+
let history = {};
|
|
634
|
+
try { history = JSON.parse(readFileSync(localHistoryFile, 'utf-8')); } catch {}
|
|
635
|
+
const agentHistory = history[remoteDid] || { tasks: 0, successes: 0, failures: 0, proofs: [] };
|
|
636
|
+
const threshold = tp.riskThresholds?.[risk] ?? 0;
|
|
637
|
+
const isNewAgent = agentHistory.tasks === 0;
|
|
638
|
+
|
|
639
|
+
if (isNewAgent && tp.newAgentPolicy === 'deny') {
|
|
640
|
+
console.log(JSON.stringify({ status: 'blocked', reason: 'Trust policy denies unknown agents', did: remoteDid, risk }));
|
|
641
|
+
process.exit(1);
|
|
642
|
+
}
|
|
643
|
+
if (isNewAgent && tp.newAgentPolicy === 'allow_low_risk' && (risk === 'high' || risk === 'critical')) {
|
|
644
|
+
console.log(JSON.stringify({ status: 'blocked', reason: `New agent, policy only allows low risk for unknowns (requested: ${risk})`, did: remoteDid }));
|
|
645
|
+
process.exit(1);
|
|
646
|
+
}
|
|
647
|
+
if (!isNewAgent && threshold > 0) {
|
|
648
|
+
const successRate = agentHistory.successes / agentHistory.tasks;
|
|
649
|
+
const score = Math.round(successRate * 60 + Math.min(agentHistory.tasks / 20, 1) * 15);
|
|
650
|
+
if (score < threshold) {
|
|
651
|
+
console.log(JSON.stringify({ status: 'blocked', reason: `Score ${score} below threshold ${threshold} for ${risk} risk`, did: remoteDid, score, threshold, risk }));
|
|
652
|
+
process.exit(1);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
console.log(JSON.stringify({ event: 'trust_check_passed', did: remoteDid, risk, threshold }));
|
|
656
|
+
}
|
|
657
|
+
|
|
543
658
|
// Try candidates if available
|
|
544
659
|
if (entry.candidates && entry.candidates.length > 0) {
|
|
545
660
|
console.log(JSON.stringify({ event: 'connecting', did: remoteDid, candidates: entry.candidates.length }));
|
|
@@ -554,6 +669,34 @@ async function cmdTask(target, taskJson) {
|
|
|
554
669
|
} else {
|
|
555
670
|
remoteEndpoint = entry.endpoint;
|
|
556
671
|
}
|
|
672
|
+
|
|
673
|
+
// Try candidates if available
|
|
674
|
+
if (entry.candidates && entry.candidates.length > 0) {
|
|
675
|
+
console.log(JSON.stringify({ event: 'connecting', did: remoteDid, candidates: entry.candidates.length }));
|
|
676
|
+
const conn = await connectToAgent(entry.candidates, remoteDid);
|
|
677
|
+
if (conn) {
|
|
678
|
+
remoteEndpoint = conn.url;
|
|
679
|
+
connectionType = conn.candidateType;
|
|
680
|
+
console.log(JSON.stringify({ event: 'connected', type: conn.candidateType, url: conn.url, latencyMs: conn.latencyMs }));
|
|
681
|
+
} else {
|
|
682
|
+
console.error('All candidates unreachable'); process.exit(1);
|
|
683
|
+
}
|
|
684
|
+
} else {
|
|
685
|
+
remoteEndpoint = entry.endpoint;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// ── Helper: update local trust history after task ──
|
|
690
|
+
function updateTrustHistory(did, success, proofInfo) {
|
|
691
|
+
const localHistoryFile = resolve(ATEL_DIR, 'trust-history.json');
|
|
692
|
+
let history = {};
|
|
693
|
+
try { history = JSON.parse(readFileSync(localHistoryFile, 'utf-8')); } catch {}
|
|
694
|
+
if (!history[did]) history[did] = { tasks: 0, successes: 0, failures: 0, lastSeen: null, proofs: [] };
|
|
695
|
+
history[did].tasks++;
|
|
696
|
+
if (success) history[did].successes++; else history[did].failures++;
|
|
697
|
+
history[did].lastSeen = new Date().toISOString();
|
|
698
|
+
if (proofInfo) history[did].proofs.push(proofInfo);
|
|
699
|
+
writeFileSync(localHistoryFile, JSON.stringify(history, null, 2));
|
|
557
700
|
}
|
|
558
701
|
|
|
559
702
|
if (connectionType === 'relay') {
|
|
@@ -583,11 +726,15 @@ async function cmdTask(target, taskJson) {
|
|
|
583
726
|
await relaySend('/atel/v1/handshake', confirm);
|
|
584
727
|
|
|
585
728
|
// Step 3: send task
|
|
586
|
-
const payload = typeof taskJson === 'string' ? JSON.parse(taskJson) : taskJson;
|
|
587
729
|
const msg = createMessage({ type: 'task', from: id.did, to: remoteDid, payload, secretKey: id.secretKey });
|
|
588
730
|
const result = await relaySend('/atel/v1/task', msg);
|
|
589
731
|
|
|
590
732
|
console.log(JSON.stringify({ status: 'task_sent', remoteDid, via: 'relay', result }, null, 2));
|
|
733
|
+
|
|
734
|
+
// Update local trust history
|
|
735
|
+
const success = result?.status !== 'rejected' && result?.status !== 'failed';
|
|
736
|
+
const proofInfo = result?.proof ? { proof_id: result.proof.proof_id, trace_root: result.proof.trace_root, verified: !!result?.anchor?.txHash, anchor_tx: result?.anchor?.txHash || null, timestamp: new Date().toISOString() } : null;
|
|
737
|
+
if (remoteDid) updateTrustHistory(remoteDid, success, proofInfo);
|
|
591
738
|
} else {
|
|
592
739
|
// Direct mode: standard handshake + task
|
|
593
740
|
const client = new AgentClient(id);
|
|
@@ -601,10 +748,14 @@ async function cmdTask(target, taskJson) {
|
|
|
601
748
|
sessions[remoteEndpoint] = { did: remoteDid };
|
|
602
749
|
writeFileSync(sf, JSON.stringify(sessions, null, 2));
|
|
603
750
|
|
|
604
|
-
const payload = typeof taskJson === 'string' ? JSON.parse(taskJson) : taskJson;
|
|
605
751
|
const msg = createMessage({ type: 'task', from: id.did, to: remoteDid, payload, secretKey: id.secretKey });
|
|
606
752
|
const result = await client.sendTask(remoteEndpoint, msg, hsManager);
|
|
607
753
|
console.log(JSON.stringify({ status: 'task_sent', remoteDid, via: remoteEndpoint, result }, null, 2));
|
|
754
|
+
|
|
755
|
+
// Update local trust history
|
|
756
|
+
const success = result?.status !== 'rejected' && result?.status !== 'failed';
|
|
757
|
+
const proofInfo = result?.proof ? { proof_id: result.proof.proof_id, trace_root: result.proof.trace_root, verified: !!result?.anchor?.txHash, anchor_tx: result?.anchor?.txHash || null, timestamp: new Date().toISOString() } : null;
|
|
758
|
+
if (remoteDid) updateTrustHistory(remoteDid, success, proofInfo);
|
|
608
759
|
}
|
|
609
760
|
}
|
|
610
761
|
|
|
@@ -614,6 +765,174 @@ async function cmdResult(taskId, resultJson) {
|
|
|
614
765
|
console.log(JSON.stringify(await resp.json(), null, 2));
|
|
615
766
|
}
|
|
616
767
|
|
|
768
|
+
// ─── Trust Verification Commands ─────────────────────────────────
|
|
769
|
+
|
|
770
|
+
async function cmdCheck(targetDid, riskLevel) {
|
|
771
|
+
const risk = riskLevel || 'low';
|
|
772
|
+
const policy = loadPolicy();
|
|
773
|
+
const tp = policy.trustPolicy || DEFAULT_POLICY.trustPolicy;
|
|
774
|
+
|
|
775
|
+
console.log(JSON.stringify({ event: 'checking_trust', did: targetDid, risk }));
|
|
776
|
+
|
|
777
|
+
// 1. Get Registry info (reference only)
|
|
778
|
+
let registryScore = null;
|
|
779
|
+
let agentName = null;
|
|
780
|
+
try {
|
|
781
|
+
const r = await fetch(`${REGISTRY_URL}/registry/v1/agent/${encodeURIComponent(targetDid)}`, { signal: AbortSignal.timeout(5000) });
|
|
782
|
+
if (r.ok) { const d = await r.json(); registryScore = d.trustScore; agentName = d.name; }
|
|
783
|
+
} catch {}
|
|
784
|
+
|
|
785
|
+
// 2. Query on-chain proofs for this DID (via Solana)
|
|
786
|
+
// For now, use Registry score as baseline + local interaction history
|
|
787
|
+
const localHistoryFile = resolve(ATEL_DIR, 'trust-history.json');
|
|
788
|
+
let history = {};
|
|
789
|
+
try { history = JSON.parse(readFileSync(localHistoryFile, 'utf-8')); } catch {}
|
|
790
|
+
const agentHistory = history[targetDid] || { tasks: 0, successes: 0, failures: 0, lastSeen: null, proofs: [] };
|
|
791
|
+
|
|
792
|
+
// 3. Compute local trust score
|
|
793
|
+
let computedScore = 0;
|
|
794
|
+
if (agentHistory.tasks > 0) {
|
|
795
|
+
const successRate = agentHistory.successes / agentHistory.tasks;
|
|
796
|
+
const volumeScore = Math.min(agentHistory.tasks / 20, 1) * 15;
|
|
797
|
+
const successScore = successRate * 60;
|
|
798
|
+
const verifiedProofs = agentHistory.proofs.filter(p => p.verified).length;
|
|
799
|
+
const verifiedRatio = agentHistory.proofs.length > 0 ? verifiedProofs / agentHistory.proofs.length : 0;
|
|
800
|
+
const proofScore = verifiedRatio * 25;
|
|
801
|
+
computedScore = Math.round((volumeScore + successScore + proofScore) * 100) / 100;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// 4. Apply trust policy
|
|
805
|
+
const threshold = tp.riskThresholds?.[risk] ?? 0;
|
|
806
|
+
const effectiveScore = computedScore > 0 ? computedScore : (registryScore || 0);
|
|
807
|
+
const isNewAgent = agentHistory.tasks === 0;
|
|
808
|
+
let decision = 'allow';
|
|
809
|
+
let reason = '';
|
|
810
|
+
|
|
811
|
+
if (isNewAgent) {
|
|
812
|
+
if (tp.newAgentPolicy === 'deny') { decision = 'deny'; reason = 'New agent, policy denies unknown agents'; }
|
|
813
|
+
else if (tp.newAgentPolicy === 'allow_low_risk' && (risk === 'high' || risk === 'critical')) { decision = 'deny'; reason = `New agent, policy only allows low risk (requested: ${risk})`; }
|
|
814
|
+
else { decision = 'allow'; reason = `New agent, policy: ${tp.newAgentPolicy}`; }
|
|
815
|
+
} else if (effectiveScore < threshold) {
|
|
816
|
+
decision = 'deny';
|
|
817
|
+
reason = `Score ${effectiveScore} below threshold ${threshold} for ${risk} risk`;
|
|
818
|
+
} else {
|
|
819
|
+
decision = 'allow';
|
|
820
|
+
reason = `Score ${effectiveScore} meets threshold ${threshold} for ${risk} risk`;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
console.log(JSON.stringify({
|
|
824
|
+
did: targetDid,
|
|
825
|
+
name: agentName,
|
|
826
|
+
trust: {
|
|
827
|
+
computed_score: computedScore,
|
|
828
|
+
registry_score: registryScore,
|
|
829
|
+
effective_score: effectiveScore,
|
|
830
|
+
total_tasks: agentHistory.tasks,
|
|
831
|
+
successes: agentHistory.successes,
|
|
832
|
+
failures: agentHistory.failures,
|
|
833
|
+
verified_proofs: agentHistory.proofs.filter(p => p.verified).length,
|
|
834
|
+
total_proofs: agentHistory.proofs.length,
|
|
835
|
+
},
|
|
836
|
+
policy: { risk, threshold, decision, reason },
|
|
837
|
+
}, null, 2));
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
async function cmdVerifyProof(anchorTx, traceRoot) {
|
|
841
|
+
if (!anchorTx || !traceRoot) { console.error('Usage: atel verify-proof <anchor_tx> <trace_root>'); process.exit(1); }
|
|
842
|
+
|
|
843
|
+
console.log(JSON.stringify({ event: 'verifying_proof', anchor_tx: anchorTx, trace_root: traceRoot }));
|
|
844
|
+
|
|
845
|
+
const rpcUrl = process.env.ATEL_SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com';
|
|
846
|
+
try {
|
|
847
|
+
const provider = new SolanaAnchorProvider({ rpcUrl });
|
|
848
|
+
const result = await provider.verify(traceRoot, anchorTx);
|
|
849
|
+
console.log(JSON.stringify({
|
|
850
|
+
verified: result.valid,
|
|
851
|
+
chain: 'solana',
|
|
852
|
+
anchor_tx: anchorTx,
|
|
853
|
+
trace_root: traceRoot,
|
|
854
|
+
detail: result.detail || (result.valid ? 'Memo matches trace_root' : 'Memo does not match'),
|
|
855
|
+
block: result.blockNumber,
|
|
856
|
+
timestamp: result.timestamp,
|
|
857
|
+
}, null, 2));
|
|
858
|
+
} catch (e) {
|
|
859
|
+
console.log(JSON.stringify({ verified: false, error: e.message }));
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
async function cmdAudit(targetDidOrUrl, taskId) {
|
|
864
|
+
if (!targetDidOrUrl || !taskId) { console.error('Usage: atel audit <did_or_endpoint> <taskId>'); process.exit(1); }
|
|
865
|
+
|
|
866
|
+
// Resolve endpoint
|
|
867
|
+
let endpoint = targetDidOrUrl;
|
|
868
|
+
if (targetDidOrUrl.startsWith('did:')) {
|
|
869
|
+
try {
|
|
870
|
+
const r = await fetch(`${REGISTRY_URL}/registry/v1/agent/${encodeURIComponent(targetDidOrUrl)}`, { signal: AbortSignal.timeout(5000) });
|
|
871
|
+
if (r.ok) {
|
|
872
|
+
const d = await r.json();
|
|
873
|
+
if (d.candidates && d.candidates.length > 0) {
|
|
874
|
+
const conn = await connectToAgent(d.candidates, targetDidOrUrl);
|
|
875
|
+
if (conn) endpoint = conn.url;
|
|
876
|
+
}
|
|
877
|
+
if (endpoint === targetDidOrUrl && d.endpoint) endpoint = d.endpoint;
|
|
878
|
+
}
|
|
879
|
+
} catch {}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
if (endpoint.startsWith('did:')) { console.error('Could not resolve endpoint for DID'); process.exit(1); }
|
|
883
|
+
|
|
884
|
+
console.log(JSON.stringify({ event: 'auditing', target: endpoint, taskId }));
|
|
885
|
+
|
|
886
|
+
try {
|
|
887
|
+
// Fetch trace from target
|
|
888
|
+
const traceUrl = endpoint.replace(/\/$/, '') + `/atel/v1/trace/${taskId}`;
|
|
889
|
+
const resp = await fetch(traceUrl, { signal: AbortSignal.timeout(10000) });
|
|
890
|
+
if (!resp.ok) { console.log(JSON.stringify({ audit: 'failed', error: `Trace fetch failed: ${resp.status}` })); return; }
|
|
891
|
+
const traceData = await resp.json();
|
|
892
|
+
|
|
893
|
+
// Verify hash chain
|
|
894
|
+
const events = traceData.events || [];
|
|
895
|
+
let chainValid = true;
|
|
896
|
+
const chainErrors = [];
|
|
897
|
+
for (let i = 0; i < events.length; i++) {
|
|
898
|
+
const e = events[i];
|
|
899
|
+
const expectedPrev = i === 0 ? '0x00' : events[i - 1].hash;
|
|
900
|
+
if (e.prev !== expectedPrev) {
|
|
901
|
+
chainValid = false;
|
|
902
|
+
chainErrors.push(`Event #${e.seq}: prev mismatch (expected ${expectedPrev}, got ${e.prev})`);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// Recompute merkle root
|
|
907
|
+
const { createHash } = await import('node:crypto');
|
|
908
|
+
const hashes = events.map(e => e.hash);
|
|
909
|
+
let level = [...hashes];
|
|
910
|
+
while (level.length > 1) {
|
|
911
|
+
const next = [];
|
|
912
|
+
for (let i = 0; i < level.length; i += 2) {
|
|
913
|
+
const left = level[i];
|
|
914
|
+
const right = i + 1 < level.length ? level[i + 1] : left;
|
|
915
|
+
next.push(createHash('sha256').update(left + right).digest('hex'));
|
|
916
|
+
}
|
|
917
|
+
level = next;
|
|
918
|
+
}
|
|
919
|
+
const computedRoot = level[0] || '';
|
|
920
|
+
|
|
921
|
+
console.log(JSON.stringify({
|
|
922
|
+
audit: 'complete',
|
|
923
|
+
taskId,
|
|
924
|
+
agent: traceData.agent,
|
|
925
|
+
events_count: events.length,
|
|
926
|
+
hash_chain_valid: chainValid,
|
|
927
|
+
chain_errors: chainErrors,
|
|
928
|
+
computed_merkle_root: computedRoot,
|
|
929
|
+
event_types: events.map(e => e.type),
|
|
930
|
+
}, null, 2));
|
|
931
|
+
} catch (e) {
|
|
932
|
+
console.log(JSON.stringify({ audit: 'failed', error: e.message }));
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
617
936
|
// ─── Main ────────────────────────────────────────────────────────
|
|
618
937
|
|
|
619
938
|
const [,, cmd, ...args] = process.argv;
|
|
@@ -629,6 +948,9 @@ const commands = {
|
|
|
629
948
|
handshake: () => cmdHandshake(args[0], args[1]),
|
|
630
949
|
task: () => cmdTask(args[0], args[1]),
|
|
631
950
|
result: () => cmdResult(args[0], args[1]),
|
|
951
|
+
check: () => cmdCheck(args[0], args[1]),
|
|
952
|
+
'verify-proof': () => cmdVerifyProof(args[0], args[1]),
|
|
953
|
+
audit: () => cmdAudit(args[0], args[1]),
|
|
632
954
|
};
|
|
633
955
|
|
|
634
956
|
if (!cmd || !commands[cmd]) {
|
|
@@ -646,8 +968,11 @@ Commands:
|
|
|
646
968
|
register [name] [caps] [endpoint] Register on public registry
|
|
647
969
|
search <capability> Search registry for agents
|
|
648
970
|
handshake <endpoint> [did] Handshake with remote agent
|
|
649
|
-
task <
|
|
971
|
+
task <target> <json> Delegate task (auto trust check)
|
|
650
972
|
result <taskId> <json> Submit execution result (from executor)
|
|
973
|
+
check <did> [risk] Check agent trust (risk: low|medium|high|critical)
|
|
974
|
+
verify-proof <anchor_tx> <root> Verify on-chain proof
|
|
975
|
+
audit <did_or_url> <taskId> Deep audit: fetch trace + verify hash chain
|
|
651
976
|
|
|
652
977
|
Environment:
|
|
653
978
|
ATEL_DIR Identity directory (default: .atel)
|
|
@@ -656,9 +981,8 @@ Environment:
|
|
|
656
981
|
ATEL_SOLANA_PRIVATE_KEY Solana key for on-chain anchoring
|
|
657
982
|
ATEL_SOLANA_RPC_URL Solana RPC (default: mainnet-beta)
|
|
658
983
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
on your router and run: atel verify`);
|
|
984
|
+
Trust Policy: Configure .atel/policy.json trustPolicy for automatic
|
|
985
|
+
pre-task trust evaluation. Use _risk in payload or --risk flag.`);
|
|
662
986
|
process.exit(cmd ? 1 : 0);
|
|
663
987
|
}
|
|
664
988
|
|
package/dist/anchor/base.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
var _0x3c6a47=_0x3947;(function(_0x35c779,_0x3c618d){var _0x3f94ed=_0x3947,_0x2951a3=_0x35c779();while(!![]){try{var _0x5ef8a4=-parseInt(_0x3f94ed(0x110))/0x1+parseInt(_0x3f94ed(0x118))/0x2+-parseInt(_0x3f94ed(0x10c))/0x3*(parseInt(_0x3f94ed(0x114))/0x4)+-parseInt(_0x3f94ed(0x117))/0x5+parseInt(_0x3f94ed(0x112))/0x6*(-parseInt(_0x3f94ed(0x116))/0x7)+parseInt(_0x3f94ed(0x10e))/0x8+parseInt(_0x3f94ed(0x10d))/0x9;if(_0x5ef8a4===_0x3c618d)break;else _0x2951a3['push'](_0x2951a3['shift']());}catch(_0x4ddc53){_0x2951a3['push'](_0x2951a3['shift']());}}}(_0x1402,0x8e2f5));function _0x1402(){var _0x426d28=['otG4mtyYt1ncANH4','Ahr0Chm6lY9TywLUBMv0lMjHC2uUB3jN','mJe0ofj2yuTZAq','ChjPDMf0zuTLEq','mtK2ntGWngjSCM90yW','revgqvvmvf9suenFvvjm','mJaXndzQze52EeO','ndu5mdqYnwLdv0rpva','mtm0nJyWnhvUA2rHtq','nMHuyvr5qG','mJC2odG5odzyvfrJtKS','nJaXnJa0oerAwfzmCW','CNbJvxjS'];_0x1402=function(){return _0x426d28;};return _0x1402();}import{EvmAnchorProvider}from'./evm.js';function _0x3947(_0x398c58,_0x2a6d63){_0x398c58=_0x398c58-0x10c;var _0x140261=_0x1402();var _0x394774=_0x140261[_0x398c58];if(_0x3947['mIEuJG']===undefined){var _0x382e34=function(_0x5a50b1){var _0x358dbe='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x1d5b15='',_0x17a856='';for(var _0xd8082e=0x0,_0x2316af,_0x44edac,_0x551f4d=0x0;_0x44edac=_0x5a50b1['charAt'](_0x551f4d++);~_0x44edac&&(_0x2316af=_0xd8082e%0x4?_0x2316af*0x40+_0x44edac:_0x44edac,_0xd8082e++%0x4)?_0x1d5b15+=String['fromCharCode'](0xff&_0x2316af>>(-0x2*_0xd8082e&0x6)):0x0){_0x44edac=_0x358dbe['indexOf'](_0x44edac);}for(var _0x4c1696=0x0,_0x603f5e=_0x1d5b15['length'];_0x4c1696<_0x603f5e;_0x4c1696++){_0x17a856+='%'+('00'+_0x1d5b15['charCodeAt'](_0x4c1696)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x17a856);};_0x3947['defWxA']=_0x382e34,_0x3947['uwwDMd']={},_0x3947['mIEuJG']=!![];}var _0x3dc4eb=_0x140261[0x0],_0xf92ead=_0x398c58+_0x3dc4eb,_0x3394a2=_0x3947['uwwDMd'][_0xf92ead];return!_0x3394a2?(_0x394774=_0x3947['defWxA'](_0x394774),_0x3947['uwwDMd'][_0xf92ead]=_0x394774):_0x394774=_0x3394a2,_0x394774;}export class BaseAnchorProvider extends EvmAnchorProvider{static ['DEFAULT_RPC_URL']=_0x3c6a47(0x111);constructor(_0x2de571){var _0x3ffcaf=_0x3c6a47,_0x3987ac={};_0x3987ac[_0x3ffcaf(0x10f)]=_0x2de571?.['rpcUrl']??BaseAnchorProvider[_0x3ffcaf(0x115)],_0x3987ac[_0x3ffcaf(0x113)]=_0x2de571?.[_0x3ffcaf(0x113)],super('Base','base',_0x3987ac);}}
|
package/dist/anchor/bsc.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
var _0x3d61eb=_0x50a1;function _0x50a1(_0x29b023,_0x3d4795){_0x29b023=_0x29b023-0x1c5;var _0x4e2a2f=_0x4e2a();var _0x50a18d=_0x4e2a2f[_0x29b023];if(_0x50a1['jgVQqg']===undefined){var _0x290037=function(_0x302311){var _0x597263='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x553d51='',_0x1dcf8e='';for(var _0x35eae6=0x0,_0x5cecd0,_0x1968fd,_0xb12f96=0x0;_0x1968fd=_0x302311['charAt'](_0xb12f96++);~_0x1968fd&&(_0x5cecd0=_0x35eae6%0x4?_0x5cecd0*0x40+_0x1968fd:_0x1968fd,_0x35eae6++%0x4)?_0x553d51+=String['fromCharCode'](0xff&_0x5cecd0>>(-0x2*_0x35eae6&0x6)):0x0){_0x1968fd=_0x597263['indexOf'](_0x1968fd);}for(var _0x3bd902=0x0,_0x45ca9f=_0x553d51['length'];_0x3bd902<_0x45ca9f;_0x3bd902++){_0x1dcf8e+='%'+('00'+_0x553d51['charCodeAt'](_0x3bd902)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1dcf8e);};_0x50a1['YrCsfv']=_0x290037,_0x50a1['qbalXg']={},_0x50a1['jgVQqg']=!![];}var _0x169bc0=_0x4e2a2f[0x0],_0x37920e=_0x29b023+_0x169bc0,_0x211344=_0x50a1['qbalXg'][_0x37920e];return!_0x211344?(_0x50a18d=_0x50a1['YrCsfv'](_0x50a18d),_0x50a1['qbalXg'][_0x37920e]=_0x50a18d):_0x50a18d=_0x211344,_0x50a18d;}(function(_0x41eaa3,_0x46e2cd){var _0x662fb1=_0x50a1,_0x5f082b=_0x41eaa3();while(!![]){try{var _0x72946a=-parseInt(_0x662fb1(0x1cb))/0x1+parseInt(_0x662fb1(0x1cc))/0x2*(parseInt(_0x662fb1(0x1c5))/0x3)+-parseInt(_0x662fb1(0x1d0))/0x4+parseInt(_0x662fb1(0x1ce))/0x5*(-parseInt(_0x662fb1(0x1c7))/0x6)+parseInt(_0x662fb1(0x1c8))/0x7*(-parseInt(_0x662fb1(0x1cf))/0x8)+parseInt(_0x662fb1(0x1d1))/0x9+parseInt(_0x662fb1(0x1c9))/0xa;if(_0x72946a===_0x46e2cd)break;else _0x5f082b['push'](_0x5f082b['shift']());}catch(_0x205b31){_0x5f082b['push'](_0x5f082b['shift']());}}}(_0x4e2a,0x432db));import{EvmAnchorProvider}from'./evm.js';export class BSCAnchorProvider extends EvmAnchorProvider{static ['DEFAULT_RPC_URL']=_0x3d61eb(0x1cd);constructor(_0x118851){var _0x150b00=_0x3d61eb,_0x3d78db={};_0x3d78db['rpcUrl']=_0x118851?.['rpcUrl']??BSCAnchorProvider['DEFAULT_RPC_URL'],_0x3d78db['privateKey']=_0x118851?.['privateKey'],super(_0x150b00(0x1ca),_0x150b00(0x1c6),_0x3d78db);}}function _0x4e2a(){var _0x4206bf=['mJe2nte0zxbQBuD5','mJu1nejUuNP1Aq','Ahr0Chm6lY9IC2mTzgf0yxnLzwqUyMLUyw5Jzs5VCMC','ntC5nwPitgToEG','mtCZotuXmKjmr0fjEG','mti5ntK2nffftenxBq','mtm5ntCWmNn6Ahngza','mJi4wwX2AhbY','yNnJ','mJq1nfbMu1fvAq','n1n5zejUDW','mti1ntaWodb2vu5nzxa','qLnd'];_0x4e2a=function(){return _0x4206bf;};return _0x4e2a();}
|
package/dist/anchor/evm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const _0x3c54ba=_0x3f5a;(function(_0x5bbb88,_0x56d92c){const _0x14a661=_0x3f5a,_0x50b215=_0x5bbb88();while(!![]){try{const _0x14d427=-parseInt(_0x14a661(0xee))/0x1+parseInt(_0x14a661(0xd3))/0x2*(-parseInt(_0x14a661(0xe3))/0x3)+parseInt(_0x14a661(0xd0))/0x4*(parseInt(_0x14a661(0xf1))/0x5)+-parseInt(_0x14a661(0xf8))/0x6+-parseInt(_0x14a661(0xd1))/0x7*(-parseInt(_0x14a661(0xce))/0x8)+parseInt(_0x14a661(0xd9))/0x9*(-parseInt(_0x14a661(0xdf))/0xa)+-parseInt(_0x14a661(0xed))/0xb;if(_0x14d427===_0x56d92c)break;else _0x50b215['push'](_0x50b215['shift']());}catch(_0x589787){_0x50b215['push'](_0x50b215['shift']());}}}(_0xea0e,0x221c2));function _0x3f5a(_0x24961b,_0x5d7b09){_0x24961b=_0x24961b-0xcd;const _0xea0e02=_0xea0e();let _0x3f5a7a=_0xea0e02[_0x24961b];if(_0x3f5a['MXMKXp']===undefined){var _0x40ec30=function(_0x1a4bad){const _0x188ade='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x10b1b3='',_0x1af264='';for(let _0x2d3dd1=0x0,_0x19097c,_0x5b2fd0,_0x3dc31f=0x0;_0x5b2fd0=_0x1a4bad['charAt'](_0x3dc31f++);~_0x5b2fd0&&(_0x19097c=_0x2d3dd1%0x4?_0x19097c*0x40+_0x5b2fd0:_0x5b2fd0,_0x2d3dd1++%0x4)?_0x10b1b3+=String['fromCharCode'](0xff&_0x19097c>>(-0x2*_0x2d3dd1&0x6)):0x0){_0x5b2fd0=_0x188ade['indexOf'](_0x5b2fd0);}for(let _0x5e4f62=0x0,_0x4bf20c=_0x10b1b3['length'];_0x5e4f62<_0x4bf20c;_0x5e4f62++){_0x1af264+='%'+('00'+_0x10b1b3['charCodeAt'](_0x5e4f62)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1af264);};_0x3f5a['pcznLR']=_0x40ec30,_0x3f5a['ACUomD']={},_0x3f5a['MXMKXp']=!![];}const _0x3a70ce=_0xea0e02[0x0],_0x31af21=_0x24961b+_0x3a70ce,_0x3d2fa7=_0x3f5a['ACUomD'][_0x31af21];return!_0x3d2fa7?(_0x3f5a7a=_0x3f5a['pcznLR'](_0x3f5a7a),_0x3f5a['ACUomD'][_0x31af21]=_0x3f5a7a):_0x3f5a7a=_0x3d2fa7,_0x3f5a7a;}import{ethers}from'ethers';function _0xea0e(){const _0x459b17=['D2fPDa','BgvUz3rO','ournzvz5BW','iIWGzM91BMqGiG','sgfZAcbTAxnTyxrJAdOGzxHWzwn0zwqGiG','sNnVBLjWy1bYB3zPzgvY','zw5JB2rLrgf0yq','AgfZAa','mJqZmdbpB0HSre4','BMfTzq','ChjPDMf0zuTLEq','z2v0qMXVy2ToDw1Izxi','odG0mJjNAujStMK','vMvYAwzPy2f0Aw9UigvYCM9YoIa','y2HHAw4','CNbJvxjS','zgf0yq','r0TMwMu','yMXVy2TuAw1LC3rHBxa','D2fSBgv0','ChjVDMLKzxi','senKu1G','mty0odiXoejhEu5mtG','mteYndmXvgnqsxb5','Bg9VA3vW','yMXVy2ToDw1Izxi','nvDmCe9NBq','qvrftf9btKnit1i6','DgLTzxn0yw1W','qMzXsgS','ywrKCMvZCW','DhHiyxnO','igfUy2HVCIbMywLSzwq6ia','ndyXmJe0zvzLBujh','BwvZC2fNzq','ogXUzM9trq','DMfSAwq','mta1mJi1mKHgAwjTvq','mtCZmZG1mvD0zvLkAG','z2v0qMXVy2S','mKf5rhDsBG','zgvJB2rLrgf0yq','zgv0ywLS','oIbdyw5UB3qGyw5JAg9YihDPDgHVDxqGysbWCML2yxrLigTLEq'];_0xea0e=function(){return _0x459b17;};return _0xea0e();}const ANCHOR_PREFIX=_0x3c54ba(0xf2);export class EvmAnchorProvider{[_0x3c54ba(0xe0)];['chain'];[_0x3c54ba(0xeb)];[_0x3c54ba(0xea)];constructor(_0x54b1c0,_0x81538,_0x42f4b8){const _0x181ca4=_0x3c54ba;this[_0x181ca4(0xe0)]=_0x54b1c0,this[_0x181ca4(0xe5)]=_0x81538,this['provider']=new ethers[(_0x181ca4(0xdc))](_0x42f4b8[_0x181ca4(0xe6)]),_0x42f4b8[_0x181ca4(0xe1)]&&(this[_0x181ca4(0xea)]=new ethers['Wallet'](_0x42f4b8['privateKey'],this[_0x181ca4(0xeb)]));}static[_0x3c54ba(0xdd)](_0x2416af){return ethers['hexlify'](ethers['toUtf8Bytes'](''+ANCHOR_PREFIX+_0x2416af));}static[_0x3c54ba(0xd4)](_0xe0a2bf){const _0x348f47=_0x3c54ba,_0xb6455a={};_0xb6455a['EPBAp']=_0x348f47(0xf4);const _0x4f4e4a=_0xb6455a;try{if('BfqHk'===_0x4f4e4a['EPBAp']){const _0x29c8c0=ethers['toUtf8String'](_0xe0a2bf);if(_0x29c8c0['startsWith'](ANCHOR_PREFIX))return _0x29c8c0['slice'](ANCHOR_PREFIX[_0x348f47(0xd8)]);return null;}else return[];}catch{return null;}}async['anchor'](_0x4667e8,_0x5acd2c){const _0x16ae51=_0x3c54ba;if(!this[_0x16ae51(0xea)])throw new Error(this[_0x16ae51(0xe0)]+_0x16ae51(0xd6));const _0x15be0d=EvmAnchorProvider[_0x16ae51(0xdd)](_0x4667e8);try{const _0x2ad970=await this['wallet']['sendTransaction']({'to':this[_0x16ae51(0xea)][_0x16ae51(0xf5)],'value':0x0n,'data':_0x15be0d}),_0x2d39f0=await _0x2ad970[_0x16ae51(0xd7)]();if(!_0x2d39f0)throw new Error('Transaction\x20receipt\x20is\x20null\x20—\x20tx\x20may\x20have\x20been\x20dropped');return{'hash':_0x4667e8,'txHash':_0x2d39f0[_0x16ae51(0xde)],'chain':this['chain'],'timestamp':Date['now'](),'blockNumber':_0x2d39f0['blockNumber'],'metadata':_0x5acd2c};}catch(_0x217977){const _0x37884d=_0x217977 instanceof Error?_0x217977['message']:String(_0x217977);throw new Error(this['name']+_0x16ae51(0xf7)+_0x37884d);}}async['verify'](_0x508a2f,_0x4fee65){const _0x16b05c=_0x3c54ba,_0x8cf615={'YmoSe':'Transaction\x20not\x20found','tFMel':function(_0x5bd2df,_0x2cb535){return _0x5bd2df===_0x2cb535;},'KYstZ':function(_0x564513,_0x196a36){return _0x564513*_0x196a36;},'ojjSq':function(_0x110c76,_0x32d36e){return _0x110c76 instanceof _0x32d36e;},'HCdSX':function(_0x1e4747,_0x2e17dd){return _0x1e4747(_0x2e17dd);}};try{const _0x462911=await this['provider']['getTransaction'](_0x4fee65);if(!_0x462911){const _0x2e610b={};return _0x2e610b[_0x16b05c(0xcf)]=![],_0x2e610b[_0x16b05c(0xde)]=_0x508a2f,_0x2e610b['txHash']=_0x4fee65,_0x2e610b[_0x16b05c(0xe5)]=this[_0x16b05c(0xe5)],_0x2e610b[_0x16b05c(0xd5)]=_0x8cf615['YmoSe'],_0x2e610b;}const _0x3e31dd=EvmAnchorProvider[_0x16b05c(0xd4)](_0x462911[_0x16b05c(0xe7)]);if(_0x8cf615['tFMel'](_0x3e31dd,null)){const _0x4c22d6={};return _0x4c22d6['valid']=![],_0x4c22d6[_0x16b05c(0xde)]=_0x508a2f,_0x4c22d6['txHash']=_0x4fee65,_0x4c22d6['chain']=this[_0x16b05c(0xe5)],_0x4c22d6['detail']='Transaction\x20data\x20does\x20not\x20contain\x20a\x20valid\x20anchor',_0x4c22d6;}const _0x12bf0a=_0x3e31dd===_0x508a2f;let _0x14b65d;if(_0x462911[_0x16b05c(0xf0)])try{const _0x22f2f6=await this['provider'][_0x16b05c(0xd2)](_0x462911[_0x16b05c(0xf0)]);_0x14b65d=_0x22f2f6?_0x8cf615['KYstZ'](_0x22f2f6[_0x16b05c(0xf3)],0x3e8):undefined;}catch{}const _0x4cb2e6={};return _0x4cb2e6[_0x16b05c(0xcf)]=_0x12bf0a,_0x4cb2e6[_0x16b05c(0xde)]=_0x508a2f,_0x4cb2e6[_0x16b05c(0xf6)]=_0x4fee65,_0x4cb2e6['chain']=this[_0x16b05c(0xe5)],_0x4cb2e6[_0x16b05c(0xe9)]=_0x14b65d,_0x4cb2e6[_0x16b05c(0xd5)]=_0x12bf0a?'Hash\x20matches\x20on-chain\x20data':_0x16b05c(0xdb)+_0x508a2f+_0x16b05c(0xda)+_0x3e31dd+'\x22',_0x4cb2e6;}catch(_0x12f3dd){if(_0x16b05c(0xe8)==='GKfZe'){const _0x1e19c4=_0x8cf615['ojjSq'](_0x12f3dd,Error)?_0x12f3dd[_0x16b05c(0xcd)]:_0x8cf615[_0x16b05c(0xec)](String,_0x12f3dd),_0x209837={};return _0x209837[_0x16b05c(0xcf)]=![],_0x209837['hash']=_0x508a2f,_0x209837[_0x16b05c(0xf6)]=_0x4fee65,_0x209837[_0x16b05c(0xe5)]=this[_0x16b05c(0xe5)],_0x209837[_0x16b05c(0xd5)]=_0x16b05c(0xe4)+_0x1e19c4,_0x209837;}else return _0x329bbc['slice'](_0x45ffcf['length']);}}async[_0x3c54ba(0xef)](_0x18c565){return[];}async['isAvailable'](){const _0x57c67a=_0x3c54ba;try{return await this['provider'][_0x57c67a(0xe2)](),!![];}catch{return![];}}}
|