@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.
Files changed (229) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +996 -0
  3. package/dist/commonjs/classes/FountainDecoder.d.ts +125 -0
  4. package/dist/commonjs/classes/FountainDecoder.js +453 -0
  5. package/dist/commonjs/classes/FountainDecoder.js.map +1 -0
  6. package/dist/commonjs/classes/FountainEncoder.d.ts +63 -0
  7. package/dist/commonjs/classes/FountainEncoder.js +168 -0
  8. package/dist/commonjs/classes/FountainEncoder.js.map +1 -0
  9. package/dist/commonjs/classes/RegistryItem.d.ts +104 -0
  10. package/dist/commonjs/classes/RegistryItem.js +172 -0
  11. package/dist/commonjs/classes/RegistryItem.js.map +1 -0
  12. package/dist/commonjs/classes/UR.d.ts +89 -0
  13. package/dist/commonjs/classes/UR.js +243 -0
  14. package/dist/commonjs/classes/UR.js.map +1 -0
  15. package/dist/commonjs/classes/UrFountainDecoder.d.ts +15 -0
  16. package/dist/commonjs/classes/UrFountainDecoder.js +127 -0
  17. package/dist/commonjs/classes/UrFountainDecoder.js.map +1 -0
  18. package/dist/commonjs/classes/UrFountainEncoder.d.ts +42 -0
  19. package/dist/commonjs/classes/UrFountainEncoder.js +92 -0
  20. package/dist/commonjs/classes/UrFountainEncoder.js.map +1 -0
  21. package/dist/commonjs/classes/key.helper.d.ts +27 -0
  22. package/dist/commonjs/classes/key.helper.js +70 -0
  23. package/dist/commonjs/classes/key.helper.js.map +1 -0
  24. package/dist/commonjs/encodingMethods/BytewordEncoding.d.ts +11 -0
  25. package/dist/commonjs/encodingMethods/BytewordEncoding.js +23 -0
  26. package/dist/commonjs/encodingMethods/BytewordEncoding.js.map +1 -0
  27. package/dist/commonjs/encodingMethods/CborEncoding.d.ts +44 -0
  28. package/dist/commonjs/encodingMethods/CborEncoding.js +151 -0
  29. package/dist/commonjs/encodingMethods/CborEncoding.js.map +1 -0
  30. package/dist/commonjs/encodingMethods/HexEncoding.d.ts +8 -0
  31. package/dist/commonjs/encodingMethods/HexEncoding.js +24 -0
  32. package/dist/commonjs/encodingMethods/HexEncoding.js.map +1 -0
  33. package/dist/commonjs/encodingMethods/UrEncoding.d.ts +10 -0
  34. package/dist/commonjs/encodingMethods/UrEncoding.js +19 -0
  35. package/dist/commonjs/encodingMethods/UrEncoding.js.map +1 -0
  36. package/dist/commonjs/encodingMethods/bytewords.d.ts +27 -0
  37. package/dist/commonjs/encodingMethods/bytewords.js +152 -0
  38. package/dist/commonjs/encodingMethods/bytewords.js.map +1 -0
  39. package/dist/commonjs/encodingMethods/index.d.ts +19 -0
  40. package/dist/commonjs/encodingMethods/index.js +27 -0
  41. package/dist/commonjs/encodingMethods/index.js.map +1 -0
  42. package/dist/commonjs/encodingMethods/pipeline.d.ts +19 -0
  43. package/dist/commonjs/encodingMethods/pipeline.js +80 -0
  44. package/dist/commonjs/encodingMethods/pipeline.js.map +1 -0
  45. package/dist/commonjs/enums/EncodingMethodName.d.ts +10 -0
  46. package/dist/commonjs/enums/EncodingMethodName.js +15 -0
  47. package/dist/commonjs/enums/EncodingMethodName.js.map +1 -0
  48. package/dist/commonjs/errors.d.ts +15 -0
  49. package/dist/commonjs/errors.js +39 -0
  50. package/dist/commonjs/errors.js.map +1 -0
  51. package/dist/commonjs/helpers/aliasSampling.d.ts +6 -0
  52. package/dist/commonjs/helpers/aliasSampling.js +73 -0
  53. package/dist/commonjs/helpers/aliasSampling.js.map +1 -0
  54. package/dist/commonjs/helpers/crc32.d.ts +1 -0
  55. package/dist/commonjs/helpers/crc32.js +19 -0
  56. package/dist/commonjs/helpers/crc32.js.map +1 -0
  57. package/dist/commonjs/helpers/fountainUtils.d.ts +40 -0
  58. package/dist/commonjs/helpers/fountainUtils.js +124 -0
  59. package/dist/commonjs/helpers/fountainUtils.js.map +1 -0
  60. package/dist/commonjs/helpers/sha256.d.ts +1 -0
  61. package/dist/commonjs/helpers/sha256.js +78 -0
  62. package/dist/commonjs/helpers/sha256.js.map +1 -0
  63. package/dist/commonjs/helpers/type.helper.d.ts +3 -0
  64. package/dist/commonjs/helpers/type.helper.js +3 -0
  65. package/dist/commonjs/helpers/type.helper.js.map +1 -0
  66. package/dist/commonjs/helpers/uintArrayHelper.d.ts +287 -0
  67. package/dist/commonjs/helpers/uintArrayHelper.js +545 -0
  68. package/dist/commonjs/helpers/uintArrayHelper.js.map +1 -0
  69. package/dist/commonjs/helpers/utils.d.ts +55 -0
  70. package/dist/commonjs/helpers/utils.js +123 -0
  71. package/dist/commonjs/helpers/utils.js.map +1 -0
  72. package/dist/commonjs/index-react-native.d.ts +9 -0
  73. package/dist/commonjs/index-react-native.js +15 -0
  74. package/dist/commonjs/index-react-native.js.map +1 -0
  75. package/dist/commonjs/index.d.ts +21 -0
  76. package/dist/commonjs/index.js +34 -0
  77. package/dist/commonjs/index.js.map +1 -0
  78. package/dist/commonjs/interfaces/IEncodingMethod.d.ts +9 -0
  79. package/dist/commonjs/interfaces/IEncodingMethod.js +3 -0
  80. package/dist/commonjs/interfaces/IEncodingMethod.js.map +1 -0
  81. package/dist/commonjs/package.json +3 -0
  82. package/dist/commonjs/registry.d.ts +26 -0
  83. package/dist/commonjs/registry.js +118 -0
  84. package/dist/commonjs/registry.js.map +1 -0
  85. package/dist/commonjs/test.utils.d.ts +31 -0
  86. package/dist/commonjs/test.utils.js +88 -0
  87. package/dist/commonjs/test.utils.js.map +1 -0
  88. package/dist/commonjs/wrappers/cbor2-cjs.cjs.map +1 -0
  89. package/dist/commonjs/wrappers/cbor2.d.ts +2 -0
  90. package/dist/commonjs/wrappers/cbor2.js +14 -0
  91. package/dist/commonjs/wrappers/cbor2Wrapper.d.ts +14 -0
  92. package/dist/commonjs/wrappers/cbor2Wrapper.js +49 -0
  93. package/dist/commonjs/wrappers/cbor2Wrapper.js.map +1 -0
  94. package/dist/commonjs/xoshiro.d.ts +12 -0
  95. package/dist/commonjs/xoshiro.js +52 -0
  96. package/dist/commonjs/xoshiro.js.map +1 -0
  97. package/dist/esm/classes/FountainDecoder.d.ts +125 -0
  98. package/dist/esm/classes/FountainDecoder.js +447 -0
  99. package/dist/esm/classes/FountainDecoder.js.map +1 -0
  100. package/dist/esm/classes/FountainEncoder.d.ts +63 -0
  101. package/dist/esm/classes/FountainEncoder.js +164 -0
  102. package/dist/esm/classes/FountainEncoder.js.map +1 -0
  103. package/dist/esm/classes/RegistryItem.d.ts +104 -0
  104. package/dist/esm/classes/RegistryItem.js +166 -0
  105. package/dist/esm/classes/RegistryItem.js.map +1 -0
  106. package/dist/esm/classes/UR.d.ts +89 -0
  107. package/dist/esm/classes/UR.js +239 -0
  108. package/dist/esm/classes/UR.js.map +1 -0
  109. package/dist/esm/classes/UrFountainDecoder.d.ts +15 -0
  110. package/dist/esm/classes/UrFountainDecoder.js +123 -0
  111. package/dist/esm/classes/UrFountainDecoder.js.map +1 -0
  112. package/dist/esm/classes/UrFountainEncoder.d.ts +42 -0
  113. package/dist/esm/classes/UrFountainEncoder.js +88 -0
  114. package/dist/esm/classes/UrFountainEncoder.js.map +1 -0
  115. package/dist/esm/classes/key.helper.d.ts +27 -0
  116. package/dist/esm/classes/key.helper.js +66 -0
  117. package/dist/esm/classes/key.helper.js.map +1 -0
  118. package/dist/esm/encodingMethods/BytewordEncoding.d.ts +11 -0
  119. package/dist/esm/encodingMethods/BytewordEncoding.js +19 -0
  120. package/dist/esm/encodingMethods/BytewordEncoding.js.map +1 -0
  121. package/dist/esm/encodingMethods/CborEncoding.d.ts +44 -0
  122. package/dist/esm/encodingMethods/CborEncoding.js +147 -0
  123. package/dist/esm/encodingMethods/CborEncoding.js.map +1 -0
  124. package/dist/esm/encodingMethods/HexEncoding.d.ts +8 -0
  125. package/dist/esm/encodingMethods/HexEncoding.js +20 -0
  126. package/dist/esm/encodingMethods/HexEncoding.js.map +1 -0
  127. package/dist/esm/encodingMethods/UrEncoding.d.ts +10 -0
  128. package/dist/esm/encodingMethods/UrEncoding.js +15 -0
  129. package/dist/esm/encodingMethods/UrEncoding.js.map +1 -0
  130. package/dist/esm/encodingMethods/bytewords.d.ts +27 -0
  131. package/dist/esm/encodingMethods/bytewords.js +147 -0
  132. package/dist/esm/encodingMethods/bytewords.js.map +1 -0
  133. package/dist/esm/encodingMethods/index.d.ts +19 -0
  134. package/dist/esm/encodingMethods/index.js +24 -0
  135. package/dist/esm/encodingMethods/index.js.map +1 -0
  136. package/dist/esm/encodingMethods/pipeline.d.ts +19 -0
  137. package/dist/esm/encodingMethods/pipeline.js +76 -0
  138. package/dist/esm/encodingMethods/pipeline.js.map +1 -0
  139. package/dist/esm/enums/EncodingMethodName.d.ts +10 -0
  140. package/dist/esm/enums/EncodingMethodName.js +12 -0
  141. package/dist/esm/enums/EncodingMethodName.js.map +1 -0
  142. package/dist/esm/errors.d.ts +15 -0
  143. package/dist/esm/errors.js +31 -0
  144. package/dist/esm/errors.js.map +1 -0
  145. package/dist/esm/helpers/aliasSampling.d.ts +6 -0
  146. package/dist/esm/helpers/aliasSampling.js +70 -0
  147. package/dist/esm/helpers/aliasSampling.js.map +1 -0
  148. package/dist/esm/helpers/crc32.d.ts +1 -0
  149. package/dist/esm/helpers/crc32.js +16 -0
  150. package/dist/esm/helpers/crc32.js.map +1 -0
  151. package/dist/esm/helpers/fountainUtils.d.ts +40 -0
  152. package/dist/esm/helpers/fountainUtils.js +114 -0
  153. package/dist/esm/helpers/fountainUtils.js.map +1 -0
  154. package/dist/esm/helpers/sha256.d.ts +1 -0
  155. package/dist/esm/helpers/sha256.js +75 -0
  156. package/dist/esm/helpers/sha256.js.map +1 -0
  157. package/dist/esm/helpers/type.helper.d.ts +3 -0
  158. package/dist/esm/helpers/type.helper.js +2 -0
  159. package/dist/esm/helpers/type.helper.js.map +1 -0
  160. package/dist/esm/helpers/uintArrayHelper.d.ts +287 -0
  161. package/dist/esm/helpers/uintArrayHelper.js +526 -0
  162. package/dist/esm/helpers/uintArrayHelper.js.map +1 -0
  163. package/dist/esm/helpers/utils.d.ts +55 -0
  164. package/dist/esm/helpers/utils.js +102 -0
  165. package/dist/esm/helpers/utils.js.map +1 -0
  166. package/dist/esm/index-react-native.d.ts +9 -0
  167. package/dist/esm/index-react-native.js +12 -0
  168. package/dist/esm/index-react-native.js.map +1 -0
  169. package/dist/esm/index.d.ts +21 -0
  170. package/dist/esm/index.js +16 -0
  171. package/dist/esm/index.js.map +1 -0
  172. package/dist/esm/interfaces/IEncodingMethod.d.ts +9 -0
  173. package/dist/esm/interfaces/IEncodingMethod.js +2 -0
  174. package/dist/esm/interfaces/IEncodingMethod.js.map +1 -0
  175. package/dist/esm/package.json +3 -0
  176. package/dist/esm/registry.d.ts +26 -0
  177. package/dist/esm/registry.js +114 -0
  178. package/dist/esm/registry.js.map +1 -0
  179. package/dist/esm/test.utils.d.ts +31 -0
  180. package/dist/esm/test.utils.js +83 -0
  181. package/dist/esm/test.utils.js.map +1 -0
  182. package/dist/esm/wrappers/cbor2-deno.d.mts +2 -0
  183. package/dist/esm/wrappers/cbor2-deno.mjs +5 -0
  184. package/dist/esm/wrappers/cbor2-deno.mjs.map +1 -0
  185. package/dist/esm/wrappers/cbor2.d.ts +2 -0
  186. package/dist/esm/wrappers/cbor2.js +5 -0
  187. package/dist/esm/wrappers/cbor2.js.map +1 -0
  188. package/dist/esm/wrappers/cbor2Wrapper.d.ts +5 -0
  189. package/dist/esm/wrappers/cbor2Wrapper.js +6 -0
  190. package/dist/esm/wrappers/cbor2Wrapper.js.map +1 -0
  191. package/dist/esm/xoshiro.d.ts +12 -0
  192. package/dist/esm/xoshiro.js +47 -0
  193. package/dist/esm/xoshiro.js.map +1 -0
  194. package/dist/web/bytewords.js +335 -0
  195. package/index.html +98 -0
  196. package/package.json +94 -0
  197. package/src/classes/FountainDecoder.ts +539 -0
  198. package/src/classes/FountainEncoder.ts +211 -0
  199. package/src/classes/RegistryItem.ts +240 -0
  200. package/src/classes/UR.ts +308 -0
  201. package/src/classes/UrFountainDecoder.ts +142 -0
  202. package/src/classes/UrFountainEncoder.ts +103 -0
  203. package/src/classes/key.helper.ts +85 -0
  204. package/src/encodingMethods/BytewordEncoding.ts +23 -0
  205. package/src/encodingMethods/CborEncoding.ts +196 -0
  206. package/src/encodingMethods/HexEncoding.ts +23 -0
  207. package/src/encodingMethods/UrEncoding.ts +19 -0
  208. package/src/encodingMethods/bytewords.ts +215 -0
  209. package/src/encodingMethods/index.ts +26 -0
  210. package/src/encodingMethods/pipeline.ts +103 -0
  211. package/src/enums/EncodingMethodName.ts +10 -0
  212. package/src/errors.ts +34 -0
  213. package/src/helpers/aliasSampling.ts +87 -0
  214. package/src/helpers/crc32.ts +19 -0
  215. package/src/helpers/fountainUtils.ts +157 -0
  216. package/src/helpers/sha256.ts +88 -0
  217. package/src/helpers/type.helper.ts +1 -0
  218. package/src/helpers/uintArrayHelper.ts +611 -0
  219. package/src/helpers/utils.ts +135 -0
  220. package/src/index-react-native.ts +12 -0
  221. package/src/index.ts +44 -0
  222. package/src/interfaces/IEncodingMethod.ts +10 -0
  223. package/src/registry.ts +146 -0
  224. package/src/test.utils.ts +105 -0
  225. package/src/wrappers/cbor2-cjs.cts +6 -0
  226. package/src/wrappers/cbor2-deno.mts +6 -0
  227. package/src/wrappers/cbor2.ts +7 -0
  228. package/src/wrappers/cbor2Wrapper.ts +14 -0
  229. package/src/xoshiro.ts +66 -0
