@btc-vision/transaction 1.8.0-alpha.1 → 1.8.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/abi/ABICoder.d.ts +8 -0
  3. package/browser/buffer/BinaryReader.d.ts +16 -1
  4. package/browser/buffer/BinaryWriter.d.ts +11 -1
  5. package/browser/deterministic/ExtendedAddressMap.d.ts +3 -1
  6. package/browser/index.js +1102 -861
  7. package/browser/keypair/Address.d.ts +1 -0
  8. package/browser/utils/lengths.d.ts +3 -1
  9. package/browser/utils/types.d.ts +3 -0
  10. package/build/_version.d.ts +1 -1
  11. package/build/_version.js +1 -1
  12. package/build/abi/ABICoder.d.ts +8 -0
  13. package/build/abi/ABICoder.js +32 -0
  14. package/build/buffer/BinaryReader.d.ts +16 -1
  15. package/build/buffer/BinaryReader.js +66 -1
  16. package/build/buffer/BinaryWriter.d.ts +11 -1
  17. package/build/buffer/BinaryWriter.js +66 -1
  18. package/build/deterministic/ExtendedAddressMap.d.ts +3 -1
  19. package/build/deterministic/ExtendedAddressMap.js +44 -17
  20. package/build/keypair/Address.d.ts +1 -0
  21. package/build/keypair/Address.js +19 -4
  22. package/build/transaction/builders/MultiSignTransaction.js +2 -2
  23. package/build/transaction/shared/TweakedTransaction.js +3 -3
  24. package/build/tsconfig.build.tsbuildinfo +1 -1
  25. package/build/utils/lengths.d.ts +3 -1
  26. package/build/utils/lengths.js +3 -1
  27. package/build/utils/types.d.ts +3 -0
  28. package/package.json +1 -1
  29. package/src/_version.ts +1 -1
  30. package/src/abi/ABICoder.ts +43 -0
  31. package/src/buffer/BinaryReader.ts +158 -2
  32. package/src/buffer/BinaryWriter.ts +143 -1
  33. package/src/deterministic/ExtendedAddressMap.ts +59 -20
  34. package/src/keypair/Address.ts +27 -6
  35. package/src/transaction/builders/MultiSignTransaction.ts +2 -2
  36. package/src/transaction/shared/TweakedTransaction.ts +3 -3
  37. package/src/utils/lengths.ts +3 -1
  38. package/src/utils/types.ts +4 -1
  39. package/test/binary-reader-writer.test.ts +457 -0
  40. package/test/derivePath.test.ts +4 -4
