@graffiti-garden/implementation-decentralized 0.0.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 (193) hide show
  1. package/LICENSE +674 -0
  2. package/dist/1-services/1-authorization.d.ts +37 -0
  3. package/dist/1-services/1-authorization.d.ts.map +1 -0
  4. package/dist/1-services/2-dids-tests.d.ts +2 -0
  5. package/dist/1-services/2-dids-tests.d.ts.map +1 -0
  6. package/dist/1-services/2-dids.d.ts +9 -0
  7. package/dist/1-services/2-dids.d.ts.map +1 -0
  8. package/dist/1-services/3-storage-buckets-tests.d.ts +2 -0
  9. package/dist/1-services/3-storage-buckets-tests.d.ts.map +1 -0
  10. package/dist/1-services/3-storage-buckets.d.ts +11 -0
  11. package/dist/1-services/3-storage-buckets.d.ts.map +1 -0
  12. package/dist/1-services/4-inboxes-tests.d.ts +2 -0
  13. package/dist/1-services/4-inboxes-tests.d.ts.map +1 -0
  14. package/dist/1-services/4-inboxes.d.ts +87 -0
  15. package/dist/1-services/4-inboxes.d.ts.map +1 -0
  16. package/dist/1-services/utilities.d.ts +7 -0
  17. package/dist/1-services/utilities.d.ts.map +1 -0
  18. package/dist/2-primitives/1-string-encoding-tests.d.ts +2 -0
  19. package/dist/2-primitives/1-string-encoding-tests.d.ts.map +1 -0
  20. package/dist/2-primitives/1-string-encoding.d.ts +6 -0
  21. package/dist/2-primitives/1-string-encoding.d.ts.map +1 -0
  22. package/dist/2-primitives/2-content-addresses-tests.d.ts +2 -0
  23. package/dist/2-primitives/2-content-addresses-tests.d.ts.map +1 -0
  24. package/dist/2-primitives/2-content-addresses.d.ts +8 -0
  25. package/dist/2-primitives/2-content-addresses.d.ts.map +1 -0
  26. package/dist/2-primitives/3-channel-attestations-tests.d.ts +2 -0
  27. package/dist/2-primitives/3-channel-attestations-tests.d.ts.map +1 -0
  28. package/dist/2-primitives/3-channel-attestations.d.ts +13 -0
  29. package/dist/2-primitives/3-channel-attestations.d.ts.map +1 -0
  30. package/dist/2-primitives/4-allowed-attestations-tests.d.ts +2 -0
  31. package/dist/2-primitives/4-allowed-attestations-tests.d.ts.map +1 -0
  32. package/dist/2-primitives/4-allowed-attestations.d.ts +9 -0
  33. package/dist/2-primitives/4-allowed-attestations.d.ts.map +1 -0
  34. package/dist/3-protocol/1-sessions.d.ts +81 -0
  35. package/dist/3-protocol/1-sessions.d.ts.map +1 -0
  36. package/dist/3-protocol/2-handles-tests.d.ts +2 -0
  37. package/dist/3-protocol/2-handles-tests.d.ts.map +1 -0
  38. package/dist/3-protocol/2-handles.d.ts +13 -0
  39. package/dist/3-protocol/2-handles.d.ts.map +1 -0
  40. package/dist/3-protocol/3-object-encoding-tests.d.ts +2 -0
  41. package/dist/3-protocol/3-object-encoding-tests.d.ts.map +1 -0
  42. package/dist/3-protocol/3-object-encoding.d.ts +43 -0
  43. package/dist/3-protocol/3-object-encoding.d.ts.map +1 -0
  44. package/dist/3-protocol/4-graffiti.d.ts +79 -0
  45. package/dist/3-protocol/4-graffiti.d.ts.map +1 -0
  46. package/dist/3-protocol/login-dialog.html.d.ts +2 -0
  47. package/dist/3-protocol/login-dialog.html.d.ts.map +1 -0
  48. package/dist/browser/ajv-QBSREQSI.js +9 -0
  49. package/dist/browser/ajv-QBSREQSI.js.map +7 -0
  50. package/dist/browser/build-BXWPS7VK.js +2 -0
  51. package/dist/browser/build-BXWPS7VK.js.map +7 -0
  52. package/dist/browser/chunk-RFBBAUMM.js +2 -0
  53. package/dist/browser/chunk-RFBBAUMM.js.map +7 -0
  54. package/dist/browser/graffiti-KV3G3O72-URO7SJIJ.js +2 -0
  55. package/dist/browser/graffiti-KV3G3O72-URO7SJIJ.js.map +7 -0
  56. package/dist/browser/index.js +16 -0
  57. package/dist/browser/index.js.map +7 -0
  58. package/dist/browser/login-dialog.html-XUWYDNNI.js +44 -0
  59. package/dist/browser/login-dialog.html-XUWYDNNI.js.map +7 -0
  60. package/dist/browser/rock-salt-LI7DAH66-KPFEBIBO.js +2 -0
  61. package/dist/browser/rock-salt-LI7DAH66-KPFEBIBO.js.map +7 -0
  62. package/dist/browser/style-YUTCEBZV-RWYJV575.js +287 -0
  63. package/dist/browser/style-YUTCEBZV-RWYJV575.js.map +7 -0
  64. package/dist/cjs/1-services/1-authorization.js +317 -0
  65. package/dist/cjs/1-services/1-authorization.js.map +7 -0
  66. package/dist/cjs/1-services/2-dids-tests.js +44 -0
  67. package/dist/cjs/1-services/2-dids-tests.js.map +7 -0
  68. package/dist/cjs/1-services/2-dids.js +47 -0
  69. package/dist/cjs/1-services/2-dids.js.map +7 -0
  70. package/dist/cjs/1-services/3-storage-buckets-tests.js +123 -0
  71. package/dist/cjs/1-services/3-storage-buckets-tests.js.map +7 -0
  72. package/dist/cjs/1-services/3-storage-buckets.js +148 -0
  73. package/dist/cjs/1-services/3-storage-buckets.js.map +7 -0
  74. package/dist/cjs/1-services/4-inboxes-tests.js +145 -0
  75. package/dist/cjs/1-services/4-inboxes-tests.js.map +7 -0
  76. package/dist/cjs/1-services/4-inboxes.js +539 -0
  77. package/dist/cjs/1-services/4-inboxes.js.map +7 -0
  78. package/dist/cjs/1-services/utilities.js +75 -0
  79. package/dist/cjs/1-services/utilities.js.map +7 -0
  80. package/dist/cjs/2-primitives/1-string-encoding-tests.js +50 -0
  81. package/dist/cjs/2-primitives/1-string-encoding-tests.js.map +7 -0
  82. package/dist/cjs/2-primitives/1-string-encoding.js +46 -0
  83. package/dist/cjs/2-primitives/1-string-encoding.js.map +7 -0
  84. package/dist/cjs/2-primitives/2-content-addresses-tests.js +62 -0
  85. package/dist/cjs/2-primitives/2-content-addresses-tests.js.map +7 -0
  86. package/dist/cjs/2-primitives/2-content-addresses.js +53 -0
  87. package/dist/cjs/2-primitives/2-content-addresses.js.map +7 -0
  88. package/dist/cjs/2-primitives/3-channel-attestations-tests.js +130 -0
  89. package/dist/cjs/2-primitives/3-channel-attestations-tests.js.map +7 -0
  90. package/dist/cjs/2-primitives/3-channel-attestations.js +84 -0
  91. package/dist/cjs/2-primitives/3-channel-attestations.js.map +7 -0
  92. package/dist/cjs/2-primitives/4-allowed-attestations-tests.js +96 -0
  93. package/dist/cjs/2-primitives/4-allowed-attestations-tests.js.map +7 -0
  94. package/dist/cjs/2-primitives/4-allowed-attestations.js +68 -0
  95. package/dist/cjs/2-primitives/4-allowed-attestations.js.map +7 -0
  96. package/dist/cjs/3-protocol/1-sessions.js +473 -0
  97. package/dist/cjs/3-protocol/1-sessions.js.map +7 -0
  98. package/dist/cjs/3-protocol/2-handles-tests.js +39 -0
  99. package/dist/cjs/3-protocol/2-handles-tests.js.map +7 -0
  100. package/dist/cjs/3-protocol/2-handles.js +65 -0
  101. package/dist/cjs/3-protocol/2-handles.js.map +7 -0
  102. package/dist/cjs/3-protocol/3-object-encoding-tests.js +253 -0
  103. package/dist/cjs/3-protocol/3-object-encoding-tests.js.map +7 -0
  104. package/dist/cjs/3-protocol/3-object-encoding.js +287 -0
  105. package/dist/cjs/3-protocol/3-object-encoding.js.map +7 -0
  106. package/dist/cjs/3-protocol/4-graffiti.js +937 -0
  107. package/dist/cjs/3-protocol/4-graffiti.js.map +7 -0
  108. package/dist/cjs/3-protocol/login-dialog.html.js +67 -0
  109. package/dist/cjs/3-protocol/login-dialog.html.js.map +7 -0
  110. package/dist/cjs/index.js +32 -0
  111. package/dist/cjs/index.js.map +7 -0
  112. package/dist/cjs/index.spec.js +130 -0
  113. package/dist/cjs/index.spec.js.map +7 -0
  114. package/dist/esm/1-services/1-authorization.js +304 -0
  115. package/dist/esm/1-services/1-authorization.js.map +7 -0
  116. package/dist/esm/1-services/2-dids-tests.js +24 -0
  117. package/dist/esm/1-services/2-dids-tests.js.map +7 -0
  118. package/dist/esm/1-services/2-dids.js +27 -0
  119. package/dist/esm/1-services/2-dids.js.map +7 -0
  120. package/dist/esm/1-services/3-storage-buckets-tests.js +103 -0
  121. package/dist/esm/1-services/3-storage-buckets-tests.js.map +7 -0
  122. package/dist/esm/1-services/3-storage-buckets.js +132 -0
  123. package/dist/esm/1-services/3-storage-buckets.js.map +7 -0
  124. package/dist/esm/1-services/4-inboxes-tests.js +125 -0
  125. package/dist/esm/1-services/4-inboxes-tests.js.map +7 -0
  126. package/dist/esm/1-services/4-inboxes.js +533 -0
  127. package/dist/esm/1-services/4-inboxes.js.map +7 -0
  128. package/dist/esm/1-services/utilities.js +60 -0
  129. package/dist/esm/1-services/utilities.js.map +7 -0
  130. package/dist/esm/2-primitives/1-string-encoding-tests.js +33 -0
  131. package/dist/esm/2-primitives/1-string-encoding-tests.js.map +7 -0
  132. package/dist/esm/2-primitives/1-string-encoding.js +26 -0
  133. package/dist/esm/2-primitives/1-string-encoding.js.map +7 -0
  134. package/dist/esm/2-primitives/2-content-addresses-tests.js +45 -0
  135. package/dist/esm/2-primitives/2-content-addresses-tests.js.map +7 -0
  136. package/dist/esm/2-primitives/2-content-addresses.js +33 -0
  137. package/dist/esm/2-primitives/2-content-addresses.js.map +7 -0
  138. package/dist/esm/2-primitives/3-channel-attestations-tests.js +116 -0
  139. package/dist/esm/2-primitives/3-channel-attestations-tests.js.map +7 -0
  140. package/dist/esm/2-primitives/3-channel-attestations.js +69 -0
  141. package/dist/esm/2-primitives/3-channel-attestations.js.map +7 -0
  142. package/dist/esm/2-primitives/4-allowed-attestations-tests.js +82 -0
  143. package/dist/esm/2-primitives/4-allowed-attestations-tests.js.map +7 -0
  144. package/dist/esm/2-primitives/4-allowed-attestations.js +51 -0
  145. package/dist/esm/2-primitives/4-allowed-attestations.js.map +7 -0
  146. package/dist/esm/3-protocol/1-sessions.js +465 -0
  147. package/dist/esm/3-protocol/1-sessions.js.map +7 -0
  148. package/dist/esm/3-protocol/2-handles-tests.js +19 -0
  149. package/dist/esm/3-protocol/2-handles-tests.js.map +7 -0
  150. package/dist/esm/3-protocol/2-handles.js +45 -0
  151. package/dist/esm/3-protocol/2-handles.js.map +7 -0
  152. package/dist/esm/3-protocol/3-object-encoding-tests.js +248 -0
  153. package/dist/esm/3-protocol/3-object-encoding-tests.js.map +7 -0
  154. package/dist/esm/3-protocol/3-object-encoding.js +280 -0
  155. package/dist/esm/3-protocol/3-object-encoding.js.map +7 -0
  156. package/dist/esm/3-protocol/4-graffiti.js +957 -0
  157. package/dist/esm/3-protocol/4-graffiti.js.map +7 -0
  158. package/dist/esm/3-protocol/login-dialog.html.js +47 -0
  159. package/dist/esm/3-protocol/login-dialog.html.js.map +7 -0
  160. package/dist/esm/index.js +14 -0
  161. package/dist/esm/index.js.map +7 -0
  162. package/dist/esm/index.spec.js +133 -0
  163. package/dist/esm/index.spec.js.map +7 -0
  164. package/dist/index.d.ts +10 -0
  165. package/dist/index.d.ts.map +1 -0
  166. package/dist/index.spec.d.ts +2 -0
  167. package/dist/index.spec.d.ts.map +1 -0
  168. package/package.json +62 -0
  169. package/src/1-services/1-authorization.ts +399 -0
  170. package/src/1-services/2-dids-tests.ts +24 -0
  171. package/src/1-services/2-dids.ts +30 -0
  172. package/src/1-services/3-storage-buckets-tests.ts +121 -0
  173. package/src/1-services/3-storage-buckets.ts +183 -0
  174. package/src/1-services/4-inboxes-tests.ts +154 -0
  175. package/src/1-services/4-inboxes.ts +722 -0
  176. package/src/1-services/utilities.ts +65 -0
  177. package/src/2-primitives/1-string-encoding-tests.ts +33 -0
  178. package/src/2-primitives/1-string-encoding.ts +33 -0
  179. package/src/2-primitives/2-content-addresses-tests.ts +46 -0
  180. package/src/2-primitives/2-content-addresses.ts +42 -0
  181. package/src/2-primitives/3-channel-attestations-tests.ts +125 -0
  182. package/src/2-primitives/3-channel-attestations.ts +95 -0
  183. package/src/2-primitives/4-allowed-attestations-tests.ts +86 -0
  184. package/src/2-primitives/4-allowed-attestations.ts +69 -0
  185. package/src/3-protocol/1-sessions.ts +601 -0
  186. package/src/3-protocol/2-handles-tests.ts +17 -0
  187. package/src/3-protocol/2-handles.ts +60 -0
  188. package/src/3-protocol/3-object-encoding-tests.ts +269 -0
  189. package/src/3-protocol/3-object-encoding.ts +396 -0
  190. package/src/3-protocol/4-graffiti.ts +1265 -0
  191. package/src/3-protocol/login-dialog.html.ts +43 -0
  192. package/src/index.spec.ts +158 -0
  193. package/src/index.ts +16 -0
