@bcts/uniform-resources 1.0.0-alpha.8 → 1.0.0-beta.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/LICENSE +3 -2
- package/README.md +1 -1
- package/dist/chunk-CfYAbeIz.mjs +13 -0
- package/dist/index.cjs +690 -6852
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +245 -257
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +243 -257
- package/dist/index.d.mts.map +1 -1
- package/dist/index.iife.js +748 -6913
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +666 -6844
- package/dist/index.mjs.map +1 -1
- package/package.json +19 -18
- package/src/bytewords-namespace.ts +42 -0
- package/src/error.ts +34 -6
- package/src/fountain.ts +152 -65
- package/src/index.ts +27 -26
- package/src/multipart-decoder.ts +36 -36
- package/src/multipart-encoder.ts +18 -54
- package/src/ur-codable.ts +6 -0
- package/src/ur-decodable.ts +60 -8
- package/src/ur-encodable.ts +60 -8
- package/src/ur-type.ts +31 -5
- package/src/ur.ts +128 -38
- package/src/utils.ts +195 -39
- package/src/xoshiro.ts +189 -77
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { Cbor } from "@bcts/dcbor";
|
|
1
|
+
import { Cbor, CborTaggedDecodable, CborTaggedEncodable } from "@bcts/dcbor";
|
|
2
2
|
|
|
3
3
|
//#region src/error.d.ts
|
|
4
4
|
/**
|
|
5
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7
|
+
*
|
|
8
|
+
*
|
|
5
9
|
* Error type for UR encoding/decoding operations.
|
|
6
10
|
*/
|
|
7
11
|
declare class URError extends Error {
|
|
@@ -9,18 +13,24 @@ declare class URError extends Error {
|
|
|
9
13
|
}
|
|
10
14
|
/**
|
|
11
15
|
* Error type for invalid UR schemes.
|
|
16
|
+
*
|
|
17
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `invalid UR scheme`.
|
|
12
18
|
*/
|
|
13
19
|
declare class InvalidSchemeError extends URError {
|
|
14
20
|
constructor();
|
|
15
21
|
}
|
|
16
22
|
/**
|
|
17
23
|
* Error type for unspecified UR types.
|
|
24
|
+
*
|
|
25
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `no UR type specified`.
|
|
18
26
|
*/
|
|
19
27
|
declare class TypeUnspecifiedError extends URError {
|
|
20
28
|
constructor();
|
|
21
29
|
}
|
|
22
30
|
/**
|
|
23
31
|
* Error type for invalid UR types.
|
|
32
|
+
*
|
|
33
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `invalid UR type`.
|
|
24
34
|
*/
|
|
25
35
|
declare class InvalidTypeError extends URError {
|
|
26
36
|
constructor();
|
|
@@ -33,22 +43,36 @@ declare class NotSinglePartError extends URError {
|
|
|
33
43
|
}
|
|
34
44
|
/**
|
|
35
45
|
* Error type for unexpected UR types.
|
|
46
|
+
*
|
|
47
|
+
* Message matches Rust bc-ur-rust/src/error.rs:
|
|
48
|
+
* `expected UR type {expected}, but found {found}`.
|
|
36
49
|
*/
|
|
37
50
|
declare class UnexpectedTypeError extends URError {
|
|
38
51
|
constructor(expected: string, found: string);
|
|
39
52
|
}
|
|
40
53
|
/**
|
|
41
54
|
* Error type for Bytewords encoding/decoding errors.
|
|
55
|
+
*
|
|
56
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `Bytewords error ({0})`.
|
|
42
57
|
*/
|
|
43
58
|
declare class BytewordsError extends URError {
|
|
44
59
|
constructor(message: string);
|
|
45
60
|
}
|
|
46
61
|
/**
|
|
47
62
|
* Error type for CBOR encoding/decoding errors.
|
|
63
|
+
*
|
|
64
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `CBOR error ({0})`.
|
|
48
65
|
*/
|
|
49
66
|
declare class CBORError extends URError {
|
|
50
67
|
constructor(message: string);
|
|
51
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Error type for UR decoder errors.
|
|
71
|
+
* Matches Rust's Error::UR(String) variant.
|
|
72
|
+
*/
|
|
73
|
+
declare class URDecodeError extends URError {
|
|
74
|
+
constructor(message: string);
|
|
75
|
+
}
|
|
52
76
|
type Result<T> = T | Error;
|
|
53
77
|
/**
|
|
54
78
|
* Helper function to check if a result is an error.
|
|
@@ -108,12 +132,36 @@ declare class URType {
|
|
|
108
132
|
*/
|
|
109
133
|
static from(value: string): URType;
|
|
110
134
|
/**
|
|
111
|
-
* Safely creates a URType, returning
|
|
135
|
+
* Safely creates a URType, returning a typed `Result`-shaped
|
|
136
|
+
* discriminated union instead of throwing.
|
|
137
|
+
*
|
|
138
|
+
* Mirrors Rust `impl TryFrom<&str> for URType` /
|
|
139
|
+
* `impl TryFrom<String> for URType` (`bc-ur-rust/src/ur_type.rs`),
|
|
140
|
+
* which return `Result<URType, Error>`. The TS shape is the
|
|
141
|
+
* idiomatic discriminated form so callers can branch on `ok`
|
|
142
|
+
* without `instanceof`:
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const r = URType.tryFrom("test");
|
|
147
|
+
* if (r.ok) {
|
|
148
|
+
* console.log(r.value.string()); // "test"
|
|
149
|
+
* } else {
|
|
150
|
+
* console.error(r.error.message);
|
|
151
|
+
* }
|
|
152
|
+
* ```
|
|
112
153
|
*
|
|
113
154
|
* @param value - The UR type string
|
|
114
|
-
* @returns
|
|
115
|
-
|
|
116
|
-
|
|
155
|
+
* @returns A typed Result: `{ ok: true; value: URType }` on success,
|
|
156
|
+
* `{ ok: false; error: InvalidTypeError }` on failure.
|
|
157
|
+
*/
|
|
158
|
+
static tryFrom(value: string): {
|
|
159
|
+
ok: true;
|
|
160
|
+
value: URType;
|
|
161
|
+
} | {
|
|
162
|
+
ok: false;
|
|
163
|
+
error: InvalidTypeError;
|
|
164
|
+
};
|
|
117
165
|
}
|
|
118
166
|
//#endregion
|
|
119
167
|
//#region src/ur.d.ts
|
|
@@ -159,11 +207,26 @@ declare class UR {
|
|
|
159
207
|
/**
|
|
160
208
|
* Creates a new UR from a UR string.
|
|
161
209
|
*
|
|
210
|
+
* Mirrors Rust's `UR::from_ur_string` (`bc-ur-rust/src/ur.rs:25-38`):
|
|
211
|
+
* 1. lowercase the entire string.
|
|
212
|
+
* 2. strip the `"ur:"` prefix → {@link InvalidSchemeError} if absent.
|
|
213
|
+
* 3. split on the first `/` → {@link TypeUnspecifiedError} if absent.
|
|
214
|
+
* 4. validate the type via {@link URType} → {@link InvalidTypeError}.
|
|
215
|
+
* 5. delegate the data section to the upstream-style decoder, which
|
|
216
|
+
* classifies the UR as single- or multi-part. Multi-part input is
|
|
217
|
+
* rejected with {@link NotSinglePartError}.
|
|
218
|
+
* 6. decode the bytewords payload (CRC32 + minimal mapping) →
|
|
219
|
+
* {@link BytewordsError} on failure.
|
|
220
|
+
* 7. parse the resulting bytes as CBOR → {@link CBORError} on failure.
|
|
221
|
+
*
|
|
162
222
|
* @param urString - A UR string like "ur:test/..."
|
|
163
223
|
* @throws {InvalidSchemeError} If the string doesn't start with "ur:"
|
|
164
|
-
* @throws {TypeUnspecifiedError} If no
|
|
224
|
+
* @throws {TypeUnspecifiedError} If no `/` separator is present
|
|
225
|
+
* @throws {InvalidTypeError} If the type contains invalid characters
|
|
165
226
|
* @throws {NotSinglePartError} If the UR is multi-part
|
|
166
|
-
* @throws {
|
|
227
|
+
* @throws {URDecodeError} For upstream-decoder errors (invalid indices, etc.)
|
|
228
|
+
* @throws {BytewordsError} If bytewords decoding fails
|
|
229
|
+
* @throws {CBORError} If CBOR parsing fails
|
|
167
230
|
*
|
|
168
231
|
* @example
|
|
169
232
|
* ```typescript
|
|
@@ -200,6 +263,12 @@ declare class UR {
|
|
|
200
263
|
qrString(): string;
|
|
201
264
|
/**
|
|
202
265
|
* Returns the QR data as bytes (uppercase UR string as UTF-8).
|
|
266
|
+
*
|
|
267
|
+
* Mirrors Rust's `UR::qr_data` (`ur.rs:52`) which does
|
|
268
|
+
* `self.qr_string().as_bytes().to_vec()` — the string's UTF-8 byte
|
|
269
|
+
* representation. We use `TextEncoder` rather than per-codepoint
|
|
270
|
+
* truncation so the behaviour stays correct if the QR string ever
|
|
271
|
+
* contains non-ASCII characters.
|
|
203
272
|
*/
|
|
204
273
|
qrData(): Uint8Array;
|
|
205
274
|
/**
|
|
@@ -215,6 +284,12 @@ declare class UR {
|
|
|
215
284
|
toString(): string;
|
|
216
285
|
/**
|
|
217
286
|
* Checks equality with another UR.
|
|
287
|
+
*
|
|
288
|
+
* Mirrors Rust's derived `PartialEq for UR` which compares the inner
|
|
289
|
+
* `ur_type` and the inner `cbor` field directly. We compare CBOR
|
|
290
|
+
* bytewise — `Uint8Array` equality, not `Array#toString` (which would
|
|
291
|
+
* coerce to a comma-joined string and could collide on pathological
|
|
292
|
+
* inputs).
|
|
218
293
|
*/
|
|
219
294
|
equals(other: UR): boolean;
|
|
220
295
|
}
|
|
@@ -226,17 +301,27 @@ declare class UR {
|
|
|
226
301
|
* Types implementing this interface should be able to convert themselves
|
|
227
302
|
* to CBOR data and associate that with a UR type identifier.
|
|
228
303
|
*
|
|
304
|
+
* Mirrors Rust's `UREncodable` trait (`bc-ur-rust/src/ur_encodable.rs`),
|
|
305
|
+
* which has a blanket impl `impl<T> UREncodable for T where T:
|
|
306
|
+
* CBORTaggedEncodable`. TypeScript has no equivalent of blanket impls, so
|
|
307
|
+
* implementers either write `ur()` / `urString()` directly *or* — for a
|
|
308
|
+
* type that already implements `CborTaggedEncodable` — call the helper
|
|
309
|
+
* functions {@link urFromEncodable} / {@link urStringFromEncodable} below
|
|
310
|
+
* to get the same auto-derivation that Rust provides for free.
|
|
311
|
+
*
|
|
229
312
|
* @example
|
|
230
313
|
* ```typescript
|
|
231
|
-
* class MyType implements UREncodable {
|
|
232
|
-
*
|
|
233
|
-
*
|
|
314
|
+
* class MyType implements UREncodable, CborTaggedEncodable {
|
|
315
|
+
* cborTags(): Tag[] {
|
|
316
|
+
* return [createTag(40000, "mytype")];
|
|
234
317
|
* }
|
|
235
318
|
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
319
|
+
* untaggedCbor(): Cbor { ... }
|
|
320
|
+
* taggedCbor(): Cbor { return createTaggedCbor(this); }
|
|
321
|
+
*
|
|
322
|
+
* // Auto-derived from the first cbor tag's name, just like Rust.
|
|
323
|
+
* ur(): UR { return urFromEncodable(this); }
|
|
324
|
+
* urString(): string { return urStringFromEncodable(this); }
|
|
240
325
|
* }
|
|
241
326
|
* ```
|
|
242
327
|
*/
|
|
@@ -250,6 +335,26 @@ interface UREncodable {
|
|
|
250
335
|
*/
|
|
251
336
|
urString(): string;
|
|
252
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* Concrete equivalent of Rust's default `UREncodable::ur` impl
|
|
340
|
+
* (`bc-ur-rust/src/ur_encodable.rs:8-18`):
|
|
341
|
+
*
|
|
342
|
+
* - Reads the first tag returned by `encodable.cborTags()`.
|
|
343
|
+
* - Uses that tag's `name` as the UR type, throwing if no name is set —
|
|
344
|
+
* matching Rust's `panic!("CBOR tag {} must have a name. Did you call
|
|
345
|
+
* `register_tags()`?", tag.value())`.
|
|
346
|
+
* - Wraps the encodable's `untaggedCbor()` in a fresh {@link UR} bound to
|
|
347
|
+
* that type.
|
|
348
|
+
*
|
|
349
|
+
* Use from a class implementing both `UREncodable` and
|
|
350
|
+
* `CborTaggedEncodable` to skip writing the boilerplate yourself.
|
|
351
|
+
*/
|
|
352
|
+
declare function urFromEncodable(encodable: CborTaggedEncodable): UR;
|
|
353
|
+
/**
|
|
354
|
+
* Concrete equivalent of Rust's default `UREncodable::ur_string` impl
|
|
355
|
+
* (`bc-ur-rust/src/ur_encodable.rs:21`): `self.ur().string()`.
|
|
356
|
+
*/
|
|
357
|
+
declare function urStringFromEncodable(encodable: CborTaggedEncodable): string;
|
|
253
358
|
/**
|
|
254
359
|
* Helper function to check if an object implements UREncodable.
|
|
255
360
|
*/
|
|
@@ -262,17 +367,26 @@ declare function isUREncodable(obj: unknown): obj is UREncodable;
|
|
|
262
367
|
* Types implementing this interface should be able to create themselves
|
|
263
368
|
* from a UR containing their data.
|
|
264
369
|
*
|
|
370
|
+
* Mirrors Rust's `URDecodable` trait (`bc-ur-rust/src/ur_decodable.rs`),
|
|
371
|
+
* which has a blanket impl `impl<T> URDecodable for T where T:
|
|
372
|
+
* CBORTaggedDecodable`. TypeScript has no equivalent of blanket impls, so
|
|
373
|
+
* implementers either write `fromUR()` directly *or* — for a type that
|
|
374
|
+
* already implements `CborTaggedDecodable` — call the helper functions
|
|
375
|
+
* {@link decodableFromUR} / {@link decodableFromURString} below to get the
|
|
376
|
+
* same auto-derivation that Rust provides for free.
|
|
377
|
+
*
|
|
265
378
|
* @example
|
|
266
379
|
* ```typescript
|
|
267
|
-
* class MyType implements URDecodable {
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
* // Decode from CBOR and return MyType instance
|
|
380
|
+
* class MyType implements URDecodable, CborTaggedDecodable<MyType> {
|
|
381
|
+
* cborTags(): Tag[] {
|
|
382
|
+
* return [createTag(40000, "mytype")];
|
|
271
383
|
* }
|
|
384
|
+
* fromUntaggedCbor(cbor: Cbor): MyType { ... }
|
|
385
|
+
* fromTaggedCbor(cbor: Cbor): MyType { ... }
|
|
272
386
|
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
* }
|
|
387
|
+
* // Auto-derived from the first cbor tag's name, matching Rust.
|
|
388
|
+
* fromUR(ur: UR): MyType { return decodableFromUR(this, ur); }
|
|
389
|
+
* fromURString(s: string): MyType { return decodableFromURString(this, s); }
|
|
276
390
|
* }
|
|
277
391
|
* ```
|
|
278
392
|
*/
|
|
@@ -297,6 +411,26 @@ interface URDecodable {
|
|
|
297
411
|
*/
|
|
298
412
|
fromURString?(urString: string): unknown;
|
|
299
413
|
}
|
|
414
|
+
/**
|
|
415
|
+
* Concrete equivalent of Rust's default `URDecodable::from_ur` impl
|
|
416
|
+
* (`bc-ur-rust/src/ur_decodable.rs:7-15`):
|
|
417
|
+
*
|
|
418
|
+
* 1. Read the first tag returned by `decodable.cborTags()`.
|
|
419
|
+
* 2. Verify the UR's type matches that tag's name via `UR#checkType`
|
|
420
|
+
* (this is what Rust's `ur.check_type(...)` does — surface
|
|
421
|
+
* `UnexpectedTypeError` on mismatch).
|
|
422
|
+
* 3. Delegate to `decodable.fromUntaggedCbor(ur.cbor())`.
|
|
423
|
+
*
|
|
424
|
+
* Use from a class implementing both `URDecodable` and
|
|
425
|
+
* `CborTaggedDecodable<T>` to skip the type-check / delegate boilerplate.
|
|
426
|
+
*/
|
|
427
|
+
declare function decodableFromUR<T>(decodable: CborTaggedDecodable<T>, ur: UR): T;
|
|
428
|
+
/**
|
|
429
|
+
* Concrete equivalent of Rust's default `URDecodable::from_ur_string` impl
|
|
430
|
+
* (`bc-ur-rust/src/ur_decodable.rs:17-22`):
|
|
431
|
+
* `Self::from_ur(UR::from_ur_string(s)?)`.
|
|
432
|
+
*/
|
|
433
|
+
declare function decodableFromURString<T>(decodable: CborTaggedDecodable<T>, urString: string): T;
|
|
300
434
|
/**
|
|
301
435
|
* Helper function to check if an object implements URDecodable.
|
|
302
436
|
*/
|
|
@@ -382,12 +516,6 @@ declare class MultipartEncoder {
|
|
|
382
516
|
* ```
|
|
383
517
|
*/
|
|
384
518
|
constructor(ur: UR, maxFragmentLen: number);
|
|
385
|
-
/**
|
|
386
|
-
* Returns whether the message fits in a single part.
|
|
387
|
-
*
|
|
388
|
-
* For single-part messages, consider using UR.string() directly.
|
|
389
|
-
*/
|
|
390
|
-
isSinglePart(): boolean;
|
|
391
519
|
/**
|
|
392
520
|
* Gets the next part of the encoding.
|
|
393
521
|
*
|
|
@@ -405,10 +533,17 @@ declare class MultipartEncoder {
|
|
|
405
533
|
nextPart(): string;
|
|
406
534
|
/**
|
|
407
535
|
* Encodes a fountain part as a UR string.
|
|
536
|
+
*
|
|
537
|
+
* Always emits the multipart `ur:<type>/<seqNum>-<seqLen>/<bytewords>`
|
|
538
|
+
* format — including for single-part messages (`1-1/...`). This mirrors
|
|
539
|
+
* Rust's `bc_ur::MultipartEncoder::next_part`, which never short-circuits
|
|
540
|
+
* to plain UR. Callers that want plain UR for tiny payloads should use
|
|
541
|
+
* `UR.string()` directly instead of constructing a `MultipartEncoder`.
|
|
408
542
|
*/
|
|
409
543
|
private _encodePart;
|
|
410
544
|
/**
|
|
411
|
-
* Encodes part metadata and data
|
|
545
|
+
* Encodes part metadata and data as CBOR for bytewords encoding.
|
|
546
|
+
* Format: CBOR array [seqNum, seqLen, messageLen, checksum, data]
|
|
412
547
|
*/
|
|
413
548
|
private _encodePartData;
|
|
414
549
|
/**
|
|
@@ -422,17 +557,6 @@ declare class MultipartEncoder {
|
|
|
422
557
|
* for additional redundancy.
|
|
423
558
|
*/
|
|
424
559
|
partsCount(): number;
|
|
425
|
-
/**
|
|
426
|
-
* Checks if all pure parts have been emitted.
|
|
427
|
-
*
|
|
428
|
-
* Even after this returns true, you can continue calling nextPart()
|
|
429
|
-
* to generate additional rateless parts for redundancy.
|
|
430
|
-
*/
|
|
431
|
-
isComplete(): boolean;
|
|
432
|
-
/**
|
|
433
|
-
* Resets the encoder to start from the beginning.
|
|
434
|
-
*/
|
|
435
|
-
reset(): void;
|
|
436
560
|
}
|
|
437
561
|
//#endregion
|
|
438
562
|
//#region src/multipart-decoder.d.ts
|
|
@@ -473,6 +597,8 @@ declare class MultipartDecoder {
|
|
|
473
597
|
private _parsePart;
|
|
474
598
|
/**
|
|
475
599
|
* Decodes a multipart UR's fountain part data.
|
|
600
|
+
*
|
|
601
|
+
* The multipart body is a CBOR array: [seqNum, seqLen, messageLen, checksum, data]
|
|
476
602
|
*/
|
|
477
603
|
private _decodeFountainPart;
|
|
478
604
|
/**
|
|
@@ -485,226 +611,29 @@ declare class MultipartDecoder {
|
|
|
485
611
|
* @returns The decoded UR, or null if not yet complete
|
|
486
612
|
*/
|
|
487
613
|
message(): UR | null;
|
|
488
|
-
/**
|
|
489
|
-
* Returns the decoding progress as a fraction (0 to 1).
|
|
490
|
-
*/
|
|
491
|
-
progress(): number;
|
|
492
|
-
/**
|
|
493
|
-
* Resets the decoder to receive a new message.
|
|
494
|
-
*/
|
|
495
|
-
reset(): void;
|
|
496
|
-
}
|
|
497
|
-
//#endregion
|
|
498
|
-
//#region src/fountain.d.ts
|
|
499
|
-
/**
|
|
500
|
-
* Fountain code implementation for multipart URs.
|
|
501
|
-
*
|
|
502
|
-
* This implements a hybrid fixed-rate and rateless fountain code system
|
|
503
|
-
* as specified in BCR-2020-005 and BCR-2024-001.
|
|
504
|
-
*
|
|
505
|
-
* Key concepts:
|
|
506
|
-
* - Parts 1-seqLen are "pure" fragments (fixed-rate)
|
|
507
|
-
* - Parts > seqLen are "mixed" fragments using XOR (rateless)
|
|
508
|
-
* - Xoshiro256** PRNG ensures encoder/decoder agree on mixing
|
|
509
|
-
*/
|
|
510
|
-
/**
|
|
511
|
-
* Represents a fountain code part with metadata.
|
|
512
|
-
*/
|
|
513
|
-
interface FountainPart {
|
|
514
|
-
/** Sequence number (1-based) */
|
|
515
|
-
seqNum: number;
|
|
516
|
-
/** Total number of pure fragments */
|
|
517
|
-
seqLen: number;
|
|
518
|
-
/** Length of original message */
|
|
519
|
-
messageLen: number;
|
|
520
|
-
/** CRC32 checksum of original message */
|
|
521
|
-
checksum: number;
|
|
522
|
-
/** Fragment data */
|
|
523
|
-
data: Uint8Array;
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* Splits data into fragments of the specified size.
|
|
527
|
-
*/
|
|
528
|
-
declare function splitMessage(message: Uint8Array, fragmentLen: number): Uint8Array[];
|
|
529
|
-
/**
|
|
530
|
-
* XOR two Uint8Arrays together.
|
|
531
|
-
*/
|
|
532
|
-
declare function xorBytes(a: Uint8Array, b: Uint8Array): Uint8Array;
|
|
533
|
-
/**
|
|
534
|
-
* Chooses which fragments to mix for a given sequence number.
|
|
535
|
-
*
|
|
536
|
-
* This uses a seeded Xoshiro256** PRNG to deterministically select fragments,
|
|
537
|
-
* ensuring encoder and decoder agree without explicit coordination.
|
|
538
|
-
*
|
|
539
|
-
* @param seqNum - The sequence number (1-based)
|
|
540
|
-
* @param seqLen - Total number of pure fragments
|
|
541
|
-
* @param checksum - CRC32 checksum of the message
|
|
542
|
-
* @returns Array of fragment indices (0-based)
|
|
543
|
-
*/
|
|
544
|
-
declare function chooseFragments(seqNum: number, seqLen: number, checksum: number): number[];
|
|
545
|
-
/**
|
|
546
|
-
* Mixes the selected fragments using XOR.
|
|
547
|
-
*/
|
|
548
|
-
declare function mixFragments(fragments: Uint8Array[], indices: number[]): Uint8Array;
|
|
549
|
-
/**
|
|
550
|
-
* Fountain encoder for creating multipart URs.
|
|
551
|
-
*/
|
|
552
|
-
declare class FountainEncoder {
|
|
553
|
-
private readonly fragments;
|
|
554
|
-
private readonly messageLen;
|
|
555
|
-
private readonly checksum;
|
|
556
|
-
private seqNum;
|
|
557
|
-
/**
|
|
558
|
-
* Creates a fountain encoder for the given message.
|
|
559
|
-
*
|
|
560
|
-
* @param message - The message to encode
|
|
561
|
-
* @param maxFragmentLen - Maximum length of each fragment
|
|
562
|
-
*/
|
|
563
|
-
constructor(message: Uint8Array, maxFragmentLen: number);
|
|
564
|
-
/**
|
|
565
|
-
* Returns the number of pure fragments.
|
|
566
|
-
*/
|
|
567
|
-
get seqLen(): number;
|
|
568
|
-
/**
|
|
569
|
-
* Returns whether the message fits in a single part.
|
|
570
|
-
*/
|
|
571
|
-
isSinglePart(): boolean;
|
|
572
|
-
/**
|
|
573
|
-
* Returns whether all pure parts have been emitted.
|
|
574
|
-
*/
|
|
575
|
-
isComplete(): boolean;
|
|
576
|
-
/**
|
|
577
|
-
* Generates the next fountain part.
|
|
578
|
-
*/
|
|
579
|
-
nextPart(): FountainPart;
|
|
580
|
-
/**
|
|
581
|
-
* Returns the current sequence number.
|
|
582
|
-
*/
|
|
583
|
-
currentSeqNum(): number;
|
|
584
|
-
/**
|
|
585
|
-
* Resets the encoder to start from the beginning.
|
|
586
|
-
*/
|
|
587
|
-
reset(): void;
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* Fountain decoder for reassembling multipart URs.
|
|
591
|
-
*/
|
|
592
|
-
declare class FountainDecoder {
|
|
593
|
-
private seqLen;
|
|
594
|
-
private messageLen;
|
|
595
|
-
private checksum;
|
|
596
|
-
private readonly pureFragments;
|
|
597
|
-
private readonly mixedParts;
|
|
598
|
-
/**
|
|
599
|
-
* Receives a fountain part and attempts to decode.
|
|
600
|
-
*
|
|
601
|
-
* @param part - The fountain part to receive
|
|
602
|
-
* @returns true if the message is now complete
|
|
603
|
-
*/
|
|
604
|
-
receive(part: FountainPart): boolean;
|
|
605
|
-
/**
|
|
606
|
-
* Attempts to extract pure fragments from mixed parts.
|
|
607
|
-
*/
|
|
608
|
-
private reduceMixedParts;
|
|
609
|
-
/**
|
|
610
|
-
* Returns whether all fragments have been received.
|
|
611
|
-
*/
|
|
612
|
-
isComplete(): boolean;
|
|
613
|
-
/**
|
|
614
|
-
* Reconstructs the original message.
|
|
615
|
-
*
|
|
616
|
-
* @returns The original message, or null if not yet complete
|
|
617
|
-
*/
|
|
618
|
-
message(): Uint8Array | null;
|
|
619
|
-
/**
|
|
620
|
-
* Returns the progress as a fraction (0 to 1).
|
|
621
|
-
*/
|
|
622
|
-
progress(): number;
|
|
623
|
-
/**
|
|
624
|
-
* Resets the decoder.
|
|
625
|
-
*/
|
|
626
|
-
reset(): void;
|
|
627
614
|
}
|
|
628
615
|
//#endregion
|
|
629
|
-
//#region src/
|
|
630
|
-
/**
|
|
631
|
-
* Xoshiro256** PRNG implementation.
|
|
632
|
-
*
|
|
633
|
-
* This is a high-quality, fast pseudo-random number generator used
|
|
634
|
-
* for deterministic fragment selection in fountain codes.
|
|
635
|
-
*
|
|
636
|
-
* Reference: https://prng.di.unimi.it/
|
|
637
|
-
*/
|
|
638
|
-
/**
|
|
639
|
-
* Xoshiro256** pseudo-random number generator.
|
|
640
|
-
*
|
|
641
|
-
* This PRNG is used for deterministic mixing in fountain codes,
|
|
642
|
-
* allowing both encoder and decoder to agree on which fragments
|
|
643
|
-
* are combined without transmitting that information.
|
|
644
|
-
*/
|
|
645
|
-
declare class Xoshiro256 {
|
|
646
|
-
private s;
|
|
647
|
-
/**
|
|
648
|
-
* Creates a new Xoshiro256** instance from a seed.
|
|
649
|
-
*
|
|
650
|
-
* The seed is hashed using SHA-256 to initialize the state.
|
|
651
|
-
* For consistent results across encoder/decoder, use the same seed.
|
|
652
|
-
*
|
|
653
|
-
* @param seed - The seed bytes (any length)
|
|
654
|
-
*/
|
|
655
|
-
constructor(seed: Uint8Array);
|
|
656
|
-
/**
|
|
657
|
-
* Creates a Xoshiro256** instance from raw state values.
|
|
658
|
-
* Useful for seeding with specific values.
|
|
659
|
-
*/
|
|
660
|
-
static fromState(s0: bigint, s1: bigint, s2: bigint, s3: bigint): Xoshiro256;
|
|
661
|
-
/**
|
|
662
|
-
* Simple hash function for seeding.
|
|
663
|
-
* This is a basic implementation - in production use SHA-256.
|
|
664
|
-
*/
|
|
665
|
-
private hashSeed;
|
|
666
|
-
/**
|
|
667
|
-
* Converts 8 bytes to a 64-bit BigInt (little-endian).
|
|
668
|
-
*/
|
|
669
|
-
private bytesToBigInt;
|
|
670
|
-
/**
|
|
671
|
-
* Generates the next 64-bit random value.
|
|
672
|
-
*/
|
|
673
|
-
next(): bigint;
|
|
674
|
-
/**
|
|
675
|
-
* Generates a random double in [0, 1).
|
|
676
|
-
*/
|
|
677
|
-
nextDouble(): number;
|
|
678
|
-
/**
|
|
679
|
-
* Generates a random integer in [low, high).
|
|
680
|
-
*/
|
|
681
|
-
nextInt(low: number, high: number): number;
|
|
682
|
-
/**
|
|
683
|
-
* Generates a random byte [0, 255].
|
|
684
|
-
*/
|
|
685
|
-
nextByte(): number;
|
|
686
|
-
/**
|
|
687
|
-
* Generates an array of random bytes.
|
|
688
|
-
*/
|
|
689
|
-
nextData(count: number): Uint8Array;
|
|
690
|
-
}
|
|
616
|
+
//#region src/utils.d.ts
|
|
691
617
|
/**
|
|
692
|
-
*
|
|
618
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
619
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
693
620
|
*
|
|
694
|
-
* This ensures that both encoder and decoder produce the same random sequence
|
|
695
|
-
* for a given message and part number.
|
|
696
621
|
*/
|
|
697
|
-
declare function createSeed(checksum: number, seqNum: number): Uint8Array;
|
|
698
|
-
//#endregion
|
|
699
|
-
//#region src/utils.d.ts
|
|
700
622
|
/**
|
|
701
623
|
* Checks if a character is a valid UR type character.
|
|
702
|
-
*
|
|
624
|
+
*
|
|
625
|
+
* Mirrors Rust's `URTypeChar::is_ur_type` (`bc-ur-rust/src/utils.rs:6-19`):
|
|
626
|
+
* lowercase a-z, digits 0-9, and the hyphen `-`.
|
|
703
627
|
*/
|
|
704
628
|
declare function isURTypeChar(char: string): boolean;
|
|
705
629
|
/**
|
|
706
630
|
* Checks if a string is a valid UR type.
|
|
707
|
-
*
|
|
631
|
+
*
|
|
632
|
+
* Mirrors Rust's `URTypeString::is_ur_type` (`bc-ur-rust/src/utils.rs:26-32`)
|
|
633
|
+
* which is `self.chars().all(...)` — meaning **the empty string is accepted**
|
|
634
|
+
* (a vacuously-true `all` over no chars). We mirror that here so that
|
|
635
|
+
* `URType::new("")` succeeds in both ports; the round-trip then fails at
|
|
636
|
+
* decode-time with `TypeUnspecified`.
|
|
708
637
|
*/
|
|
709
638
|
declare function isValidURType(urType: string): boolean;
|
|
710
639
|
/**
|
|
@@ -716,36 +645,78 @@ declare function validateURType(urType: string): string;
|
|
|
716
645
|
* See: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-004-bytewords.md
|
|
717
646
|
*/
|
|
718
647
|
declare const BYTEWORDS: string[];
|
|
719
|
-
declare const BYTEWORDS_MAP: Map<string, number>;
|
|
720
648
|
/**
|
|
721
649
|
* Bytemojis for encoding/decoding bytes as emojis.
|
|
722
650
|
* See: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2024-008-bytemoji.md
|
|
723
651
|
*/
|
|
724
652
|
declare const BYTEMOJIS: string[];
|
|
653
|
+
/**
|
|
654
|
+
* Encodes an arbitrary byte slice as a string of space-separated bytewords.
|
|
655
|
+
*
|
|
656
|
+
* Mirrors `bytewords::encode_to_words` in `bc-ur-rust` (≥ v0.19.1). Does not
|
|
657
|
+
* add a CRC32 checksum — use {@link encodeBytewords} for UR-style encoding.
|
|
658
|
+
*/
|
|
659
|
+
declare function encodeToWords(data: Uint8Array): string;
|
|
660
|
+
/**
|
|
661
|
+
* Encodes an arbitrary byte slice as a string of space-separated bytemojis.
|
|
662
|
+
*
|
|
663
|
+
* Mirrors `bytewords::encode_to_bytemojis` in `bc-ur-rust` (≥ v0.19.1).
|
|
664
|
+
*/
|
|
665
|
+
declare function encodeToBytemojis(data: Uint8Array): string;
|
|
666
|
+
/**
|
|
667
|
+
* Encodes an arbitrary byte slice as minimal bytewords (first + last letter of
|
|
668
|
+
* each word, concatenated with no separator).
|
|
669
|
+
*
|
|
670
|
+
* Mirrors `bytewords::encode_to_minimal_bytewords` in `bc-ur-rust`
|
|
671
|
+
* (≥ v0.19.1). Does not add a CRC32 checksum.
|
|
672
|
+
*/
|
|
673
|
+
declare function encodeToMinimalBytewords(data: Uint8Array): string;
|
|
725
674
|
/**
|
|
726
675
|
* Encodes a 4-byte slice as a string of bytewords for identification.
|
|
676
|
+
*
|
|
677
|
+
* Thin wrapper over {@link encodeToWords} that enforces the 4-byte length
|
|
678
|
+
* contract historically used by `bc-ur-rust`'s `bytewords::identifier`.
|
|
727
679
|
*/
|
|
728
680
|
declare function encodeBytewordsIdentifier(data: Uint8Array): string;
|
|
729
681
|
/**
|
|
730
682
|
* Encodes a 4-byte slice as a string of bytemojis for identification.
|
|
683
|
+
*
|
|
684
|
+
* Thin wrapper over {@link encodeToBytemojis} that enforces the 4-byte length
|
|
685
|
+
* contract historically used by `bc-ur-rust`'s `bytewords::bytemoji_identifier`.
|
|
731
686
|
*/
|
|
732
687
|
declare function encodeBytemojisIdentifier(data: Uint8Array): string;
|
|
688
|
+
/**
|
|
689
|
+
* Returns `true` if `emoji` is one of the 256 bytemojis.
|
|
690
|
+
*
|
|
691
|
+
* Mirrors `bytewords::is_valid_bytemoji` in `bc-ur-rust` (≥ v0.19.1).
|
|
692
|
+
*/
|
|
693
|
+
declare function isValidBytemoji(emoji: string): boolean;
|
|
694
|
+
/**
|
|
695
|
+
* Canonicalises a byteword token (2–4 ASCII letters, case-insensitive) to its
|
|
696
|
+
* full 4-letter lowercase form. Returns `undefined` if the token is not a
|
|
697
|
+
* valid byteword or any of its short forms.
|
|
698
|
+
*
|
|
699
|
+
* Mirrors `bytewords::canonicalize_byteword` in `bc-ur-rust` (≥ v0.19.1).
|
|
700
|
+
*
|
|
701
|
+
* - 2-letter tokens are matched against the first + last letter of each
|
|
702
|
+
* byteword (identical to the minimal bytewords encoding).
|
|
703
|
+
* - 3-letter tokens are matched against the first 3 and the last 3 letters of
|
|
704
|
+
* each byteword; if both match different entries, the first-3 match wins
|
|
705
|
+
* (matching rust's `or_else` priority).
|
|
706
|
+
* - 4-letter tokens must exactly match a full byteword (after lower-casing).
|
|
707
|
+
*/
|
|
708
|
+
declare function canonicalizeByteword(token: string): string | undefined;
|
|
733
709
|
/**
|
|
734
710
|
* Bytewords encoding style.
|
|
735
711
|
*/
|
|
736
712
|
declare enum BytewordsStyle {
|
|
737
713
|
/** Full 4-letter words separated by spaces */
|
|
738
714
|
Standard = "standard",
|
|
739
|
-
/** Full 4-letter words
|
|
715
|
+
/** Full 4-letter words separated by hyphens (URI-safe) */
|
|
740
716
|
Uri = "uri",
|
|
741
717
|
/** First and last character only (minimal) - used by UR encoding */
|
|
742
|
-
Minimal = "minimal"
|
|
718
|
+
Minimal = "minimal"
|
|
743
719
|
}
|
|
744
|
-
declare const MINIMAL_BYTEWORDS_MAP: Map<string, number>;
|
|
745
|
-
/**
|
|
746
|
-
* Calculate CRC32 checksum of data.
|
|
747
|
-
*/
|
|
748
|
-
declare function crc32(data: Uint8Array): number;
|
|
749
720
|
/**
|
|
750
721
|
* Encode data as bytewords with the specified style.
|
|
751
722
|
* Includes CRC32 checksum.
|
|
@@ -754,8 +725,23 @@ declare function encodeBytewords(data: Uint8Array, style?: BytewordsStyle): stri
|
|
|
754
725
|
/**
|
|
755
726
|
* Decode bytewords string back to data.
|
|
756
727
|
* Validates and removes CRC32 checksum.
|
|
728
|
+
*
|
|
729
|
+
* Errors mirror the upstream Rust `ur::bytewords::Error` enum
|
|
730
|
+
* (`ur-0.4.1/src/bytewords.rs`):
|
|
731
|
+
* - `NonAscii` — input contains non-ASCII characters (checked first).
|
|
732
|
+
* - `InvalidLength` — minimal-style input has odd length.
|
|
733
|
+
* - `InvalidWord` — a token does not map to a byteword index.
|
|
734
|
+
* - `InvalidChecksum` — the trailing 4-byte CRC32 does not match.
|
|
735
|
+
*
|
|
736
|
+
* All variants are surfaced as {@link BytewordsError} with the same default
|
|
737
|
+
* `Display` strings as Rust (e.g. "invalid checksum", "non-ASCII"), so
|
|
738
|
+
* callers can branch on the error class rather than the bare `Error`
|
|
739
|
+
* thrown by earlier revisions of this port.
|
|
757
740
|
*/
|
|
758
741
|
declare function decodeBytewords(encoded: string, style?: BytewordsStyle): Uint8Array;
|
|
742
|
+
declare namespace bytewords_namespace_d_exports {
|
|
743
|
+
export { BYTEMOJIS, BYTEWORDS, BytewordsStyle as Style, encodeBytemojisIdentifier as bytemojiIdentifier, canonicalizeByteword, decodeBytewords as decode, encodeBytewords as encode, encodeToBytemojis, encodeToMinimalBytewords, encodeToWords, encodeBytewordsIdentifier as identifier, isValidBytemoji };
|
|
744
|
+
}
|
|
759
745
|
//#endregion
|
|
760
|
-
export { BYTEMOJIS, BYTEWORDS,
|
|
746
|
+
export { BYTEMOJIS, BYTEWORDS, BytewordsError, BytewordsStyle, CBORError, InvalidSchemeError, InvalidTypeError, MultipartDecoder, MultipartEncoder, NotSinglePartError, type Result, TypeUnspecifiedError, UR, type URCodable, type URDecodable, URDecodeError, type UREncodable, URError, URType, UnexpectedTypeError, bytewords_namespace_d_exports as bytewords, canonicalizeByteword, decodableFromUR, decodableFromURString, decodeBytewords, encodeBytemojisIdentifier, encodeBytewords, encodeBytewordsIdentifier, encodeToBytemojis, encodeToMinimalBytewords, encodeToWords, isError, isURCodable, isURDecodable, isUREncodable, isURTypeChar, isValidBytemoji, isValidURType, urFromEncodable, urStringFromEncodable, validateURType };
|
|
761
747
|
//# sourceMappingURL=index.d.mts.map
|