@hashtree/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bep52.d.ts +179 -0
  3. package/dist/bep52.d.ts.map +1 -0
  4. package/dist/bep52.js +384 -0
  5. package/dist/bep52.js.map +1 -0
  6. package/dist/builder.d.ts +137 -0
  7. package/dist/builder.d.ts.map +1 -0
  8. package/dist/builder.js +281 -0
  9. package/dist/builder.js.map +1 -0
  10. package/dist/codec.d.ts +37 -0
  11. package/dist/codec.d.ts.map +1 -0
  12. package/dist/codec.js +109 -0
  13. package/dist/codec.js.map +1 -0
  14. package/dist/crypto.d.ts +92 -0
  15. package/dist/crypto.d.ts.map +1 -0
  16. package/dist/crypto.js +212 -0
  17. package/dist/crypto.js.map +1 -0
  18. package/dist/encrypted.d.ts +114 -0
  19. package/dist/encrypted.d.ts.map +1 -0
  20. package/dist/encrypted.js +446 -0
  21. package/dist/encrypted.js.map +1 -0
  22. package/dist/hash.d.ts +14 -0
  23. package/dist/hash.d.ts.map +1 -0
  24. package/dist/hash.js +27 -0
  25. package/dist/hash.js.map +1 -0
  26. package/dist/hashtree.d.ts +237 -0
  27. package/dist/hashtree.d.ts.map +1 -0
  28. package/dist/hashtree.js +557 -0
  29. package/dist/hashtree.js.map +1 -0
  30. package/dist/index.d.ts +27 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +44 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/nhash.d.ts +94 -0
  35. package/dist/nhash.d.ts.map +1 -0
  36. package/dist/nhash.js +293 -0
  37. package/dist/nhash.js.map +1 -0
  38. package/dist/resolver/index.d.ts +5 -0
  39. package/dist/resolver/index.d.ts.map +1 -0
  40. package/dist/resolver/index.js +5 -0
  41. package/dist/resolver/index.js.map +1 -0
  42. package/dist/resolver/nostr.d.ts +82 -0
  43. package/dist/resolver/nostr.d.ts.map +1 -0
  44. package/dist/resolver/nostr.js +868 -0
  45. package/dist/resolver/nostr.js.map +1 -0
  46. package/dist/store/blossom.d.ts +100 -0
  47. package/dist/store/blossom.d.ts.map +1 -0
  48. package/dist/store/blossom.js +355 -0
  49. package/dist/store/blossom.js.map +1 -0
  50. package/dist/store/dexie.d.ts +44 -0
  51. package/dist/store/dexie.d.ts.map +1 -0
  52. package/dist/store/dexie.js +196 -0
  53. package/dist/store/dexie.js.map +1 -0
  54. package/dist/store/fallback.d.ts +40 -0
  55. package/dist/store/fallback.d.ts.map +1 -0
  56. package/dist/store/fallback.js +71 -0
  57. package/dist/store/fallback.js.map +1 -0
  58. package/dist/store/index.d.ts +6 -0
  59. package/dist/store/index.d.ts.map +1 -0
  60. package/dist/store/index.js +6 -0
  61. package/dist/store/index.js.map +1 -0
  62. package/dist/store/memory.d.ts +29 -0
  63. package/dist/store/memory.d.ts.map +1 -0
  64. package/dist/store/memory.js +66 -0
  65. package/dist/store/memory.js.map +1 -0
  66. package/dist/store/opfs.d.ts +56 -0
  67. package/dist/store/opfs.d.ts.map +1 -0
  68. package/dist/store/opfs.js +200 -0
  69. package/dist/store/opfs.js.map +1 -0
  70. package/dist/streaming.d.ts +74 -0
  71. package/dist/streaming.d.ts.map +1 -0
  72. package/dist/streaming.js +199 -0
  73. package/dist/streaming.js.map +1 -0
  74. package/dist/tree/create.d.ts +35 -0
  75. package/dist/tree/create.d.ts.map +1 -0
  76. package/dist/tree/create.js +90 -0
  77. package/dist/tree/create.js.map +1 -0
  78. package/dist/tree/edit.d.ts +28 -0
  79. package/dist/tree/edit.d.ts.map +1 -0
  80. package/dist/tree/edit.js +115 -0
  81. package/dist/tree/edit.js.map +1 -0
  82. package/dist/tree/editEncrypted.d.ts +46 -0
  83. package/dist/tree/editEncrypted.d.ts.map +1 -0
  84. package/dist/tree/editEncrypted.js +225 -0
  85. package/dist/tree/editEncrypted.js.map +1 -0
  86. package/dist/tree/index.d.ts +7 -0
  87. package/dist/tree/index.d.ts.map +1 -0
  88. package/dist/tree/index.js +7 -0
  89. package/dist/tree/index.js.map +1 -0
  90. package/dist/tree/read.d.ts +75 -0
  91. package/dist/tree/read.d.ts.map +1 -0
  92. package/dist/tree/read.js +389 -0
  93. package/dist/tree/read.js.map +1 -0
  94. package/dist/tree/writeAt.d.ts +44 -0
  95. package/dist/tree/writeAt.d.ts.map +1 -0
  96. package/dist/tree/writeAt.js +282 -0
  97. package/dist/tree/writeAt.js.map +1 -0
  98. package/dist/types.d.ts +274 -0
  99. package/dist/types.d.ts.map +1 -0
  100. package/dist/types.js +47 -0
  101. package/dist/types.js.map +1 -0
  102. package/dist/verify.d.ts +12 -0
  103. package/dist/verify.d.ts.map +1 -0
  104. package/dist/verify.js +32 -0
  105. package/dist/verify.js.map +1 -0
  106. package/dist/visibility.d.ts +50 -0
  107. package/dist/visibility.d.ts.map +1 -0
  108. package/dist/visibility.js +111 -0
  109. package/dist/visibility.js.map +1 -0
  110. package/dist/webrtc/index.d.ts +4 -0
  111. package/dist/webrtc/index.d.ts.map +1 -0
  112. package/dist/webrtc/index.js +4 -0
  113. package/dist/webrtc/index.js.map +1 -0
  114. package/dist/webrtc/lruCache.d.ts +20 -0
  115. package/dist/webrtc/lruCache.d.ts.map +1 -0
  116. package/dist/webrtc/lruCache.js +59 -0
  117. package/dist/webrtc/lruCache.js.map +1 -0
  118. package/dist/webrtc/peer.d.ts +122 -0
  119. package/dist/webrtc/peer.d.ts.map +1 -0
  120. package/dist/webrtc/peer.js +583 -0
  121. package/dist/webrtc/peer.js.map +1 -0
  122. package/dist/webrtc/protocol.d.ts +76 -0
  123. package/dist/webrtc/protocol.d.ts.map +1 -0
  124. package/dist/webrtc/protocol.js +167 -0
  125. package/dist/webrtc/protocol.js.map +1 -0
  126. package/dist/webrtc/store.d.ts +190 -0
  127. package/dist/webrtc/store.d.ts.map +1 -0
  128. package/dist/webrtc/store.js +1043 -0
  129. package/dist/webrtc/store.js.map +1 -0
  130. package/dist/webrtc/types.d.ts +196 -0
  131. package/dist/webrtc/types.d.ts.map +1 -0
  132. package/dist/webrtc/types.js +46 -0
  133. package/dist/webrtc/types.js.map +1 -0
  134. package/dist/worker/protocol.d.ts +493 -0
  135. package/dist/worker/protocol.d.ts.map +1 -0
  136. package/dist/worker/protocol.js +15 -0
  137. package/dist/worker/protocol.js.map +1 -0
  138. package/package.json +59 -0
