@bsv/sdk 1.0.4 → 1.0.5

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 (52) hide show
  1. package/dist/cjs/src/primitives/BigNumber.js +1 -1
  2. package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
  3. package/dist/cjs/src/primitives/SymmetricKey.js +1 -1
  4. package/dist/cjs/src/primitives/SymmetricKey.js.map +1 -1
  5. package/dist/cjs/src/script/Spend.js +3 -2
  6. package/dist/cjs/src/script/Spend.js.map +1 -1
  7. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  8. package/dist/esm/src/primitives/BigNumber.js +1 -1
  9. package/dist/esm/src/primitives/BigNumber.js.map +1 -1
  10. package/dist/esm/src/primitives/SymmetricKey.js +1 -1
  11. package/dist/esm/src/primitives/SymmetricKey.js.map +1 -1
  12. package/dist/esm/src/script/Spend.js +3 -2
  13. package/dist/esm/src/script/Spend.js.map +1 -1
  14. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  15. package/dist/types/src/primitives/SymmetricKey.d.ts.map +1 -1
  16. package/dist/types/src/script/Spend.d.ts.map +1 -1
  17. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  18. package/docs/examples/EXAMPLE_BUILDING_CUSTOM_TX_BROADCASTER.md +89 -0
  19. package/docs/examples/EXAMPLE_COMPLEX_TX.md +164 -0
  20. package/docs/examples/EXAMPLE_ECIES.md +37 -0
  21. package/docs/examples/EXAMPLE_ENCRYPT_DECRYPT_MESSAGE.md +52 -0
  22. package/docs/examples/EXAMPLE_FEE_MODELING.md +199 -0
  23. package/docs/examples/EXAMPLE_HD_WALLETS.md +71 -0
  24. package/docs/examples/EXAMPLE_MESSAGE_SIGNING.md +63 -0
  25. package/docs/examples/EXAMPLE_PULSE_HEADERS.md +140 -0
  26. package/docs/examples/EXAMPLE_SCRIPT_TEMPLATES.md +170 -0
  27. package/docs/examples/EXAMPLE_SIMPLE_TX.md +64 -0
  28. package/docs/examples/EXAMPLE_TYPE_42.md +108 -0
  29. package/docs/examples/EXAMPLE_VERIFYING_BEEF.md +55 -0
  30. package/docs/examples/EXAMPLE_VERIFYING_SPENDS.md +69 -0
  31. package/docs/examples/GETTING_STARTED_NODE_CJS.md +73 -0
  32. package/docs/examples/GETTING_STARTED_REACT.md +121 -0
  33. package/docs/examples/README.md +19 -0
  34. package/docs/low-level/README.md +6 -0
  35. package/docs/low-level/TX_SIG.md +129 -0
  36. package/docs/low-level/TYPE_42.md +0 -0
  37. package/docs/primitives.md +585 -562
  38. package/docs/script.md +4 -4
  39. package/package.json +1 -1
  40. package/src/primitives/BigNumber.ts +2 -1
  41. package/src/primitives/Hash.ts +118 -64
  42. package/src/primitives/PrivateKey.ts +28 -1
  43. package/src/primitives/PublicKey.ts +24 -2
  44. package/src/primitives/SymmetricKey.ts +17 -3
  45. package/src/primitives/__tests/HMAC.test.ts +2 -2
  46. package/src/primitives/__tests/Hash.test.ts +2 -2
  47. package/src/primitives/index.ts +1 -0
  48. package/src/primitives/utils.ts +3 -3
  49. package/src/script/__tests/Script.test.ts +34 -0
  50. package/src/script/__tests/Spend.test.ts +7 -7
  51. package/src/script/templates/P2PKH.ts +13 -4
  52. package/src/transaction/__tests/Transaction.test.ts +1 -1
package/docs/script.md CHANGED
@@ -611,7 +611,7 @@ This class provides methods to create Pay To Public Key Hash locking and unlocki
611
611
 
612
612
  ```ts
613
613
  export default class P2PKH implements ScriptTemplate {
614
- lock(pubkeyhash: number[]): LockingScript
614
+ lock(pubkeyhash: string | number[]): LockingScript
615
615
  unlock(privateKey: PrivateKey, signOutputs: "all" | "none" | "single" = "all", anyoneCanPay: boolean = false): {
616
616
  sign: (tx: Transaction, inputIndex: number) => Promise<UnlockingScript>;
617
617
  estimateLength: () => Promise<106>;
@@ -625,10 +625,10 @@ export default class P2PKH implements ScriptTemplate {
625
625
 
626
626
  #### Method lock
627
627
 
628
- Creates a P2PKH locking script for a given public key hash.
628
+ Creates a P2PKH locking script for a given public key hash or address string
629
629
 
630
630
  ```ts
