@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.cts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import { Cbor } from "@bcts/dcbor";
|
|
1
|
+
import { Cbor, CborTaggedDecodable, CborTaggedEncodable } from "@bcts/dcbor";
|
|
2
2
|
|
|
3
|
+
//#region \0rolldown/runtime.js
|
|
4
|
+
//#endregion
|
|
3
5
|
//#region src/error.d.ts
|
|
4
6
|
/**
|
|
7
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
8
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
9
|
+
*
|
|
10
|
+
*
|
|
5
11
|
* Error type for UR encoding/decoding operations.
|
|
6
12
|
*/
|
|
7
13
|
declare class URError extends Error {
|
|
@@ -9,18 +15,24 @@ declare class URError extends Error {
|
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
11
17
|
* Error type for invalid UR schemes.
|
|
18
|
+
*
|
|
19
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `invalid UR scheme`.
|
|
12
20
|
*/
|
|
13
21
|
declare class InvalidSchemeError extends URError {
|
|
14
22
|
constructor();
|
|
15
23
|
}
|
|
16
24
|
/**
|
|
17
25
|
* Error type for unspecified UR types.
|
|
26
|
+
*
|
|
27
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `no UR type specified`.
|
|
18
28
|
*/
|
|
19
29
|
declare class TypeUnspecifiedError extends URError {
|
|
20
30
|
constructor();
|
|
21
31
|
}
|
|
22
32
|
/**
|
|
23
33
|
* Error type for invalid UR types.
|
|
34
|
+
*
|
|
35
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `invalid UR type`.
|
|
24
36
|
*/
|
|
25
37
|
declare class InvalidTypeError extends URError {
|
|
26
38
|
constructor();
|
|
@@ -33,22 +45,36 @@ declare class NotSinglePartError extends URError {
|
|
|
33
45
|
}
|
|
34
46
|
/**
|
|
35
47
|
* Error type for unexpected UR types.
|
|
48
|
+
*
|
|
49
|
+
* Message matches Rust bc-ur-rust/src/error.rs:
|
|
50
|
+
* `expected UR type {expected}, but found {found}`.
|
|
36
51
|
*/
|
|
37
52
|
declare class UnexpectedTypeError extends URError {
|
|
38
53
|
constructor(expected: string, found: string);
|
|
39
54
|
}
|
|
40
55
|
/**
|
|
41
56
|
* Error type for Bytewords encoding/decoding errors.
|
|
57
|
+
*
|
|
58
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `Bytewords error ({0})`.
|
|
42
59
|
*/
|
|
43
60
|
declare class BytewordsError extends URError {
|
|
44
61
|
constructor(message: string);
|
|
45
62
|
}
|
|
46
63
|
/**
|
|
47
64
|
* Error type for CBOR encoding/decoding errors.
|
|
65
|
+
*
|
|
66
|
+
* Message matches Rust bc-ur-rust/src/error.rs: `CBOR error ({0})`.
|
|
48
67
|
*/
|
|
49
68
|
declare class CBORError extends URError {
|
|
50
69
|
constructor(message: string);
|
|
51
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Error type for UR decoder errors.
|
|
73
|
+
* Matches Rust's Error::UR(String) variant.
|
|
74
|
+
*/
|
|
75
|
+
declare class URDecodeError extends URError {
|
|
76
|
+
constructor(message: string);
|
|
77
|
+
}
|
|
52
78
|
type Result<T> = T | Error;
|
|
53
79
|
/**
|
|
54
80
|
* Helper function to check if a result is an error.
|
|
@@ -108,12 +134,36 @@ declare class URType {
|
|
|
108
134
|
*/
|
|
109
135
|
static from(value: string): URType;
|
|
110
136
|
/**
|
|
111
|
-
* Safely creates a URType, returning
|
|
137
|
+
* Safely creates a URType, returning a typed `Result`-shaped
|
|
138
|
+
* discriminated union instead of throwing.
|
|
139
|
+
*
|
|
140
|
+
* Mirrors Rust `impl TryFrom<&str> for URType` /
|
|
141
|
+
* `impl TryFrom<String> for URType` (`bc-ur-rust/src/ur_type.rs`),
|
|
142
|
+
* which return `Result<URType, Error>`. The TS shape is the
|
|
143
|
+
* idiomatic discriminated form so callers can branch on `ok`
|
|
144
|
+
* without `instanceof`:
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* const r = URType.tryFrom("test");
|
|
149
|
+
* if (r.ok) {
|
|
150
|
+
* console.log(r.value.string()); // "test"
|
|
151
|
+
* } else {
|
|
152
|
+
* console.error(r.error.message);
|
|
153
|
+
* }
|
|
154
|
+
* ```
|
|
112
155
|
*
|
|
113
156
|
* @param value - The UR type string
|
|
114
|
-
* @returns
|
|
115
|
-
|
|
116
|
-
|
|
157
|
+
* @returns A typed Result: `{ ok: true; value: URType }` on success,
|
|
158
|
+
* `{ ok: false; error: InvalidTypeError }` on failure.
|
|
159
|
+
*/
|
|
160
|
+
static tryFrom(value: string): {
|
|
161
|
+
ok: true;
|
|
162
|
+
value: URType;
|
|
163
|
+
} | {
|
|
164
|
+
ok: false;
|
|
165
|
+
error: InvalidTypeError;
|
|
166
|
+
};
|
|
117
167
|
}
|
|
118
168
|
//#endregion
|
|
119
169
|
//#region src/ur.d.ts
|
|
@@ -159,11 +209,26 @@ declare class UR {
|
|
|
159
209
|
/**
|
|
160
210
|
* Creates a new UR from a UR string.
|
|
161
211
|
*
|
|
212
|
+
* Mirrors Rust's `UR::from_ur_string` (`bc-ur-rust/src/ur.rs:25-38`):
|
|
213
|
+
* 1. lowercase the entire string.
|
|
214
|
+
* 2. strip the `"ur:"` prefix → {@link InvalidSchemeError} if absent.
|
|
215
|
+
* 3. split on the first `/` → {@link TypeUnspecifiedError} if absent.
|
|
216
|
+
* 4. validate the type via {@link URType} → {@link InvalidTypeError}.
|
|
217
|
+
* 5. delegate the data section to the upstream-style decoder, which
|
|
218
|
+
* classifies the UR as single- or multi-part. Multi-part input is
|
|
219
|
+
* rejected with {@link NotSinglePartError}.
|
|
220
|
+
* 6. decode the bytewords payload (CRC32 + minimal mapping) →
|
|
221
|
+
* {@link BytewordsError} on failure.
|
|
222
|
+
* 7. parse the resulting bytes as CBOR → {@link CBORError} on failure.
|
|
223
|
+
*
|
|
162
224
|
* @param urString - A UR string like "ur:test/..."
|
|
163
225
|
* @throws {InvalidSchemeError} If the string doesn't start with "ur:"
|
|
164
|
-
* @throws {TypeUnspecifiedError} If no
|
|
226
|
+
* @throws {TypeUnspecifiedError} If no `/` separator is present
|
|
227
|
+
* @throws {InvalidTypeError} If the type contains invalid characters
|
|
165
228
|
* @throws {NotSinglePartError} If the UR is multi-part
|
|
166
|
-
* @throws {
|
|
229
|
+
* @throws {URDecodeError} For upstream-decoder errors (invalid indices, etc.)
|
|
230
|
+
* @throws {BytewordsError} If bytewords decoding fails
|
|
231
|
+
* @throws {CBORError} If CBOR parsing fails
|
|
167
232
|
*
|
|
168
233
|
* @example
|
|
169
234
|
* ```typescript
|
|
@@ -200,6 +265,12 @@ declare class UR {
|
|
|
200
265
|
qrString(): string;
|
|
201
266
|
/**
|
|
202
267
|
* Returns the QR data as bytes (uppercase UR string as UTF-8).
|
|
268
|
+
*
|
|
269
|
+
* Mirrors Rust's `UR::qr_data` (`ur.rs:52`) which does
|
|
270
|
+
* `self.qr_string().as_bytes().to_vec()` — the string's UTF-8 byte
|
|
271
|
+
* representation. We use `TextEncoder` rather than per-codepoint
|
|
272
|
+
* truncation so the behaviour stays correct if the QR string ever
|
|
273
|
+
* contains non-ASCII characters.
|
|
203
274
|
*/
|
|
204
275
|
qrData(): Uint8Array;
|
|
205
276
|
/**
|
|
@@ -215,6 +286,12 @@ declare class UR {
|
|
|
215
286
|
toString(): string;
|
|
216
287
|
/**
|
|
217
288
|
* Checks equality with another UR.
|
|
289
|
+
*
|
|
290
|
+
* Mirrors Rust's derived `PartialEq for UR` which compares the inner
|
|
291
|
+
* `ur_type` and the inner `cbor` field directly. We compare CBOR
|
|
292
|
+
* bytewise — `Uint8Array` equality, not `Array#toString` (which would
|
|
293
|
+
* coerce to a comma-joined string and could collide on pathological
|
|
294
|
+
* inputs).
|
|
218
295
|
*/
|
|
219
296
|
equals(other: UR): boolean;
|
|
220
297
|
}
|
|
@@ -226,17 +303,27 @@ declare class UR {
|
|
|
226
303
|
* Types implementing this interface should be able to convert themselves
|
|
227
304
|
* to CBOR data and associate that with a UR type identifier.
|
|
228
305
|
*
|
|
306
|
+
* Mirrors Rust's `UREncodable` trait (`bc-ur-rust/src/ur_encodable.rs`),
|
|
307
|
+
* which has a blanket impl `impl<T> UREncodable for T where T:
|
|
308
|
+
* CBORTaggedEncodable`. TypeScript has no equivalent of blanket impls, so
|
|
309
|
+
* implementers either write `ur()` / `urString()` directly *or* — for a
|
|
310
|
+
* type that already implements `CborTaggedEncodable` — call the helper
|
|
311
|
+
* functions {@link urFromEncodable} / {@link urStringFromEncodable} below
|
|
312
|
+
* to get the same auto-derivation that Rust provides for free.
|
|
313
|
+
*
|
|
229
314
|
* @example
|
|
230
315
|
* ```typescript
|
|
231
|
-
* class MyType implements UREncodable {
|
|
232
|
-
*
|
|
233
|
-
*
|
|
316
|
+
* class MyType implements UREncodable, CborTaggedEncodable {
|
|
317
|
+
* cborTags(): Tag[] {
|
|
318
|
+
* return [createTag(40000, "mytype")];
|
|
234
319
|
* }
|
|
235
320
|
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
321
|
+
* untaggedCbor(): Cbor { ... }
|
|
322
|
+
* taggedCbor(): Cbor { return createTaggedCbor(this); }
|
|
323
|
+
*
|
|
324
|
+
* // Auto-derived from the first cbor tag's name, just like Rust.
|
|
325
|
+
* ur(): UR { return urFromEncodable(this); }
|
|
326
|
+
* urString(): string { return urStringFromEncodable(this); }
|
|
240
327
|
* }
|
|
241
328
|
* ```
|
|
242
329
|
*/
|
|
@@ -250,6 +337,26 @@ interface UREncodable {
|
|
|
250
337
|
*/
|
|
251
338
|
urString(): string;
|
|
252
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Concrete equivalent of Rust's default `UREncodable::ur` impl
|
|
342
|
+
* (`bc-ur-rust/src/ur_encodable.rs:8-18`):
|
|
343
|
+
*
|
|
344
|
+
* - Reads the first tag returned by `encodable.cborTags()`.
|
|
345
|
+
* - Uses that tag's `name` as the UR type, throwing if no name is set —
|
|
346
|
+
* matching Rust's `panic!("CBOR tag {} must have a name. Did you call
|
|
347
|
+
* `register_tags()`?", tag.value())`.
|
|
348
|
+
* - Wraps the encodable's `untaggedCbor()` in a fresh {@link UR} bound to
|
|
349
|
+
* that type.
|
|
350
|
+
*
|
|
351
|
+
* Use from a class implementing both `UREncodable` and
|
|
352
|
+
* `CborTaggedEncodable` to skip writing the boilerplate yourself.
|
|
353
|
+
*/
|
|
354
|
+
declare function urFromEncodable(encodable: CborTaggedEncodable): UR;
|
|
355
|
+
/**
|
|
356
|
+
* Concrete equivalent of Rust's default `UREncodable::ur_string` impl
|
|
357
|
+
* (`bc-ur-rust/src/ur_encodable.rs:21`): `self.ur().string()`.
|
|
358
|
+
*/
|
|
359
|
+
declare function urStringFromEncodable(encodable: CborTaggedEncodable): string;
|
|
253
360
|
/**
|
|
254
361
|
* Helper function to check if an object implements UREncodable.
|
|
255
362
|
*/
|
|
@@ -262,17 +369,26 @@ declare function isUREncodable(obj: unknown): obj is UREncodable;
|
|
|
262
369
|
* Types implementing this interface should be able to create themselves
|
|
263
370
|
* from a UR containing their data.
|
|
264
371
|
*
|
|
372
|
+
* Mirrors Rust's `URDecodable` trait (`bc-ur-rust/src/ur_decodable.rs`),
|
|
373
|
+
* which has a blanket impl `impl<T> URDecodable for T where T:
|
|
374
|
+
* CBORTaggedDecodable`. TypeScript has no equivalent of blanket impls, so
|
|
375
|
+
* implementers either write `fromUR()` directly *or* — for a type that
|
|
376
|
+
* already implements `CborTaggedDecodable` — call the helper functions
|
|
377
|
+
* {@link decodableFromUR} / {@link decodableFromURString} below to get the
|
|
378
|
+
* same auto-derivation that Rust provides for free.
|
|
379
|
+
*
|
|
265
380
|
* @example
|
|
266
381
|
* ```typescript
|
|
267
|
-
* class MyType implements URDecodable {
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
* // Decode from CBOR and return MyType instance
|
|
382
|
+
* class MyType implements URDecodable, CborTaggedDecodable<MyType> {
|
|
383
|
+
* cborTags(): Tag[] {
|
|
384
|
+
* return [createTag(40000, "mytype")];
|
|
271
385
|
* }
|
|
386
|
+
* fromUntaggedCbor(cbor: Cbor): MyType { ... }
|
|
387
|
+
* fromTaggedCbor(cbor: Cbor): MyType { ... }
|
|
272
388
|
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
* }
|
|
389
|
+
* // Auto-derived from the first cbor tag's name, matching Rust.
|
|
390
|
+
* fromUR(ur: UR): MyType { return decodableFromUR(this, ur); }
|
|
391
|
+
* fromURString(s: string): MyType { return decodableFromURString(this, s); }
|
|
276
392
|
* }
|
|
277
393
|
* ```
|
|
278
394
|
*/
|
|
@@ -297,6 +413,26 @@ interface URDecodable {
|
|
|
297
413
|
*/
|
|
298
414
|
fromURString?(urString: string): unknown;
|
|
299
415
|
}
|
|
416
|
+
/**
|
|
417
|
+
* Concrete equivalent of Rust's default `URDecodable::from_ur` impl
|
|
418
|
+
* (`bc-ur-rust/src/ur_decodable.rs:7-15`):
|
|
419
|
+
*
|
|
420
|
+
* 1. Read the first tag returned by `decodable.cborTags()`.
|
|
421
|
+
* 2. Verify the UR's type matches that tag's name via `UR#checkType`
|
|
422
|
+
* (this is what Rust's `ur.check_type(...)` does — surface
|
|
423
|
+
* `UnexpectedTypeError` on mismatch).
|
|
424
|
+
* 3. Delegate to `decodable.fromUntaggedCbor(ur.cbor())`.
|
|
425
|
+
*
|
|
426
|
+
* Use from a class implementing both `URDecodable` and
|
|
427
|
+
* `CborTaggedDecodable<T>` to skip the type-check / delegate boilerplate.
|
|
428
|
+
*/
|
|
429
|
+
declare function decodableFromUR<T>(decodable: CborTaggedDecodable<T>, ur: UR): T;
|
|
430
|
+
/**
|
|
431
|
+
* Concrete equivalent of Rust's default `URDecodable::from_ur_string` impl
|
|
432
|
+
* (`bc-ur-rust/src/ur_decodable.rs:17-22`):
|
|
433
|
+
* `Self::from_ur(UR::from_ur_string(s)?)`.
|
|
434
|
+
*/
|
|
435
|
+
declare function decodableFromURString<T>(decodable: CborTaggedDecodable<T>, urString: string): T;
|
|
300
436
|
/**
|
|
301
437
|
* Helper function to check if an object implements URDecodable.
|
|
302
438
|
*/
|
|
@@ -382,12 +518,6 @@ declare class MultipartEncoder {
|
|
|
382
518
|
* ```
|
|
383
519
|
*/
|
|
384
520
|
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
521
|
/**
|
|
392
522
|
* Gets the next part of the encoding.
|
|
393
523
|
*
|
|
@@ -405,10 +535,17 @@ declare class MultipartEncoder {
|
|
|
405
535
|
nextPart(): string;
|
|
406
536
|
/**
|
|
407
537
|
* Encodes a fountain part as a UR string.
|
|
538
|
+
*
|
|
539
|
+
* Always emits the multipart `ur:<type>/<seqNum>-<seqLen>/<bytewords>`
|
|
540
|
+
* format — including for single-part messages (`1-1/...`). This mirrors
|
|
541
|
+
* Rust's `bc_ur::MultipartEncoder::next_part`, which never short-circuits
|
|
542
|
+
* to plain UR. Callers that want plain UR for tiny payloads should use
|
|
543
|
+
* `UR.string()` directly instead of constructing a `MultipartEncoder`.
|
|
408
544
|
*/
|
|
409
545
|
private _encodePart;
|
|
410
546
|
/**
|
|
411
|
-
* Encodes part metadata and data
|
|
547
|
+
* Encodes part metadata and data as CBOR for bytewords encoding.
|
|
548
|
+
* Format: CBOR array [seqNum, seqLen, messageLen, checksum, data]
|
|
412
549
|
*/
|
|
413
550
|
private _encodePartData;
|
|
414
551
|
/**
|
|
@@ -422,17 +559,6 @@ declare class MultipartEncoder {
|
|
|
422
559
|
* for additional redundancy.
|
|
423
560
|
*/
|
|
424
561
|
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
562
|
}
|
|
437
563
|
//#endregion
|
|
438
564
|
//#region src/multipart-decoder.d.ts
|
|
@@ -473,6 +599,8 @@ declare class MultipartDecoder {
|
|
|
473
599
|
private _parsePart;
|
|
474
600
|
/**
|
|
475
601
|
* Decodes a multipart UR's fountain part data.
|
|
602
|
+
*
|
|
603
|
+
* The multipart body is a CBOR array: [seqNum, seqLen, messageLen, checksum, data]
|
|
476
604
|
*/
|
|
477
605
|
private _decodeFountainPart;
|
|
478
606
|
/**
|
|
@@ -485,226 +613,29 @@ declare class MultipartDecoder {
|
|
|
485
613
|
* @returns The decoded UR, or null if not yet complete
|
|
486
614
|
*/
|
|
487
615
|
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
616
|
}
|
|
497
617
|
//#endregion
|
|
498
|
-
//#region src/
|
|
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
|
-
}
|
|
628
|
-
//#endregion
|
|
629
|
-
//#region src/xoshiro.d.ts
|
|
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
|
-
}
|
|
618
|
+
//#region src/utils.d.ts
|
|
691
619
|
/**
|
|
692
|
-
*
|
|
620
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
621
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
693
622
|
*
|
|
694
|
-
* This ensures that both encoder and decoder produce the same random sequence
|
|
695
|
-
* for a given message and part number.
|
|
696
623
|
*/
|
|
697
|
-
declare function createSeed(checksum: number, seqNum: number): Uint8Array;
|
|
698
|
-
//#endregion
|
|
699
|
-
//#region src/utils.d.ts
|
|
700
624
|
/**
|
|
701
625
|
* Checks if a character is a valid UR type character.
|
|
702
|
-
*
|
|
626
|
+
*
|
|
627
|
+
* Mirrors Rust's `URTypeChar::is_ur_type` (`bc-ur-rust/src/utils.rs:6-19`):
|
|
628
|
+
* lowercase a-z, digits 0-9, and the hyphen `-`.
|
|
703
629
|
*/
|
|
704
630
|
declare function isURTypeChar(char: string): boolean;
|
|
705
631
|
/**
|
|
706
632
|
* Checks if a string is a valid UR type.
|
|
707
|
-
*
|
|
633
|
+
*
|
|
634
|
+
* Mirrors Rust's `URTypeString::is_ur_type` (`bc-ur-rust/src/utils.rs:26-32`)
|
|
635
|
+
* which is `self.chars().all(...)` — meaning **the empty string is accepted**
|
|
636
|
+
* (a vacuously-true `all` over no chars). We mirror that here so that
|
|
637
|
+
* `URType::new("")` succeeds in both ports; the round-trip then fails at
|
|
638
|
+
* decode-time with `TypeUnspecified`.
|
|
708
639
|
*/
|
|
709
640
|
declare function isValidURType(urType: string): boolean;
|
|
710
641
|
/**
|
|
@@ -716,36 +647,78 @@ declare function validateURType(urType: string): string;
|
|
|
716
647
|
* See: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-004-bytewords.md
|
|
717
648
|
*/
|
|
718
649
|
declare const BYTEWORDS: string[];
|
|
719
|
-
declare const BYTEWORDS_MAP: Map<string, number>;
|
|
720
650
|
/**
|
|
721
651
|
* Bytemojis for encoding/decoding bytes as emojis.
|
|
722
652
|
* See: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2024-008-bytemoji.md
|
|
723
653
|
*/
|
|
724
654
|
declare const BYTEMOJIS: string[];
|
|
655
|
+
/**
|
|
656
|
+
* Encodes an arbitrary byte slice as a string of space-separated bytewords.
|
|
657
|
+
*
|
|
658
|
+
* Mirrors `bytewords::encode_to_words` in `bc-ur-rust` (≥ v0.19.1). Does not
|
|
659
|
+
* add a CRC32 checksum — use {@link encodeBytewords} for UR-style encoding.
|
|
660
|
+
*/
|
|
661
|
+
declare function encodeToWords(data: Uint8Array): string;
|
|
662
|
+
/**
|
|
663
|
+
* Encodes an arbitrary byte slice as a string of space-separated bytemojis.
|
|
664
|
+
*
|
|
665
|
+
* Mirrors `bytewords::encode_to_bytemojis` in `bc-ur-rust` (≥ v0.19.1).
|
|
666
|
+
*/
|
|
667
|
+
declare function encodeToBytemojis(data: Uint8Array): string;
|
|
668
|
+
/**
|
|
669
|
+
* Encodes an arbitrary byte slice as minimal bytewords (first + last letter of
|
|
670
|
+
* each word, concatenated with no separator).
|
|
671
|
+
*
|
|
672
|
+
* Mirrors `bytewords::encode_to_minimal_bytewords` in `bc-ur-rust`
|
|
673
|
+
* (≥ v0.19.1). Does not add a CRC32 checksum.
|
|
674
|
+
*/
|
|
675
|
+
declare function encodeToMinimalBytewords(data: Uint8Array): string;
|
|
725
676
|
/**
|
|
726
677
|
* Encodes a 4-byte slice as a string of bytewords for identification.
|
|
678
|
+
*
|
|
679
|
+
* Thin wrapper over {@link encodeToWords} that enforces the 4-byte length
|
|
680
|
+
* contract historically used by `bc-ur-rust`'s `bytewords::identifier`.
|
|
727
681
|
*/
|
|
728
682
|
declare function encodeBytewordsIdentifier(data: Uint8Array): string;
|
|
729
683
|
/**
|
|
730
684
|
* Encodes a 4-byte slice as a string of bytemojis for identification.
|
|
685
|
+
*
|
|
686
|
+
* Thin wrapper over {@link encodeToBytemojis} that enforces the 4-byte length
|
|
687
|
+
* contract historically used by `bc-ur-rust`'s `bytewords::bytemoji_identifier`.
|
|
731
688
|
*/
|
|
732
689
|
declare function encodeBytemojisIdentifier(data: Uint8Array): string;
|
|
690
|
+
/**
|
|
691
|
+
* Returns `true` if `emoji` is one of the 256 bytemojis.
|
|
692
|
+
*
|
|
693
|
+
* Mirrors `bytewords::is_valid_bytemoji` in `bc-ur-rust` (≥ v0.19.1).
|
|
694
|
+
*/
|
|
695
|
+
declare function isValidBytemoji(emoji: string): boolean;
|
|
696
|
+
/**
|
|
697
|
+
* Canonicalises a byteword token (2–4 ASCII letters, case-insensitive) to its
|
|
698
|
+
* full 4-letter lowercase form. Returns `undefined` if the token is not a
|
|
699
|
+
* valid byteword or any of its short forms.
|
|
700
|
+
*
|
|
701
|
+
* Mirrors `bytewords::canonicalize_byteword` in `bc-ur-rust` (≥ v0.19.1).
|
|
702
|
+
*
|
|
703
|
+
* - 2-letter tokens are matched against the first + last letter of each
|
|
704
|
+
* byteword (identical to the minimal bytewords encoding).
|
|
705
|
+
* - 3-letter tokens are matched against the first 3 and the last 3 letters of
|
|
706
|
+
* each byteword; if both match different entries, the first-3 match wins
|
|
707
|
+
* (matching rust's `or_else` priority).
|
|
708
|
+
* - 4-letter tokens must exactly match a full byteword (after lower-casing).
|
|
709
|
+
*/
|
|
710
|
+
declare function canonicalizeByteword(token: string): string | undefined;
|
|
733
711
|
/**
|
|
734
712
|
* Bytewords encoding style.
|
|
735
713
|
*/
|
|
736
714
|
declare enum BytewordsStyle {
|
|
737
715
|
/** Full 4-letter words separated by spaces */
|
|
738
716
|
Standard = "standard",
|
|
739
|
-
/** Full 4-letter words
|
|
717
|
+
/** Full 4-letter words separated by hyphens (URI-safe) */
|
|
740
718
|
Uri = "uri",
|
|
741
719
|
/** First and last character only (minimal) - used by UR encoding */
|
|
742
|
-
Minimal = "minimal"
|
|
720
|
+
Minimal = "minimal"
|
|
743
721
|
}
|
|
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
722
|
/**
|
|
750
723
|
* Encode data as bytewords with the specified style.
|
|
751
724
|
* Includes CRC32 checksum.
|
|
@@ -754,8 +727,23 @@ declare function encodeBytewords(data: Uint8Array, style?: BytewordsStyle): stri
|
|
|
754
727
|
/**
|
|
755
728
|
* Decode bytewords string back to data.
|
|
756
729
|
* Validates and removes CRC32 checksum.
|
|
730
|
+
*
|
|
731
|
+
* Errors mirror the upstream Rust `ur::bytewords::Error` enum
|
|
732
|
+
* (`ur-0.4.1/src/bytewords.rs`):
|
|
733
|
+
* - `NonAscii` — input contains non-ASCII characters (checked first).
|
|
734
|
+
* - `InvalidLength` — minimal-style input has odd length.
|
|
735
|
+
* - `InvalidWord` — a token does not map to a byteword index.
|
|
736
|
+
* - `InvalidChecksum` — the trailing 4-byte CRC32 does not match.
|
|
737
|
+
*
|
|
738
|
+
* All variants are surfaced as {@link BytewordsError} with the same default
|
|
739
|
+
* `Display` strings as Rust (e.g. "invalid checksum", "non-ASCII"), so
|
|
740
|
+
* callers can branch on the error class rather than the bare `Error`
|
|
741
|
+
* thrown by earlier revisions of this port.
|
|
757
742
|
*/
|
|
758
743
|
declare function decodeBytewords(encoded: string, style?: BytewordsStyle): Uint8Array;
|
|
744
|
+
declare namespace bytewords_namespace_d_exports {
|
|
745
|
+
export { BYTEMOJIS, BYTEWORDS, BytewordsStyle as Style, encodeBytemojisIdentifier as bytemojiIdentifier, canonicalizeByteword, decodeBytewords as decode, encodeBytewords as encode, encodeToBytemojis, encodeToMinimalBytewords, encodeToWords, encodeBytewordsIdentifier as identifier, isValidBytemoji };
|
|
746
|
+
}
|
|
759
747
|
//#endregion
|
|
760
|
-
export { BYTEMOJIS, BYTEWORDS,
|
|
748
|
+
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
749
|
//# sourceMappingURL=index.d.cts.map
|