@@ -0,0 +1,196 @@
1
+ import { URRegistryClass, UrRegistry } from "../registry.js";
2
+ import { RegistryItem, RegistryItemClass, registryItemFactory } from "../classes/RegistryItem.js";
3
+ import { EncodingMethodName } from "../enums/EncodingMethodName.js";
4
+ import { IEncodingMethod } from "../interfaces/IEncodingMethod.js";
5
+
6
+ import {
7
+ DecodeOptions,
8
+ EncodeOptions,
9
+ decode, encode, Tag
10
+ } from "../wrappers/cbor2.js";
11
+
12
+ interface inputOptions {
13
+ registry?: URRegistryClass;
14
+ cborLibEncoderOptions?: EncodeOptions & {ignoreTopLevelTag?: boolean};
15
+ cborLibDecoderOptions?: DecodeOptions;
16
+ }
17
+
18
+ interface decodeOptions {
19
+ enforceType?: RegistryItemClass | string;
20
+ cborLibOptions?: DecodeOptions;
21
+ }
22
+
23
+ export class CborEncoding<T extends RegistryItem>
24
+ implements IEncodingMethod<T, Uint8Array>
25
+ {
26
+ private _name: EncodingMethodName = EncodingMethodName.cbor;
27
+ public registry: URRegistryClass = UrRegistry;
28
+
29
+ /** Decoding options for CBOR2 library */
30
+ cborLibEncoderOptions: EncodeOptions;
31
+ cborLibDecoderOptions: DecodeOptions;
32
+
33
+ constructor(options?: inputOptions) {
34
+ this.cborLibEncoderOptions = options?.cborLibEncoderOptions;
35
+ this.cborLibDecoderOptions = options?.cborLibDecoderOptions;
36
+ }
37
+
38
+ get name(): EncodingMethodName {
39
+ return this._name;
40
+ }
41
+
42
+ /**
43
+ * Encode the given payload to CBOR
44
+ *
45
+ * @param payload @type RegistryItem
46
+ * @param cborLibOptions @type EncodeOptions
47
+ * @returns @type Uint8Array
48
+ */
49
+ encode(payload: any, cborLibOptions?: EncodeOptions & {ignoreTopLevelTag?: boolean}): Uint8Array {
50
+ // Combine instance cborLibOptions with the given cborLibOptions
51
+ const combinedOptions = {
52
+ ...this.cborLibEncoderOptions,
53
+ ...cborLibOptions,
54
+ };
55
+
56
+ // By default encode return Uint8Array
57
+ const encoded = encode(payload, combinedOptions);
58
+ return encoded;
59
+ }
60
+
61
+ /**
62
+ * Decode the CBOR encoded payload to the given type
63
+ * @param payload @type Uint8Array
64
+ * @param enforceType Forces decoding into given type or throws error if it cannot be decoded @type RegistryItemClass
65
+ * @param cborLibOptions @type DecodeOptions
66
+ * @returns @type T
67
+ */
68
+ decode(
69
+ payload: Uint8Array,
70
+ options?: decodeOptions,
71
+ ): T {
72
+ // Combine instance cborLibOptions with the given cborLibOptions
73
+ const { cborLibOptions, enforceType } = options || {};
74
+ const combinedOptions = {
75
+ ...this.cborLibDecoderOptions,
76
+ ...cborLibOptions,
77
+ };
78
+
79
+ const decoded = decode(payload, combinedOptions);
80
+
81
+ // Check if enforce type is given, if so then give the value to the enforced type
82
+ if (enforceType) {
83
+ let foundType: RegistryItemClass;
84
+ // If enforceType is string then find the type from the registry
85
+ if (typeof enforceType === "string") {
86
+ foundType = this.registry.queryByURType(enforceType);
87
+ }
88
+ else {
89
+ foundType = enforceType;
90
+ }
91
+
92
+ // If we have a registry item then force the type
93
+ if (foundType) {
94
+ return forceType(decoded, foundType) as unknown as T;
95
+ }
96
+ }
97
+
98
+ // If we still have a cbor tag but not registry item then return try to convert it to registry item
99
+ if (decoded instanceof Tag) {
100
+ return tag2registryItem(decoded) as unknown as T;
101
+ }
102
+
103
+ // Otherwise just return the decoded value
104
+ // TODO: fix as unknown as T;
105
+ return decoded as unknown as T;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Force the data to be of the enforced type registry item
111
+ * @param data
112
+ * @param enforceType
113
+ * @returns
114
+ */
115
+ function forceType(data: any, enforceType: RegistryItemClass): RegistryItem {
116
+ // If its already the enforced type then return
117
+ if (data instanceof enforceType) {
118
+ return data;
119
+ }
120
+
121
+ // If data is CBOR tag item, try to convert it to enforced type
122
+ if (data instanceof Tag) {
123
+ if (data.tag !== enforceType.tag) {
124
+ throw new Error(
125
+ `Enforced type does not match the tag of ${enforceType.URType}:${enforceType.tag} !== ${data.tag}`
126
+ );
127
+ }
128
+ return enforceType.fromCBORData(data.contents, enforceType.allowKeysNotInMap);
129
+ }
130
+
131
+ // If data is raw then try to convert it to enforced type
132
+ return enforceType.fromCBORData(data, enforceType.allowKeysNotInMap);
133
+ }
134
+
135
+ /**
136
+ * Converts a CBOR tag to a registry item
137
+ * @param unkownTag
138
+ * @returns
139
+ */
140
+ function tag2registryItem(unkownTag: Tag): RegistryItem {
141
+ const tag = toRegistryTagNumber(unkownTag.tag);
142
+ const data = unkownTag.contents;
143
+
144
+ const registryItem = UrRegistry.queryByTag(tag);
145
+ if (registryItem) {
146
+ return registryItem.fromCBORData(
147
+ data,
148
+ registryItem.allowKeysNotInMap
149
+ );
150
+ }
151
+
152
+ // If we dont have the tag in the registry return unknown item
153
+ const UnknownTag = class extends registryItemFactory({
154
+ tag: tag,
155
+ URType: "unknown-tag",
156
+ CDDL: ``,
157
+ }) {};
158
+
159
+ const unknownItem = new UnknownTag(data);
160
+
161
+ // Search through all the children in unknownItem.data if any one of them are tags
162
+ deepSearchObject(unknownItem.data);
163
+
164
+ return unknownItem;
165
+ }
166
+
167
+ function toRegistryTagNumber(tag: Tag["tag"]): number {
168
+ if (typeof tag === "bigint") {
169
+ const converted = Number(tag);
170
+ if (!Number.isSafeInteger(converted)) {
171
+ throw new Error(`CBOR tag ${tag.toString()} exceeds JavaScript safe integer range`);
172
+ }
173
+ return converted;
174
+ }
175
+
176
+ return Number(tag);
177
+ }
178
+
179
+ /**
180
+ * Search through the object and convert tags to registry items
181
+ * @param obj
182
+ * @returns
183
+ */
184
+ function deepSearchObject(obj: any) {
185
+ if (typeof obj !== "object") {
186
+ return obj;
187
+ }
188
+
189
+ for (const key in obj) {
190
+ if (obj[key] instanceof Tag) {
191
+ obj[key] = tag2registryItem(obj[key]);
192
+ } else if (typeof obj[key] === "object") {
193
+ deepSearchObject(obj[key]);
194
+ }
195
+ }
196
+ }
@@ -0,0 +1,23 @@
1
+ import { hexToUint8Array, uint8ArrayToHex } from "../helpers/uintArrayHelper.js";
2
+ import { EncodingMethodName } from "../enums/EncodingMethodName.js";
3
+ import { IEncodingMethod } from "../interfaces/IEncodingMethod.js";
4
+
5
+ export class HexEncoding implements IEncodingMethod<Uint8Array, string> {
6
+ private _name: EncodingMethodName = EncodingMethodName.hex;
7
+
8
+ get name(): EncodingMethodName {
9
+ return this._name;
10
+ }
11
+
12
+ encode(payload: Uint8Array): string {
13
+ // return payload.toString("hex");
14
+ return uint8ArrayToHex(payload);
15
+ }
16
+ decode(payload: string): Uint8Array {
17
+ const hexRegex = /^[0-9a-fA-F]+$/;
18
+ if (!hexRegex.test(payload)) {
19
+ throw new Error("Invalid hex string");
20
+ }
21
+ return hexToUint8Array(payload);
22
+ }
23
+ }
@@ -0,0 +1,19 @@
1
+ import { EncodingMethodName } from "../enums/EncodingMethodName.js";
2
+ import { IEncodingMethod } from "../interfaces/IEncodingMethod.js";
3
+ import { UR } from "../classes/UR.js";
4
+ import { RegistryItem } from "../classes/RegistryItem.js";
5
+
6
+ export class UrEncoding implements IEncodingMethod<RegistryItem, UR> {
7
+ private _name: EncodingMethodName = EncodingMethodName.ur;
8
+
9
+ get name(): EncodingMethodName {
10
+ return this._name;
11
+ }
12
+
13
+ encode(payload: RegistryItem): UR {
14
+ return UR.fromRegistryItem(payload);
15
+ }
16
+ decode(payload: UR): RegistryItem {
17
+ return payload.toRegistryItem();
18
+ }
19
+ }
@@ -0,0 +1,215 @@
1
+ import { assert, getCRCHex, partition, split } from "../helpers/utils.js";
2
+ import { uint8ArrayToHex, hexToUint8Array } from "../helpers/uintArrayHelper.js";
3
+
4
+ const bytewords =
5
+ "ableacidalsoapexaquaarchatomauntawayaxisbackbaldbarnbeltbetabiasbluebodybragbrewbulbbuzzcalmcashcatschefcityclawcodecolacookcostcruxcurlcuspcyandarkdatadaysdelidicedietdoordowndrawdropdrumdulldutyeacheasyechoedgeepicevenexamexiteyesfactfairfernfigsfilmfishfizzflapflewfluxfoxyfreefrogfuelfundgalagamegeargemsgiftgirlglowgoodgraygrimgurugushgyrohalfhanghardhawkheathelphighhillholyhopehornhutsicedideaidleinchinkyintoirisironitemjadejazzjoinjoltjowljudojugsjumpjunkjurykeepkenokeptkeyskickkilnkingkitekiwiknoblamblavalazyleaflegsliarlimplionlistlogoloudloveluaulucklungmainmanymathmazememomenumeowmildmintmissmonknailnavyneednewsnextnoonnotenumbobeyoboeomitonyxopenovalowlspaidpartpeckplaypluspoempoolposepuffpumapurrquadquizraceramprealredorichroadrockroofrubyruinrunsrustsafesagascarsetssilkskewslotsoapsolosongstubsurfswantacotasktaxitenttiedtimetinytoiltombtoystriptunatwinuglyundouniturgeuservastveryvetovialvibeviewvisavoidvowswallwandwarmwaspwavewaxywebswhatwhenwhizwolfworkyankyawnyellyogayurtzapszerozestzinczonezoom";
6
+ let bytewordsLookUpTable: number[] = [];
7
+ const BYTEWORDS_NUM = 256;
8
+ const BYTEWORD_LENGTH = 4;
9
+ const MINIMAL_BYTEWORD_LENGTH = 2;
10
+
11
+ export enum STYLES {
12
+ STANDARD = "standard",
13
+ URI = "uri",
14
+ MINIMAL = "minimal",
15
+ }
16
+
17
+ const getWord = (index: number): string => {
18
+ return bytewords.slice(
19
+ index * BYTEWORD_LENGTH,
20
+ index * BYTEWORD_LENGTH + BYTEWORD_LENGTH
21
+ );
22
+ };
23
+
24
+ const getMinimalWord = (index: number): string => {
25
+ const byteword = getWord(index);
26
+
27
+ return `${byteword[0]}${byteword[BYTEWORD_LENGTH - 1]}`;
28
+ };
29
+
30
+ const addCRC = (string: string): string => {
31
+ const crc = getCRCHex(hexToUint8Array(string));
32
+
33
+ return `${string}${crc}`;
34
+ };
35
+
36
+ const encodeWithSeparator = (word: string, separator: string, includeChecksum: boolean): string => {
37
+ const crcAppendedWord = includeChecksum ? addCRC(word) : word;
38
+ const crcWordArray = hexToUint8Array(crcAppendedWord);
39
+ const result = crcWordArray.reduce(
40
+ (result: string[], w) => [...result, getWord(w)],
41
+ []
42
+ );
43
+
44
+ return result.join(separator);
45
+ };
46
+
47
+ const encodeMinimal = (word: string, includeChecksum: boolean): string => {
48
+ const crcAppendedWord = includeChecksum ? addCRC(word) : word;
49
+ const crcWordArray = hexToUint8Array(crcAppendedWord);
50
+ const result = crcWordArray.reduce(
51
+ (result, w) => result + getMinimalWord(w),
52
+ ""
53
+ );
54
+
55
+ return result;
56
+ };
57
+
58
+ const decodeWord = (word: string, wordLength: number): string => {
59
+ assert(
60
+ word.length === wordLength,
61
+ "Invalid Bytewords: word.length does not match wordLength provided"
62
+ );
63
+
64
+ const dim = 26;
65
+
66
+ // Since the first and last letters of each Byteword are unique,
67
+ // we can use them as indexes into a two-dimensional lookup table.
68
+ // This table is generated lazily.
69
+ if (bytewordsLookUpTable.length === 0) {
70
+ const array_len = dim * dim;
71
+ bytewordsLookUpTable = [...new Array(array_len)].map(() => -1);
72
+
73
+ for (let i = 0; i < BYTEWORDS_NUM; i++) {
74
+ const byteword = getWord(i);
75
+ let x = byteword[0].charCodeAt(0) - "a".charCodeAt(0);
76
+ let y = byteword[3].charCodeAt(0) - "a".charCodeAt(0);
77
+ let offset = y * dim + x;
78
+ bytewordsLookUpTable[offset] = i;
79
+ }
80
+ }
81
+
82
+ // If the coordinates generated by the first and last letters are out of bounds,
83
+ // or the lookup table contains -1 at the coordinates, then the word is not valid.
84
+ let x = word[0].toLowerCase().charCodeAt(0) - "a".charCodeAt(0);
85
+ let y =
86
+ word[wordLength == 4 ? 3 : 1].toLowerCase().charCodeAt(0) -
87
+ "a".charCodeAt(0);
88
+
89
+ assert(
90
+ 0 <= x && x < dim && 0 <= y && y < dim,
91
+ "Invalid Bytewords: invalid word"
92
+ );
93
+
94
+ let offset = y * dim + x;
95
+ let value = bytewordsLookUpTable[offset];
96
+
97
+ assert(value !== -1, "Invalid Bytewords: value not in lookup table");
98
+
99
+ // If we're decoding a full four-letter word, verify that the two middle letters are correct.
100
+ if (wordLength == BYTEWORD_LENGTH) {
101
+ const byteword = getWord(value);
102
+ let c1 = word[1].toLowerCase();
103
+ let c2 = word[2].toLowerCase();
104
+
105
+ assert(
106
+ c1 === byteword[1] && c2 === byteword[2],
107
+ "Invalid Bytewords: invalid middle letters of word"
108
+ );
109
+ }
110
+
111
+ // Successful decode.
112
+ return value.toString(16).padStart(2, "0");
113
+ };
114
+
115
+ /**
116
+ * Decode a string of Bytewords into a hex string.
117
+ * @param string string of Bytewords. e.g. "lpamchcfatttcyclehgsdphdhgehfghkkkdl..."
118
+ * @param separator e.g. " " or "-" or "" or any other separator
119
+ * @param wordLength e.g. 4 or 2 or any other length
120
+ * @param includeChecksum whether to include checksum in the decoding.
121
+ * @returns hex string
122
+ */
123
+ const _decode = (
124
+ string: string,
125
+ separator: string,
126
+ wordLength: number,
127
+ includeChecksum: boolean
128
+ ): string => {
129
+ // Split the string into words. e.g. ["lp", "am", "ch", "cf", "at", "tt", "cy", "cl", "eh", "gs", "dp", "hd", "hg", "eh", "fg", "hk", "kk", "dl", ...]
130
+ const words =
131
+ wordLength == BYTEWORD_LENGTH
132
+ ? string.split(separator)
133
+ : partition(string, 2);
134
+
135
+ // Decode each word. e.g. ["85", "06", "17", "19", "07", "d1", "1a", "21", "31", "4c", "2d", "58", "57", "31", "46", "59", "79", "2f", ...]
136
+ const decodedWords = words.map((word: string) =>
137
+ decodeWord(word, wordLength)
138
+ );
139
+
140
+ // e.g. "8506171907d11a21314c2d5857314659792f..."
141
+ const decodedString = decodedWords.join("");
142
+
143
+ if (includeChecksum) {
144
+ // 4 bytes for checksum, at least 1 byte for body
145
+ assert(
146
+ decodedString.length >= 5,
147
+ "Invalid Bytewords: invalid decoded string length"
148
+ );
149
+
150
+ // decoded string consists of `body` and `checksum`
151
+ const decodedArray = hexToUint8Array(decodedString);
152
+ const [body, bodyChecksum] = split(decodedArray, 4);
153
+ const checksum = getCRCHex(body); // convert to hex
154
+
155
+ assert(checksum === uint8ArrayToHex(bodyChecksum), "Invalid Checksum");
156
+
157
+ return uint8ArrayToHex(body);
158
+ } else {
159
+ return decodedString;
160
+ }
161
+ };
162
+
163
+ /**
164
+ * Decode a string of bytewords into a hex string.
165
+ * @param string string of Bytewords
166
+ * @param style style of Bytewords
167
+ * @param includeChecksum whether to include checksum in the decoding.
168
+ * @returns hex string
169
+ */
170
+ export const decode = (
171
+ string: string,
172
+ style: STYLES = STYLES.MINIMAL,
173
+ includeChecksum: boolean = true
174
+ ): string => {
175
+ switch (style) {
176
+ case STYLES.STANDARD:
177
+ return _decode(string, " ", BYTEWORD_LENGTH, includeChecksum);
178
+ case STYLES.URI:
179
+ return _decode(string, "-", BYTEWORD_LENGTH, includeChecksum);
180
+ case STYLES.MINIMAL:
181
+ return _decode(string, "", MINIMAL_BYTEWORD_LENGTH, includeChecksum);
182
+ default:
183
+ throw new Error(`Invalid style ${style}`);
184
+ }
185
+ };
186
+
187
+ /**
188
+ * Encodes a string (hex representation of a buffer) into bytewords.
189
+ * @param string string to encode.
190
+ * @param style style to use for the encoding.
191
+ * @param includeChecksum whether to include checksum in the encoding.
192
+ * @returns the byteword encoded string
193
+ */
194
+ export const encode = (
195
+ string: string,
196
+ style: STYLES = STYLES.MINIMAL,
197
+ includeChecksum: boolean = true
198
+ ): string => {
199
+ switch (style) {
200
+ case STYLES.STANDARD:
201
+ return encodeWithSeparator(string, " ", includeChecksum);
202
+ case STYLES.URI:
203
+ return encodeWithSeparator(string, "-", includeChecksum);
204
+ case STYLES.MINIMAL:
205
+ return encodeMinimal(string, includeChecksum);
206
+ default:
207
+ throw new Error(`Invalid style ${style}`);
208
+ }
209
+ };
210
+
211
+ export default {
212
+ decode,
213
+ encode,
214
+ STYLES,
215
+ };
@@ -0,0 +1,26 @@
1
+ import { BytewordEncoding } from "./BytewordEncoding.js";
2
+ import { CborEncoding } from "./CborEncoding.js";
3
+ import { HexEncoding } from "./HexEncoding.js";
4
+ import { EncodingPipeline } from "./pipeline.js";
5
+
6
+ /**
7
+ * Pipeline that encodes registry registryItem | any -> cbor -> hex -> bytewords
8
+ *
9
+ * Uses default encoding options for each encoding method
10
+ * 1. Cbor: CBOR2 library
11
+ * 2. Hex: Uint8Array -> hex string
12
+ * 3. Bytewords: Uint8Array -> bytewords string with checksum and minimal style
13
+ *
14
+ */
15
+
16
+ export const defaultEncoders = {
17
+ cbor: new CborEncoding(),
18
+ hex: new HexEncoding(),
19
+ bytewords: new BytewordEncoding(),
20
+ }
21
+
22
+ export const dataPipeline = new EncodingPipeline<any, string>([
23
+ defaultEncoders.cbor,
24
+ defaultEncoders.hex,
25
+ defaultEncoders.bytewords,
26
+ ]);
@@ -0,0 +1,103 @@
1
+ import { EncodingMethodName } from "../enums/EncodingMethodName.js";
2
+ import { IEncodingMethod } from "../interfaces/IEncodingMethod.js";
3
+
4
+ interface pipelineConfig {
5
+ from?: EncodingMethodName;
6
+ until?: EncodingMethodName;
7
+ [key: string]: any;
8
+ }
9
+
10
+ export class EncodingPipeline<T, U> implements IEncodingMethod<T, U> {
11
+ private _name: EncodingMethodName = EncodingMethodName.pipe;
12
+ private _encodingMethods: IEncodingMethod<any, any>[];
13
+
14
+ constructor(encodingMethods: IEncodingMethod<any, any>[]) {
15
+ this._encodingMethods = encodingMethods;
16
+ }
17
+
18
+ get name(): EncodingMethodName {
19
+ return this._name;
20
+ }
21
+
22
+ get encodingMethods() {
23
+ return this._encodingMethods;
24
+ }
25
+
26
+ get decodingMethods() {
27
+ return this._encodingMethods.slice().reverse();
28
+ }
29
+
30
+
31
+ // TODO: change until to "to"
32
+ encode<O = U>(payload: T, config: pipelineConfig = {from:undefined, until:undefined}): O {
33
+ let encodedValue: any = payload;
34
+ let fromIndex = 0;
35
+ let untilIndex = this.encodingMethods.length;
36
+
37
+ const { from, until, ...rest } = config;
38
+
39
+ // Find the index of the specified start and until encoding methods
40
+ if(from) {
41
+ fromIndex = this.encodingMethods.findIndex((method) => method.name === from);
42
+ if(fromIndex === -1) {
43
+ throw new Error(`Encoding method ${from} not found`);
44
+ }
45
+ }
46
+
47
+ if(until) {
48
+ untilIndex = this.encodingMethods.findIndex((method) => method.name === until);
49
+ if(untilIndex === -1) {
50
+ throw new Error(`Encoding method ${until} not found`);
51
+ }
52
+ }
53
+
54
+ if(fromIndex > untilIndex) {
55
+ throw new Error("Invalid encoding method range");
56
+ }
57
+
58
+ // Apply each encoding method in sequence until the specified encoding method or the end
59
+ for (let i = fromIndex; i < untilIndex; i++) {
60
+ encodedValue = this.encodingMethods[i].encode(encodedValue, rest);
61
+ }
62
+ return encodedValue;
63
+ }
64
+
65
+ decode<O = T>(payload: U, config: pipelineConfig = {from:undefined, until:undefined}): O {
66
+ let decodedValue: any = payload;
67
+ let fromIndex = 0;
68
+ let untilIndex = this.decodingMethods.length;
69
+
70
+ const { from, until, ...rest } = config;
71
+
72
+ // Find the index of the specified start and until encoding methods
73
+ if(from) {
74
+ fromIndex = this.decodingMethods.findIndex((method) => method.name === from);
75
+ if(fromIndex === -1) {
76
+ throw new Error(`Encoding method ${from} not found`);
77
+ }
78
+ }
79
+
80
+ if(until) {
81
+ untilIndex = this.decodingMethods.findIndex((method) => method.name === until);
82
+ if(untilIndex === -1) {
83
+ throw new Error(`Encoding method ${until} not found`);
84
+ }
85
+ }
86
+
87
+ if(fromIndex > untilIndex) {
88
+ throw new Error("Invalid encoding method range");
89
+ }
90
+
91
+ // Apply each encoding method in sequence until the specified encoding method or the end
92
+ for (let i = fromIndex; i < untilIndex; i++) {
93
+ decodedValue = this.decodingMethods[i].decode(decodedValue, rest);
94
+ }
95
+
96
+ return decodedValue;
97
+ }
98
+
99
+ getMethod(methodName: EncodingMethodName): IEncodingMethod<any, any> {
100
+ return this.encodingMethods.find((method) => method.name === methodName);
101
+ }
102
+
103
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Defaultly used encoding methods.
3
+ */
4
+ export enum EncodingMethodName {
5
+ bytewords = "bytewords",
6
+ cbor = "cbor",
7
+ hex = "hex",
8
+ pipe = "pipe",
9
+ ur = "ur",
10
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,34 @@
1
+ export class InvalidSchemeError extends Error {
2
+ constructor() {
3
+ super("Invalid Scheme");
4
+ this.name = "InvalidSchemeError";
5
+ }
6
+ }
7
+
8
+ export class InvalidPathLengthError extends Error {
9
+ constructor() {
10
+ super("Invalid Path");
11
+ this.name = "InvalidPathLengthError";
12
+ }
13
+ }
14
+
15
+ export class InvalidTypeError extends Error {
16
+ constructor() {
17
+ super("Invalid Type");
18
+ this.name = "InvalidTypeError";
19
+ }
20
+ }
21
+
22
+ export class InvalidSequenceComponentError extends Error {
23
+ constructor() {
24
+ super("Invalid Sequence Component");
25
+ this.name = "InvalidSequenceComponentError";
26
+ }
27
+ }
28
+
29
+ export class InvalidChecksumError extends Error {
30
+ constructor() {
31
+ super("Invalid Checksum");
32
+ this.name = "InvalidChecksumError";
33
+ }
34
+ }