631
- lock(pubkeyhash: number[]): LockingScript
631
+ lock(pubkeyhash: string | number[]): LockingScript
632
632
  ```
633
633
 
634
634
  Returns
@@ -638,7 +638,7 @@ Returns
638
638
  Argument Details
639
639
 
640
640
  + **pubkeyhash**
641
- + An array representing the public key hash.
641
+ + or address - An array or address representing the public key hash.
642
642
 
643
643
  #### Method unlock
644
644
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/sdk",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "type": "module",
5
5
  "description": "BSV Blockchain Standard Development Kit",
6
6
  "main": "dist/cjs/mod.js",
@@ -194,6 +194,7 @@ export default class BigNumber {
194
194
  base: number | 'be' | 'le' | 'hex' = 10,
195
195
  endian: 'be' | 'le' = 'be'
196
196
  ) {
197
+
197
198
  this.negative = 0
198
199
  this.words = []
199
200
  this.length = 0
@@ -634,7 +635,7 @@ export default class BigNumber {
634
635
  * @returns - Returns the BigNumber after stripping leading zeros.
635
636
  *
636
637
  * @example
637
- * const bn = new BigNumber('000000", 2, "be");
638
+ * const bn = new BigNumber("000000", 2, "be");
638
639
  * bn.strip();
639
640
  * // bn now represents 0
640
641
  */
@@ -68,7 +68,11 @@ abstract class BaseHash {
68
68
  throw new Error('Not implemented')
69
69
  }
70
70
 
71
- _digest(enc?: 'hex'): number[] | string {
71
+ _digest(): number[] {
72
+ throw new Error('Not implemented')
73
+ }
74
+
75
+ _digestHex(): string {
72
76
  throw new Error('Not implemented')
73
77
  }
74
78
 
@@ -85,7 +89,7 @@ abstract class BaseHash {
85
89
  * @example
86
90
  * sha256.update('Hello World', 'utf8');
87
91
  */
88
- update(msg: number[] | string, enc?: 'hex'): this {
92
+ update(msg: number[] | string, enc?: 'hex' | 'utf8'): this {
89
93
  // Convert message to array, pad it, and join into 32bit blocks
90
94
  msg = toArray(msg, enc)
91
95
  if (this.pending == null) {
@@ -117,18 +121,34 @@ abstract class BaseHash {
117
121
  * Finalizes the hash computation and returns the hash value/result.
118
122
  *
119
123
  * @method digest
120
- * @param enc - The encoding of the final hash. If 'hex' then a hex string will be provided, otherwise an array of numbers.
121
124
  *
122
125
  * @returns Returns the final hash value.
123
126
  *
124
127
  * @example
125
- * const hash = sha256.digest('hex');
128
+ * const hash = sha256.digest();
126
129
  */
127
- digest(enc?: 'hex'): number[] | string {
130
+ digest(): number[] {
128
131
  this.update(this._pad())
129
132
  assert(this.pending === null)
130
133
 
131
- return this._digest(enc)
134
+ return this._digest()
135
+ };
136
+
137
+ /**
138
+ * Finalizes the hash computation and returns the hash value/result as a hex string.
139
+ *
140
+ * @method digest
141
+ *
142
+ * @returns Returns the final hash value as a hex string.
143
+ *
144
+ * @example
145
+ * const hash = sha256.digestHex();
146
+ */
147
+ digestHex(): string {
148
+ this.update(this._pad())
149
+ assert(this.pending === null)
150
+
151
+ return this._digestHex()
132
152
  };
133
153
 
134
154
  /**
@@ -189,7 +209,13 @@ function isSurrogatePair(msg: string, i: number): boolean {
189
209
  return (msg.charCodeAt(i + 1) & 0xFC00) === 0xDC00
190
210
  }
191
211
 
192
- export function toArray(msg: number[] | string, enc?: 'hex'): number[] {
212
+ /**
213
+ *
214
+ * @param msg
215
+ * @param enc Optional. Encoding to use if msg is string. Default is 'utf8'.
216
+ * @returns array of byte values from msg. If msg is an array, a copy is returned.
217
+ */
218
+ export function toArray(msg: number[] | string, enc?: 'hex' | 'utf8'): number[] {
193
219
  if (Array.isArray(msg)) { return msg.slice() }
194
220
  if (!(msg as unknown as boolean)) { return [] }
195
221
  const res = []
@@ -563,12 +589,12 @@ export class RIPEMD160 extends BaseHash {
563
589
  this.h[0] = T
564
590
  }
565
591
 
566
- _digest(enc?: 'hex'): string | number[] {
567
- if (enc === 'hex') {
568
- return toHex32(this.h, 'little')
569
- } else {
592
+ _digest(): number[] {
570
593
  return split32(this.h, 'little')
571
- }
594
+ }
595
+
596
+ _digestHex(): string {
597
+ return toHex32(this.h, 'little')
572
598
  }
573
599
  }
574
600
 
@@ -667,12 +693,12 @@ export class SHA256 extends BaseHash {
667
693
  this.h[7] = sum32(this.h[7], h)
668
694
  };
669
695
 
670
- _digest(enc?: 'hex'): number[] | string {
671
- if (enc === 'hex') {
672
- return toHex32(this.h, 'big')
673
- } else {
674
- return split32(this.h, 'big')
675
- }
696
+ _digest(): number[] {
697
+ return split32(this.h, 'big')
698
+ }
699
+
700
+ _digestHex(): string {
701
+ return toHex32(this.h, 'big')
676
702
  }
677
703
  }
678
704
 
@@ -745,12 +771,12 @@ export class SHA1 extends BaseHash {
745
771
  this.h[4] = sum32(this.h[4], e)
746
772
  }
747
773
 
748
- _digest(enc?: 'hex'): number[] | string {
749
- if (enc === 'hex') {
750
- return toHex32(this.h, 'big')
751
- } else {
752
- return split32(this.h, 'big')
753
- }
774
+ _digest(): number[] {
775
+ return split32(this.h, 'big')
776
+ }
777
+
778
+ _digestHex(): string {
779
+ return toHex32(this.h, 'big')
754
780
  }
755
781
  }
756
782
 
@@ -956,11 +982,12 @@ export class SHA512 extends BaseHash {
956
982
  sum64(this.h, 14, hh, hl);
957
983
  }
958
984
 
959
- _digest(enc) {
960
- if (enc === 'hex')
961
- return toHex32(this.h, 'big');
962
- else
963
- return split32(this.h, 'big');
985
+ _digest() {
986
+ return split32(this.h, 'big');
987
+ }
988
+
989
+ _digestHex() {
990
+ return toHex32(this.h, 'big');
964
991
  }
965
992
  }
966
993
 
@@ -1151,15 +1178,28 @@ export class SHA256HMAC {
1151
1178
  * Finalizes the HMAC computation and returns the resultant hash.
1152
1179
  *
1153
1180
  * @method digest
1154
- * @param enc - If 'hex', then the output is encoded as hexadecimal. If undefined or not 'hex', then no encoding is performed.
1155
1181
  * @returns Returns the digest of the hashed data. Can be a number array or a string.
1156
1182
  *
1157
1183
  * @example
1158
- * let hashedMessage = myHMAC.digest('hex');
1184
+ * let hashedMessage = myHMAC.digest();
1159
1185
  */
1160
- digest(enc?: 'hex'): number[] | string {
1161
- this.outer.update(this.inner.digest() as number[])
1162
- return this.outer.digest(enc)
1186
+ digest(): number[] {
1187
+ this.outer.update(this.inner.digest())
1188
+ return this.outer.digest()
1189
+ }
1190
+
1191
+ /**
1192
+ * Finalizes the HMAC computation and returns the resultant hash as a hex string.
1193
+ *
1194
+ * @method digest
1195
+ * @returns Returns the digest of the hashed data as a hex string
1196
+ *
1197
+ * @example
1198
+ * let hashedMessage = myHMAC.digestHex();
1199
+ */
1200
+ digestHex(): string {
1201
+ this.outer.update(this.inner.digest())
1202
+ return this.outer.digestHex()
1163
1203
  }
1164
1204
  }
1165
1205
 
@@ -1225,7 +1265,7 @@ export class SHA512HMAC {
1225
1265
  * @example
1226
1266
  * myHMAC.update('deadbeef', 'hex');
1227
1267
  */
1228
- update(msg: number[] | string, enc?: 'hex'): SHA512HMAC {
1268
+ update(msg: number[] | string, enc?: 'hex' | 'utf8'): SHA512HMAC {
1229
1269
  this.inner.update(msg, enc)
1230
1270
  return this
1231
1271
  }
@@ -1234,76 +1274,90 @@ export class SHA512HMAC {
1234
1274
  * Finalizes the HMAC computation and returns the resultant hash.
1235
1275
  *
1236
1276
  * @method digest
1237
- * @param enc - If 'hex', then the output is encoded as hexadecimal. If undefined or not 'hex', then no encoding is performed.
1238
- * @returns Returns the digest of the hashed data. Can be a number array or a string.
1277
+ * @returns Returns the digest of the hashed data as a number array.
1239
1278
  *
1240
1279
  * @example
1241
- * let hashedMessage = myHMAC.digest('hex');
1280
+ * let hashedMessage = myHMAC.digest();
1242
1281
  */
1243
- digest(enc?: 'hex'): number[] | string {
1282
+ digest(): number[] {
1244
1283
  this.outer.update(this.inner.digest() as number[])
1245
- return this.outer.digest(enc)
1284
+ return this.outer.digest()
1246
1285
  }
1286
+
1287
+ /**
1288
+ * Finalizes the HMAC computation and returns the resultant hash as a hex string.
1289
+ *
1290
+ * @method digest
1291
+ * @returns Returns the digest of the hashed data as a hex string
1292
+ *
1293
+ * @example
1294
+ * let hashedMessage = myHMAC.digestHex();
1295
+ */
1296
+ digestHex(): string {
1297
+ this.outer.update(this.inner.digest() as number[])
1298
+ return this.outer.digestHex()
1299
+ }
1300
+
1247
1301
  }
1248
1302
 
1249
1303
  /**
1250
1304
  * Computes RIPEMD160 hash of a given message.
1251
1305
  * @function ripemd160
1252
1306
  * @param msg - The message to compute the hash for.
1253
- * @param enc - The encoding of the message. If 'hex', the message is decoded from hexadecimal first.
1307
+ * @param enc - The encoding of msg if string. Default is 'utf8'.
1254
1308
  *
1255
1309
  * @returns the computed RIPEMD160 hash of the message.
1256
1310
  *
1257
1311
  * @example
1258
1312
  * const digest = ripemd160('Hello, world!');
1259
1313
  */
1260
- export const ripemd160 = (msg: number[] | string, enc?: 'hex'): number[] | string => {
1261
- return new RIPEMD160().update(msg, enc).digest(enc)
1314
+ export const ripemd160 = (msg: number[] | string, enc?: 'hex' | 'utf8'): number[] => {
1315
+ return new RIPEMD160().update(msg, enc).digest()
1262
1316
  }
1263
1317
 
1264
1318
  /**
1265
1319
  * Computes SHA1 hash of a given message.
1266
1320
  * @function sha1
1267
1321
  * @param msg - The message to compute the hash for.
1268
- * @param enc - The encoding of the message. If 'hex', the message is decoded from hexadecimal first.
1322
+ * @param enc - The encoding of msg if string. Default is 'utf8'.
1269
1323
  *
1270
1324
  * @returns the computed SHA1 hash of the message.
1271
1325
  *
1272
1326
  * @example
1273
1327
  * const digest = sha1('Hello, world!');
1274
1328
  */
1275
- export const sha1 = (msg: number[] | string, enc?: 'hex'): number[] | string => {
1276
- return new SHA1().update(msg, enc).digest(enc)
1329
+ export const sha1 = (msg: number[] | string, enc?: 'hex' | 'utf8'): number[] => {
1330
+ return new SHA1().update(msg, enc).digest()
1277
1331
  }
1278
1332
 
1279
1333
  /**
1280
1334
  * Computes SHA256 hash of a given message.
1281
1335
  * @function sha256
1282
1336
  * @param msg - The message to compute the hash for.
1283
- * @param enc - The encoding of the message. If 'hex', the message is decoded from hexadecimal first.
1337
+ * @param enc - The encoding of msg if string. Default is 'utf8'.
1284
1338
  *
1285
1339
  * @returns the computed SHA256 hash of the message.
1286
1340
  *
1287
1341
  * @example
1288
1342
  * const digest = sha256('Hello, world!');
1289
1343
  */
1290
- export const sha256 = (msg: number[] | string, enc?: 'hex'): number[] | string => {
1291
- return new SHA256().update(msg, enc).digest(enc)
1344
+ export const sha256 = (msg: number[] | string, enc?: 'hex' | 'utf8'): number[] => {
1345
+ return new SHA256().update(msg, enc).digest()
1292
1346
  }
1293
1347
 
1294
1348
  /**
1295
1349
  * Computes SHA512 hash of a given message.
1296
1350
  * @function sha512
1297
1351
  * @param msg - The message to compute the hash for.
1298
- * @param enc - The encoding of the message. If 'hex', the message is decoded from hexadecimal first.
1352
+ * @param enc - The encoding of msg if string. Default is 'utf8'.
1299
1353
  *
1300
1354
  * @returns the computed SHA512 hash of the message.
1301
1355
  *
1302
1356
  * @example
1303
1357
  * const digest = sha512('Hello, world!');
1304
1358
  */
1305
- export const sha512 = (msg: number[] | string, enc?: 'hex'): number[] | string => {
1306
- return new SHA512().update(msg, enc).digest(enc)
1359
+ export const sha512 = (msg: number[] | string, enc?: 'hex' | 'utf8'): number[] => {
1360
+ return new SHA512().update(msg, enc).digest()
1307
1361
  }
1308
1362
 
1309
1363
  /**
@@ -1312,16 +1366,16 @@ export const sha512 = (msg: number[] | string, enc?: 'hex'): number[] | string =
1312
1366
  * SHA256 hash of the resulting hash is computed.
1313
1367
  * @function hash256
1314
1368
  * @param msg - The message to compute the hash for.
1315
- * @param enc - Encoding of the message.If 'hex', the message is decoded from hexadecimal.
1369
+ * @param enc - The encoding of msg if string. Default is 'utf8'.
1316
1370
  *
1317
1371
  * @returns the double hashed SHA256 output.
1318
1372
  *
1319
1373
  * @example
1320
1374
  * const doubleHash = hash256('Hello, world!');
1321
1375
  */
1322
- export const hash256 = (msg: number[] | string, enc?: 'hex'): number[] | string => {
1376
+ export const hash256 = (msg: number[] | string, enc?: 'hex' | 'utf8'): number[] => {
1323
1377
  const first = new SHA256().update(msg, enc).digest()
1324
- return new SHA256().update(first).digest(enc)
1378
+ return new SHA256().update(first).digest()
1325
1379
  }
1326
1380
 
1327
1381
  /**
@@ -1329,16 +1383,16 @@ export const hash256 = (msg: number[] | string, enc?: 'hex'): number[] | string
1329
1383
  *
1330
1384
  * @function hash160
1331
1385
  * @param msg - The message to compute the hash for.
1332
- * @param enc - The encoding of the message. If 'hex', the message is decoded from hexadecimal.
1386
+ * @param enc - The encoding of msg if string. Default is 'utf8'.
1333
1387
  *
1334
1388
  * @returns the RIPEMD160 hash of the SHA256 hash of the input message.
1335
1389
  *
1336
1390
  * @example
1337
1391
  * const hash = hash160('Hello, world!');
1338
1392
  */
1339
- export const hash160 = (msg: number[] | string, enc?: 'hex'): number[] | string => {
1393
+ export const hash160 = (msg: number[] | string, enc?: 'hex' | 'utf8'): number[] => {
1340
1394
  const first = new SHA256().update(msg, enc).digest()
1341
- return new RIPEMD160().update(first).digest(enc)
1395
+ return new RIPEMD160().update(first).digest()
1342
1396
  }
1343
1397
 
1344
1398
  /**
@@ -1346,15 +1400,15 @@ export const hash160 = (msg: number[] | string, enc?: 'hex'): number[] | string
1346
1400
  * @function sha256hmac
1347
1401
  * @param key - The key used to compute the HMAC
1348
1402
  * @param msg - The message to compute the hash for.
1349
- * @param enc - The encoding of the message. If 'hex', the message is decoded from hexadecimal first.
1403
+ * @param enc - The encoding of msg if string. Default is 'utf8'.
1350
1404
  *
1351
1405
  * @returns the computed HMAC of the message.
1352
1406
  *
1353
1407
  * @example
1354
1408
  * const digest = sha256hmac('deadbeef', 'ffff001d');
1355
1409
  */
1356
- export const sha256hmac = (key: number[] | string, msg: number[] | string, enc?: 'hex'): number[] | string => {
1357
- return new SHA256HMAC(key).update(msg, enc).digest(enc)
1410
+ export const sha256hmac = (key: number[] | string, msg: number[] | string, enc?: 'hex'): number[] => {
1411
+ return new SHA256HMAC(key).update(msg, enc).digest()
1358
1412
  }
1359
1413
 
1360
1414
  /**
@@ -1362,15 +1416,15 @@ export const sha256hmac = (key: number[] | string, msg: number[] | string, enc?:
1362
1416
  * @function sha512hmac
1363
1417
  * @param key - The key used to compute the HMAC
1364
1418
  * @param msg - The message to compute the hash for.
1365
- * @param enc - The encoding of the message. If 'hex', the message is decoded from hexadecimal first.
1419
+ * @param enc - The encoding of msg if string. Default is 'utf8'.
1366
1420
  *
1367
1421
  * @returns the computed HMAC of the message.
1368
1422
  *
1369
1423
  * @example
1370
1424
  * const digest = sha512hmac('deadbeef', 'ffff001d');
1371
1425
  */
1372
- export const sha512hmac = (key: number[] | string, msg: number[] | string, enc?: 'hex'): number[] | string => {
1373
- return new SHA512HMAC(key).update(msg, enc).digest(enc)
1426
+ export const sha512hmac = (key: number[] | string, msg: number[] | string, enc?: 'hex'): number[] => {
1427
+ return new SHA512HMAC(key).update(msg, enc).digest()
1374
1428
  }
1375
1429
 
1376
1430
  /**
@@ -67,6 +67,33 @@ export default class PrivateKey extends BigNumber {
67
67
  return new PrivateKey(decoded.data.slice(0, 32))
68
68
  }
69
69
 
70
+ /**
71
+ * @constructor
72
+ *
73
+ * @param number - The number (various types accepted) to construct a BigNumber from. Default is 0.
74
+ *
75
+ * @param base - The base of number provided. By default is 10. Ignored if number is BigNumber.
76
+ *
77
+ * @param endian - The endianness provided. By default is 'big endian'. Ignored if number is BigNumber.
78
+ *
79
+ * @example
80
+ * import PrivateKey from './PrivateKey';
81
+ * import BigNumber from './BigNumber';
82
+ * const privKey = new PrivateKey(new BigNumber('123456', 10, 'be'));
83
+ */
84
+ constructor (
85
+ number: BigNumber | number | string | number[] = 0,
86
+ base: number | 'be' | 'le' | 'hex' = 10,
87
+ endian: 'be' | 'le' = 'be'
88
+ ) {
89
+ if (number instanceof BigNumber) {
90
+ super()
91
+ number.copy(this)
92
+ } else {
93
+ super(number, base, endian)
94
+ }
95
+ }
96
+
70
97
  /**
71
98
  * Signs a message using the private key.
72
99
  *
@@ -81,7 +108,7 @@ export default class PrivateKey extends BigNumber {
81
108
  * const privateKey = PrivateKey.fromRandom();
82
109
  * const signature = privateKey.sign('Hello, World!');
83
110
  */
84
- sign (msg: number[] | string, enc?: 'hex', forceLowS: boolean = true, customK?: Function | BigNumber): Signature {
111
+ sign (msg: number[] | string, enc?: 'hex' | 'utf8', forceLowS: boolean = true, customK?: Function | BigNumber): Signature {
85
112
  const msgHash = new BigNumber(sha256(msg, enc), 16)
86
113
  return sign(msgHash, this, forceLowS, customK)
87
114
  }
@@ -52,6 +52,28 @@ export default class PublicKey extends Point {
52
52
  return new PublicKey(p.x, p.y)
53
53
  }
54
54
 
55
+ /**
56
+ * @constructor
57
+ * @param x - A point or the x-coordinate of the point. May be a number, a BigNumber, a string (which will be interpreted as hex), a number array, or null. If null, an "Infinity" point is constructed.
58
+ * @param y - If x is not a point, the y-coordinate of the point, similar to x.
59
+ * @param isRed - A boolean indicating if the point is a member of the field of integers modulo the k256 prime. Default is true.
60
+ *
61
+ * @example
62
+ * new PublicKey(point1);
63
+ * new PublicKey('abc123', 'def456');
64
+ */
65
+ constructor (
66
+ x: Point | BigNumber | number | number[] | string | null,
67
+ y: BigNumber | number | number[] | string | null = null,
68
+ isRed: boolean = true
69
+ ) {
70
+ if (x instanceof Point) {
71
+ super(x.getX(), x.getY())
72
+ } else {
73
+ super(x, y, isRed)
74
+ }
75
+ }
76
+
55
77
  /**
56
78
  * Derive a shared secret from a public key and a private key for use in symmetric encryption.
57
79
  * This method multiplies the public key (an instance of Point) with a private key.
@@ -78,7 +100,7 @@ export default class PublicKey extends Point {
78
100
  *
79
101
  * @param msg - The message to verify. It can be a string or an array of numbers.
80
102
  * @param sig - The Signature of the message that needs verification.
81
- * @param enc - The encoding of the message. It defaults to 'hex'.
103
+ * @param enc - The encoding of the message. It defaults to 'utf8'.
82
104
  *
83
105
  * @returns Returns true if the signature is verified successfully, otherwise false.
84
106
  *
@@ -87,7 +109,7 @@ export default class PublicKey extends Point {
87
109
  * const mySignature = new Signature(...)
88
110
  * const isVerified = myPubKey.verify(myMessage, mySignature)
89
111
  */
90
- verify (msg: number[] | string, sig: Signature, enc?: 'hex'): boolean {
112
+ verify (msg: number[] | string, sig: Signature, enc?: 'hex' | 'utf8'): boolean {
91
113
  const msgHash = new BigNumber(sha256(msg, enc), 16)
92
114
  return verify(msgHash, sig, this)
93
115
  }
@@ -12,6 +12,20 @@ import { toArray, encode } from './utils.js'
12
12
  * @extends {BigNumber}
13
13
  */
14
14
  export default class SymmetricKey extends BigNumber {
15
+ /**
16
+ * Generates a symmetric key randomly.
17
+ *
18
+ * @method fromRandom
19
+ * @static
20
+ * @returns The newly generated Symmetric Key.
21
+ *
22
+ * @example
23
+ * const symmetricKey = SymmetricKey.fromRandom();
24
+ */
25
+ static fromRandom(): SymmetricKey {
26
+ return new SymmetricKey(Random(32))
27
+ }
28
+
15
29
  /**
16
30
  * Encrypts a given message using AES-GCM encryption.
17
31
  * The generated Initialization Vector (IV) is attached to the encrypted message for decryption purposes.
@@ -26,14 +40,14 @@ export default class SymmetricKey extends BigNumber {
26
40
  * const key = new SymmetricKey(1234);
27
41
  * const encryptedMessage = key.encrypt('plainText', 'utf8');
28
42
  */
29
- encrypt (msg: number[] | string, enc?: 'hex'): string | number[] {
43
+ encrypt(msg: number[] | string, enc?: 'hex'): string | number[] {
30
44
  const iv = Random(32)
31
45
  msg = toArray(msg, enc)
32
46
  const { result, authenticationTag } = AESGCM(
33
47
  msg,
34
48
  [],
35
49
  iv,
36
- this.toArray()
50
+ this.toArray('be', 32)
37
51
  )
38
52
  return encode([...iv, ...result, ...authenticationTag], enc)
39
53
  }
@@ -54,7 +68,7 @@ export default class SymmetricKey extends BigNumber {
54
68
  *
55
69
  * @throws {Error} Will throw an error if the decryption fails, likely due to message tampering or incorrect decryption key.
56
70
  */
57
- decrypt (msg: number[] | string, enc?: 'hex' | 'utf8'): string | number[] {
71
+ decrypt(msg: number[] | string, enc?: 'hex' | 'utf8'): string | number[] {
58
72
  msg = toArray(msg, enc) as number[]
59
73
  const iv = msg.slice(0, 32)
60
74
  const ciphertextWithTag = msg.slice(32)
@@ -47,12 +47,12 @@ describe('HMAC', function () {
47
47
  function test (opt): void {
48
48
  it(`should not fail at ${opt.name as string}`, function (): void {
49
49
  let h = new SHA256HMAC(opt.key)
50
- expect(h.update(opt.msg, opt.msgEnc).digest('hex')).toEqual(opt.res)
50
+ expect(h.update(opt.msg, opt.msgEnc).digestHex()).toEqual(opt.res)
51
51
  h = h = new SHA256HMAC(opt.key)
52
52
  expect(h
53
53
  .update(opt.msg.slice(0, 10), opt.msgEnc)
54
54
  .update(opt.msg.slice(10), opt.msgEnc)
55
- .digest('hex')).toEqual(opt.res)
55
+ .digestHex()).toEqual(opt.res)
56
56
  })
57
57
  }
58
58
  })
@@ -11,13 +11,13 @@ describe('Hash', function () {
11
11
  const res = cases[i][1]
12
12
  const enc = cases[i][2]
13
13
 
14
- let dgst = new Hash().update(msg, enc).digest('hex')
14
+ let dgst = new Hash().update(msg, enc).digestHex()
15
15
  expect(dgst).toEqual(res)
16
16
 
17
17
  // Split message
18
18
  dgst = new Hash().update(msg.slice(0, 2), enc)
19
19
  .update(msg.slice(2), enc)
20
- .digest('hex')
20
+ .digestHex()
21
21
  expect(dgst).toEqual(res)
22
22
  }
23
23
  }
@@ -1,4 +1,5 @@
1
1
  export { default as BigNumber } from './BigNumber.js'
2
+ export { default as Curve } from './Curve.js'
2
3
  export { default as Point } from './Point.js'
3
4
  export { default as PublicKey } from './PublicKey.js'
4
5
  export { default as Signature } from './Signature.js'
@@ -2,12 +2,12 @@ import BigNumber from './BigNumber.js'
2
2
  import { hash256 } from './Hash.js'
3
3
 
4
4
  /**
5
- * Appends a '0' to a single-character word to ensure it has two characters.
5
+ * Prepends a '0' to an odd character length word to ensure it has an even number of characters.
6
6
  * @param {string} word - The input word.
7
- * @returns {string} - The word with a leading '0' if it's a single character; otherwise, the original word.
7
+ * @returns {string} - The word with a leading '0' if it's an odd character length; otherwise, the original word.
8
8
  */
9
9
  export const zero2 = (word: string): string => {
10
- if (word.length === 1) {
10
+ if (word.length % 2 === 1) {
11
11
  return '0' + word
12
12
  } else {
13
13
  return word
@@ -1,4 +1,6 @@
1
1
  import Script from '../../../dist/cjs/src/script/Script'
2
+ import PrivateKey from '../../../dist/cjs/src/primitives/PrivateKey'
3
+ import P2PKH from '../../../dist/cjs/src/script/templates/P2PKH'
2
4
  import OP from '../../../dist/cjs/src/script/OP'
3
5
  import { toHex } from '../../../dist/cjs/src/primitives/utils'
4
6
  import scriptFromVector from './scriptFromVector'
@@ -23,6 +25,38 @@ describe('Script', () => {
23
25
  })
24
26
  })
25
27
 
28
+ describe('fromAddress', () => {
29
+ it('should parse this mainnet Base58Check encoded address string and result in a P2PKH Script', () => {
30
+ const priv = PrivateKey.fromRandom()
31
+ const address = priv.toAddress()
32
+ const publicKey = priv.toPublicKey()
33
+ const pkh = publicKey.toHash()
34
+ const lockingScriptFromTemplate = new P2PKH().lock(pkh).toASM()
35
+ const script = new P2PKH().lock(address).toASM()
36
+ expect(script).toBe(lockingScriptFromTemplate)
37
+ })
38
+
39
+ it('should parse this testnet Base58Check encoded address string and result in a P2PKH Script', () => {
40
+ const priv = PrivateKey.fromRandom()
41
+ const address = priv.toAddress([0x6f])
42
+ const publicKey = priv.toPublicKey()
43
+ const pkh = publicKey.toHash()
44
+ const lockingScriptFromTemplate = new P2PKH().lock(pkh).toASM()
45
+ const script = new P2PKH().lock(address).toASM()
46
+ expect(script).toBe(lockingScriptFromTemplate)
47
+ })
48
+
49
+ it('should error when attempting to parse this strange Base58Check encoded string', () => {
50
+ const priv = PrivateKey.fromRandom()
51
+ const address = priv.toAddress([0x88])
52
+ function attemptToDeriveAddress() {
53
+ const script = new P2PKH().lock(address).toASM()
54
+ return script
55
+ }
56
+ expect(attemptToDeriveAddress).toThrow('only P2PKH is supported')
57
+ })
58
+ })
59
+
26
60
  describe('fromBinary', () => {
27
61
  it('should parse this buffer containing an OP code', () => {
28
62
  const buf = Buffer.alloc(1)