@hamradio/meshcore 1.2.2 → 1.3.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.
@@ -1,3 +1,44 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Contact: () => Contact,
24
+ Contacts: () => Contacts,
25
+ Group: () => Group,
26
+ Identity: () => Identity,
27
+ LocalIdentity: () => LocalIdentity,
28
+ NodeType: () => NodeType,
29
+ Packet: () => Packet,
30
+ PayloadType: () => PayloadType,
31
+ PrivateKey: () => PrivateKey,
32
+ PublicKey: () => PublicKey,
33
+ RequestType: () => RequestType,
34
+ RouteType: () => RouteType,
35
+ SharedSecret: () => SharedSecret,
36
+ StaticSecret: () => StaticSecret,
37
+ TextType: () => TextType,
38
+ parseNodeHash: () => parseNodeHash
39
+ });
40
+ module.exports = __toCommonJS(index_exports);
41
+
1
42
  // src/packet.types.ts
2
43
  var RouteType = /* @__PURE__ */ ((RouteType2) => {
3
44
  RouteType2[RouteType2["TRANSPORT_FLOOD"] = 0] = "TRANSPORT_FLOOD";
@@ -45,127 +86,8 @@ var NodeType = /* @__PURE__ */ ((NodeType2) => {
45
86
  })(NodeType || {});
46
87
 
47
88
  // src/packet.ts
48
- import { sha256 } from "@noble/hashes/sha2.js";
49
-
50
- // src/parser.ts
51
- import { equalBytes } from "@noble/ciphers/utils.js";
52
- import { bytesToHex, hexToBytes as nobleHexToBytes } from "@noble/hashes/utils.js";
53
- var base64ToBytes = (base64, size) => {
54
- let normalized = base64.replace(/-/g, "+").replace(/_/g, "/");
55
- while (normalized.length % 4 !== 0) {
56
- normalized += "=";
57
- }
58
- const binaryString = atob(normalized);
59
- const bytes = new Uint8Array(binaryString.length);
60
- for (let i = 0; i < binaryString.length; i++) {
61
- bytes[i] = binaryString.charCodeAt(i);
62
- }
63
- if (size !== void 0 && bytes.length !== size) {
64
- throw new Error(`Invalid base64 length: expected ${size} bytes, got ${bytes.length}`);
65
- }
66
- return bytes;
67
- };
68
- var hexToBytes = (hex, size) => {
69
- const bytes = nobleHexToBytes(hex);
70
- if (size !== void 0 && bytes.length !== size) {
71
- throw new Error(`Invalid hex length: expected ${size} bytes, got ${bytes.length}`);
72
- }
73
- return bytes;
74
- };
75
- var BufferReader = class {
76
- constructor(buffer) {
77
- this.buffer = buffer;
78
- this.offset = 0;
79
- }
80
- readByte() {
81
- if (!this.hasMore()) throw new Error("read past end");
82
- return this.buffer[this.offset++];
83
- }
84
- readBytes(length) {
85
- if (length === void 0) {
86
- length = this.buffer.length - this.offset;
87
- }
88
- if (this.remainingBytes() < length) throw new Error("read past end");
89
- const bytes = this.buffer.slice(this.offset, this.offset + length);
90
- this.offset += length;
91
- return bytes;
92
- }
93
- hasMore() {
94
- return this.offset < this.buffer.length;
95
- }
96
- remainingBytes() {
97
- return this.buffer.length - this.offset;
98
- }
99
- peekByte() {
100
- if (!this.hasMore()) throw new Error("read past end");
101
- return this.buffer[this.offset];
102
- }
103
- readUint16LE() {
104
- if (this.remainingBytes() < 2) throw new Error("read past end");
105
- const value = this.buffer[this.offset] | this.buffer[this.offset + 1] << 8;
106
- this.offset += 2;
107
- return value;
108
- }
109
- readUint32LE() {
110
- if (this.remainingBytes() < 4) throw new Error("read past end");
111
- const value = (this.buffer[this.offset] | this.buffer[this.offset + 1] << 8 | this.buffer[this.offset + 2] << 16 | this.buffer[this.offset + 3] << 24) >>> 0;
112
- this.offset += 4;
113
- return value;
114
- }
115
- readInt16LE() {
116
- if (this.remainingBytes() < 2) throw new Error("read past end");
117
- const value = this.buffer[this.offset] | this.buffer[this.offset + 1] << 8;
118
- this.offset += 2;
119
- return value < 32768 ? value : value - 65536;
120
- }
121
- readInt32LE() {
122
- if (this.remainingBytes() < 4) throw new Error("read past end");
123
- const u = (this.buffer[this.offset] | this.buffer[this.offset + 1] << 8 | this.buffer[this.offset + 2] << 16 | this.buffer[this.offset + 3] << 24) >>> 0;
124
- this.offset += 4;
125
- return u < 2147483648 ? u : u - 4294967296;
126
- }
127
- readTimestamp() {
128
- const timestamp = this.readUint32LE();
129
- return new Date(timestamp * 1e3);
130
- }
131
- };
132
- var BufferWriter = class {
133
- constructor() {
134
- this.buffer = [];
135
- }
136
- writeByte(value) {
137
- this.buffer.push(value & 255);
138
- }
139
- writeBytes(bytes) {
140
- this.buffer.push(...bytes);
141
- }
142
- writeUint16LE(value) {
143
- this.buffer.push(value & 255, value >> 8 & 255);
144
- }
145
- writeUint32LE(value) {
146
- this.buffer.push(
147
- value & 255,
148
- value >> 8 & 255,
149
- value >> 16 & 255,
150
- value >> 24 & 255
151
- );
152
- }
153
- writeInt16LE(value) {
154
- this.writeUint16LE(value < 0 ? value + 65536 : value);
155
- }
156
- writeInt32LE(value) {
157
- this.writeUint32LE(value < 0 ? value + 4294967296 : value);
158
- }
159
- writeTimestamp(date) {
160
- const timestamp = Math.floor(date.getTime() / 1e3);
161
- this.writeUint32LE(timestamp);
162
- }
163
- toBytes() {
164
- return new Uint8Array(this.buffer);
165
- }
166
- };
167
-
168
- // src/packet.ts
89
+ var import_sha2 = require("@noble/hashes/sha2.js");
90
+ var import_packet2 = require("@hamradio/packet");
169
91
  var Packet = class _Packet {
170
92
  constructor(header, transport, pathLength, path, payload) {
171
93
  this.header = header;
@@ -182,13 +104,13 @@ var Packet = class _Packet {
182
104
  this.pathHashes = [];
183
105
  for (let i = 0; i < this.pathHashBytes; i += this.pathHashSize) {
184
106
  const hashBytes = this.path.slice(i, i + this.pathHashSize);
185
- const hashHex = bytesToHex(hashBytes);
107
+ const hashHex = (0, import_packet2.bytesToHex)(hashBytes);
186
108
  this.pathHashes.push(hashHex);
187
109
  }
188
110
  }
189
111
  static fromBytes(bytes) {
190
112
  if (typeof bytes === "string") {
191
- bytes = base64ToBytes(bytes);
113
+ bytes = (0, import_packet2.base64ToBytes)(bytes);
192
114
  }
193
115
  let offset = 0;
194
116
  const header = bytes[offset++];
@@ -209,14 +131,14 @@ var Packet = class _Packet {
209
131
  return routeType === 0 /* TRANSPORT_FLOOD */ || routeType === 3 /* TRANSPORT_DIRECT */;
210
132
  }
211
133
  hash() {
212
- const hash = sha256.create();
134
+ const hash = import_sha2.sha256.create();
213
135
  hash.update(new Uint8Array([this.payloadType]));
214
136
  if (this.payloadType === 9 /* TRACE */) {
215
137
  hash.update(new Uint8Array([this.pathLength]));
216
138
  }
217
139
  hash.update(this.payload);
218
140
  const digest = hash.digest();
219
- return bytesToHex(digest.slice(0, 8));
141
+ return (0, import_packet2.bytesToHex)(digest.slice(0, 8));
220
142
  }
221
143
  ensureStructure() {
222
144
  if (typeof this.structure !== "undefined") {
@@ -225,13 +147,13 @@ var Packet = class _Packet {
225
147
  let pathHashType;
226
148
  switch (this.pathHashSize) {
227
149
  case 1:
228
- pathHashType = 6 /* BYTES */;
150
+ pathHashType = import_packet2.FieldType.BYTES;
229
151
  break;
230
152
  case 2:
231
- pathHashType = 7 /* WORDS */;
153
+ pathHashType = import_packet2.FieldType.WORDS;
232
154
  break;
233
155
  case 4:
234
- pathHashType = 8 /* DWORDS */;
156
+ pathHashType = import_packet2.FieldType.DWORDS;
235
157
  break;
236
158
  default:
237
159
  throw new Error(`Unsupported path hash size: ${this.pathHashSize}`);
@@ -240,13 +162,13 @@ var Packet = class _Packet {
240
162
  /* Header segment */
241
163
  {
242
164
  name: "header",
243
- data: new Uint8Array([this.header]),
165
+ data: new Uint8Array([this.header]).buffer,
244
166
  fields: [
245
167
  /* Header flags */
246
168
  {
247
169
  name: "flags",
248
- type: 0 /* BITS */,
249
- size: 1,
170
+ type: import_packet2.FieldType.BITS,
171
+ length: 1,
250
172
  bits: [
251
173
  { name: "payload version", size: 2 },
252
174
  { name: "payload type", size: 4 },
@@ -256,38 +178,40 @@ var Packet = class _Packet {
256
178
  ]
257
179
  },
258
180
  /* Transport codes */
259
- ..._Packet.hasTransportCodes(this.routeType) ? [{
260
- name: "transport codes",
261
- data: new Uint8Array([
262
- this.transport[0] >> 8 & 255,
263
- this.transport[0] & 255,
264
- this.transport[1] >> 8 & 255,
265
- this.transport[1] & 255
266
- ]),
267
- fields: [
268
- {
269
- name: "transport code 1",
270
- type: 3 /* UINT16_BE */,
271
- size: 2,
272
- value: this.transport[0]
273
- },
274
- {
275
- name: "transport code 2",
276
- type: 3 /* UINT16_BE */,
277
- size: 2,
278
- value: this.transport[1]
279
- }
280
- ]
281
- }] : [],
181
+ ..._Packet.hasTransportCodes(this.routeType) ? [
182
+ {
183
+ name: "transport codes",
184
+ data: new Uint8Array([
185
+ this.transport[0] >> 8 & 255,
186
+ this.transport[0] & 255,
187
+ this.transport[1] >> 8 & 255,
188
+ this.transport[1] & 255
189
+ ]).buffer,
190
+ fields: [
191
+ {
192
+ name: "transport code 1",
193
+ type: import_packet2.FieldType.UINT16_BE,
194
+ length: 2,
195
+ value: this.transport[0]
196
+ },
197
+ {
198
+ name: "transport code 2",
199
+ type: import_packet2.FieldType.UINT16_BE,
200
+ length: 2,
201
+ value: this.transport[1]
202
+ }
203
+ ]
204
+ }
205
+ ] : [],
282
206
  /* Path length and hashes */
283
207
  {
284
208
  name: "path",
285
- data: new Uint8Array([this.pathLength, ...this.path]),
209
+ data: new Uint8Array([this.pathLength, ...this.path]).buffer,
286
210
  fields: [
287
211
  {
288
212
  name: "path length",
289
- type: 1 /* UINT8 */,
290
- size: 1,
213
+ type: import_packet2.FieldType.UINT8,
214
+ length: 1,
291
215
  bits: [
292
216
  { name: "path hash size", size: 2 },
293
217
  { name: "path hash count", size: 6 }
@@ -296,7 +220,7 @@ var Packet = class _Packet {
296
220
  {
297
221
  name: "path hashes",
298
222
  type: pathHashType,
299
- size: this.path.length
223
+ length: this.path.length
300
224
  }
301
225
  ]
302
226
  }
@@ -341,7 +265,6 @@ var Packet = class _Packet {
341
265
  default:
342
266
  throw new Error(`Unsupported payload type: ${this.payloadType}`);
343
267
  }
344
- console.log("packet decode with structure:", typeof withStructure, withStructure, { result });
345
268
  if (typeof withStructure === "boolean" && withStructure && "segment" in result && "payload" in result) {
346
269
  this.ensureStructure();
347
270
  const structure = [...this.structure, result.segment];
@@ -350,17 +273,17 @@ var Packet = class _Packet {
350
273
  return result;
351
274
  }
352
275
  decodeEncryptedPayload(reader) {
353
- const cipherMAC = reader.readBytes(2);
354
- const cipherText = reader.readBytes(reader.remainingBytes());
276
+ const cipherMAC = reader.bytes(2);
277
+ const cipherText = reader.bytes();
355
278
  return { cipherMAC, cipherText };
356
279
  }
357
280
  decodeRequest(withSegment) {
358
281
  if (this.payload.length < 4) {
359
282
  throw new Error("Invalid request payload: too short");
360
283
  }
361
- const reader = new BufferReader(this.payload);
362
- const dst = reader.readByte();
363
- const src = reader.readByte();
284
+ const reader = import_packet2.Reader.fromBytes(this.payload);
285
+ const dst = reader.uint8();
286
+ const src = reader.uint8();
364
287
  const encrypted = this.decodeEncryptedPayload(reader);
365
288
  const payload = {
366
289
  type: 0 /* REQUEST */,
@@ -371,12 +294,17 @@ var Packet = class _Packet {
371
294
  if (typeof withSegment === "boolean" && withSegment) {
372
295
  const segment = {
373
296
  name: "request payload",
374
- data: this.payload,
297
+ data: new Uint8Array(this.payload).buffer,
375
298
  fields: [
376
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: dst },
377
- { name: "source hash", type: 1 /* UINT8 */, size: 1, value: src },
378
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: encrypted.cipherMAC },
379
- { name: "cipher text", type: 6 /* BYTES */, size: encrypted.cipherText.length, value: encrypted.cipherText }
299
+ { name: "destination hash", type: import_packet2.FieldType.UINT8, length: 1, value: dst },
300
+ { name: "source hash", type: import_packet2.FieldType.UINT8, length: 1, value: src },
301
+ { name: "cipher MAC", type: import_packet2.FieldType.BYTES, length: 2, value: encrypted.cipherMAC },
302
+ {
303
+ name: "cipher text",
304
+ type: import_packet2.FieldType.BYTES,
305
+ length: encrypted.cipherText.length,
306
+ value: encrypted.cipherText
307
+ }
380
308
  ]
381
309
  };
382
310
  return { payload, segment };
@@ -387,9 +315,9 @@ var Packet = class _Packet {
387
315
  if (this.payload.length < 4) {
388
316
  throw new Error("Invalid response payload: too short");
389
317
  }
390
- const reader = new BufferReader(this.payload);
391
- const dst = reader.readByte();
392
- const src = reader.readByte();
318
+ const reader = import_packet2.Reader.fromBytes(this.payload);
319
+ const dst = reader.uint8();
320
+ const src = reader.uint8();
393
321
  const encrypted = this.decodeEncryptedPayload(reader);
394
322
  const payload = {
395
323
  type: 1 /* RESPONSE */,
@@ -400,12 +328,17 @@ var Packet = class _Packet {
400
328
  if (typeof withSegment === "boolean" && withSegment) {
401
329
  const segment = {
402
330
  name: "response payload",
403
- data: this.payload,
331
+ data: new Uint8Array(this.payload).buffer,
404
332
  fields: [
405
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: dst },
406
- { name: "source hash", type: 1 /* UINT8 */, size: 1, value: src },
407
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: encrypted.cipherMAC },
408
- { name: "cipher text", type: 6 /* BYTES */, size: encrypted.cipherText.length, value: encrypted.cipherText }
333
+ { name: "destination hash", type: import_packet2.FieldType.UINT8, length: 1, value: dst },
334
+ { name: "source hash", type: import_packet2.FieldType.UINT8, length: 1, value: src },
335
+ { name: "cipher MAC", type: import_packet2.FieldType.BYTES, length: 2, value: encrypted.cipherMAC },
336
+ {
337
+ name: "cipher text",
338
+ type: import_packet2.FieldType.BYTES,
339
+ length: encrypted.cipherText.length,
340
+ value: encrypted.cipherText
341
+ }
409
342
  ]
410
343
  };
411
344
  return { payload, segment };
@@ -416,9 +349,9 @@ var Packet = class _Packet {
416
349
  if (this.payload.length < 4) {
417
350
  throw new Error("Invalid text payload: too short");
418
351
  }
419
- const reader = new BufferReader(this.payload);
420
- const dst = reader.readByte();
421
- const src = reader.readByte();
352
+ const reader = import_packet2.Reader.fromBytes(this.payload);
353
+ const dst = reader.uint8();
354
+ const src = reader.uint8();
422
355
  const encrypted = this.decodeEncryptedPayload(reader);
423
356
  const payload = {
424
357
  type: 2 /* TEXT */,
@@ -429,12 +362,17 @@ var Packet = class _Packet {
429
362
  if (typeof withSegment === "boolean" && withSegment) {
430
363
  const segment = {
431
364
  name: "text payload",
432
- data: this.payload,
365
+ data: new Uint8Array(this.payload).buffer,
433
366
  fields: [
434
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: dst },
435
- { name: "source hash", type: 1 /* UINT8 */, size: 1, value: src },
436
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: encrypted.cipherMAC },
437
- { name: "cipher text", type: 6 /* BYTES */, size: encrypted.cipherText.length, value: encrypted.cipherText }
367
+ { name: "destination hash", type: import_packet2.FieldType.UINT8, length: 1, value: dst },
368
+ { name: "source hash", type: import_packet2.FieldType.UINT8, length: 1, value: src },
369
+ { name: "cipher MAC", type: import_packet2.FieldType.BYTES, length: 2, value: encrypted.cipherMAC },
370
+ {
371
+ name: "cipher text",
372
+ type: import_packet2.FieldType.BYTES,
373
+ length: encrypted.cipherText.length,
374
+ value: encrypted.cipherText
375
+ }
438
376
  ]
439
377
  };
440
378
  return { payload, segment };
@@ -445,8 +383,8 @@ var Packet = class _Packet {
445
383
  if (this.payload.length < 4) {
446
384
  throw new Error("Invalid ack payload: too short");
447
385
  }
448
- const reader = new BufferReader(this.payload);
449
- const checksum = reader.readBytes(4);
386
+ const reader = import_packet2.Reader.fromBytes(this.payload);
387
+ const checksum = reader.bytes(4);
450
388
  const payload = {
451
389
  type: 3 /* ACK */,
452
390
  checksum
@@ -454,10 +392,8 @@ var Packet = class _Packet {
454
392
  if (typeof withSegment === "boolean" && withSegment) {
455
393
  const segment = {
456
394
  name: "ack payload",
457
- data: this.payload,
458
- fields: [
459
- { name: "checksum", type: 6 /* BYTES */, size: 4, value: checksum }
460
- ]
395
+ data: new Uint8Array(this.payload).buffer,
396
+ fields: [{ name: "checksum", type: import_packet2.FieldType.BYTES, length: 4, value: checksum }]
461
397
  };
462
398
  return { payload, segment };
463
399
  }
@@ -467,26 +403,26 @@ var Packet = class _Packet {
467
403
  if (this.payload.length < 4) {
468
404
  throw new Error("Invalid advert payload: too short");
469
405
  }
470
- const reader = new BufferReader(this.payload);
406
+ const reader = import_packet2.Reader.fromBytes(this.payload);
471
407
  const payload = {
472
408
  type: 4 /* ADVERT */,
473
- publicKey: reader.readBytes(32),
474
- timestamp: reader.readTimestamp(),
475
- signature: reader.readBytes(64)
409
+ publicKey: reader.bytes(32),
410
+ timestamp: reader.date32(),
411
+ signature: reader.bytes(64)
476
412
  };
477
413
  let segment;
478
414
  if (typeof withSegment === "boolean" && withSegment) {
479
415
  segment = {
480
416
  name: "advert payload",
481
- data: this.payload,
417
+ data: new Uint8Array(this.payload).buffer,
482
418
  fields: [
483
- { type: 6 /* BYTES */, name: "public key", size: 32 },
484
- { type: 4 /* UINT32_LE */, name: "timestamp", size: 4, value: payload.timestamp },
485
- { type: 6 /* BYTES */, name: "signature", size: 64 }
419
+ { type: import_packet2.FieldType.BYTES, name: "public key", length: 32 },
420
+ { type: import_packet2.FieldType.UINT32_LE, name: "timestamp", length: 4, value: payload.timestamp },
421
+ { type: import_packet2.FieldType.BYTES, name: "signature", length: 64 }
486
422
  ]
487
423
  };
488
424
  }
489
- const flags = reader.readByte();
425
+ const flags = reader.uint8();
490
426
  const appdata = {
491
427
  nodeType: flags & 15,
492
428
  hasLocation: (flags & 16 /* HAS_LOCATION */) !== 0,
@@ -495,44 +431,50 @@ var Packet = class _Packet {
495
431
  hasName: (flags & 128 /* HAS_NAME */) !== 0
496
432
  };
497
433
  if (typeof withSegment === "boolean" && withSegment) {
498
- segment.fields.push({ type: 0 /* BITS */, name: "flags", size: 1, value: flags, bits: [
499
- { size: 1, name: "name flag" },
500
- { size: 1, name: "feature2 flag" },
501
- { size: 1, name: "feature1 flag" },
502
- { size: 1, name: "location flag" },
503
- { size: 4, name: "node type" }
504
- ] });
434
+ segment.fields.push({
435
+ type: import_packet2.FieldType.BITS,
436
+ name: "flags",
437
+ length: 1,
438
+ value: flags,
439
+ bits: [
440
+ { size: 1, name: "name flag" },
441
+ { size: 1, name: "feature2 flag" },
442
+ { size: 1, name: "feature1 flag" },
443
+ { size: 1, name: "location flag" },
444
+ { size: 4, name: "node type" }
445
+ ]
446
+ });
505
447
  }
506
448
  if (appdata.hasLocation) {
507
- const lat = reader.readInt32LE() / 1e5;
508
- const lon = reader.readInt32LE() / 1e5;
449
+ const lat = reader.int32() / 1e6;
450
+ const lon = reader.int32() / 1e6;
509
451
  appdata.location = [lat, lon];
510
452
  if (typeof withSegment === "boolean" && withSegment) {
511
- segment.fields.push({ type: 4 /* UINT32_LE */, name: "latitude", size: 4, value: lat });
512
- segment.fields.push({ type: 4 /* UINT32_LE */, name: "longitude", size: 4, value: lon });
453
+ segment.fields.push({ type: import_packet2.FieldType.UINT32_LE, name: "latitude", length: 4, value: lat });
454
+ segment.fields.push({ type: import_packet2.FieldType.UINT32_LE, name: "longitude", length: 4, value: lon });
513
455
  }
514
456
  }
515
457
  if (appdata.hasFeature1) {
516
- appdata.feature1 = reader.readUint16LE();
458
+ appdata.feature1 = reader.uint16();
517
459
  if (typeof withSegment === "boolean" && withSegment) {
518
- segment.fields.push({ type: 2 /* UINT16_LE */, name: "feature1", size: 2, value: appdata.feature1 });
460
+ segment.fields.push({ type: import_packet2.FieldType.UINT16_LE, name: "feature1", length: 2, value: appdata.feature1 });
519
461
  }
520
462
  }
521
463
  if (appdata.hasFeature2) {
522
- appdata.feature2 = reader.readUint16LE();
464
+ appdata.feature2 = reader.uint16();
523
465
  if (typeof withSegment === "boolean" && withSegment) {
524
- segment.fields.push({ type: 2 /* UINT16_LE */, name: "feature2", size: 2, value: appdata.feature2 });
466
+ segment.fields.push({ type: import_packet2.FieldType.UINT16_LE, name: "feature2", length: 2, value: appdata.feature2 });
525
467
  }
526
468
  }
527
469
  if (appdata.hasName) {
528
- const nameBytes = reader.readBytes();
529
- let nullPos = nameBytes.indexOf(0);
530
- if (nullPos === -1) {
531
- nullPos = nameBytes.length;
532
- }
533
- appdata.name = new TextDecoder("utf-8").decode(nameBytes.subarray(0, nullPos));
470
+ appdata.name = reader.cString();
534
471
  if (typeof withSegment === "boolean" && withSegment) {
535
- segment.fields.push({ type: 10 /* C_STRING */, name: "name", size: nameBytes.length, value: appdata.name });
472
+ segment.fields.push({
473
+ type: import_packet2.FieldType.C_STRING,
474
+ name: "name",
475
+ length: appdata.name.length,
476
+ value: appdata.name
477
+ });
536
478
  }
537
479
  }
538
480
  if (typeof withSegment === "boolean" && withSegment && typeof segment !== "undefined") {
@@ -544,8 +486,8 @@ var Packet = class _Packet {
544
486
  if (this.payload.length < 3) {
545
487
  throw new Error("Invalid group text payload: too short");
546
488
  }
547
- const reader = new BufferReader(this.payload);
548
- const channelHash = reader.readByte();
489
+ const reader = import_packet2.Reader.fromBytes(this.payload);
490
+ const channelHash = reader.uint8();
549
491
  const encrypted = this.decodeEncryptedPayload(reader);
550
492
  const payload = {
551
493
  type: 5 /* GROUP_TEXT */,
@@ -555,11 +497,16 @@ var Packet = class _Packet {
555
497
  if (typeof withSegment === "boolean" && withSegment) {
556
498
  const segment = {
557
499
  name: "group text payload",
558
- data: this.payload,
500
+ data: new Uint8Array(this.payload).buffer,
559
501
  fields: [
560
- { name: "channel hash", type: 1 /* UINT8 */, size: 1, value: channelHash },
561
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: encrypted.cipherMAC },
562
- { name: "cipher text", type: 6 /* BYTES */, size: encrypted.cipherText.length, value: encrypted.cipherText }
502
+ { name: "channel hash", type: import_packet2.FieldType.UINT8, length: 1, value: channelHash },
503
+ { name: "cipher MAC", type: import_packet2.FieldType.BYTES, length: 2, value: encrypted.cipherMAC },
504
+ {
505
+ name: "cipher text",
506
+ type: import_packet2.FieldType.BYTES,
507
+ length: encrypted.cipherText.length,
508
+ value: encrypted.cipherText
509
+ }
563
510
  ]
564
511
  };
565
512
  return { payload, segment };
@@ -570,20 +517,25 @@ var Packet = class _Packet {
570
517
  if (this.payload.length < 3) {
571
518
  throw new Error("Invalid group data payload: too short");
572
519
  }
573
- const reader = new BufferReader(this.payload);
520
+ const reader = import_packet2.Reader.fromBytes(this.payload);
574
521
  const payload = {
575
522
  type: 6 /* GROUP_DATA */,
576
- channelHash: reader.readByte(),
523
+ channelHash: reader.uint8(),
577
524
  encrypted: this.decodeEncryptedPayload(reader)
578
525
  };
579
526
  if (typeof withSegment === "boolean" && withSegment) {
580
527
  const segment = {
581
528
  name: "group data payload",
582
- data: this.payload,
529
+ data: new Uint8Array(this.payload).buffer,
583
530
  fields: [
584
- { name: "channel hash", type: 1 /* UINT8 */, size: 1, value: payload.channelHash },
585
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: payload.encrypted.cipherMAC },
586
- { name: "cipher text", type: 6 /* BYTES */, size: payload.encrypted.cipherText.length, value: payload.encrypted.cipherText }
531
+ { name: "channel hash", type: import_packet2.FieldType.UINT8, length: 1, value: payload.channelHash },
532
+ { name: "cipher MAC", type: import_packet2.FieldType.BYTES, length: 2, value: payload.encrypted.cipherMAC },
533
+ {
534
+ name: "cipher text",
535
+ type: import_packet2.FieldType.BYTES,
536
+ length: payload.encrypted.cipherText.length,
537
+ value: payload.encrypted.cipherText
538
+ }
587
539
  ]
588
540
  };
589
541
  return { payload, segment };
@@ -594,22 +546,27 @@ var Packet = class _Packet {
594
546
  if (this.payload.length < 1 + 32 + 2) {
595
547
  throw new Error("Invalid anon req payload: too short");
596
548
  }
597
- const reader = new BufferReader(this.payload);
549
+ const reader = import_packet2.Reader.fromBytes(this.payload);
598
550
  const payload = {
599
551
  type: 7 /* ANON_REQ */,
600
- dst: reader.readByte(),
601
- publicKey: reader.readBytes(32),
552
+ dst: reader.uint8(),
553
+ publicKey: reader.bytes(32),
602
554
  encrypted: this.decodeEncryptedPayload(reader)
603
555
  };
604
556
  if (typeof withSegment === "boolean" && withSegment) {
605
557
  const segment = {
606
558
  name: "anon req payload",
607
- data: this.payload,
559
+ data: new Uint8Array(this.payload).buffer,
608
560
  fields: [
609
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: payload.dst },
610
- { name: "public key", type: 6 /* BYTES */, size: 32, value: payload.publicKey },
611
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: payload.encrypted.cipherMAC },
612
- { name: "cipher text", type: 6 /* BYTES */, size: payload.encrypted.cipherText.length, value: payload.encrypted.cipherText }
561
+ { name: "destination hash", type: import_packet2.FieldType.UINT8, length: 1, value: payload.dst },
562
+ { name: "public key", type: import_packet2.FieldType.BYTES, length: 32, value: payload.publicKey },
563
+ { name: "cipher MAC", type: import_packet2.FieldType.BYTES, length: 2, value: payload.encrypted.cipherMAC },
564
+ {
565
+ name: "cipher text",
566
+ type: import_packet2.FieldType.BYTES,
567
+ length: payload.encrypted.cipherText.length,
568
+ value: payload.encrypted.cipherText
569
+ }
613
570
  ]
614
571
  };
615
572
  return { payload, segment };
@@ -620,19 +577,19 @@ var Packet = class _Packet {
620
577
  if (this.payload.length < 2) {
621
578
  throw new Error("Invalid path payload: too short");
622
579
  }
623
- const reader = new BufferReader(this.payload);
580
+ const reader = import_packet2.Reader.fromBytes(this.payload);
624
581
  const payload = {
625
582
  type: 8 /* PATH */,
626
- dst: reader.readByte(),
627
- src: reader.readByte()
583
+ dst: reader.uint8(),
584
+ src: reader.uint8()
628
585
  };
629
586
  if (typeof withSegment === "boolean" && withSegment) {
630
587
  const segment = {
631
588
  name: "path payload",
632
- data: this.payload,
589
+ data: new Uint8Array(this.payload).buffer,
633
590
  fields: [
634
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: payload.dst },
635
- { name: "source hash", type: 1 /* UINT8 */, size: 1, value: payload.src }
591
+ { name: "destination hash", type: import_packet2.FieldType.UINT8, length: 1, value: payload.dst },
592
+ { name: "source hash", type: import_packet2.FieldType.UINT8, length: 1, value: payload.src }
636
593
  ]
637
594
  };
638
595
  return { payload, segment };
@@ -643,23 +600,23 @@ var Packet = class _Packet {
643
600
  if (this.payload.length < 9) {
644
601
  throw new Error("Invalid trace payload: too short");
645
602
  }
646
- const reader = new BufferReader(this.payload);
603
+ const reader = import_packet2.Reader.fromBytes(this.payload);
647
604
  const payload = {
648
605
  type: 9 /* TRACE */,
649
- tag: reader.readUint32LE() >>> 0,
650
- authCode: reader.readUint32LE() >>> 0,
651
- flags: reader.readByte() & 3,
652
- nodes: reader.readBytes()
606
+ tag: reader.uint32(),
607
+ authCode: reader.uint32(),
608
+ flags: reader.uint8() & 3,
609
+ nodes: reader.bytes()
653
610
  };
654
611
  if (typeof withSegment === "boolean" && withSegment) {
655
612
  const segment = {
656
613
  name: "trace payload",
657
- data: this.payload,
614
+ data: new Uint8Array(this.payload).buffer,
658
615
  fields: [
659
- { name: "tag", type: 8 /* DWORDS */, size: 4, value: payload.tag },
660
- { name: "auth code", type: 8 /* DWORDS */, size: 4, value: payload.authCode },
661
- { name: "flags", type: 1 /* UINT8 */, size: 1, value: payload.flags },
662
- { name: "nodes", type: 6 /* BYTES */, size: payload.nodes.length, value: payload.nodes }
616
+ { name: "tag", type: import_packet2.FieldType.DWORDS, length: 4, value: payload.tag },
617
+ { name: "auth code", type: import_packet2.FieldType.DWORDS, length: 4, value: payload.authCode },
618
+ { name: "flags", type: import_packet2.FieldType.UINT8, length: 1, value: payload.flags },
619
+ { name: "nodes", type: import_packet2.FieldType.BYTES, length: payload.nodes.length, value: payload.nodes }
663
620
  ]
664
621
  };
665
622
  return { payload, segment };
@@ -674,10 +631,8 @@ var Packet = class _Packet {
674
631
  if (typeof withSegment === "boolean" && withSegment) {
675
632
  const segment = {
676
633
  name: "raw custom payload",
677
- data: this.payload,
678
- fields: [
679
- { name: "data", type: 6 /* BYTES */, size: this.payload.length, value: this.payload }
680
- ]
634
+ data: new Uint8Array(this.payload).buffer,
635
+ fields: [{ name: "data", type: import_packet2.FieldType.BYTES, length: this.payload.length, value: this.payload }]
681
636
  };
682
637
  return { payload, segment };
683
638
  }
@@ -686,35 +641,39 @@ var Packet = class _Packet {
686
641
  };
687
642
 
688
643
  // src/crypto.ts
689
- import { ed25519, x25519 } from "@noble/curves/ed25519.js";
690
- import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
691
- import { hmac } from "@noble/hashes/hmac.js";
692
- import { ecb } from "@noble/ciphers/aes.js";
644
+ var import_ed25519 = require("@noble/curves/ed25519.js");
645
+ var import_sha22 = require("@noble/hashes/sha2.js");
646
+ var import_hmac = require("@noble/hashes/hmac.js");
647
+ var import_aes = require("@noble/ciphers/aes.js");
648
+ var import_packet3 = require("@hamradio/packet");
693
649
  var PUBLIC_KEY_SIZE = 32;
694
650
  var SEED_SIZE = 32;
695
651
  var HMAC_SIZE = 2;
696
- var SHARED_SECRET_SIZE = 32;
652
+ var SHARED_SECRET_SIZE = 16;
697
653
  var SIGNATURE_SIZE = 64;
698
654
  var STATIC_SECRET_SIZE = 32;
699
- var publicSecret = hexToBytes("8b3387e9c5cdea6ac9e5edbaa115cd72", 16);
655
+ var publicSecret = (0, import_packet3.hexToBytes)("8b3387e9c5cdea6ac9e5edbaa115cd72");
700
656
  var PublicKey = class _PublicKey {
701
657
  constructor(key) {
702
658
  if (typeof key === "string") {
703
- this.key = hexToBytes(key, PUBLIC_KEY_SIZE);
659
+ this.key = (0, import_packet3.hexToBytes)(key);
704
660
  } else if (key instanceof Uint8Array) {
705
661
  this.key = key;
706
662
  } else {
707
663
  throw new Error("Invalid type for PublicKey constructor");
708
664
  }
665
+ if (this.key.length !== PUBLIC_KEY_SIZE) {
666
+ throw new Error(`Invalid public key length: expected ${PUBLIC_KEY_SIZE} bytes, got ${this.key.length}`);
667
+ }
709
668
  }
710
669
  toHash() {
711
- return sha2562.create().update(this.key).digest()[0];
670
+ return import_sha22.sha256.create().update(this.key).digest()[0];
712
671
  }
713
672
  toBytes() {
714
673
  return this.key;
715
674
  }
716
675
  toString() {
717
- return bytesToHex(this.key);
676
+ return (0, import_packet3.bytesToHex)(this.key);
718
677
  }
719
678
  equals(other) {
720
679
  let otherKey;
@@ -723,28 +682,39 @@ var PublicKey = class _PublicKey {
723
682
  } else if (other instanceof Uint8Array) {
724
683
  otherKey = other;
725
684
  } else if (typeof other === "string") {
726
- otherKey = hexToBytes(other, PUBLIC_KEY_SIZE);
685
+ otherKey = (0, import_packet3.hexToBytes)(other);
727
686
  } else {
728
687
  throw new Error("Invalid type for PublicKey comparison");
729
688
  }
730
- return equalBytes(this.key, otherKey);
689
+ if (otherKey.length !== PUBLIC_KEY_SIZE) {
690
+ throw new Error(
691
+ `Invalid public key length for comparison: expected ${PUBLIC_KEY_SIZE} bytes, got ${otherKey.length}`
692
+ );
693
+ }
694
+ return (0, import_packet3.equalBytes)(this.key, otherKey);
731
695
  }
732
696
  verify(message, signature) {
733
697
  if (signature.length !== SIGNATURE_SIZE) {
734
698
  throw new Error(`Invalid signature length: expected ${SIGNATURE_SIZE} bytes, got ${signature.length}`);
735
699
  }
736
- return ed25519.verify(signature, message, this.key);
700
+ return import_ed25519.ed25519.verify(signature, message, this.key);
701
+ }
702
+ static fromBytes(key) {
703
+ return new _PublicKey(key);
704
+ }
705
+ static fromString(key) {
706
+ return new _PublicKey(key);
737
707
  }
738
708
  };
739
709
  var PrivateKey = class _PrivateKey {
740
710
  constructor(seed) {
741
711
  if (typeof seed === "string") {
742
- seed = hexToBytes(seed, SEED_SIZE);
712
+ seed = (0, import_packet3.hexToBytes)(seed);
743
713
  }
744
714
  if (seed.length !== SEED_SIZE) {
745
715
  throw new Error(`Invalid seed length: expected ${SEED_SIZE} bytes, got ${seed.length}`);
746
716
  }
747
- const { secretKey, publicKey } = ed25519.keygen(seed);
717
+ const { secretKey, publicKey } = import_ed25519.ed25519.keygen(seed);
748
718
  this.secretKey = secretKey;
749
719
  this.publicKey = new PublicKey(publicKey);
750
720
  }
@@ -755,10 +725,10 @@ var PrivateKey = class _PrivateKey {
755
725
  return this.secretKey;
756
726
  }
757
727
  toString() {
758
- return bytesToHex(this.secretKey);
728
+ return (0, import_packet3.bytesToHex)(this.secretKey);
759
729
  }
760
730
  sign(message) {
761
- return ed25519.sign(message, this.secretKey);
731
+ return import_ed25519.ed25519.sign(message, this.secretKey);
762
732
  }
763
733
  calculateSharedSecret(other) {
764
734
  let otherPublicKey;
@@ -771,43 +741,40 @@ var PrivateKey = class _PrivateKey {
771
741
  } else {
772
742
  throw new Error("Invalid type for calculateSharedSecret comparison");
773
743
  }
774
- return x25519.getSharedSecret(this.secretKey, otherPublicKey.toBytes());
744
+ return import_ed25519.x25519.getSharedSecret(this.secretKey, otherPublicKey.toBytes());
775
745
  }
776
746
  static generate() {
777
- const { secretKey } = ed25519.keygen();
747
+ const { secretKey } = import_ed25519.ed25519.keygen();
778
748
  return new _PrivateKey(secretKey);
779
749
  }
780
750
  };
781
751
  var SharedSecret = class _SharedSecret {
782
752
  constructor(secret) {
783
- if (secret.length === SHARED_SECRET_SIZE / 2) {
784
- const padded = new Uint8Array(SHARED_SECRET_SIZE);
785
- padded.set(secret, SHARED_SECRET_SIZE - secret.length);
786
- secret = padded;
787
- }
788
753
  if (secret.length !== SHARED_SECRET_SIZE) {
789
754
  throw new Error(`Invalid shared secret length: expected ${SHARED_SECRET_SIZE} bytes, got ${secret.length}`);
790
755
  }
791
- this.secret = secret;
756
+ this.secret = new Uint8Array(SHARED_SECRET_SIZE * 2);
757
+ this.secret.set(secret, 0);
792
758
  }
793
759
  toHash() {
794
- return this.secret[0];
760
+ const hash = import_sha22.sha256.create().update(this.secret.slice(0, 16)).digest();
761
+ return hash[0];
795
762
  }
796
763
  toBytes() {
797
- return this.secret;
764
+ return this.secret.slice(0, 16);
798
765
  }
799
766
  toString() {
800
- return bytesToHex(this.secret);
767
+ return (0, import_packet3.bytesToHex)(this.secret.slice(0, 16));
801
768
  }
802
769
  decrypt(hmac2, ciphertext) {
803
770
  if (hmac2.length !== HMAC_SIZE) {
804
771
  throw new Error(`Invalid HMAC length: expected ${HMAC_SIZE} bytes, got ${hmac2.length}`);
805
772
  }
806
773
  const expectedHmac = this.calculateHmac(ciphertext);
807
- if (!equalBytes(hmac2, expectedHmac)) {
808
- throw new Error(`Invalid HMAC: decryption failed: expected ${bytesToHex(expectedHmac)}, got ${bytesToHex(hmac2)}`);
774
+ if (!(0, import_packet3.equalBytes)(hmac2, expectedHmac)) {
775
+ throw new Error(`Invalid HMAC: decryption failed: expected ${(0, import_packet3.bytesToHex)(expectedHmac)}, got ${(0, import_packet3.bytesToHex)(hmac2)}`);
809
776
  }
810
- const cipher = ecb(this.secret.slice(0, 16), { disablePadding: true });
777
+ const cipher = (0, import_aes.ecb)(this.secret.slice(0, 16), { disablePadding: true });
811
778
  const plaintext = new Uint8Array(ciphertext.length);
812
779
  for (let i = 0; i < ciphertext.length; i += 16) {
813
780
  const block = ciphertext.slice(i, i + 16);
@@ -822,7 +789,7 @@ var SharedSecret = class _SharedSecret {
822
789
  }
823
790
  encrypt(data) {
824
791
  const key = this.secret.slice(0, 16);
825
- const cipher = ecb(key, { disablePadding: true });
792
+ const cipher = (0, import_aes.ecb)(key, { disablePadding: true });
826
793
  const fullBlocks = Math.floor(data.length / 16);
827
794
  const remaining = data.length % 16;
828
795
  const ciphertext = new Uint8Array((fullBlocks + (remaining > 0 ? 1 : 0)) * 16);
@@ -841,7 +808,7 @@ var SharedSecret = class _SharedSecret {
841
808
  return { hmac: hmac2, ciphertext };
842
809
  }
843
810
  calculateHmac(data) {
844
- return hmac(sha2562, this.secret, data).slice(0, HMAC_SIZE);
811
+ return (0, import_hmac.hmac)(import_sha22.sha256, this.secret, data).slice(0, HMAC_SIZE);
845
812
  }
846
813
  static fromName(name) {
847
814
  if (name === "Public") {
@@ -849,14 +816,14 @@ var SharedSecret = class _SharedSecret {
849
816
  } else if (!/^#/.test(name)) {
850
817
  throw new Error("Only the 'Public' group or groups starting with '#' are supported");
851
818
  }
852
- const hash = sha2562.create().update(new TextEncoder().encode(name)).digest();
819
+ const hash = import_sha22.sha256.create().update(new TextEncoder().encode(name)).digest();
853
820
  return new _SharedSecret(hash.slice(0, SHARED_SECRET_SIZE));
854
821
  }
855
822
  };
856
823
  var StaticSecret = class {
857
824
  constructor(secret) {
858
825
  if (typeof secret === "string") {
859
- secret = hexToBytes(secret, STATIC_SECRET_SIZE);
826
+ secret = (0, import_packet3.hexToBytes)(secret);
860
827
  }
861
828
  if (secret.length !== STATIC_SECRET_SIZE) {
862
829
  throw new Error(`Invalid static secret length: expected ${STATIC_SECRET_SIZE} bytes, got ${secret.length}`);
@@ -864,16 +831,17 @@ var StaticSecret = class {
864
831
  this.secret = secret;
865
832
  }
866
833
  publicKey() {
867
- const publicKey = x25519.getPublicKey(this.secret);
834
+ const publicKey = import_ed25519.x25519.getPublicKey(this.secret);
868
835
  return new PublicKey(publicKey);
869
836
  }
870
837
  diffieHellman(otherPublicKey) {
871
- const sharedSecret = x25519.getSharedSecret(this.secret, otherPublicKey.toBytes());
872
- return new SharedSecret(sharedSecret);
838
+ const sharedSecret = import_ed25519.x25519.getSharedSecret(this.secret, otherPublicKey.toBytes());
839
+ return new SharedSecret(sharedSecret.slice(0, 16));
873
840
  }
874
841
  };
875
842
 
876
843
  // src/identity.ts
844
+ var import_packet4 = require("@hamradio/packet");
877
845
  var parseNodeHash = (hash) => {
878
846
  if (hash instanceof Uint8Array) {
879
847
  return hash[0];
@@ -884,7 +852,7 @@ var parseNodeHash = (hash) => {
884
852
  }
885
853
  return hash;
886
854
  } else if (typeof hash === "string") {
887
- const parsed = hexToBytes(hash);
855
+ const parsed = (0, import_packet4.hexToBytes)(hash);
888
856
  if (parsed.length !== 1) {
889
857
  throw new Error("NodeHash string must represent a single byte");
890
858
  }
@@ -900,7 +868,7 @@ var toPublicKeyBytes = (key) => {
900
868
  } else if (key instanceof Uint8Array) {
901
869
  return key;
902
870
  } else if (typeof key === "string") {
903
- return hexToBytes(key);
871
+ return (0, import_packet4.hexToBytes)(key);
904
872
  } else {
905
873
  throw new Error("Invalid type for toPublicKeyBytes");
906
874
  }
@@ -959,7 +927,7 @@ var LocalIdentity = class extends Identity {
959
927
  } else {
960
928
  throw new Error("Invalid type for calculateSharedSecret comparison");
961
929
  }
962
- return new SharedSecret(this.privateKey.calculateSharedSecret(otherPublicKey));
930
+ return new SharedSecret(this.privateKey.calculateSharedSecret(otherPublicKey).slice(0, 16));
963
931
  }
964
932
  };
965
933
  var Contact = class {
@@ -1003,12 +971,12 @@ var Group = class {
1003
971
  if (data.length < 5) {
1004
972
  throw new Error("Invalid ciphertext");
1005
973
  }
1006
- const reader = new BufferReader(data);
1007
- const timestamp = reader.readTimestamp();
1008
- const flags = reader.readByte();
974
+ const reader = new import_packet4.Reader(data);
975
+ const timestamp = reader.date32();
976
+ const flags = reader.uint8();
1009
977
  const textType = flags >> 2 & 63;
1010
978
  const attempt = flags & 3;
1011
- const message = new TextDecoder("utf-8").decode(reader.readBytes());
979
+ const message = new TextDecoder("utf-8").decode(reader.bytes());
1012
980
  return {
1013
981
  timestamp,
1014
982
  textType,
@@ -1017,11 +985,11 @@ var Group = class {
1017
985
  };
1018
986
  }
1019
987
  encryptText(plain) {
1020
- const writer = new BufferWriter();
1021
- writer.writeTimestamp(plain.timestamp);
988
+ const writer = new import_packet4.Writer(4 + 1 + new TextEncoder().encode(plain.message).length);
989
+ writer.date32(plain.timestamp);
1022
990
  const flags = (plain.textType & 63) << 2 | plain.attempt & 3;
1023
- writer.writeByte(flags);
1024
- writer.writeBytes(new TextEncoder().encode(plain.message));
991
+ writer.uint8(flags);
992
+ writer.utf8String(plain.message);
1025
993
  const data = writer.toBytes();
1026
994
  return this.secret.encrypt(data);
1027
995
  }
@@ -1030,16 +998,16 @@ var Group = class {
1030
998
  if (data.length < 4) {
1031
999
  throw new Error("Invalid ciphertext");
1032
1000
  }
1033
- const reader = new BufferReader(data);
1001
+ const reader = new import_packet4.Reader(data);
1034
1002
  return {
1035
- timestamp: reader.readTimestamp(),
1036
- data: reader.readBytes(reader.remainingBytes())
1003
+ timestamp: reader.date32(),
1004
+ data: reader.bytes()
1037
1005
  };
1038
1006
  }
1039
1007
  encryptData(plain) {
1040
- const writer = new BufferWriter();
1041
- writer.writeTimestamp(plain.timestamp);
1042
- writer.writeBytes(plain.data);
1008
+ const writer = new import_packet4.Writer(4 + plain.data.length);
1009
+ writer.date32(plain.timestamp);
1010
+ writer.bytes(plain.data);
1043
1011
  const data = writer.toBytes();
1044
1012
  return this.secret.encrypt(data);
1045
1013
  }
@@ -1049,6 +1017,8 @@ var Contacts = class {
1049
1017
  this.localIdentities = [];
1050
1018
  this.contacts = {};
1051
1019
  this.groups = {};
1020
+ this.addGroup(new Group("Public"));
1021
+ this.addGroup(new Group("#test"));
1052
1022
  }
1053
1023
  addLocalIdentity(identity) {
1054
1024
  this.localIdentities.push({ identity, sharedSecrets: {} });
@@ -1060,6 +1030,23 @@ var Contacts = class {
1060
1030
  }
1061
1031
  this.contacts[hash].push(contact);
1062
1032
  }
1033
+ hasContact(nameOrHash) {
1034
+ if (typeof nameOrHash === "string") {
1035
+ return Object.values(this.contacts).flat().some((contact) => contact.name.toLowerCase() === nameOrHash.toLowerCase());
1036
+ } else {
1037
+ const hash = parseNodeHash(nameOrHash);
1038
+ return (this.contacts[hash] || []).length > 0;
1039
+ }
1040
+ }
1041
+ getContactByName(name) {
1042
+ const contact = Object.values(this.contacts).flat().find((contact2) => contact2.name.toLowerCase() === name.toLowerCase());
1043
+ return contact || null;
1044
+ }
1045
+ getContacts() {
1046
+ const contacts = Object.values(this.contacts).flat();
1047
+ contacts.sort((a, b) => a.name.localeCompare(b.name));
1048
+ return contacts;
1049
+ }
1063
1050
  decrypt(src, dst, hmac2, ciphertext) {
1064
1051
  let contacts = [];
1065
1052
  if (src instanceof PublicKey) {
@@ -1107,17 +1094,45 @@ var Contacts = class {
1107
1094
  return sharedSecret;
1108
1095
  }
1109
1096
  addGroup(group) {
1110
- const hash = parseNodeHash(group.hash());
1097
+ for (const key of Object.keys(this.groups)) {
1098
+ const hash2 = Number(key);
1099
+ this.groups[hash2] = this.groups[hash2].filter((g) => g.name.toLowerCase() !== group.name.toLowerCase());
1100
+ if (this.groups[hash2].length === 0) {
1101
+ delete this.groups[hash2];
1102
+ }
1103
+ }
1104
+ const hash = group.hash();
1111
1105
  if (!this.groups[hash]) {
1112
1106
  this.groups[hash] = [];
1113
1107
  }
1114
1108
  this.groups[hash].push(group);
1115
1109
  }
1110
+ hasGroup(nameOrHash) {
1111
+ if (typeof nameOrHash === "string") {
1112
+ return Object.values(this.groups).flat().some((group) => group.name.toLowerCase() === nameOrHash.toLowerCase());
1113
+ } else {
1114
+ const hash = parseNodeHash(nameOrHash);
1115
+ return (this.groups[hash] || []).length > 0;
1116
+ }
1117
+ }
1118
+ getGroupByName(name) {
1119
+ const group = Object.values(this.groups).flat().find((group2) => group2.name.toLowerCase() === name.toLowerCase());
1120
+ return group || null;
1121
+ }
1122
+ getGroups() {
1123
+ const groups = Object.values(this.groups).flat();
1124
+ groups.sort((a, b) => {
1125
+ if (a.name === "Public") return -1;
1126
+ if (b.name === "Public") return 1;
1127
+ return a.name.localeCompare(b.name);
1128
+ });
1129
+ return groups;
1130
+ }
1116
1131
  decryptGroupText(channelHash, hmac2, ciphertext) {
1117
1132
  const hash = parseNodeHash(channelHash);
1118
1133
  const groups = this.groups[hash] || [];
1119
1134
  if (groups.length === 0) {
1120
- throw new Error("Unknown group hash");
1135
+ throw new Error(`Unknown group hash ${hash.toString(16).padStart(2, "0")}`);
1121
1136
  }
1122
1137
  for (const group of groups) {
1123
1138
  try {
@@ -1126,13 +1141,13 @@ var Contacts = class {
1126
1141
  } catch {
1127
1142
  }
1128
1143
  }
1129
- throw new Error("Decryption failed with all known groups");
1144
+ throw new Error(`Decryption failed with all known groups with hash ${hash.toString(16).padStart(2, "0")}`);
1130
1145
  }
1131
1146
  decryptGroupData(channelHash, hmac2, ciphertext) {
1132
1147
  const hash = parseNodeHash(channelHash);
1133
1148
  const groups = this.groups[hash] || [];
1134
1149
  if (groups.length === 0) {
1135
- throw new Error("Unknown group hash");
1150
+ throw new Error(`Unknown group hash ${hash.toString(16).padStart(2, "0")}`);
1136
1151
  }
1137
1152
  for (const group of groups) {
1138
1153
  try {
@@ -1141,10 +1156,11 @@ var Contacts = class {
1141
1156
  } catch {
1142
1157
  }
1143
1158
  }
1144
- throw new Error("Decryption failed with all known groups");
1159
+ throw new Error(`Decryption failed with all known groups with hash ${hash.toString(16).padStart(2, "0")}`);
1145
1160
  }
1146
1161
  };
1147
- export {
1162
+ // Annotate the CommonJS export names for ESM import in node:
1163
+ 0 && (module.exports = {
1148
1164
  Contact,
1149
1165
  Contacts,
1150
1166
  Group,
@@ -1161,4 +1177,4 @@ export {
1161
1177
  StaticSecret,
1162
1178
  TextType,
1163
1179
  parseNodeHash
1164
- };
1180
+ });