ccip-router 0.1.0

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 (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +528 -0
  3. package/contracts/AttestationIndex.sol +125 -0
  4. package/contracts/NodeRegistry.sol +85 -0
  5. package/dist/attestation/eip712.d.ts +50 -0
  6. package/dist/attestation/eip712.d.ts.map +1 -0
  7. package/dist/attestation/eip712.js +31 -0
  8. package/dist/attestation/eip712.js.map +1 -0
  9. package/dist/attestation/ocp.d.ts +9 -0
  10. package/dist/attestation/ocp.d.ts.map +1 -0
  11. package/dist/attestation/ocp.js +11 -0
  12. package/dist/attestation/ocp.js.map +1 -0
  13. package/dist/attestation/withWyriwe.d.ts +11 -0
  14. package/dist/attestation/withWyriwe.d.ts.map +1 -0
  15. package/dist/attestation/withWyriwe.js +92 -0
  16. package/dist/attestation/withWyriwe.js.map +1 -0
  17. package/dist/chain/abi.d.ts +178 -0
  18. package/dist/chain/abi.d.ts.map +1 -0
  19. package/dist/chain/abi.js +94 -0
  20. package/dist/chain/abi.js.map +1 -0
  21. package/dist/chain/client.d.ts +16762 -0
  22. package/dist/chain/client.d.ts.map +1 -0
  23. package/dist/chain/client.js +21 -0
  24. package/dist/chain/client.js.map +1 -0
  25. package/dist/chain/publish.d.ts +26 -0
  26. package/dist/chain/publish.d.ts.map +1 -0
  27. package/dist/chain/publish.js +66 -0
  28. package/dist/chain/publish.js.map +1 -0
  29. package/dist/chain/register.d.ts +9 -0
  30. package/dist/chain/register.d.ts.map +1 -0
  31. package/dist/chain/register.js +20 -0
  32. package/dist/chain/register.js.map +1 -0
  33. package/dist/crypto/hash.d.ts +3 -0
  34. package/dist/crypto/hash.d.ts.map +1 -0
  35. package/dist/crypto/hash.js +12 -0
  36. package/dist/crypto/hash.js.map +1 -0
  37. package/dist/crypto/index.d.ts +3 -0
  38. package/dist/crypto/index.d.ts.map +1 -0
  39. package/dist/crypto/index.js +3 -0
  40. package/dist/crypto/index.js.map +1 -0
  41. package/dist/crypto/sign.d.ts +6 -0
  42. package/dist/crypto/sign.d.ts.map +1 -0
  43. package/dist/crypto/sign.js +60 -0
  44. package/dist/crypto/sign.js.map +1 -0
  45. package/dist/db/index.d.ts +5 -0
  46. package/dist/db/index.d.ts.map +1 -0
  47. package/dist/db/index.js +13 -0
  48. package/dist/db/index.js.map +1 -0
  49. package/dist/db/schema.d.ts +6 -0
  50. package/dist/db/schema.d.ts.map +1 -0
  51. package/dist/db/schema.js +41 -0
  52. package/dist/db/schema.js.map +1 -0
  53. package/dist/db/sqlite.d.ts +19 -0
  54. package/dist/db/sqlite.d.ts.map +1 -0
  55. package/dist/db/sqlite.js +196 -0
  56. package/dist/db/sqlite.js.map +1 -0
  57. package/dist/db/types.d.ts +34 -0
  58. package/dist/db/types.d.ts.map +1 -0
  59. package/dist/db/types.js +5 -0
  60. package/dist/db/types.js.map +1 -0
  61. package/dist/gateway/__tests__/eip3668.test.d.ts +2 -0
  62. package/dist/gateway/__tests__/eip3668.test.d.ts.map +1 -0
  63. package/dist/gateway/__tests__/eip3668.test.js +31 -0
  64. package/dist/gateway/__tests__/eip3668.test.js.map +1 -0
  65. package/dist/gateway/eip3668.d.ts +14 -0
  66. package/dist/gateway/eip3668.d.ts.map +1 -0
  67. package/dist/gateway/eip3668.js +28 -0
  68. package/dist/gateway/eip3668.js.map +1 -0
  69. package/dist/lib.d.ts +12 -0
  70. package/dist/lib.d.ts.map +1 -0
  71. package/dist/lib.js +8 -0
  72. package/dist/lib.js.map +1 -0
  73. package/dist/mesh/cron.d.ts +4 -0
  74. package/dist/mesh/cron.d.ts.map +1 -0
  75. package/dist/mesh/cron.js +22 -0
  76. package/dist/mesh/cron.js.map +1 -0
  77. package/dist/mesh/records.d.ts +4 -0
  78. package/dist/mesh/records.d.ts.map +1 -0
  79. package/dist/mesh/records.js +47 -0
  80. package/dist/mesh/records.js.map +1 -0
  81. package/dist/mesh/sync.d.ts +5 -0
  82. package/dist/mesh/sync.d.ts.map +1 -0
  83. package/dist/mesh/sync.js +154 -0
  84. package/dist/mesh/sync.js.map +1 -0
  85. package/dist/mesh/vni.d.ts +14 -0
  86. package/dist/mesh/vni.d.ts.map +1 -0
  87. package/dist/mesh/vni.js +52 -0
  88. package/dist/mesh/vni.js.map +1 -0
  89. package/dist/router/CcipRouter.d.ts +26 -0
  90. package/dist/router/CcipRouter.d.ts.map +1 -0
  91. package/dist/router/CcipRouter.js +85 -0
  92. package/dist/router/CcipRouter.js.map +1 -0
  93. package/dist/router/index.d.ts +3 -0
  94. package/dist/router/index.d.ts.map +1 -0
  95. package/dist/router/index.js +2 -0
  96. package/dist/router/index.js.map +1 -0
  97. package/package.json +63 -0
@@ -0,0 +1,196 @@
1
+ import Database from 'better-sqlite3';
2
+ import { SCHEMA, MIGRATIONS } from './schema.js';
3
+ export class SQLiteDB {
4
+ db;
5
+ stmts;
6
+ constructor(path) {
7
+ this.db = new Database(path);
8
+ this.db.pragma('journal_mode = WAL');
9
+ this.db.pragma('foreign_keys = ON');
10
+ this.db.exec(SCHEMA);
11
+ this.runMigrations();
12
+ this.stmts = {
13
+ insert: this.db.prepare(`
14
+ INSERT OR IGNORE INTO records
15
+ (input_hash, namespace, key, value, timestamp, signature, source_peer)
16
+ VALUES
17
+ (@inputHash, @namespace, @key, @value, @timestamp, @signature, @sourcePeer)
18
+ `),
19
+ // cursor is composite: timestamp|input_hash — avoids skipping records
20
+ // when multiple records share the same timestamp
21
+ getSince: this.db.prepare(`
22
+ SELECT * FROM records
23
+ WHERE namespace = @namespace AND timestamp > @since
24
+ ORDER BY timestamp ASC, input_hash ASC
25
+ LIMIT @limit
26
+ `),
27
+ getSinceAfterCursor: this.db.prepare(`
28
+ SELECT * FROM records
29
+ WHERE namespace = @namespace
30
+ AND (
31
+ timestamp > @cursorTs
32
+ OR (timestamp = @cursorTs AND input_hash > @cursorHash)
33
+ )
34
+ ORDER BY timestamp ASC, input_hash ASC
35
+ LIMIT @limit
36
+ `),
37
+ // first match across all namespaces (basic tier lookup)
38
+ getOne: this.db.prepare(`
39
+ SELECT * FROM records WHERE input_hash = ? LIMIT 1
40
+ `),
41
+ // exact match on composite PK
42
+ getOneNs: this.db.prepare(`
43
+ SELECT * FROM records WHERE input_hash = ? AND namespace = ?
44
+ `),
45
+ // all records for an inputHash across every namespace (used by /verify)
46
+ getAllByHash: this.db.prepare(`
47
+ SELECT * FROM records WHERE input_hash = ? ORDER BY namespace ASC
48
+ `),
49
+ upsertPeer: this.db.prepare(`
50
+ INSERT INTO peers (url, last_sync_at, healthy, node_version, signer_address)
51
+ VALUES (@url, @lastSyncAt, @healthy, @nodeVersion, @signerAddress)
52
+ ON CONFLICT(url) DO UPDATE SET
53
+ last_sync_at = excluded.last_sync_at,
54
+ healthy = excluded.healthy,
55
+ node_version = excluded.node_version,
56
+ signer_address = excluded.signer_address
57
+ `),
58
+ getPeers: this.db.prepare(`SELECT * FROM peers`),
59
+ count: this.db.prepare(`
60
+ SELECT COUNT(*) as n FROM records WHERE namespace = ?
61
+ `),
62
+ recent: this.db.prepare(`
63
+ SELECT * FROM records
64
+ WHERE namespace = ?
65
+ ORDER BY timestamp DESC
66
+ LIMIT ?
67
+ `),
68
+ removePeer: this.db.prepare(`DELETE FROM peers WHERE url = ?`),
69
+ contributions: this.db.prepare(`
70
+ SELECT source_peer, COUNT(*) as count
71
+ FROM records WHERE namespace = ?
72
+ GROUP BY source_peer ORDER BY count DESC
73
+ `),
74
+ // double-sign: same (input_hash, namespace), different signature — slashable
75
+ doubleSigns: this.db.prepare(`
76
+ SELECT input_hash FROM records
77
+ WHERE input_hash = @inputHash
78
+ AND namespace = @namespace
79
+ AND signature != @signature
80
+ `),
81
+ };
82
+ }
83
+ // Run pending migrations in order, tracking applied versions in schema_version.
84
+ runMigrations() {
85
+ const applied = this.db
86
+ .prepare(`SELECT version FROM schema_version ORDER BY version ASC`)
87
+ .all();
88
+ const appliedVersions = new Set(applied.map((r) => r.version));
89
+ for (const migration of MIGRATIONS) {
90
+ if (appliedVersions.has(migration.version))
91
+ continue;
92
+ console.log(`[db] applying migration v${migration.version}`);
93
+ this.db.exec(migration.sql);
94
+ this.db
95
+ .prepare(`INSERT INTO schema_version (version) VALUES (?)`)
96
+ .run(migration.version);
97
+ }
98
+ }
99
+ async insertRecord(record) {
100
+ const existing = this.stmts.doubleSigns.get({
101
+ inputHash: record.inputHash,
102
+ namespace: record.namespace,
103
+ signature: record.signature,
104
+ });
105
+ if (existing) {
106
+ console.warn(`[double-sign] input_hash=${record.inputHash} ns=${record.namespace} — flagged for future slashing`);
107
+ }
108
+ this.stmts.insert.run({
109
+ inputHash: record.inputHash,
110
+ namespace: record.namespace,
111
+ key: record.key,
112
+ value: record.value,
113
+ timestamp: record.timestamp,
114
+ signature: record.signature,
115
+ sourcePeer: record.sourcePeer,
116
+ });
117
+ }
118
+ async getRecordsSince(namespace, since, limit, cursor) {
119
+ let rows;
120
+ if (cursor) {
121
+ const [cursorTs, cursorHash] = cursor.split('|');
122
+ rows = this.stmts.getSinceAfterCursor.all({
123
+ namespace,
124
+ cursorTs: Number(cursorTs),
125
+ cursorHash,
126
+ limit,
127
+ });
128
+ }
129
+ else {
130
+ rows = this.stmts.getSince.all({ namespace, since, limit });
131
+ }
132
+ return rows.map(toMeshRecord);
133
+ }
134
+ async getRecord(inputHash, namespace) {
135
+ const row = namespace
136
+ ? this.stmts.getOneNs.get(inputHash, namespace)
137
+ : this.stmts.getOne.get(inputHash);
138
+ return row ? toMeshRecord(row) : null;
139
+ }
140
+ async getRecordsByInputHash(inputHash) {
141
+ const rows = this.stmts.getAllByHash.all(inputHash);
142
+ return rows.map(toMeshRecord);
143
+ }
144
+ async upsertPeer(peer) {
145
+ this.stmts.upsertPeer.run({
146
+ url: peer.url,
147
+ lastSyncAt: peer.lastSyncAt,
148
+ healthy: peer.healthy ? 1 : 0,
149
+ nodeVersion: peer.nodeVersion,
150
+ signerAddress: peer.signerAddress,
151
+ });
152
+ }
153
+ async getPeers() {
154
+ const rows = this.stmts.getPeers.all();
155
+ return rows.map(toPeerState);
156
+ }
157
+ async recordCount(namespace) {
158
+ const row = this.stmts.count.get(namespace);
159
+ return row.n;
160
+ }
161
+ async getRecentRecords(namespace, limit) {
162
+ const rows = this.stmts.recent.all(namespace, limit);
163
+ return rows.map(toMeshRecord);
164
+ }
165
+ async getContributions(namespace) {
166
+ const rows = this.stmts.contributions.all(namespace);
167
+ return rows.map((r) => ({ sourcePeer: r.source_peer, count: r.count }));
168
+ }
169
+ async removePeer(url) {
170
+ this.stmts.removePeer.run(url);
171
+ }
172
+ close() {
173
+ this.db.close();
174
+ }
175
+ }
176
+ function toMeshRecord(row) {
177
+ return {
178
+ inputHash: row.input_hash,
179
+ namespace: row.namespace,
180
+ key: row.key,
181
+ value: row.value,
182
+ timestamp: row.timestamp,
183
+ signature: row.signature,
184
+ sourcePeer: row.source_peer,
185
+ };
186
+ }
187
+ function toPeerState(row) {
188
+ return {
189
+ url: row.url,
190
+ lastSyncAt: row.last_sync_at,
191
+ healthy: row.healthy === 1,
192
+ nodeVersion: row.node_version,
193
+ signerAddress: row.signer_address,
194
+ };
195
+ }
196
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/db/sqlite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export type MeshRecord = {
2
+ inputHash: string;
3
+ namespace: string;
4
+ key: string;
5
+ value: string;
6
+ timestamp: number;
7
+ signature: string;
8
+ sourcePeer: string | null;
9
+ };
10
+ export type PeerState = {
11
+ url: string;
12
+ lastSyncAt: number;
13
+ healthy: boolean;
14
+ nodeVersion: string | null;
15
+ signerAddress: string | null;
16
+ };
17
+ export type Contribution = {
18
+ sourcePeer: string | null;
19
+ count: number;
20
+ };
21
+ export interface DB {
22
+ insertRecord(record: MeshRecord): Promise<void>;
23
+ getRecordsSince(namespace: string, since: number, limit: number, cursor?: string): Promise<MeshRecord[]>;
24
+ getRecord(inputHash: string, namespace?: string): Promise<MeshRecord | null>;
25
+ getRecordsByInputHash(inputHash: string): Promise<MeshRecord[]>;
26
+ getRecentRecords(namespace: string, limit: number): Promise<MeshRecord[]>;
27
+ getContributions(namespace: string): Promise<Contribution[]>;
28
+ upsertPeer(peer: PeerState): Promise<void>;
29
+ removePeer(url: string): Promise<void>;
30
+ getPeers(): Promise<PeerState[]>;
31
+ recordCount(namespace: string): Promise<number>;
32
+ close(): void;
33
+ }
34
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/db/types.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,KAAK,EAAO,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,WAAW,EAAE;IACjB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IACxG,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IAC5E,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IAC/D,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IACzE,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC5D,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,QAAQ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAA;IAChC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/C,KAAK,IAAI,IAAI,CAAA;CACd"}
@@ -0,0 +1,5 @@
1
+ // DB interface — implementation (SQLite) lives in db/sqlite.ts
2
+ // CcipRouter depends on this interface, not the implementation.
3
+ // Swap the implementation without touching router logic.
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/db/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,gEAAgE;AAChE,yDAAyD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=eip3668.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eip3668.test.d.ts","sourceRoot":"","sources":["../../../src/gateway/__tests__/eip3668.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,31 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { decodeRequest, CcipRequestError } from '../eip3668.js';
4
+ describe('decodeRequest', () => {
5
+ const sender = '0xe61f5a6783ae09949b9a1b6821b68f89c0d7bb2d';
6
+ const calldata = '0xabcdef';
7
+ it('accepts 0x-prefixed sender and calldata', () => {
8
+ const req = decodeRequest(sender, calldata);
9
+ assert.equal(req.sender.toLowerCase(), sender);
10
+ assert.equal(req.calldata, calldata);
11
+ });
12
+ it('accepts bare hex calldata without 0x prefix', () => {
13
+ const req = decodeRequest(sender, 'abcdef');
14
+ assert.equal(req.calldata, '0xabcdef');
15
+ });
16
+ it('strips .json suffix from calldata', () => {
17
+ const req = decodeRequest(sender, `${calldata}.json`);
18
+ assert.equal(req.calldata, calldata);
19
+ });
20
+ it('strips .json suffix from bare calldata', () => {
21
+ const req = decodeRequest(sender, 'abcdef.json');
22
+ assert.equal(req.calldata, '0xabcdef');
23
+ });
24
+ it('throws CcipRequestError(400) for invalid sender', () => {
25
+ assert.throws(() => decodeRequest('notanaddress', calldata), (err) => err instanceof CcipRequestError && err.status === 400);
26
+ });
27
+ it('throws CcipRequestError(400) for invalid calldata', () => {
28
+ assert.throws(() => decodeRequest(sender, 'not-hex'), (err) => err instanceof CcipRequestError && err.status === 400);
29
+ });
30
+ });
31
+ //# sourceMappingURL=eip3668.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eip3668.test.js","sourceRoot":"","sources":["../../../src/gateway/__tests__/eip3668.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAE/D,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,MAAM,MAAM,GAAG,4CAA4C,CAAA;IAC3D,MAAM,QAAQ,GAAG,UAAU,CAAA;IAE3B,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC3C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAA;QAC9C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IACtC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC3C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAA;QACrD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IACtC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;QAChD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,QAAQ,CAAC,EAC7C,CAAC,GAAY,EAAE,EAAE,CAAC,GAAG,YAAY,gBAAgB,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CACxE,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,EACtC,CAAC,GAAY,EAAE,EAAE,CAAC,GAAG,YAAY,gBAAgB,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CACxE,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,14 @@
1
+ export type CcipRequest = {
2
+ sender: `0x${string}`;
3
+ calldata: `0x${string}`;
4
+ };
5
+ export type CcipResponse = {
6
+ data: `0x${string}`;
7
+ };
8
+ export declare function decodeRequest(rawSender: string, rawData: string): CcipRequest;
9
+ export declare function encodeResponse(result: `0x${string}`): CcipResponse;
10
+ export declare class CcipRequestError extends Error {
11
+ readonly status: 400 | 500;
12
+ constructor(message: string, status: 400 | 500);
13
+ }
14
+ //# sourceMappingURL=eip3668.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eip3668.d.ts","sourceRoot":"","sources":["../../src/gateway/eip3668.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,KAAK,MAAM,EAAE,CAAA;IACrB,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,KAAK,MAAM,EAAE,CAAA;CACpB,CAAA;AAID,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAa7E;AAGD,wBAAgB,cAAc,CAAC,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,YAAY,CAElE;AAED,qBAAa,gBAAiB,SAAQ,KAAK;aACI,MAAM,EAAE,GAAG,GAAG,GAAG;gBAAlD,OAAO,EAAE,MAAM,EAAkB,MAAM,EAAE,GAAG,GAAG,GAAG;CAI/D"}
@@ -0,0 +1,28 @@
1
+ import { isAddress, isHex } from 'viem';
2
+ // Decode sender + calldata from EIP-3668 URL path segments.
3
+ // Handles: checksummed / lowercase addresses, 0x-prefixed / bare hex calldata, .json suffix.
4
+ export function decodeRequest(rawSender, rawData) {
5
+ const sender = rawSender.startsWith('0x') ? rawSender : `0x${rawSender}`;
6
+ if (!isAddress(sender)) {
7
+ throw new CcipRequestError(`invalid sender address: "${rawSender}"`, 400);
8
+ }
9
+ const stripped = rawData.replace(/\.json$/, '');
10
+ const calldata = (stripped.startsWith('0x') ? stripped : `0x${stripped}`);
11
+ if (!isHex(calldata)) {
12
+ throw new CcipRequestError(`invalid calldata: "${rawData}"`, 400);
13
+ }
14
+ return { sender: sender, calldata };
15
+ }
16
+ // Wrap resolver output in the EIP-3668 JSON response envelope.
17
+ export function encodeResponse(result) {
18
+ return { data: result };
19
+ }
20
+ export class CcipRequestError extends Error {
21
+ status;
22
+ constructor(message, status) {
23
+ super(message);
24
+ this.status = status;
25
+ this.name = 'CcipRequestError';
26
+ }
27
+ }
28
+ //# sourceMappingURL=eip3668.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eip3668.js","sourceRoot":"","sources":["../../src/gateway/eip3668.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,MAAM,CAAA;AAWvC,4DAA4D;AAC5D,6FAA6F;AAC7F,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,OAAe;IAC9D,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAA;IACxE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,gBAAgB,CAAC,4BAA4B,SAAS,GAAG,EAAE,GAAG,CAAC,CAAA;IAC3E,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IAC/C,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAkB,CAAA;IAC1F,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,gBAAgB,CAAC,sBAAsB,OAAO,GAAG,EAAE,GAAG,CAAC,CAAA;IACnE,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAuB,EAAE,QAAQ,EAAE,CAAA;AACtD,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,cAAc,CAAC,MAAqB;IAClD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACzB,CAAC;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACI;IAA7C,YAAY,OAAe,EAAkB,MAAiB;QAC5D,KAAK,CAAC,OAAO,CAAC,CAAA;QAD6B,WAAM,GAAN,MAAM,CAAW;QAE5D,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAA;IAChC,CAAC;CACF"}
package/dist/lib.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export { CcipRouter } from './router/index.js';
2
+ export type { ResolverFn, CcipRouterOptions, IdentityOpts } from './router/CcipRouter.js';
3
+ export { withWyriwe } from './attestation/withWyriwe.js';
4
+ export type { WyriweOpts } from './attestation/withWyriwe.js';
5
+ export type { DB, MeshRecord, PeerState } from './db/types.js';
6
+ export { publishAttestation, checkOnChain } from './chain/publish.js';
7
+ export type { ChainOpts, PublishResult, OnChainProof } from './chain/publish.js';
8
+ export { registerNode } from './chain/register.js';
9
+ export { ATTESTATION_INDEX_ABI, NODE_REGISTRY_ABI } from './chain/abi.js';
10
+ export { makeVni, verifyVni, fetchPeerVni } from './mesh/vni.js';
11
+ export type { SignedVni, VniDocument } from './mesh/vni.js';
12
+ //# sourceMappingURL=lib.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACzF,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AACxD,YAAY,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAC7D,YAAY,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACrE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAChE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
package/dist/lib.js ADDED
@@ -0,0 +1,8 @@
1
+ // Public library surface — import from 'ccip-router' in downstream projects
2
+ export { CcipRouter } from './router/index.js';
3
+ export { withWyriwe } from './attestation/withWyriwe.js';
4
+ export { publishAttestation, checkOnChain } from './chain/publish.js';
5
+ export { registerNode } from './chain/register.js';
6
+ export { ATTESTATION_INDEX_ABI, NODE_REGISTRY_ABI } from './chain/abi.js';
7
+ export { makeVni, verifyVni, fetchPeerVni } from './mesh/vni.js';
8
+ //# sourceMappingURL=lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAGxD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAErE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,4 @@
1
+ import type { DB } from '../db/types.js';
2
+ import type { Config } from '../config.js';
3
+ export declare function startSyncCron(config: Config, db: DB): void;
4
+ //# sourceMappingURL=cron.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/mesh/cron.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAA;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAG1C,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,CAuB1D"}
@@ -0,0 +1,22 @@
1
+ import cron from 'node-cron';
2
+ import { syncPeer } from './sync.js';
3
+ export function startSyncCron(config, db) {
4
+ if (!cron.validate(config.syncInterval)) {
5
+ throw new Error(`[cron] invalid SYNC_INTERVAL: "${config.syncInterval}"`);
6
+ }
7
+ if (config.peers.length === 0 && !config.autoDiscover) {
8
+ console.log('[cron] no peers configured and auto-discover off — sync cron not started');
9
+ return;
10
+ }
11
+ console.log(`[cron] sync starting — interval: ${config.syncInterval}, namespace: ${config.syncNamespace}`);
12
+ cron.schedule(config.syncInterval, async () => {
13
+ const peers = await db.getPeers();
14
+ if (!peers.length)
15
+ return;
16
+ await Promise.allSettled(peers.map(async (peer) => {
17
+ const update = await syncPeer(peer, config.syncNamespace, db, config.autoDiscover);
18
+ await db.upsertPeer({ ...peer, ...update });
19
+ }));
20
+ });
21
+ }
22
+ //# sourceMappingURL=cron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/mesh/cron.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAG5B,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,EAAM;IAClD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,kCAAkC,MAAM,CAAC,YAAY,GAAG,CAAC,CAAA;IAC3E,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,0EAA0E,CAAC,CAAA;QACvF,OAAM;IACR,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,oCAAoC,MAAM,CAAC,YAAY,gBAAgB,MAAM,CAAC,aAAa,EAAE,CAAC,CAAA;IAE1G,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAA;QACjC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,OAAM;QAEzB,MAAM,OAAO,CAAC,UAAU,CACtB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACvB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;YAClF,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;QAC7C,CAAC,CAAC,CACH,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ export declare const recordsRouter: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export declare const peersRouter: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
4
+ //# sourceMappingURL=records.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../src/mesh/records.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAO3B,eAAO,MAAM,aAAa,4EAAa,CAAA;AA2BvC,eAAO,MAAM,WAAW,4EAAa,CAAA"}
@@ -0,0 +1,47 @@
1
+ import { Hono } from 'hono';
2
+ import { getDB } from '../db/index.js';
3
+ import { getConfig } from '../config.js';
4
+ import { privateKeyToAccount } from 'viem/accounts';
5
+ // Standard mesh sync interface — any CCIP gateway implementing this is mesh-compatible
6
+ // GET /records?since=<unix_timestamp>&namespace=<string>&limit=<n>&cursor=<string>
7
+ export const recordsRouter = new Hono();
8
+ recordsRouter.get('/', async (c) => {
9
+ const since = Number(c.req.query('since') ?? 0);
10
+ const namespace = c.req.query('namespace') ?? 'agent-attestations';
11
+ const limit = Math.min(Number(c.req.query('limit') ?? 100), 500);
12
+ const cursor = c.req.query('cursor') ?? undefined;
13
+ const db = getDB();
14
+ const records = await db.getRecordsSince(namespace, since, limit, cursor);
15
+ // next cursor: timestamp|input_hash of the last record returned
16
+ const nextCursor = records.length === limit
17
+ ? `${records[records.length - 1].timestamp}|${records[records.length - 1].inputHash}`
18
+ : null;
19
+ return c.json({
20
+ protocol: 1,
21
+ node_version: '0.1.0',
22
+ namespace,
23
+ records,
24
+ cursor: nextCursor,
25
+ });
26
+ });
27
+ // GET /peers — public peer list for gossip / auto-discovery
28
+ // Other nodes call this during sync to find new peers in the mesh.
29
+ export const peersRouter = new Hono();
30
+ peersRouter.get('/', async (c) => {
31
+ const config = getConfig();
32
+ const db = getDB();
33
+ const peers = await db.getPeers();
34
+ const signerAddress = config.gatewayKey ? privateKeyToAccount(config.gatewayKey).address : null;
35
+ return c.json({
36
+ protocol: 1,
37
+ node_version: '0.1.0',
38
+ signerAddress,
39
+ peers: peers.map((p) => ({
40
+ url: p.url,
41
+ signerAddress: p.signerAddress,
42
+ healthy: p.healthy,
43
+ lastSyncAt: p.lastSyncAt,
44
+ })),
45
+ });
46
+ });
47
+ //# sourceMappingURL=records.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/mesh/records.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAEnD,uFAAuF;AACvF,mFAAmF;AACnF,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,IAAI,EAAE,CAAA;AAEvC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACjC,MAAM,KAAK,GAAO,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IACnD,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,oBAAoB,CAAA;IAClE,MAAM,KAAK,GAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;IACpE,MAAM,MAAM,GAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAA;IAEpD,MAAM,EAAE,GAAG,KAAK,EAAE,CAAA;IAClB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;IAEzE,gEAAgE;IAChE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,KAAK,KAAK;QACzC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE;QACrF,CAAC,CAAC,IAAI,CAAA;IAER,OAAO,CAAC,CAAC,IAAI,CAAC;QACZ,QAAQ,EAAM,CAAC;QACf,YAAY,EAAE,OAAO;QACrB,SAAS;QACT,OAAO;QACP,MAAM,EAAQ,UAAU;KACzB,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,4DAA4D;AAC5D,mEAAmE;AACnE,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAA;AAErC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC/B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,EAAE,GAAO,KAAK,EAAE,CAAA;IACtB,MAAM,KAAK,GAAI,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAA;IAClC,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA;IAC/F,OAAO,CAAC,CAAC,IAAI,CAAC;QACZ,QAAQ,EAAQ,CAAC;QACjB,YAAY,EAAG,OAAO;QACtB,aAAa;QACb,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvB,GAAG,EAAY,CAAC,CAAC,GAAG;YACpB,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,OAAO,EAAQ,CAAC,CAAC,OAAO;YACxB,UAAU,EAAK,CAAC,CAAC,UAAU;SAC5B,CAAC,CAAC;KACJ,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ import type { DB, PeerState } from '../db/types.js';
2
+ import type { Config } from '../config.js';
3
+ export declare function syncAll(config: Config, db: DB): Promise<number>;
4
+ export declare function syncPeer(peer: PeerState, namespace: string, db: DB, autoDiscover?: boolean): Promise<Partial<PeerState>>;
5
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/mesh/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAc,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAK1C,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CASrE;AAmBD,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,EAAE,EACN,YAAY,UAAO,GAClB,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAqD7B"}