@sig-net/midnight 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +113 -49
  2. package/dist/constants.d.ts +55 -0
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/constants.js +85 -5
  5. package/dist/constants.js.map +1 -1
  6. package/dist/ecdsa-attestation.d.ts +6 -5
  7. package/dist/ecdsa-attestation.d.ts.map +1 -1
  8. package/dist/ecdsa-attestation.js +5 -4
  9. package/dist/ecdsa-attestation.js.map +1 -1
  10. package/dist/index.d.ts +1 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +3 -4
  13. package/dist/index.js.map +1 -1
  14. package/dist/managed/compiler/contract-manifest.json +2 -2
  15. package/dist/managed/contract/index.js +31 -31
  16. package/dist/managed/contract/index.js.map +1 -1
  17. package/dist/signature-requests-state-reader.d.ts +7 -7
  18. package/dist/signature-requests-state-reader.js +7 -7
  19. package/dist/signature-response-verification.d.ts +1 -1
  20. package/dist/signature-response-verification.d.ts.map +1 -1
  21. package/dist/signature-response-verification.js +3 -3
  22. package/dist/signature-response-verification.js.map +1 -1
  23. package/dist/signature-state-reading.js +2 -2
  24. package/dist/signature-state-reading.js.map +1 -1
  25. package/dist/signet-contract-events.d.ts +267 -0
  26. package/dist/signet-contract-events.d.ts.map +1 -0
  27. package/dist/signet-contract-events.js +272 -0
  28. package/dist/signet-contract-events.js.map +1 -0
  29. package/dist/signet-evtype2tx-requests.d.ts +4 -4
  30. package/dist/signet-evtype2tx-requests.d.ts.map +1 -1
  31. package/dist/signet-evtype2tx-requests.js +3 -3
  32. package/dist/signet-request-feed.d.ts +61 -33
  33. package/dist/signet-request-feed.d.ts.map +1 -1
  34. package/dist/signet-request-feed.js +116 -62
  35. package/dist/signet-request-feed.js.map +1 -1
  36. package/dist/signet-request-response-reader.d.ts +62 -55
  37. package/dist/signet-request-response-reader.d.ts.map +1 -1
  38. package/dist/signet-request-response-reader.js +85 -99
  39. package/dist/signet-request-response-reader.js.map +1 -1
  40. package/dist/signet-requests.js +2 -2
  41. package/dist/signet-requests.js.map +1 -1
  42. package/package.json +2 -2
  43. package/src/Signet.compact +45 -36
  44. package/dist/signet-contract-state-reader.d.ts +0 -247
  45. package/dist/signet-contract-state-reader.d.ts.map +0 -1
  46. package/dist/signet-contract-state-reader.js +0 -363
  47. package/dist/signet-contract-state-reader.js.map +0 -1
  48. package/dist/signet-request-resolver.d.ts +0 -60
  49. package/dist/signet-request-resolver.d.ts.map +0 -1
  50. package/dist/signet-request-resolver.js +0 -78
  51. package/dist/signet-request-resolver.js.map +0 -1
@@ -1,22 +1,42 @@
1
- import { type ResolvedSignetRequest } from "./signet-request-resolver.ts";
1
+ import { type SignetEventSource } from "./signet-contract-events.ts";
2
2
  import type { SignetPublicStateSource } from "./signet-request-response-reader.ts";
3
- import { type RequestIdHex } from "./signet-requests.ts";
3
+ import { type RequestIdHex, type SignBidirectionalEvent } from "./signet-requests.ts";
4
4
  /** Default gap between poll cycles of {@link SignetRequestFeed.requests}. */
5
5
  export declare const DEFAULT_FEED_POLL_INTERVAL_MS = 3000;
6
+ /**
7
+ * A request discovered through a notification event and read from the named
8
+ * caller's own authenticated ledger.
9
+ */
10
+ export interface ResolvedSignetRequest {
11
+ /**
12
+ * The contract whose authenticated state the request was read from: the
13
+ * epsilon-derivation predecessor. Key derivation keys off THIS, never off a
14
+ * field taken from the notification on faith.
15
+ */
16
+ callerAddress: string;
17
+ /** The request id the record is stored under in `callerAddress`'s index. */
18
+ requestId: RequestIdHex;
19
+ /** The authenticated request record to sign. */
20
+ request: SignBidirectionalEvent;
21
+ }
6
22
  /** Everything a {@link SignetRequestFeed} needs. */
