@qrkit/bc-ur 2.0.0-beta.9-qrkit.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +996 -0
- package/dist/commonjs/classes/FountainDecoder.d.ts +125 -0
- package/dist/commonjs/classes/FountainDecoder.js +453 -0
- package/dist/commonjs/classes/FountainDecoder.js.map +1 -0
- package/dist/commonjs/classes/FountainEncoder.d.ts +63 -0
- package/dist/commonjs/classes/FountainEncoder.js +168 -0
- package/dist/commonjs/classes/FountainEncoder.js.map +1 -0
- package/dist/commonjs/classes/RegistryItem.d.ts +104 -0
- package/dist/commonjs/classes/RegistryItem.js +172 -0
- package/dist/commonjs/classes/RegistryItem.js.map +1 -0
- package/dist/commonjs/classes/UR.d.ts +89 -0
- package/dist/commonjs/classes/UR.js +243 -0
- package/dist/commonjs/classes/UR.js.map +1 -0
- package/dist/commonjs/classes/UrFountainDecoder.d.ts +15 -0
- package/dist/commonjs/classes/UrFountainDecoder.js +127 -0
- package/dist/commonjs/classes/UrFountainDecoder.js.map +1 -0
- package/dist/commonjs/classes/UrFountainEncoder.d.ts +42 -0
- package/dist/commonjs/classes/UrFountainEncoder.js +92 -0
- package/dist/commonjs/classes/UrFountainEncoder.js.map +1 -0
- package/dist/commonjs/classes/key.helper.d.ts +27 -0
- package/dist/commonjs/classes/key.helper.js +70 -0
- package/dist/commonjs/classes/key.helper.js.map +1 -0
- package/dist/commonjs/encodingMethods/BytewordEncoding.d.ts +11 -0
- package/dist/commonjs/encodingMethods/BytewordEncoding.js +23 -0
- package/dist/commonjs/encodingMethods/BytewordEncoding.js.map +1 -0
- package/dist/commonjs/encodingMethods/CborEncoding.d.ts +44 -0
- package/dist/commonjs/encodingMethods/CborEncoding.js +151 -0
- package/dist/commonjs/encodingMethods/CborEncoding.js.map +1 -0
- package/dist/commonjs/encodingMethods/HexEncoding.d.ts +8 -0
- package/dist/commonjs/encodingMethods/HexEncoding.js +24 -0
- package/dist/commonjs/encodingMethods/HexEncoding.js.map +1 -0
- package/dist/commonjs/encodingMethods/UrEncoding.d.ts +10 -0
- package/dist/commonjs/encodingMethods/UrEncoding.js +19 -0
- package/dist/commonjs/encodingMethods/UrEncoding.js.map +1 -0
- package/dist/commonjs/encodingMethods/bytewords.d.ts +27 -0
- package/dist/commonjs/encodingMethods/bytewords.js +152 -0
- package/dist/commonjs/encodingMethods/bytewords.js.map +1 -0
- package/dist/commonjs/encodingMethods/index.d.ts +19 -0
- package/dist/commonjs/encodingMethods/index.js +27 -0
- package/dist/commonjs/encodingMethods/index.js.map +1 -0
- package/dist/commonjs/encodingMethods/pipeline.d.ts +19 -0
- package/dist/commonjs/encodingMethods/pipeline.js +80 -0
- package/dist/commonjs/encodingMethods/pipeline.js.map +1 -0
- package/dist/commonjs/enums/EncodingMethodName.d.ts +10 -0
- package/dist/commonjs/enums/EncodingMethodName.js +15 -0
- package/dist/commonjs/enums/EncodingMethodName.js.map +1 -0
- package/dist/commonjs/errors.d.ts +15 -0
- package/dist/commonjs/errors.js +39 -0
- package/dist/commonjs/errors.js.map +1 -0
- package/dist/commonjs/helpers/aliasSampling.d.ts +6 -0
- package/dist/commonjs/helpers/aliasSampling.js +73 -0
- package/dist/commonjs/helpers/aliasSampling.js.map +1 -0
- package/dist/commonjs/helpers/crc32.d.ts +1 -0
- package/dist/commonjs/helpers/crc32.js +19 -0
- package/dist/commonjs/helpers/crc32.js.map +1 -0
- package/dist/commonjs/helpers/fountainUtils.d.ts +40 -0
- package/dist/commonjs/helpers/fountainUtils.js +124 -0
- package/dist/commonjs/helpers/fountainUtils.js.map +1 -0
- package/dist/commonjs/helpers/sha256.d.ts +1 -0
- package/dist/commonjs/helpers/sha256.js +78 -0
- package/dist/commonjs/helpers/sha256.js.map +1 -0
- package/dist/commonjs/helpers/type.helper.d.ts +3 -0
- package/dist/commonjs/helpers/type.helper.js +3 -0
- package/dist/commonjs/helpers/type.helper.js.map +1 -0
- package/dist/commonjs/helpers/uintArrayHelper.d.ts +287 -0
- package/dist/commonjs/helpers/uintArrayHelper.js +545 -0
- package/dist/commonjs/helpers/uintArrayHelper.js.map +1 -0
- package/dist/commonjs/helpers/utils.d.ts +55 -0
- package/dist/commonjs/helpers/utils.js +123 -0
- package/dist/commonjs/helpers/utils.js.map +1 -0
- package/dist/commonjs/index-react-native.d.ts +9 -0
- package/dist/commonjs/index-react-native.js +15 -0
- package/dist/commonjs/index-react-native.js.map +1 -0
- package/dist/commonjs/index.d.ts +21 -0
- package/dist/commonjs/index.js +34 -0
- package/dist/commonjs/index.js.map +1 -0
- package/dist/commonjs/interfaces/IEncodingMethod.d.ts +9 -0
- package/dist/commonjs/interfaces/IEncodingMethod.js +3 -0
- package/dist/commonjs/interfaces/IEncodingMethod.js.map +1 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/commonjs/registry.d.ts +26 -0
- package/dist/commonjs/registry.js +118 -0
- package/dist/commonjs/registry.js.map +1 -0
- package/dist/commonjs/test.utils.d.ts +31 -0
- package/dist/commonjs/test.utils.js +88 -0
- package/dist/commonjs/test.utils.js.map +1 -0
- package/dist/commonjs/wrappers/cbor2-cjs.cjs.map +1 -0
- package/dist/commonjs/wrappers/cbor2.d.ts +2 -0
- package/dist/commonjs/wrappers/cbor2.js +14 -0
- package/dist/commonjs/wrappers/cbor2Wrapper.d.ts +14 -0
- package/dist/commonjs/wrappers/cbor2Wrapper.js +49 -0
- package/dist/commonjs/wrappers/cbor2Wrapper.js.map +1 -0
- package/dist/commonjs/xoshiro.d.ts +12 -0
- package/dist/commonjs/xoshiro.js +52 -0
- package/dist/commonjs/xoshiro.js.map +1 -0
- package/dist/esm/classes/FountainDecoder.d.ts +125 -0
- package/dist/esm/classes/FountainDecoder.js +447 -0
- package/dist/esm/classes/FountainDecoder.js.map +1 -0
- package/dist/esm/classes/FountainEncoder.d.ts +63 -0
- package/dist/esm/classes/FountainEncoder.js +164 -0
- package/dist/esm/classes/FountainEncoder.js.map +1 -0
- package/dist/esm/classes/RegistryItem.d.ts +104 -0
- package/dist/esm/classes/RegistryItem.js +166 -0
- package/dist/esm/classes/RegistryItem.js.map +1 -0
- package/dist/esm/classes/UR.d.ts +89 -0
- package/dist/esm/classes/UR.js +239 -0
- package/dist/esm/classes/UR.js.map +1 -0
- package/dist/esm/classes/UrFountainDecoder.d.ts +15 -0
- package/dist/esm/classes/UrFountainDecoder.js +123 -0
- package/dist/esm/classes/UrFountainDecoder.js.map +1 -0
- package/dist/esm/classes/UrFountainEncoder.d.ts +42 -0
- package/dist/esm/classes/UrFountainEncoder.js +88 -0
- package/dist/esm/classes/UrFountainEncoder.js.map +1 -0
- package/dist/esm/classes/key.helper.d.ts +27 -0
- package/dist/esm/classes/key.helper.js +66 -0
- package/dist/esm/classes/key.helper.js.map +1 -0
- package/dist/esm/encodingMethods/BytewordEncoding.d.ts +11 -0
- package/dist/esm/encodingMethods/BytewordEncoding.js +19 -0
- package/dist/esm/encodingMethods/BytewordEncoding.js.map +1 -0
- package/dist/esm/encodingMethods/CborEncoding.d.ts +44 -0
- package/dist/esm/encodingMethods/CborEncoding.js +147 -0
- package/dist/esm/encodingMethods/CborEncoding.js.map +1 -0
- package/dist/esm/encodingMethods/HexEncoding.d.ts +8 -0
- package/dist/esm/encodingMethods/HexEncoding.js +20 -0
- package/dist/esm/encodingMethods/HexEncoding.js.map +1 -0
- package/dist/esm/encodingMethods/UrEncoding.d.ts +10 -0
- package/dist/esm/encodingMethods/UrEncoding.js +15 -0
- package/dist/esm/encodingMethods/UrEncoding.js.map +1 -0
- package/dist/esm/encodingMethods/bytewords.d.ts +27 -0
- package/dist/esm/encodingMethods/bytewords.js +147 -0
- package/dist/esm/encodingMethods/bytewords.js.map +1 -0
- package/dist/esm/encodingMethods/index.d.ts +19 -0
- package/dist/esm/encodingMethods/index.js +24 -0
- package/dist/esm/encodingMethods/index.js.map +1 -0
- package/dist/esm/encodingMethods/pipeline.d.ts +19 -0
- package/dist/esm/encodingMethods/pipeline.js +76 -0
- package/dist/esm/encodingMethods/pipeline.js.map +1 -0
- package/dist/esm/enums/EncodingMethodName.d.ts +10 -0
- package/dist/esm/enums/EncodingMethodName.js +12 -0
- package/dist/esm/enums/EncodingMethodName.js.map +1 -0
- package/dist/esm/errors.d.ts +15 -0
- package/dist/esm/errors.js +31 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/helpers/aliasSampling.d.ts +6 -0
- package/dist/esm/helpers/aliasSampling.js +70 -0
- package/dist/esm/helpers/aliasSampling.js.map +1 -0
- package/dist/esm/helpers/crc32.d.ts +1 -0
- package/dist/esm/helpers/crc32.js +16 -0
- package/dist/esm/helpers/crc32.js.map +1 -0
- package/dist/esm/helpers/fountainUtils.d.ts +40 -0
- package/dist/esm/helpers/fountainUtils.js +114 -0
- package/dist/esm/helpers/fountainUtils.js.map +1 -0
- package/dist/esm/helpers/sha256.d.ts +1 -0
- package/dist/esm/helpers/sha256.js +75 -0
- package/dist/esm/helpers/sha256.js.map +1 -0
- package/dist/esm/helpers/type.helper.d.ts +3 -0
- package/dist/esm/helpers/type.helper.js +2 -0
- package/dist/esm/helpers/type.helper.js.map +1 -0
- package/dist/esm/helpers/uintArrayHelper.d.ts +287 -0
- package/dist/esm/helpers/uintArrayHelper.js +526 -0
- package/dist/esm/helpers/uintArrayHelper.js.map +1 -0
- package/dist/esm/helpers/utils.d.ts +55 -0
- package/dist/esm/helpers/utils.js +102 -0
- package/dist/esm/helpers/utils.js.map +1 -0
- package/dist/esm/index-react-native.d.ts +9 -0
- package/dist/esm/index-react-native.js +12 -0
- package/dist/esm/index-react-native.js.map +1 -0
- package/dist/esm/index.d.ts +21 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/interfaces/IEncodingMethod.d.ts +9 -0
- package/dist/esm/interfaces/IEncodingMethod.js +2 -0
- package/dist/esm/interfaces/IEncodingMethod.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/registry.d.ts +26 -0
- package/dist/esm/registry.js +114 -0
- package/dist/esm/registry.js.map +1 -0
- package/dist/esm/test.utils.d.ts +31 -0
- package/dist/esm/test.utils.js +83 -0
- package/dist/esm/test.utils.js.map +1 -0
- package/dist/esm/wrappers/cbor2-deno.d.mts +2 -0
- package/dist/esm/wrappers/cbor2-deno.mjs +5 -0
- package/dist/esm/wrappers/cbor2-deno.mjs.map +1 -0
- package/dist/esm/wrappers/cbor2.d.ts +2 -0
- package/dist/esm/wrappers/cbor2.js +5 -0
- package/dist/esm/wrappers/cbor2.js.map +1 -0
- package/dist/esm/wrappers/cbor2Wrapper.d.ts +5 -0
- package/dist/esm/wrappers/cbor2Wrapper.js +6 -0
- package/dist/esm/wrappers/cbor2Wrapper.js.map +1 -0
- package/dist/esm/xoshiro.d.ts +12 -0
- package/dist/esm/xoshiro.js +47 -0
- package/dist/esm/xoshiro.js.map +1 -0
- package/dist/web/bytewords.js +335 -0
- package/index.html +98 -0
- package/package.json +94 -0
- package/src/classes/FountainDecoder.ts +539 -0
- package/src/classes/FountainEncoder.ts +211 -0
- package/src/classes/RegistryItem.ts +240 -0
- package/src/classes/UR.ts +308 -0
- package/src/classes/UrFountainDecoder.ts +142 -0
- package/src/classes/UrFountainEncoder.ts +103 -0
- package/src/classes/key.helper.ts +85 -0
- package/src/encodingMethods/BytewordEncoding.ts +23 -0
- package/src/encodingMethods/CborEncoding.ts +196 -0
- package/src/encodingMethods/HexEncoding.ts +23 -0
- package/src/encodingMethods/UrEncoding.ts +19 -0
- package/src/encodingMethods/bytewords.ts +215 -0
- package/src/encodingMethods/index.ts +26 -0
- package/src/encodingMethods/pipeline.ts +103 -0
- package/src/enums/EncodingMethodName.ts +10 -0
- package/src/errors.ts +34 -0
- package/src/helpers/aliasSampling.ts +87 -0
- package/src/helpers/crc32.ts +19 -0
- package/src/helpers/fountainUtils.ts +157 -0
- package/src/helpers/sha256.ts +88 -0
- package/src/helpers/type.helper.ts +1 -0
- package/src/helpers/uintArrayHelper.ts +611 -0
- package/src/helpers/utils.ts +135 -0
- package/src/index-react-native.ts +12 -0
- package/src/index.ts +44 -0
- package/src/interfaces/IEncodingMethod.ts +10 -0
- package/src/registry.ts +146 -0
- package/src/test.utils.ts +105 -0
- package/src/wrappers/cbor2-cjs.cts +6 -0
- package/src/wrappers/cbor2-deno.mts +6 -0
- package/src/wrappers/cbor2.ts +7 -0
- package/src/wrappers/cbor2Wrapper.ts +14 -0
- package/src/xoshiro.ts +66 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { isRegistryItem, RegistryItem, RegistryItemBase } from "./RegistryItem.js";
|
|
2
|
+
import { EncodingMethodName } from "../enums/EncodingMethodName.js";
|
|
3
|
+
import { EncodingPipeline } from "../encodingMethods/pipeline.js";
|
|
4
|
+
import {
|
|
5
|
+
InvalidPathLengthError,
|
|
6
|
+
InvalidSchemeError,
|
|
7
|
+
InvalidTypeError,
|
|
8
|
+
} from "../errors.js";
|
|
9
|
+
import { dataPipeline } from "../encodingMethods/index.js";
|
|
10
|
+
import { ReplaceKeyType } from "../helpers/type.helper.js";
|
|
11
|
+
|
|
12
|
+
export interface IUR {
|
|
13
|
+
type: string; // bc-ur type defined in the registry
|
|
14
|
+
payload: string; // encoded data
|
|
15
|
+
seqNum?: number; // sequence number if multipart starting with index 1 - if single part, this is 0
|
|
16
|
+
seqLength?: number; // total number of parts in the multipart message - if single part, this is 0
|
|
17
|
+
isFragment?: boolean; // if the ur is a fragment of a multipart message
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md
|
|
22
|
+
* Class that represents the structure of the data we encode/decode in this package.
|
|
23
|
+
* e.g. 'ur:bytes/lpamcmcfatrdcyzcpldpgwhdhtiaiaecgyktgsflguhshthfghjtjngrhsfegtiafegaktgugui'
|
|
24
|
+
*
|
|
25
|
+
*
|
|
26
|
+
* Single part = ur:<type>/<message(payload)>
|
|
27
|
+
* Multi part = ur:<type>/<seqNum-seqLength>/<fragment(payload)>
|
|
28
|
+
*
|
|
29
|
+
* CBOR encoding should not include tag on top level when UR has a tag
|
|
30
|
+
*
|
|
31
|
+
* I want to be able to create UR from encoding normal js types
|
|
32
|
+
* Or from any type in the pipeline
|
|
33
|
+
*
|
|
34
|
+
* Should i do it on the encoder or ur class itself?
|
|
35
|
+
*/
|
|
36
|
+
export class UR {
|
|
37
|
+
public type: string;
|
|
38
|
+
public payload: string;
|
|
39
|
+
public seqNum?: number;
|
|
40
|
+
public seqLength?: number;
|
|
41
|
+
public isFragment: boolean;
|
|
42
|
+
|
|
43
|
+
static pipeline: EncodingPipeline<any, string> = dataPipeline;
|
|
44
|
+
|
|
45
|
+
// If type is unknown it should be cbor, because default encoding will take any and convert to cbor without tagging
|
|
46
|
+
constructor(input: IUR | RegistryItem) {
|
|
47
|
+
// Create from registry item
|
|
48
|
+
if (input instanceof RegistryItemBase || isRegistryItem(input)) {
|
|
49
|
+
const ur = UR.fromRegistryItem(input as RegistryItem);
|
|
50
|
+
this.type = ur.type;
|
|
51
|
+
this.payload = ur.payload;
|
|
52
|
+
this.seqNum = ur.seqNum;
|
|
53
|
+
this.seqLength = ur.seqLength;
|
|
54
|
+
this.isFragment = ur.isFragment;
|
|
55
|
+
}
|
|
56
|
+
// Create from raw data
|
|
57
|
+
else if (typeof input == "object" && 'type' in input && 'payload' in input) {
|
|
58
|
+
const { type, payload, seqNum = 0, seqLength = 0 } = input;
|
|
59
|
+
this.payload = payload;
|
|
60
|
+
this.type = type;
|
|
61
|
+
this.seqNum = seqNum;
|
|
62
|
+
this.seqLength = seqLength;
|
|
63
|
+
this.isFragment = seqLength > 0;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
throw new InvalidTypeError();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Decode
|
|
71
|
+
decode(until?: EncodingMethodName) {
|
|
72
|
+
return UR.pipeline.decode(this.payload, {until, enforceType: this.isFragment ? undefined : this.type});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Get string representation
|
|
76
|
+
toString() {
|
|
77
|
+
return UR.getUrString(this.type, this.payload, this.seqNum, this.seqLength);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Get payload in bytewords
|
|
81
|
+
getPayloadBytewords() {
|
|
82
|
+
return this.payload;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Get payload in hex
|
|
86
|
+
getPayloadHex() {
|
|
87
|
+
return UR.pipeline.decode<string>(this.payload, { until: EncodingMethodName.hex });
|
|
88
|
+
// TODO: add tag information
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Get Payload in cbor
|
|
92
|
+
getPayloadCbor() {
|
|
93
|
+
return UR.pipeline.decode<Uint8Array>(this.payload, {until: EncodingMethodName.cbor} );
|
|
94
|
+
// TODO: add tag information
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
toRegistryItem() {
|
|
98
|
+
if (this.isFragment) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
"Cannot convert a multipart ur to registry item, it needs to be decoded first"
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
// Enforce type
|
|
104
|
+
// registrtqueryByURType
|
|
105
|
+
return UR.decode(this);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// Static methods
|
|
109
|
+
|
|
110
|
+
static fromRegistryItem(item: RegistryItem) {
|
|
111
|
+
// First convert Registry item to bytewords
|
|
112
|
+
// Only on the top level, we should not include the tag
|
|
113
|
+
const bytewords = UR.pipeline.encode(item, {ignoreTopLevelTag: true});
|
|
114
|
+
|
|
115
|
+
// Now create new UR
|
|
116
|
+
return new UR({
|
|
117
|
+
type: item.type.URType,
|
|
118
|
+
payload: bytewords,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Create UR from native javascript types by encoding them to bytewords
|
|
124
|
+
* @param input
|
|
125
|
+
* @returns
|
|
126
|
+
*/
|
|
127
|
+
static fromData(input: ReplaceKeyType<IUR, 'payload', any>) {
|
|
128
|
+
const bytewords = UR.pipeline.encode(input.payload);
|
|
129
|
+
|
|
130
|
+
// Now create new UR
|
|
131
|
+
return new UR({
|
|
132
|
+
...input,
|
|
133
|
+
payload: bytewords,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static fromCbor(input: ReplaceKeyType<IUR, 'payload', Uint8Array>) {
|
|
138
|
+
// This means we already have cbor Uint8Array
|
|
139
|
+
// So we will start from the next method
|
|
140
|
+
const bytewords = UR.pipeline.encode(input.payload, { from: EncodingMethodName.hex });
|
|
141
|
+
|
|
142
|
+
return new UR({
|
|
143
|
+
...input,
|
|
144
|
+
payload: bytewords,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static fromHex(input: ReplaceKeyType<IUR, 'payload', string>) {
|
|
149
|
+
// This means we already have hex string
|
|
150
|
+
// So we will start from the next method
|
|
151
|
+
const bytewords = UR.pipeline.encode(input.payload, { from: EncodingMethodName.bytewords });
|
|
152
|
+
|
|
153
|
+
return new UR({
|
|
154
|
+
...input,
|
|
155
|
+
payload: bytewords,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static fromBytewords(input: IUR) {
|
|
160
|
+
return new UR({
|
|
161
|
+
...input,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static from(input: ReplaceKeyType<IUR, 'payload', any>, type: EncodingMethodName) {
|
|
166
|
+
switch (type) {
|
|
167
|
+
case EncodingMethodName.bytewords:
|
|
168
|
+
return UR.fromBytewords(input);
|
|
169
|
+
case EncodingMethodName.cbor:
|
|
170
|
+
return UR.fromCbor(input);
|
|
171
|
+
case EncodingMethodName.hex:
|
|
172
|
+
return UR.fromHex(input);
|
|
173
|
+
case EncodingMethodName.ur:
|
|
174
|
+
return UR.fromData(input);
|
|
175
|
+
default:
|
|
176
|
+
throw new Error("Invalid encoding method");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
static fromString(ur: string) {
|
|
181
|
+
return new UR(UR.parseUr(ur));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
static encode = this.fromRegistryItem;
|
|
185
|
+
static decode(ur: UR): RegistryItem {
|
|
186
|
+
// Force cbor type
|
|
187
|
+
return UR.pipeline.decode(ur.payload);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Check if the given string is a valid UR
|
|
192
|
+
* For single part ur, it should be in the form of "ur:<type>/<payload>" which is "ur:<lowercase letters, numbers or dashes>/<bytewords>"
|
|
193
|
+
* For multi part ur, it should be in the form of "ur:<type>/<seqNum-seqLength>/<fragment>" which is "ur:<lowercase letters, numbers or dashes>/<number-number>/<bytewords>"
|
|
194
|
+
* ur uses minimal bytewords encoding style which is a-z and has checksome bytes at the end
|
|
195
|
+
*
|
|
196
|
+
* @param input
|
|
197
|
+
* @returns
|
|
198
|
+
*/
|
|
199
|
+
static validate(input: string): boolean {
|
|
200
|
+
// TODO: use bytewords encoding to validate the payload
|
|
201
|
+
|
|
202
|
+
const singlePartPattern = /^ur:[a-z0-9-]+\/[a-z]+$/;
|
|
203
|
+
const multiPartPattern = /^ur:[a-z0-9-]+\/[0-9]+-[0-9]+\/[a-z]+$/;
|
|
204
|
+
|
|
205
|
+
return singlePartPattern.test(input) || multiPartPattern.test(input);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Generates a UR string from the given type and payload.
|
|
210
|
+
* Single part = ur:<type>/<message(payload)> if seqNum and seqLength are 0
|
|
211
|
+
* Multi part = ur:<type>/<seqNum-seqLength>/<fragment(payload)>
|
|
212
|
+
*/
|
|
213
|
+
static getUrString(
|
|
214
|
+
type: string,
|
|
215
|
+
payload: string,
|
|
216
|
+
seqNum = 0,
|
|
217
|
+
seqLen = 0
|
|
218
|
+
): string {
|
|
219
|
+
// Single UR
|
|
220
|
+
if (seqNum === 0 && seqLen === 0) {
|
|
221
|
+
return joinUri("ur", [type, payload]);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Multi part UR
|
|
225
|
+
const seq = `${seqNum}-${seqLen}`;
|
|
226
|
+
return joinUri("ur", [type, seq, payload]);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Parses a UR and performs basic validation
|
|
231
|
+
* @param message e.g. "UR:BYTES/6-23/LPAMCHCFATTTCYCLEHGSDPHDHGEHFGHKKKDL..."
|
|
232
|
+
*/
|
|
233
|
+
static parseUr(message: string): IUR {
|
|
234
|
+
const lowercase = message.toLowerCase(); // e.g. "ur:bytes/6-23/lpamchcfatttcyclehgsdphdhgehfghkkkdl..."
|
|
235
|
+
|
|
236
|
+
// check if it is valid ur string
|
|
237
|
+
if (!UR.validate(lowercase)) {
|
|
238
|
+
throw new Error("Invalid UR string");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const components = lowercase.slice(3).split("/");
|
|
242
|
+
let isFragment = false;
|
|
243
|
+
let seqNum = 0;
|
|
244
|
+
let seqLength = 0;
|
|
245
|
+
let payload = "";
|
|
246
|
+
|
|
247
|
+
// Check for the number of components
|
|
248
|
+
switch (components.length) {
|
|
249
|
+
case 2:
|
|
250
|
+
// single part ur
|
|
251
|
+
isFragment = false;
|
|
252
|
+
break;
|
|
253
|
+
case 3:
|
|
254
|
+
// multi part ur
|
|
255
|
+
isFragment = true;
|
|
256
|
+
break;
|
|
257
|
+
default:
|
|
258
|
+
throw new InvalidPathLengthError();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const type = components[0]; //e.g. "bytes"
|
|
262
|
+
if (isFragment) {
|
|
263
|
+
const seq = components[1]; //e.g. "6-23"
|
|
264
|
+
const [num, length] = seq.split("-").map(Number);
|
|
265
|
+
seqNum = num;
|
|
266
|
+
seqLength = length;
|
|
267
|
+
payload = components[2];
|
|
268
|
+
} else {
|
|
269
|
+
payload = components[1];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
type,
|
|
274
|
+
payload,
|
|
275
|
+
seqNum,
|
|
276
|
+
seqLength,
|
|
277
|
+
isFragment,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/// Helper functions
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Generates a uri. e.g. 'ur:bytes/6-22/lpamcmcfatrdcyzcpldpgwhdhtiaiaecgyktgsflguhshthfghjtjngrhsfegtiafegaktgugui'
|
|
286
|
+
* @param scheme scheme of the uri. e.g. "ur"
|
|
287
|
+
* @param pathComponents adds additional information to the uri in the form of a path (divided by "/"). e.g. "bytes/6-22/lpamcmcfatrdcyzcpldpgwhdhtiaiaecgyktgsflguhshthfghjtjngrhsfegtiafegaktgugui"
|
|
288
|
+
* @returns the complete uri.
|
|
289
|
+
*/
|
|
290
|
+
function joinUri(scheme: string, pathComponents: string[]): string {
|
|
291
|
+
const path = pathComponents.join("/");
|
|
292
|
+
return [scheme, path].join(":");
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* [seqNum, fragments.length, totalPayloadLength, checksum, fragment]
|
|
299
|
+
*
|
|
300
|
+
* part = [
|
|
301
|
+
* uint32 seqNum,
|
|
302
|
+
* uint seqLen,
|
|
303
|
+
* uint messageLen,
|
|
304
|
+
* uint32 checksum,
|
|
305
|
+
* bytes data
|
|
306
|
+
* ]
|
|
307
|
+
*/
|
|
308
|
+
export type IMultipartUrPayload = [number, number, number, number, Uint8Array];
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { RegistryItem } from "../classes/RegistryItem.js";
|
|
2
|
+
import { EncodingMethodName } from "../enums/EncodingMethodName.js";
|
|
3
|
+
import { FountainDecoder, MultipartPayload, validateDecodedMultipart } from "./FountainDecoder.js";
|
|
4
|
+
import { UR } from "./UR.js";
|
|
5
|
+
|
|
6
|
+
export class UrFountainDecoder extends FountainDecoder {
|
|
7
|
+
public expectedType: string;
|
|
8
|
+
public resultUr: UR;
|
|
9
|
+
public decodedData: RegistryItem | any;
|
|
10
|
+
|
|
11
|
+
constructor(parts: UR[] | string[] = []) {
|
|
12
|
+
super();
|
|
13
|
+
parts.forEach((part) => {
|
|
14
|
+
this.receivePartUr(part);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public reset(): void {
|
|
19
|
+
super.reset();
|
|
20
|
+
this.resultUr = undefined;
|
|
21
|
+
this.expectedType = undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setExpectedValuesUr(part: UR, decodedPart: MultipartPayload): void {
|
|
25
|
+
this.expectedType = part.type;
|
|
26
|
+
this.expectedPartCount = part.seqLength;
|
|
27
|
+
super.setExpectedValues(decodedPart);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
protected validateUr(part: UR, decodedPart: MultipartPayload): boolean {
|
|
31
|
+
// Check if UR is a fragment
|
|
32
|
+
if (!part.isFragment) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Check the type of the UR
|
|
37
|
+
if (part.type !== this.expectedType) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Expect metadata ur seqNum to be equal to the decoded part seqNum
|
|
42
|
+
if (part.seqNum !== decodedPart.seqNum) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Expect metadata ur seqLength to be equal to the decoded part seqLength
|
|
47
|
+
if (part.seqLength !== decodedPart.seqLength) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Validate decoded paylad
|
|
52
|
+
return super.validatePart(decodedPart);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
receivePartUr(part: UR | string): boolean {
|
|
56
|
+
// If we already have a result, we're done
|
|
57
|
+
if (this.done) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Convert string into UR
|
|
62
|
+
if (typeof part === "string") {
|
|
63
|
+
part = UR.fromString(part);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// If what we received is not a multupart UR, then we're done
|
|
67
|
+
if (!part.isFragment) {
|
|
68
|
+
// If this is not a fragment and we have not received any fragments yet then its the whole UR
|
|
69
|
+
if (!this.started) {
|
|
70
|
+
this.resultUr = part;
|
|
71
|
+
this.started = true;
|
|
72
|
+
this.done = true;
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
this.decodedData = this.resultUr.decode();
|
|
76
|
+
} catch (error) {
|
|
77
|
+
this.error = error;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Finish here
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
// If we have received fragments before then this is an error
|
|
84
|
+
else {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let parsed: MultipartPayload;
|
|
90
|
+
try {
|
|
91
|
+
const decoded = part.decode();
|
|
92
|
+
parsed = validateDecodedMultipart(decoded);
|
|
93
|
+
} catch (e) {
|
|
94
|
+
console.error(e);
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// If this is the first part we've seen then set expected values
|
|
99
|
+
if (!this.started) this.setExpectedValuesUr(part, parsed);
|
|
100
|
+
|
|
101
|
+
// If this is a fragment validate UR
|
|
102
|
+
if (!this.validateUr(part, parsed)) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return super.receivePart(parsed);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Assemble data and generate single result UR
|
|
110
|
+
public finalize(): void {
|
|
111
|
+
super.finalize();
|
|
112
|
+
|
|
113
|
+
if (this.error) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (this.resultRaw !== undefined) {
|
|
118
|
+
// Result data is already in CBOR
|
|
119
|
+
// Just convert it to bytewords instead of encoding it again
|
|
120
|
+
const payload = UR.pipeline.encode(this.resultRaw, { from: EncodingMethodName.hex });
|
|
121
|
+
this.resultUr = new UR({
|
|
122
|
+
type: this.expectedType,
|
|
123
|
+
payload: payload,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Now Try to decode the result UR
|
|
127
|
+
try {
|
|
128
|
+
this.decodedData = this.resultUr.decode();
|
|
129
|
+
} catch (error) {
|
|
130
|
+
this.error = error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
getDecodedData(): RegistryItem | any {
|
|
136
|
+
if (!this.isSuccessful()) {
|
|
137
|
+
console.log("Fountain decoding was not successful");
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
return this.decodedData;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { isRegistryItem, RegistryItem, RegistryItemBase } from "../classes/RegistryItem.js";
|
|
2
|
+
import { UR } from "./UR.js";
|
|
3
|
+
import { FountainEncoder } from "./FountainEncoder.js";
|
|
4
|
+
import { EncodingMethodName } from "../enums/EncodingMethodName.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* UrFountainEncoder encodes data on the fly using an internal state to keep generating UR fragments of the payload.
|
|
8
|
+
* It extends the FountainEncoder class to provide additional functionality specific to UR encoding.
|
|
9
|
+
*/
|
|
10
|
+
export class UrFountainEncoder extends FountainEncoder {
|
|
11
|
+
/** The UR type of the input data */
|
|
12
|
+
private _type: string;
|
|
13
|
+
/** The original input data as a UR object */
|
|
14
|
+
private _inputUr: UR;
|
|
15
|
+
/** Reset counter to 1 after hitting `fragmentCount * ratio`; if undefined or 0, it goes forever */
|
|
16
|
+
public repeatAfterRatio = 2;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates an instance of UrFountainEncoder.
|
|
20
|
+
* @param input - The input data to be encoded, either as a RegistryItem or UR.
|
|
21
|
+
* @param maxFragmentLength - The maximum length of each fragment.
|
|
22
|
+
* @param minFragmentLength - The minimum length of each fragment.
|
|
23
|
+
* @param firstSeqNum - The sequence number to start with.
|
|
24
|
+
* @param repeatAfterRatio - The ratio after which the sequence number resets. Default is 2. If 0 fountain goes forever.
|
|
25
|
+
*/
|
|
26
|
+
constructor(
|
|
27
|
+
input: RegistryItem | UR,
|
|
28
|
+
maxFragmentLength: number = 100,
|
|
29
|
+
minFragmentLength: number = 10,
|
|
30
|
+
firstSeqNum: number = 0,
|
|
31
|
+
repeatAfterRatio = 2
|
|
32
|
+
) {
|
|
33
|
+
|
|
34
|
+
let inputUr;
|
|
35
|
+
// If the input is a RegistryItem, convert it to a Ur
|
|
36
|
+
if (input instanceof RegistryItemBase || isRegistryItem(input)) {
|
|
37
|
+
inputUr = UR.fromRegistryItem(input);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
inputUr = input;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Input in CBOR
|
|
44
|
+
let inputCBOR = inputUr.getPayloadCbor();
|
|
45
|
+
|
|
46
|
+
super(inputCBOR, maxFragmentLength, minFragmentLength, firstSeqNum);
|
|
47
|
+
|
|
48
|
+
this._inputUr = inputUr;
|
|
49
|
+
this._type = inputUr.type;
|
|
50
|
+
this.repeatAfterRatio = repeatAfterRatio;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Return all the fragments based on the fountain ratio at once as an array of Uint8Arrays.
|
|
56
|
+
* @param fountainRatio - The ratio of the fountain fragments to the pure fragments. Default is 0.
|
|
57
|
+
* @returns An array of UR objects representing the fragments.
|
|
58
|
+
*/
|
|
59
|
+
getAllPartsUr(fountainRatio: number = 0): UR[] {
|
|
60
|
+
const allParts = super.getAllParts(fountainRatio);
|
|
61
|
+
return allParts.map((part, index) => this.fragment2Ur(index+1, part));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Give the 'next' fragment for the ur for which the fountainEncoder was created.
|
|
66
|
+
* @returns The 'next' fragment, represented as a Ur multipart string.
|
|
67
|
+
*/
|
|
68
|
+
public nextPartUr(): UR {
|
|
69
|
+
// Reset the sequence number if we hit the ratio
|
|
70
|
+
if (this.repeatAfterRatio) {
|
|
71
|
+
if (this._seqNum > this._pureFragments.length * this.repeatAfterRatio) {
|
|
72
|
+
this._seqNum = 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const encodedFragment = super.nextPart();
|
|
76
|
+
return this.fragment2Ur(this._seqNum, encodedFragment);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Converts a fragment to a UR object.
|
|
81
|
+
* @param seqNum - The sequence number of the fragment.
|
|
82
|
+
* @param fragment - The fragment data as a Uint8Array.
|
|
83
|
+
* @returns A UR object representing the fragment.
|
|
84
|
+
*/
|
|
85
|
+
private fragment2Ur(seqNum:number, fragment:Uint8Array) {
|
|
86
|
+
// Fragment is already encoded in CBOR
|
|
87
|
+
// Just convert it to bytewords instead of encoding it again
|
|
88
|
+
const payload = UR.pipeline.encode(fragment, {from: EncodingMethodName.hex});
|
|
89
|
+
if (this.isSinglePart()) {
|
|
90
|
+
return new UR({
|
|
91
|
+
type: this._type,
|
|
92
|
+
payload: payload,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return new UR({
|
|
96
|
+
type: this._type,
|
|
97
|
+
payload: payload,
|
|
98
|
+
seqNum: seqNum,
|
|
99
|
+
seqLength: this._pureFragments.length,
|
|
100
|
+
isFragment: true,
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file contains helper functions for encoding and decoding keys
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Interface for the key to integer mapping
|
|
7
|
+
*/
|
|
8
|
+
export type IKeyMap = Record<string, string | number>;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* For some CDDL types we use integer as keys to keep the CBOR encoded data small
|
|
12
|
+
* This function converts the data keys to their respective integer values
|
|
13
|
+
*
|
|
14
|
+
* It needs to return MAP because cbor library only then encodes the keys as integers
|
|
15
|
+
*
|
|
16
|
+
* @param data Object that has key value pairs
|
|
17
|
+
* @param keyMap Map of the keys to integers values
|
|
18
|
+
* @returns Map with integer keys
|
|
19
|
+
*/
|
|
20
|
+
export function encodeKeys(
|
|
21
|
+
data: object,
|
|
22
|
+
keyMap: IKeyMap,
|
|
23
|
+
allowKeysNotInMap: boolean
|
|
24
|
+
): Map<string | number, any> {
|
|
25
|
+
const map = new Map();
|
|
26
|
+
// If we have a mapping, use it to map the data
|
|
27
|
+
// Check if our data is an object
|
|
28
|
+
if (typeof data !== "object") return undefined;
|
|
29
|
+
|
|
30
|
+
// Create a set from the keys of the data
|
|
31
|
+
const keys = new Set(Object.keys(data));
|
|
32
|
+
|
|
33
|
+
// Add the keys in the correct order to the map
|
|
34
|
+
for (const key in keyMap) {
|
|
35
|
+
// Check if the key exists in the data
|
|
36
|
+
if(data[key] !== undefined) map.set(keyMap[key], data[key]);
|
|
37
|
+
keys.delete(key);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (allowKeysNotInMap) {
|
|
41
|
+
// Add other keys as string if they are not existent in the map
|
|
42
|
+
keys.forEach((key) => {
|
|
43
|
+
map.set(key, data[key]);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return map;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* For some CDDL types we use integer as keys to keep the CBOR encoded data small
|
|
52
|
+
* This function converts the data keys back to their respective string values
|
|
53
|
+
*
|
|
54
|
+
* @param _data Object that has encoded key - value pairs
|
|
55
|
+
* @param keyMap Map of the keys to integer values
|
|
56
|
+
* @returns Object with string keys
|
|
57
|
+
*/
|
|
58
|
+
export function decodeKeys(
|
|
59
|
+
data: Map<string | number, any> | Record<string | number, any>,
|
|
60
|
+
keyMap: IKeyMap,
|
|
61
|
+
allowKeysNotInMap: boolean
|
|
62
|
+
): object {
|
|
63
|
+
// If we have a mapping, use it to map the data
|
|
64
|
+
const result = {};
|
|
65
|
+
// Convert the data to a map if it is not already
|
|
66
|
+
const _data = data instanceof Map ? data : new Map(Object.entries(data));
|
|
67
|
+
|
|
68
|
+
// Get all the keys in the data
|
|
69
|
+
const keys = new Set(_data.keys());
|
|
70
|
+
|
|
71
|
+
// Add the keys in the correct order
|
|
72
|
+
for (const key in keyMap) {
|
|
73
|
+
if (_data.has(keyMap[key])) result[key] = _data.get(keyMap[key]);
|
|
74
|
+
keys.delete(keyMap[key]);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (allowKeysNotInMap) {
|
|
78
|
+
// Add other keys as string if they are not existent in the map
|
|
79
|
+
keys.forEach((key) => {
|
|
80
|
+
result[key] = _data.get(key);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { STYLES, decode, encode } from "./bytewords.js";
|
|
2
|
+
import { EncodingMethodName } from "../enums/EncodingMethodName.js";
|
|
3
|
+
import { IEncodingMethod } from "../interfaces/IEncodingMethod.js";
|
|
4
|
+
|
|
5
|
+
export class BytewordEncoding implements IEncodingMethod<string, string> {
|
|
6
|
+
private _name: EncodingMethodName = EncodingMethodName.bytewords;
|
|
7
|
+
|
|
8
|
+
readonly _style: STYLES;
|
|
9
|
+
|
|
10
|
+
get name(): EncodingMethodName {
|
|
11
|
+
return this._name;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
constructor(style: STYLES = STYLES.MINIMAL) {
|
|
15
|
+
this._style = style;
|
|
16
|
+
}
|
|
17
|
+
encode(payload: string): string {
|
|
18
|
+
return encode(payload, this._style);
|
|
19
|
+
}
|
|
20
|
+
decode(payload: string): string {
|
|
21
|
+
return decode(payload, this._style);
|
|
22
|
+
}
|
|
23
|
+
}
|