@did-btcr2/method 0.29.0 → 0.32.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/README.md +13 -5
- package/dist/.tsbuildinfo +1 -1
- package/dist/browser.js +8174 -7157
- package/dist/browser.mjs +8174 -7157
- package/dist/cjs/index.js +1845 -455
- package/dist/esm/core/aggregation/transport/factory.js +15 -6
- package/dist/esm/core/aggregation/transport/factory.js.map +1 -1
- package/dist/esm/core/aggregation/transport/http/client.js +350 -0
- package/dist/esm/core/aggregation/transport/http/client.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/envelope.js +126 -0
- package/dist/esm/core/aggregation/transport/http/envelope.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/errors.js +11 -0
- package/dist/esm/core/aggregation/transport/http/errors.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/inbox-buffer.js +45 -0
- package/dist/esm/core/aggregation/transport/http/inbox-buffer.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/index.js +12 -0
- package/dist/esm/core/aggregation/transport/http/index.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/nonce-cache.js +38 -0
- package/dist/esm/core/aggregation/transport/http/nonce-cache.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/protocol.js +28 -0
- package/dist/esm/core/aggregation/transport/http/protocol.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/rate-limiter.js +45 -0
- package/dist/esm/core/aggregation/transport/http/rate-limiter.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/request-auth.js +100 -0
- package/dist/esm/core/aggregation/transport/http/request-auth.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/server.js +481 -0
- package/dist/esm/core/aggregation/transport/http/server.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/sse-stream.js +110 -0
- package/dist/esm/core/aggregation/transport/http/sse-stream.js.map +1 -0
- package/dist/esm/core/aggregation/transport/http/sse-writer.js +25 -0
- package/dist/esm/core/aggregation/transport/http/sse-writer.js.map +1 -0
- package/dist/esm/core/aggregation/transport/index.js +1 -0
- package/dist/esm/core/aggregation/transport/index.js.map +1 -1
- package/dist/esm/core/beacon/beacon.js +197 -51
- package/dist/esm/core/beacon/beacon.js.map +1 -1
- package/dist/esm/core/beacon/cas-beacon.js +3 -3
- package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
- package/dist/esm/core/beacon/singleton-beacon.js +3 -3
- package/dist/esm/core/beacon/singleton-beacon.js.map +1 -1
- package/dist/esm/core/beacon/smt-beacon.js +3 -3
- package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
- package/dist/esm/core/updater.js +63 -55
- package/dist/esm/core/updater.js.map +1 -1
- package/dist/types/core/aggregation/transport/factory.d.ts +22 -7
- package/dist/types/core/aggregation/transport/factory.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/http/client.d.ts +48 -0
- package/dist/types/core/aggregation/transport/http/client.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/envelope.d.ts +64 -0
- package/dist/types/core/aggregation/transport/http/envelope.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/errors.d.ts +9 -0
- package/dist/types/core/aggregation/transport/http/errors.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/inbox-buffer.d.ts +32 -0
- package/dist/types/core/aggregation/transport/http/inbox-buffer.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/index.d.ts +12 -0
- package/dist/types/core/aggregation/transport/http/index.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/nonce-cache.d.ts +26 -0
- package/dist/types/core/aggregation/transport/http/nonce-cache.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/protocol.d.ts +53 -0
- package/dist/types/core/aggregation/transport/http/protocol.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/rate-limiter.d.ts +41 -0
- package/dist/types/core/aggregation/transport/http/rate-limiter.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/request-auth.d.ts +50 -0
- package/dist/types/core/aggregation/transport/http/request-auth.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/server.d.ts +110 -0
- package/dist/types/core/aggregation/transport/http/server.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/sse-stream.d.ts +34 -0
- package/dist/types/core/aggregation/transport/http/sse-stream.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/http/sse-writer.d.ts +12 -0
- package/dist/types/core/aggregation/transport/http/sse-writer.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/index.d.ts +1 -0
- package/dist/types/core/aggregation/transport/index.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/transport.d.ts +1 -1
- package/dist/types/core/aggregation/transport/transport.d.ts.map +1 -1
- package/dist/types/core/beacon/beacon.d.ts +72 -12
- package/dist/types/core/beacon/beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts +3 -3
- package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/singleton-beacon.d.ts +3 -3
- package/dist/types/core/beacon/singleton-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/smt-beacon.d.ts +3 -3
- package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
- package/dist/types/core/updater.d.ts +27 -12
- package/dist/types/core/updater.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/core/aggregation/transport/factory.ts +48 -12
- package/src/core/aggregation/transport/http/client.ts +409 -0
- package/src/core/aggregation/transport/http/envelope.ts +204 -0
- package/src/core/aggregation/transport/http/errors.ts +11 -0
- package/src/core/aggregation/transport/http/inbox-buffer.ts +53 -0
- package/src/core/aggregation/transport/http/index.ts +11 -0
- package/src/core/aggregation/transport/http/nonce-cache.ts +43 -0
- package/src/core/aggregation/transport/http/protocol.ts +57 -0
- package/src/core/aggregation/transport/http/rate-limiter.ts +75 -0
- package/src/core/aggregation/transport/http/request-auth.ts +164 -0
- package/src/core/aggregation/transport/http/server.ts +615 -0
- package/src/core/aggregation/transport/http/sse-stream.ts +121 -0
- package/src/core/aggregation/transport/http/sse-writer.ts +23 -0
- package/src/core/aggregation/transport/index.ts +1 -0
- package/src/core/aggregation/transport/transport.ts +1 -1
- package/src/core/beacon/beacon.ts +255 -64
- package/src/core/beacon/cas-beacon.ts +4 -4
- package/src/core/beacon/singleton-beacon.ts +4 -4
- package/src/core/beacon/smt-beacon.ts +4 -4
- package/src/core/updater.ts +113 -67
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface BucketState {
|
|
2
|
+
tokens: number;
|
|
3
|
+
lastRefillMs: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Pluggable storage backend for rate-limit state. The default
|
|
7
|
+
* {@link InMemoryRateLimitStore} is a plain Map; swap in Redis-backed or
|
|
8
|
+
* SQLite-backed implementations for multi-instance deployments.
|
|
9
|
+
*/
|
|
10
|
+
export interface RateLimitStore {
|
|
11
|
+
get(key: string): BucketState | undefined;
|
|
12
|
+
set(key: string, state: BucketState): void;
|
|
13
|
+
}
|
|
14
|
+
export declare class InMemoryRateLimitStore implements RateLimitStore {
|
|
15
|
+
#private;
|
|
16
|
+
get(key: string): BucketState | undefined;
|
|
17
|
+
set(key: string, state: BucketState): void;
|
|
18
|
+
}
|
|
19
|
+
export interface RateLimiterConfig {
|
|
20
|
+
/** Steady-state request rate per key (requests per second). Default 10. */
|
|
21
|
+
rps?: number;
|
|
22
|
+
/** Peak burst allowance (bucket capacity). Default 30. */
|
|
23
|
+
burst?: number;
|
|
24
|
+
/** Optional pluggable store. Defaults to an in-memory Map. */
|
|
25
|
+
store?: RateLimitStore;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Token-bucket rate limiter keyed by an opaque string (typically a verified
|
|
29
|
+
* sender DID). Tokens refill linearly at `rps` up to `burst`. Each `consume`
|
|
30
|
+
* call atomically debits one token or returns `false` to reject.
|
|
31
|
+
*
|
|
32
|
+
* The limiter is synchronous and deterministic given `nowMs` — tests can
|
|
33
|
+
* drive it with a fixed clock to exercise exact boundaries.
|
|
34
|
+
*/
|
|
35
|
+
export declare class RateLimiter {
|
|
36
|
+
#private;
|
|
37
|
+
constructor(config?: RateLimiterConfig);
|
|
38
|
+
/** Consume one token for `key`. Returns `true` if accepted, `false` if throttled. */
|
|
39
|
+
consume(key: string, nowMs: number): boolean;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../../../../../src/core/aggregation/transport/http/rate-limiter.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IAC1C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5C;AAED,qBAAa,sBAAuB,YAAW,cAAc;;IAG3D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAIzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;CAG3C;AAED,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,qBAAa,WAAW;;gBAKV,MAAM,GAAE,iBAAsB;IAM1C,qFAAqF;IACrF,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;CAkB7C"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { CompressedSecp256k1PublicKey, SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
2
|
+
/**
|
|
3
|
+
* `Authorization`-header scheme used to authenticate SSE subscription
|
|
4
|
+
* requests. The header value takes the form
|
|
5
|
+
* `BTCR2-Sig v=<n>,did=<did>,ts=<unix>,nonce=<hex>,sig=<hex>`.
|
|
6
|
+
*
|
|
7
|
+
* Used only for GET endpoints (SSE inbox subscribe). POST endpoints carry a
|
|
8
|
+
* full {@link SignedEnvelope} in the request body instead.
|
|
9
|
+
*/
|
|
10
|
+
export declare const REQUEST_AUTH_SCHEME = "BTCR2-Sig";
|
|
11
|
+
export interface ParsedRequestAuth {
|
|
12
|
+
/** Transport envelope format version. */
|
|
13
|
+
v: number;
|
|
14
|
+
/** Subscriber DID. */
|
|
15
|
+
did: string;
|
|
16
|
+
/** Unix-seconds timestamp. */
|
|
17
|
+
ts: number;
|
|
18
|
+
/** Hex-encoded anti-replay nonce. */
|
|
19
|
+
nonce: string;
|
|
20
|
+
/** Hex-encoded 64-byte BIP340 signature. */
|
|
21
|
+
sig: string;
|
|
22
|
+
}
|
|
23
|
+
export interface BuildRequestAuthOptions {
|
|
24
|
+
nonce?: string;
|
|
25
|
+
timestamp?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build an `Authorization` header value proving the caller controls the
|
|
29
|
+
* private key for `did`. Covers a specific request path so the signature
|
|
30
|
+
* can't be replayed against a different endpoint.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildRequestAuth(did: string, keys: SchnorrKeyPair, path: string, opts?: BuildRequestAuthOptions): string;
|
|
33
|
+
/**
|
|
34
|
+
* Parse a `BTCR2-Sig` auth header value into its structured fields. Does NOT
|
|
35
|
+
* verify the signature — call {@link verifyRequestAuth} for that.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseRequestAuth(headerValue: string): ParsedRequestAuth;
|
|
38
|
+
export interface VerifyRequestAuthOptions {
|
|
39
|
+
clockSkewSec?: number;
|
|
40
|
+
now?: () => number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Parse + verify an auth header. Throws {@link HttpTransportError} on any
|
|
44
|
+
* failure; returns the parsed fields on success.
|
|
45
|
+
*
|
|
46
|
+
* `expectedPath` must match the path the signature commits to. `senderPk`
|
|
47
|
+
* must correspond to the DID the signer claims.
|
|
48
|
+
*/
|
|
49
|
+
export declare function verifyRequestAuth(headerValue: string, expectedPath: string, senderPk: CompressedSecp256k1PublicKey, opts?: VerifyRequestAuthOptions): ParsedRequestAuth;
|
|
50
|
+
//# sourceMappingURL=request-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-auth.d.ts","sourceRoot":"","sources":["../../../../../../src/core/aggregation/transport/http/request-auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,4BAA4B,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAMvF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,CAAC,EAAE,MAAM,CAAC;IACV,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAG,MAAM,EACZ,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,uBAA4B,GACjC,MAAM,CAcR;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,CA4BvE;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAG,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAM,4BAA4B,EAC1C,IAAI,GAAU,wBAA6B,GAC1C,iBAAiB,CAmDnB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
2
|
+
import type { Logger } from '../../logger.js';
|
|
3
|
+
import type { BaseMessage } from '../../messages/base.js';
|
|
4
|
+
import type { MessageHandler, Transport } from '../transport.js';
|
|
5
|
+
import { NonceCache } from './nonce-cache.js';
|
|
6
|
+
import { RateLimiter } from './rate-limiter.js';
|
|
7
|
+
/** Framework-agnostic incoming-request shape. */
|
|
8
|
+
export interface HttpRequestLike {
|
|
9
|
+
method: string;
|
|
10
|
+
/** Either a full URL or path+query; path extraction works with both. */
|
|
11
|
+
url: string;
|
|
12
|
+
/** Header names MUST be lowercased. */
|
|
13
|
+
headers: Record<string, string>;
|
|
14
|
+
/** Request body (already read). Undefined for GETs. */
|
|
15
|
+
body?: string;
|
|
16
|
+
/** Optional remote-address hint for per-IP policies (advert rate limits etc). */
|
|
17
|
+
remoteAddr?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Framework-agnostic outgoing-response shape. */
|
|
20
|
+
export interface HttpResponseLike {
|
|
21
|
+
status: number;
|
|
22
|
+
headers: Record<string, string>;
|
|
23
|
+
body: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Framework-agnostic SSE stream handle. Callers (Express/Hono/Fastify/Workers)
|
|
27
|
+
* adapt this to their response-writing primitives. All methods are synchronous
|
|
28
|
+
* from the transport's perspective; the adapter is free to buffer/batch.
|
|
29
|
+
*/
|
|
30
|
+
export interface SseStream {
|
|
31
|
+
/** Write a named event with data and optional id. */
|
|
32
|
+
writeEvent(event: string, data: string, id?: string): void;
|
|
33
|
+
/** Write a comment frame (keepalive; ignored by parsers). */
|
|
34
|
+
writeComment(comment: string): void;
|
|
35
|
+
/** Close the stream from the server side. */
|
|
36
|
+
close(): void;
|
|
37
|
+
/** Register a callback fired when the client disconnects (or we close). */
|
|
38
|
+
onClose(cb: () => void): void;
|
|
39
|
+
}
|
|
40
|
+
export type CorsPolicy = {
|
|
41
|
+
mode: 'permissive';
|
|
42
|
+
} | {
|
|
43
|
+
mode: 'allowlist';
|
|
44
|
+
origins: string[];
|
|
45
|
+
} | {
|
|
46
|
+
mode: 'same-origin';
|
|
47
|
+
};
|
|
48
|
+
export interface HttpServerTransportConfig {
|
|
49
|
+
logger?: Logger;
|
|
50
|
+
/** CORS policy. Defaults to `{ mode: 'permissive' }`. */
|
|
51
|
+
cors?: CorsPolicy;
|
|
52
|
+
/** Envelope / request-auth clock-skew tolerance, seconds. */
|
|
53
|
+
clockSkewSec?: number;
|
|
54
|
+
/** Per-recipient inbox buffer size. Default 100. */
|
|
55
|
+
inboxBufferSize?: number;
|
|
56
|
+
/** Advert cache TTL, milliseconds. Default 5 minutes. */
|
|
57
|
+
advertTtlMs?: number;
|
|
58
|
+
/** Custom rate limiter (pre-configured). If absent, uses defaults. */
|
|
59
|
+
rateLimiter?: RateLimiter;
|
|
60
|
+
/** Custom nonce cache (pre-configured). If absent, uses defaults. */
|
|
61
|
+
nonceCache?: NonceCache;
|
|
62
|
+
/** SSE heartbeat interval, milliseconds. Default 20000. Set 0 to disable. */
|
|
63
|
+
heartbeatIntervalMs?: number;
|
|
64
|
+
/** Clock injection point for tests. Returns unix milliseconds. */
|
|
65
|
+
now?: () => number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Server-side HTTP transport. Sans-I/O — the caller mounts
|
|
69
|
+
* {@link handleRequest} and {@link handleSse} under their HTTP framework of
|
|
70
|
+
* choice; the transport owns only in-memory state (actors, inboxes, advert
|
|
71
|
+
* cache, replay / rate-limit policies).
|
|
72
|
+
*
|
|
73
|
+
* Implements the generic {@link Transport} interface so the aggregation
|
|
74
|
+
* runners can drive it exactly the same way they drive {@link NostrTransport}
|
|
75
|
+
* or {@link HttpClientTransport}.
|
|
76
|
+
*/
|
|
77
|
+
export declare class HttpServerTransport implements Transport {
|
|
78
|
+
#private;
|
|
79
|
+
readonly name = "http";
|
|
80
|
+
constructor(config?: HttpServerTransportConfig);
|
|
81
|
+
start(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Detach the transport: close every open SSE subscription, clear the advert
|
|
84
|
+
* cache, and drop all actor / peer / inbox state. Intended for shutdown and
|
|
85
|
+
* for test teardown.
|
|
86
|
+
*/
|
|
87
|
+
stop(): void;
|
|
88
|
+
registerActor(did: string, keys: SchnorrKeyPair): void;
|
|
89
|
+
unregisterActor(did: string): void;
|
|
90
|
+
getActorPk(did: string): Uint8Array | undefined;
|
|
91
|
+
registerPeer(did: string, communicationPk: Uint8Array): void;
|
|
92
|
+
getPeerPk(did: string): Uint8Array | undefined;
|
|
93
|
+
registerMessageHandler(actorDid: string, messageType: string, handler: MessageHandler): void;
|
|
94
|
+
unregisterMessageHandler(actorDid: string, messageType: string): void;
|
|
95
|
+
sendMessage(message: BaseMessage, sender: string, recipient?: string): Promise<void>;
|
|
96
|
+
publishRepeating(message: BaseMessage, sender: string, _intervalMs: number, _recipient?: string): () => void;
|
|
97
|
+
/**
|
|
98
|
+
* Handle a POST / GET request (non-SSE). The caller dispatches SSE paths to
|
|
99
|
+
* {@link handleSse} instead. Returns a fully formed response; the caller's
|
|
100
|
+
* adapter turns it into an HTTP write.
|
|
101
|
+
*/
|
|
102
|
+
handleRequest(req: HttpRequestLike): Promise<HttpResponseLike>;
|
|
103
|
+
/**
|
|
104
|
+
* Open an SSE stream for a GET request. The caller is responsible for
|
|
105
|
+
* flushing writes and propagating the `onClose` callback when the HTTP
|
|
106
|
+
* connection ends.
|
|
107
|
+
*/
|
|
108
|
+
handleSse(req: HttpRequestLike, stream: SseStream): void;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../../../src/core/aggregation/transport/http/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parsed Server-Sent Events record.
|
|
3
|
+
*
|
|
4
|
+
* Events without a `data` field are never yielded (per the SSE spec — only a
|
|
5
|
+
* blank line that follows at least one `data:` line dispatches an event).
|
|
6
|
+
*/
|
|
7
|
+
export interface SseEvent {
|
|
8
|
+
/** Optional event name (from `event:` field). Defaults to "message" if omitted. */
|
|
9
|
+
event?: string;
|
|
10
|
+
/** Accumulated data payload (multiple `data:` lines joined with `\n`). */
|
|
11
|
+
data: string;
|
|
12
|
+
/** Last-Event-ID value for reconnect resumption. */
|
|
13
|
+
id?: string;
|
|
14
|
+
/** Retry delay hint in milliseconds. */
|
|
15
|
+
retry?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse an SSE stream into an async iterable of {@link SseEvent} records.
|
|
19
|
+
*
|
|
20
|
+
* The parser follows the HTML Living Standard ({@link https://html.spec.whatwg.org/multipage/server-sent-events.html})
|
|
21
|
+
* closely enough for our needs: LF and CRLF line terminators, multi-line
|
|
22
|
+
* `data` fields, `event` / `id` / `retry` fields, and `:`-prefixed comments.
|
|
23
|
+
* CR-only line terminators are not supported (every mainstream SSE
|
|
24
|
+
* implementation emits LF or CRLF).
|
|
25
|
+
*
|
|
26
|
+
* Pure, runtime-agnostic — works anywhere `ReadableStream<Uint8Array>` and
|
|
27
|
+
* `TextDecoder` exist (browsers and Node 22+).
|
|
28
|
+
*
|
|
29
|
+
* The caller owns stream lifecycle: cancellation should be effected via an
|
|
30
|
+
* `AbortController` on the producing `fetch`, which propagates as a read
|
|
31
|
+
* error and cleanly unwinds this generator's `finally`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseSseStream(readable: ReadableStream<Uint8Array>): AsyncGenerator<SseEvent, void, void>;
|
|
34
|
+
//# sourceMappingURL=sse-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-stream.d.ts","sourceRoot":"","sources":["../../../../../../src/core/aggregation/transport/http/sse-stream.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAuB,cAAc,CACnC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,GACnC,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAqFtC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format an SSE event frame. Pairs with {@link parseSseStream}.
|
|
3
|
+
*
|
|
4
|
+
* Multi-line `data` is split across multiple `data:` lines per the SSE spec —
|
|
5
|
+
* each embedded `\n` becomes its own line, and the parser rejoins them.
|
|
6
|
+
*
|
|
7
|
+
* The returned string includes a trailing blank line (the dispatch marker).
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatSseEvent(event: string, data: string, id?: string): string;
|
|
10
|
+
/** SSE comment frame (server keepalive). Lines starting with `:` are ignored by compliant parsers. */
|
|
11
|
+
export declare function formatSseComment(comment: string): string;
|
|
12
|
+
//# sourceMappingURL=sse-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-writer.d.ts","sourceRoot":"","sources":["../../../../../../src/core/aggregation/transport/http/sse-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ/E;AAED,sGAAsG;AACtG,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGxD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/aggregation/transport/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/aggregation/transport/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
|
|
@@ -3,7 +3,7 @@ import type { BaseMessage } from '../messages/base.js';
|
|
|
3
3
|
export type SyncMessageHandler = (msg: any) => void;
|
|
4
4
|
export type AsyncMessageHandler = (msg: any) => Promise<void>;
|
|
5
5
|
export type MessageHandler = SyncMessageHandler | AsyncMessageHandler;
|
|
6
|
-
export type TransportType = 'nostr' | 'didcomm';
|
|
6
|
+
export type TransportType = 'nostr' | 'didcomm' | 'http';
|
|
7
7
|
/**
|
|
8
8
|
* Multi-actor message transport.
|
|
9
9
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../../../src/core/aggregation/transport/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;AACpD,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9D,MAAM,MAAM,cAAc,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;AAEtE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../../../src/core/aggregation/transport/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;AACpD,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9D,MAAM,MAAM,cAAc,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;AAEtE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEzD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IAEb,sEAAsE;IACtE,KAAK,IAAI,IAAI,CAAC;IAEd,sEAAsE;IACtE,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAEvD,uEAAuE;IACvE,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAEhD,4EAA4E;IAC5E,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,GAAG,IAAI,CAAC;IAE7D,yDAAyD;IACzD,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAE/C,6DAA6D;IAC7D,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAE7F,uEAAuE;IACvE,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtE;;;;OAIG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnC,6EAA6E;IAC7E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErF;;;;;;;;;;;;;;;OAeG;IACH,gBAAgB,CACd,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,IAAI,CAAC;CACf"}
|
|
@@ -1,11 +1,52 @@
|
|
|
1
1
|
import type { AddressUtxo, BitcoinConnection, BTCNetwork } from '@did-btcr2/bitcoin';
|
|
2
2
|
import type { KeyBytes } from '@did-btcr2/common';
|
|
3
3
|
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
4
|
+
import type { Signer } from '@did-btcr2/keypair';
|
|
4
5
|
import { Transaction } from '@scure/btc-signer';
|
|
5
6
|
import type { BeaconProcessResult } from '../resolver.js';
|
|
6
7
|
import type { SidecarData } from '../types.js';
|
|
7
8
|
import type { FeeEstimator } from './fee-estimator.js';
|
|
8
9
|
import type { BeaconService, BeaconSignal } from './interfaces.js';
|
|
10
|
+
/**
|
|
11
|
+
* Singleton beacon script kinds. Per the did:btcr2 spec, deterministic DID documents
|
|
12
|
+
* include three beacon services: P2PKH, P2WPKH, and P2TR (taproot key-path) — all
|
|
13
|
+
* derived from the genesis secp256k1 public key. The singleton broadcast path must
|
|
14
|
+
* support signing for all three.
|
|
15
|
+
*/
|
|
16
|
+
export type SingletonScriptKind = 'p2pkh' | 'p2wpkh' | 'p2tr';
|
|
17
|
+
/**
|
|
18
|
+
* Conservative vsize estimate for a 1-input P2TR key-path → 1 P2TR change + 1 OP_RETURN(32) tx.
|
|
19
|
+
* Stripped 137 + witness ≈ 68 (marker + flag + stack-count + sig-len + 64 BIP-340 sig).
|
|
20
|
+
* Weight = 137*4 + 68 = 616, vsize ≈ 154, rounded to 160 for headroom.
|
|
21
|
+
*/
|
|
22
|
+
export declare const P2TR_BEACON_TX_VSIZE = 160;
|
|
23
|
+
/**
|
|
24
|
+
* Conservative vsize estimate for a 1-input P2WPKH → 1 P2WPKH change + 1 OP_RETURN(32) tx.
|
|
25
|
+
* Stripped 125 + witness ≈ 110 (worst-case DER ECDSA sig 72 + sighash byte + 33 pubkey + framing).
|
|
26
|
+
* vsize = ceil((125*4 + 110) / 4) ≈ 153, rounded to 155.
|
|
27
|
+
*/
|
|
28
|
+
export declare const P2WPKH_BEACON_TX_VSIZE = 155;
|
|
29
|
+
/**
|
|
30
|
+
* Conservative vsize estimate for a 1-input P2PKH → 1 P2PKH change + 1 OP_RETURN(32) tx.
|
|
31
|
+
* Legacy (non-segwit): scriptSig carries the full sig+pubkey (~108 bytes), no witness
|
|
32
|
+
* discount. Stripped ≈ 4 nVer + 1 vin-count + (32+4+1+108+4) input + 1 vout-count +
|
|
33
|
+
* 34 P2PKH-change + 43 OP_RETURN + 4 nLockTime ≈ 236 bytes. vsize = 236, rounded to 240.
|
|
34
|
+
*/
|
|
35
|
+
export declare const P2PKH_BEACON_TX_VSIZE = 240;
|
|
36
|
+
/** Per-kind vsize lookup for singleton beacon fee estimation. */
|
|
37
|
+
export declare const SINGLETON_BEACON_TX_VSIZE: Readonly<Record<SingletonScriptKind, number>>;
|
|
38
|
+
/**
|
|
39
|
+
* Detect the singleton script kind of a Bitcoin address (P2PKH / P2WPKH / P2TR).
|
|
40
|
+
* The deterministic-DID document emits all three kinds; the broadcast path needs
|
|
41
|
+
* to know which is in use to construct the input and dispatch the signing primitive.
|
|
42
|
+
*/
|
|
43
|
+
export declare function detectSingletonScriptKind(bitcoinAddress: string, network: BTCNetwork): SingletonScriptKind;
|
|
44
|
+
/**
|
|
45
|
+
* Derive the address that `pubkey` produces under the given script kind. Used to
|
|
46
|
+
* fail-fast when a caller wires a signer to a beacon address that the signer's
|
|
47
|
+
* pubkey cannot actually spend.
|
|
48
|
+
*/
|
|
49
|
+
export declare function deriveSingletonAddress(kind: SingletonScriptKind, pubkey: KeyBytes, network: BTCNetwork): string;
|
|
9
50
|
/**
|
|
10
51
|
* Options accepted by {@link Beacon.buildSignAndBroadcast} and related helpers.
|
|
11
52
|
*/
|
|
@@ -30,11 +71,24 @@ export interface BeaconTxPlan {
|
|
|
30
71
|
utxo: AddressUtxo;
|
|
31
72
|
/** The fee (sats) already deducted from the change output. */
|
|
32
73
|
feeSats: bigint;
|
|
74
|
+
/**
|
|
75
|
+
* Singleton beacon script kind, when applicable. Drives the signing dispatch
|
|
76
|
+
* in {@link Beacon.signSinglePartyTx}. Aggregation plans set this to `'p2tr'`.
|
|
77
|
+
*/
|
|
78
|
+
scriptKind: SingletonScriptKind;
|
|
33
79
|
}
|
|
34
80
|
/**
|
|
35
81
|
* Build an OP_RETURN script carrying a 32-byte beacon signal.
|
|
36
82
|
* Exported as a utility so callers building txs outside Beacon (e.g., the aggregation
|
|
37
83
|
* `onProvideTxData` callback) can produce identical output.
|
|
84
|
+
*
|
|
85
|
+
* Uses the opcode *string* `'RETURN'` rather than the numeric `OP.RETURN`
|
|
86
|
+
* constant because scure's `Script.encode` interprets a number as a byte to
|
|
87
|
+
* push, not as the opcode. The string form emits the bare opcode (0x6a)
|
|
88
|
+
* followed by an `OP_PUSHBYTES_32` push, producing the standard NULL_DATA
|
|
89
|
+
* shape Bitcoin Core's `IsStandard` accepts. The numeric form silently
|
|
90
|
+
* produces `OP_PUSHBYTES_1 0x6a OP_PUSHBYTES_32 <32 bytes>`, which is
|
|
91
|
+
* non-standard and rejected at broadcast with `RPC error -26: scriptpubkey`.
|
|
38
92
|
*/
|
|
39
93
|
export declare function opReturnScript(signalBytes: Uint8Array): Uint8Array;
|
|
40
94
|
/**
|
|
@@ -79,7 +133,6 @@ export declare function buildAggregationBeaconTx(opts: {
|
|
|
79
133
|
* @type {Beacon}
|
|
80
134
|
*/
|
|
81
135
|
export declare abstract class Beacon {
|
|
82
|
-
#private;
|
|
83
136
|
/**
|
|
84
137
|
* The Beacon service configuration parsed from the DID Document.
|
|
85
138
|
*/
|
|
@@ -101,14 +154,17 @@ export declare abstract class Beacon {
|
|
|
101
154
|
* Broadcasts a signed update as a Beacon Signal to the Bitcoin network.
|
|
102
155
|
* Used during the update path.
|
|
103
156
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
104
|
-
* @param {
|
|
157
|
+
* @param {Signer} signer Signer that produces the signature for the spending input.
|
|
158
|
+
* ECDSA for P2PKH / P2WPKH singletons, Schnorr (BIP-340) for P2TR key-path.
|
|
105
159
|
* @param {BitcoinConnection} bitcoin The Bitcoin network connection.
|
|
106
160
|
* @param {BroadcastOptions} [options] Optional broadcast configuration (e.g. fee estimator).
|
|
107
161
|
* @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
|
|
108
162
|
*/
|
|
109
|
-
abstract broadcastSignal(signedUpdate: SignedBTCR2Update,
|
|
163
|
+
abstract broadcastSignal(signedUpdate: SignedBTCR2Update, signer: Signer, bitcoin: BitcoinConnection, options?: BroadcastOptions): Promise<SignedBTCR2Update>;
|
|
110
164
|
/**
|
|
111
|
-
* Build + sign + broadcast a
|
|
165
|
+
* Build + sign + broadcast a singleton beacon signal transaction. The beacon
|
|
166
|
+
* address's script kind (P2PKH / P2WPKH / P2TR) is detected automatically
|
|
167
|
+
* and the input is constructed and signed accordingly.
|
|
112
168
|
*
|
|
113
169
|
* Composed from the three extracted phases ({@link buildSinglePartyTx},
|
|
114
170
|
* {@link signSinglePartyTx}, {@link broadcastRawTx}) so each piece can be exercised
|
|
@@ -117,33 +173,37 @@ export declare abstract class Beacon {
|
|
|
117
173
|
* plumbing (UTXO fetch + OP_RETURN output + change output) is shared.
|
|
118
174
|
*
|
|
119
175
|
* @param signalBytes 32-byte payload to embed in OP_RETURN.
|
|
120
|
-
* @param
|
|
176
|
+
* @param signer Signer used to sign the spending input.
|
|
121
177
|
* @param bitcoin Bitcoin network connection.
|
|
122
178
|
* @param options Broadcast options (fee estimator, etc.).
|
|
123
179
|
* @returns The txid of the broadcast transaction.
|
|
124
180
|
* @throws {BeaconError} if the address is unfunded, no UTXO is available, or fee exceeds value.
|
|
125
181
|
*/
|
|
126
|
-
protected buildSignAndBroadcast(signalBytes: Uint8Array,
|
|
182
|
+
protected buildSignAndBroadcast(signalBytes: Uint8Array, signer: Signer, bitcoin: BitcoinConnection, options?: BroadcastOptions): Promise<string>;
|
|
127
183
|
/**
|
|
128
|
-
* Build an unsigned
|
|
129
|
-
* then rebuild with the real fee. Returns the tx and prev-output metadata.
|
|
184
|
+
* Build an unsigned singleton beacon tx ready for {@link signSinglePartyTx}.
|
|
130
185
|
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
186
|
+
* Detects the beacon address script kind (P2PKH / P2WPKH / P2TR) and configures
|
|
187
|
+
* the input accordingly. Validates that the signer's pubkey produces the beacon
|
|
188
|
+
* address under that script kind — without this check, a misconfigured caller
|
|
189
|
+
* would burn a real UTXO on a tx that fails at broadcast. Fees are computed from
|
|
190
|
+
* the per-kind {@link SINGLETON_BEACON_TX_VSIZE} constant, avoiding any probe-sign
|
|
191
|
+
* round-trip.
|
|
133
192
|
*/
|
|
134
193
|
protected buildSinglePartyTx(opts: {
|
|
135
194
|
signalBytes: Uint8Array;
|
|
136
195
|
beaconAddress: string;
|
|
137
196
|
utxo: AddressUtxo;
|
|
138
197
|
prevTxBytes: Uint8Array;
|
|
139
|
-
|
|
198
|
+
signer: Signer;
|
|
140
199
|
bitcoin: BitcoinConnection;
|
|
141
200
|
feeEstimator: FeeEstimator;
|
|
142
201
|
}): Promise<BeaconTxPlan>;
|
|
143
202
|
/**
|
|
144
203
|
* Sign + finalize the unsigned single-party tx and return its raw hex.
|
|
204
|
+
* Dispatches to the correct signing primitive based on `plan.scriptKind`.
|
|
145
205
|
*/
|
|
146
|
-
protected signSinglePartyTx(
|
|
206
|
+
protected signSinglePartyTx(plan: BeaconTxPlan, signer: Signer): Promise<string>;
|
|
147
207
|
/**
|
|
148
208
|
* Broadcast raw transaction hex via the Bitcoin REST endpoint. Returns the txid.
|
|
149
209
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/beacon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/beacon.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
|
-
import type { KeyBytes } from '@did-btcr2/common';
|
|
3
2
|
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
3
|
+
import type { Signer } from '@did-btcr2/keypair';
|
|
4
4
|
import type { BeaconProcessResult } from '../resolver.js';
|
|
5
5
|
import type { SidecarData } from '../types.js';
|
|
6
6
|
import type { BroadcastOptions } from './beacon.js';
|
|
@@ -56,13 +56,13 @@ export declare class CASBeacon extends Beacon {
|
|
|
56
56
|
* and broadcast are delegated to {@link Beacon.buildSignAndBroadcast}.
|
|
57
57
|
*
|
|
58
58
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
59
|
-
* @param {
|
|
59
|
+
* @param {Signer} signer Signer that produces the ECDSA signature for the Bitcoin transaction.
|
|
60
60
|
* @param {BitcoinConnection} bitcoin The Bitcoin network connection.
|
|
61
61
|
* @param {CASBroadcastOptions} [options] Optional broadcast configuration, including a
|
|
62
62
|
* `casPublish` callback to publish the announcement off-chain and a `feeEstimator`.
|
|
63
63
|
* @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
|
|
64
64
|
* @throws {BeaconError} if the bitcoin address is invalid, unfunded, or UTXO cannot cover the fee.
|
|
65
65
|
*/
|
|
66
|
-
broadcastSignal(signedUpdate: SignedBTCR2Update,
|
|
66
|
+
broadcastSignal(signedUpdate: SignedBTCR2Update, signer: Signer, bitcoin: BitcoinConnection, options?: CASBroadcastOptions): Promise<SignedBTCR2Update>;
|
|
67
67
|
}
|
|
68
68
|
//# sourceMappingURL=cas-beacon.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cas-beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/cas-beacon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"cas-beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/cas-beacon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAY,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAiB,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEhG;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC3D,UAAU,CAAC,EAAE,YAAY,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,SAAU,SAAQ,MAAM;IACnC;;;OAGG;gBACS,OAAO,EAAE,aAAa;IAIlC;;;;;;;;;;;;OAYG;IACH,cAAc,CACZ,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,EAC5B,OAAO,EAAE,WAAW,GACnB,mBAAmB;IAsDtB;;;;;;;;;;;;;;;OAeG;IACG,eAAe,CACnB,YAAY,EAAE,iBAAiB,EAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,iBAAiB,CAAC;CAuB9B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
|
-
import type { KeyBytes } from '@did-btcr2/common';
|
|
3
2
|
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
3
|
+
import type { Signer } from '@did-btcr2/keypair';
|
|
4
4
|
import type { BeaconProcessResult } from '../resolver.js';
|
|
5
5
|
import type { SidecarData } from '../types.js';
|
|
6
6
|
import type { BroadcastOptions } from './beacon.js';
|
|
@@ -33,12 +33,12 @@ export declare class SingletonBeacon extends Beacon {
|
|
|
33
33
|
* {@link Beacon.buildSignAndBroadcast}.
|
|
34
34
|
*
|
|
35
35
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
36
|
-
* @param {
|
|
36
|
+
* @param {Signer} signer Signer that produces the ECDSA signature for the Bitcoin transaction.
|
|
37
37
|
* @param {BitcoinConnection} bitcoin The Bitcoin network connection.
|
|
38
38
|
* @param {BroadcastOptions} [options] Optional broadcast configuration (e.g. fee estimator).
|
|
39
39
|
* @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
|
|
40
40
|
* @throws {BeaconError} if the bitcoin address is invalid, unfunded, or UTXO cannot cover the fee.
|
|
41
41
|
*/
|
|
42
|
-
broadcastSignal(signedUpdate: SignedBTCR2Update,
|
|
42
|
+
broadcastSignal(signedUpdate: SignedBTCR2Update, signer: Signer, bitcoin: BitcoinConnection, options?: BroadcastOptions): Promise<SignedBTCR2Update>;
|
|
43
43
|
}
|
|
44
44
|
//# sourceMappingURL=singleton-beacon.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singleton-beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/singleton-beacon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"singleton-beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/singleton-beacon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAY,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAiB,MAAM,iBAAiB,CAAC;AAElF;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,MAAM;IAEzC;;;OAGG;gBACS,OAAO,EAAE,aAAa;IAIlC;;;;;OAKG;IACH,cAAc,CACZ,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,EAC5B,OAAO,EAAE,WAAW,GACnB,mBAAmB;IA0BtB;;;;;;;;;;;;;OAaG;IACG,eAAe,CACnB,YAAY,EAAE,iBAAiB,EAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,iBAAiB,CAAC;CAK9B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
|
-
import type { KeyBytes } from '@did-btcr2/common';
|
|
3
2
|
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
3
|
+
import type { Signer } from '@did-btcr2/keypair';
|
|
4
4
|
import type { BeaconProcessResult } from '../resolver.js';
|
|
5
5
|
import type { SidecarData } from '../types.js';
|
|
6
6
|
import type { BroadcastOptions } from './beacon.js';
|
|
@@ -47,12 +47,12 @@ export declare class SMTBeacon extends Beacon {
|
|
|
47
47
|
* signing, and broadcast are delegated to {@link Beacon.buildSignAndBroadcast}.
|
|
48
48
|
*
|
|
49
49
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
50
|
-
* @param {
|
|
50
|
+
* @param {Signer} signer Signer that produces the ECDSA signature for the Bitcoin transaction.
|
|
51
51
|
* @param {BitcoinConnection} bitcoin The Bitcoin network connection.
|
|
52
52
|
* @param {BroadcastOptions} [options] Optional broadcast configuration (e.g. fee estimator).
|
|
53
53
|
* @return {Promise<SignedBTCR2Update>} The signed update that was broadcast.
|
|
54
54
|
* @throws {BeaconError} if the bitcoin address is invalid, unfunded, or UTXO cannot cover the fee.
|
|
55
55
|
*/
|
|
56
|
-
broadcastSignal(signedUpdate: SignedBTCR2Update,
|
|
56
|
+
broadcastSignal(signedUpdate: SignedBTCR2Update, signer: Signer, bitcoin: BitcoinConnection, options?: BroadcastOptions): Promise<SignedBTCR2Update>;
|
|
57
57
|
}
|
|
58
58
|
//# sourceMappingURL=smt-beacon.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smt-beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/smt-beacon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"smt-beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/smt-beacon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,KAAK,EAAE,mBAAmB,EAAY,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAiB,MAAM,iBAAiB,CAAC;AAElF;;;;;;;;;;;GAWG;AACH,qBAAa,SAAU,SAAQ,MAAM;IACnC;;;OAGG;gBACS,OAAO,EAAE,aAAa;IAIlC;;;;;;;;;;;;OAYG;IACH,cAAc,CACZ,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,EAC5B,OAAO,EAAE,WAAW,GACnB,mBAAmB;IAiEtB;;;;;;;;;;;;;;OAcG;IACG,eAAe,CACnB,YAAY,EAAE,iBAAiB,EAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,iBAAiB,CAAC;CAgB9B"}
|