@hamradio/meshcore 1.2.1 → 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,60 +147,83 @@ 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}`);
238
160
  }
239
161
  this.structure = [
240
162
  /* Header segment */
241
- { name: "header", data: new Uint8Array([this.header, this.pathLength, ...this.path]), fields: [
242
- /* Header flags */
163
+ {
164
+ name: "header",
165
+ data: new Uint8Array([this.header]).buffer,
166
+ fields: [
167
+ /* Header flags */
168
+ {
169
+ name: "flags",
170
+ type: import_packet2.FieldType.BITS,
171
+ length: 1,
172
+ bits: [
173
+ { name: "payload version", size: 2 },
174
+ { name: "payload type", size: 4 },
175
+ { name: "route type", size: 2 }
176
+ ]
177
+ }
178
+ ]
179
+ },
180
+ /* Transport codes */
181
+ ..._Packet.hasTransportCodes(this.routeType) ? [
243
182
  {
244
- name: "flags",
245
- type: 0 /* BITS */,
246
- size: 1,
247
- bits: [
248
- { name: "payload version", size: 2 },
249
- { name: "payload type", size: 4 },
250
- { name: "route type", size: 2 }
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
+ }
251
203
  ]
252
- },
253
- /* Transport codes */
254
- ..._Packet.hasTransportCodes(this.routeType) ? [
204
+ }
205
+ ] : [],
206
+ /* Path length and hashes */
207
+ {
208
+ name: "path",
209
+ data: new Uint8Array([this.pathLength, ...this.path]).buffer,
210
+ fields: [
255
211
  {
256
- name: "transport code 1",
257
- type: 3 /* UINT16_BE */,
258
- size: 2
212
+ name: "path length",
213
+ type: import_packet2.FieldType.UINT8,
214
+ length: 1,
215
+ bits: [
216
+ { name: "path hash size", size: 2 },
217
+ { name: "path hash count", size: 6 }
218
+ ]
259
219
  },
260
220
  {
261
- name: "transport code 2",
262
- type: 3 /* UINT16_BE */,
263
- size: 2
221
+ name: "path hashes",
222
+ type: pathHashType,
223
+ length: this.path.length
264
224
  }
265
- ] : [],
266
- /* Path length and hashes */
267
- {
268
- name: "path length",
269
- type: 1 /* UINT8 */,
270
- size: 1,
271
- bits: [
272
- { name: "path hash size", size: 2 },
273
- { name: "path hash count", size: 6 }
274
- ]
275
- },
276
- {
277
- name: "path hashes",
278
- type: pathHashType,
279
- size: this.path.length
280
- }
281
- ] }
225
+ ]
226
+ }
282
227
  ];
283
228
  }
284
229
  decode(withStructure) {
@@ -320,7 +265,6 @@ var Packet = class _Packet {
320
265
  default:
321
266
  throw new Error(`Unsupported payload type: ${this.payloadType}`);
322
267
  }
323
- console.log("packet decode with structure:", typeof withStructure, withStructure, { result });
324
268
  if (typeof withStructure === "boolean" && withStructure && "segment" in result && "payload" in result) {
325
269
  this.ensureStructure();
326
270
  const structure = [...this.structure, result.segment];
@@ -329,17 +273,17 @@ var Packet = class _Packet {
329
273
  return result;
330
274
  }
331
275
  decodeEncryptedPayload(reader) {
332
- const cipherMAC = reader.readBytes(2);
333
- const cipherText = reader.readBytes(reader.remainingBytes());
276
+ const cipherMAC = reader.bytes(2);
277
+ const cipherText = reader.bytes();
334
278
  return { cipherMAC, cipherText };
335
279
  }
336
280
  decodeRequest(withSegment) {
337
281
  if (this.payload.length < 4) {
338
282
  throw new Error("Invalid request payload: too short");
339
283
  }
340
- const reader = new BufferReader(this.payload);
341
- const dst = reader.readByte();
342
- const src = reader.readByte();
284
+ const reader = import_packet2.Reader.fromBytes(this.payload);
285
+ const dst = reader.uint8();
286
+ const src = reader.uint8();
343
287
  const encrypted = this.decodeEncryptedPayload(reader);
344
288
  const payload = {
345
289
  type: 0 /* REQUEST */,
@@ -350,12 +294,17 @@ var Packet = class _Packet {
350
294
  if (typeof withSegment === "boolean" && withSegment) {
351
295
  const segment = {
352
296
  name: "request payload",
353
- data: this.payload,
297
+ data: new Uint8Array(this.payload).buffer,
354
298
  fields: [
355
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: dst },
356
- { name: "source hash", type: 1 /* UINT8 */, size: 1, value: src },
357
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: encrypted.cipherMAC },
358
- { 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
+ }
359
308
  ]
360
309
  };
361
310
  return { payload, segment };
@@ -366,9 +315,9 @@ var Packet = class _Packet {
366
315
  if (this.payload.length < 4) {
367
316
  throw new Error("Invalid response payload: too short");
368
317
  }
369
- const reader = new BufferReader(this.payload);
370
- const dst = reader.readByte();
371
- const src = reader.readByte();
318
+ const reader = import_packet2.Reader.fromBytes(this.payload);
319
+ const dst = reader.uint8();
320
+ const src = reader.uint8();
372
321
  const encrypted = this.decodeEncryptedPayload(reader);
373
322
  const payload = {
374
323
  type: 1 /* RESPONSE */,
@@ -379,12 +328,17 @@ var Packet = class _Packet {
379
328
  if (typeof withSegment === "boolean" && withSegment) {
380
329
  const segment = {
381
330
  name: "response payload",
382
- data: this.payload,
331
+ data: new Uint8Array(this.payload).buffer,
383
332
  fields: [
384
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: dst },
385
- { name: "source hash", type: 1 /* UINT8 */, size: 1, value: src },
386
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: encrypted.cipherMAC },
387
- { 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
+ }
388
342
  ]
389
343
  };
390
344
  return { payload, segment };
@@ -395,9 +349,9 @@ var Packet = class _Packet {
395
349
  if (this.payload.length < 4) {
396
350
  throw new Error("Invalid text payload: too short");
397
351
  }
398
- const reader = new BufferReader(this.payload);
399
- const dst = reader.readByte();
400
- const src = reader.readByte();
352
+ const reader = import_packet2.Reader.fromBytes(this.payload);
353
+ const dst = reader.uint8();
354
+ const src = reader.uint8();
401
355
  const encrypted = this.decodeEncryptedPayload(reader);
402
356
  const payload = {
403
357
  type: 2 /* TEXT */,
@@ -408,12 +362,17 @@ var Packet = class _Packet {
408
362
  if (typeof withSegment === "boolean" && withSegment) {
409
363
  const segment = {
410
364
  name: "text payload",
411
- data: this.payload,
365
+ data: new Uint8Array(this.payload).buffer,
412
366
  fields: [
413
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: dst },
414
- { name: "source hash", type: 1 /* UINT8 */, size: 1, value: src },
415
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: encrypted.cipherMAC },
416
- { 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
+ }
417
376
  ]
418
377
  };
419
378
  return { payload, segment };
@@ -424,8 +383,8 @@ var Packet = class _Packet {
424
383
  if (this.payload.length < 4) {
425
384
  throw new Error("Invalid ack payload: too short");
426
385
  }
427
- const reader = new BufferReader(this.payload);
428
- const checksum = reader.readBytes(4);
386
+ const reader = import_packet2.Reader.fromBytes(this.payload);
387
+ const checksum = reader.bytes(4);
429
388
  const payload = {
430
389
  type: 3 /* ACK */,
431
390
  checksum
@@ -433,10 +392,8 @@ var Packet = class _Packet {
433
392
  if (typeof withSegment === "boolean" && withSegment) {
434
393
  const segment = {
435
394
  name: "ack payload",
436
- data: this.payload,
437
- fields: [
438
- { name: "checksum", type: 6 /* BYTES */, size: 4, value: checksum }
439
- ]
395
+ data: new Uint8Array(this.payload).buffer,
396
+ fields: [{ name: "checksum", type: import_packet2.FieldType.BYTES, length: 4, value: checksum }]
440
397
  };
441
398
  return { payload, segment };
442
399
  }
@@ -446,26 +403,26 @@ var Packet = class _Packet {
446
403
  if (this.payload.length < 4) {
447
404
  throw new Error("Invalid advert payload: too short");
448
405
  }
449
- const reader = new BufferReader(this.payload);
406
+ const reader = import_packet2.Reader.fromBytes(this.payload);
450
407
  const payload = {
451
408
  type: 4 /* ADVERT */,
452
- publicKey: reader.readBytes(32),
453
- timestamp: reader.readTimestamp(),
454
- signature: reader.readBytes(64)
409
+ publicKey: reader.bytes(32),
410
+ timestamp: reader.date32(),
411
+ signature: reader.bytes(64)
455
412
  };
456
413
  let segment;
457
414
  if (typeof withSegment === "boolean" && withSegment) {
458
415
  segment = {
459
416
  name: "advert payload",
460
- data: this.payload,
417
+ data: new Uint8Array(this.payload).buffer,
461
418
  fields: [
462
- { type: 6 /* BYTES */, name: "public key", size: 32 },
463
- { type: 4 /* UINT32_LE */, name: "timestamp", size: 4, value: payload.timestamp },
464
- { 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 }
465
422
  ]
466
423
  };
467
424
  }
468
- const flags = reader.readByte();
425
+ const flags = reader.uint8();
469
426
  const appdata = {
470
427
  nodeType: flags & 15,
471
428
  hasLocation: (flags & 16 /* HAS_LOCATION */) !== 0,
@@ -474,44 +431,50 @@ var Packet = class _Packet {
474
431
  hasName: (flags & 128 /* HAS_NAME */) !== 0
475
432
  };
476
433
  if (typeof withSegment === "boolean" && withSegment) {
477
- segment.fields.push({ type: 0 /* BITS */, name: "flags", size: 1, value: flags, bits: [
478
- { size: 1, name: "name flag" },
479
- { size: 1, name: "feature2 flag" },
480
- { size: 1, name: "feature1 flag" },
481
- { size: 1, name: "location flag" },
482
- { size: 4, name: "node type" }
483
- ] });
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
+ });
484
447
  }
485
448
  if (appdata.hasLocation) {
486
- const lat = reader.readInt32LE() / 1e5;
487
- const lon = reader.readInt32LE() / 1e5;
449
+ const lat = reader.int32() / 1e6;
450
+ const lon = reader.int32() / 1e6;
488
451
  appdata.location = [lat, lon];
489
452
  if (typeof withSegment === "boolean" && withSegment) {
490
- segment.fields.push({ type: 4 /* UINT32_LE */, name: "latitude", size: 4, value: lat });
491
- 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 });
492
455
  }
493
456
  }
494
457
  if (appdata.hasFeature1) {
495
- appdata.feature1 = reader.readUint16LE();
458
+ appdata.feature1 = reader.uint16();
496
459
  if (typeof withSegment === "boolean" && withSegment) {
497
- 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 });
498
461
  }
499
462
  }
500
463
  if (appdata.hasFeature2) {
501
- appdata.feature2 = reader.readUint16LE();
464
+ appdata.feature2 = reader.uint16();
502
465
  if (typeof withSegment === "boolean" && withSegment) {
503
- 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 });
504
467
  }
505
468
  }
506
469
  if (appdata.hasName) {
507
- const nameBytes = reader.readBytes();
508
- let nullPos = nameBytes.indexOf(0);
509
- if (nullPos === -1) {
510
- nullPos = nameBytes.length;
511
- }
512
- appdata.name = new TextDecoder("utf-8").decode(nameBytes.subarray(0, nullPos));
470
+ appdata.name = reader.cString();
513
471
  if (typeof withSegment === "boolean" && withSegment) {
514
- 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
+ });
515
478
  }
516
479
  }
517
480
  if (typeof withSegment === "boolean" && withSegment && typeof segment !== "undefined") {
@@ -523,8 +486,8 @@ var Packet = class _Packet {
523
486
  if (this.payload.length < 3) {
524
487
  throw new Error("Invalid group text payload: too short");
525
488
  }
526
- const reader = new BufferReader(this.payload);
527
- const channelHash = reader.readByte();
489
+ const reader = import_packet2.Reader.fromBytes(this.payload);
490
+ const channelHash = reader.uint8();
528
491
  const encrypted = this.decodeEncryptedPayload(reader);
529
492
  const payload = {
530
493
  type: 5 /* GROUP_TEXT */,
@@ -534,11 +497,16 @@ var Packet = class _Packet {
534
497
  if (typeof withSegment === "boolean" && withSegment) {
535
498
  const segment = {
536
499
  name: "group text payload",
537
- data: this.payload,
500
+ data: new Uint8Array(this.payload).buffer,
538
501
  fields: [
539
- { name: "channel hash", type: 1 /* UINT8 */, size: 1, value: channelHash },
540
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: encrypted.cipherMAC },
541
- { 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
+ }
542
510
  ]
543
511
  };
544
512
  return { payload, segment };
@@ -549,20 +517,25 @@ var Packet = class _Packet {
549
517
  if (this.payload.length < 3) {
550
518
  throw new Error("Invalid group data payload: too short");
551
519
  }
552
- const reader = new BufferReader(this.payload);
520
+ const reader = import_packet2.Reader.fromBytes(this.payload);
553
521
  const payload = {
554
522
  type: 6 /* GROUP_DATA */,
555
- channelHash: reader.readByte(),
523
+ channelHash: reader.uint8(),
556
524
  encrypted: this.decodeEncryptedPayload(reader)
557
525
  };
558
526
  if (typeof withSegment === "boolean" && withSegment) {
559
527
  const segment = {
560
528
  name: "group data payload",
561
- data: this.payload,
529
+ data: new Uint8Array(this.payload).buffer,
562
530
  fields: [
563
- { name: "channel hash", type: 1 /* UINT8 */, size: 1, value: payload.channelHash },
564
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: payload.encrypted.cipherMAC },
565
- { 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
+ }
566
539
  ]
567
540
  };
568
541
  return { payload, segment };
@@ -573,22 +546,27 @@ var Packet = class _Packet {
573
546
  if (this.payload.length < 1 + 32 + 2) {
574
547
  throw new Error("Invalid anon req payload: too short");
575
548
  }
576
- const reader = new BufferReader(this.payload);
549
+ const reader = import_packet2.Reader.fromBytes(this.payload);
577
550
  const payload = {
578
551
  type: 7 /* ANON_REQ */,
579
- dst: reader.readByte(),
580
- publicKey: reader.readBytes(32),
552
+ dst: reader.uint8(),
553
+ publicKey: reader.bytes(32),
581
554
  encrypted: this.decodeEncryptedPayload(reader)
582
555
  };
583
556
  if (typeof withSegment === "boolean" && withSegment) {
584
557
  const segment = {
585
558
  name: "anon req payload",
586
- data: this.payload,
559
+ data: new Uint8Array(this.payload).buffer,
587
560
  fields: [
588
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: payload.dst },
589
- { name: "public key", type: 6 /* BYTES */, size: 32, value: payload.publicKey },
590
- { name: "cipher MAC", type: 6 /* BYTES */, size: 2, value: payload.encrypted.cipherMAC },
591
- { 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
+ }
592
570
  ]
593
571
  };
594
572
  return { payload, segment };
@@ -599,19 +577,19 @@ var Packet = class _Packet {
599
577
  if (this.payload.length < 2) {
600
578
  throw new Error("Invalid path payload: too short");
601
579
  }
602
- const reader = new BufferReader(this.payload);
580
+ const reader = import_packet2.Reader.fromBytes(this.payload);
603
581
  const payload = {
604
582
  type: 8 /* PATH */,
605
- dst: reader.readByte(),
606
- src: reader.readByte()
583
+ dst: reader.uint8(),
584
+ src: reader.uint8()
607
585
  };
608
586
  if (typeof withSegment === "boolean" && withSegment) {
609
587
  const segment = {
610
588
  name: "path payload",
611
- data: this.payload,
589
+ data: new Uint8Array(this.payload).buffer,
612
590
  fields: [
613
- { name: "destination hash", type: 1 /* UINT8 */, size: 1, value: payload.dst },
614
- { 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 }
615
593
  ]
616
594
  };
617
595
  return { payload, segment };
@@ -622,23 +600,23 @@ var Packet = class _Packet {
622
600
  if (this.payload.length < 9) {
623
601
  throw new Error("Invalid trace payload: too short");
624
602
  }
625
- const reader = new BufferReader(this.payload);
603
+ const reader = import_packet2.Reader.fromBytes(this.payload);
626
604
  const payload = {
627
605
  type: 9 /* TRACE */,
628
- tag: reader.readUint32LE() >>> 0,
629
- authCode: reader.readUint32LE() >>> 0,
630
- flags: reader.readByte() & 3,
631
- nodes: reader.readBytes()
606
+ tag: reader.uint32(),
607
+ authCode: reader.uint32(),
608
+ flags: reader.uint8() & 3,
609
+ nodes: reader.bytes()
632
610
  };
633
611
  if (typeof withSegment === "boolean" && withSegment) {
634
612
  const segment = {
635
613
  name: "trace payload",
636
- data: this.payload,
614
+ data: new Uint8Array(this.payload).buffer,
637
615
  fields: [
638
- { name: "tag", type: 8 /* DWORDS */, size: 4, value: payload.tag },
639
- { name: "auth code", type: 8 /* DWORDS */, size: 4, value: payload.authCode },
640
- { name: "flags", type: 1 /* UINT8 */, size: 1, value: payload.flags },
641
- { 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 }
642
620
  ]
643
621
  };
644
622
  return { payload, segment };
@@ -653,10 +631,8 @@ var Packet = class _Packet {
653
631
  if (typeof withSegment === "boolean" && withSegment) {
654
632
  const segment = {
655
633
  name: "raw custom payload",
656
- data: this.payload,
657
- fields: [
658
- { name: "data", type: 6 /* BYTES */, size: this.payload.length, value: this.payload }
659
- ]
634
+ data: new Uint8Array(this.payload).buffer,
635
+ fields: [{ name: "data", type: import_packet2.FieldType.BYTES, length: this.payload.length, value: this.payload }]
660
636
  };
661
637
  return { payload, segment };
662
638
  }
@@ -665,35 +641,39 @@ var Packet = class _Packet {
665
641
  };
666
642
 
667
643
  // src/crypto.ts
668
- import { ed25519, x25519 } from "@noble/curves/ed25519.js";
669
- import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
670
- import { hmac } from "@noble/hashes/hmac.js";
671
- 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");
672
649
  var PUBLIC_KEY_SIZE = 32;
673
650
  var SEED_SIZE = 32;
674
651
  var HMAC_SIZE = 2;
675
- var SHARED_SECRET_SIZE = 32;
652
+ var SHARED_SECRET_SIZE = 16;
676
653
  var SIGNATURE_SIZE = 64;
677
654
  var STATIC_SECRET_SIZE = 32;
678
- var publicSecret = hexToBytes("8b3387e9c5cdea6ac9e5edbaa115cd72", 16);
655
+ var publicSecret = (0, import_packet3.hexToBytes)("8b3387e9c5cdea6ac9e5edbaa115cd72");
679
656
  var PublicKey = class _PublicKey {
680
657
  constructor(key) {
681
658
  if (typeof key === "string") {
682
- this.key = hexToBytes(key, PUBLIC_KEY_SIZE);
659
+ this.key = (0, import_packet3.hexToBytes)(key);
683
660
  } else if (key instanceof Uint8Array) {
684
661
  this.key = key;
685
662
  } else {
686
663
  throw new Error("Invalid type for PublicKey constructor");
687
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
+ }
688
668
  }
689
669
  toHash() {
690
- return sha2562.create().update(this.key).digest()[0];
670
+ return import_sha22.sha256.create().update(this.key).digest()[0];
691
671
  }
692
672
  toBytes() {
693
673
  return this.key;
694
674
  }
695
675
  toString() {
696
- return bytesToHex(this.key);
676
+ return (0, import_packet3.bytesToHex)(this.key);
697
677
  }
698
678
  equals(other) {
699
679
  let otherKey;
@@ -702,28 +682,39 @@ var PublicKey = class _PublicKey {
702
682
  } else if (other instanceof Uint8Array) {
703
683
  otherKey = other;
704
684
  } else if (typeof other === "string") {
705
- otherKey = hexToBytes(other, PUBLIC_KEY_SIZE);
685
+ otherKey = (0, import_packet3.hexToBytes)(other);
706
686
  } else {
707
687
  throw new Error("Invalid type for PublicKey comparison");
708
688
  }
709
- 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);
710
695
  }
711
696
  verify(message, signature) {
712
697
  if (signature.length !== SIGNATURE_SIZE) {
713
698
  throw new Error(`Invalid signature length: expected ${SIGNATURE_SIZE} bytes, got ${signature.length}`);
714
699
  }
715
- 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);
716
707
  }
717
708
  };
718
709
  var PrivateKey = class _PrivateKey {
719
710
  constructor(seed) {
720
711
  if (typeof seed === "string") {
721
- seed = hexToBytes(seed, SEED_SIZE);
712
+ seed = (0, import_packet3.hexToBytes)(seed);
722
713
  }
723
714
  if (seed.length !== SEED_SIZE) {
724
715
  throw new Error(`Invalid seed length: expected ${SEED_SIZE} bytes, got ${seed.length}`);
725
716
  }
726
- const { secretKey, publicKey } = ed25519.keygen(seed);
717
+ const { secretKey, publicKey } = import_ed25519.ed25519.keygen(seed);
727
718
  this.secretKey = secretKey;
728
719
  this.publicKey = new PublicKey(publicKey);
729
720
  }
@@ -734,10 +725,10 @@ var PrivateKey = class _PrivateKey {
734
725
  return this.secretKey;
735
726
  }
736
727
  toString() {
737
- return bytesToHex(this.secretKey);
728
+ return (0, import_packet3.bytesToHex)(this.secretKey);
738
729
  }
739
730
  sign(message) {
740
- return ed25519.sign(message, this.secretKey);
731
+ return import_ed25519.ed25519.sign(message, this.secretKey);
741
732
  }
742
733
  calculateSharedSecret(other) {
743
734
  let otherPublicKey;
@@ -750,43 +741,40 @@ var PrivateKey = class _PrivateKey {
750
741
  } else {
751
742
  throw new Error("Invalid type for calculateSharedSecret comparison");
752
743
  }
753
- return x25519.getSharedSecret(this.secretKey, otherPublicKey.toBytes());
744
+ return import_ed25519.x25519.getSharedSecret(this.secretKey, otherPublicKey.toBytes());
754
745
  }
755
746
  static generate() {
756
- const { secretKey } = ed25519.keygen();
747
+ const { secretKey } = import_ed25519.ed25519.keygen();
757
748
  return new _PrivateKey(secretKey);
758
749
  }
759
750
  };
760
751
  var SharedSecret = class _SharedSecret {
761
752
  constructor(secret) {
762
- if (secret.length === SHARED_SECRET_SIZE / 2) {
763
- const padded = new Uint8Array(SHARED_SECRET_SIZE);
764
- padded.set(secret, SHARED_SECRET_SIZE - secret.length);
765
- secret = padded;
766
- }
767
753
  if (secret.length !== SHARED_SECRET_SIZE) {
768
754
  throw new Error(`Invalid shared secret length: expected ${SHARED_SECRET_SIZE} bytes, got ${secret.length}`);
769
755
  }
770
- this.secret = secret;
756
+ this.secret = new Uint8Array(SHARED_SECRET_SIZE * 2);
757
+ this.secret.set(secret, 0);
771
758
  }
772
759
  toHash() {
773
- return this.secret[0];
760
+ const hash = import_sha22.sha256.create().update(this.secret.slice(0, 16)).digest();
761
+ return hash[0];
774
762
  }
775
763
  toBytes() {
776
- return this.secret;
764
+ return this.secret.slice(0, 16);
777
765
  }
778
766
  toString() {
779
- return bytesToHex(this.secret);
767
+ return (0, import_packet3.bytesToHex)(this.secret.slice(0, 16));
780
768
  }
781
769
  decrypt(hmac2, ciphertext) {
782
770
  if (hmac2.length !== HMAC_SIZE) {
783
771
  throw new Error(`Invalid HMAC length: expected ${HMAC_SIZE} bytes, got ${hmac2.length}`);
784
772
  }
785
773
  const expectedHmac = this.calculateHmac(ciphertext);
786
- if (!equalBytes(hmac2, expectedHmac)) {
787
- 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)}`);
788
776
  }
