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.
- package/LICENSE +21 -0
- package/README.md +528 -0
- package/contracts/AttestationIndex.sol +125 -0
- package/contracts/NodeRegistry.sol +85 -0
- package/dist/attestation/eip712.d.ts +50 -0
- package/dist/attestation/eip712.d.ts.map +1 -0
- package/dist/attestation/eip712.js +31 -0
- package/dist/attestation/eip712.js.map +1 -0
- package/dist/attestation/ocp.d.ts +9 -0
- package/dist/attestation/ocp.d.ts.map +1 -0
- package/dist/attestation/ocp.js +11 -0
- package/dist/attestation/ocp.js.map +1 -0
- package/dist/attestation/withWyriwe.d.ts +11 -0
- package/dist/attestation/withWyriwe.d.ts.map +1 -0
- package/dist/attestation/withWyriwe.js +92 -0
- package/dist/attestation/withWyriwe.js.map +1 -0
- package/dist/chain/abi.d.ts +178 -0
- package/dist/chain/abi.d.ts.map +1 -0
- package/dist/chain/abi.js +94 -0
- package/dist/chain/abi.js.map +1 -0
- package/dist/chain/client.d.ts +16762 -0
- package/dist/chain/client.d.ts.map +1 -0
- package/dist/chain/client.js +21 -0
- package/dist/chain/client.js.map +1 -0
- package/dist/chain/publish.d.ts +26 -0
- package/dist/chain/publish.d.ts.map +1 -0
- package/dist/chain/publish.js +66 -0
- package/dist/chain/publish.js.map +1 -0
- package/dist/chain/register.d.ts +9 -0
- package/dist/chain/register.d.ts.map +1 -0
- package/dist/chain/register.js +20 -0
- package/dist/chain/register.js.map +1 -0
- package/dist/crypto/hash.d.ts +3 -0
- package/dist/crypto/hash.d.ts.map +1 -0
- package/dist/crypto/hash.js +12 -0
- package/dist/crypto/hash.js.map +1 -0
- package/dist/crypto/index.d.ts +3 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +3 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/sign.d.ts +6 -0
- package/dist/crypto/sign.d.ts.map +1 -0
- package/dist/crypto/sign.js +60 -0
- package/dist/crypto/sign.js.map +1 -0
- package/dist/db/index.d.ts +5 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +13 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +6 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +41 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/sqlite.d.ts +19 -0
- package/dist/db/sqlite.d.ts.map +1 -0
- package/dist/db/sqlite.js +196 -0
- package/dist/db/sqlite.js.map +1 -0
- package/dist/db/types.d.ts +34 -0
- package/dist/db/types.d.ts.map +1 -0
- package/dist/db/types.js +5 -0
- package/dist/db/types.js.map +1 -0
- package/dist/gateway/__tests__/eip3668.test.d.ts +2 -0
- package/dist/gateway/__tests__/eip3668.test.d.ts.map +1 -0
- package/dist/gateway/__tests__/eip3668.test.js +31 -0
- package/dist/gateway/__tests__/eip3668.test.js.map +1 -0
- package/dist/gateway/eip3668.d.ts +14 -0
- package/dist/gateway/eip3668.d.ts.map +1 -0
- package/dist/gateway/eip3668.js +28 -0
- package/dist/gateway/eip3668.js.map +1 -0
- package/dist/lib.d.ts +12 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +8 -0
- package/dist/lib.js.map +1 -0
- package/dist/mesh/cron.d.ts +4 -0
- package/dist/mesh/cron.d.ts.map +1 -0
- package/dist/mesh/cron.js +22 -0
- package/dist/mesh/cron.js.map +1 -0
- package/dist/mesh/records.d.ts +4 -0
- package/dist/mesh/records.d.ts.map +1 -0
- package/dist/mesh/records.js +47 -0
- package/dist/mesh/records.js.map +1 -0
- package/dist/mesh/sync.d.ts +5 -0
- package/dist/mesh/sync.d.ts.map +1 -0
- package/dist/mesh/sync.js +154 -0
- package/dist/mesh/sync.js.map +1 -0
- package/dist/mesh/vni.d.ts +14 -0
- package/dist/mesh/vni.d.ts.map +1 -0
- package/dist/mesh/vni.js +52 -0
- package/dist/mesh/vni.js.map +1 -0
- package/dist/router/CcipRouter.d.ts +26 -0
- package/dist/router/CcipRouter.d.ts.map +1 -0
- package/dist/router/CcipRouter.js +85 -0
- package/dist/router/CcipRouter.js.map +1 -0
- package/dist/router/index.d.ts +3 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +2 -0
- package/dist/router/index.js.map +1 -0
- 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"}
|
package/dist/db/types.js
ADDED
|
@@ -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 @@
|
|
|
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
|
package/dist/lib.js.map
ADDED
|
@@ -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 @@
|
|
|
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"}
|