7
23
  export interface SignetRequestFeedConfig {
8
- /** Address of the central signet contract whose notification registry to poll. */
24
+ /** Address of the central signet contract whose notification events to poll. */
9
25
  readonly signetContractAddress: string;
10
26
  /**
11
- * Source of raw contract state for BOTH the signet contract's registry and
12
- * the requester ledgers the resolver authenticates against — a full
13
- * `indexerPublicDataProvider` is assignable.
27
+ * Source of raw contract state for the requester ledgers the feed
28
+ * enumerates. A full `indexerPublicDataProvider` is assignable.
14
29
  */
15
30
  readonly source: SignetPublicStateSource;
31
+ /**
32
+ * Source of the signet contract's emitted events (discovery). Adapt a full
33
+ * provider with `signetEventSourceFromPublicDataProvider`.
34
+ */
35
+ readonly eventSource: SignetEventSource;
16
36
  /**
17
37
  * Optional policy allow-list of requester contract addresses to serve
18
38
  * (matched case- and `0x`-prefix-insensitively). Omit to serve every
19
- * requester the resolver can authenticate. NOT a security control.
39
+ * requester a notification points at. NOT a security control.
20
40
  */
21
41
  readonly allowContracts?: Iterable<string>;
22
42
  /** Poll cadence for {@link SignetRequestFeed.requests}; default {@link DEFAULT_FEED_POLL_INTERVAL_MS}. */
@@ -32,51 +52,59 @@ export interface SignetRequestFeedConfig {
32
52
  */
33
53
  export declare function sleepUnlessAborted(ms: number, signal?: AbortSignal): Promise<void>;
34
54
  /**
35
- * The registry-polling request feed. Reads the signet contract's notification
36
- * registry (discovery) and hands each notification to a
37
- * {@link SignetRequestResolver} (authentication), yielding only notifications
38
- * that resolve to a real, member request. Dedupes by request id across its
39
- * lifetime, so a re-registered notification is not re-yielded; call
55
+ * The event-polling request feed. Reads the signet contract's emitted
56
+ * notifications (discovery) and looks each declared request id up in the
57
+ * pointed-at caller's own request map (authentication by construction: the
58
+ * records come from the caller's ledger), yielding each found request once.
59
+ * A request stored WITHOUT a notification is never discovered: the
60
+ * notification is the doorbell. Dedupes by request id across its lifetime,
61
+ * so a re-notified or still-pending request is not re-yielded. Call
40
62
  * {@link forget} to re-arm a request whose downstream processing failed.
41
63
  */
42
64
  export declare class SignetRequestFeed {
43
65
  private readonly signetContractAddress;
44
66
  private readonly source;
45
- private readonly resolver;
67
+ private readonly eventSource;
46
68
  private readonly allowContracts?;
47
69
  private readonly pollIntervalMs;
48
70
  private readonly yielded;
49
71
  /**
50
- * @param config - The signet contract, state source, and optional policy
51
- * allow-list.
72
+ * @param config - The signet contract, state and event sources, and
73
+ * optional policy allow-list.
52
74
  */
53
75
  constructor(config: SignetRequestFeedConfig);
54
76
  /** Whether the policy allow-list admits `callerAddress` (always true when unset). */
55
77
  private allowed;
56
78
  /**
57
- * One-shot: every currently-registered notification that decodes, is
58
- * admitted by the allow-list, not already yielded, and resolves to an
59
- * authenticated member request. Registry enumeration has no meaningful
60
- * on-ledger order, so entries are processed in ascending request-id-hex
61
- * order — a stable, deterministic sequence. Forged / not-yet-indexed /
62
- * wrong-field notifications resolve to nothing and are dropped WITHOUT
63
- * being marked yielded, so a genuine request whose ledger write has not
64
- * indexed yet is retried next cycle; undecodable or unsupported-version
65
- * records are likewise skipped (and logged) without being marked.
79
+ * The unique `(callerAddress, requestsPath, requestId)` pointers of the
80
+ * currently emitted notification events, allow-list applied, in ascending
81
+ * (caller-address, request-id) order (event enumeration order is
82
+ * per-source, so a stable sort keeps the poll deterministic). Deduped by
83
+ * the FULL triple, not the id alone, so a forged notification declaring a
84
+ * genuine id under a wrong pointer cannot shadow the genuine one.
85
+ * Undecodable or unsupported-version events are skipped (and logged):
86
+ * they carry no readable pointer, so nothing is lost.
66
87
  *
67
- * Dedupe and resolution key off the request id of the registry entry's map
68
- * key (the V1 payload no longer carries one). The key is caller-supplied,
69
- * so it confers no authority — the resolver's membership check against the
70
- * named caller's own ledger is what authenticates it.
88
+ * @returns The deduplicated pointers to look up this cycle.
89
+ */
90
+ private notificationPointers;
91
+ /**
92
+ * One-shot: every notified request that is admitted by the allow-list,
93
+ * not already yielded, and found by id in the pointed-at caller's own
94
+ * request map. A pointer whose caller has no readable state, whose path
95
+ * holds no request map, or whose declared id is not (yet) a member yields
96
+ * nothing WITHOUT marking anything, so a genuine request whose ledger
97
+ * write has not indexed yet is retried next cycle. One caller's state is
98
+ * queried at most once per cycle.
71
99
  *
72
- * @returns The newly-authenticated requests this cycle.
73
- * @throws Error if the signet contract has no readable state at the
74
- * configured address (wrong address or not yet deployed/indexed).
100
+ * @returns The newly-discovered authenticated requests this cycle.
101
+ * @throws Error when the event source itself fails (e.g. the indexer is
102
+ * unreachable).
75
103
  */
76
104
  poll(): Promise<ResolvedSignetRequest[]>;
77
105
  /**
78
106
  * Re-arm `requestId` for redelivery on the next {@link poll} / {@link requests}
79
- * cycle — call when downstream processing of a yielded request failed, so it
107
+ * cycle: call when downstream processing of a yielded request failed, so it
80
108
  * is retried (mirrors the MPC's delete-on-failure of its processed set).
81
109
  *
82
110
  * @param requestId - The request id to allow through again.
@@ -85,7 +113,7 @@ export declare class SignetRequestFeed {
85
113
  /**
86
114
  * Live stream: poll + sleep, yielding each authenticated request exactly once
87
115
  * (subject to {@link forget}), until `opts.signal` aborts. The natural
88
- * sequential `for await` consumption serializes downstream processing — no
116
+ * sequential `for await` consumption serializes downstream processing: no
89
117
  * two requests are handed over concurrently.
90
118
  *
91
119
  * @param opts.signal - Abort to stop the stream.
@@ -1 +1 @@
1
- {"version":3,"file":"signet-request-feed.d.ts","sourceRoot":"","sources":["../src/signet-request-feed.ts"],"names":[],"mappings":"AAkBA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzE,6EAA6E;AAC7E,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACtC,kFAAkF;IAClF,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3C,0GAA0G;IAC1G,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,MAAM,EACV,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAaf;AAOD;;;;;;;GAOG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAc;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAIxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IAEnD;;;OAGG;gBACS,MAAM,EAAE,uBAAuB;IAW3C,qFAAqF;IACrF,OAAO,CAAC,OAAO;IAOf;;;;;;;;;;;;;;;;;;;OAmBG;IACG,IAAI,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAqC9C;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI;IAIrC;;;;;;;;OAQG;IACI,QAAQ,CAAC,IAAI,CAAC,EAAE;QACrB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,qBAAqB,CAAC,qBAAqB,CAAC;CAQjD"}
1
+ {"version":3,"file":"signet-request-feed.d.ts","sourceRoot":"","sources":["../src/signet-request-feed.ts"],"names":[],"mappings":"AAoBA,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAEnF,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC5B,MAAM,sBAAsB,CAAC;AAE9B,6EAA6E;AAC7E,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,SAAS,EAAE,YAAY,CAAC;IACxB,gDAAgD;IAChD,OAAO,EAAE,sBAAsB,CAAC;CACjC;AAED,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACtC,gFAAgF;IAChF,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3C,0GAA0G;IAC1G,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,MAAM,EACV,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAaf;AAOD;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAc;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAIxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IAEnD;;;OAGG;gBACS,MAAM,EAAE,uBAAuB;IAW3C,qFAAqF;IACrF,OAAO,CAAC,OAAO;IAOf;;;;;;;;;;;OAWG;YACW,oBAAoB;IA+ClC;;;;;;;;;;;;OAYG;IACG,IAAI,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAuC9C;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI;IAIrC;;;;;;;;OAQG;IACI,QAAQ,CAAC,IAAI,CAAC,EAAE;QACrB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,qBAAqB,CAAC,qBAAqB,CAAC;CAQjD"}
@@ -1,19 +1,25 @@
1
1
  // The MPC's single entry point for discovering signature requests: poll the
2
- // central signet contract's notification registry (ledger field 4), resolve
3
- // each notification to an AUTHENTICATED request read from the named caller's
4
- // own ledger, and yield only the ones that pass the membership check. The
5
- // registry is append-only with no on-ledger cursor, so the feed's in-memory
6
- // `yielded` set is the diff cursor: every poll enumerates the registry and
7
- // serves what it has not served before.
2
+ // central signet contract's emitted SignBidirectionalEvent notifications,
3
+ // follow each to the named caller contract, and read the AUTHENTICATED
4
+ // request it declares from that caller's own request map. A notification is
5
+ // a doorbell, never an authority: it says only WHERE to look (caller
6
+ // address + the resolved ledger-tree path of its request map) and WHICH
7
+ // request (the declared id), and every request served comes from the named
8
+ // caller's own ledger. An attacker cannot write into a contract it does not
9
+ // control, so a forged notification can at most re-point at a legitimate
10
+ // caller's stored request, never inject one.
11
+ //
12
+ // The event log has no on-ledger cursor the feed consumes, so the feed's
13
+ // in-memory `yielded` set is the diff cursor: every poll looks up the
14
+ // notified requests and serves what it has not served before.
8
15
  //
9
16
  // The requester allow-list is an OPTIONAL policy filter here (drop requests
10
17
  // from contracts you choose not to serve), never a security requirement and
11
- // never the discovery mechanism — attribution comes from the resolver's
12
- // authenticated read (see signet-request-resolver.ts and
13
- // knowledge-base/caller-attribution.md).
14
- import { decodeSignBidirectionalNotification, readSignBidirectionalNotificationIndexFromState, } from "./signet-contract-state-reader.js";
15
- import { SignetRequestResolver, } from "./signet-request-resolver.js";
16
- import { stripHexPrefix } from "./signet-requests.js";
18
+ // never the discovery mechanism: attribution comes from reading the
19
+ // caller's authenticated state.
20
+ import { decodeSignBidirectionalEventNotificationPayload, decodeSignBidirectionalNotification, SignetEventName, } from "./signet-contract-events.js";
21
+ import { lookupSignetRequestAt } from "./signature-requests-state-reader.js";
22
+ import { requestIdHex, stripHexPrefix, } from "./signet-requests.js";
17
23
  /** Default gap between poll cycles of {@link SignetRequestFeed.requests}. */
18
24
  export const DEFAULT_FEED_POLL_INTERVAL_MS = 3000;
19
25
  /**
@@ -44,30 +50,32 @@ function normalizeAddress(address) {
44
50
  return stripHexPrefix(address).toLowerCase();
45
51
  }
46
52
  /**
47
- * The registry-polling request feed. Reads the signet contract's notification
48
- * registry (discovery) and hands each notification to a
49
- * {@link SignetRequestResolver} (authentication), yielding only notifications
50
- * that resolve to a real, member request. Dedupes by request id across its
51
- * lifetime, so a re-registered notification is not re-yielded; call
53
+ * The event-polling request feed. Reads the signet contract's emitted
54
+ * notifications (discovery) and looks each declared request id up in the
55
+ * pointed-at caller's own request map (authentication by construction: the
56
+ * records come from the caller's ledger), yielding each found request once.
57
+ * A request stored WITHOUT a notification is never discovered: the
58
+ * notification is the doorbell. Dedupes by request id across its lifetime,
59
+ * so a re-notified or still-pending request is not re-yielded. Call
52
60
  * {@link forget} to re-arm a request whose downstream processing failed.
53
61
  */
54
62
  export class SignetRequestFeed {
55
63
  signetContractAddress;
56
64
  source;
57
- resolver;
65
+ eventSource;
58
66
  allowContracts;
59
67
  pollIntervalMs;
60
- // Request ids already yielded. NOT the security boundary (the resolver is) —
61
- // just an at-most-once gate so one request is not processed twice.
68
+ // Request ids already yielded. NOT the security boundary (the caller-ledger
69
+ // read is), just an at-most-once gate so one request is not processed twice.
62
70
  yielded = new Set();
63
71
  /**
64
- * @param config - The signet contract, state source, and optional policy
65
- * allow-list.
72
+ * @param config - The signet contract, state and event sources, and
73
+ * optional policy allow-list.
66
74
  */
67
75
  constructor(config) {
68
76
  this.signetContractAddress = config.signetContractAddress;
69
77
  this.source = config.source;
70
- this.resolver = new SignetRequestResolver({ source: config.source });
78
+ this.eventSource = config.eventSource;
71
79
  this.allowContracts = config.allowContracts
72
80
  ? new Set(Array.from(config.allowContracts, normalizeAddress))
73
81
  : undefined;
@@ -80,58 +88,104 @@ export class SignetRequestFeed {
80
88
  this.allowContracts.has(normalizeAddress(callerAddress)));
81
89
  }
82
90
  /**
83
- * One-shot: every currently-registered notification that decodes, is
84
- * admitted by the allow-list, not already yielded, and resolves to an
85
- * authenticated member request. Registry enumeration has no meaningful
86
- * on-ledger order, so entries are processed in ascending request-id-hex
87
- * order — a stable, deterministic sequence. Forged / not-yet-indexed /
88
- * wrong-field notifications resolve to nothing and are dropped WITHOUT
89
- * being marked yielded, so a genuine request whose ledger write has not
90
- * indexed yet is retried next cycle; undecodable or unsupported-version
91
- * records are likewise skipped (and logged) without being marked.
92
- *
93
- * Dedupe and resolution key off the request id of the registry entry's map
94
- * key (the V1 payload no longer carries one). The key is caller-supplied,
95
- * so it confers no authority — the resolver's membership check against the
96
- * named caller's own ledger is what authenticates it.
91
+ * The unique `(callerAddress, requestsPath, requestId)` pointers of the
92
+ * currently emitted notification events, allow-list applied, in ascending
93
+ * (caller-address, request-id) order (event enumeration order is
94
+ * per-source, so a stable sort keeps the poll deterministic). Deduped by
95
+ * the FULL triple, not the id alone, so a forged notification declaring a
96
+ * genuine id under a wrong pointer cannot shadow the genuine one.
97
+ * Undecodable or unsupported-version events are skipped (and logged):
98
+ * they carry no readable pointer, so nothing is lost.
97
99
  *
98
- * @returns The newly-authenticated requests this cycle.
99
- * @throws Error if the signet contract has no readable state at the
100
- * configured address (wrong address or not yet deployed/indexed).
100
+ * @returns The deduplicated pointers to look up this cycle.
101
101
  */
102
- async poll() {
103
- const state = await this.source.queryContractState(this.signetContractAddress);
104
- if (!state?.data) {
105
- throw new Error(`No contract state at signet contract ${this.signetContractAddress} ` +
106
- `— wrong address, or not yet deployed/indexed`);
107
- }
108
- const registry = readSignBidirectionalNotificationIndexFromState(state.data);
109
- const out = [];
110
- for (const [requestId, record] of [...registry.entries()].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))) {
111
- let notification;
102
+ async notificationPointers() {
103
+ const events = await this.eventSource.querySignetEvents(this.signetContractAddress);
104
+ const pointers = new Map();
105
+ for (const event of events) {
106
+ if (event.name !== SignetEventName.SignBidirectionalEvent)
107
+ continue;
108
+ let pointer;
112
109
  try {
113
- notification = decodeSignBidirectionalNotification(record);
110
+ const post = decodeSignBidirectionalEventNotificationPayload(event.payload);
111
+ const notification = decodeSignBidirectionalNotification(post.event);
112
+ pointer = {
113
+ callerAddress: notification.callerAddress,
114
+ requestsPath: notification.requestsPath,
115
+ requestId: requestIdHex(post.requestId),
116
+ };
114
117
  }
115
118
  catch (error) {
116
- console.warn(`SignetRequestFeed: skipping undecodable notification ` +
117
- `registered under ${requestId}: ${String(error)}`);
119
+ console.warn(`SignetRequestFeed: skipping undecodable notification event: ${String(error)}`);
118
120
  continue;
119
121
  }
120
- if (this.yielded.has(requestId))
121
- continue;
122
- if (!this.allowed(notification.callerAddress))
122
+ if (!this.allowed(pointer.callerAddress))
123
123
  continue;
124
- const resolved = await this.resolver.resolve(requestId, notification);
125
- if (resolved === undefined)
124
+ pointers.set(`${pointer.callerAddress}:${pointer.requestsPath.join(",")}:${pointer.requestId}`, pointer);
125
+ }
126
+ return [...pointers.values()].sort((a, b) => {
127
+ const byCaller = a.callerAddress < b.callerAddress
128
+ ? -1
129
+ : a.callerAddress > b.callerAddress
130
+ ? 1
131
+ : 0;
132
+ if (byCaller !== 0)
133
+ return byCaller;
134
+ return a.requestId < b.requestId ? -1 : a.requestId > b.requestId ? 1 : 0;
135
+ });
136
+ }
137
+ /**
138
+ * One-shot: every notified request that is admitted by the allow-list,
139
+ * not already yielded, and found by id in the pointed-at caller's own
140
+ * request map. A pointer whose caller has no readable state, whose path
141
+ * holds no request map, or whose declared id is not (yet) a member yields
142
+ * nothing WITHOUT marking anything, so a genuine request whose ledger
143
+ * write has not indexed yet is retried next cycle. One caller's state is
144
+ * queried at most once per cycle.
145
+ *
146
+ * @returns The newly-discovered authenticated requests this cycle.
147
+ * @throws Error when the event source itself fails (e.g. the indexer is
148
+ * unreachable).
149
+ */
150
+ async poll() {
151
+ const out = [];
152
+ // Per-cycle caller-state cache: null marks a caller whose state could
153
+ // not be read this cycle (not a contract / transient read error).
154
+ const states = new Map();
155
+ for (const pointer of await this.notificationPointers()) {
156
+ if (this.yielded.has(pointer.requestId))
126
157
  continue;
127
- this.yielded.add(requestId);
128
- out.push(resolved);
158
+ let raw = states.get(pointer.callerAddress);
159
+ if (raw === undefined) {
160
+ try {
161
+ raw =
162
+ (await this.source.queryContractState(pointer.callerAddress))
163
+ ?.data ?? null;
164
+ }
165
+ catch {
166
+ raw = null;
167
+ }
168
+ states.set(pointer.callerAddress, raw);
169
+ }
170
+ if (raw === null) {
171
+ continue; // no state at the named caller: nothing to serve yet
172
+ }
173
+ const request = lookupSignetRequestAt(raw, pointer.requestsPath, pointer.requestId);
174
+ if (request === undefined) {
175
+ continue; // forged pointer, or the ledger write has not indexed yet
176
+ }
177
+ this.yielded.add(pointer.requestId);
178
+ out.push({
179
+ callerAddress: pointer.callerAddress,
180
+ requestId: pointer.requestId,
181
+ request,
182
+ });
129
183
  }
130
184
  return out;
131
185
  }
132
186
  /**
133
187
  * Re-arm `requestId` for redelivery on the next {@link poll} / {@link requests}
134
- * cycle — call when downstream processing of a yielded request failed, so it
188
+ * cycle: call when downstream processing of a yielded request failed, so it
135
189
  * is retried (mirrors the MPC's delete-on-failure of its processed set).
136
190
  *
137
191
  * @param requestId - The request id to allow through again.
@@ -142,7 +196,7 @@ export class SignetRequestFeed {
142
196
  /**
143
197
  * Live stream: poll + sleep, yielding each authenticated request exactly once
144
198
  * (subject to {@link forget}), until `opts.signal` aborts. The natural
145
- * sequential `for await` consumption serializes downstream processing — no
199
+ * sequential `for await` consumption serializes downstream processing: no
146
200
  * two requests are handed over concurrently.
147
201
  *
148
202
  * @param opts.signal - Abort to stop the stream.
@@ -1 +1 @@
1
- {"version":3,"file":"signet-request-feed.js","sourceRoot":"","sources":["../src/signet-request-feed.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"signet-request-feed.js","sourceRoot":"","sources":["../src/signet-request-feed.ts"],"names":[],"mappings":"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"}