@xyo-network/event-kit-statement-graph 0.1.9 → 1.0.1
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/neutral/checkpointViewer.d.ts.map +1 -1
- package/dist/neutral/finalizedReplayController.d.ts.map +1 -1
- package/dist/neutral/grantReadModel.d.ts.map +1 -1
- package/dist/neutral/handshakeReadModel.d.ts.map +1 -1
- package/dist/neutral/index.mjs +81 -104
- package/dist/neutral/index.mjs.map +2 -2
- package/dist/neutral/publisherSubjectViewer.d.ts.map +1 -1
- package/dist/neutral/replayCheckpoint.d.ts.map +1 -1
- package/dist/neutral/subscriptionLifecycleView.d.ts.map +1 -1
- package/package.json +25 -25
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpointViewer.d.ts","sourceRoot":"","sources":["../../src/checkpointViewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,oBAAoB,EAIrB,MAAM,yCAAyC,CAAA;AAQhD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAmErE,+FAA+F;AAC/F,wBAAgB,oCAAoC,CAClD,UAAU,EAAE,wBAAwB,GACnC,oBAAoB,
|
|
1
|
+
{"version":3,"file":"checkpointViewer.d.ts","sourceRoot":"","sources":["../../src/checkpointViewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,oBAAoB,EAIrB,MAAM,yCAAyC,CAAA;AAQhD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAmErE,+FAA+F;AAC/F,wBAAgB,oCAAoC,CAClD,UAAU,EAAE,wBAAwB,GACnC,oBAAoB,CAmEtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finalizedReplayController.d.ts","sourceRoot":"","sources":["../../src/finalizedReplayController.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAA;AAMnF,OAAO,KAAK,EACV,UAAU,EAEX,MAAM,sCAAsC,CAAA;AAQ7C,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAA;AAM7E,OAAO,KAAK,EACV,wBAAwB,EACxB,gCAAgC,EAChC,kBAAkB,EAGnB,MAAM,uBAAuB,CAAA;AAO9B,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxB,oFAAoF;IACpF,IAAI,CAAC,UAAU,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1D;AAED,MAAM,WAAW,8BAA+B,SAAQ,gCAAgC;IACtF,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,4BAA4B,CAAA;IAC5C,0EAA0E;IAC1E,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,6BAA6B,CAAA;IACvD,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAChC;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAA;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CACvC;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,kCAAkC;IACjD,+FAA+F;IAC/F,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED,MAAM,WAAW,iCAAiC;IAChD,6EAA6E;IAC7E,MAAM,IAAI,QAAQ,CAAC,6BAA6B,CAAC,GAAG,IAAI,CAAA;IACxD,8FAA8F;IAC9F,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAA;IACjE,QAAQ,IAAI,QAAQ,CAAC,wBAAwB,CAAC,CAAA;IAC9C,MAAM,IAAI,6BAA6B,CAAA;IACvC,yFAAyF;IACzF,IAAI,CAAC,OAAO,CAAC,EAAE,kCAAkC,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAA;IAC1F,sFAAsF;IACtF,MAAM,IAAI,oBAAoB,CAAA;CAC/B;
|
|
1
|
+
{"version":3,"file":"finalizedReplayController.d.ts","sourceRoot":"","sources":["../../src/finalizedReplayController.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAA;AAMnF,OAAO,KAAK,EACV,UAAU,EAEX,MAAM,sCAAsC,CAAA;AAQ7C,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAA;AAM7E,OAAO,KAAK,EACV,wBAAwB,EACxB,gCAAgC,EAChC,kBAAkB,EAGnB,MAAM,uBAAuB,CAAA;AAO9B,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxB,oFAAoF;IACpF,IAAI,CAAC,UAAU,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1D;AAED,MAAM,WAAW,8BAA+B,SAAQ,gCAAgC;IACtF,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,4BAA4B,CAAA;IAC5C,0EAA0E;IAC1E,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,6BAA6B,CAAA;IACvD,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAChC;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAA;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CACvC;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,kCAAkC;IACjD,+FAA+F;IAC/F,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED,MAAM,WAAW,iCAAiC;IAChD,6EAA6E;IAC7E,MAAM,IAAI,QAAQ,CAAC,6BAA6B,CAAC,GAAG,IAAI,CAAA;IACxD,8FAA8F;IAC9F,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAA;IACjE,QAAQ,IAAI,QAAQ,CAAC,wBAAwB,CAAC,CAAA;IAC9C,MAAM,IAAI,6BAA6B,CAAA;IACvC,yFAAyF;IACzF,IAAI,CAAC,OAAO,CAAC,EAAE,kCAAkC,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAA;IAC1F,sFAAsF;IACtF,MAAM,IAAI,oBAAoB,CAAA;CAC/B;AA8ZD,wBAAsB,uCAAuC,CAC3D,UAAU,EAAE,8BAA8B,GACzC,OAAO,CAAC,iCAAiC,CAAC,CAwB5C;AAED,uFAAuF;AACvF,wBAAgB,yCAAyC,CACvD,OAAO,CAAC,EAAE,OAAO,GAChB,6BAA6B,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,wBAAwB,EAAE,CAAA;CAAE,CAWzF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grantReadModel.d.ts","sourceRoot":"","sources":["../../src/grantReadModel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,4BAA4B,EAC7B,MAAM,iCAAiC,CAAA;AAExC,OAAO,KAAK,EAEV,oBAAoB,EACrB,MAAM,yCAAyC,CAAA;AAMhD,MAAM,WAAW,mCAAmC;IAClD;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,mCAAmC,GAC3C,4BAA4B,
|
|
1
|
+
{"version":3,"file":"grantReadModel.d.ts","sourceRoot":"","sources":["../../src/grantReadModel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,4BAA4B,EAC7B,MAAM,iCAAiC,CAAA;AAExC,OAAO,KAAK,EAEV,oBAAoB,EACrB,MAAM,yCAAyC,CAAA;AAMhD,MAAM,WAAW,mCAAmC;IAClD;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,mCAAmC,GAC3C,4BAA4B,CAmB9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handshakeReadModel.d.ts","sourceRoot":"","sources":["../../src/handshakeReadModel.ts"],"names":[],"mappings":"AAiDA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,iCAAiC,EAWlC,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"handshakeReadModel.d.ts","sourceRoot":"","sources":["../../src/handshakeReadModel.ts"],"names":[],"mappings":"AAiDA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,iCAAiC,EAWlC,MAAM,8BAA8B,CAAA;AAsZrC,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,iCAAiC,GACzC,0BAA0B,CA2D5B"}
|
package/dist/neutral/index.mjs
CHANGED
|
@@ -20,7 +20,7 @@ function exactActiveTuple(subscriptions, binding, expectedHead) {
|
|
|
20
20
|
if (tuples.length !== 1) return;
|
|
21
21
|
const tuple = tuples[0];
|
|
22
22
|
const service = tuple.service.body;
|
|
23
|
-
if (service.authorizationChainId !== binding.route.authorizationChainId ||
|
|
23
|
+
if (service.authorizationChainId !== binding.route.authorizationChainId || service.events.every((event) => !wakeSourcesEqual(event.source, binding.route.source))) return;
|
|
24
24
|
return { selected, tuple };
|
|
25
25
|
}
|
|
26
26
|
function createActiveSourceWakeGrantAuthorizer(options) {
|
|
@@ -124,7 +124,7 @@ function buildClaims(applied) {
|
|
|
124
124
|
claims.set(key, { ...prior, lastBlock: record.block });
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
-
return sortClaims(
|
|
127
|
+
return sortClaims(claims.values().toArray());
|
|
128
128
|
}
|
|
129
129
|
function withoutSchema(body) {
|
|
130
130
|
return Object.fromEntries(Object.entries(body).filter(([key]) => key !== "schema"));
|
|
@@ -143,16 +143,12 @@ function createCheckpointStatementGraphViewer(checkpoint) {
|
|
|
143
143
|
const normalized = normalizeAddress(source);
|
|
144
144
|
return claims.filter((record) => normalizeAddress(record.source) === normalized && matchesClaim(record, query));
|
|
145
145
|
},
|
|
146
|
-
async
|
|
147
|
-
return claims.filter((record) => record.objectHash === objectHash);
|
|
148
|
-
},
|
|
146
|
+
claimsByObject: async (objectHash) => claims.filter((record) => record.objectHash === objectHash),
|
|
149
147
|
async claimsBySubject(subject, query) {
|
|
150
148
|
const normalized = normalizeAddress(subject);
|
|
151
149
|
return claims.filter((record) => normalizeAddress(record.subject) === normalized && matchesClaim(record, query));
|
|
152
150
|
},
|
|
153
|
-
async
|
|
154
|
-
return applied.filter((record) => record.txHash === txHash && record.eventHash === eventHash);
|
|
155
|
-
},
|
|
151
|
+
event: async (txHash, eventHash) => applied.filter((record) => record.txHash === txHash && record.eventHash === eventHash),
|
|
156
152
|
async events(source, query) {
|
|
157
153
|
const normalized = normalizeAddress(source);
|
|
158
154
|
return applied.filter((record) => normalizeAddress(record.source) === normalized && (query?.fromBlock === void 0 || record.block >= query.fromBlock) && (query?.toBlock === void 0 || record.block <= query.toBlock) && (query?.objectSchemaPrefix === void 0 || record.objectSchema.startsWith(query.objectSchemaPrefix)) && (query?.subject === void 0 || normalizeAddress(record.subject) === normalizeAddress(query.subject)));
|
|
@@ -176,16 +172,15 @@ function createCheckpointStatementGraphViewer(checkpoint) {
|
|
|
176
172
|
const normalized = normalizeAddress(source);
|
|
177
173
|
const records = applied.filter((record) => normalizeAddress(record.source) === normalized);
|
|
178
174
|
const blocks = records.map((record) => record.block);
|
|
175
|
+
const uniqueClaims = new Set(records.map((record) => claimKey(record.source, record.subject, record.objectHash)));
|
|
179
176
|
return {
|
|
180
|
-
claims:
|
|
177
|
+
claims: uniqueClaims.size,
|
|
181
178
|
firstBlock: blocks.length === 0 ? null : Math.min(...blocks),
|
|
182
179
|
lastBlock: blocks.length === 0 ? null : Math.max(...blocks),
|
|
183
180
|
source: normalized
|
|
184
181
|
};
|
|
185
182
|
},
|
|
186
|
-
async
|
|
187
|
-
return unresolved.find((record) => record.txHash === txHash && record.eventHash === eventHash);
|
|
188
|
-
}
|
|
183
|
+
unresolved: async (txHash, eventHash) => unresolved.find((record) => record.txHash === txHash && record.eventHash === eventHash)
|
|
189
184
|
});
|
|
190
185
|
}
|
|
191
186
|
|
|
@@ -351,8 +346,7 @@ function checkpointIdentityError(checkpoint, identity) {
|
|
|
351
346
|
if (checkpoint.floorBlock !== identity.floorBlock) return `floorBlock ${checkpoint.floorBlock} != ${identity.floorBlock}`;
|
|
352
347
|
if (checkpoint.network !== identity.network) return `network ${checkpoint.network} != ${identity.network}`;
|
|
353
348
|
if (checkpoint.sourceId !== identity.sourceId) return `sourceId ${checkpoint.sourceId} != ${identity.sourceId}`;
|
|
354
|
-
|
|
355
|
-
return void 0;
|
|
349
|
+
return checkpoint.publisher === identity.publisher ? void 0 : `publisher ${checkpoint.publisher} != ${identity.publisher}`;
|
|
356
350
|
}
|
|
357
351
|
function appliedKey(record) {
|
|
358
352
|
return `${record.txHash}:${record.eventHash}:${record.hashIndex}`;
|
|
@@ -392,13 +386,12 @@ function expectedClaimRecords(applied) {
|
|
|
392
386
|
records.set(key, { ...prior, lastBlock: event.block });
|
|
393
387
|
}
|
|
394
388
|
}
|
|
395
|
-
return sortClaimRecords(
|
|
389
|
+
return sortClaimRecords(records.values().toArray());
|
|
396
390
|
}
|
|
397
391
|
function sameClaimRecords(left, right) {
|
|
398
392
|
return left.length === right.length && left.every((record, index) => {
|
|
399
393
|
const candidate = right[index];
|
|
400
|
-
|
|
401
|
-
return record.declaredObjectSchema === candidate.declaredObjectSchema && record.firstBlock === candidate.firstBlock && record.firstEventHash === candidate.firstEventHash && record.lastBlock === candidate.lastBlock && record.objectHash === candidate.objectHash && normalizeAddress2(record.source) === normalizeAddress2(candidate.source) && normalizeAddress2(record.subject) === normalizeAddress2(candidate.subject);
|
|
394
|
+
return candidate?.objectHash === record.objectHash && record.declaredObjectSchema === candidate.declaredObjectSchema && record.firstBlock === candidate.firstBlock && record.firstEventHash === candidate.firstEventHash && record.lastBlock === candidate.lastBlock && normalizeAddress2(record.source) === normalizeAddress2(candidate.source) && normalizeAddress2(record.subject) === normalizeAddress2(candidate.subject);
|
|
402
395
|
});
|
|
403
396
|
}
|
|
404
397
|
function progressIntegrityError(checkpoint) {
|
|
@@ -421,10 +414,7 @@ function progressIntegrityError(checkpoint) {
|
|
|
421
414
|
if (indexedThrough === null && checkpoint.applied.length > 0) {
|
|
422
415
|
return "applied events exist before floorBlock has been indexed";
|
|
423
416
|
}
|
|
424
|
-
|
|
425
|
-
return "resolved bodies exist before floorBlock has been indexed";
|
|
426
|
-
}
|
|
427
|
-
return void 0;
|
|
417
|
+
return indexedThrough === null && checkpoint.bodies.length > 0 ? "resolved bodies exist before floorBlock has been indexed" : void 0;
|
|
428
418
|
}
|
|
429
419
|
function bodySetIntegrityError(checkpoint) {
|
|
430
420
|
const hashes = /* @__PURE__ */ new Set();
|
|
@@ -523,10 +513,7 @@ function scanIntegrityError(checkpoint) {
|
|
|
523
513
|
if (!sameClaimRecords(actualRecords, expectedClaimRecords(checkpoint.applied))) {
|
|
524
514
|
return "scan claim records differ from applied-event history";
|
|
525
515
|
}
|
|
526
|
-
|
|
527
|
-
return `scan watermark block ${scan.watermark.block} exceeds indexedThrough ${indexedThrough}`;
|
|
528
|
-
}
|
|
529
|
-
return watermarkIntegrityError(checkpoint);
|
|
516
|
+
return scan.watermark !== void 0 && scan.watermark.block > indexedThrough ? `scan watermark block ${scan.watermark.block} exceeds indexedThrough ${indexedThrough}` : watermarkIntegrityError(checkpoint);
|
|
530
517
|
}
|
|
531
518
|
function watermarkIntegrityError(checkpoint) {
|
|
532
519
|
const scan = checkpoint.scan;
|
|
@@ -541,7 +528,8 @@ function watermarkIntegrityError(checkpoint) {
|
|
|
541
528
|
}
|
|
542
529
|
const aboveWatermark = checkpoint.applied.find((event) => event.block > watermark.block || event.block === watermark.block && event.blockEventOrdinal.tx > watermark.ordinal.tx || event.block === watermark.block && event.blockEventOrdinal.tx === watermark.ordinal.tx && event.blockEventOrdinal.event > watermark.ordinal.event);
|
|
543
530
|
if (aboveWatermark !== void 0) return "applied event lies above the scan watermark";
|
|
544
|
-
const
|
|
531
|
+
const uniqueActualKeys = new Set(watermarkGroupEventKeys);
|
|
532
|
+
const actualKeys = uniqueActualKeys.values().toArray().toSorted();
|
|
545
533
|
if (actualKeys.length !== watermarkGroupEventKeys.length) {
|
|
546
534
|
return "scan watermark group event keys contain duplicates";
|
|
547
535
|
}
|
|
@@ -549,11 +537,9 @@ function watermarkIntegrityError(checkpoint) {
|
|
|
549
537
|
return "scan watermark group contains a malformed event key";
|
|
550
538
|
}
|
|
551
539
|
const group = checkpoint.applied.filter((event) => event.block === watermark.block && event.blockEventOrdinal.tx === watermark.ordinal.tx);
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
}
|
|
556
|
-
return void 0;
|
|
540
|
+
const uniqueExpectedKeys = new Set(group.map(eventKey2));
|
|
541
|
+
const expectedKeys = uniqueExpectedKeys.values().toArray().toSorted();
|
|
542
|
+
return expectedKeys.some((key) => !actualKeys.includes(key)) ? "scan watermark group event keys omit publisher applied-event history" : void 0;
|
|
557
543
|
}
|
|
558
544
|
function blockedIntegrityError(checkpoint) {
|
|
559
545
|
const { blocked, indexedThrough } = checkpoint;
|
|
@@ -565,10 +551,7 @@ function blockedIntegrityError(checkpoint) {
|
|
|
565
551
|
if (blocked.atBlock > checkpoint.finalizedHead) {
|
|
566
552
|
return `blocked atBlock ${blocked.atBlock} exceeds finalizedHead ${checkpoint.finalizedHead}`;
|
|
567
553
|
}
|
|
568
|
-
|
|
569
|
-
return "blocked unresolved event does not belong to blocked block";
|
|
570
|
-
}
|
|
571
|
-
return void 0;
|
|
554
|
+
return blocked.unresolvedEvents.some((event) => event.block !== blocked.atBlock) ? "blocked unresolved event does not belong to blocked block" : void 0;
|
|
572
555
|
}
|
|
573
556
|
function checkpointIntegrityError(checkpoint) {
|
|
574
557
|
return progressIntegrityError(checkpoint) ?? bodySetIntegrityError(checkpoint) ?? appliedIntegrityError(checkpoint) ?? scanIntegrityError(checkpoint) ?? blockedIntegrityError(checkpoint);
|
|
@@ -607,8 +590,7 @@ async function loadEventKitReplayCheckpoint(value, identity) {
|
|
|
607
590
|
const bodyIntegrityError = await persistedBodyIntegrityError(checkpoint);
|
|
608
591
|
if (bodyIntegrityError !== void 0) return { detail: bodyIntegrityError, status: "corrupt" };
|
|
609
592
|
const integrityError = checkpointIntegrityError(checkpoint);
|
|
610
|
-
|
|
611
|
-
return { checkpoint, status: "valid" };
|
|
593
|
+
return integrityError === void 0 ? { checkpoint, status: "valid" } : { detail: integrityError, status: "corrupt" };
|
|
612
594
|
}
|
|
613
595
|
|
|
614
596
|
// src/finalizedReplayController.ts
|
|
@@ -672,10 +654,12 @@ function corruptKey(record) {
|
|
|
672
654
|
return `${record.claimedHash ?? ""}:${record.computedHash}`;
|
|
673
655
|
}
|
|
674
656
|
function uniqueCorrupt(records) {
|
|
675
|
-
|
|
657
|
+
const unique = new Map(records.map((record) => [corruptKey(record), record]));
|
|
658
|
+
return unique.values().toArray();
|
|
676
659
|
}
|
|
677
660
|
function uniqueStrings(values) {
|
|
678
|
-
|
|
661
|
+
const unique = new Set(values);
|
|
662
|
+
return unique.values().toArray();
|
|
679
663
|
}
|
|
680
664
|
function appliedKey2(record) {
|
|
681
665
|
return `${record.txHash}:${record.eventHash}:${record.hashIndex}`;
|
|
@@ -690,7 +674,7 @@ function mergeApplied(existing, additions) {
|
|
|
690
674
|
}
|
|
691
675
|
merged.set(key, record);
|
|
692
676
|
}
|
|
693
|
-
return
|
|
677
|
+
return merged.values().toArray().toSorted((left, right) => left.block - right.block || left.blockEventOrdinal.tx - right.blockEventOrdinal.tx || left.blockEventOrdinal.event - right.blockEventOrdinal.event || left.hashIndex - right.hashIndex);
|
|
694
678
|
}
|
|
695
679
|
function mergeBodies(existing, additions) {
|
|
696
680
|
const merged = new Map(existing.map((entry) => [entry.hash, entry.body]));
|
|
@@ -701,7 +685,7 @@ function mergeBodies(existing, additions) {
|
|
|
701
685
|
}
|
|
702
686
|
merged.set(hash, body);
|
|
703
687
|
}
|
|
704
|
-
return
|
|
688
|
+
return merged.entries().map(([hash, body]) => ({ body, hash: HashZod4.parse(hash) })).toArray().toSorted((left, right) => left.hash.localeCompare(right.hash));
|
|
705
689
|
}
|
|
706
690
|
async function stageAppliedBlock(options, applied) {
|
|
707
691
|
const appliedObjectHashes = uniqueStrings(applied.map((record) => record.objectHash));
|
|
@@ -730,7 +714,10 @@ async function stageAppliedBlock(options, applied) {
|
|
|
730
714
|
...missingAttachments
|
|
731
715
|
]).map((hash) => HashZod4.parse(hash));
|
|
732
716
|
return {
|
|
733
|
-
bodies: new Map([
|
|
717
|
+
bodies: new Map([
|
|
718
|
+
...objects.bodies,
|
|
719
|
+
...attachments.bodies
|
|
720
|
+
]),
|
|
734
721
|
corrupt,
|
|
735
722
|
objectHashes
|
|
736
723
|
};
|
|
@@ -768,7 +755,11 @@ async function stageRange(options, prior, fromBlock, throughBlock, signal) {
|
|
|
768
755
|
result.unresolved.filter((event) => event.block >= fromBlock && event.block <= throughBlock),
|
|
769
756
|
(event) => event.block
|
|
770
757
|
);
|
|
771
|
-
const
|
|
758
|
+
const relevant = /* @__PURE__ */ new Set([
|
|
759
|
+
...appliedByBlock.keys(),
|
|
760
|
+
...unresolvedByBlock.keys()
|
|
761
|
+
]);
|
|
762
|
+
const relevantBlocks = relevant.values().toArray().toSorted((left, right) => left - right);
|
|
772
763
|
const bodies = /* @__PURE__ */ new Map();
|
|
773
764
|
for (const block of relevantBlocks) {
|
|
774
765
|
signal?.throwIfAborted();
|
|
@@ -822,11 +813,22 @@ var DefaultFinalizedEventKitReplayController = class {
|
|
|
822
813
|
};
|
|
823
814
|
}
|
|
824
815
|
sync(options) {
|
|
825
|
-
const
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
816
|
+
const previous = this.#syncTail;
|
|
817
|
+
const result = (async () => {
|
|
818
|
+
try {
|
|
819
|
+
await previous;
|
|
820
|
+
} catch {
|
|
821
|
+
}
|
|
822
|
+
return await this.#syncOnce(options);
|
|
823
|
+
})();
|
|
824
|
+
this.#syncTail = (async () => {
|
|
825
|
+
try {
|
|
826
|
+
await result;
|
|
827
|
+
return true;
|
|
828
|
+
} catch {
|
|
829
|
+
return false;
|
|
830
|
+
}
|
|
831
|
+
})();
|
|
830
832
|
return result;
|
|
831
833
|
}
|
|
832
834
|
viewer() {
|
|
@@ -845,7 +847,7 @@ var DefaultFinalizedEventKitReplayController = class {
|
|
|
845
847
|
signal?.throwIfAborted();
|
|
846
848
|
if (exact.blocked === void 0) {
|
|
847
849
|
await this.#commitStaged(exact, blockedAt, finalizedHead, signal);
|
|
848
|
-
return blockedAt
|
|
850
|
+
return blockedAt !== throughBlock && await this.#commitRange(blockedAt + 1, throughBlock, finalizedHead, signal);
|
|
849
851
|
}
|
|
850
852
|
const blocked = EventKitReplayCheckpointZod.parse({
|
|
851
853
|
...this.#checkpoint,
|
|
@@ -894,7 +896,7 @@ var DefaultFinalizedEventKitReplayController = class {
|
|
|
894
896
|
let next = indexedThrough === null ? this.#options.floorBlock : indexedThrough + 1;
|
|
895
897
|
const remaining = next <= finalizedHead ? finalizedHead - next + 1 : 0;
|
|
896
898
|
const budget = maxBlocks === void 0 ? remaining : Math.min(maxBlocks, remaining);
|
|
897
|
-
const target = budget === 0 ?
|
|
899
|
+
const target = next + (budget === 0 ? -1 : budget - 1);
|
|
898
900
|
const checkpointBatchSize = requirePositiveInteger(
|
|
899
901
|
this.#options.checkpointBatchSize,
|
|
900
902
|
DEFAULT_CHECKPOINT_BATCH_SIZE,
|
|
@@ -946,9 +948,7 @@ function createMemoryEventKitReplayCheckpointStore(initial) {
|
|
|
946
948
|
let value = initial;
|
|
947
949
|
const saved = [];
|
|
948
950
|
return {
|
|
949
|
-
async
|
|
950
|
-
return value;
|
|
951
|
-
},
|
|
951
|
+
load: async () => value,
|
|
952
952
|
async save(checkpoint) {
|
|
953
953
|
value = checkpoint;
|
|
954
954
|
saved.push(checkpoint);
|
|
@@ -963,9 +963,7 @@ import { XyoAddressZod } from "@xyo-network/sdk-protocol/address";
|
|
|
963
963
|
function createStatementGraphGrantReadModel(options) {
|
|
964
964
|
const { viewer } = options;
|
|
965
965
|
return Object.freeze({
|
|
966
|
-
async head()
|
|
967
|
-
return await viewer.head();
|
|
968
|
-
},
|
|
966
|
+
head: async () => await viewer.head(),
|
|
969
967
|
async claims(source, query) {
|
|
970
968
|
const records = await viewer.claims(XyoAddressZod.parse(source), toClaimQuery(query));
|
|
971
969
|
return Object.freeze(records.map(toGrantClaim));
|
|
@@ -1079,7 +1077,7 @@ function earliestByHash(records) {
|
|
|
1079
1077
|
result.set(record.objectHash, record);
|
|
1080
1078
|
}
|
|
1081
1079
|
}
|
|
1082
|
-
return
|
|
1080
|
+
return result.values().toArray();
|
|
1083
1081
|
}
|
|
1084
1082
|
async function verifiedHandshakeObjectBody(viewer, record) {
|
|
1085
1083
|
const object = await viewer.object(record.objectHash);
|
|
@@ -1160,7 +1158,7 @@ async function buildHandshakeCatalogs(viewer, publisher) {
|
|
|
1160
1158
|
}));
|
|
1161
1159
|
return {
|
|
1162
1160
|
keyByHash,
|
|
1163
|
-
keyLifecycles:
|
|
1161
|
+
keyLifecycles: keyByHash.values().map((key) => ({
|
|
1164
1162
|
claimedAtBlock: key.evidence.block,
|
|
1165
1163
|
expiresAtBlock: key.body.expiresAtBlock,
|
|
1166
1164
|
keyId: key.body.keyId,
|
|
@@ -1168,9 +1166,9 @@ async function buildHandshakeCatalogs(viewer, publisher) {
|
|
|
1168
1166
|
revokedAtBlock: key.revokedAtBlock,
|
|
1169
1167
|
source: key.evidence.source,
|
|
1170
1168
|
validFromBlock: key.body.validFromBlock
|
|
1171
|
-
})),
|
|
1169
|
+
})).toArray(),
|
|
1172
1170
|
serviceByHash,
|
|
1173
|
-
serviceLifecycles:
|
|
1171
|
+
serviceLifecycles: serviceByHash.values().map((service) => ({
|
|
1174
1172
|
claimedAtBlock: service.evidence.block,
|
|
1175
1173
|
encryptionKeys: service.body.encryptionKeys,
|
|
1176
1174
|
eventKinds: service.body.events.map((event) => event.kind),
|
|
@@ -1183,7 +1181,7 @@ async function buildHandshakeCatalogs(viewer, publisher) {
|
|
|
1183
1181
|
source: service.evidence.source,
|
|
1184
1182
|
supersedes: service.body.supersedes,
|
|
1185
1183
|
validFromBlock: service.body.validFromBlock
|
|
1186
|
-
}))
|
|
1184
|
+
})).toArray()
|
|
1187
1185
|
};
|
|
1188
1186
|
}
|
|
1189
1187
|
async function viewHead(viewer, finalizedHead) {
|
|
@@ -1328,34 +1326,15 @@ function publisherSubjectViewer(viewer, publisher) {
|
|
|
1328
1326
|
const filterClaims = async (records) => (await records).filter((record) => isPublisherSubject(record.subject, publisher));
|
|
1329
1327
|
const filterEvents = async (records) => (await records).filter((record) => isPublisherSubject(record.subject, publisher));
|
|
1330
1328
|
return Object.freeze({
|
|
1331
|
-
async claims(source, query)
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
async
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
async
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
},
|
|
1341
|
-
async event(txHash, eventHash) {
|
|
1342
|
-
return await filterEvents(viewer.event(txHash, eventHash));
|
|
1343
|
-
},
|
|
1344
|
-
async events(source, query) {
|
|
1345
|
-
return await filterEvents(viewer.events(source, eventQuery(query)));
|
|
1346
|
-
},
|
|
1347
|
-
async head() {
|
|
1348
|
-
return await viewer.head();
|
|
1349
|
-
},
|
|
1350
|
-
async object(objectHash) {
|
|
1351
|
-
return await viewer.object(objectHash);
|
|
1352
|
-
},
|
|
1353
|
-
async source(source) {
|
|
1354
|
-
return await viewer.source(source);
|
|
1355
|
-
},
|
|
1356
|
-
async unresolved(txHash, eventHash) {
|
|
1357
|
-
return await viewer.unresolved(txHash, eventHash);
|
|
1358
|
-
}
|
|
1329
|
+
claims: async (source, query) => await filterClaims(viewer.claims(source, claimQuery(query))),
|
|
1330
|
+
claimsByObject: async (objectHash) => await filterClaims(viewer.claimsBySubject(publisher, claimQuery({ objectHash }))),
|
|
1331
|
+
claimsBySubject: async (subject, query) => isPublisherSubject(subject, publisher) ? await filterClaims(viewer.claimsBySubject(publisher, claimQuery(query))) : [],
|
|
1332
|
+
event: async (txHash, eventHash) => await filterEvents(viewer.event(txHash, eventHash)),
|
|
1333
|
+
events: async (source, query) => await filterEvents(viewer.events(source, eventQuery(query))),
|
|
1334
|
+
head: async () => await viewer.head(),
|
|
1335
|
+
object: async (objectHash) => await viewer.object(objectHash),
|
|
1336
|
+
source: async (source) => await viewer.source(source),
|
|
1337
|
+
unresolved: async (txHash, eventHash) => await viewer.unresolved(txHash, eventHash)
|
|
1359
1338
|
});
|
|
1360
1339
|
}
|
|
1361
1340
|
|
|
@@ -1363,17 +1342,16 @@ function publisherSubjectViewer(viewer, publisher) {
|
|
|
1363
1342
|
import { selectSubscriptionActivation } from "@xyo-network/event-kit-protocol";
|
|
1364
1343
|
function inactiveState(tuples, acceptances, finalizedHead) {
|
|
1365
1344
|
const subscriptionHashes = new Set(tuples.map((tuple) => tuple.subscription.objectHash));
|
|
1366
|
-
if (tuples.some((tuple) => (tuple.grantRevokedAtBlock ??
|
|
1345
|
+
if (tuples.some((tuple) => (tuple.grantRevokedAtBlock ?? Infinity) <= finalizedHead) || tuples.some((tuple) => (tuple.subscription.revokedAtBlock ?? Infinity) <= finalizedHead) || acceptances.some((item) => subscriptionHashes.has(item.lifecycle.subscription) && (item.lifecycle.revokedAtBlock ?? Infinity) <= finalizedHead)) {
|
|
1367
1346
|
return "revoked";
|
|
1368
1347
|
}
|
|
1369
|
-
|
|
1370
|
-
return "inactive";
|
|
1348
|
+
return tuples.every((tuple) => tuple.subscription.body.expiresAtBlock <= finalizedHead) ? "expired" : "inactive";
|
|
1371
1349
|
}
|
|
1372
1350
|
function pendingState(tuples, acceptances, finalizedHead) {
|
|
1373
1351
|
const latest = tuples.reduce((selected, candidate) => selected === void 0 || candidate.subscriptionLifecycle.revision > selected.subscriptionLifecycle.revision ? candidate : selected, void 0);
|
|
1374
1352
|
if (latest === void 0) return "inactive";
|
|
1375
1353
|
const matchingAcceptances = acceptances.filter((item) => item.lifecycle.subscription === latest.subscription.objectHash);
|
|
1376
|
-
if ((latest.grantRevokedAtBlock ??
|
|
1354
|
+
if ((latest.grantRevokedAtBlock ?? Infinity) <= finalizedHead || (latest.subscription.revokedAtBlock ?? Infinity) <= finalizedHead || matchingAcceptances.some((item) => (item.lifecycle.revokedAtBlock ?? Infinity) <= finalizedHead)) {
|
|
1377
1355
|
return "revoked";
|
|
1378
1356
|
}
|
|
1379
1357
|
return latest.subscription.body.expiresAtBlock <= finalizedHead ? "expired" : "pending";
|
|
@@ -1527,14 +1505,14 @@ async function validateTuple(viewer, records, subscriber, service, catalogs, cha
|
|
|
1527
1505
|
if (!subscriptionParsed.success) return reject("malformed-subscription");
|
|
1528
1506
|
const grant = grantParsed.data;
|
|
1529
1507
|
const subscription = subscriptionParsed.data;
|
|
1530
|
-
const tupleBlock = subscriptionRecord.block;
|
|
1531
1508
|
if (!hasMatchingHandshakeProfile(service.body, subscription, chainId)) return reject("subscription-binding-invalid");
|
|
1532
1509
|
if (!hasExactGrantBinding(grant, publisher)) return reject("grant-binding-invalid");
|
|
1533
1510
|
if (!hasExactSubscriptionBinding(subscription, chainId, publisher, service.objectHash, grantRecord.objectHash)) {
|
|
1534
1511
|
return reject("subscription-binding-invalid");
|
|
1535
1512
|
}
|
|
1536
|
-
const
|
|
1513
|
+
const tupleBlock = subscriptionRecord.block;
|
|
1537
1514
|
if (service.evidence.block >= tupleBlock) return reject("service-inactive-at-claim");
|
|
1515
|
+
const claimedKey = catalogs.keyByHash.get(subscription.encryptionKey);
|
|
1538
1516
|
if (claimedKey === void 0 || claimedKey.evidence.block >= tupleBlock) return reject("key-binding-invalid");
|
|
1539
1517
|
if (!exactHandshakeServiceAt(catalogs, service, publisher, tupleBlock)) return reject("service-inactive-at-claim");
|
|
1540
1518
|
if (!hasExactKeyBinding(subscription, service, catalogs, tupleBlock)) return reject("key-binding-invalid");
|
|
@@ -1575,7 +1553,10 @@ async function validateTuple(viewer, records, subscriber, service, catalogs, cha
|
|
|
1575
1553
|
async function discoverTuples(viewer, services, catalogs, query, candidateSources) {
|
|
1576
1554
|
const serviceByHash = new Map(services.map((service) => [service.objectHash, service]));
|
|
1577
1555
|
const serviceHashes = new Set(serviceByHash.keys());
|
|
1578
|
-
const
|
|
1556
|
+
const uniqueSources = new Set(
|
|
1557
|
+
candidateSources ?? (await viewer.claimsBySubject(XyoAddressZod3.parse(query.publisher))).filter((claim) => serviceHashes.has(claim.objectHash)).map((claim) => claim.source)
|
|
1558
|
+
);
|
|
1559
|
+
const sources = uniqueSources.values().filter((source) => !isPublisherSubject(source, query.publisher)).toArray();
|
|
1579
1560
|
const tuples = /* @__PURE__ */ new Map();
|
|
1580
1561
|
const rejections = [];
|
|
1581
1562
|
for (const source of sources) {
|
|
@@ -1609,7 +1590,7 @@ async function discoverTuples(viewer, services, catalogs, query, candidateSource
|
|
|
1609
1590
|
}
|
|
1610
1591
|
}
|
|
1611
1592
|
}
|
|
1612
|
-
return { rejections, tuples:
|
|
1593
|
+
return { rejections, tuples: tuples.values().toArray() };
|
|
1613
1594
|
}
|
|
1614
1595
|
function challengeMatchesTuple(challenge, response, acceptance, tuple, chainId, publisher) {
|
|
1615
1596
|
return challenge.chainId === chainId && challenge.publisher === publisher && challenge.subscriber === tuple.subscriber && challenge.service === tuple.service.objectHash && challenge.encryptionKey === tuple.subscription.body.encryptionKey && challenge.keyId === tuple.subscription.body.keyId && challenge.subscription === tuple.subscription.objectHash && challenge.grant === tuple.grant.objectHash && challenge.eventKind === tuple.subscription.body.eventKind && response.challenge === acceptance.challenge;
|
|
@@ -1663,7 +1644,7 @@ async function handshakeLifecycle(options, rawQuery, candidateSources, subscript
|
|
|
1663
1644
|
const scopedOptions = publisherSubjectOptions(options, rawQuery.publisher);
|
|
1664
1645
|
const discovery = await discoverHandshakeService(scopedOptions, rawQuery);
|
|
1665
1646
|
if (discovery.catalogs === void 0) return { discovery };
|
|
1666
|
-
const serviceRevisions =
|
|
1647
|
+
const serviceRevisions = discovery.catalogs.serviceByHash.values().filter((service) => service.evidence.source === discovery.query.publisher && (discovery.query.serviceId === void 0 || service.body.serviceId === discovery.query.serviceId) && service.body.events.some((event) => event.kind === discovery.query.eventKind) && service.evidence.block <= discovery.query.finalizedHead).toArray();
|
|
1667
1648
|
const found = await discoverTuples(
|
|
1668
1649
|
scopedOptions.viewer,
|
|
1669
1650
|
serviceRevisions,
|
|
@@ -1765,12 +1746,8 @@ function createEventKitHandshakeReadModel(options) {
|
|
|
1765
1746
|
subscriptions: projection.subscriptions
|
|
1766
1747
|
};
|
|
1767
1748
|
},
|
|
1768
|
-
async
|
|
1769
|
-
|
|
1770
|
-
},
|
|
1771
|
-
async publisher(query) {
|
|
1772
|
-
return handshakeView(await handshakeLifecycle(options, query));
|
|
1773
|
-
},
|
|
1749
|
+
discoverPublisherService: async (query) => (await discoverHandshakeService(publisherSubjectOptions(options, query.publisher), query)).result,
|
|
1750
|
+
publisher: async (query) => handshakeView(await handshakeLifecycle(options, query)),
|
|
1774
1751
|
async subscriber(rawQuery) {
|
|
1775
1752
|
const subscriber = NormalizedAddressZod5.parse(rawQuery.subscriber);
|
|
1776
1753
|
const subscriptionId = rawQuery.subscriptionId === void 0 ? void 0 : HandshakeIdZod.parse(rawQuery.subscriptionId);
|