789
- const cipher = ecb(this.secret.slice(0, 16), { disablePadding: true });
777
+ const cipher = (0, import_aes.ecb)(this.secret.slice(0, 16), { disablePadding: true });
790
778
  const plaintext = new Uint8Array(ciphertext.length);
791
779
  for (let i = 0; i < ciphertext.length; i += 16) {
792
780
  const block = ciphertext.slice(i, i + 16);
@@ -801,7 +789,7 @@ var SharedSecret = class _SharedSecret {
801
789
  }
802
790
  encrypt(data) {
803
791
  const key = this.secret.slice(0, 16);
804
- const cipher = ecb(key, { disablePadding: true });
792
+ const cipher = (0, import_aes.ecb)(key, { disablePadding: true });
805
793
  const fullBlocks = Math.floor(data.length / 16);
806
794
  const remaining = data.length % 16;
807
795
  const ciphertext = new Uint8Array((fullBlocks + (remaining > 0 ? 1 : 0)) * 16);
@@ -820,7 +808,7 @@ var SharedSecret = class _SharedSecret {
820
808
  return { hmac: hmac2, ciphertext };
821
809
  }
822
810
  calculateHmac(data) {
823
- 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);
824
812
  }
825
813
  static fromName(name) {
826
814
  if (name === "Public") {
@@ -828,14 +816,14 @@ var SharedSecret = class _SharedSecret {
828
816
  } else if (!/^#/.test(name)) {
829
817
  throw new Error("Only the 'Public' group or groups starting with '#' are supported");
830
818
  }
831
- const hash = sha2562.create().update(new TextEncoder().encode(name)).digest();
819
+ const hash = import_sha22.sha256.create().update(new TextEncoder().encode(name)).digest();
832
820
  return new _SharedSecret(hash.slice(0, SHARED_SECRET_SIZE));
833
821
  }
834
822
  };
835
823
  var StaticSecret = class {
836
824
  constructor(secret) {
837
825
  if (typeof secret === "string") {
838
- secret = hexToBytes(secret, STATIC_SECRET_SIZE);
826
+ secret = (0, import_packet3.hexToBytes)(secret);
839
827
  }
840
828
  if (secret.length !== STATIC_SECRET_SIZE) {
841
829
  throw new Error(`Invalid static secret length: expected ${STATIC_SECRET_SIZE} bytes, got ${secret.length}`);
@@ -843,16 +831,17 @@ var StaticSecret = class {
843
831
  this.secret = secret;
844
832
  }
845
833
  publicKey() {
846
- const publicKey = x25519.getPublicKey(this.secret);
834
+ const publicKey = import_ed25519.x25519.getPublicKey(this.secret);
847
835
  return new PublicKey(publicKey);
848
836
  }
849
837
  diffieHellman(otherPublicKey) {
850
- const sharedSecret = x25519.getSharedSecret(this.secret, otherPublicKey.toBytes());
851
- return new SharedSecret(sharedSecret);
838
+ const sharedSecret = import_ed25519.x25519.getSharedSecret(this.secret, otherPublicKey.toBytes());
839
+ return new SharedSecret(sharedSecret.slice(0, 16));
852
840
  }
853
841
  };
854
842
 
855
843
  // src/identity.ts
844
+ var import_packet4 = require("@hamradio/packet");
856
845
  var parseNodeHash = (hash) => {
857
846
  if (hash instanceof Uint8Array) {
858
847
  return hash[0];
@@ -863,7 +852,7 @@ var parseNodeHash = (hash) => {
863
852
  }
864
853
  return hash;
865
854
  } else if (typeof hash === "string") {
866
- const parsed = hexToBytes(hash);
855
+ const parsed = (0, import_packet4.hexToBytes)(hash);
867
856
  if (parsed.length !== 1) {
868
857
  throw new Error("NodeHash string must represent a single byte");
869
858
  }
@@ -879,7 +868,7 @@ var toPublicKeyBytes = (key) => {
879
868
  } else if (key instanceof Uint8Array) {
880
869
  return key;
881
870
  } else if (typeof key === "string") {
882
- return hexToBytes(key);
871
+ return (0, import_packet4.hexToBytes)(key);
883
872
  } else {
884
873
  throw new Error("Invalid type for toPublicKeyBytes");
885
874
  }
@@ -938,7 +927,7 @@ var LocalIdentity = class extends Identity {
938
927
  } else {
939
928
  throw new Error("Invalid type for calculateSharedSecret comparison");
940
929
  }
941
- return new SharedSecret(this.privateKey.calculateSharedSecret(otherPublicKey));
930
+ return new SharedSecret(this.privateKey.calculateSharedSecret(otherPublicKey).slice(0, 16));
942
931
  }
943
932
  };
944
933
  var Contact = class {
@@ -982,12 +971,12 @@ var Group = class {
982
971
  if (data.length < 5) {
983
972
  throw new Error("Invalid ciphertext");
984
973
  }
985
- const reader = new BufferReader(data);
986
- const timestamp = reader.readTimestamp();
987
- const flags = reader.readByte();
974
+ const reader = new import_packet4.Reader(data);
975
+ const timestamp = reader.date32();
976
+ const flags = reader.uint8();
988
977
  const textType = flags >> 2 & 63;
989
978
  const attempt = flags & 3;
990
- const message = new TextDecoder("utf-8").decode(reader.readBytes());
979
+ const message = new TextDecoder("utf-8").decode(reader.bytes());
991
980
  return {
992
981
  timestamp,
993
982
  textType,
@@ -996,11 +985,11 @@ var Group = class {
996
985
  };
997
986
  }
998
987
  encryptText(plain) {
999
- const writer = new BufferWriter();
1000
- writer.writeTimestamp(plain.timestamp);
988
+ const writer = new import_packet4.Writer(4 + 1 + new TextEncoder().encode(plain.message).length);
989
+ writer.date32(plain.timestamp);
1001
990
  const flags = (plain.textType & 63) << 2 | plain.attempt & 3;
1002
- writer.writeByte(flags);
1003
- writer.writeBytes(new TextEncoder().encode(plain.message));
991
+ writer.uint8(flags);
992
+ writer.utf8String(plain.message);
1004
993
  const data = writer.toBytes();
1005
994
  return this.secret.encrypt(data);
1006
995
  }
@@ -1009,16 +998,16 @@ var Group = class {
1009
998
  if (data.length < 4) {
1010
999
  throw new Error("Invalid ciphertext");
1011
1000
  }
1012
- const reader = new BufferReader(data);
1001
+ const reader = new import_packet4.Reader(data);
1013
1002
  return {
1014
- timestamp: reader.readTimestamp(),
1015
- data: reader.readBytes(reader.remainingBytes())
1003
+ timestamp: reader.date32(),
1004
+ data: reader.bytes()
1016
1005
  };
1017
1006
  }
1018
1007
  encryptData(plain) {
1019
- const writer = new BufferWriter();
1020
- writer.writeTimestamp(plain.timestamp);
1021
- 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);
1022
1011
  const data = writer.toBytes();
1023
1012
  return this.secret.encrypt(data);
1024
1013
  }
@@ -1028,6 +1017,8 @@ var Contacts = class {
1028
1017
  this.localIdentities = [];
1029
1018
  this.contacts = {};
1030
1019
  this.groups = {};
1020
+ this.addGroup(new Group("Public"));
1021
+ this.addGroup(new Group("#test"));
1031
1022
  }
1032
1023
  addLocalIdentity(identity) {
1033
1024
  this.localIdentities.push({ identity, sharedSecrets: {} });
@@ -1039,6 +1030,23 @@ var Contacts = class {
1039
1030
  }
1040
1031
  this.contacts[hash].push(contact);
1041
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
+ }
1042
1050
  decrypt(src, dst, hmac2, ciphertext) {
1043
1051
  let contacts = [];
1044
1052
  if (src instanceof PublicKey) {
@@ -1086,17 +1094,45 @@ var Contacts = class {
1086
1094
  return sharedSecret;
1087
1095
  }
1088
1096
  addGroup(group) {
1089
- 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();
1090
1105
  if (!this.groups[hash]) {
1091
1106
  this.groups[hash] = [];
1092
1107
  }
1093
1108
  this.groups[hash].push(group);
1094
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
+ }
1095
1131
  decryptGroupText(channelHash, hmac2, ciphertext) {
1096
1132
  const hash = parseNodeHash(channelHash);
1097
1133
  const groups = this.groups[hash] || [];
1098
1134
  if (groups.length === 0) {
1099
- throw new Error("Unknown group hash");
1135
+ throw new Error(`Unknown group hash ${hash.toString(16).padStart(2, "0")}`);
1100
1136
  }
1101
1137
  for (const group of groups) {
1102
1138
  try {
@@ -1105,13 +1141,13 @@ var Contacts = class {
1105
1141
  } catch {
1106
1142
  }
1107
1143
  }
1108
- 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")}`);
1109
1145
  }
1110
1146
  decryptGroupData(channelHash, hmac2, ciphertext) {
1111
1147
  const hash = parseNodeHash(channelHash);
1112
1148
  const groups = this.groups[hash] || [];
1113
1149
  if (groups.length === 0) {
1114
- throw new Error("Unknown group hash");
1150
+ throw new Error(`Unknown group hash ${hash.toString(16).padStart(2, "0")}`);
1115
1151
  }
1116
1152
  for (const group of groups) {
1117
1153
  try {
@@ -1120,10 +1156,11 @@ var Contacts = class {
1120
1156
  } catch {
1121
1157
  }
1122
1158
  }
1123
- 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")}`);
1124
1160
  }
1125
1161
  };
1126
- export {
1162
+ // Annotate the CommonJS export names for ESM import in node:
1163
+ 0 && (module.exports = {
1127
1164
  Contact,
1128
1165
  Contacts,
1129
1166
  Group,
@@ -1140,4 +1177,4 @@ export {
1140
1177
  StaticSecret,
1141
1178
  TextType,
1142
1179
  parseNodeHash
1143
- };
1180
+ });