package/dist/verify.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Tree verification utilities
3
+ */
4
+ import { toHex } from './types.js';
5
+ import { tryDecodeTreeNode } from './codec.js';
6
+ /**
7
+ * Verify tree integrity - checks that all referenced hashes exist
8
+ */
9
+ export async function verifyTree(store, rootHash) {
10
+ const missing = [];
11
+ const visited = new Set();
12
+ async function check(hash) {
13
+ const hex = toHex(hash);
14
+ if (visited.has(hex))
15
+ return;
16
+ visited.add(hex);
17
+ const data = await store.get(hash);
18
+ if (!data) {
19
+ missing.push(hash);
20
+ return;
21
+ }
22
+ const node = tryDecodeTreeNode(data);
23
+ if (node) {
24
+ for (const link of node.links) {
25
+ await check(link.hash);
26
+ }
27
+ }
28
+ }
29
+ await check(rootHash);
30
+ return { valid: missing.length === 0, missing };
31
+ }
32
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAe,KAAK,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAAY,EACZ,QAAc;IAEd,MAAM,OAAO,GAAW,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,KAAK,UAAU,KAAK,CAAC,IAAU;QAC7B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEjB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC9B,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEtB,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;AAClD,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Tree visibility and encryption utilities
3
+ *
4
+ * ## Encryption Modes
5
+ *
6
+ * - **Unencrypted**: No CHK, just hash - anyone with hash can read
7
+ * - **Public**: CHK encrypted, ["key", "<hex>"] in event - anyone can decrypt
8
+ * - **Link-visible**: CHK + XOR mask, ["encryptedKey", XOR(key,secret)] - need #k=<secret> URL
9
+ * - **Private**: CHK + NIP-44 to self, ["selfEncryptedKey", "..."] - author only
10
+ *
11
+ * Default is Public (CHK encrypted, key in nostr event).
12
+ */
13
+ /**
14
+ * Tree visibility levels
15
+ */
16
+ export type TreeVisibility = 'public' | 'link-visible' | 'private';
17
+ /**
18
+ * Generate a random 32-byte link key for link-visible trees
19
+ */
20
+ export declare function generateLinkKey(): Uint8Array;
21
+ /**
22
+ * Compute keyId from link key (first 8 bytes of SHA-256 hash)
23
+ * Used to identify which link key was used without revealing the key
24
+ */
25
+ export declare function computeKeyId(linkKey: Uint8Array): Promise<Uint8Array>;
26
+ /**
27
+ * Encrypt a CHK key for link-visible visibility using XOR (one-time pad)
28
+ * @param chkKey - The CHK key to encrypt (32 bytes)
29
+ * @param linkKey - The link decryption key (32 bytes)
30
+ * @returns Encrypted key (32 bytes) - XOR of chkKey and linkKey
31
+ */
32
+ export declare function encryptKeyForLink(chkKey: Uint8Array, linkKey: Uint8Array): Uint8Array;
33
+ /**
34
+ * Decrypt a CHK key for link-visible visibility
35
+ * Supports both new XOR format (32 bytes) and legacy AES-GCM format (60 bytes)
36
+ * @param encryptedKey - Encrypted key (32 bytes for XOR, 60 bytes for AES-GCM)
37
+ * @param linkKey - The link decryption key (32 bytes)
38
+ * @returns Decrypted CHK key (32 bytes), or null if decryption fails
39
+ */
40
+ export declare function decryptKeyFromLink(encryptedKey: Uint8Array, linkKey: Uint8Array): Promise<Uint8Array | null>;
41
+ /**
42
+ * Hex string versions of the encryption functions for convenience
43
+ */
44
+ export declare const hex: {
45
+ generateLinkKey(): string;
46
+ computeKeyId(linkKeyHex: string): Promise<string>;
47
+ encryptKeyForLink(chkKeyHex: string, linkKeyHex: string): string;
48
+ decryptKeyFromLink(encryptedKeyHex: string, linkKeyHex: string): Promise<string | null>;
49
+ };
50
+ //# sourceMappingURL=visibility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../src/visibility.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,cAAc,GAAG,SAAS,CAAC;AAEnE;;GAEG;AACH,wBAAgB,eAAe,IAAI,UAAU,CAE5C;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAG3E;AA2CD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,CAErF;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAgBlH;AAED;;GAEG;AACH,eAAO,MAAM,GAAG;uBACK,MAAM;6BAIM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;iCAK1B,MAAM,cAAc,MAAM,GAAG,MAAM;wCAKtB,MAAM,cAAc,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAI9F,CAAC"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Tree visibility and encryption utilities
3
+ *
4
+ * ## Encryption Modes
5
+ *
6
+ * - **Unencrypted**: No CHK, just hash - anyone with hash can read
7
+ * - **Public**: CHK encrypted, ["key", "<hex>"] in event - anyone can decrypt
8
+ * - **Link-visible**: CHK + XOR mask, ["encryptedKey", XOR(key,secret)] - need #k=<secret> URL
9
+ * - **Private**: CHK + NIP-44 to self, ["selfEncryptedKey", "..."] - author only
10
+ *
11
+ * Default is Public (CHK encrypted, key in nostr event).
12
+ */
13
+ import { sha256 } from './hash.js';
14
+ import { toHex, fromHex } from './types.js';
15
+ /**
16
+ * Generate a random 32-byte link key for link-visible trees
17
+ */
18
+ export function generateLinkKey() {
19
+ return crypto.getRandomValues(new Uint8Array(32));
20
+ }
21
+ /**
22
+ * Compute keyId from link key (first 8 bytes of SHA-256 hash)
23
+ * Used to identify which link key was used without revealing the key
24
+ */
25
+ export async function computeKeyId(linkKey) {
26
+ const hash = await sha256(linkKey);
27
+ return hash.slice(0, 8);
28
+ }
29
+ /**
30
+ * XOR two 32-byte arrays
31
+ * Used for encrypting/decrypting CHK keys with link keys.
32
+ * XOR with random key is one-time pad (information-theoretically secure).
33
+ */
34
+ function xor32(a, b) {
35
+ const result = new Uint8Array(32);
36
+ for (let i = 0; i < 32; i++) {
37
+ result[i] = a[i] ^ b[i];
38
+ }
39
+ return result;
40
+ }
41
+ /**
42
+ * Legacy AES-GCM decryption for backward compatibility
43
+ * Old format: 12-byte nonce + ciphertext + 16-byte tag = 60 bytes total
44
+ */
45
+ async function decryptAesGcm(encryptedKey, linkKey) {
46
+ try {
47
+ const keyBuffer = new ArrayBuffer(linkKey.length);
48
+ new Uint8Array(keyBuffer).set(linkKey);
49
+ const nonce = encryptedKey.slice(0, 12);
50
+ const ciphertext = encryptedKey.slice(12);
51
+ const ciphertextBuffer = new ArrayBuffer(ciphertext.length);
52
+ new Uint8Array(ciphertextBuffer).set(ciphertext);
53
+ const cryptoKey = await crypto.subtle.importKey('raw', keyBuffer, { name: 'AES-GCM' }, false, ['decrypt']);
54
+ const plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: nonce }, cryptoKey, ciphertextBuffer);
55
+ return new Uint8Array(plaintext);
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ }
61
+ /**
62
+ * Encrypt a CHK key for link-visible visibility using XOR (one-time pad)
63
+ * @param chkKey - The CHK key to encrypt (32 bytes)
64
+ * @param linkKey - The link decryption key (32 bytes)
65
+ * @returns Encrypted key (32 bytes) - XOR of chkKey and linkKey
66
+ */
67
+ export function encryptKeyForLink(chkKey, linkKey) {
68
+ return xor32(chkKey, linkKey);
69
+ }
70
+ /**
71
+ * Decrypt a CHK key for link-visible visibility
72
+ * Supports both new XOR format (32 bytes) and legacy AES-GCM format (60 bytes)
73
+ * @param encryptedKey - Encrypted key (32 bytes for XOR, 60 bytes for AES-GCM)
74
+ * @param linkKey - The link decryption key (32 bytes)
75
+ * @returns Decrypted CHK key (32 bytes), or null if decryption fails
76
+ */
77
+ export async function decryptKeyFromLink(encryptedKey, linkKey) {
78
+ if (linkKey.length !== 32) {
79
+ return null;
80
+ }
81
+ // New XOR format: 32 bytes
82
+ if (encryptedKey.length === 32) {
83
+ return xor32(encryptedKey, linkKey);
84
+ }
85
+ // Legacy AES-GCM format: 60 bytes (12 nonce + 32 ciphertext + 16 tag)
86
+ if (encryptedKey.length === 60) {
87
+ return decryptAesGcm(encryptedKey, linkKey);
88
+ }
89
+ return null;
90
+ }
91
+ /**
92
+ * Hex string versions of the encryption functions for convenience
93
+ */
94
+ export const hex = {
95
+ generateLinkKey() {
96
+ return toHex(generateLinkKey());
97
+ },
98
+ async computeKeyId(linkKeyHex) {
99
+ const keyId = await computeKeyId(fromHex(linkKeyHex));
100
+ return toHex(keyId);
101
+ },
102
+ encryptKeyForLink(chkKeyHex, linkKeyHex) {
103
+ const encrypted = encryptKeyForLink(fromHex(chkKeyHex), fromHex(linkKeyHex));
104
+ return toHex(encrypted);
105
+ },
106
+ async decryptKeyFromLink(encryptedKeyHex, linkKeyHex) {
107
+ const decrypted = await decryptKeyFromLink(fromHex(encryptedKeyHex), fromHex(linkKeyHex));
108
+ return decrypted ? toHex(decrypted) : null;
109
+ },
110
+ };
111
+ //# sourceMappingURL=visibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visibility.js","sourceRoot":"","sources":["../src/visibility.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAO5C;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAmB;IACpD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,SAAS,KAAK,CAAC,CAAa,EAAE,CAAa;IACzC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,aAAa,CAAC,YAAwB,EAAE,OAAmB;IACxE,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEvC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,gBAAgB,GAAG,IAAI,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,UAAU,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAEjD,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAC7C,KAAK,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,CAC1D,CAAC;QAEF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAC3C,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAC5D,CAAC;QAEF,OAAO,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAkB,EAAE,OAAmB;IACvE,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,YAAwB,EAAE,OAAmB;IACpF,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2BAA2B;IAC3B,IAAI,YAAY,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,sEAAsE;IACtE,IAAI,YAAY,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC/B,OAAO,aAAa,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,eAAe;QACb,OAAO,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,UAAkB;QACnC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IAED,iBAAiB,CAAC,SAAiB,EAAE,UAAkB;QACrD,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;QAC7E,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,eAAuB,EAAE,UAAkB;QAClE,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;QAC1F,OAAO,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7C,CAAC;CACF,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { WebRTCStore, DEFAULT_RELAYS } from './store.js';
2
+ export { Peer } from './peer.js';
3
+ export { PeerId, generateUuid, type SignalingMessage, type WebRTCStoreConfig, type PeerStatus, type WebRTCStoreEvent, type WebRTCStoreEventHandler, type EventSigner, type EventEncrypter, type EventDecrypter, type GiftWrapper, type GiftUnwrapper, type SignedEvent, type PeerPool, type PeerClassifier, type PoolConfig, type WebRTCStats, type BandwidthSample, } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,MAAM,EACN,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { WebRTCStore, DEFAULT_RELAYS } from './store.js';
2
+ export { Peer } from './peer.js';
3
+ export { PeerId, generateUuid, } from './types.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,MAAM,EACN,YAAY,GAiBb,MAAM,YAAY,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Simple LRU Cache implementation
3
+ */
4
+ export declare class LRUCache<K, V> {
5
+ private cache;
6
+ private maxSize;
7
+ constructor(maxSize?: number);
8
+ get(key: K): V | undefined;
9
+ set(key: K, value: V): void;
10
+ has(key: K): boolean;
11
+ delete(key: K): boolean;
12
+ clear(): void;
13
+ get size(): number;
14
+ keys(): IterableIterator<K>;
15
+ values(): IterableIterator<V>;
16
+ entries(): IterableIterator<[K, V]>;
17
+ forEach(callback: (value: V, key: K) => void): void;
18
+ [Symbol.iterator](): IterableIterator<[K, V]>;
19
+ }
20
+ //# sourceMappingURL=lruCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lruCache.d.ts","sourceRoot":"","sources":["../../src/webrtc/lruCache.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,QAAQ,CAAC,CAAC,EAAE,CAAC;IACxB,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,MAAY;IAIjC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS;IAU1B,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAe3B,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAIpB,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAIvB,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAI3B,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAI5B,OAAO,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAIpC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI;IAInD,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAG9C"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Simple LRU Cache implementation
3
+ */
4
+ export class LRUCache {
5
+ cache = new Map();
6
+ maxSize;
7
+ constructor(maxSize = 100) {
8
+ this.maxSize = maxSize;
9
+ }
10
+ get(key) {
11
+ const value = this.cache.get(key);
12
+ if (value !== undefined) {
13
+ // Move to end (most recently used)
14
+ this.cache.delete(key);
15
+ this.cache.set(key, value);
16
+ }
17
+ return value;
18
+ }
19
+ set(key, value) {
20
+ // Delete first to reset position if exists
21
+ this.cache.delete(key);
22
+ // Evict oldest if at capacity
23
+ if (this.cache.size >= this.maxSize) {
24
+ const oldest = this.cache.keys().next().value;
25
+ if (oldest !== undefined) {
26
+ this.cache.delete(oldest);
27
+ }
28
+ }
29
+ this.cache.set(key, value);
30
+ }
31
+ has(key) {
32
+ return this.cache.has(key);
33
+ }
34
+ delete(key) {
35
+ return this.cache.delete(key);
36
+ }
37
+ clear() {
38
+ this.cache.clear();
39
+ }
40
+ get size() {
41
+ return this.cache.size;
42
+ }
43
+ keys() {
44
+ return this.cache.keys();
45
+ }
46
+ values() {
47
+ return this.cache.values();
48
+ }
49
+ *entries() {
50
+ yield* this.cache.entries();
51
+ }
52
+ forEach(callback) {
53
+ this.cache.forEach(callback);
54
+ }
55
+ [Symbol.iterator]() {
56
+ return this.entries();
57
+ }
58
+ }
59
+ //# sourceMappingURL=lruCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lruCache.js","sourceRoot":"","sources":["../../src/webrtc/lruCache.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,QAAQ;IACX,KAAK,GAAG,IAAI,GAAG,EAAQ,CAAC;IACxB,OAAO,CAAS;IAExB,YAAY,UAAkB,GAAG;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,GAAG,CAAC,GAAM;QACR,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,mCAAmC;YACnC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,GAAG,CAAC,GAAM,EAAE,KAAQ;QAClB,2CAA2C;QAC3C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAEvB,8BAA8B;QAC9B,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAC9C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,GAAG,CAAC,GAAM;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,GAAM;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IAC7B,CAAC;IAED,CAAC,OAAO;QACN,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO,CAAC,QAAoC;QAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;CACF"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * WebRTC peer connection for hashtree data exchange
3
+ */
4
+ import type { Store, Hash } from '../types.js';
5
+ import type { SignalingMessage, PeerId } from './types.js';
6
+ export declare class Peer {
7
+ readonly peerId: string;
8
+ readonly pubkey: string;
9
+ readonly direction: 'inbound' | 'outbound';
10
+ private pc;
11
+ private dataChannel;
12
+ private localStore;
13
+ private sendSignaling;
14
+ private onClose;
15
+ private onConnected?;
16
+ private onConnectedFired;
17
+ private debug;
18
+ private makingOffer;
19
+ private ignoreOffer;
20
+ private isPolite;
21
+ private myPeerId;
22
+ private ourRequests;
23
+ private theirRequests;
24
+ private requestTimeout;
25
+ private pendingCandidates;
26
+ private candidateBatchTimeout;
27
+ private queuedRemoteCandidates;
28
+ private onForwardRequest?;
29
+ private stats;
30
+ private pendingReassemblies;
31
+ private reassemblyCleanupInterval?;
32
+ private htlConfig;
33
+ readonly createdAt: number;
34
+ connectedAt?: number;
35
+ constructor(options: {
36
+ peerId: PeerId;
37
+ myPeerId: string;
38
+ direction: 'inbound' | 'outbound';
39
+ localStore: Store | null;
40
+ sendSignaling: (msg: SignalingMessage) => Promise<void>;
41
+ onClose: () => void;
42
+ onConnected?: () => void;
43
+ onForwardRequest?: (hash: Uint8Array, excludePeerId: string, htl: number) => Promise<Uint8Array | null>;
44
+ requestTimeout?: number;
45
+ debug?: boolean;
46
+ });
47
+ private log;
48
+ get state(): RTCPeerConnectionState;
49
+ get isConnected(): boolean;
50
+ get pendingTheirRequestsCount(): number;
51
+ private scheduleCandidateBatch;
52
+ private setupPeerConnection;
53
+ private setupDataChannel;
54
+ private handleMessage;
55
+ private handleRequest;
56
+ private sendResponse;
57
+ /**
58
+ * Handle a fragmented response - buffer and reassemble
59
+ * Returns assembled data when complete, null when waiting for more fragments
60
+ */
61
+ private handleFragmentResponse;
62
+ /**
63
+ * Assemble fragments in order into a single buffer
64
+ */
65
+ private assembleFragments;
66
+ /**
67
+ * Clean up stale reassemblies (stalled or timed out)
68
+ */
69
+ private cleanupStaleReassemblies;
70
+ /**
71
+ * Request data by hash from this peer
72
+ * @param htl Hops To Live - decremented before sending
73
+ */
74
+ request(hash: Hash, htl?: number): Promise<Uint8Array | null>;
75
+ /**
76
+ * Get per-peer statistics
77
+ */
78
+ getStats(): {
79
+ requestsSent: number;
80
+ requestsReceived: number;
81
+ responsesSent: number;
82
+ responsesReceived: number;
83
+ receiveErrors: number;
84
+ fragmentsSent: number;
85
+ fragmentsReceived: number;
86
+ fragmentTimeouts: number;
87
+ reassembliesCompleted: number;
88
+ bytesSent: number;
89
+ bytesReceived: number;
90
+ bytesForwarded: number;
91
+ };
92
+ /**
93
+ * Send data to this peer for a hash they previously requested
94
+ * Returns true if this peer had requested this hash
95
+ */
96
+ sendData(hash: Uint8Array, data: Uint8Array): boolean;
97
+ /**
98
+ * Check if this peer has requested a hash
99
+ */
100
+ hasRequested(hash: Uint8Array): boolean;
101
+ /**
102
+ * Get count of pending requests from this peer
103
+ */
104
+ getTheirRequestCount(): number;
105
+ /**
106
+ * Initiate connection (create offer)
107
+ * Uses perfect negotiation pattern - both peers can call this
108
+ */
109
+ connect(): Promise<void>;
110
+ /**
111
+ * Handle incoming signaling message
112
+ * Implements perfect negotiation pattern for collision handling
113
+ */
114
+ handleSignaling(msg: SignalingMessage): Promise<void>;
115
+ private addRemoteCandidate;
116
+ private processQueuedCandidates;
117
+ /**
118
+ * Close the peer connection
119
+ */
120
+ close(): void;
121
+ }
122
+ //# sourceMappingURL=peer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer.d.ts","sourceRoot":"","sources":["../../src/webrtc/peer.ts"],"names":[],"mappings":"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"}