@sig-net/midnight 0.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/README.md +20 -0
- package/dist/constants.d.ts +62 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +83 -0
- package/dist/constants.js.map +1 -0
- package/dist/epsilon-derivation.d.ts +32 -0
- package/dist/epsilon-derivation.d.ts.map +1 -0
- package/dist/epsilon-derivation.js +54 -0
- package/dist/epsilon-derivation.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/managed/compiler/contract-info.json +165 -0
- package/dist/managed/compiler/contract-manifest.json +32 -0
- package/dist/managed/contract/index.d.ts +65 -0
- package/dist/managed/contract/index.js +611 -0
- package/dist/managed/contract/index.js.map +8 -0
- package/dist/schnorr.d.ts +100 -0
- package/dist/schnorr.d.ts.map +1 -0
- package/dist/schnorr.js +144 -0
- package/dist/schnorr.js.map +1 -0
- package/dist/signature-requests-state-reader.d.ts +74 -0
- package/dist/signature-requests-state-reader.d.ts.map +1 -0
- package/dist/signature-requests-state-reader.js +167 -0
- package/dist/signature-requests-state-reader.js.map +1 -0
- package/dist/signature-response-verification.d.ts +27 -0
- package/dist/signature-response-verification.d.ts.map +1 -0
- package/dist/signature-response-verification.js +45 -0
- package/dist/signature-response-verification.js.map +1 -0
- package/dist/signature-state-reading.d.ts +36 -0
- package/dist/signature-state-reading.d.ts.map +1 -0
- package/dist/signature-state-reading.js +62 -0
- package/dist/signature-state-reading.js.map +1 -0
- package/dist/signet-contract-state-reader.d.ts +146 -0
- package/dist/signet-contract-state-reader.d.ts.map +1 -0
- package/dist/signet-contract-state-reader.js +226 -0
- package/dist/signet-contract-state-reader.js.map +1 -0
- package/dist/signet-event-observer.d.ts +102 -0
- package/dist/signet-event-observer.d.ts.map +1 -0
- package/dist/signet-event-observer.js +127 -0
- package/dist/signet-event-observer.js.map +1 -0
- package/dist/signet-events.d.ts +175 -0
- package/dist/signet-events.d.ts.map +1 -0
- package/dist/signet-events.js +210 -0
- package/dist/signet-events.js.map +1 -0
- package/dist/signet-request-feed.d.ts +78 -0
- package/dist/signet-request-feed.d.ts.map +1 -0
- package/dist/signet-request-feed.js +116 -0
- package/dist/signet-request-feed.js.map +1 -0
- package/dist/signet-request-resolver.d.ts +58 -0
- package/dist/signet-request-resolver.d.ts.map +1 -0
- package/dist/signet-request-resolver.js +76 -0
- package/dist/signet-request-resolver.js.map +1 -0
- package/dist/signet-request-response-reader.d.ts +160 -0
- package/dist/signet-request-response-reader.d.ts.map +1 -0
- package/dist/signet-request-response-reader.js +198 -0
- package/dist/signet-request-response-reader.js.map +1 -0
- package/dist/signet-requests.d.ts +363 -0
- package/dist/signet-requests.d.ts.map +1 -0
- package/dist/signet-requests.js +497 -0
- package/dist/signet-requests.js.map +1 -0
- package/dist/signet-response-feed.d.ts +161 -0
- package/dist/signet-response-feed.d.ts.map +1 -0
- package/dist/signet-response-feed.js +234 -0
- package/dist/signet-response-feed.js.map +1 -0
- package/package.json +47 -0
- package/src/Schnorr.compact +63 -0
- package/src/Signet.compact +529 -0
- package/src/circuits.compact +36 -0
- package/src/constants.ts +97 -0
- package/src/epsilon-derivation.ts +62 -0
- package/src/index.ts +31 -0
- package/src/managed/compiler/contract-info.json +165 -0
- package/src/managed/compiler/contract-manifest.json +32 -0
- package/src/managed/contract/index.d.ts +65 -0
- package/src/managed/contract/index.js +611 -0
- package/src/managed/contract/index.js.map +8 -0
- package/src/schnorr.ts +210 -0
- package/src/signature-requests-state-reader.ts +223 -0
- package/src/signature-response-verification.ts +64 -0
- package/src/signature-state-reading.ts +87 -0
- package/src/signet-contract-state-reader.ts +391 -0
- package/src/signet-event-observer.ts +186 -0
- package/src/signet-events.ts +337 -0
- package/src/signet-request-feed.ts +158 -0
- package/src/signet-request-resolver.ts +116 -0
- package/src/signet-request-response-reader.ts +324 -0
- package/src/signet-requests.ts +737 -0
- package/src/signet-response-feed.ts +325 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Watch the CENTRAL signet contract's `Misc` events and surface ONE kind of
|
|
2
|
+
// signet notification (selected by the codec) as typed events in id order —
|
|
3
|
+
// the event-observation replacement for polling ledgers blind. Instantiated
|
|
4
|
+
// with `signBidirectionalEventCodec` it discovers signature requests for the
|
|
5
|
+
// MPC (see signet-request-feed.ts); with `signatureRespondedEventCodec` it
|
|
6
|
+
// discovers posted signature responses for the requesting client (see
|
|
7
|
+
// signet-response-feed.ts). The observer only DISCOVERS; authenticating /
|
|
8
|
+
// verifying what an event points at is its consumer's job. The event is a
|
|
9
|
+
// ping, never the source of truth — see
|
|
10
|
+
// knowledge-base/caller-attribution.md.
|
|
11
|
+
import { eventNameTag, hexToBytes, } from "./signet-events.js";
|
|
12
|
+
/** Default gap between polls of the indexer's event stream. */
|
|
13
|
+
export const DEFAULT_EVENT_POLL_INTERVAL_MS = 3000;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve after `ms`, or immediately once `signal` aborts. Used to space out
|
|
16
|
+
* polls without wedging a shutdown.
|
|
17
|
+
*/
|
|
18
|
+
function sleep(ms, signal) {
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
if (signal?.aborted)
|
|
21
|
+
return resolve();
|
|
22
|
+
const timer = setTimeout(() => {
|
|
23
|
+
signal?.removeEventListener("abort", onAbort);
|
|
24
|
+
resolve();
|
|
25
|
+
}, ms);
|
|
26
|
+
const onAbort = () => {
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
resolve();
|
|
29
|
+
};
|
|
30
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Watches one signet contract's `Misc` events and surfaces the notifications
|
|
35
|
+
* of ONE kind among them (the codec's name tag), decoded and in ascending
|
|
36
|
+
* indexer-id order. A single decode failure is logged and skipped — one
|
|
37
|
+
* malformed event never stalls the stream.
|
|
38
|
+
*/
|
|
39
|
+
export class SignetEventObserver {
|
|
40
|
+
signetContractAddress;
|
|
41
|
+
source;
|
|
42
|
+
codec;
|
|
43
|
+
fromEventId;
|
|
44
|
+
pollIntervalMs;
|
|
45
|
+
/**
|
|
46
|
+
* @param config - The signet contract, event source, codec, and resume floor.
|
|
47
|
+
*/
|
|
48
|
+
constructor(config) {
|
|
49
|
+
this.signetContractAddress = config.signetContractAddress;
|
|
50
|
+
this.source = config.source;
|
|
51
|
+
this.codec = config.codec;
|
|
52
|
+
this.fromEventId = config.fromEventId ?? 0;
|
|
53
|
+
this.pollIntervalMs = config.pollIntervalMs ?? DEFAULT_EVENT_POLL_INTERVAL_MS;
|
|
54
|
+
}
|
|
55
|
+
/** The `Misc` filter for the watched signet contract. */
|
|
56
|
+
filter() {
|
|
57
|
+
return { contractAddress: this.signetContractAddress, types: ["Misc"] };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Every currently-visible notification of the codec's kind at or after the
|
|
61
|
+
* resume floor, each paired with its indexer cursor id, ascending by id.
|
|
62
|
+
* Non-`Misc` events, other name tags, and decode failures are dropped
|
|
63
|
+
* (failures logged).
|
|
64
|
+
*/
|
|
65
|
+
async scan() {
|
|
66
|
+
const events = await this.source.queryContractEvents(this.filter());
|
|
67
|
+
const out = [];
|
|
68
|
+
for (const event of events) {
|
|
69
|
+
if (event.eventType !== "Misc")
|
|
70
|
+
continue;
|
|
71
|
+
if (event.id < this.fromEventId)
|
|
72
|
+
continue;
|
|
73
|
+
if (eventNameTag(event.name) !== this.codec.tag)
|
|
74
|
+
continue;
|
|
75
|
+
let decoded;
|
|
76
|
+
try {
|
|
77
|
+
decoded = this.codec.decode(hexToBytes(event.payload));
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.warn(`SignetEventObserver: dropping undecodable ${this.codec.tag} ` +
|
|
81
|
+
`event id=${event.id}: ${String(error)}`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
out.push({ id: event.id, event: decoded });
|
|
85
|
+
}
|
|
86
|
+
out.sort((a, b) => a.id - b.id);
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* One-shot: every notification of the codec's kind currently visible at or
|
|
91
|
+
* after the resume floor, in id order. The polling feeds
|
|
92
|
+
* ({@link SignetRequestFeed}, `SignetResponseFeed`) re-scan through this
|
|
93
|
+
* each cycle (so a not-yet-indexed write is retried); it does NOT advance a
|
|
94
|
+
* cursor — the feeds dedupe by content instead.
|
|
95
|
+
*
|
|
96
|
+
* @returns The decoded notifications, ascending by indexer id.
|
|
97
|
+
*/
|
|
98
|
+
async currentEvents() {
|
|
99
|
+
return (await this.scan()).map((entry) => entry.event);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Live stream: poll the event source forever, yielding each notification
|
|
103
|
+
* exactly once in id order — nothing at or below the last yielded id is
|
|
104
|
+
* re-emitted (the cursor advances as `id + 1`, matching the indexer's
|
|
105
|
+
* resume convention). Runs until `opts.signal` aborts.
|
|
106
|
+
*
|
|
107
|
+
* @param opts.signal - Abort to stop the stream (between polls or on the next yield).
|
|
108
|
+
* @yields Each decoded notification once, ascending by indexer id.
|
|
109
|
+
*/
|
|
110
|
+
async *watch(opts) {
|
|
111
|
+
let cursor = this.fromEventId;
|
|
112
|
+
while (!opts?.signal?.aborted) {
|
|
113
|
+
const batch = await this.scan();
|
|
114
|
+
for (const { id, event } of batch) {
|
|
115
|
+
if (id < cursor)
|
|
116
|
+
continue;
|
|
117
|
+
yield event;
|
|
118
|
+
cursor = id + 1;
|
|
119
|
+
}
|
|
120
|
+
if (opts?.signal?.aborted)
|
|
121
|
+
break;
|
|
122
|
+
await sleep(this.pollIntervalMs, opts?.signal);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export { sleep as sleepUnlessAborted };
|
|
127
|
+
//# sourceMappingURL=signet-event-observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signet-event-observer.js","sourceRoot":"","sources":["../src/signet-event-observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { type RequestIdHex } from "./signet-requests.ts";
|
|
2
|
+
/**
|
|
3
|
+
* The `Misc` event `name` tag the signet contract emits alongside the
|
|
4
|
+
* serialized {@link SignBidirectionalEvent} payload (Compact:
|
|
5
|
+
* `pad(32, "SignBidirectionalEvent")`). Observers filter on this ascii tag.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SIGN_BIDIRECTIONAL_EVENT_TAG = "SignBidirectionalEvent";
|
|
8
|
+
/**
|
|
9
|
+
* TS twin of the Compact `SignBidirectionalEvent` *event* struct (not the
|
|
10
|
+
* request record). The notification the signet contract emits so the MPC knows
|
|
11
|
+
* a {@link SignBidirectionalRequest} was stored — and, crucially, WHERE to read
|
|
12
|
+
* the authenticated copy of it.
|
|
13
|
+
*/
|
|
14
|
+
export interface SignBidirectionalEvent {
|
|
15
|
+
/**
|
|
16
|
+
* The frozen envelope's `version` tag (Compact `Uint<8>`). Selects how the
|
|
17
|
+
* opaque payload was interpreted; this decoder only understands version 1.
|
|
18
|
+
*/
|
|
19
|
+
version: number;
|
|
20
|
+
/**
|
|
21
|
+
* Address of the contract whose request index holds the request (Compact
|
|
22
|
+
* `ContractAddress`, rendered as lowercase hex, no `0x` prefix — directly
|
|
23
|
+
* usable as a `queryContractState` argument). The MPC reads the request from
|
|
24
|
+
* THIS contract's authenticated state; the event field itself confers no
|
|
25
|
+
* authority.
|
|
26
|
+
*/
|
|
27
|
+
callerAddress: string;
|
|
28
|
+
/** Which request in {@link callerAddress}'s index this notification is about. */
|
|
29
|
+
requestId: RequestIdHex;
|
|
30
|
+
/**
|
|
31
|
+
* Ledger field position of the `Map<RequestId, SignBidirectionalRequest>`
|
|
32
|
+
* request index in {@link callerAddress} (the signet layout convention puts
|
|
33
|
+
* it at field 0, but the event carries it so the reader never assumes).
|
|
34
|
+
*/
|
|
35
|
+
requestsIndexField: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Strip an optional `0x`/`0X` prefix from a hex string.
|
|
39
|
+
*
|
|
40
|
+
* @param hex - A hex string, with or without a `0x` prefix.
|
|
41
|
+
* @returns The bare hex digits.
|
|
42
|
+
*/
|
|
43
|
+
export declare function stripHexPrefix(hex: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Decode a hex string (as the indexer returns `Misc.name` / `Misc.payload`)
|
|
46
|
+
* into bytes.
|
|
47
|
+
*
|
|
48
|
+
* @param hex - Hex digits, with or without a `0x` prefix.
|
|
49
|
+
* @returns The decoded bytes.
|
|
50
|
+
*/
|
|
51
|
+
export declare function hexToBytes(hex: string): Uint8Array;
|
|
52
|
+
/**
|
|
53
|
+
* The ascii tag of a zero-padded `Bytes<N>` name (the Compact `pad(N, "text")`
|
|
54
|
+
* convention): decode the hex, then trim the trailing NUL padding.
|
|
55
|
+
*
|
|
56
|
+
* @param nameHex - The indexer's hex-encoded `Misc.name`.
|
|
57
|
+
* @returns The trimmed ascii tag, e.g. `"SignBidirectionalEvent"`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function eventNameTag(nameHex: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Decode a `Misc` payload (`serialize<SignBidirectionalEvent, 256>`) into the
|
|
62
|
+
* struct. The event is a frozen `{ version: Uint<8>, payload: Bytes<224> }`
|
|
63
|
+
* envelope, and V1 packs the concrete fields into that inner payload with
|
|
64
|
+
* `serialize<SignBidirectionalEventV1Payload, 224>`. `serialize<T,N>` lays
|
|
65
|
+
* fields out in declaration order, packed at the front and right-zero-padded
|
|
66
|
+
* (see knowledge-base/events.md), so in the outer 256-byte payload:
|
|
67
|
+
* `version = payload[0]`, then everything shifts one byte —
|
|
68
|
+
* `callerAddress = payload[1..33]`, `requestId = payload[33..65]`,
|
|
69
|
+
* `requestsIndexField = payload[65]`.
|
|
70
|
+
*
|
|
71
|
+
* The byte layout is pinned against a live indexer by the golden e2e test —
|
|
72
|
+
* `callerAddress` is the V1 payload's FIRST field, a different position than the
|
|
73
|
+
* DepositEvent precedent's `caller`, so do not assume it without that test.
|
|
74
|
+
*
|
|
75
|
+
* Fails closed on an unrecognised `version`: a future payload layout adds a
|
|
76
|
+
* branch here (and, off-chain, a V{N} decoder) rather than silently
|
|
77
|
+
* misinterpreting bytes under the V1 offsets.
|
|
78
|
+
*
|
|
79
|
+
* @param payload - The decoded (raw bytes) `Misc.payload`.
|
|
80
|
+
* @returns The decoded event notification.
|
|
81
|
+
* @throws Error if the payload is shorter than the fixed fields require, or its
|
|
82
|
+
* `version` is not one this decoder understands.
|
|
83
|
+
*/
|
|
84
|
+
export declare function decodeSignBidirectionalEvent(payload: Uint8Array): SignBidirectionalEvent;
|
|
85
|
+
/**
|
|
86
|
+
* The `Misc` event `name` tag the signet contract emits alongside the
|
|
87
|
+
* serialized {@link SignatureRespondedEvent} payload (Compact:
|
|
88
|
+
* `pad(32, "SignatureRespondedEvent")`). Observers filter on this ascii tag.
|
|
89
|
+
*/
|
|
90
|
+
export declare const SIGNATURE_RESPONDED_EVENT_TAG = "SignatureRespondedEvent";
|
|
91
|
+
/**
|
|
92
|
+
* TS twin of the Compact `SignatureRespondedEvent` *event* struct (not the
|
|
93
|
+
* {@link SignatureResponse} record it announces). The notification the signet
|
|
94
|
+
* contract emits from `postSignatureResponse` so the requesting client knows
|
|
95
|
+
* a response post landed — and WHERE in the response log to read it back.
|
|
96
|
+
* A ping only: the log is unauthenticated, so the client must verify the
|
|
97
|
+
* post's signature off-chain (see signet-response-feed.ts).
|
|
98
|
+
*/
|
|
99
|
+
export interface SignatureRespondedEvent {
|
|
100
|
+
/** Which request the posted response answers. */
|
|
101
|
+
requestId: RequestIdHex;
|
|
102
|
+
/**
|
|
103
|
+
* 0-based position of the post in {@link requestId}'s response log — the
|
|
104
|
+
* `count` half of the `SignetResponseKey` it is stored under.
|
|
105
|
+
*/
|
|
106
|
+
count: bigint;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Decode a `Misc` payload (`serialize<SignatureRespondedEvent, 256>`) into
|
|
110
|
+
* the struct. Layout per knowledge-base/events.md: fields in declaration
|
|
111
|
+
* order packed at the front — `requestId = payload[0..32]` (raw bytes),
|
|
112
|
+
* `count = payload[32..40]` (Uint<64>, LITTLE-endian) — right-zero-padded.
|
|
113
|
+
*
|
|
114
|
+
* @param payload - The decoded (raw bytes) `Misc.payload`.
|
|
115
|
+
* @returns The decoded event notification.
|
|
116
|
+
* @throws Error if the payload is shorter than the fixed fields require.
|
|
117
|
+
*/
|
|
118
|
+
export declare function decodeSignatureRespondedEvent(payload: Uint8Array): SignatureRespondedEvent;
|
|
119
|
+
/**
|
|
120
|
+
* The `Misc` event `name` tag the signet contract emits alongside the
|
|
121
|
+
* serialized {@link RespondBidirectionalEvent} payload (Compact:
|
|
122
|
+
* `pad(32, "RespondBidirectionalEvent")`). Observers filter on this ascii tag.
|
|
123
|
+
*/
|
|
124
|
+
export declare const RESPOND_BIDIRECTIONAL_EVENT_TAG = "RespondBidirectionalEvent";
|
|
125
|
+
/**
|
|
126
|
+
* TS twin of the Compact `RespondBidirectionalEvent` *event* struct (not the
|
|
127
|
+
* `RespondBidirectional` record it announces). The notification the signet
|
|
128
|
+
* contract emits from `postRespondBidirectional` when the MPC's attestation
|
|
129
|
+
* of a request's remote execution lands in the respond-bidirectional index —
|
|
130
|
+
* at most once per request (one authenticated slot, first valid write wins).
|
|
131
|
+
* A ping only, but unlike {@link SignatureRespondedEvent} no off-chain
|
|
132
|
+
* verification follows the read-back: the contract verified the attestation
|
|
133
|
+
* in-circuit at post time, so the stored record is authentic by construction.
|
|
134
|
+
*/
|
|
135
|
+
export interface RespondBidirectionalEvent {
|
|
136
|
+
/** Which request the stored attestation answers. */
|
|
137
|
+
requestId: RequestIdHex;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Decode a `Misc` payload (`serialize<RespondBidirectionalEvent, 256>`) into
|
|
141
|
+
* the struct. Layout per knowledge-base/events.md: fields in declaration
|
|
142
|
+
* order packed at the front — `requestId = payload[0..32]` (raw bytes) —
|
|
143
|
+
* right-zero-padded.
|
|
144
|
+
*
|
|
145
|
+
* @param payload - The decoded (raw bytes) `Misc.payload`.
|
|
146
|
+
* @returns The decoded event notification.
|
|
147
|
+
* @throws Error if the payload is shorter than the fixed fields require.
|
|
148
|
+
*/
|
|
149
|
+
export declare function decodeRespondBidirectionalEvent(payload: Uint8Array): RespondBidirectionalEvent;
|
|
150
|
+
/**
|
|
151
|
+
* One signet event kind as an observer consumes it: the `Misc.name` ascii tag
|
|
152
|
+
* to filter on plus the payload decoder. A `SignetEventObserver` is
|
|
153
|
+
* instantiated with one of these — see {@link signBidirectionalEventCodec},
|
|
154
|
+
* {@link signatureRespondedEventCodec}, and
|
|
155
|
+
* {@link respondBidirectionalEventCodec}.
|
|
156
|
+
*/
|
|
157
|
+
export interface SignetMiscEventCodec<T> {
|
|
158
|
+
/** The ascii `Misc.name` tag identifying this event kind. */
|
|
159
|
+
readonly tag: string;
|
|
160
|
+
/**
|
|
161
|
+
* Decode a raw `Misc.payload` into the typed notification.
|
|
162
|
+
*
|
|
163
|
+
* @param payload - The decoded (raw bytes) `Misc.payload`.
|
|
164
|
+
* @returns The decoded event notification.
|
|
165
|
+
* @throws Error if the payload is malformed.
|
|
166
|
+
*/
|
|
167
|
+
decode(payload: Uint8Array): T;
|
|
168
|
+
}
|
|
169
|
+
/** The {@link SignetMiscEventCodec} of {@link SignBidirectionalEvent} notifications. */
|
|
170
|
+
export declare const signBidirectionalEventCodec: SignetMiscEventCodec<SignBidirectionalEvent>;
|
|
171
|
+
/** The {@link SignetMiscEventCodec} of {@link SignatureRespondedEvent} notifications. */
|
|
172
|
+
export declare const signatureRespondedEventCodec: SignetMiscEventCodec<SignatureRespondedEvent>;
|
|
173
|
+
/** The {@link SignetMiscEventCodec} of {@link RespondBidirectionalEvent} notifications. */
|
|
174
|
+
export declare const respondBidirectionalEventCodec: SignetMiscEventCodec<RespondBidirectionalEvent>;
|
|
175
|
+
//# sourceMappingURL=signet-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signet-events.d.ts","sourceRoot":"","sources":["../src/signet-events.ts"],"names":[],"mappings":"AAwBA,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEnF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,2BAA2B,CAAC;AAoCrE;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,SAAS,EAAE,YAAY,CAAC;IACxB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAOlD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,UAAU,GAClB,sBAAsB,CAsBxB;AAED;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,4BAA4B,CAAC;AAYvE;;;;;;;GAOG;AACH,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,SAAS,EAAE,YAAY,CAAC;IACxB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,UAAU,GAClB,uBAAuB,CAazB;AAED;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,8BAA8B,CAAC;AAS3E;;;;;;;;;GASG;AACH,MAAM,WAAW,yBAAyB;IACxC,oDAAoD;IACpD,SAAS,EAAE,YAAY,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,UAAU,GAClB,yBAAyB,CAQ3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,6DAA6D;IAC7D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,CAAC,CAAC;CAChC;AAED,wFAAwF;AACxF,eAAO,MAAM,2BAA2B,EAAE,oBAAoB,CAAC,sBAAsB,CAIlF,CAAC;AAEJ,yFAAyF;AACzF,eAAO,MAAM,4BAA4B,EAAE,oBAAoB,CAAC,uBAAuB,CAIpF,CAAC;AAEJ,2FAA2F;AAC3F,eAAO,MAAM,8BAA8B,EAAE,oBAAoB,CAAC,yBAAyB,CAIxF,CAAC"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// Off-chain codecs for the event notifications the central signet contract
|
|
2
|
+
// emits (Signet.compact structs wrapped in stdlib `Misc { name, payload }`
|
|
3
|
+
// events — see packages/xcontract-events/knowledge-base/events.md), one per
|
|
4
|
+
// direction of the MPC round trip:
|
|
5
|
+
// - SignBidirectionalEvent: the MPC watches these to discover WHEN a
|
|
6
|
+
// request was stored and WHERE to read it. Attribution is re-established
|
|
7
|
+
// by reading the request from the named caller's own authenticated ledger
|
|
8
|
+
// (see signet-request-resolver.ts and
|
|
9
|
+
// knowledge-base/caller-attribution.md); a field inside the event is not
|
|
10
|
+
// trustworthy (a Midnight contract cannot see its caller — gotcha #21).
|
|
11
|
+
// - SignatureRespondedEvent: the requesting client watches these to learn a
|
|
12
|
+
// signature response was posted, then reads the post back from the
|
|
13
|
+
// response log and verifies the signature off-chain (the log is
|
|
14
|
+
// unauthenticated — see signet-response-feed.ts).
|
|
15
|
+
// - RespondBidirectionalEvent: the requesting client watches these to learn
|
|
16
|
+
// the MPC's attestation of a request's remote execution landed, then reads
|
|
17
|
+
// the record back from the respond-bidirectional index — no off-chain
|
|
18
|
+
// verification, the contract authenticated it in-circuit at post time.
|
|
19
|
+
// In every case the event is a notification only — never the source of truth.
|
|
20
|
+
//
|
|
21
|
+
// These are the event-side twins of the Compact structs — each MUST stay in
|
|
22
|
+
// lockstep with its struct in Signet.compact (field order and widths). The
|
|
23
|
+
// byte layouts are pinned by the golden e2e tests against a live indexer.
|
|
24
|
+
import { bytesToHex, requestIdHex } from "./signet-requests.js";
|
|
25
|
+
/**
|
|
26
|
+
* The `Misc` event `name` tag the signet contract emits alongside the
|
|
27
|
+
* serialized {@link SignBidirectionalEvent} payload (Compact:
|
|
28
|
+
* `pad(32, "SignBidirectionalEvent")`). Observers filter on this ascii tag.
|
|
29
|
+
*/
|
|
30
|
+
export const SIGN_BIDIRECTIONAL_EVENT_TAG = "SignBidirectionalEvent";
|
|
31
|
+
/**
|
|
32
|
+
* Byte width of the leading `version` tag (Compact `Uint<8>`). The event is a
|
|
33
|
+
* FROZEN `{ version, payload }` envelope (see `SignBidirectionalEvent` in
|
|
34
|
+
* Signet.compact): `version` is at offset 0 and every V1 field is shifted one
|
|
35
|
+
* byte to make room for it.
|
|
36
|
+
*/
|
|
37
|
+
const VERSION_BYTES = 1;
|
|
38
|
+
/** The only payload interpretation this decoder understands today. */
|
|
39
|
+
const SUPPORTED_VERSION = 1;
|
|
40
|
+
/** Byte width of the `callerAddress` field (Compact `ContractAddress` = 32 raw bytes). */
|
|
41
|
+
const CALLER_ADDRESS_BYTES = 32;
|
|
42
|
+
/** Byte width of the `requestId` field (Compact `Bytes<32>`). */
|
|
43
|
+
const REQUEST_ID_BYTES = 32;
|
|
44
|
+
/** Offset of the V1 `callerAddress` in the outer payload (after the version byte). */
|
|
45
|
+
const CALLER_ADDRESS_OFFSET = VERSION_BYTES;
|
|
46
|
+
/** Offset of the V1 `requestId` (after version + callerAddress). */
|
|
47
|
+
const REQUEST_ID_OFFSET = CALLER_ADDRESS_OFFSET + CALLER_ADDRESS_BYTES;
|
|
48
|
+
/** Offset of the V1 `signBidirectionalRequestsIndexField` (after version + caller + requestId). */
|
|
49
|
+
const REQUESTS_INDEX_FIELD_OFFSET = REQUEST_ID_OFFSET + REQUEST_ID_BYTES;
|
|
50
|
+
/**
|
|
51
|
+
* Minimum serialized length of a V1 event: `version` (1) + `callerAddress` (32)
|
|
52
|
+
* + `requestId` (32) + `signBidirectionalRequestsIndexField` (1) = 66.
|
|
53
|
+
* `serialize<T,256>` right-pads to 256, so a real payload is longer; this is the
|
|
54
|
+
* floor the decoder needs.
|
|
55
|
+
*/
|
|
56
|
+
const MIN_PAYLOAD_BYTES = REQUESTS_INDEX_FIELD_OFFSET + 1;
|
|
57
|
+
/**
|
|
58
|
+
* Strip an optional `0x`/`0X` prefix from a hex string.
|
|
59
|
+
*
|
|
60
|
+
* @param hex - A hex string, with or without a `0x` prefix.
|
|
61
|
+
* @returns The bare hex digits.
|
|
62
|
+
*/
|
|
63
|
+
export function stripHexPrefix(hex) {
|
|
64
|
+
return hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Decode a hex string (as the indexer returns `Misc.name` / `Misc.payload`)
|
|
68
|
+
* into bytes.
|
|
69
|
+
*
|
|
70
|
+
* @param hex - Hex digits, with or without a `0x` prefix.
|
|
71
|
+
* @returns The decoded bytes.
|
|
72
|
+
*/
|
|
73
|
+
export function hexToBytes(hex) {
|
|
74
|
+
const digits = stripHexPrefix(hex);
|
|
75
|
+
const out = new Uint8Array(digits.length >> 1);
|
|
76
|
+
for (let i = 0; i < out.length; i++) {
|
|
77
|
+
out[i] = Number.parseInt(digits.slice(2 * i, 2 * i + 2), 16);
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The ascii tag of a zero-padded `Bytes<N>` name (the Compact `pad(N, "text")`
|
|
83
|
+
* convention): decode the hex, then trim the trailing NUL padding.
|
|
84
|
+
*
|
|
85
|
+
* @param nameHex - The indexer's hex-encoded `Misc.name`.
|
|
86
|
+
* @returns The trimmed ascii tag, e.g. `"SignBidirectionalEvent"`.
|
|
87
|
+
*/
|
|
88
|
+
export function eventNameTag(nameHex) {
|
|
89
|
+
return new TextDecoder().decode(hexToBytes(nameHex)).replace(/\0+$/, "");
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Decode a `Misc` payload (`serialize<SignBidirectionalEvent, 256>`) into the
|
|
93
|
+
* struct. The event is a frozen `{ version: Uint<8>, payload: Bytes<224> }`
|
|
94
|
+
* envelope, and V1 packs the concrete fields into that inner payload with
|
|
95
|
+
* `serialize<SignBidirectionalEventV1Payload, 224>`. `serialize<T,N>` lays
|
|
96
|
+
* fields out in declaration order, packed at the front and right-zero-padded
|
|
97
|
+
* (see knowledge-base/events.md), so in the outer 256-byte payload:
|
|
98
|
+
* `version = payload[0]`, then everything shifts one byte —
|
|
99
|
+
* `callerAddress = payload[1..33]`, `requestId = payload[33..65]`,
|
|
100
|
+
* `requestsIndexField = payload[65]`.
|
|
101
|
+
*
|
|
102
|
+
* The byte layout is pinned against a live indexer by the golden e2e test —
|
|
103
|
+
* `callerAddress` is the V1 payload's FIRST field, a different position than the
|
|
104
|
+
* DepositEvent precedent's `caller`, so do not assume it without that test.
|
|
105
|
+
*
|
|
106
|
+
* Fails closed on an unrecognised `version`: a future payload layout adds a
|
|
107
|
+
* branch here (and, off-chain, a V{N} decoder) rather than silently
|
|
108
|
+
* misinterpreting bytes under the V1 offsets.
|
|
109
|
+
*
|
|
110
|
+
* @param payload - The decoded (raw bytes) `Misc.payload`.
|
|
111
|
+
* @returns The decoded event notification.
|
|
112
|
+
* @throws Error if the payload is shorter than the fixed fields require, or its
|
|
113
|
+
* `version` is not one this decoder understands.
|
|
114
|
+
*/
|
|
115
|
+
export function decodeSignBidirectionalEvent(payload) {
|
|
116
|
+
if (payload.length < MIN_PAYLOAD_BYTES) {
|
|
117
|
+
throw new Error(`SignBidirectionalEvent payload is ${payload.length} bytes — fewer than ` +
|
|
118
|
+
`the ${MIN_PAYLOAD_BYTES} its fixed fields need`);
|
|
119
|
+
}
|
|
120
|
+
const version = payload[0];
|
|
121
|
+
if (version !== SUPPORTED_VERSION) {
|
|
122
|
+
throw new Error(`SignBidirectionalEvent version ${version} is not supported ` +
|
|
123
|
+
`(this decoder understands version ${SUPPORTED_VERSION})`);
|
|
124
|
+
}
|
|
125
|
+
const callerAddress = bytesToHex(payload.slice(CALLER_ADDRESS_OFFSET, CALLER_ADDRESS_OFFSET + CALLER_ADDRESS_BYTES));
|
|
126
|
+
const requestId = requestIdHex(payload.slice(REQUEST_ID_OFFSET, REQUEST_ID_OFFSET + REQUEST_ID_BYTES));
|
|
127
|
+
const requestsIndexField = payload[REQUESTS_INDEX_FIELD_OFFSET];
|
|
128
|
+
return { version, callerAddress, requestId, requestsIndexField };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The `Misc` event `name` tag the signet contract emits alongside the
|
|
132
|
+
* serialized {@link SignatureRespondedEvent} payload (Compact:
|
|
133
|
+
* `pad(32, "SignatureRespondedEvent")`). Observers filter on this ascii tag.
|
|
134
|
+
*/
|
|
135
|
+
export const SIGNATURE_RESPONDED_EVENT_TAG = "SignatureRespondedEvent";
|
|
136
|
+
/** Byte width of the `count` field (Compact `Uint<64>` = 8 bytes, little-endian). */
|
|
137
|
+
const COUNT_BYTES = 8;
|
|
138
|
+
/**
|
|
139
|
+
* Minimum serialized length of a {@link SignatureRespondedEvent}: `requestId`
|
|
140
|
+
* (32) + `count` (8). `serialize<T,256>` right-pads to 256, so a real payload
|
|
141
|
+
* is longer; this is the floor the decoder needs.
|
|
142
|
+
*/
|
|
143
|
+
const MIN_RESPONDED_PAYLOAD_BYTES = REQUEST_ID_BYTES + COUNT_BYTES;
|
|
144
|
+
/**
|
|
145
|
+
* Decode a `Misc` payload (`serialize<SignatureRespondedEvent, 256>`) into
|
|
146
|
+
* the struct. Layout per knowledge-base/events.md: fields in declaration
|
|
147
|
+
* order packed at the front — `requestId = payload[0..32]` (raw bytes),
|
|
148
|
+
* `count = payload[32..40]` (Uint<64>, LITTLE-endian) — right-zero-padded.
|
|
149
|
+
*
|
|
150
|
+
* @param payload - The decoded (raw bytes) `Misc.payload`.
|
|
151
|
+
* @returns The decoded event notification.
|
|
152
|
+
* @throws Error if the payload is shorter than the fixed fields require.
|
|
153
|
+
*/
|
|
154
|
+
export function decodeSignatureRespondedEvent(payload) {
|
|
155
|
+
if (payload.length < MIN_RESPONDED_PAYLOAD_BYTES) {
|
|
156
|
+
throw new Error(`SignatureRespondedEvent payload is ${payload.length} bytes — fewer than ` +
|
|
157
|
+
`the ${MIN_RESPONDED_PAYLOAD_BYTES} its fixed fields need`);
|
|
158
|
+
}
|
|
159
|
+
const requestId = requestIdHex(payload.slice(0, REQUEST_ID_BYTES));
|
|
160
|
+
let count = 0n;
|
|
161
|
+
for (let i = REQUEST_ID_BYTES + COUNT_BYTES - 1; i >= REQUEST_ID_BYTES; i--) {
|
|
162
|
+
count = (count << 8n) | BigInt(payload[i]);
|
|
163
|
+
}
|
|
164
|
+
return { requestId, count };
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* The `Misc` event `name` tag the signet contract emits alongside the
|
|
168
|
+
* serialized {@link RespondBidirectionalEvent} payload (Compact:
|
|
169
|
+
* `pad(32, "RespondBidirectionalEvent")`). Observers filter on this ascii tag.
|
|
170
|
+
*/
|
|
171
|
+
export const RESPOND_BIDIRECTIONAL_EVENT_TAG = "RespondBidirectionalEvent";
|
|
172
|
+
/**
|
|
173
|
+
* Minimum serialized length of a {@link RespondBidirectionalEvent}:
|
|
174
|
+
* `requestId` (32). `serialize<T,256>` right-pads to 256, so a real payload
|
|
175
|
+
* is longer; this is the floor the decoder needs.
|
|
176
|
+
*/
|
|
177
|
+
const MIN_RESPOND_BIDIRECTIONAL_PAYLOAD_BYTES = REQUEST_ID_BYTES;
|
|
178
|
+
/**
|
|
179
|
+
* Decode a `Misc` payload (`serialize<RespondBidirectionalEvent, 256>`) into
|
|
180
|
+
* the struct. Layout per knowledge-base/events.md: fields in declaration
|
|
181
|
+
* order packed at the front — `requestId = payload[0..32]` (raw bytes) —
|
|
182
|
+
* right-zero-padded.
|
|
183
|
+
*
|
|
184
|
+
* @param payload - The decoded (raw bytes) `Misc.payload`.
|
|
185
|
+
* @returns The decoded event notification.
|
|
186
|
+
* @throws Error if the payload is shorter than the fixed fields require.
|
|
187
|
+
*/
|
|
188
|
+
export function decodeRespondBidirectionalEvent(payload) {
|
|
189
|
+
if (payload.length < MIN_RESPOND_BIDIRECTIONAL_PAYLOAD_BYTES) {
|
|
190
|
+
throw new Error(`RespondBidirectionalEvent payload is ${payload.length} bytes — fewer than ` +
|
|
191
|
+
`the ${MIN_RESPOND_BIDIRECTIONAL_PAYLOAD_BYTES} its fixed fields need`);
|
|
192
|
+
}
|
|
193
|
+
return { requestId: requestIdHex(payload.slice(0, REQUEST_ID_BYTES)) };
|
|
194
|
+
}
|
|
195
|
+
/** The {@link SignetMiscEventCodec} of {@link SignBidirectionalEvent} notifications. */
|
|
196
|
+
export const signBidirectionalEventCodec = {
|
|
197
|
+
tag: SIGN_BIDIRECTIONAL_EVENT_TAG,
|
|
198
|
+
decode: decodeSignBidirectionalEvent,
|
|
199
|
+
};
|
|
200
|
+
/** The {@link SignetMiscEventCodec} of {@link SignatureRespondedEvent} notifications. */
|
|
201
|
+
export const signatureRespondedEventCodec = {
|
|
202
|
+
tag: SIGNATURE_RESPONDED_EVENT_TAG,
|
|
203
|
+
decode: decodeSignatureRespondedEvent,
|
|
204
|
+
};
|
|
205
|
+
/** The {@link SignetMiscEventCodec} of {@link RespondBidirectionalEvent} notifications. */
|
|
206
|
+
export const respondBidirectionalEventCodec = {
|
|
207
|
+
tag: RESPOND_BIDIRECTIONAL_EVENT_TAG,
|
|
208
|
+
decode: decodeRespondBidirectionalEvent,
|
|
209
|
+
};
|
|
210
|
+
//# sourceMappingURL=signet-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signet-events.js","sourceRoot":"","sources":["../src/signet-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type SignetEventSource } from "./signet-event-observer.ts";
|
|
2
|
+
import { type ResolvedSignetRequest } from "./signet-request-resolver.ts";
|
|
3
|
+
import type { SignetPublicStateSource } from "./signet-request-response-reader.ts";
|
|
4
|
+
import type { RequestIdHex } from "./signet-requests.ts";
|
|
5
|
+
/** Default gap between poll cycles of {@link SignetRequestFeed.requests}. */
|
|
6
|
+
export declare const DEFAULT_FEED_POLL_INTERVAL_MS = 3000;
|
|
7
|
+
/** Everything a {@link SignetRequestFeed} needs. */
|
|
8
|
+
export interface SignetRequestFeedConfig {
|
|
9
|
+
/** Address of the central signet contract whose events to watch. */
|
|
10
|
+
readonly signetContractAddress: string;
|
|
11
|
+
/**
|
|
12
|
+
* Source of BOTH events and raw contract state — a full
|
|
13
|
+
* `indexerPublicDataProvider` satisfies both halves.
|
|
14
|
+
*/
|
|
15
|
+
readonly source: SignetEventSource & SignetPublicStateSource;
|
|
16
|
+
/**
|
|
17
|
+
* Optional policy allow-list of requester contract addresses to serve
|
|
18
|
+
* (matched case- and `0x`-prefix-insensitively). Omit to serve every
|
|
19
|
+
* requester the resolver can authenticate. NOT a security control.
|
|
20
|
+
*/
|
|
21
|
+
readonly allowContracts?: Iterable<string>;
|
|
22
|
+
/** Durable resume floor for the underlying observer (see {@link SignetEventObserverConfig.fromEventId}). */
|
|
23
|
+
readonly fromEventId?: number;
|
|
24
|
+
/** Poll cadence for {@link SignetRequestFeed.requests}; default {@link DEFAULT_FEED_POLL_INTERVAL_MS}. */
|
|
25
|
+
readonly pollIntervalMs?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The event-driven request feed. Composes a {@link SignetEventObserver}
|
|
29
|
+
* (discovery) with a {@link SignetRequestResolver} (authentication), yielding
|
|
30
|
+
* only notifications that resolve to a real, member request. Dedupes by request
|
|
31
|
+
* id across its lifetime, so a redelivered notification is not re-yielded; call
|
|
32
|
+
* {@link forget} to re-arm a request whose downstream processing failed.
|
|
33
|
+
*/
|
|
34
|
+
export declare class SignetRequestFeed {
|
|
35
|
+
private readonly observer;
|
|
36
|
+
private readonly resolver;
|
|
37
|
+
private readonly allowContracts?;
|
|
38
|
+
private readonly pollIntervalMs;
|
|
39
|
+
private readonly yielded;
|
|
40
|
+
/**
|
|
41
|
+
* @param config - The signet contract, combined event/state source, optional
|
|
42
|
+
* policy allow-list, and resume floor.
|
|
43
|
+
*/
|
|
44
|
+
constructor(config: SignetRequestFeedConfig);
|
|
45
|
+
/** Whether the policy allow-list admits `callerAddress` (always true when unset). */
|
|
46
|
+
private allowed;
|
|
47
|
+
/**
|
|
48
|
+
* One-shot: every currently-visible notification that is admitted by the
|
|
49
|
+
* allow-list, not already yielded, and resolves to an authenticated member
|
|
50
|
+
* request. Forged / not-yet-indexed / wrong-field notifications resolve to
|
|
51
|
+
* nothing and are dropped WITHOUT being marked yielded, so a genuine
|
|
52
|
+
* request whose ledger write has not indexed yet is retried next cycle.
|
|
53
|
+
*
|
|
54
|
+
* @returns The newly-authenticated requests this cycle, in event id order.
|
|
55
|
+
*/
|
|
56
|
+
poll(): Promise<ResolvedSignetRequest[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Re-arm `requestId` for redelivery on the next {@link poll} / {@link requests}
|
|
59
|
+
* cycle — call when downstream processing of a yielded request failed, so it
|
|
60
|
+
* is retried (mirrors the MPC's delete-on-failure of its processed set).
|
|
61
|
+
*
|
|
62
|
+
* @param requestId - The request id to allow through again.
|
|
63
|
+
*/
|
|
64
|
+
forget(requestId: RequestIdHex): void;
|
|
65
|
+
/**
|
|
66
|
+
* Live stream: poll + sleep, yielding each authenticated request exactly once
|
|
67
|
+
* (subject to {@link forget}), until `opts.signal` aborts. The natural
|
|
68
|
+
* sequential `for await` consumption serializes downstream processing — no
|
|
69
|
+
* two requests are handed over concurrently.
|
|
70
|
+
*
|
|
71
|
+
* @param opts.signal - Abort to stop the stream.
|
|
72
|
+
* @yields Each authenticated request, in discovery order.
|
|
73
|
+
*/
|
|
74
|
+
requests(opts?: {
|
|
75
|
+
signal?: AbortSignal;
|
|
76
|
+
}): AsyncIterableIterator<ResolvedSignetRequest>;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=signet-request-feed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signet-request-feed.d.ts","sourceRoot":"","sources":["../src/signet-request-feed.ts"],"names":[],"mappings":"AAaA,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,4BAA4B,CAAC;AAMpC,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,6EAA6E;AAC7E,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,uBAAuB,CAAC;IAC7D;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3C,4GAA4G;IAC5G,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,0GAA0G;IAC1G,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAOD;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8C;IACvE,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;IAgB3C,qFAAqF;IACrF,OAAO,CAAC,OAAO;IAOf;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAc9C;;;;;;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"}
|