@bcts/uniform-resources 1.0.0-alpha.11 → 1.0.0-alpha.13
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/dist/index.cjs +38 -112
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -247
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +8 -247
- package/dist/index.d.mts.map +1 -1
- package/dist/index.iife.js +38 -112
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +38 -99
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
- package/src/error.ts +11 -0
- package/src/index.ts +5 -24
- package/src/multipart-decoder.ts +0 -22
- package/src/multipart-encoder.ts +0 -27
package/dist/index.d.cts
CHANGED
|
@@ -49,6 +49,13 @@ declare class BytewordsError extends URError {
|
|
|
49
49
|
declare class CBORError extends URError {
|
|
50
50
|
constructor(message: string);
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Error type for UR decoder errors.
|
|
54
|
+
* Matches Rust's Error::UR(String) variant.
|
|
55
|
+
*/
|
|
56
|
+
declare class URDecodeError extends URError {
|
|
57
|
+
constructor(message: string);
|
|
58
|
+
}
|
|
52
59
|
type Result<T> = T | Error;
|
|
53
60
|
/**
|
|
54
61
|
* Helper function to check if a result is an error.
|
|
@@ -382,12 +389,6 @@ declare class MultipartEncoder {
|
|
|
382
389
|
* ```
|
|
383
390
|
*/
|
|
384
391
|
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
392
|
/**
|
|
392
393
|
* Gets the next part of the encoding.
|
|
393
394
|
*
|
|
@@ -422,17 +423,6 @@ declare class MultipartEncoder {
|
|
|
422
423
|
* for additional redundancy.
|
|
423
424
|
*/
|
|
424
425
|
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
426
|
}
|
|
437
427
|
//#endregion
|
|
438
428
|
//#region src/multipart-decoder.d.ts
|
|
@@ -485,238 +475,14 @@ declare class MultipartDecoder {
|
|
|
485
475
|
* @returns The decoded UR, or null if not yet complete
|
|
486
476
|
*/
|
|
487
477
|
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
|
-
}
|
|
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
478
|
}
|
|
691
|
-
/**
|
|
692
|
-
* Creates a seed for the Xoshiro PRNG from message checksum and sequence number.
|
|
693
|
-
*
|
|
694
|
-
* This ensures that both encoder and decoder produce the same random sequence
|
|
695
|
-
* for a given message and part number.
|
|
696
|
-
*/
|
|
697
|
-
declare function createSeed(checksum: number, seqNum: number): Uint8Array;
|
|
698
479
|
//#endregion
|
|
699
480
|
//#region src/utils.d.ts
|
|
700
|
-
/**
|
|
701
|
-
* Checks if a character is a valid UR type character.
|
|
702
|
-
* Valid characters are lowercase letters, digits, and hyphens.
|
|
703
|
-
*/
|
|
704
|
-
declare function isURTypeChar(char: string): boolean;
|
|
705
|
-
/**
|
|
706
|
-
* Checks if a string is a valid UR type.
|
|
707
|
-
* Valid UR types contain only lowercase letters, digits, and hyphens.
|
|
708
|
-
*/
|
|
709
|
-
declare function isValidURType(urType: string): boolean;
|
|
710
|
-
/**
|
|
711
|
-
* Validates and returns a UR type, or throws an error if invalid.
|
|
712
|
-
*/
|
|
713
|
-
declare function validateURType(urType: string): string;
|
|
714
481
|
/**
|
|
715
482
|
* Bytewords for encoding/decoding bytes as words.
|
|
716
483
|
* See: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-004-bytewords.md
|
|
717
484
|
*/
|
|
718
485
|
declare const BYTEWORDS: string[];
|
|
719
|
-
declare const BYTEWORDS_MAP: Map<string, number>;
|
|
720
486
|
/**
|
|
721
487
|
* Bytemojis for encoding/decoding bytes as emojis.
|
|
722
488
|
* See: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2024-008-bytemoji.md
|
|
@@ -741,11 +507,6 @@ declare enum BytewordsStyle {
|
|
|
741
507
|
/** First and last character only (minimal) - used by UR encoding */
|
|
742
508
|
Minimal = "minimal",
|
|
743
509
|
}
|
|
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
510
|
/**
|
|
750
511
|
* Encode data as bytewords with the specified style.
|
|
751
512
|
* Includes CRC32 checksum.
|
|
@@ -757,5 +518,5 @@ declare function encodeBytewords(data: Uint8Array, style?: BytewordsStyle): stri
|
|
|
757
518
|
*/
|
|
758
519
|
declare function decodeBytewords(encoded: string, style?: BytewordsStyle): Uint8Array;
|
|
759
520
|
//#endregion
|
|
760
|
-
export { BYTEMOJIS, BYTEWORDS,
|
|
521
|
+
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, decodeBytewords, encodeBytemojisIdentifier, encodeBytewords, encodeBytewordsIdentifier, isError, isURCodable, isURDecodable, isUREncodable };
|
|
761
522
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/error.ts","../src/ur-type.ts","../src/ur.ts","../src/ur-encodable.ts","../src/ur-decodable.ts","../src/ur-codable.ts","../src/multipart-encoder.ts","../src/multipart-decoder.ts","../src/
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/error.ts","../src/ur-type.ts","../src/ur.ts","../src/ur-encodable.ts","../src/ur-decodable.ts","../src/ur-codable.ts","../src/multipart-encoder.ts","../src/multipart-decoder.ts","../src/utils.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -49,6 +49,13 @@ declare class BytewordsError extends URError {
|
|
|
49
49
|
declare class CBORError extends URError {
|
|
50
50
|
constructor(message: string);
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Error type for UR decoder errors.
|
|
54
|
+
* Matches Rust's Error::UR(String) variant.
|
|
55
|
+
*/
|
|
56
|
+
declare class URDecodeError extends URError {
|
|
57
|
+
constructor(message: string);
|
|
58
|
+
}
|
|
52
59
|
type Result<T> = T | Error;
|
|
53
60
|
/**
|
|
54
61
|
* Helper function to check if a result is an error.
|
|
@@ -382,12 +389,6 @@ declare class MultipartEncoder {
|
|
|
382
389
|
* ```
|
|
383
390
|
*/
|
|
384
391
|
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
392
|
/**
|
|
392
393
|
* Gets the next part of the encoding.
|
|
393
394
|
*
|
|
@@ -422,17 +423,6 @@ declare class MultipartEncoder {
|
|
|
422
423
|
* for additional redundancy.
|
|
423
424
|
*/
|
|
424
425
|
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
426
|
}
|
|
437
427
|
//#endregion
|
|
438
428
|
//#region src/multipart-decoder.d.ts
|
|
@@ -485,238 +475,14 @@ declare class MultipartDecoder {
|
|
|
485
475
|
* @returns The decoded UR, or null if not yet complete
|
|
486
476
|
*/
|
|
487
477
|
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
|
-
}
|
|
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
478
|
}
|
|
691
|
-
/**
|
|
692
|
-
* Creates a seed for the Xoshiro PRNG from message checksum and sequence number.
|
|
693
|
-
*
|
|
694
|
-
* This ensures that both encoder and decoder produce the same random sequence
|
|
695
|
-
* for a given message and part number.
|
|
696
|
-
*/
|
|
697
|
-
declare function createSeed(checksum: number, seqNum: number): Uint8Array;
|
|
698
479
|
//#endregion
|
|
699
480
|
//#region src/utils.d.ts
|
|
700
|
-
/**
|
|
701
|
-
* Checks if a character is a valid UR type character.
|
|
702
|
-
* Valid characters are lowercase letters, digits, and hyphens.
|
|
703
|
-
*/
|
|
704
|
-
declare function isURTypeChar(char: string): boolean;
|
|
705
|
-
/**
|
|
706
|
-
* Checks if a string is a valid UR type.
|
|
707
|
-
* Valid UR types contain only lowercase letters, digits, and hyphens.
|
|
708
|
-
*/
|
|
709
|
-
declare function isValidURType(urType: string): boolean;
|
|
710
|
-
/**
|
|
711
|
-
* Validates and returns a UR type, or throws an error if invalid.
|
|
712
|
-
*/
|
|
713
|
-
declare function validateURType(urType: string): string;
|
|
714
481
|
/**
|
|
715
482
|
* Bytewords for encoding/decoding bytes as words.
|
|
716
483
|
* See: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-004-bytewords.md
|
|
717
484
|
*/
|
|
718
485
|
declare const BYTEWORDS: string[];
|
|
719
|
-
declare const BYTEWORDS_MAP: Map<string, number>;
|
|
720
486
|
/**
|
|
721
487
|
* Bytemojis for encoding/decoding bytes as emojis.
|
|
722
488
|
* See: https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2024-008-bytemoji.md
|
|
@@ -741,11 +507,6 @@ declare enum BytewordsStyle {
|
|
|
741
507
|
/** First and last character only (minimal) - used by UR encoding */
|
|
742
508
|
Minimal = "minimal",
|
|
743
509
|
}
|
|
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
510
|
/**
|
|
750
511
|
* Encode data as bytewords with the specified style.
|
|
751
512
|
* Includes CRC32 checksum.
|
|
@@ -757,5 +518,5 @@ declare function encodeBytewords(data: Uint8Array, style?: BytewordsStyle): stri
|
|
|
757
518
|
*/
|
|
758
519
|
declare function decodeBytewords(encoded: string, style?: BytewordsStyle): Uint8Array;
|
|
759
520
|
//#endregion
|
|
760
|
-
export { BYTEMOJIS, BYTEWORDS,
|
|
521
|
+
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, decodeBytewords, encodeBytemojisIdentifier, encodeBytewords, encodeBytewordsIdentifier, isError, isURCodable, isURDecodable, isUREncodable };
|
|
761
522
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/error.ts","../src/ur-type.ts","../src/ur.ts","../src/ur-encodable.ts","../src/ur-decodable.ts","../src/ur-codable.ts","../src/multipart-encoder.ts","../src/multipart-decoder.ts","../src/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/error.ts","../src/ur-type.ts","../src/ur.ts","../src/ur-encodable.ts","../src/ur-decodable.ts","../src/ur-codable.ts","../src/multipart-encoder.ts","../src/multipart-decoder.ts","../src/utils.ts"],"sourcesContent":[],"mappings":"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"}
|