@xyo-network/event-kit-statement-graph 0.1.9 → 1.0.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/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 +71 -75
- 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/package.json +20 -20
|
@@ -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;AAgaD,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
|
|
|
@@ -392,7 +387,7 @@ function expectedClaimRecords(applied) {
|
|
|
392
387
|
records.set(key, { ...prior, lastBlock: event.block });
|
|
393
388
|
}
|
|
394
389
|
}
|
|
395
|
-
return sortClaimRecords(
|
|
390
|
+
return sortClaimRecords(records.values().toArray());
|
|
396
391
|
}
|
|
397
392
|
function sameClaimRecords(left, right) {
|
|
398
393
|
return left.length === right.length && left.every((record, index) => {
|
|
@@ -541,7 +536,8 @@ function watermarkIntegrityError(checkpoint) {
|
|
|
541
536
|
}
|
|
542
537
|
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
538
|
if (aboveWatermark !== void 0) return "applied event lies above the scan watermark";
|
|
544
|
-
const
|
|
539
|
+
const uniqueActualKeys = new Set(watermarkGroupEventKeys);
|
|
540
|
+
const actualKeys = uniqueActualKeys.values().toArray().toSorted();
|
|
545
541
|
if (actualKeys.length !== watermarkGroupEventKeys.length) {
|
|
546
542
|
return "scan watermark group event keys contain duplicates";
|
|
547
543
|
}
|
|
@@ -549,7 +545,8 @@ function watermarkIntegrityError(checkpoint) {
|
|
|
549
545
|
return "scan watermark group contains a malformed event key";
|
|
550
546
|
}
|
|
551
547
|
const group = checkpoint.applied.filter((event) => event.block === watermark.block && event.blockEventOrdinal.tx === watermark.ordinal.tx);
|
|
552
|
-
const
|
|
548
|
+
const uniqueExpectedKeys = new Set(group.map(eventKey2));
|
|
549
|
+
const expectedKeys = uniqueExpectedKeys.values().toArray().toSorted();
|
|
553
550
|
if (expectedKeys.some((key) => !actualKeys.includes(key))) {
|
|
554
551
|
return "scan watermark group event keys omit publisher applied-event history";
|
|
555
552
|
}
|
|
@@ -672,10 +669,12 @@ function corruptKey(record) {
|
|
|
672
669
|
return `${record.claimedHash ?? ""}:${record.computedHash}`;
|
|
673
670
|
}
|
|
674
671
|
function uniqueCorrupt(records) {
|
|
675
|
-
|
|
672
|
+
const unique = new Map(records.map((record) => [corruptKey(record), record]));
|
|
673
|
+
return unique.values().toArray();
|
|
676
674
|
}
|
|
677
675
|
function uniqueStrings(values) {
|
|
678
|
-
|
|
676
|
+
const unique = new Set(values);
|
|
677
|
+
return unique.values().toArray();
|
|
679
678
|
}
|
|
680
679
|
function appliedKey2(record) {
|
|
681
680
|
return `${record.txHash}:${record.eventHash}:${record.hashIndex}`;
|
|
@@ -690,7 +689,7 @@ function mergeApplied(existing, additions) {
|
|
|
690
689
|
}
|
|
691
690
|
merged.set(key, record);
|
|
692
691
|
}
|
|
693
|
-
return
|
|
692
|
+
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
693
|
}
|
|
695
694
|
function mergeBodies(existing, additions) {
|
|
696
695
|
const merged = new Map(existing.map((entry) => [entry.hash, entry.body]));
|
|
@@ -701,7 +700,7 @@ function mergeBodies(existing, additions) {
|
|
|
701
700
|
}
|
|
702
701
|
merged.set(hash, body);
|
|
703
702
|
}
|
|
704
|
-
return
|
|
703
|
+
return merged.entries().map(([hash, body]) => ({ body, hash: HashZod4.parse(hash) })).toArray().toSorted((left, right) => left.hash.localeCompare(right.hash));
|
|
705
704
|
}
|
|
706
705
|
async function stageAppliedBlock(options, applied) {
|
|
707
706
|
const appliedObjectHashes = uniqueStrings(applied.map((record) => record.objectHash));
|
|
@@ -730,7 +729,10 @@ async function stageAppliedBlock(options, applied) {
|
|
|
730
729
|
...missingAttachments
|
|
731
730
|
]).map((hash) => HashZod4.parse(hash));
|
|
732
731
|
return {
|
|
733
|
-
bodies: new Map([
|
|
732
|
+
bodies: new Map([
|
|
733
|
+
...objects.bodies,
|
|
734
|
+
...attachments.bodies
|
|
735
|
+
]),
|
|
734
736
|
corrupt,
|
|
735
737
|
objectHashes
|
|
736
738
|
};
|
|
@@ -768,7 +770,11 @@ async function stageRange(options, prior, fromBlock, throughBlock, signal) {
|
|
|
768
770
|
result.unresolved.filter((event) => event.block >= fromBlock && event.block <= throughBlock),
|
|
769
771
|
(event) => event.block
|
|
770
772
|
);
|
|
771
|
-
const
|
|
773
|
+
const relevant = /* @__PURE__ */ new Set([
|
|
774
|
+
...appliedByBlock.keys(),
|
|
775
|
+
...unresolvedByBlock.keys()
|
|
776
|
+
]);
|
|
777
|
+
const relevantBlocks = relevant.values().toArray().toSorted((left, right) => left - right);
|
|
772
778
|
const bodies = /* @__PURE__ */ new Map();
|
|
773
779
|
for (const block of relevantBlocks) {
|
|
774
780
|
signal?.throwIfAborted();
|
|
@@ -822,11 +828,22 @@ var DefaultFinalizedEventKitReplayController = class {
|
|
|
822
828
|
};
|
|
823
829
|
}
|
|
824
830
|
sync(options) {
|
|
825
|
-
const
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
831
|
+
const previous = this.#syncTail;
|
|
832
|
+
const result = (async () => {
|
|
833
|
+
try {
|
|
834
|
+
await previous;
|
|
835
|
+
} catch {
|
|
836
|
+
}
|
|
837
|
+
return await this.#syncOnce(options);
|
|
838
|
+
})();
|
|
839
|
+
this.#syncTail = (async () => {
|
|
840
|
+
try {
|
|
841
|
+
await result;
|
|
842
|
+
return true;
|
|
843
|
+
} catch {
|
|
844
|
+
return false;
|
|
845
|
+
}
|
|
846
|
+
})();
|
|
830
847
|
return result;
|
|
831
848
|
}
|
|
832
849
|
viewer() {
|
|
@@ -894,7 +911,7 @@ var DefaultFinalizedEventKitReplayController = class {
|
|
|
894
911
|
let next = indexedThrough === null ? this.#options.floorBlock : indexedThrough + 1;
|
|
895
912
|
const remaining = next <= finalizedHead ? finalizedHead - next + 1 : 0;
|
|
896
913
|
const budget = maxBlocks === void 0 ? remaining : Math.min(maxBlocks, remaining);
|
|
897
|
-
const target = budget === 0 ?
|
|
914
|
+
const target = next + (budget === 0 ? -1 : budget - 1);
|
|
898
915
|
const checkpointBatchSize = requirePositiveInteger(
|
|
899
916
|
this.#options.checkpointBatchSize,
|
|
900
917
|
DEFAULT_CHECKPOINT_BATCH_SIZE,
|
|
@@ -946,9 +963,7 @@ function createMemoryEventKitReplayCheckpointStore(initial) {
|
|
|
946
963
|
let value = initial;
|
|
947
964
|
const saved = [];
|
|
948
965
|
return {
|
|
949
|
-
async
|
|
950
|
-
return value;
|
|
951
|
-
},
|
|
966
|
+
load: async () => value,
|
|
952
967
|
async save(checkpoint) {
|
|
953
968
|
value = checkpoint;
|
|
954
969
|
saved.push(checkpoint);
|
|
@@ -963,9 +978,7 @@ import { XyoAddressZod } from "@xyo-network/sdk-protocol/address";
|
|
|
963
978
|
function createStatementGraphGrantReadModel(options) {
|
|
964
979
|
const { viewer } = options;
|
|
965
980
|
return Object.freeze({
|
|
966
|
-
async head()
|
|
967
|
-
return await viewer.head();
|
|
968
|
-
},
|
|
981
|
+
head: async () => await viewer.head(),
|
|
969
982
|
async claims(source, query) {
|
|
970
983
|
const records = await viewer.claims(XyoAddressZod.parse(source), toClaimQuery(query));
|
|
971
984
|
return Object.freeze(records.map(toGrantClaim));
|
|
@@ -1079,7 +1092,7 @@ function earliestByHash(records) {
|
|
|
1079
1092
|
result.set(record.objectHash, record);
|
|
1080
1093
|
}
|
|
1081
1094
|
}
|
|
1082
|
-
return
|
|
1095
|
+
return result.values().toArray();
|
|
1083
1096
|
}
|
|
1084
1097
|
async function verifiedHandshakeObjectBody(viewer, record) {
|
|
1085
1098
|
const object = await viewer.object(record.objectHash);
|
|
@@ -1160,7 +1173,7 @@ async function buildHandshakeCatalogs(viewer, publisher) {
|
|
|
1160
1173
|
}));
|
|
1161
1174
|
return {
|
|
1162
1175
|
keyByHash,
|
|
1163
|
-
keyLifecycles:
|
|
1176
|
+
keyLifecycles: keyByHash.values().map((key) => ({
|
|
1164
1177
|
claimedAtBlock: key.evidence.block,
|
|
1165
1178
|
expiresAtBlock: key.body.expiresAtBlock,
|
|
1166
1179
|
keyId: key.body.keyId,
|
|
@@ -1168,9 +1181,9 @@ async function buildHandshakeCatalogs(viewer, publisher) {
|
|
|
1168
1181
|
revokedAtBlock: key.revokedAtBlock,
|
|
1169
1182
|
source: key.evidence.source,
|
|
1170
1183
|
validFromBlock: key.body.validFromBlock
|
|
1171
|
-
})),
|
|
1184
|
+
})).toArray(),
|
|
1172
1185
|
serviceByHash,
|
|
1173
|
-
serviceLifecycles:
|
|
1186
|
+
serviceLifecycles: serviceByHash.values().map((service) => ({
|
|
1174
1187
|
claimedAtBlock: service.evidence.block,
|
|
1175
1188
|
encryptionKeys: service.body.encryptionKeys,
|
|
1176
1189
|
eventKinds: service.body.events.map((event) => event.kind),
|
|
@@ -1183,7 +1196,7 @@ async function buildHandshakeCatalogs(viewer, publisher) {
|
|
|
1183
1196
|
source: service.evidence.source,
|
|
1184
1197
|
supersedes: service.body.supersedes,
|
|
1185
1198
|
validFromBlock: service.body.validFromBlock
|
|
1186
|
-
}))
|
|
1199
|
+
})).toArray()
|
|
1187
1200
|
};
|
|
1188
1201
|
}
|
|
1189
1202
|
async function viewHead(viewer, finalizedHead) {
|
|
@@ -1328,34 +1341,18 @@ function publisherSubjectViewer(viewer, publisher) {
|
|
|
1328
1341
|
const filterClaims = async (records) => (await records).filter((record) => isPublisherSubject(record.subject, publisher));
|
|
1329
1342
|
const filterEvents = async (records) => (await records).filter((record) => isPublisherSubject(record.subject, publisher));
|
|
1330
1343
|
return Object.freeze({
|
|
1331
|
-
async claims(source, query)
|
|
1332
|
-
|
|
1333
|
-
},
|
|
1334
|
-
async claimsByObject(objectHash) {
|
|
1335
|
-
return await filterClaims(viewer.claimsBySubject(publisher, claimQuery({ objectHash })));
|
|
1336
|
-
},
|
|
1344
|
+
claims: async (source, query) => await filterClaims(viewer.claims(source, claimQuery(query))),
|
|
1345
|
+
claimsByObject: async (objectHash) => await filterClaims(viewer.claimsBySubject(publisher, claimQuery({ objectHash }))),
|
|
1337
1346
|
async claimsBySubject(subject, query) {
|
|
1338
1347
|
if (!isPublisherSubject(subject, publisher)) return [];
|
|
1339
1348
|
return await filterClaims(viewer.claimsBySubject(publisher, claimQuery(query)));
|
|
1340
1349
|
},
|
|
1341
|
-
async event(txHash, eventHash)
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
async
|
|
1345
|
-
|
|
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
|
-
}
|
|
1350
|
+
event: async (txHash, eventHash) => await filterEvents(viewer.event(txHash, eventHash)),
|
|
1351
|
+
events: async (source, query) => await filterEvents(viewer.events(source, eventQuery(query))),
|
|
1352
|
+
head: async () => await viewer.head(),
|
|
1353
|
+
object: async (objectHash) => await viewer.object(objectHash),
|
|
1354
|
+
source: async (source) => await viewer.source(source),
|
|
1355
|
+
unresolved: async (txHash, eventHash) => await viewer.unresolved(txHash, eventHash)
|
|
1359
1356
|
});
|
|
1360
1357
|
}
|
|
1361
1358
|
|
|
@@ -1363,7 +1360,7 @@ function publisherSubjectViewer(viewer, publisher) {
|
|
|
1363
1360
|
import { selectSubscriptionActivation } from "@xyo-network/event-kit-protocol";
|
|
1364
1361
|
function inactiveState(tuples, acceptances, finalizedHead) {
|
|
1365
1362
|
const subscriptionHashes = new Set(tuples.map((tuple) => tuple.subscription.objectHash));
|
|
1366
|
-
if (tuples.some((tuple) => (tuple.grantRevokedAtBlock ??
|
|
1363
|
+
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
1364
|
return "revoked";
|
|
1368
1365
|
}
|
|
1369
1366
|
if (tuples.every((tuple) => tuple.subscription.body.expiresAtBlock <= finalizedHead)) return "expired";
|
|
@@ -1373,7 +1370,7 @@ function pendingState(tuples, acceptances, finalizedHead) {
|
|
|
1373
1370
|
const latest = tuples.reduce((selected, candidate) => selected === void 0 || candidate.subscriptionLifecycle.revision > selected.subscriptionLifecycle.revision ? candidate : selected, void 0);
|
|
1374
1371
|
if (latest === void 0) return "inactive";
|
|
1375
1372
|
const matchingAcceptances = acceptances.filter((item) => item.lifecycle.subscription === latest.subscription.objectHash);
|
|
1376
|
-
if ((latest.grantRevokedAtBlock ??
|
|
1373
|
+
if ((latest.grantRevokedAtBlock ?? Infinity) <= finalizedHead || (latest.subscription.revokedAtBlock ?? Infinity) <= finalizedHead || matchingAcceptances.some((item) => (item.lifecycle.revokedAtBlock ?? Infinity) <= finalizedHead)) {
|
|
1377
1374
|
return "revoked";
|
|
1378
1375
|
}
|
|
1379
1376
|
return latest.subscription.body.expiresAtBlock <= finalizedHead ? "expired" : "pending";
|
|
@@ -1527,14 +1524,14 @@ async function validateTuple(viewer, records, subscriber, service, catalogs, cha
|
|
|
1527
1524
|
if (!subscriptionParsed.success) return reject("malformed-subscription");
|
|
1528
1525
|
const grant = grantParsed.data;
|
|
1529
1526
|
const subscription = subscriptionParsed.data;
|
|
1530
|
-
const tupleBlock = subscriptionRecord.block;
|
|
1531
1527
|
if (!hasMatchingHandshakeProfile(service.body, subscription, chainId)) return reject("subscription-binding-invalid");
|
|
1532
1528
|
if (!hasExactGrantBinding(grant, publisher)) return reject("grant-binding-invalid");
|
|
1533
1529
|
if (!hasExactSubscriptionBinding(subscription, chainId, publisher, service.objectHash, grantRecord.objectHash)) {
|
|
1534
1530
|
return reject("subscription-binding-invalid");
|
|
1535
1531
|
}
|
|
1536
|
-
const
|
|
1532
|
+
const tupleBlock = subscriptionRecord.block;
|
|
1537
1533
|
if (service.evidence.block >= tupleBlock) return reject("service-inactive-at-claim");
|
|
1534
|
+
const claimedKey = catalogs.keyByHash.get(subscription.encryptionKey);
|
|
1538
1535
|
if (claimedKey === void 0 || claimedKey.evidence.block >= tupleBlock) return reject("key-binding-invalid");
|
|
1539
1536
|
if (!exactHandshakeServiceAt(catalogs, service, publisher, tupleBlock)) return reject("service-inactive-at-claim");
|
|
1540
1537
|
if (!hasExactKeyBinding(subscription, service, catalogs, tupleBlock)) return reject("key-binding-invalid");
|
|
@@ -1575,7 +1572,10 @@ async function validateTuple(viewer, records, subscriber, service, catalogs, cha
|
|
|
1575
1572
|
async function discoverTuples(viewer, services, catalogs, query, candidateSources) {
|
|
1576
1573
|
const serviceByHash = new Map(services.map((service) => [service.objectHash, service]));
|
|
1577
1574
|
const serviceHashes = new Set(serviceByHash.keys());
|
|
1578
|
-
const
|
|
1575
|
+
const uniqueSources = new Set(
|
|
1576
|
+
candidateSources ?? (await viewer.claimsBySubject(XyoAddressZod3.parse(query.publisher))).filter((claim) => serviceHashes.has(claim.objectHash)).map((claim) => claim.source)
|
|
1577
|
+
);
|
|
1578
|
+
const sources = uniqueSources.values().filter((source) => !isPublisherSubject(source, query.publisher)).toArray();
|
|
1579
1579
|
const tuples = /* @__PURE__ */ new Map();
|
|
1580
1580
|
const rejections = [];
|
|
1581
1581
|
for (const source of sources) {
|
|
@@ -1609,7 +1609,7 @@ async function discoverTuples(viewer, services, catalogs, query, candidateSource
|
|
|
1609
1609
|
}
|
|
1610
1610
|
}
|
|
1611
1611
|
}
|
|
1612
|
-
return { rejections, tuples:
|
|
1612
|
+
return { rejections, tuples: tuples.values().toArray() };
|
|
1613
1613
|
}
|
|
1614
1614
|
function challengeMatchesTuple(challenge, response, acceptance, tuple, chainId, publisher) {
|
|
1615
1615
|
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 +1663,7 @@ async function handshakeLifecycle(options, rawQuery, candidateSources, subscript
|
|
|
1663
1663
|
const scopedOptions = publisherSubjectOptions(options, rawQuery.publisher);
|
|
1664
1664
|
const discovery = await discoverHandshakeService(scopedOptions, rawQuery);
|
|
1665
1665
|
if (discovery.catalogs === void 0) return { discovery };
|
|
1666
|
-
const serviceRevisions =
|
|
1666
|
+
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
1667
|
const found = await discoverTuples(
|
|
1668
1668
|
scopedOptions.viewer,
|
|
1669
1669
|
serviceRevisions,
|
|
@@ -1765,12 +1765,8 @@ function createEventKitHandshakeReadModel(options) {
|
|
|
1765
1765
|
subscriptions: projection.subscriptions
|
|
1766
1766
|
};
|
|
1767
1767
|
},
|
|
1768
|
-
async
|
|
1769
|
-
|
|
1770
|
-
},
|
|
1771
|
-
async publisher(query) {
|
|
1772
|
-
return handshakeView(await handshakeLifecycle(options, query));
|
|
1773
|
-
},
|
|
1768
|
+
discoverPublisherService: async (query) => (await discoverHandshakeService(publisherSubjectOptions(options, query.publisher), query)).result,
|
|
1769
|
+
publisher: async (query) => handshakeView(await handshakeLifecycle(options, query)),
|
|
1774
1770
|
async subscriber(rawQuery) {
|
|
1775
1771
|
const subscriber = NormalizedAddressZod5.parse(rawQuery.subscriber);
|
|
1776
1772
|
const subscriptionId = rawQuery.subscriptionId === void 0 ? void 0 : HandshakeIdZod.parse(rawQuery.subscriptionId);
|