@origintrail-official/dkg-node-ui 10.0.16 → 10.0.18
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/dist/chain-cursor-stores.d.ts +48 -0
- package/dist/chain-cursor-stores.d.ts.map +1 -1
- package/dist/chain-cursor-stores.js +145 -0
- package/dist/chain-cursor-stores.js.map +1 -1
- package/dist/chain-event-log-store.d.ts +84 -0
- package/dist/chain-event-log-store.d.ts.map +1 -0
- package/dist/chain-event-log-store.js +289 -0
- package/dist/chain-event-log-store.js.map +1 -0
- package/dist/db.d.ts +16 -58
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +125 -144
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/protocol-outbox-store.d.ts +67 -0
- package/dist/protocol-outbox-store.d.ts.map +1 -0
- package/dist/protocol-outbox-store.js +199 -0
- package/dist/protocol-outbox-store.js.map +1 -0
- package/dist-ui/assets/{3d-force-graph-bUKbeTGZ.js → 3d-force-graph-DGF2sXeK.js} +1 -1
- package/dist-ui/assets/ActivityFeed-DNatshHL.js +99 -0
- package/dist-ui/assets/{AgentHub-4c4sH_Jd.js → AgentHub-lOm96XuE.js} +1 -1
- package/dist-ui/assets/{AgentProfilePage-ClhUeZxy.js → AgentProfilePage-BRtazufK.js} +1 -1
- package/dist-ui/assets/ApproveWalletsModal-BMtRgndO.js +3 -0
- package/dist-ui/assets/{ContextGraphPrimitives-Bwc2i7EX.js → ContextGraphPrimitives-CBc6kvmp.js} +1 -1
- package/dist-ui/assets/ConvictionDetailView-DOTYSm7p.js +2 -0
- package/dist-ui/assets/{MemoryLayerView-DxL2MjyA.js → MemoryLayerView-DDFI2ngR.js} +2 -2
- package/dist-ui/assets/{MemoryStackView-BLhA3bn0.js → MemoryStackView-Bol2eMyq.js} +1 -1
- package/dist-ui/assets/{Network-BNhbBzOD.js → Network-B49IxpAj.js} +1 -1
- package/dist-ui/assets/{OnChainProvenanceCard-DKyfVEjF.js → OnChainProvenanceCard-BpUoHg4b.js} +1 -1
- package/dist-ui/assets/{Operations-mCPe0E-j.js → Operations-BCQ545Yk.js} +1 -1
- package/dist-ui/assets/{ProjectView-jrGPu5ON.js → ProjectView-BaQQSy8L.js} +20 -20
- package/dist-ui/assets/PublishingConviction-B5nWRsUP.js +2 -0
- package/dist-ui/assets/Settings-DeZKX_Ry.js +1 -0
- package/dist-ui/assets/browserWalletTransaction-B6wyaMOV.js +55 -0
- package/dist-ui/assets/ccip-B_vQl40F.js +1 -0
- package/dist-ui/assets/{index-VYV5TH6q.css → index-BLQUVvVz.css} +1 -1
- package/dist-ui/assets/index-CT-LdpBE.js +1175 -0
- package/dist-ui/assets/{index-UvxrSkC_.js → index-DHd3qhAk.js} +3 -3
- package/dist-ui/assets/{jsonld-32FQRO67-Dl6_9Lk9.js → jsonld-32FQRO67-BYu8pE-5.js} +2 -2
- package/dist-ui/assets/{jsonld-Dj4KMENF.js → jsonld-Crm5iwcE.js} +1 -1
- package/dist-ui/assets/{renderer-3d-2EVDZII7-DfnhcMkF.js → renderer-3d-2EVDZII7-C2z5aUgo.js} +2 -2
- package/dist-ui/assets/{shikiHighlighter-ByXDJnWi.js → shikiHighlighter-DW1fRfBU.js} +1 -1
- package/dist-ui/assets/{useEntityOnChainReceipt-BRK_O_sb.js → useEntityOnChainReceipt-0Ub24t6e.js} +1 -1
- package/dist-ui/assets/{useProjectActivity-OdoQs9mK.js → useProjectActivity-CLza3psq.js} +1 -1
- package/dist-ui/index.html +2 -2
- package/package.json +3 -3
- package/dist-ui/assets/ActivityFeed-CC5S_gk9.js +0 -100
- package/dist-ui/assets/ApproveWalletsModal-CBKp6zQB.js +0 -57
- package/dist-ui/assets/ConvictionDetailView-a3v7xwcm.js +0 -2
- package/dist-ui/assets/PublishingConviction-BGi128uo.js +0 -2
- package/dist-ui/assets/Settings-D1oxLo1Y.js +0 -1
- package/dist-ui/assets/ccip-WHHgwjp-.js +0 -1
- package/dist-ui/assets/index-RLb1kuzE.js +0 -1174
|
@@ -25,8 +25,22 @@ export declare class SqliteChainEventCursorStore {
|
|
|
25
25
|
* historical scan path.
|
|
26
26
|
*/
|
|
27
27
|
export declare class SqliteContextGraphRegistryScanCursorStore {
|
|
28
|
+
static readonly REPAIR_KEY_PREFIX = "contextGraphRegistryScan.repair:v1";
|
|
28
29
|
private readonly cursors;
|
|
29
30
|
private readonly legacyCursors;
|
|
31
|
+
private readonly db;
|
|
32
|
+
readonly repairAudit: {
|
|
33
|
+
load: (key: {
|
|
34
|
+
chainId: string;
|
|
35
|
+
deploymentId: string;
|
|
36
|
+
registryAddress: string;
|
|
37
|
+
}) => Promise<unknown>;
|
|
38
|
+
save: (key: {
|
|
39
|
+
chainId: string;
|
|
40
|
+
deploymentId: string;
|
|
41
|
+
registryAddress: string;
|
|
42
|
+
}, checkpoint: unknown) => Promise<void>;
|
|
43
|
+
};
|
|
30
44
|
constructor(dashboard: DashboardDB);
|
|
31
45
|
load(key: {
|
|
32
46
|
chainId: string;
|
|
@@ -41,5 +55,39 @@ export declare class SqliteContextGraphRegistryScanCursorStore {
|
|
|
41
55
|
private scope;
|
|
42
56
|
private registryKey;
|
|
43
57
|
private legacyKey;
|
|
58
|
+
private repairKey;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Opaque, SQLite-backed authority-history checkpoints.
|
|
62
|
+
*
|
|
63
|
+
* SQLite makes each replacement atomic. The chain package exclusively owns
|
|
64
|
+
* the versioned codec, integrity check, and authority-state model; this adapter
|
|
65
|
+
* intentionally only persists and returns JSON values.
|
|
66
|
+
*/
|
|
67
|
+
export declare class SqliteContextGraphAuthorityHistoryStore {
|
|
68
|
+
static readonly KEY_PREFIX = "contextGraphAuthorityHistory.checkpoint:v1:";
|
|
69
|
+
private readonly db;
|
|
70
|
+
constructor(dashboard: DashboardDB);
|
|
71
|
+
load(cacheKey: string): Promise<unknown>;
|
|
72
|
+
save(cacheKey: string, checkpoint: unknown): Promise<void>;
|
|
73
|
+
delete(cacheKey: string): Promise<void>;
|
|
74
|
+
private key;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Opaque SQLite persistence for the chain-owned contract-wide authority index.
|
|
78
|
+
*
|
|
79
|
+
* Authority-bearing JSON is never interpreted here. The store owns the
|
|
80
|
+
* monotonic CAS token, and JSON `null` is its durable invalidation tombstone.
|
|
81
|
+
* Tokens therefore never repeat, including across corruption/reorg recovery.
|
|
82
|
+
*/
|
|
83
|
+
export declare class SqliteContextGraphAuthorityIndexStore {
|
|
84
|
+
private readonly db;
|
|
85
|
+
constructor(dashboard: DashboardDB);
|
|
86
|
+
load(scope: string): Promise<Readonly<{
|
|
87
|
+
token: number;
|
|
88
|
+
value: unknown | null;
|
|
89
|
+
}> | undefined>;
|
|
90
|
+
compareAndSwap(scope: string, expectedToken: number | undefined, checkpoint: unknown): Promise<number | undefined>;
|
|
91
|
+
invalidate(scope: string, expectedToken: number): Promise<number | undefined>;
|
|
44
92
|
}
|
|
45
93
|
//# sourceMappingURL=chain-cursor-stores.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chain-cursor-stores.d.ts","sourceRoot":"","sources":["../src/chain-cursor-stores.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAmD3C;;;;;GAKG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IACnE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,SAAS,EAAE,WAAW,EAAE,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO;IAM9D,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAInD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,OAAO,CAAC,SAAS;CAGlB;AAED;;;;;;;GAOG;AACH,qBAAa,yCAAyC;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;
|
|
1
|
+
{"version":3,"file":"chain-cursor-stores.d.ts","sourceRoot":"","sources":["../src/chain-cursor-stores.ts"],"names":[],"mappings":"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"}
|
|
@@ -76,9 +76,31 @@ export class SqliteChainEventCursorStore {
|
|
|
76
76
|
* historical scan path.
|
|
77
77
|
*/
|
|
78
78
|
export class SqliteContextGraphRegistryScanCursorStore {
|
|
79
|
+
static REPAIR_KEY_PREFIX = 'contextGraphRegistryScan.repair:v1';
|
|
79
80
|
cursors;
|
|
80
81
|
legacyCursors;
|
|
82
|
+
db;
|
|
83
|
+
repairAudit = {
|
|
84
|
+
load: async (key) => {
|
|
85
|
+
const row = this.db.prepare(`SELECT value FROM settings WHERE key = ?`).get(this.repairKey(key));
|
|
86
|
+
if (!row)
|
|
87
|
+
return undefined;
|
|
88
|
+
try {
|
|
89
|
+
return JSON.parse(row.value);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
save: async (key, checkpoint) => {
|
|
96
|
+
const encoded = JSON.stringify(checkpoint);
|
|
97
|
+
if (encoded === undefined)
|
|
98
|
+
throw new Error('Registry repair checkpoint is not serializable');
|
|
99
|
+
this.db.prepare(`INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)`).run(this.repairKey(key), encoded);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
81
102
|
constructor(dashboard) {
|
|
103
|
+
this.db = dashboard.db;
|
|
82
104
|
this.cursors = new RuntimePositiveIntegerCursorStore(dashboard.db, 'contextGraphRegistryScan.cursor');
|
|
83
105
|
this.legacyCursors = new SettingsPositiveIntegerCursorStore(dashboard.db);
|
|
84
106
|
}
|
|
@@ -103,5 +125,128 @@ export class SqliteContextGraphRegistryScanCursorStore {
|
|
|
103
125
|
key.registryAddress.toLowerCase(),
|
|
104
126
|
].join(':');
|
|
105
127
|
}
|
|
128
|
+
repairKey(key) {
|
|
129
|
+
return [
|
|
130
|
+
SqliteContextGraphRegistryScanCursorStore.REPAIR_KEY_PREFIX,
|
|
131
|
+
key.chainId,
|
|
132
|
+
key.deploymentId,
|
|
133
|
+
key.registryAddress.toLowerCase(),
|
|
134
|
+
].join(':');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Opaque, SQLite-backed authority-history checkpoints.
|
|
139
|
+
*
|
|
140
|
+
* SQLite makes each replacement atomic. The chain package exclusively owns
|
|
141
|
+
* the versioned codec, integrity check, and authority-state model; this adapter
|
|
142
|
+
* intentionally only persists and returns JSON values.
|
|
143
|
+
*/
|
|
144
|
+
export class SqliteContextGraphAuthorityHistoryStore {
|
|
145
|
+
static KEY_PREFIX = 'contextGraphAuthorityHistory.checkpoint:v1:';
|
|
146
|
+
db;
|
|
147
|
+
constructor(dashboard) {
|
|
148
|
+
this.db = dashboard.db;
|
|
149
|
+
}
|
|
150
|
+
async load(cacheKey) {
|
|
151
|
+
const row = this.db.prepare(`SELECT value FROM settings WHERE key = ?`).get(this.key(cacheKey));
|
|
152
|
+
if (row === undefined)
|
|
153
|
+
return undefined;
|
|
154
|
+
try {
|
|
155
|
+
return JSON.parse(row.value);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async save(cacheKey, checkpoint) {
|
|
162
|
+
const value = JSON.stringify(checkpoint);
|
|
163
|
+
this.db.prepare(`INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)`).run(this.key(cacheKey), value);
|
|
164
|
+
}
|
|
165
|
+
async delete(cacheKey) {
|
|
166
|
+
this.db.prepare(`DELETE FROM settings WHERE key = ?`).run(this.key(cacheKey));
|
|
167
|
+
}
|
|
168
|
+
key(cacheKey) {
|
|
169
|
+
return `${SqliteContextGraphAuthorityHistoryStore.KEY_PREFIX}${cacheKey}`;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Opaque SQLite persistence for the chain-owned contract-wide authority index.
|
|
174
|
+
*
|
|
175
|
+
* Authority-bearing JSON is never interpreted here. The store owns the
|
|
176
|
+
* monotonic CAS token, and JSON `null` is its durable invalidation tombstone.
|
|
177
|
+
* Tokens therefore never repeat, including across corruption/reorg recovery.
|
|
178
|
+
*/
|
|
179
|
+
export class SqliteContextGraphAuthorityIndexStore {
|
|
180
|
+
db;
|
|
181
|
+
constructor(dashboard) {
|
|
182
|
+
this.db = dashboard.db;
|
|
183
|
+
}
|
|
184
|
+
async load(scope) {
|
|
185
|
+
const row = this.db.prepare(`
|
|
186
|
+
SELECT revision, checkpoint_json
|
|
187
|
+
FROM context_graph_authority_indexes
|
|
188
|
+
WHERE scope = ?
|
|
189
|
+
`).get(scope);
|
|
190
|
+
if (row === undefined)
|
|
191
|
+
return undefined;
|
|
192
|
+
try {
|
|
193
|
+
return Object.freeze({
|
|
194
|
+
token: row.revision,
|
|
195
|
+
value: JSON.parse(row.checkpoint_json),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Preserve the durable token even when the opaque payload is corrupt, so
|
|
200
|
+
// chain can conditionally invalidate this exact row without racing a
|
|
201
|
+
// newer compare-and-swap winner.
|
|
202
|
+
return Object.freeze({
|
|
203
|
+
token: row.revision,
|
|
204
|
+
value: Object.freeze({ invalidCheckpointJson: row.checkpoint_json }),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async compareAndSwap(scope, expectedToken, checkpoint) {
|
|
209
|
+
if (scope.trim().length === 0)
|
|
210
|
+
throw new Error('Authority index scope is empty');
|
|
211
|
+
const value = JSON.stringify(checkpoint);
|
|
212
|
+
if (value === undefined)
|
|
213
|
+
throw new Error('Authority index checkpoint is not serializable');
|
|
214
|
+
if (expectedToken === undefined) {
|
|
215
|
+
const inserted = this.db.prepare(`
|
|
216
|
+
INSERT OR IGNORE INTO context_graph_authority_indexes (
|
|
217
|
+
scope, revision, checkpoint_json, updated_at
|
|
218
|
+
) VALUES (?, ?, ?, ?)
|
|
219
|
+
`).run(scope, 1, value, Date.now()).changes === 1;
|
|
220
|
+
return inserted ? 1 : undefined;
|
|
221
|
+
}
|
|
222
|
+
if (!Number.isSafeInteger(expectedToken) || expectedToken < 1) {
|
|
223
|
+
throw new Error('Authority index expected token is invalid');
|
|
224
|
+
}
|
|
225
|
+
const nextToken = expectedToken + 1;
|
|
226
|
+
if (!Number.isSafeInteger(nextToken)) {
|
|
227
|
+
throw new Error('Authority index token exceeds the safe integer range');
|
|
228
|
+
}
|
|
229
|
+
const updated = this.db.prepare(`
|
|
230
|
+
UPDATE context_graph_authority_indexes
|
|
231
|
+
SET revision = ?, checkpoint_json = ?, updated_at = ?
|
|
232
|
+
WHERE scope = ? AND revision = ?
|
|
233
|
+
`).run(nextToken, value, Date.now(), scope, expectedToken).changes === 1;
|
|
234
|
+
return updated ? nextToken : undefined;
|
|
235
|
+
}
|
|
236
|
+
async invalidate(scope, expectedToken) {
|
|
237
|
+
if (!Number.isSafeInteger(expectedToken) || expectedToken < 1) {
|
|
238
|
+
throw new Error('Authority index expected token is invalid');
|
|
239
|
+
}
|
|
240
|
+
const nextToken = expectedToken + 1;
|
|
241
|
+
if (!Number.isSafeInteger(nextToken)) {
|
|
242
|
+
throw new Error('Authority index token exceeds the safe integer range');
|
|
243
|
+
}
|
|
244
|
+
const invalidated = this.db.prepare(`
|
|
245
|
+
UPDATE context_graph_authority_indexes
|
|
246
|
+
SET revision = ?, checkpoint_json = 'null', updated_at = ?
|
|
247
|
+
WHERE scope = ? AND revision = ?
|
|
248
|
+
`).run(nextToken, Date.now(), scope, expectedToken).changes === 1;
|
|
249
|
+
return invalidated ? nextToken : undefined;
|
|
250
|
+
}
|
|
106
251
|
}
|
|
107
252
|
//# sourceMappingURL=chain-cursor-stores.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chain-cursor-stores.js","sourceRoot":"","sources":["../src/chain-cursor-stores.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"chain-cursor-stores.js","sourceRoot":"","sources":["../src/chain-cursor-stores.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { DashboardDB } from './db.js';
|
|
2
|
+
/**
|
|
3
|
+
* SQLite backing for the node's ONE chain log.
|
|
4
|
+
*
|
|
5
|
+
* Opaque, exactly like `SqliteContextGraphAuthorityIndexStore` beside it: this
|
|
6
|
+
* file stores and returns rows and never decides what a topic means. The chain
|
|
7
|
+
* package owns the model, the decoders and every security decision; SQLite owns
|
|
8
|
+
* atomicity and the monotonic CAS token.
|
|
9
|
+
*
|
|
10
|
+
* The one invariant enforced HERE, because only a transaction can enforce it:
|
|
11
|
+
* a tick's cursor advance, its tail replacement and its coverage extension are
|
|
12
|
+
* one atomic act. A half-applied tick would leave coverage claiming a range
|
|
13
|
+
* whose rows were rolled back, and a reader would then report an unindexed
|
|
14
|
+
* Context Graph as absent.
|
|
15
|
+
*/
|
|
16
|
+
/** Mirrors the chain package's `ChainEventLogRow`; matched structurally. */
|
|
17
|
+
export interface SqliteChainEventLogRow {
|
|
18
|
+
readonly blockNumber: number;
|
|
19
|
+
readonly blockHash: string;
|
|
20
|
+
readonly logIndex: number;
|
|
21
|
+
readonly transactionHash: string;
|
|
22
|
+
readonly address: string;
|
|
23
|
+
readonly topics: readonly string[];
|
|
24
|
+
readonly data: string;
|
|
25
|
+
readonly settled: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface SqliteChainEventLogHead {
|
|
28
|
+
readonly number: number;
|
|
29
|
+
readonly hash: string;
|
|
30
|
+
readonly timestampSeconds: number;
|
|
31
|
+
readonly fetchedAtMs: number;
|
|
32
|
+
}
|
|
33
|
+
export interface SqliteChainEventLogCursor {
|
|
34
|
+
readonly revision: number;
|
|
35
|
+
readonly lineage: string;
|
|
36
|
+
readonly deploymentBlockNumber: number;
|
|
37
|
+
readonly settledBlockNumber: number;
|
|
38
|
+
readonly settledBlockHash: string;
|
|
39
|
+
readonly head: SqliteChainEventLogHead;
|
|
40
|
+
readonly topicSetVersion: string;
|
|
41
|
+
}
|
|
42
|
+
export interface SqliteChainEventLogCoverage {
|
|
43
|
+
readonly family: string;
|
|
44
|
+
readonly address: string;
|
|
45
|
+
readonly coveredFromBlock: number;
|
|
46
|
+
readonly coveredThroughBlock: number;
|
|
47
|
+
readonly floorBlock: number;
|
|
48
|
+
}
|
|
49
|
+
export interface SqliteChainEventLogState {
|
|
50
|
+
readonly cursor: SqliteChainEventLogCursor;
|
|
51
|
+
readonly coverage: readonly SqliteChainEventLogCoverage[];
|
|
52
|
+
readonly suspectedForkBlockNumber?: number;
|
|
53
|
+
}
|
|
54
|
+
export interface SqliteChainEventLogBlockRange {
|
|
55
|
+
readonly fromBlockNumber: number;
|
|
56
|
+
readonly throughBlockNumber: number;
|
|
57
|
+
}
|
|
58
|
+
export interface SqliteChainEventLogCommit {
|
|
59
|
+
readonly cursor: Omit<SqliteChainEventLogCursor, 'revision'>;
|
|
60
|
+
readonly rows: readonly SqliteChainEventLogRow[];
|
|
61
|
+
/** Blocks this commit re-fetched; the only tail it may replace. */
|
|
62
|
+
readonly replacedRange?: SqliteChainEventLogBlockRange;
|
|
63
|
+
readonly coverage: readonly SqliteChainEventLogCoverage[];
|
|
64
|
+
readonly suspectedForkBlockNumber?: number;
|
|
65
|
+
readonly clearsForkSuspicion?: boolean;
|
|
66
|
+
}
|
|
67
|
+
export interface SqliteChainEventLogQuery {
|
|
68
|
+
readonly fromBlockNumber: number;
|
|
69
|
+
readonly throughBlockNumber: number;
|
|
70
|
+
readonly addresses?: readonly string[];
|
|
71
|
+
readonly topic0?: readonly string[];
|
|
72
|
+
readonly topic1?: readonly string[];
|
|
73
|
+
}
|
|
74
|
+
export declare class SqliteChainEventLogStore {
|
|
75
|
+
private readonly db;
|
|
76
|
+
constructor(dashboard: DashboardDB);
|
|
77
|
+
load(scope: string): Promise<SqliteChainEventLogState | undefined>;
|
|
78
|
+
commit(scope: string, expectedRevision: number | undefined, commit: SqliteChainEventLogCommit): Promise<number | undefined>;
|
|
79
|
+
tombstone(scope: string, expectedRevision: number): Promise<number | undefined>;
|
|
80
|
+
readEvents(scope: string, query: SqliteChainEventLogQuery): Promise<readonly SqliteChainEventLogRow[]>;
|
|
81
|
+
blockHashAt(scope: string, blockNumber: number): Promise<string | undefined>;
|
|
82
|
+
private writeCursor;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=chain-event-log-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-event-log-store.d.ts","sourceRoot":"","sources":["../src/chain-event-log-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
const CHAIN_EVENT_LOG_ZERO_HASH = `0x${'00'.repeat(32)}`;
|
|
2
|
+
/**
|
|
3
|
+
* A tombstoned scope keeps its row so its CAS token can never repeat.
|
|
4
|
+
*
|
|
5
|
+
* The empty lineage is the tombstone: `load` refuses to return such a scope, so
|
|
6
|
+
* nothing derived from the dead chain can be served, while a fresh cold start
|
|
7
|
+
* re-initializes the SAME row at a strictly higher revision. Deleting the row
|
|
8
|
+
* instead would restart the token at 1 and let a scanner holding the old token
|
|
9
|
+
* overwrite a rebuilt log (the ABA case the authority index already guards).
|
|
10
|
+
*/
|
|
11
|
+
const TOMBSTONE_LINEAGE = '';
|
|
12
|
+
function placeholders(count) {
|
|
13
|
+
return Array.from({ length: count }, () => '?').join(', ');
|
|
14
|
+
}
|
|
15
|
+
/** The re-fetched range, or `undefined` when this commit replaces no tail. */
|
|
16
|
+
function normalizeReplacedRange(range) {
|
|
17
|
+
if (range === undefined)
|
|
18
|
+
return undefined;
|
|
19
|
+
if (!Number.isSafeInteger(range.fromBlockNumber)
|
|
20
|
+
|| !Number.isSafeInteger(range.throughBlockNumber)) {
|
|
21
|
+
throw new Error('Chain event log replaced range is invalid');
|
|
22
|
+
}
|
|
23
|
+
// An empty range is a legitimate "this pass fetched nothing", not an error:
|
|
24
|
+
// it simply replaces no tail.
|
|
25
|
+
return range.throughBlockNumber < range.fromBlockNumber ? undefined : range;
|
|
26
|
+
}
|
|
27
|
+
export class SqliteChainEventLogStore {
|
|
28
|
+
db;
|
|
29
|
+
constructor(dashboard) {
|
|
30
|
+
this.db = dashboard.db;
|
|
31
|
+
}
|
|
32
|
+
async load(scope) {
|
|
33
|
+
const row = this.db.prepare(`
|
|
34
|
+
SELECT revision, lineage, deployment_block, settled_block, settled_hash,
|
|
35
|
+
head_block, head_hash, head_timestamp_seconds, head_fetched_at_ms,
|
|
36
|
+
topic_set_version, suspected_fork_block
|
|
37
|
+
FROM chain_index_cursor
|
|
38
|
+
WHERE scope = ?
|
|
39
|
+
`).get(scope);
|
|
40
|
+
if (row === undefined || row.lineage === TOMBSTONE_LINEAGE)
|
|
41
|
+
return undefined;
|
|
42
|
+
const coverage = this.db.prepare(`
|
|
43
|
+
SELECT family, address, covered_from_block, covered_through_block, floor_block
|
|
44
|
+
FROM chain_index_coverage
|
|
45
|
+
WHERE scope = ?
|
|
46
|
+
ORDER BY family, address
|
|
47
|
+
`).all(scope);
|
|
48
|
+
return Object.freeze({
|
|
49
|
+
cursor: Object.freeze({
|
|
50
|
+
revision: row.revision,
|
|
51
|
+
lineage: row.lineage,
|
|
52
|
+
deploymentBlockNumber: row.deployment_block,
|
|
53
|
+
settledBlockNumber: row.settled_block,
|
|
54
|
+
settledBlockHash: row.settled_hash,
|
|
55
|
+
head: Object.freeze({
|
|
56
|
+
number: row.head_block,
|
|
57
|
+
hash: row.head_hash,
|
|
58
|
+
timestampSeconds: row.head_timestamp_seconds,
|
|
59
|
+
fetchedAtMs: row.head_fetched_at_ms,
|
|
60
|
+
}),
|
|
61
|
+
topicSetVersion: row.topic_set_version,
|
|
62
|
+
}),
|
|
63
|
+
coverage: Object.freeze(coverage.map((entry) => Object.freeze({
|
|
64
|
+
family: entry.family,
|
|
65
|
+
address: entry.address,
|
|
66
|
+
coveredFromBlock: entry.covered_from_block,
|
|
67
|
+
coveredThroughBlock: entry.covered_through_block,
|
|
68
|
+
floorBlock: entry.floor_block,
|
|
69
|
+
}))),
|
|
70
|
+
...(row.suspected_fork_block === null
|
|
71
|
+
? {}
|
|
72
|
+
: { suspectedForkBlockNumber: row.suspected_fork_block }),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async commit(scope, expectedRevision, commit) {
|
|
76
|
+
if (scope.trim().length === 0)
|
|
77
|
+
throw new Error('Chain event log scope is empty');
|
|
78
|
+
if (commit.cursor.lineage === TOMBSTONE_LINEAGE) {
|
|
79
|
+
throw new Error('Chain event log lineage is empty');
|
|
80
|
+
}
|
|
81
|
+
if (expectedRevision !== undefined
|
|
82
|
+
&& (!Number.isSafeInteger(expectedRevision) || expectedRevision < 1)) {
|
|
83
|
+
throw new Error('Chain event log expected revision is invalid');
|
|
84
|
+
}
|
|
85
|
+
const replaced = normalizeReplacedRange(commit.replacedRange);
|
|
86
|
+
// A tail row outside the re-fetched range would be unreachable by any later
|
|
87
|
+
// replacement, so it could only ever be dropped by a commit that did not
|
|
88
|
+
// look at its block. Refusing here keeps the invariant a property of the
|
|
89
|
+
// schema rather than of whoever wrote the caller.
|
|
90
|
+
for (const row of commit.rows) {
|
|
91
|
+
if (row.settled)
|
|
92
|
+
continue;
|
|
93
|
+
if (replaced !== undefined
|
|
94
|
+
&& row.blockNumber >= replaced.fromBlockNumber
|
|
95
|
+
&& row.blockNumber <= replaced.throughBlockNumber) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
throw new Error('Chain event log tail row falls outside the replaced range');
|
|
99
|
+
}
|
|
100
|
+
const apply = this.db.transaction(() => {
|
|
101
|
+
const revision = this.writeCursor(scope, expectedRevision, commit);
|
|
102
|
+
if (revision === undefined)
|
|
103
|
+
return undefined;
|
|
104
|
+
// The previous tail goes first, but ONLY inside the range this commit
|
|
105
|
+
// re-fetched. Coverage never shrinks, so deleting a tail block this pass
|
|
106
|
+
// did not look at would leave coverage claiming a range whose rows are
|
|
107
|
+
// gone — and a read over that range would answer "no such event".
|
|
108
|
+
if (replaced !== undefined) {
|
|
109
|
+
this.db.prepare(`
|
|
110
|
+
DELETE FROM chain_events
|
|
111
|
+
WHERE scope = ? AND settled = 0
|
|
112
|
+
AND block_number >= ? AND block_number <= ?
|
|
113
|
+
`).run(scope, replaced.fromBlockNumber, replaced.throughBlockNumber);
|
|
114
|
+
}
|
|
115
|
+
const insert = this.db.prepare(`
|
|
116
|
+
INSERT OR IGNORE INTO chain_events (
|
|
117
|
+
scope, block_number, log_index, block_hash, tx_hash, address,
|
|
118
|
+
topic0, topic1, topic2, topic3, data, settled
|
|
119
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
120
|
+
`);
|
|
121
|
+
for (const row of commit.rows) {
|
|
122
|
+
// OR IGNORE, not OR REPLACE: a settled row is written ONCE. A second
|
|
123
|
+
// write at the same (block, logIndex) would mean the settled prefix was
|
|
124
|
+
// re-fetched, which only a reorg below the tail can cause — and that is
|
|
125
|
+
// the tombstone's job, not a silent overwrite's.
|
|
126
|
+
insert.run(scope, row.blockNumber, row.logIndex, row.blockHash, row.transactionHash, row.address, row.topics[0] ?? '', row.topics[1] ?? null, row.topics[2] ?? null, row.topics[3] ?? null, row.data, row.settled ? 1 : 0);
|
|
127
|
+
}
|
|
128
|
+
const upsertCoverage = this.db.prepare(`
|
|
129
|
+
INSERT INTO chain_index_coverage (
|
|
130
|
+
scope, family, address, covered_from_block, covered_through_block,
|
|
131
|
+
floor_block, updated_at
|
|
132
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
133
|
+
ON CONFLICT(scope, family, address) DO UPDATE SET
|
|
134
|
+
covered_from_block = excluded.covered_from_block,
|
|
135
|
+
covered_through_block = excluded.covered_through_block,
|
|
136
|
+
floor_block = excluded.floor_block,
|
|
137
|
+
updated_at = excluded.updated_at
|
|
138
|
+
`);
|
|
139
|
+
for (const entry of commit.coverage) {
|
|
140
|
+
upsertCoverage.run(scope, entry.family, entry.address, entry.coveredFromBlock, entry.coveredThroughBlock, entry.floorBlock, Date.now());
|
|
141
|
+
}
|
|
142
|
+
return revision;
|
|
143
|
+
});
|
|
144
|
+
return apply();
|
|
145
|
+
}
|
|
146
|
+
async tombstone(scope, expectedRevision) {
|
|
147
|
+
if (!Number.isSafeInteger(expectedRevision) || expectedRevision < 1) {
|
|
148
|
+
throw new Error('Chain event log expected revision is invalid');
|
|
149
|
+
}
|
|
150
|
+
const nextRevision = expectedRevision + 1;
|
|
151
|
+
if (!Number.isSafeInteger(nextRevision)) {
|
|
152
|
+
throw new Error('Chain event log revision exceeds the safe integer range');
|
|
153
|
+
}
|
|
154
|
+
const apply = this.db.transaction(() => {
|
|
155
|
+
const invalidated = this.db.prepare(`
|
|
156
|
+
UPDATE chain_index_cursor
|
|
157
|
+
SET revision = ?, lineage = ?, settled_block = -1, settled_hash = '',
|
|
158
|
+
suspected_fork_block = NULL, updated_at = ?
|
|
159
|
+
WHERE scope = ? AND revision = ?
|
|
160
|
+
`).run(nextRevision, TOMBSTONE_LINEAGE, Date.now(), scope, expectedRevision).changes === 1;
|
|
161
|
+
if (!invalidated)
|
|
162
|
+
return undefined;
|
|
163
|
+
// Everything derived from the dead chain goes with the cursor. A single
|
|
164
|
+
// surviving "permanent memo" is enough to answer an id-reuse question
|
|
165
|
+
// from a chain that no longer exists.
|
|
166
|
+
for (const table of [
|
|
167
|
+
'chain_events',
|
|
168
|
+
'chain_index_coverage',
|
|
169
|
+
]) {
|
|
170
|
+
this.db.prepare(`DELETE FROM ${table} WHERE scope = ?`).run(scope);
|
|
171
|
+
}
|
|
172
|
+
return nextRevision;
|
|
173
|
+
});
|
|
174
|
+
return apply();
|
|
175
|
+
}
|
|
176
|
+
async readEvents(scope, query) {
|
|
177
|
+
const clauses = ['scope = ?', 'block_number >= ?', 'block_number <= ?'];
|
|
178
|
+
const parameters = [scope, query.fromBlockNumber, query.throughBlockNumber];
|
|
179
|
+
for (const [column, values] of [
|
|
180
|
+
['address', query.addresses],
|
|
181
|
+
['topic0', query.topic0],
|
|
182
|
+
['topic1', query.topic1],
|
|
183
|
+
]) {
|
|
184
|
+
if (values === undefined || values.length === 0)
|
|
185
|
+
continue;
|
|
186
|
+
clauses.push(`${column} IN (${placeholders(values.length)})`);
|
|
187
|
+
parameters.push(...values);
|
|
188
|
+
}
|
|
189
|
+
const rows = this.db.prepare(`
|
|
190
|
+
SELECT block_number, log_index, block_hash, tx_hash, address,
|
|
191
|
+
topic0, topic1, topic2, topic3, data, settled
|
|
192
|
+
FROM chain_events
|
|
193
|
+
WHERE ${clauses.join(' AND ')}
|
|
194
|
+
ORDER BY block_number, log_index
|
|
195
|
+
`).all(...parameters);
|
|
196
|
+
return Object.freeze(rows.map((row) => Object.freeze({
|
|
197
|
+
blockNumber: row.block_number,
|
|
198
|
+
blockHash: row.block_hash,
|
|
199
|
+
logIndex: row.log_index,
|
|
200
|
+
transactionHash: row.tx_hash,
|
|
201
|
+
address: row.address,
|
|
202
|
+
// Absent topics are omitted rather than zero-filled: a decoder must see
|
|
203
|
+
// the log's real arity, not a padded one.
|
|
204
|
+
topics: Object.freeze([row.topic0, row.topic1, row.topic2, row.topic3]
|
|
205
|
+
.filter((topic) => typeof topic === 'string' && topic.length > 0)),
|
|
206
|
+
data: row.data,
|
|
207
|
+
settled: row.settled === 1,
|
|
208
|
+
})));
|
|
209
|
+
}
|
|
210
|
+
async blockHashAt(scope, blockNumber) {
|
|
211
|
+
const cursor = this.db.prepare(`
|
|
212
|
+
SELECT settled_block, settled_hash, head_block, head_hash
|
|
213
|
+
FROM chain_index_cursor
|
|
214
|
+
WHERE scope = ? AND lineage <> ?
|
|
215
|
+
`).get(scope, TOMBSTONE_LINEAGE);
|
|
216
|
+
if (cursor?.settled_block === blockNumber
|
|
217
|
+
&& cursor.settled_hash.length > 0
|
|
218
|
+
&& cursor.settled_hash !== CHAIN_EVENT_LOG_ZERO_HASH) {
|
|
219
|
+
return cursor.settled_hash;
|
|
220
|
+
}
|
|
221
|
+
if (cursor?.head_block === blockNumber)
|
|
222
|
+
return cursor.head_hash;
|
|
223
|
+
const row = this.db.prepare(`
|
|
224
|
+
SELECT block_hash FROM chain_events
|
|
225
|
+
WHERE scope = ? AND block_number = ?
|
|
226
|
+
LIMIT 1
|
|
227
|
+
`).get(scope, blockNumber);
|
|
228
|
+
return row?.block_hash;
|
|
229
|
+
}
|
|
230
|
+
writeCursor(scope, expectedRevision, commit) {
|
|
231
|
+
const cursor = commit.cursor;
|
|
232
|
+
const suspected = commit.suspectedForkBlockNumber ?? null;
|
|
233
|
+
const now = Date.now();
|
|
234
|
+
if (expectedRevision === undefined) {
|
|
235
|
+
const inserted = this.db.prepare(`
|
|
236
|
+
INSERT INTO chain_index_cursor (
|
|
237
|
+
scope, revision, lineage, deployment_block, settled_block, settled_hash,
|
|
238
|
+
head_block, head_hash, head_timestamp_seconds, head_fetched_at_ms,
|
|
239
|
+
topic_set_version, suspected_fork_block, updated_at
|
|
240
|
+
) VALUES (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
241
|
+
ON CONFLICT(scope) DO UPDATE SET
|
|
242
|
+
revision = chain_index_cursor.revision + 1,
|
|
243
|
+
lineage = excluded.lineage,
|
|
244
|
+
deployment_block = excluded.deployment_block,
|
|
245
|
+
settled_block = excluded.settled_block,
|
|
246
|
+
settled_hash = excluded.settled_hash,
|
|
247
|
+
head_block = excluded.head_block,
|
|
248
|
+
head_hash = excluded.head_hash,
|
|
249
|
+
head_timestamp_seconds = excluded.head_timestamp_seconds,
|
|
250
|
+
head_fetched_at_ms = excluded.head_fetched_at_ms,
|
|
251
|
+
topic_set_version = excluded.topic_set_version,
|
|
252
|
+
suspected_fork_block = excluded.suspected_fork_block,
|
|
253
|
+
updated_at = excluded.updated_at
|
|
254
|
+
-- Re-initializing is allowed ONLY for a tombstoned scope. A live cursor
|
|
255
|
+
-- must lose this CAS, so a caller that thinks the scope is cold cannot
|
|
256
|
+
-- reset a cursor another pass is advancing.
|
|
257
|
+
WHERE chain_index_cursor.lineage = ''
|
|
258
|
+
`).run(scope, cursor.lineage, cursor.deploymentBlockNumber, cursor.settledBlockNumber, cursor.settledBlockHash, cursor.head.number, cursor.head.hash, cursor.head.timestampSeconds, cursor.head.fetchedAtMs, cursor.topicSetVersion, suspected, now).changes === 1;
|
|
259
|
+
if (!inserted)
|
|
260
|
+
return undefined;
|
|
261
|
+
return this.db.prepare(`SELECT revision FROM chain_index_cursor WHERE scope = ?`)
|
|
262
|
+
.get(scope).revision;
|
|
263
|
+
}
|
|
264
|
+
const nextRevision = expectedRevision + 1;
|
|
265
|
+
if (!Number.isSafeInteger(nextRevision)) {
|
|
266
|
+
throw new Error('Chain event log revision exceeds the safe integer range');
|
|
267
|
+
}
|
|
268
|
+
// STICKY. A suspicion is the tick's only memory between two passes, so a
|
|
269
|
+
// commit that says nothing about forks — a backfill page, an idle head
|
|
270
|
+
// refresh — must leave the held one alone. Writing NULL here is what let a
|
|
271
|
+
// backfill between two mismatching passes reset the two-pass rule forever.
|
|
272
|
+
const suspectedClause = commit.clearsForkSuspicion === true
|
|
273
|
+
? 'NULL'
|
|
274
|
+
: commit.suspectedForkBlockNumber === undefined
|
|
275
|
+
? 'suspected_fork_block'
|
|
276
|
+
: '?';
|
|
277
|
+
const updated = this.db.prepare(`
|
|
278
|
+
UPDATE chain_index_cursor
|
|
279
|
+
SET revision = ?, lineage = ?, deployment_block = ?, settled_block = ?,
|
|
280
|
+
settled_hash = ?, head_block = ?, head_hash = ?,
|
|
281
|
+
head_timestamp_seconds = ?, head_fetched_at_ms = ?,
|
|
282
|
+
topic_set_version = ?, suspected_fork_block = ${suspectedClause},
|
|
283
|
+
updated_at = ?
|
|
284
|
+
WHERE scope = ? AND revision = ? AND lineage <> ''
|
|
285
|
+
`).run(nextRevision, cursor.lineage, cursor.deploymentBlockNumber, cursor.settledBlockNumber, cursor.settledBlockHash, cursor.head.number, cursor.head.hash, cursor.head.timestampSeconds, cursor.head.fetchedAtMs, cursor.topicSetVersion, ...(suspectedClause === '?' ? [suspected] : []), now, scope, expectedRevision).changes === 1;
|
|
286
|
+
return updated ? nextRevision : undefined;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=chain-event-log-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-event-log-store.js","sourceRoot":"","sources":["../src/chain-event-log-store.ts"],"names":[],"mappings":"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"}
|