@@ -0,0 +1,33 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import {
3
+ STRING_ENCODER_METHOD_BASE64URL,
4
+ StringEncoder
5
+ } from "./1-string-encoding";
6
+ import { randomBytes } from "@noble/hashes/utils.js";
7
+ function stringEncodingTests() {
8
+ describe("String encoding tests", () => {
9
+ const stringEncodingMethods = [STRING_ENCODER_METHOD_BASE64URL];
10
+ const stringEncoder = new StringEncoder();
11
+ test("Invalid string decoding method", async () => {
12
+ const bytes = randomBytes();
13
+ await expect(
14
+ () => stringEncoder.encode("invalid-method", bytes)
15
+ ).rejects.toThrow();
16
+ });
17
+ for (const method of stringEncodingMethods) {
18
+ describe(`String Encoding Method: ${method}`, () => {
19
+ test("encodes and decodes strings correctly", async () => {
20
+ const bytes = randomBytes();
21
+ const encoded = await stringEncoder.encode(method, bytes);
22
+ const decoded = await stringEncoder.decode(encoded);
23
+ expect(decoded).toEqual(bytes);
24
+ expect(decoded).not.toEqual(randomBytes());
25
+ });
26
+ });
27
+ }
28
+ });
29
+ }
30
+ export {
31
+ stringEncodingTests
32
+ };
33
+ //# sourceMappingURL=1-string-encoding-tests.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/2-primitives/1-string-encoding-tests.ts"],
4
+ "sourcesContent": ["import { describe, expect, test } from \"vitest\";\nimport {\n STRING_ENCODER_METHOD_BASE64URL,\n StringEncoder,\n} from \"./1-string-encoding\";\nimport { randomBytes } from \"@noble/hashes/utils.js\";\n\nexport function stringEncodingTests() {\n describe(\"String encoding tests\", () => {\n const stringEncodingMethods = [STRING_ENCODER_METHOD_BASE64URL];\n const stringEncoder = new StringEncoder();\n\n test(\"Invalid string decoding method\", async () => {\n const bytes = randomBytes();\n await expect(() =>\n stringEncoder.encode(\"invalid-method\", bytes),\n ).rejects.toThrow();\n });\n\n for (const method of stringEncodingMethods) {\n describe(`String Encoding Method: ${method}`, () => {\n test(\"encodes and decodes strings correctly\", async () => {\n const bytes = randomBytes();\n const encoded = await stringEncoder.encode(method, bytes);\n const decoded = await stringEncoder.decode(encoded);\n\n expect(decoded).toEqual(bytes);\n expect(decoded).not.toEqual(randomBytes());\n });\n });\n }\n });\n}\n"],
5
+ "mappings": "AAAA,SAAS,UAAU,QAAQ,YAAY;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;AAErB,SAAS,sBAAsB;AACpC,WAAS,yBAAyB,MAAM;AACtC,UAAM,wBAAwB,CAAC,+BAA+B;AAC9D,UAAM,gBAAgB,IAAI,cAAc;AAExC,SAAK,kCAAkC,YAAY;AACjD,YAAM,QAAQ,YAAY;AAC1B,YAAM;AAAA,QAAO,MACX,cAAc,OAAO,kBAAkB,KAAK;AAAA,MAC9C,EAAE,QAAQ,QAAQ;AAAA,IACpB,CAAC;AAED,eAAW,UAAU,uBAAuB;AAC1C,eAAS,2BAA2B,MAAM,IAAI,MAAM;AAClD,aAAK,yCAAyC,YAAY;AACxD,gBAAM,QAAQ,YAAY;AAC1B,gBAAM,UAAU,MAAM,cAAc,OAAO,QAAQ,KAAK;AACxD,gBAAM,UAAU,MAAM,cAAc,OAAO,OAAO;AAElD,iBAAO,OAAO,EAAE,QAAQ,KAAK;AAC7B,iBAAO,OAAO,EAAE,IAAI,QAAQ,YAAY,CAAC;AAAA,QAC3C,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ const STRING_ENCODER_METHOD_BASE64URL = "base64url";
2
+ const STRING_ENCODER_PREFIX_BASE64URL = "u";
3
+ class StringEncoder {
4
+ async encode(method, bytes) {
5
+ if (method !== STRING_ENCODER_METHOD_BASE64URL) {
6
+ throw new Error(`Unsupported string encoding method: ${method}`);
7
+ }
8
+ const base64 = btoa(String.fromCodePoint(...bytes));
9
+ const encoded = base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/\=+$/, "");
10
+ return STRING_ENCODER_PREFIX_BASE64URL + encoded;
11
+ }
12
+ async decode(base64Url) {
13
+ if (!base64Url.startsWith(STRING_ENCODER_PREFIX_BASE64URL)) {
14
+ throw new Error(`Unsupported string encoding prefix: ${base64Url[0]}`);
15
+ }
16
+ base64Url = base64Url.slice(1);
17
+ let base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
18
+ while (base64.length % 4 !== 0) base64 += "=";
19
+ return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
20
+ }
21
+ }
22
+ export {
23
+ STRING_ENCODER_METHOD_BASE64URL,
24
+ StringEncoder
25
+ };
26
+ //# sourceMappingURL=1-string-encoding.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/2-primitives/1-string-encoding.ts"],
4
+ "sourcesContent": ["// https://github.com/multiformats/multibase/blob/master/multibase.csv\nexport const STRING_ENCODER_METHOD_BASE64URL = \"base64url\";\nconst STRING_ENCODER_PREFIX_BASE64URL = \"u\";\n\nexport class StringEncoder {\n async encode(method: string, bytes: Uint8Array): Promise<string> {\n if (method !== STRING_ENCODER_METHOD_BASE64URL) {\n throw new Error(`Unsupported string encoding method: ${method}`);\n }\n // Convert it to base64\n const base64 = btoa(String.fromCodePoint(...bytes));\n // Make sure it is url safe\n const encoded = base64\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/\\=+$/, \"\");\n // Append method prefix\n return STRING_ENCODER_PREFIX_BASE64URL + encoded;\n }\n\n async decode(base64Url: string): Promise<Uint8Array> {\n if (!base64Url.startsWith(STRING_ENCODER_PREFIX_BASE64URL)) {\n throw new Error(`Unsupported string encoding prefix: ${base64Url[0]}`);\n }\n base64Url = base64Url.slice(1);\n // Undo url-safe base64\n let base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n // Add padding if necessary\n while (base64.length % 4 !== 0) base64 += \"=\";\n // Decode\n return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));\n }\n}\n"],
5
+ "mappings": "AACO,MAAM,kCAAkC;AAC/C,MAAM,kCAAkC;AAEjC,MAAM,cAAc;AAAA,EACzB,MAAM,OAAO,QAAgB,OAAoC;AAC/D,QAAI,WAAW,iCAAiC;AAC9C,YAAM,IAAI,MAAM,uCAAuC,MAAM,EAAE;AAAA,IACjE;AAEA,UAAM,SAAS,KAAK,OAAO,cAAc,GAAG,KAAK,CAAC;AAElD,UAAM,UAAU,OACb,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,QAAQ,EAAE;AAErB,WAAO,kCAAkC;AAAA,EAC3C;AAAA,EAEA,MAAM,OAAO,WAAwC;AACnD,QAAI,CAAC,UAAU,WAAW,+BAA+B,GAAG;AAC1D,YAAM,IAAI,MAAM,uCAAuC,UAAU,CAAC,CAAC,EAAE;AAAA,IACvE;AACA,gBAAY,UAAU,MAAM,CAAC;AAE7B,QAAI,SAAS,UAAU,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AAE3D,WAAO,OAAO,SAAS,MAAM,EAAG,WAAU;AAE1C,WAAO,WAAW,KAAK,KAAK,MAAM,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAAA,EAC7D;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,45 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import {
3
+ CONTENT_ADDRESS_METHOD_SHA256,
4
+ ContentAddresses
5
+ } from "./2-content-addresses";
6
+ import { randomBytes } from "@noble/hashes/utils.js";
7
+ function contentAddressesTests() {
8
+ describe("Content Address Tests", () => {
9
+ const contentAddressMethods = [CONTENT_ADDRESS_METHOD_SHA256];
10
+ const contentAddresses = new ContentAddresses();
11
+ test("Invalid content address method", async () => {
12
+ const bytes = randomBytes();
13
+ await expect(
14
+ () => contentAddresses.register("invalid-method", bytes)
15
+ ).rejects.toThrow();
16
+ });
17
+ for (const method of contentAddressMethods) {
18
+ describe(`Content Address Method: ${method}`, () => {
19
+ test("idempotent addresses", async () => {
20
+ const bytes = randomBytes();
21
+ const address1 = await contentAddresses.register(method, bytes);
22
+ const address2 = await contentAddresses.register(method, bytes);
23
+ expect(address1).toEqual(address2);
24
+ });
25
+ test("unique adddresses", async () => {
26
+ const bytes1 = randomBytes();
27
+ const bytes2 = randomBytes();
28
+ const address1 = await contentAddresses.register(method, bytes1);
29
+ const address2 = await contentAddresses.register(method, bytes2);
30
+ expect(address1).not.toEqual(address2);
31
+ });
32
+ test("get method", async () => {
33
+ const bytes = randomBytes();
34
+ const address = await contentAddresses.register(method, bytes);
35
+ const retrievedMethod = await contentAddresses.getMethod(address);
36
+ expect(retrievedMethod).toEqual(method);
37
+ });
38
+ });
39
+ }
40
+ });
41
+ }
42
+ export {
43
+ contentAddressesTests
44
+ };
45
+ //# sourceMappingURL=2-content-addresses-tests.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/2-primitives/2-content-addresses-tests.ts"],
4
+ "sourcesContent": ["import { describe, expect, test } from \"vitest\";\nimport {\n CONTENT_ADDRESS_METHOD_SHA256,\n ContentAddresses,\n} from \"./2-content-addresses\";\nimport { randomBytes } from \"@noble/hashes/utils.js\";\n\nexport function contentAddressesTests() {\n describe(\"Content Address Tests\", () => {\n const contentAddressMethods = [CONTENT_ADDRESS_METHOD_SHA256];\n const contentAddresses = new ContentAddresses();\n\n test(\"Invalid content address method\", async () => {\n const bytes = randomBytes();\n await expect(() =>\n contentAddresses.register(\"invalid-method\", bytes),\n ).rejects.toThrow();\n });\n\n for (const method of contentAddressMethods) {\n describe(`Content Address Method: ${method}`, () => {\n test(\"idempotent addresses\", async () => {\n const bytes = randomBytes();\n const address1 = await contentAddresses.register(method, bytes);\n const address2 = await contentAddresses.register(method, bytes);\n expect(address1).toEqual(address2);\n });\n\n test(\"unique adddresses\", async () => {\n const bytes1 = randomBytes();\n const bytes2 = randomBytes();\n const address1 = await contentAddresses.register(method, bytes1);\n const address2 = await contentAddresses.register(method, bytes2);\n expect(address1).not.toEqual(address2);\n });\n\n test(\"get method\", async () => {\n const bytes = randomBytes();\n const address = await contentAddresses.register(method, bytes);\n const retrievedMethod = await contentAddresses.getMethod(address);\n expect(retrievedMethod).toEqual(method);\n });\n });\n }\n });\n}\n"],
5
+ "mappings": "AAAA,SAAS,UAAU,QAAQ,YAAY;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;AAErB,SAAS,wBAAwB;AACtC,WAAS,yBAAyB,MAAM;AACtC,UAAM,wBAAwB,CAAC,6BAA6B;AAC5D,UAAM,mBAAmB,IAAI,iBAAiB;AAE9C,SAAK,kCAAkC,YAAY;AACjD,YAAM,QAAQ,YAAY;AAC1B,YAAM;AAAA,QAAO,MACX,iBAAiB,SAAS,kBAAkB,KAAK;AAAA,MACnD,EAAE,QAAQ,QAAQ;AAAA,IACpB,CAAC;AAED,eAAW,UAAU,uBAAuB;AAC1C,eAAS,2BAA2B,MAAM,IAAI,MAAM;AAClD,aAAK,wBAAwB,YAAY;AACvC,gBAAM,QAAQ,YAAY;AAC1B,gBAAM,WAAW,MAAM,iBAAiB,SAAS,QAAQ,KAAK;AAC9D,gBAAM,WAAW,MAAM,iBAAiB,SAAS,QAAQ,KAAK;AAC9D,iBAAO,QAAQ,EAAE,QAAQ,QAAQ;AAAA,QACnC,CAAC;AAED,aAAK,qBAAqB,YAAY;AACpC,gBAAM,SAAS,YAAY;AAC3B,gBAAM,SAAS,YAAY;AAC3B,gBAAM,WAAW,MAAM,iBAAiB,SAAS,QAAQ,MAAM;AAC/D,gBAAM,WAAW,MAAM,iBAAiB,SAAS,QAAQ,MAAM;AAC/D,iBAAO,QAAQ,EAAE,IAAI,QAAQ,QAAQ;AAAA,QACvC,CAAC;AAED,aAAK,cAAc,YAAY;AAC7B,gBAAM,QAAQ,YAAY;AAC1B,gBAAM,UAAU,MAAM,iBAAiB,SAAS,QAAQ,KAAK;AAC7D,gBAAM,kBAAkB,MAAM,iBAAiB,UAAU,OAAO;AAChE,iBAAO,eAAe,EAAE,QAAQ,MAAM;AAAA,QACxC,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -0,0 +1,33 @@
1
+ import { sha256 } from "@noble/hashes/webcrypto.js";
2
+ const CONTENT_ADDRESS_METHOD_SHA256 = "sha2-256";
3
+ const MULTIHASH_CODE_SHA256 = 18;
4
+ const MULTIHASH_LENGTH_SHA256 = 32;
5
+ class ContentAddresses {
6
+ async register(contentAddressMethod, data) {
7
+ if (contentAddressMethod !== CONTENT_ADDRESS_METHOD_SHA256) {
8
+ throw new Error(
9
+ `Unsupported content address method: ${contentAddressMethod}`
10
+ );
11
+ }
12
+ const hash = await sha256(data);
13
+ const prefixedHash = new Uint8Array(2 + hash.length);
14
+ prefixedHash[0] = MULTIHASH_CODE_SHA256;
15
+ prefixedHash[1] = MULTIHASH_LENGTH_SHA256;
16
+ prefixedHash.set(hash, 2);
17
+ return prefixedHash;
18
+ }
19
+ async getMethod(contentAddress) {
20
+ if (contentAddress[0] === MULTIHASH_CODE_SHA256 && contentAddress[1] === MULTIHASH_LENGTH_SHA256 && contentAddress.length === 2 + MULTIHASH_LENGTH_SHA256) {
21
+ return CONTENT_ADDRESS_METHOD_SHA256;
22
+ } else {
23
+ throw new Error(`Unrecognized content address format.`);
24
+ }
25
+ }
26
+ }
27
+ export {
28
+ CONTENT_ADDRESS_METHOD_SHA256,
29
+ ContentAddresses,
30
+ MULTIHASH_CODE_SHA256,
31
+ MULTIHASH_LENGTH_SHA256
32
+ };
33
+ //# sourceMappingURL=2-content-addresses.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/2-primitives/2-content-addresses.ts"],
4
+ "sourcesContent": ["import { sha256 } from \"@noble/hashes/webcrypto.js\";\n\nexport const CONTENT_ADDRESS_METHOD_SHA256 = \"sha2-256\";\n\n// Multihash code and length for SHA2-256\n// https://multiformats.io/multihash/#sha2-256---256-bits-aka-sha256\nexport const MULTIHASH_CODE_SHA256 = 0x12;\nexport const MULTIHASH_LENGTH_SHA256 = 32;\n\nexport class ContentAddresses {\n async register(\n contentAddressMethod: string,\n data: Uint8Array,\n ): Promise<Uint8Array> {\n if (contentAddressMethod !== CONTENT_ADDRESS_METHOD_SHA256) {\n throw new Error(\n `Unsupported content address method: ${contentAddressMethod}`,\n );\n }\n\n const hash = await sha256(data);\n\n const prefixedHash = new Uint8Array(2 + hash.length);\n prefixedHash[0] = MULTIHASH_CODE_SHA256;\n prefixedHash[1] = MULTIHASH_LENGTH_SHA256;\n prefixedHash.set(hash, 2);\n\n return prefixedHash;\n }\n\n async getMethod(contentAddress: Uint8Array): Promise<string> {\n if (\n contentAddress[0] === MULTIHASH_CODE_SHA256 &&\n contentAddress[1] === MULTIHASH_LENGTH_SHA256 &&\n contentAddress.length === 2 + MULTIHASH_LENGTH_SHA256\n ) {\n return CONTENT_ADDRESS_METHOD_SHA256;\n } else {\n throw new Error(`Unrecognized content address format.`);\n }\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,cAAc;AAEhB,MAAM,gCAAgC;AAItC,MAAM,wBAAwB;AAC9B,MAAM,0BAA0B;AAEhC,MAAM,iBAAiB;AAAA,EAC5B,MAAM,SACJ,sBACA,MACqB;AACrB,QAAI,yBAAyB,+BAA+B;AAC1D,YAAM,IAAI;AAAA,QACR,uCAAuC,oBAAoB;AAAA,MAC7D;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,OAAO,IAAI;AAE9B,UAAM,eAAe,IAAI,WAAW,IAAI,KAAK,MAAM;AACnD,iBAAa,CAAC,IAAI;AAClB,iBAAa,CAAC,IAAI;AAClB,iBAAa,IAAI,MAAM,CAAC;AAExB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,gBAA6C;AAC3D,QACE,eAAe,CAAC,MAAM,yBACtB,eAAe,CAAC,MAAM,2BACtB,eAAe,WAAW,IAAI,yBAC9B;AACA,aAAO;AAAA,IACT,OAAO;AACL,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,116 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import {
3
+ CHANNEL_ATTESTATION_METHOD_SHA256_ED25519,
4
+ ChannelAttestations
5
+ } from "./3-channel-attestations";
6
+ import { randomBytes } from "@noble/hashes/utils.js";
7
+ import {
8
+ StringEncoder,
9
+ STRING_ENCODER_METHOD_BASE64URL
10
+ } from "./1-string-encoding";
11
+ function channelAttestationTests() {
12
+ describe("Channel Attestation Tests", () => {
13
+ const allowedAttestationMethods = [
14
+ CHANNEL_ATTESTATION_METHOD_SHA256_ED25519
15
+ ];
16
+ const channelAttestations = new ChannelAttestations();
17
+ async function randomActor() {
18
+ const bytes = randomBytes();
19
+ const str = await new StringEncoder().encode(
20
+ STRING_ENCODER_METHOD_BASE64URL,
21
+ bytes
22
+ );
23
+ return `did:web:${str}.com`;
24
+ }
25
+ async function randomChannel() {
26
+ const bytes = randomBytes();
27
+ return await new StringEncoder().encode(
28
+ STRING_ENCODER_METHOD_BASE64URL,
29
+ bytes
30
+ );
31
+ }
32
+ test("Invalid attestation method", async () => {
33
+ const actor = await randomActor();
34
+ await expect(
35
+ () => channelAttestations.register("invalid-method", actor)
36
+ ).rejects.toThrow();
37
+ });
38
+ for (const method of allowedAttestationMethods) {
39
+ describe(`Attestation Method: ${method}`, () => {
40
+ test("get method", async () => {
41
+ const channel = await randomChannel();
42
+ const publicId = await channelAttestations.register(method, channel);
43
+ const methodReturned = await channelAttestations.getMethod(publicId);
44
+ expect(methodReturned).toEqual(method);
45
+ });
46
+ test("Idempotent public Ids", async () => {
47
+ const channel = await randomChannel();
48
+ const publicId1 = await channelAttestations.register(method, channel);
49
+ const publicId2 = await channelAttestations.register(method, channel);
50
+ expect(publicId1).toEqual(publicId2);
51
+ });
52
+ test("Unique public ids", async () => {
53
+ const channel1 = await randomChannel();
54
+ const channel2 = await randomChannel();
55
+ const publicId1 = await channelAttestations.register(
56
+ method,
57
+ channel1
58
+ );
59
+ const publicId2 = await channelAttestations.register(
60
+ method,
61
+ channel2
62
+ );
63
+ expect(publicId1).not.toEqual(publicId2);
64
+ });
65
+ test("Valid attestation", async () => {
66
+ const actor = await randomActor();
67
+ const channel = await randomChannel();
68
+ const { attestation, channelPublicId } = await channelAttestations.attest(method, actor, channel);
69
+ const isValid = await channelAttestations.validate(
70
+ attestation,
71
+ actor,
72
+ channelPublicId
73
+ );
74
+ expect(isValid).toBe(true);
75
+ const channelPublicIdSeperate = await channelAttestations.register(
76
+ method,
77
+ channel
78
+ );
79
+ expect(channelPublicId).toEqual(channelPublicIdSeperate);
80
+ });
81
+ test("Invalid attestation with wrong actor", async () => {
82
+ const actor = await randomActor();
83
+ const wrongActor = await randomActor();
84
+ const channel = await randomChannel();
85
+ const { attestation, channelPublicId } = await channelAttestations.attest(method, actor, channel);
86
+ const isValid = await channelAttestations.validate(
87
+ attestation,
88
+ wrongActor,
89
+ channelPublicId
90
+ );
91
+ expect(isValid).toBe(false);
92
+ });
93
+ test("Invalid attestation with wrong channel", async () => {
94
+ const actor = await randomActor();
95
+ const channel = await randomChannel();
96
+ const wrongChannel = await randomChannel();
97
+ const { attestation, channelPublicId } = await channelAttestations.attest(method, actor, channel);
98
+ const wrongChannelPublicId = await channelAttestations.register(
99
+ method,
100
+ wrongChannel
101
+ );
102
+ const isValid = await channelAttestations.validate(
103
+ attestation,
104
+ actor,
105
+ wrongChannelPublicId
106
+ );
107
+ expect(isValid).toBe(false);
108
+ });
109
+ });
110
+ }
111
+ });
112
+ }
113
+ export {
114
+ channelAttestationTests
115
+ };
116
+ //# sourceMappingURL=3-channel-attestations-tests.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/2-primitives/3-channel-attestations-tests.ts"],
4
+ "sourcesContent": ["import { describe, expect, test } from \"vitest\";\nimport {\n CHANNEL_ATTESTATION_METHOD_SHA256_ED25519,\n ChannelAttestations,\n} from \"./3-channel-attestations\";\nimport { randomBytes } from \"@noble/hashes/utils.js\";\nimport {\n StringEncoder,\n STRING_ENCODER_METHOD_BASE64URL,\n} from \"./1-string-encoding\";\n\nexport function channelAttestationTests() {\n describe(\"Channel Attestation Tests\", () => {\n const allowedAttestationMethods = [\n CHANNEL_ATTESTATION_METHOD_SHA256_ED25519,\n ];\n const channelAttestations = new ChannelAttestations();\n\n async function randomActor() {\n const bytes = randomBytes();\n const str = await new StringEncoder().encode(\n STRING_ENCODER_METHOD_BASE64URL,\n bytes,\n );\n return `did:web:${str}.com`;\n }\n async function randomChannel() {\n const bytes = randomBytes();\n return await new StringEncoder().encode(\n STRING_ENCODER_METHOD_BASE64URL,\n bytes,\n );\n }\n\n test(\"Invalid attestation method\", async () => {\n const actor = await randomActor();\n await expect(() =>\n channelAttestations.register(\"invalid-method\", actor),\n ).rejects.toThrow();\n });\n\n for (const method of allowedAttestationMethods) {\n describe(`Attestation Method: ${method}`, () => {\n test(\"get method\", async () => {\n const channel = await randomChannel();\n const publicId = await channelAttestations.register(method, channel);\n const methodReturned = await channelAttestations.getMethod(publicId);\n expect(methodReturned).toEqual(method);\n });\n\n test(\"Idempotent public Ids\", async () => {\n const channel = await randomChannel();\n const publicId1 = await channelAttestations.register(method, channel);\n const publicId2 = await channelAttestations.register(method, channel);\n expect(publicId1).toEqual(publicId2);\n });\n\n test(\"Unique public ids\", async () => {\n const channel1 = await randomChannel();\n const channel2 = await randomChannel();\n const publicId1 = await channelAttestations.register(\n method,\n channel1,\n );\n const publicId2 = await channelAttestations.register(\n method,\n channel2,\n );\n expect(publicId1).not.toEqual(publicId2);\n });\n\n test(\"Valid attestation\", async () => {\n const actor = await randomActor();\n const channel = await randomChannel();\n const { attestation, channelPublicId } =\n await channelAttestations.attest(method, actor, channel);\n const isValid = await channelAttestations.validate(\n attestation,\n actor,\n channelPublicId,\n );\n expect(isValid).toBe(true);\n\n const channelPublicIdSeperate = await channelAttestations.register(\n method,\n channel,\n );\n expect(channelPublicId).toEqual(channelPublicIdSeperate);\n });\n\n test(\"Invalid attestation with wrong actor\", async () => {\n const actor = await randomActor();\n const wrongActor = await randomActor();\n const channel = await randomChannel();\n const { attestation, channelPublicId } =\n await channelAttestations.attest(method, actor, channel);\n const isValid = await channelAttestations.validate(\n attestation,\n wrongActor,\n channelPublicId,\n );\n expect(isValid).toBe(false);\n });\n\n test(\"Invalid attestation with wrong channel\", async () => {\n const actor = await randomActor();\n const channel = await randomChannel();\n const wrongChannel = await randomChannel();\n const { attestation, channelPublicId } =\n await channelAttestations.attest(method, actor, channel);\n const wrongChannelPublicId = await channelAttestations.register(\n method,\n wrongChannel,\n );\n const isValid = await channelAttestations.validate(\n attestation,\n actor,\n wrongChannelPublicId,\n );\n expect(isValid).toBe(false);\n });\n });\n }\n });\n}\n"],
5
+ "mappings": "AAAA,SAAS,UAAU,QAAQ,YAAY;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEA,SAAS,0BAA0B;AACxC,WAAS,6BAA6B,MAAM;AAC1C,UAAM,4BAA4B;AAAA,MAChC;AAAA,IACF;AACA,UAAM,sBAAsB,IAAI,oBAAoB;AAEpD,mBAAe,cAAc;AAC3B,YAAM,QAAQ,YAAY;AAC1B,YAAM,MAAM,MAAM,IAAI,cAAc,EAAE;AAAA,QACpC;AAAA,QACA;AAAA,MACF;AACA,aAAO,WAAW,GAAG;AAAA,IACvB;AACA,mBAAe,gBAAgB;AAC7B,YAAM,QAAQ,YAAY;AAC1B,aAAO,MAAM,IAAI,cAAc,EAAE;AAAA,QAC/B;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,SAAK,8BAA8B,YAAY;AAC7C,YAAM,QAAQ,MAAM,YAAY;AAChC,YAAM;AAAA,QAAO,MACX,oBAAoB,SAAS,kBAAkB,KAAK;AAAA,MACtD,EAAE,QAAQ,QAAQ;AAAA,IACpB,CAAC;AAED,eAAW,UAAU,2BAA2B;AAC9C,eAAS,uBAAuB,MAAM,IAAI,MAAM;AAC9C,aAAK,cAAc,YAAY;AAC7B,gBAAM,UAAU,MAAM,cAAc;AACpC,gBAAM,WAAW,MAAM,oBAAoB,SAAS,QAAQ,OAAO;AACnE,gBAAM,iBAAiB,MAAM,oBAAoB,UAAU,QAAQ;AACnE,iBAAO,cAAc,EAAE,QAAQ,MAAM;AAAA,QACvC,CAAC;AAED,aAAK,yBAAyB,YAAY;AACxC,gBAAM,UAAU,MAAM,cAAc;AACpC,gBAAM,YAAY,MAAM,oBAAoB,SAAS,QAAQ,OAAO;AACpE,gBAAM,YAAY,MAAM,oBAAoB,SAAS,QAAQ,OAAO;AACpE,iBAAO,SAAS,EAAE,QAAQ,SAAS;AAAA,QACrC,CAAC;AAED,aAAK,qBAAqB,YAAY;AACpC,gBAAM,WAAW,MAAM,cAAc;AACrC,gBAAM,WAAW,MAAM,cAAc;AACrC,gBAAM,YAAY,MAAM,oBAAoB;AAAA,YAC1C;AAAA,YACA;AAAA,UACF;AACA,gBAAM,YAAY,MAAM,oBAAoB;AAAA,YAC1C;AAAA,YACA;AAAA,UACF;AACA,iBAAO,SAAS,EAAE,IAAI,QAAQ,SAAS;AAAA,QACzC,CAAC;AAED,aAAK,qBAAqB,YAAY;AACpC,gBAAM,QAAQ,MAAM,YAAY;AAChC,gBAAM,UAAU,MAAM,cAAc;AACpC,gBAAM,EAAE,aAAa,gBAAgB,IACnC,MAAM,oBAAoB,OAAO,QAAQ,OAAO,OAAO;AACzD,gBAAM,UAAU,MAAM,oBAAoB;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,iBAAO,OAAO,EAAE,KAAK,IAAI;AAEzB,gBAAM,0BAA0B,MAAM,oBAAoB;AAAA,YACxD;AAAA,YACA;AAAA,UACF;AACA,iBAAO,eAAe,EAAE,QAAQ,uBAAuB;AAAA,QACzD,CAAC;AAED,aAAK,wCAAwC,YAAY;AACvD,gBAAM,QAAQ,MAAM,YAAY;AAChC,gBAAM,aAAa,MAAM,YAAY;AACrC,gBAAM,UAAU,MAAM,cAAc;AACpC,gBAAM,EAAE,aAAa,gBAAgB,IACnC,MAAM,oBAAoB,OAAO,QAAQ,OAAO,OAAO;AACzD,gBAAM,UAAU,MAAM,oBAAoB;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,iBAAO,OAAO,EAAE,KAAK,KAAK;AAAA,QAC5B,CAAC;AAED,aAAK,0CAA0C,YAAY;AACzD,gBAAM,QAAQ,MAAM,YAAY;AAChC,gBAAM,UAAU,MAAM,cAAc;AACpC,gBAAM,eAAe,MAAM,cAAc;AACzC,gBAAM,EAAE,aAAa,gBAAgB,IACnC,MAAM,oBAAoB,OAAO,QAAQ,OAAO,OAAO;AACzD,gBAAM,uBAAuB,MAAM,oBAAoB;AAAA,YACrD;AAAA,YACA;AAAA,UACF;AACA,gBAAM,UAAU,MAAM,oBAAoB;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,iBAAO,OAAO,EAAE,KAAK,KAAK;AAAA,QAC5B,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -0,0 +1,69 @@
1
+ import {
2
+ getPublicKeyAsync,
3
+ signAsync,
4
+ verifyAsync,
5
+ hashes
6
+ } from "@noble/ed25519";
7
+ import { sha256, sha512 } from "@noble/hashes/webcrypto.js";
8
+ hashes.sha512Async = sha512;
9
+ const CHANNEL_ATTESTATION_METHOD_SHA256_ED25519 = "pk:sha2-256+ed25519";
10
+ const CHANNEL_ATTESTATION_METHOD_PREFIX_SHA256_ED25519 = 0;
11
+ class ChannelAttestations {
12
+ async register(channelAttestationMethod, channel) {
13
+ if (channelAttestationMethod !== CHANNEL_ATTESTATION_METHOD_SHA256_ED25519) {
14
+ throw new Error(
15
+ `Unsupported channel attestation method: ${channelAttestationMethod}`
16
+ );
17
+ }
18
+ const privateKey = await this.channelToPrivateKey(channel);
19
+ return await this.channelPublicIdFromPrivateKey(privateKey);
20
+ }
21
+ async getMethod(channelPublicId) {
22
+ if (channelPublicId[0] === CHANNEL_ATTESTATION_METHOD_PREFIX_SHA256_ED25519) {
23
+ return CHANNEL_ATTESTATION_METHOD_SHA256_ED25519;
24
+ } else {
25
+ throw new Error(`Unrecognized channel attestation method.`);
26
+ }
27
+ }
28
+ async channelToPrivateKey(channel) {
29
+ const channelBytes = new TextEncoder().encode(channel);
30
+ return await sha256(channelBytes);
31
+ }
32
+ async channelPublicIdFromPrivateKey(privateKey) {
33
+ const channelPublicIdRaw = await getPublicKeyAsync(privateKey);
34
+ const channelPublicId = new Uint8Array(channelPublicIdRaw.length + 1);
35
+ channelPublicId[0] = CHANNEL_ATTESTATION_METHOD_PREFIX_SHA256_ED25519;
36
+ channelPublicId.set(channelPublicIdRaw, 1);
37
+ return channelPublicId;
38
+ }
39
+ async attest(channelAttestationMethod, actor, channel) {
40
+ if (channelAttestationMethod !== CHANNEL_ATTESTATION_METHOD_SHA256_ED25519) {
41
+ throw new Error(
42
+ `Unsupported channel attestation method: ${channelAttestationMethod}`
43
+ );
44
+ }
45
+ const privateKey = await this.channelToPrivateKey(channel);
46
+ const channelPublicId = await this.channelPublicIdFromPrivateKey(privateKey);
47
+ const actorBytes = new TextEncoder().encode(actor);
48
+ const attestation = await signAsync(actorBytes, privateKey);
49
+ return { attestation, channelPublicId };
50
+ }
51
+ async validate(attestation, actor, channelPublicId) {
52
+ const prefix = channelPublicId[0];
53
+ if (prefix !== CHANNEL_ATTESTATION_METHOD_PREFIX_SHA256_ED25519) {
54
+ throw new Error(
55
+ `Unrecognized channel attestation method prefix: ${prefix}`
56
+ );
57
+ }
58
+ return await verifyAsync(
59
+ attestation,
60
+ new TextEncoder().encode(actor),
61
+ channelPublicId.slice(1)
62
+ );
63
+ }
64
+ }
65
+ export {
66
+ CHANNEL_ATTESTATION_METHOD_SHA256_ED25519,
67
+ ChannelAttestations
68
+ };
69
+ //# sourceMappingURL=3-channel-attestations.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/2-primitives/3-channel-attestations.ts"],
4
+ "sourcesContent": ["import {\n getPublicKeyAsync,\n signAsync,\n verifyAsync,\n hashes,\n} from \"@noble/ed25519\";\nimport { sha256, sha512 } from \"@noble/hashes/webcrypto.js\";\nhashes.sha512Async = sha512;\n\nexport const CHANNEL_ATTESTATION_METHOD_SHA256_ED25519 = \"pk:sha2-256+ed25519\";\nconst CHANNEL_ATTESTATION_METHOD_PREFIX_SHA256_ED25519 = 0;\n\nexport class ChannelAttestations {\n async register(\n channelAttestationMethod: string,\n channel: string,\n ): Promise<Uint8Array> {\n if (\n channelAttestationMethod !== CHANNEL_ATTESTATION_METHOD_SHA256_ED25519\n ) {\n throw new Error(\n `Unsupported channel attestation method: ${channelAttestationMethod}`,\n );\n }\n const privateKey = await this.channelToPrivateKey(channel);\n return await this.channelPublicIdFromPrivateKey(privateKey);\n }\n\n async getMethod(channelPublicId: Uint8Array): Promise<string> {\n if (\n channelPublicId[0] === CHANNEL_ATTESTATION_METHOD_PREFIX_SHA256_ED25519\n ) {\n return CHANNEL_ATTESTATION_METHOD_SHA256_ED25519;\n } else {\n throw new Error(`Unrecognized channel attestation method.`);\n }\n }\n\n protected async channelToPrivateKey(channel: string): Promise<Uint8Array> {\n const channelBytes = new TextEncoder().encode(channel);\n return await sha256(channelBytes);\n }\n protected async channelPublicIdFromPrivateKey(\n privateKey: Uint8Array,\n ): Promise<Uint8Array> {\n const channelPublicIdRaw = await getPublicKeyAsync(privateKey);\n const channelPublicId = new Uint8Array(channelPublicIdRaw.length + 1);\n channelPublicId[0] = CHANNEL_ATTESTATION_METHOD_PREFIX_SHA256_ED25519;\n channelPublicId.set(channelPublicIdRaw, 1);\n return channelPublicId;\n }\n\n async attest(\n channelAttestationMethod: string,\n actor: string,\n channel: string,\n ): Promise<{\n attestation: Uint8Array;\n channelPublicId: Uint8Array;\n }> {\n if (\n channelAttestationMethod !== CHANNEL_ATTESTATION_METHOD_SHA256_ED25519\n ) {\n throw new Error(\n `Unsupported channel attestation method: ${channelAttestationMethod}`,\n );\n }\n const privateKey = await this.channelToPrivateKey(channel);\n const channelPublicId =\n await this.channelPublicIdFromPrivateKey(privateKey);\n\n const actorBytes = new TextEncoder().encode(actor);\n const attestation = await signAsync(actorBytes, privateKey);\n return { attestation, channelPublicId };\n }\n\n async validate(\n attestation: Uint8Array,\n actor: string,\n channelPublicId: Uint8Array,\n ): Promise<boolean> {\n const prefix = channelPublicId[0];\n if (prefix !== CHANNEL_ATTESTATION_METHOD_PREFIX_SHA256_ED25519) {\n throw new Error(\n `Unrecognized channel attestation method prefix: ${prefix}`,\n );\n }\n\n return await verifyAsync(\n attestation,\n new TextEncoder().encode(actor),\n channelPublicId.slice(1),\n );\n }\n}\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,QAAQ,cAAc;AAC/B,OAAO,cAAc;AAEd,MAAM,4CAA4C;AACzD,MAAM,mDAAmD;AAElD,MAAM,oBAAoB;AAAA,EAC/B,MAAM,SACJ,0BACA,SACqB;AACrB,QACE,6BAA6B,2CAC7B;AACA,YAAM,IAAI;AAAA,QACR,2CAA2C,wBAAwB;AAAA,MACrE;AAAA,IACF;AACA,UAAM,aAAa,MAAM,KAAK,oBAAoB,OAAO;AACzD,WAAO,MAAM,KAAK,8BAA8B,UAAU;AAAA,EAC5D;AAAA,EAEA,MAAM,UAAU,iBAA8C;AAC5D,QACE,gBAAgB,CAAC,MAAM,kDACvB;AACA,aAAO;AAAA,IACT,OAAO;AACL,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAAA,EACF;AAAA,EAEA,MAAgB,oBAAoB,SAAsC;AACxE,UAAM,eAAe,IAAI,YAAY,EAAE,OAAO,OAAO;AACrD,WAAO,MAAM,OAAO,YAAY;AAAA,EAClC;AAAA,EACA,MAAgB,8BACd,YACqB;AACrB,UAAM,qBAAqB,MAAM,kBAAkB,UAAU;AAC7D,UAAM,kBAAkB,IAAI,WAAW,mBAAmB,SAAS,CAAC;AACpE,oBAAgB,CAAC,IAAI;AACrB,oBAAgB,IAAI,oBAAoB,CAAC;AACzC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OACJ,0BACA,OACA,SAIC;AACD,QACE,6BAA6B,2CAC7B;AACA,YAAM,IAAI;AAAA,QACR,2CAA2C,wBAAwB;AAAA,MACrE;AAAA,IACF;AACA,UAAM,aAAa,MAAM,KAAK,oBAAoB,OAAO;AACzD,UAAM,kBACJ,MAAM,KAAK,8BAA8B,UAAU;AAErD,UAAM,aAAa,IAAI,YAAY,EAAE,OAAO,KAAK;AACjD,UAAM,cAAc,MAAM,UAAU,YAAY,UAAU;AAC1D,WAAO,EAAE,aAAa,gBAAgB;AAAA,EACxC;AAAA,EAEA,MAAM,SACJ,aACA,OACA,iBACkB;AAClB,UAAM,SAAS,gBAAgB,CAAC;AAChC,QAAI,WAAW,kDAAkD;AAC/D,YAAM,IAAI;AAAA,QACR,mDAAmD,MAAM;AAAA,MAC3D;AAAA,IACF;AAEA,WAAO,MAAM;AAAA,MACX;AAAA,MACA,IAAI,YAAY,EAAE,OAAO,KAAK;AAAA,MAC9B,gBAAgB,MAAM,CAAC;AAAA,IACzB;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,82 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import {
3
+ ALLOWED_ATTESTATION_METHOD_HMAC_SHA256,
4
+ AllowedAttestations
5
+ } from "./4-allowed-attestations";
6
+ import { randomBytes } from "@noble/hashes/utils.js";
7
+ import {
8
+ StringEncoder,
9
+ STRING_ENCODER_METHOD_BASE64URL
10
+ } from "./1-string-encoding";
11
+ function allowedAttestationTests() {
12
+ describe("Allowed Attestation Tests", () => {
13
+ const allowedAttestationMethods = [ALLOWED_ATTESTATION_METHOD_HMAC_SHA256];
14
+ const allowedAttestations = new AllowedAttestations();
15
+ async function randomActor() {
16
+ const bytes = randomBytes();
17
+ const str = await new StringEncoder().encode(
18
+ STRING_ENCODER_METHOD_BASE64URL,
19
+ bytes
20
+ );
21
+ return `did:web:${str}.com`;
22
+ }
23
+ test("Invalid attestation method", async () => {
24
+ const actor = await randomActor();
25
+ await expect(
26
+ () => allowedAttestations.attest("invalid-method", actor)
27
+ ).rejects.toThrow();
28
+ });
29
+ for (const method of allowedAttestationMethods) {
30
+ describe(`Attestation Method: ${method}`, () => {
31
+ test("Valid attestation", async () => {
32
+ const actor = await randomActor();
33
+ const { attestation, ticket } = await allowedAttestations.attest(
34
+ method,
35
+ actor
36
+ );
37
+ const isValid = await allowedAttestations.validate(
38
+ attestation,
39
+ actor,
40
+ ticket
41
+ );
42
+ expect(isValid).toBe(true);
43
+ });
44
+ test("Wrong actor", async () => {
45
+ const actor = await randomActor();
46
+ const { attestation, ticket } = await allowedAttestations.attest(
47
+ method,
48
+ actor
49
+ );
50
+ const otherActor = await randomActor();
51
+ const isValid = await allowedAttestations.validate(
52
+ attestation,
53
+ otherActor,
54
+ ticket
55
+ );
56
+ expect(isValid).toBe(false);
57
+ });
58
+ test("Wrong ticket", async () => {
59
+ const actor = await randomActor();
60
+ const { attestation: attestation1, ticket: ticket1 } = await allowedAttestations.attest(method, actor);
61
+ const { attestation: attestation2, ticket: ticket2 } = await allowedAttestations.attest(method, actor);
62
+ const isValid1 = await allowedAttestations.validate(
63
+ attestation1,
64
+ actor,
65
+ ticket2
66
+ );
67
+ const isValid2 = await allowedAttestations.validate(
68
+ attestation2,
69
+ actor,
70
+ ticket1
71
+ );
72
+ expect(isValid1).toBe(false);
73
+ expect(isValid2).toBe(false);
74
+ });
75
+ });
76
+ }
77
+ });
78
+ }
79
+ export {
80
+ allowedAttestationTests
81
+ };
82
+ //# sourceMappingURL=4-allowed-attestations-tests.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/2-primitives/4-allowed-attestations-tests.ts"],
4
+ "sourcesContent": ["import { describe, expect, test } from \"vitest\";\nimport {\n ALLOWED_ATTESTATION_METHOD_HMAC_SHA256,\n AllowedAttestations,\n} from \"./4-allowed-attestations\";\nimport { randomBytes } from \"@noble/hashes/utils.js\";\nimport {\n StringEncoder,\n STRING_ENCODER_METHOD_BASE64URL,\n} from \"./1-string-encoding\";\n\nexport function allowedAttestationTests() {\n describe(\"Allowed Attestation Tests\", () => {\n const allowedAttestationMethods = [ALLOWED_ATTESTATION_METHOD_HMAC_SHA256];\n const allowedAttestations = new AllowedAttestations();\n\n async function randomActor() {\n const bytes = randomBytes();\n const str = await new StringEncoder().encode(\n STRING_ENCODER_METHOD_BASE64URL,\n bytes,\n );\n return `did:web:${str}.com`;\n }\n\n test(\"Invalid attestation method\", async () => {\n const actor = await randomActor();\n await expect(() =>\n allowedAttestations.attest(\"invalid-method\", actor),\n ).rejects.toThrow();\n });\n\n for (const method of allowedAttestationMethods) {\n describe(`Attestation Method: ${method}`, () => {\n test(\"Valid attestation\", async () => {\n const actor = await randomActor();\n const { attestation, ticket } = await allowedAttestations.attest(\n method,\n actor,\n );\n const isValid = await allowedAttestations.validate(\n attestation,\n actor,\n ticket,\n );\n expect(isValid).toBe(true);\n });\n\n test(\"Wrong actor\", async () => {\n const actor = await randomActor();\n const { attestation, ticket } = await allowedAttestations.attest(\n method,\n actor,\n );\n const otherActor = await randomActor();\n const isValid = await allowedAttestations.validate(\n attestation,\n otherActor,\n ticket,\n );\n expect(isValid).toBe(false);\n });\n\n test(\"Wrong ticket\", async () => {\n const actor = await randomActor();\n const { attestation: attestation1, ticket: ticket1 } =\n await allowedAttestations.attest(method, actor);\n const { attestation: attestation2, ticket: ticket2 } =\n await allowedAttestations.attest(method, actor);\n const isValid1 = await allowedAttestations.validate(\n attestation1,\n actor,\n ticket2,\n );\n const isValid2 = await allowedAttestations.validate(\n attestation2,\n actor,\n ticket1,\n );\n expect(isValid1).toBe(false);\n expect(isValid2).toBe(false);\n });\n });\n }\n });\n}\n"],
5
+ "mappings": "AAAA,SAAS,UAAU,QAAQ,YAAY;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEA,SAAS,0BAA0B;AACxC,WAAS,6BAA6B,MAAM;AAC1C,UAAM,4BAA4B,CAAC,sCAAsC;AACzE,UAAM,sBAAsB,IAAI,oBAAoB;AAEpD,mBAAe,cAAc;AAC3B,YAAM,QAAQ,YAAY;AAC1B,YAAM,MAAM,MAAM,IAAI,cAAc,EAAE;AAAA,QACpC;AAAA,QACA;AAAA,MACF;AACA,aAAO,WAAW,GAAG;AAAA,IACvB;AAEA,SAAK,8BAA8B,YAAY;AAC7C,YAAM,QAAQ,MAAM,YAAY;AAChC,YAAM;AAAA,QAAO,MACX,oBAAoB,OAAO,kBAAkB,KAAK;AAAA,MACpD,EAAE,QAAQ,QAAQ;AAAA,IACpB,CAAC;AAED,eAAW,UAAU,2BAA2B;AAC9C,eAAS,uBAAuB,MAAM,IAAI,MAAM;AAC9C,aAAK,qBAAqB,YAAY;AACpC,gBAAM,QAAQ,MAAM,YAAY;AAChC,gBAAM,EAAE,aAAa,OAAO,IAAI,MAAM,oBAAoB;AAAA,YACxD;AAAA,YACA;AAAA,UACF;AACA,gBAAM,UAAU,MAAM,oBAAoB;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,iBAAO,OAAO,EAAE,KAAK,IAAI;AAAA,QAC3B,CAAC;AAED,aAAK,eAAe,YAAY;AAC9B,gBAAM,QAAQ,MAAM,YAAY;AAChC,gBAAM,EAAE,aAAa,OAAO,IAAI,MAAM,oBAAoB;AAAA,YACxD;AAAA,YACA;AAAA,UACF;AACA,gBAAM,aAAa,MAAM,YAAY;AACrC,gBAAM,UAAU,MAAM,oBAAoB;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,iBAAO,OAAO,EAAE,KAAK,KAAK;AAAA,QAC5B,CAAC;AAED,aAAK,gBAAgB,YAAY;AAC/B,gBAAM,QAAQ,MAAM,YAAY;AAChC,gBAAM,EAAE,aAAa,cAAc,QAAQ,QAAQ,IACjD,MAAM,oBAAoB,OAAO,QAAQ,KAAK;AAChD,gBAAM,EAAE,aAAa,cAAc,QAAQ,QAAQ,IACjD,MAAM,oBAAoB,OAAO,QAAQ,KAAK;AAChD,gBAAM,WAAW,MAAM,oBAAoB;AAAA,YACzC;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,gBAAM,WAAW,MAAM,oBAAoB;AAAA,YACzC;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,iBAAO,QAAQ,EAAE,KAAK,KAAK;AAC3B,iBAAO,QAAQ,EAAE,KAAK,KAAK;AAAA,QAC7B,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -0,0 +1,51 @@
1
+ import { sha256, hmac } from "@noble/hashes/webcrypto.js";
2
+ import { randomBytes } from "@noble/hashes/utils.js";
3
+ import {
4
+ MULTIHASH_CODE_SHA256,
5
+ MULTIHASH_LENGTH_SHA256
6
+ } from "./2-content-addresses";
7
+ const ALLOWED_ATTESTATION_METHOD_HMAC_SHA256 = "hmac:sha2-256";
8
+ const ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC = 0;
9
+ class AllowedAttestations {
10
+ async attest(allowedAttestationMethod, actor) {
11
+ if (allowedAttestationMethod !== ALLOWED_ATTESTATION_METHOD_HMAC_SHA256) {
12
+ throw new Error(
13
+ `Unsupported allowed attestation method: ${allowedAttestationMethod}`
14
+ );
15
+ }
16
+ const ticket = randomBytes();
17
+ const attestation = await hmac(
18
+ sha256,
19
+ ticket,
20
+ new TextEncoder().encode(actor)
21
+ );
22
+ const prefixedTicket = new Uint8Array(ticket.length + 3);
23
+ prefixedTicket[0] = ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC;
24
+ prefixedTicket[1] = MULTIHASH_CODE_SHA256;
25
+ prefixedTicket[2] = MULTIHASH_LENGTH_SHA256;
26
+ prefixedTicket.set(ticket, 3);
27
+ return { attestation, ticket: prefixedTicket };
28
+ }
29
+ async validate(attestation, actor, ticket) {
30
+ const typePrefix = ticket[0];
31
+ const hashPrefix = ticket[1];
32
+ const lengthPrefix = ticket[2];
33
+ if (typePrefix !== ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC || hashPrefix !== MULTIHASH_CODE_SHA256 || lengthPrefix !== MULTIHASH_LENGTH_SHA256) {
34
+ throw new Error(`Unrecognized allowed ticket format`);
35
+ }
36
+ const expected = await hmac(
37
+ sha256,
38
+ ticket.slice(3),
39
+ new TextEncoder().encode(actor)
40
+ );
41
+ if (attestation.length !== expected.length) {
42
+ return false;
43
+ }
44
+ return expected.every((b, i) => attestation[i] === b);
45
+ }
46
+ }
47
+ export {
48
+ ALLOWED_ATTESTATION_METHOD_HMAC_SHA256,
49
+ AllowedAttestations
50
+ };
51
+ //# sourceMappingURL=4-allowed-attestations.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/2-primitives/4-allowed-attestations.ts"],
4
+ "sourcesContent": ["import { sha256, hmac } from \"@noble/hashes/webcrypto.js\";\nimport { randomBytes } from \"@noble/hashes/utils.js\";\nimport {\n MULTIHASH_CODE_SHA256,\n MULTIHASH_LENGTH_SHA256,\n} from \"./2-content-addresses\";\n\nexport const ALLOWED_ATTESTATION_METHOD_HMAC_SHA256 = \"hmac:sha2-256\";\nconst ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC = 0;\n\nexport class AllowedAttestations {\n async attest(\n allowedAttestationMethod: string,\n actor: string,\n ): Promise<{\n attestation: Uint8Array;\n ticket: Uint8Array;\n }> {\n if (allowedAttestationMethod !== ALLOWED_ATTESTATION_METHOD_HMAC_SHA256) {\n throw new Error(\n `Unsupported allowed attestation method: ${allowedAttestationMethod}`,\n );\n }\n\n const ticket = randomBytes();\n const attestation = await hmac(\n sha256,\n ticket,\n new TextEncoder().encode(actor),\n );\n\n const prefixedTicket = new Uint8Array(ticket.length + 3);\n prefixedTicket[0] = ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC;\n prefixedTicket[1] = MULTIHASH_CODE_SHA256;\n prefixedTicket[2] = MULTIHASH_LENGTH_SHA256;\n prefixedTicket.set(ticket, 3);\n\n return { attestation, ticket: prefixedTicket };\n }\n\n async validate(\n attestation: Uint8Array,\n actor: string,\n ticket: Uint8Array,\n ): Promise<boolean> {\n const typePrefix = ticket[0];\n const hashPrefix = ticket[1];\n const lengthPrefix = ticket[2];\n if (\n typePrefix !== ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC ||\n hashPrefix !== MULTIHASH_CODE_SHA256 ||\n lengthPrefix !== MULTIHASH_LENGTH_SHA256\n ) {\n throw new Error(`Unrecognized allowed ticket format`);\n }\n\n const expected = await hmac(\n sha256,\n ticket.slice(3),\n new TextEncoder().encode(actor),\n );\n\n // Make sure the bytes are exactly equal\n if (attestation.length !== expected.length) {\n return false;\n }\n return expected.every((b, i) => attestation[i] === b);\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,QAAQ,YAAY;AAC7B,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEA,MAAM,yCAAyC;AACtD,MAAM,yCAAyC;AAExC,MAAM,oBAAoB;AAAA,EAC/B,MAAM,OACJ,0BACA,OAIC;AACD,QAAI,6BAA6B,wCAAwC;AACvE,YAAM,IAAI;AAAA,QACR,2CAA2C,wBAAwB;AAAA,MACrE;AAAA,IACF;AAEA,UAAM,SAAS,YAAY;AAC3B,UAAM,cAAc,MAAM;AAAA,MACxB;AAAA,MACA;AAAA,MACA,IAAI,YAAY,EAAE,OAAO,KAAK;AAAA,IAChC;AAEA,UAAM,iBAAiB,IAAI,WAAW,OAAO,SAAS,CAAC;AACvD,mBAAe,CAAC,IAAI;AACpB,mBAAe,CAAC,IAAI;AACpB,mBAAe,CAAC,IAAI;AACpB,mBAAe,IAAI,QAAQ,CAAC;AAE5B,WAAO,EAAE,aAAa,QAAQ,eAAe;AAAA,EAC/C;AAAA,EAEA,MAAM,SACJ,aACA,OACA,QACkB;AAClB,UAAM,aAAa,OAAO,CAAC;AAC3B,UAAM,aAAa,OAAO,CAAC;AAC3B,UAAM,eAAe,OAAO,CAAC;AAC7B,QACE,eAAe,0CACf,eAAe,yBACf,iBAAiB,yBACjB;AACA,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AAEA,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA,OAAO,MAAM,CAAC;AAAA,MACd,IAAI,YAAY,EAAE,OAAO,KAAK;AAAA,IAChC;AAGA,QAAI,YAAY,WAAW,SAAS,QAAQ;AAC1C,aAAO;AAAA,IACT;AACA,WAAO,SAAS,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC;AAAA,EACtD;AACF;",
6
+ "names": []
7
+ }