@@ -207,7 +207,8 @@ export class Address extends Uint8Array {
207
207
  */
208
208
  public static fromBigInt(value: bigint, tweakedValue?: bigint): Address {
209
209
  const address = Address.bigintToUint8Array(value);
210
- const legacyAddress = tweakedValue ? Address.bigintToUint8Array(tweakedValue) : undefined;
210
+ const legacyAddress =
211
+ tweakedValue !== undefined ? Address.bigintToUint8Array(tweakedValue) : undefined;
211
212
 
212
213
  return new Address(address, legacyAddress);
213
214
  }
@@ -769,6 +770,7 @@ export class Address extends Uint8Array {
769
770
 
770
771
  public toTweakedHybridPublicKeyHex(): string {
771
772
  this.ensureLegacyProcessed();
773
+ this.ensureTweakedUncompressed();
772
774
  if (!this.#tweakedUncompressed) {
773
775
  throw new Error('Legacy public key not set');
774
776
  }
@@ -778,6 +780,7 @@ export class Address extends Uint8Array {
778
780
 
779
781
  public toTweakedHybridPublicKeyBuffer(): Buffer {
780
782
  this.ensureLegacyProcessed();
783
+ this.ensureTweakedUncompressed();
781
784
  if (!this.#tweakedUncompressed) {
782
785
  throw new Error('Legacy public key not set');
783
786
  }
@@ -785,6 +788,29 @@ export class Address extends Uint8Array {
785
788
  return this.#tweakedUncompressed;
786
789
  }
787
790
 
791
+ /**
792
+ * Lazily generates the tweaked uncompressed/hybrid key from the legacy public key.
793
+ * Only called when toTweakedHybridPublicKey* methods are accessed.
794
+ */
795
+ private ensureTweakedUncompressed(): void {
796
+ if (this.#tweakedUncompressed) return;
797
+
798
+ const key = this.#legacyPublicKey;
799
+ if (!key) return;
800
+
801
+ // Only attempt hybrid key generation for 32-byte keys that weren't processed through autoFormat
802
+ if (key.length === ADDRESS_BYTE_LENGTH && !this.#originalPublicKey) {
803
+ try {
804
+ const buf = Buffer.alloc(ADDRESS_BYTE_LENGTH);
805
+ buf.set(key);
806
+ this.#tweakedUncompressed = ContractAddress.generateHybridKeyFromHash(buf);
807
+ } catch {
808
+ // Hybrid key generation may fail for keys that aren't valid EC points
809
+ // (e.g., zero addresses). Leave #tweakedUncompressed undefined.
810
+ }
811
+ }
812
+ }
813
+
788
814
  /**
789
815
  * Sets the MLDSA key portion of the address.
790
816
  * @param {ArrayLike<number>} mldsaPublicKey - The MLDSA public key or its hash
@@ -837,11 +863,6 @@ export class Address extends Uint8Array {
837
863
  // Length validation already done in constructor
838
864
 
839
865
  if (pending.length === ADDRESS_BYTE_LENGTH) {
840
- // 32-byte input: already tweaked x-only, just generate hybrid
841
- const buf = Buffer.alloc(ADDRESS_BYTE_LENGTH);
842
- buf.set(pending);
843
-
844
- this.#tweakedUncompressed = ContractAddress.generateHybridKeyFromHash(buf);
845
866
  this.#legacyPublicKey = pending;
846
867
  } else {
847
868
  // 33 or 65 bytes: full autoFormat processing with EC operations
@@ -227,7 +227,7 @@ export class MultiSignTransaction extends TransactionBuilder<TransactionType.MUL
227
227
  input.tapScriptSig = (input.tapScriptSig || []).concat(partialSignatures);
228
228
  }
229
229
 
230
- delete input.finalScriptWitness;
230
+ Reflect.deleteProperty(input, 'finalScriptWitness');
231
231
 
232
232
  const signHashTypes: number[] = MultiSignTransaction.signHashTypesArray
233
233
  ? [MultiSignTransaction.calculateSignHash(MultiSignTransaction.signHashTypesArray)]
@@ -397,7 +397,7 @@ export class MultiSignTransaction extends TransactionBuilder<TransactionType.MUL
397
397
  );
398
398
  }
399
399
 
400
- delete input.finalScriptWitness;
400
+ Reflect.deleteProperty(input, 'finalScriptWitness');
401
401
 
402
402
  psbt.finalizeInput(
403
403
  i,
@@ -948,18 +948,18 @@ export abstract class TweakedTransaction extends Logger {
948
948
  if (isP2WPKH(redeemOutput)) {
949
949
  // P2SH-P2WPKH
950
950
  // Use witnessUtxo + redeemScript
951
- delete input.nonWitnessUtxo; // ensure we do NOT have nonWitnessUtxo
951
+ Reflect.deleteProperty(input, 'nonWitnessUtxo'); // ensure we do NOT have nonWitnessUtxo
952
952
  // witnessScript is not needed
953
953
  } else if (isP2WSHScript(redeemOutput)) {
954
954
  // P2SH-P2WSH
955
955
  // Use witnessUtxo + redeemScript + witnessScript
956
- delete input.nonWitnessUtxo; // ensure we do NOT have nonWitnessUtxo
956
+ Reflect.deleteProperty(input, 'nonWitnessUtxo'); // ensure we do NOT have nonWitnessUtxo
957
957
 
958
958
  this.processP2WSHInput(utxo, input, i);
959
959
  } else {
960
960
  // Legacy P2SH
961
961
  // Use nonWitnessUtxo
962
- delete input.witnessUtxo; // ensure we do NOT have witnessUtxo
962
+ Reflect.deleteProperty(input, 'witnessUtxo'); // ensure we do NOT have witnessUtxo
963
963
  }
964
964
  }
965
965
 
@@ -1,4 +1,6 @@
1
1
  export const ADDRESS_BYTE_LENGTH: number = 32;
2
+ export const EXTENDED_ADDRESS_BYTE_LENGTH: number = 64;
3
+ export const SCHNORR_SIGNATURE_BYTE_LENGTH: number = 64;
2
4
  export const SELECTOR_BYTE_LENGTH: number = 4;
3
5
 
4
6
  export const U256_BYTE_LENGTH: number = 32;
@@ -11,7 +13,7 @@ export const U8_BYTE_LENGTH: number = 1;
11
13
  export const I256_BYTE_LENGTH: number = 32;
12
14
  export const I128_BYTE_LENGTH: number = 16;
13
15
  export const I64_BYTE_LENGTH: number = 8;
14
- export const number_BYTE_LENGTH: number = 4;
16
+ export const I32_BYTE_LENGTH: number = 4;
15
17
  export const I16_BYTE_LENGTH: number = 2;
16
18
  export const I8_BYTE_LENGTH: number = 1;
17
19
 
@@ -8,11 +8,14 @@ export type MemorySlotData<T> = T;
8
8
  export type PointerStorage = DeterministicMap<MemorySlotPointer, MemorySlotData<bigint>>;
9
9
  export type BlockchainStorage = DeterministicMap<string, PointerStorage>;
10
10
 
11
+ export type i8 = number;
12
+ export type i16 = number;
11
13
  export type i32 = number;
14
+ export type i64 = bigint;
15
+
12
16
  export type u8 = number;
13
17
  export type u16 = number;
14
18
  export type u32 = number;
15
-
16
19
  export type u64 = bigint;
17
20
 
18
21
  export type Selector = number;
@@ -0,0 +1,457 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { Address, BinaryReader, BinaryWriter, ExtendedAddressMap } from '../src/opnet.js';
3
+
4
+ describe('BinaryReader/BinaryWriter', () => {
5
+ // Helper to create an Address with both MLDSA and tweaked keys
6
+ const createFullAddress = (mldsaValue: bigint, tweakedValue: bigint): Address => {
7
+ return Address.fromBigInt(mldsaValue, tweakedValue);
8
+ };
9
+
10
+ describe('Signed Integer Methods', () => {
11
+ describe('i8', () => {
12
+ it('should write and read positive i8', () => {
13
+ const writer = new BinaryWriter();
14
+ writer.writeI8(127);
15
+ writer.writeI8(0);
16
+ writer.writeI8(1);
17
+
18
+ const reader = new BinaryReader(writer.getBuffer());
19
+ expect(reader.readI8()).toBe(127);
20
+ expect(reader.readI8()).toBe(0);
21
+ expect(reader.readI8()).toBe(1);
22
+ });
23
+
24
+ it('should write and read negative i8', () => {
25
+ const writer = new BinaryWriter();
26
+ writer.writeI8(-128);
27
+ writer.writeI8(-1);
28
+ writer.writeI8(-50);
29
+
30
+ const reader = new BinaryReader(writer.getBuffer());
31
+ expect(reader.readI8()).toBe(-128);
32
+ expect(reader.readI8()).toBe(-1);
33
+ expect(reader.readI8()).toBe(-50);
34
+ });
35
+
36
+ it('should throw on out of range i8', () => {
37
+ const writer = new BinaryWriter();
38
+ expect(() => writer.writeI8(128)).toThrow();
39
+ expect(() => writer.writeI8(-129)).toThrow();
40
+ });
41
+ });
42
+
43
+ describe('i16', () => {
44
+ it('should write and read positive i16 big-endian', () => {
45
+ const writer = new BinaryWriter();
46
+ writer.writeI16(32767);
47
+ writer.writeI16(256);
48
+ writer.writeI16(0);
49
+
50
+ const reader = new BinaryReader(writer.getBuffer());
51
+ expect(reader.readI16()).toBe(32767);
52
+ expect(reader.readI16()).toBe(256);
53
+ expect(reader.readI16()).toBe(0);
54
+ });
55
+
56
+ it('should write and read negative i16 big-endian', () => {
57
+ const writer = new BinaryWriter();
58
+ writer.writeI16(-32768);
59
+ writer.writeI16(-1);
60
+ writer.writeI16(-256);
61
+
62
+ const reader = new BinaryReader(writer.getBuffer());
63
+ expect(reader.readI16()).toBe(-32768);
64
+ expect(reader.readI16()).toBe(-1);
65
+ expect(reader.readI16()).toBe(-256);
66
+ });
67
+
68
+ it('should write and read i16 little-endian', () => {
69
+ const writer = new BinaryWriter();
70
+ writer.writeI16(12345, false);
71
+ writer.writeI16(-12345, false);
72
+
73
+ const reader = new BinaryReader(writer.getBuffer());
74
+ expect(reader.readI16(false)).toBe(12345);
75
+ expect(reader.readI16(false)).toBe(-12345);
76
+ });
77
+
78
+ it('should throw on out of range i16', () => {
79
+ const writer = new BinaryWriter();
80
+ expect(() => writer.writeI16(32768)).toThrow();
81
+ expect(() => writer.writeI16(-32769)).toThrow();
82
+ });
83
+ });
84
+
85
+ describe('i32', () => {
86
+ it('should write and read positive i32 big-endian', () => {
87
+ const writer = new BinaryWriter();
88
+ writer.writeI32(2147483647);
89
+ writer.writeI32(65536);
90
+ writer.writeI32(0);
91
+
92
+ const reader = new BinaryReader(writer.getBuffer());
93
+ expect(reader.readI32()).toBe(2147483647);
94
+ expect(reader.readI32()).toBe(65536);
95
+ expect(reader.readI32()).toBe(0);
96
+ });
97
+
98
+ it('should write and read negative i32 big-endian', () => {
99
+ const writer = new BinaryWriter();
100
+ writer.writeI32(-2147483648);
101
+ writer.writeI32(-1);
102
+ writer.writeI32(-65536);
103
+
104
+ const reader = new BinaryReader(writer.getBuffer());
105
+ expect(reader.readI32()).toBe(-2147483648);
106
+ expect(reader.readI32()).toBe(-1);
107
+ expect(reader.readI32()).toBe(-65536);
108
+ });
109
+
110
+ it('should write and read i32 little-endian', () => {
111
+ const writer = new BinaryWriter();
112
+ writer.writeI32(123456789, false);
113
+ writer.writeI32(-123456789, false);
114
+
115
+ const reader = new BinaryReader(writer.getBuffer());
116
+ expect(reader.readI32(false)).toBe(123456789);
117
+ expect(reader.readI32(false)).toBe(-123456789);
118
+ });
119
+
120
+ it('should throw on out of range i32', () => {
121
+ const writer = new BinaryWriter();
122
+ expect(() => writer.writeI32(2147483648)).toThrow();
123
+ expect(() => writer.writeI32(-2147483649)).toThrow();
124
+ });
125
+ });
126
+
127
+ describe('i64', () => {
128
+ it('should write and read positive i64 big-endian', () => {
129
+ const writer = new BinaryWriter();
130
+ writer.writeI64(9223372036854775807n);
131
+ writer.writeI64(4294967296n);
132
+ writer.writeI64(0n);
133
+
134
+ const reader = new BinaryReader(writer.getBuffer());
135
+ expect(reader.readI64()).toBe(9223372036854775807n);
136
+ expect(reader.readI64()).toBe(4294967296n);
137
+ expect(reader.readI64()).toBe(0n);
138
+ });
139
+
140
+ it('should write and read negative i64 big-endian', () => {
141
+ const writer = new BinaryWriter();
142
+ writer.writeI64(-9223372036854775808n);
143
+ writer.writeI64(-1n);
144
+ writer.writeI64(-4294967296n);
145
+
146
+ const reader = new BinaryReader(writer.getBuffer());
147
+ expect(reader.readI64()).toBe(-9223372036854775808n);
148
+ expect(reader.readI64()).toBe(-1n);
149
+ expect(reader.readI64()).toBe(-4294967296n);
150
+ });
151
+
152
+ it('should write and read i64 little-endian', () => {
153
+ const writer = new BinaryWriter();
154
+ writer.writeI64(1234567890123456789n, false);
155
+ writer.writeI64(-1234567890123456789n, false);
156
+
157
+ const reader = new BinaryReader(writer.getBuffer());
158
+ expect(reader.readI64(false)).toBe(1234567890123456789n);
159
+ expect(reader.readI64(false)).toBe(-1234567890123456789n);
160
+ });
161
+
162
+ it('should throw on out of range i64', () => {
163
+ const writer = new BinaryWriter();
164
+ expect(() => writer.writeI64(9223372036854775808n)).toThrow();
165
+ expect(() => writer.writeI64(-9223372036854775809n)).toThrow();
166
+ });
167
+ });
168
+ });
169
+
170
+ describe('Extended Address Methods', () => {
171
+ describe('readExtendedAddress / writeExtendedAddress', () => {
172
+ it('should write and read extended address', () => {
173
+ const writer = new BinaryWriter();
174
+ const address = createFullAddress(123n, 456n);
175
+
176
+ writer.writeExtendedAddress(address);
177
+
178
+ const reader = new BinaryReader(writer.getBuffer());
179
+ const result = reader.readExtendedAddress();
180
+
181
+ expect(result.toBigInt()).toBe(123n);
182
+ expect(result.tweakedToBigInt()).toBe(456n);
183
+ });
184
+
185
+ it('should write and read multiple extended addresses', () => {
186
+ const writer = new BinaryWriter();
187
+ const addr1 = createFullAddress(100n, 200n);
188
+ const addr2 = createFullAddress(300n, 400n);
189
+ const addr3 = createFullAddress(500n, 600n);
190
+
191
+ writer.writeExtendedAddress(addr1);
192
+ writer.writeExtendedAddress(addr2);
193
+ writer.writeExtendedAddress(addr3);
194
+
195
+ const reader = new BinaryReader(writer.getBuffer());
196
+
197
+ const result1 = reader.readExtendedAddress();
198
+ expect(result1.toBigInt()).toBe(100n);
199
+ expect(result1.tweakedToBigInt()).toBe(200n);
200
+
201
+ const result2 = reader.readExtendedAddress();
202
+ expect(result2.toBigInt()).toBe(300n);
203
+ expect(result2.tweakedToBigInt()).toBe(400n);
204
+
205
+ const result3 = reader.readExtendedAddress();
206
+ expect(result3.toBigInt()).toBe(500n);
207
+ expect(result3.tweakedToBigInt()).toBe(600n);
208
+ });
209
+
210
+ it('should handle zero addresses', () => {
211
+ const writer = new BinaryWriter();
212
+ const address = createFullAddress(0n, 0n);
213
+
214
+ writer.writeExtendedAddress(address);
215
+
216
+ const reader = new BinaryReader(writer.getBuffer());
217
+ const result = reader.readExtendedAddress();
218
+
219
+ expect(result.toBigInt()).toBe(0n);
220
+ expect(result.tweakedToBigInt()).toBe(0n);
221
+ });
222
+
223
+ it('should handle max value addresses', () => {
224
+ const writer = new BinaryWriter();
225
+ const maxValue = 2n ** 256n - 1n;
226
+ const address = createFullAddress(maxValue, maxValue);
227
+
228
+ writer.writeExtendedAddress(address);
229
+
230
+ const reader = new BinaryReader(writer.getBuffer());
231
+ const result = reader.readExtendedAddress();
232
+
233
+ expect(result.toBigInt()).toBe(maxValue);
234
+ expect(result.tweakedToBigInt()).toBe(maxValue);
235
+ });
236
+ });
237
+
238
+ describe('readExtendedAddressArray / writeExtendedAddressArray', () => {
239
+ it('should write and read empty array', () => {
240
+ const writer = new BinaryWriter();
241
+ writer.writeExtendedAddressArray([]);
242
+
243
+ const reader = new BinaryReader(writer.getBuffer());
244
+ const result = reader.readExtendedAddressArray();
245
+
246
+ expect(result).toEqual([]);
247
+ });
248
+
249
+ it('should write and read array of extended addresses', () => {
250
+ const writer = new BinaryWriter();
251
+ const addresses = [
252
+ createFullAddress(1n, 2n),
253
+ createFullAddress(3n, 4n),
254
+ createFullAddress(5n, 6n),
255
+ ];
256
+
257
+ writer.writeExtendedAddressArray(addresses);
258
+
259
+ const reader = new BinaryReader(writer.getBuffer());
260
+ const result = reader.readExtendedAddressArray();
261
+
262
+ expect(result.length).toBe(3);
263
+ expect(result[0].toBigInt()).toBe(1n);
264
+ expect(result[0].tweakedToBigInt()).toBe(2n);
265
+ expect(result[1].toBigInt()).toBe(3n);
266
+ expect(result[1].tweakedToBigInt()).toBe(4n);
267
+ expect(result[2].toBigInt()).toBe(5n);
268
+ expect(result[2].tweakedToBigInt()).toBe(6n);
269
+ });
270
+
271
+ it('should handle large arrays', () => {
272
+ const writer = new BinaryWriter();
273
+ const addresses: Address[] = [];
274
+ for (let i = 0; i < 100; i++) {
275
+ addresses.push(createFullAddress(BigInt(i), BigInt(i * 2)));
276
+ }
277
+
278
+ writer.writeExtendedAddressArray(addresses);
279
+
280
+ const reader = new BinaryReader(writer.getBuffer());
281
+ const result = reader.readExtendedAddressArray();
282
+
283
+ expect(result.length).toBe(100);
284
+ for (let i = 0; i < 100; i++) {
285
+ expect(result[i].toBigInt()).toBe(BigInt(i));
286
+ expect(result[i].tweakedToBigInt()).toBe(BigInt(i * 2));
287
+ }
288
+ });
289
+ });
290
+ });
291
+
292
+ describe('ExtendedAddressMapU256 Methods', () => {
293
+ describe('readExtendedAddressMapU256 / writeExtendedAddressMapU256', () => {
294
+ it('should write and read empty map', () => {
295
+ const writer = new BinaryWriter();
296
+ const map = new ExtendedAddressMap<bigint>();
297
+
298
+ writer.writeExtendedAddressMapU256(map);
299
+
300
+ const reader = new BinaryReader(writer.getBuffer());
301
+ const result = reader.readExtendedAddressMapU256();
302
+
303
+ expect(result.size).toBe(0);
304
+ });
305
+
306
+ it('should write and read map with entries', () => {
307
+ const writer = new BinaryWriter();
308
+ const map = new ExtendedAddressMap<bigint>();
309
+
310
+ const addr1 = createFullAddress(100n, 200n);
311
+ const addr2 = createFullAddress(300n, 400n);
312
+
313
+ map.set(addr1, 1000n);
314
+ map.set(addr2, 2000n);
315
+
316
+ writer.writeExtendedAddressMapU256(map);
317
+
318
+ const reader = new BinaryReader(writer.getBuffer());
319
+ const result = reader.readExtendedAddressMapU256();
320
+
321
+ expect(result.size).toBe(2);
322
+ });
323
+
324
+ it('should handle large u256 values', () => {
325
+ const writer = new BinaryWriter();
326
+ const map = new ExtendedAddressMap<bigint>();
327
+
328
+ const addr = createFullAddress(1n, 2n);
329
+ const largeValue = 2n ** 256n - 1n;
330
+
331
+ map.set(addr, largeValue);
332
+
333
+ writer.writeExtendedAddressMapU256(map);
334
+
335
+ const reader = new BinaryReader(writer.getBuffer());
336
+ const result = reader.readExtendedAddressMapU256();
337
+
338
+ expect(result.size).toBe(1);
339
+ });
340
+ });
341
+ });
342
+
343
+ describe('Schnorr Signature Methods', () => {
344
+ describe('readSchnorrSignature / writeSchnorrSignature', () => {
345
+ it('should write and read Schnorr signature', () => {
346
+ const writer = new BinaryWriter();
347
+ const address = createFullAddress(12345n, 67890n);
348
+ const signature = new Uint8Array(64);
349
+ for (let i = 0; i < 64; i++) {
350
+ signature[i] = i;
351
+ }
352
+
353
+ writer.writeSchnorrSignature(address, signature);
354
+
355
+ const reader = new BinaryReader(writer.getBuffer());
356
+ const result = reader.readSchnorrSignature();
357
+
358
+ expect(result.address.toBigInt()).toBe(12345n);
359
+ expect(result.address.tweakedToBigInt()).toBe(67890n);
360
+ expect(result.signature.length).toBe(64);
361
+ for (let i = 0; i < 64; i++) {
362
+ expect(result.signature[i]).toBe(i);
363
+ }
364
+ });
365
+
366
+ it('should throw on invalid signature length', () => {
367
+ const writer = new BinaryWriter();
368
+ const address = createFullAddress(1n, 2n);
369
+ const invalidSignature = new Uint8Array(32); // Should be 64
370
+
371
+ expect(() => writer.writeSchnorrSignature(address, invalidSignature)).toThrow();
372
+ });
373
+
374
+ it('should handle multiple signatures', () => {
375
+ const writer = new BinaryWriter();
376
+
377
+ const sig1 = new Uint8Array(64).fill(1);
378
+ const sig2 = new Uint8Array(64).fill(2);
379
+
380
+ writer.writeSchnorrSignature(createFullAddress(1n, 2n), sig1);
381
+ writer.writeSchnorrSignature(createFullAddress(3n, 4n), sig2);
382
+
383
+ const reader = new BinaryReader(writer.getBuffer());
384
+
385
+ const result1 = reader.readSchnorrSignature();
386
+ expect(result1.address.toBigInt()).toBe(1n);
387
+ expect(result1.signature[0]).toBe(1);
388
+
389
+ const result2 = reader.readSchnorrSignature();
390
+ expect(result2.address.toBigInt()).toBe(3n);
391
+ expect(result2.signature[0]).toBe(2);
392
+ });
393
+ });
394
+ });
395
+
396
+ describe('Mixed Operations', () => {
397
+ it('should handle mixed data types in sequence', () => {
398
+ const writer = new BinaryWriter();
399
+
400
+ // Write various types
401
+ writer.writeI8(-50);
402
+ writer.writeI16(-1000);
403
+ writer.writeI32(-100000);
404
+ writer.writeI64(-10000000000n);
405
+ writer.writeExtendedAddress(createFullAddress(111n, 222n));
406
+ writer.writeU256(999n);
407
+
408
+ const reader = new BinaryReader(writer.getBuffer());
409
+
410
+ expect(reader.readI8()).toBe(-50);
411
+ expect(reader.readI16()).toBe(-1000);
412
+ expect(reader.readI32()).toBe(-100000);
413
+ expect(reader.readI64()).toBe(-10000000000n);
414
+
415
+ const addr = reader.readExtendedAddress();
416
+ expect(addr.toBigInt()).toBe(111n);
417
+ expect(addr.tweakedToBigInt()).toBe(222n);
418
+
419
+ expect(reader.readU256()).toBe(999n);
420
+ });
421
+
422
+ it('should correctly track buffer position', () => {
423
+ const writer = new BinaryWriter();
424
+
425
+ writer.writeI8(1);
426
+ writer.writeI16(2);
427
+ writer.writeI32(3);
428
+ writer.writeI64(4n);
429
+ writer.writeExtendedAddress(createFullAddress(5n, 6n));
430
+
431
+ const buffer = writer.getBuffer();
432
+ // i8: 1 byte, i16: 2 bytes, i32: 4 bytes, i64: 8 bytes, extended address: 64 bytes
433
+ expect(buffer.length).toBe(1 + 2 + 4 + 8 + 64);
434
+ });
435
+ });
436
+
437
+ describe('Error Handling', () => {
438
+ it('should throw when reading beyond buffer', () => {
439
+ const writer = new BinaryWriter();
440
+ writer.writeI8(1);
441
+
442
+ const reader = new BinaryReader(writer.getBuffer());
443
+ reader.readI8();
444
+
445
+ expect(() => reader.readI8()).toThrow();
446
+ });
447
+
448
+ it('should throw when reading extended address from insufficient buffer', () => {
449
+ const writer = new BinaryWriter();
450
+ writer.writeU256(1n); // Only 32 bytes
451
+
452
+ const reader = new BinaryReader(writer.getBuffer());
453
+
454
+ expect(() => reader.readExtendedAddress()).toThrow();
455
+ });
456
+ });
457
+ });
@@ -419,7 +419,7 @@ describe('Mnemonic.deriveOPWallet', () => {
419
419
  });
420
420
  });
421
421
 
422
- describe('deriveMultipleOPWallet', () => {
422
+ describe('deriveMultipleUnisat', () => {
423
423
  it('should derive multiple wallets', () => {
424
424
  const mnemonic = new Mnemonic(
425
425
  testMnemonic,
@@ -428,7 +428,7 @@ describe('Mnemonic.deriveOPWallet', () => {
428
428
  MLDSASecurityLevel.LEVEL2,
429
429
  );
430
430
 
431
- const wallets = mnemonic.deriveMultipleOPWallet(AddressTypes.P2TR, 5);
431
+ const wallets = mnemonic.deriveMultipleUnisat(AddressTypes.P2TR, 5);
432
432
 
433
433
  expect(wallets.length).toBe(5);
434
434
  expect(wallets[0].p2tr).toBeDefined();
@@ -443,7 +443,7 @@ describe('Mnemonic.deriveOPWallet', () => {
443
443
  MLDSASecurityLevel.LEVEL2,
444
444
  );
445
445
 
446
- const wallets = mnemonic.deriveMultipleOPWallet(AddressTypes.P2TR, 3);
446
+ const wallets = mnemonic.deriveMultipleUnisat(AddressTypes.P2TR, 3);
447
447
 
448
448
  const addresses = wallets.map((w) => w.p2tr);
449
449
  const uniqueAddresses = new Set(addresses);
@@ -459,7 +459,7 @@ describe('Mnemonic.deriveOPWallet', () => {
459
459
  MLDSASecurityLevel.LEVEL2,
460
460
  );
461
461
 
462
- const wallets = mnemonic.deriveMultipleOPWallet(AddressTypes.P2TR, 2, 5);
462
+ const wallets = mnemonic.deriveMultipleUnisat(AddressTypes.P2TR, 2, 5);
463
463
  const wallet5 = mnemonic.deriveOPWallet(AddressTypes.P2TR, 5);
464
464
 
465
465
  expect(wallets[0].p2tr).toBe(wallet5.p2tr);