koilib 5.1.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/koinos.js CHANGED
@@ -10675,6 +10675,14 @@ class Serializer {
10675
10675
  * Preformat bytes for base64url, base58 or hex string
10676
10676
  */
10677
10677
  this.bytesConversion = true;
10678
+ /**
10679
+ * Verify checksum in addresses during serialization
10680
+ * or deserialization
10681
+ */
10682
+ this.verifyChecksum = {
10683
+ serialize: true,
10684
+ deserialize: false,
10685
+ };
10678
10686
  this.types = types;
10679
10687
  this.root = light_1.Root.fromJSON(this.types);
10680
10688
  if (opts === null || opts === void 0 ? void 0 : opts.defaultTypeName)
@@ -10682,7 +10690,7 @@ class Serializer {
10682
10690
  if (opts && typeof opts.bytesConversion !== "undefined")
10683
10691
  this.bytesConversion = opts.bytesConversion;
10684
10692
  }
10685
- btypeDecode(valueBtypeEncoded, protobufType) {
10693
+ btypeDecode(valueBtypeEncoded, protobufType, verifyChecksum) {
10686
10694
  const valueBtypeDecoded = {};
10687
10695
  Object.keys(protobufType.fields).forEach((fieldName) => {
10688
10696
  // @ts-ignore
@@ -10701,26 +10709,35 @@ class Serializer {
10701
10709
  valueBtypeDecoded[name] = valueBtypeEncoded[name].map((itemEncoded) => {
10702
10710
  // custom objects
10703
10711
  if (!nativeTypes.includes(type)) {
10704
- const protoBuf = this.root.lookupType(type);
10705
- return this.btypeDecode(itemEncoded, protoBuf);
10712
+ const protoBuf = this.root.lookupTypeOrEnum(type);
10713
+ if (!protoBuf.fields) {
10714
+ // it's an enum
10715
+ return itemEncoded;
10716
+ }
10717
+ return this.btypeDecode(itemEncoded, protoBuf, verifyChecksum);
10706
10718
  }
10707
10719
  // native types
10708
- return (0, utils_1.btypeDecodeValue)(itemEncoded, typeField);
10720
+ return (0, utils_1.btypeDecodeValue)(itemEncoded, typeField, verifyChecksum);
10709
10721
  });
10710
10722
  return;
10711
10723
  }
10712
10724
  // custom objects
10713
10725
  if (!nativeTypes.includes(type)) {
10714
- const protoBuf = this.root.lookupType(type);
10715
- valueBtypeDecoded[name] = this.btypeDecode(valueBtypeEncoded[name], protoBuf);
10726
+ const protoBuf = this.root.lookupTypeOrEnum(type);
10727
+ if (!protoBuf.fields) {
10728
+ // it's an enum
10729
+ valueBtypeDecoded[name] = valueBtypeEncoded[name];
10730
+ return;
10731
+ }
10732
+ valueBtypeDecoded[name] = this.btypeDecode(valueBtypeEncoded[name], protoBuf, verifyChecksum);
10716
10733
  return;
10717
10734
  }
10718
10735
  // native types
10719
- valueBtypeDecoded[name] = (0, utils_1.btypeDecodeValue)(valueBtypeEncoded[name], typeField);
10736
+ valueBtypeDecoded[name] = (0, utils_1.btypeDecodeValue)(valueBtypeEncoded[name], typeField, verifyChecksum);
10720
10737
  });
10721
10738
  return valueBtypeDecoded;
10722
10739
  }
10723
- btypeEncode(valueBtypeDecoded, protobufType) {
10740
+ btypeEncode(valueBtypeDecoded, protobufType, verifyChecksum) {
10724
10741
  const valueBtypeEncoded = {};
10725
10742
  Object.keys(protobufType.fields).forEach((fieldName) => {
10726
10743
  // @ts-ignore
@@ -10739,22 +10756,31 @@ class Serializer {
10739
10756
  valueBtypeEncoded[name] = valueBtypeDecoded[name].map((itemDecoded) => {
10740
10757
  // custom objects
10741
10758
  if (!nativeTypes.includes(type)) {
10742
- const protoBuf = this.root.lookupType(type);
10743
- return this.btypeEncode(itemDecoded, protoBuf);
10759
+ const protoBuf = this.root.lookupTypeOrEnum(type);
10760
+ if (!protoBuf.fields) {
10761
+ // it's an enum
10762
+ return itemDecoded;
10763
+ }
10764
+ return this.btypeEncode(itemDecoded, protoBuf, verifyChecksum);
10744
10765
  }
10745
10766
  // native types
10746
- return (0, utils_1.btypeEncodeValue)(itemDecoded, typeField);
10767
+ return (0, utils_1.btypeEncodeValue)(itemDecoded, typeField, verifyChecksum);
10747
10768
  });
10748
10769
  return;
10749
10770
  }
10750
10771
  // custom objects
10751
10772
  if (!nativeTypes.includes(type)) {
10752
- const protoBuf = this.root.lookupType(type);
10753
- valueBtypeEncoded[name] = this.btypeEncode(valueBtypeDecoded[name], protoBuf);
10773
+ const protoBuf = this.root.lookupTypeOrEnum(type);
10774
+ if (!protoBuf.fields) {
10775
+ // it's an enum
10776
+ valueBtypeEncoded[name] = valueBtypeDecoded[name];
10777
+ return;
10778
+ }
10779
+ valueBtypeEncoded[name] = this.btypeEncode(valueBtypeDecoded[name], protoBuf, verifyChecksum);
10754
10780
  return;
10755
10781
  }
10756
10782
  // native types
10757
- valueBtypeEncoded[name] = (0, utils_1.btypeEncodeValue)(valueBtypeDecoded[name], typeField);
10783
+ valueBtypeEncoded[name] = (0, utils_1.btypeEncodeValue)(valueBtypeDecoded[name], typeField, verifyChecksum);
10758
10784
  });
10759
10785
  return valueBtypeEncoded;
10760
10786
  }
@@ -10769,8 +10795,11 @@ class Serializer {
10769
10795
  const bytesConversion = (opts === null || opts === void 0 ? void 0 : opts.bytesConversion) === undefined
10770
10796
  ? this.bytesConversion
10771
10797
  : opts.bytesConversion;
10798
+ const verifyChecksum = (opts === null || opts === void 0 ? void 0 : opts.verifyChecksum) === undefined
10799
+ ? this.verifyChecksum.serialize
10800
+ : opts.verifyChecksum;
10772
10801
  if (bytesConversion) {
10773
- object = this.btypeDecode(valueDecoded, protobufType);
10802
+ object = this.btypeDecode(valueDecoded, protobufType, verifyChecksum);
10774
10803
  }
10775
10804
  else {
10776
10805
  object = valueDecoded;
@@ -10797,8 +10826,11 @@ class Serializer {
10797
10826
  const bytesConversion = (opts === null || opts === void 0 ? void 0 : opts.bytesConversion) === undefined
10798
10827
  ? this.bytesConversion
10799
10828
  : opts.bytesConversion;
10829
+ const verifyChecksum = (opts === null || opts === void 0 ? void 0 : opts.verifyChecksum) === undefined
10830
+ ? this.verifyChecksum.deserialize
10831
+ : opts.verifyChecksum;
10800
10832
  if (bytesConversion) {
10801
- return this.btypeEncode(object, protobufType);
10833
+ return this.btypeEncode(object, protobufType, verifyChecksum);
10802
10834
  }
10803
10835
  return object;
10804
10836
  }
@@ -10901,6 +10933,13 @@ const btypesOperation = {
10901
10933
  },
10902
10934
  },
10903
10935
  },
10936
+ set_system_contract: {
10937
+ type: "object",
10938
+ subtypes: {
10939
+ contract_id: { type: "bytes", btype: "CONTRACT_ID" },
10940
+ system_contract: { type: "bool" },
10941
+ },
10942
+ },
10904
10943
  };
10905
10944
  /**
10906
10945
  * The Signer Class contains the private key needed to sign transactions.
@@ -11252,7 +11291,7 @@ class Signer {
11252
11291
  if (!block.signature)
11253
11292
  throw new Error("Missing block signature");
11254
11293
  signatures = [block.signature];
11255
- const headerDecoded = (0, utils_1.btypeDecode)(block.header, btypeBlockHeader);
11294
+ const headerDecoded = (0, utils_1.btypeDecode)(block.header, btypeBlockHeader, false);
11256
11295
  const message = protocol_proto_js_1.koinos.protocol.block_header.create(headerDecoded);
11257
11296
  headerBytes = protocol_proto_js_1.koinos.protocol.block_header.encode(message).finish();
11258
11297
  }
@@ -11263,7 +11302,7 @@ class Signer {
11263
11302
  if (!transaction.signatures)
11264
11303
  throw new Error("Missing transaction signatures");
11265
11304
  signatures = transaction.signatures;
11266
- const headerDecoded = (0, utils_1.btypeDecode)(transaction.header, btypeTransactionHeader);
11305
+ const headerDecoded = (0, utils_1.btypeDecode)(transaction.header, btypeTransactionHeader, false);
11267
11306
  const message = protocol_proto_js_1.koinos.protocol.transaction_header.create(headerDecoded);
11268
11307
  headerBytes = protocol_proto_js_1.koinos.protocol.transaction_header.encode(message).finish();
11269
11308
  }
@@ -11376,7 +11415,7 @@ class Signer {
11376
11415
  const operationsHashes = [];
11377
11416
  if (tx.operations) {
11378
11417
  for (let index = 0; index < ((_b = tx.operations) === null || _b === void 0 ? void 0 : _b.length); index += 1) {
11379
- const operationDecoded = (0, utils_1.btypeDecode)(tx.operations[index], btypesOperation);
11418
+ const operationDecoded = (0, utils_1.btypeDecode)(tx.operations[index], btypesOperation, false);
11380
11419
  const message = protocol_proto_js_1.koinos.protocol.operation.create(operationDecoded);
11381
11420
  const operationEncoded = protocol_proto_js_1.koinos.protocol.operation
11382
11421
  .encode(message)
@@ -11399,7 +11438,7 @@ class Signer {
11399
11438
  ...(payee && { payee }),
11400
11439
  // TODO: Option to resolve names (payer, payee)
11401
11440
  };
11402
- const headerDecoded = (0, utils_1.btypeDecode)(tx.header, btypeTransactionHeader);
11441
+ const headerDecoded = (0, utils_1.btypeDecode)(tx.header, btypeTransactionHeader, false);
11403
11442
  const message = protocol_proto_js_1.koinos.protocol.transaction_header.create(headerDecoded);
11404
11443
  const headerBytes = protocol_proto_js_1.koinos.protocol.transaction_header
11405
11444
  .encode(message)
@@ -11423,7 +11462,7 @@ class Signer {
11423
11462
  if (block.transactions) {
11424
11463
  for (let index = 0; index < block.transactions.length; index++) {
11425
11464
  const tx = block.transactions[index];
11426
- const headerDecoded = (0, utils_1.btypeDecode)(tx.header, btypeTransactionHeader);
11465
+ const headerDecoded = (0, utils_1.btypeDecode)(tx.header, btypeTransactionHeader, false);
11427
11466
  const message = protocol_proto_js_1.koinos.protocol.transaction_header.create(headerDecoded);
11428
11467
  const headerBytes = protocol_proto_js_1.koinos.protocol.transaction_header
11429
11468
  .encode(message)
@@ -11465,7 +11504,7 @@ class Signer {
11465
11504
  ])),
11466
11505
  signer: this.address,
11467
11506
  };
11468
- const headerDecoded = (0, utils_1.btypeDecode)(block.header, btypeBlockHeader);
11507
+ const headerDecoded = (0, utils_1.btypeDecode)(block.header, btypeBlockHeader, false);
11469
11508
  const message = protocol_proto_js_1.koinos.protocol.block_header.create(headerDecoded);
11470
11509
  const headerBytes = protocol_proto_js_1.koinos.protocol.block_header
11471
11510
  .encode(message)
@@ -11558,7 +11597,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11558
11597
  return (mod && mod.__esModule) ? mod : { "default": mod };
11559
11598
  };
11560
11599
  Object.defineProperty(exports, "__esModule", ({ value: true }));
11561
- exports.tokenAbi = exports.btypeEncode = exports.btypeDecode = exports.btypeEncodeValue = exports.btypeDecodeValue = exports.parseUnits = exports.formatUnits = exports.bitcoinAddress = exports.bitcoinDecode = exports.bitcoinEncode = exports.calculateMerkleRoot = exports.decodeBase64 = exports.multihash = exports.encodeBase64 = exports.decodeBase64url = exports.encodeBase64url = exports.decodeBase58 = exports.encodeBase58 = exports.toHexString = exports.toUint8Array = void 0;
11600
+ exports.tokenAbi = exports.btypeEncode = exports.btypeDecode = exports.btypeEncodeValue = exports.btypeDecodeValue = exports.parseUnits = exports.formatUnits = exports.isChecksumWif = exports.isChecksumAddress = exports.isChecksum = exports.bitcoinAddress = exports.bitcoinDecode = exports.bitcoinEncode = exports.calculateMerkleRoot = exports.decodeBase64 = exports.multihash = exports.encodeBase64 = exports.decodeBase64url = exports.encodeBase64url = exports.decodeBase58 = exports.encodeBase58 = exports.toHexString = exports.toUint8Array = void 0;
11562
11601
  const multibase = __importStar(__webpack_require__(6957));
11563
11602
  const sha256_1 = __webpack_require__(3061);
11564
11603
  const ripemd160_1 = __webpack_require__(830);
@@ -11739,6 +11778,82 @@ function bitcoinAddress(publicKey) {
11739
11778
  return bitcoinEncode(hash160, "public");
11740
11779
  }
11741
11780
  exports.bitcoinAddress = bitcoinAddress;
11781
+ /**
11782
+ * Checks if the last 4 bytes matches with the double sha256
11783
+ * of the first part
11784
+ */
11785
+ function isChecksum(buffer) {
11786
+ const dataLength = buffer.length - 4;
11787
+ const data = new Uint8Array(dataLength);
11788
+ data.set(buffer.slice(0, dataLength));
11789
+ const checksum = new Uint8Array(4);
11790
+ checksum.set(buffer.slice(dataLength));
11791
+ const doubleHash = (0, sha256_1.sha256)((0, sha256_1.sha256)(data));
11792
+ // checksum must be the first 4 bytes of the double hash
11793
+ for (let i = 0; i < 4; i += 1) {
11794
+ if (checksum[i] !== doubleHash[i])
11795
+ return false;
11796
+ }
11797
+ return true;
11798
+ }
11799
+ exports.isChecksum = isChecksum;
11800
+ /**
11801
+ * Checks if the checksum of an address is correct.
11802
+ *
11803
+ * The address has 3 parts in this order:
11804
+ * - prefix: 1 byte
11805
+ * - data: 20 bytes
11806
+ * - checksum: 4 bytes
11807
+ *
11808
+ * checks:
11809
+ * - It must be "pay to public key hash" (P2PKH). That is prefix 0
11810
+ * - checksum = first 4 bytes of sha256(sha256(prefix + data))
11811
+ *
11812
+ * See [How to generate a bitcoin address step by step](https://medium.com/coinmonks/how-to-generate-a-bitcoin-address-step-by-step-9d7fcbf1ad0b).
11813
+ */
11814
+ function isChecksumAddress(address) {
11815
+ const bufferAddress = typeof address === "string" ? decodeBase58(address) : address;
11816
+ // it must have 25 bytes
11817
+ if (bufferAddress.length !== 25)
11818
+ return false;
11819
+ // it must have prefix 0 (P2PKH address)
11820
+ if (bufferAddress[0] !== 0)
11821
+ return false;
11822
+ return isChecksum(bufferAddress);
11823
+ }
11824
+ exports.isChecksumAddress = isChecksumAddress;
11825
+ /**
11826
+ * Checks if the checksum of an private key WIF is correct.
11827
+ *
11828
+ * The private key WIF has 3 parts in this order:
11829
+ * - prefix: 1 byte
11830
+ * - private key: 32 bytes
11831
+ * - compressed: 1 byte for compressed public key (no byte for uncompressed)
11832
+ * - checksum: 4 bytes
11833
+ *
11834
+ * checks:
11835
+ * - It must use version 0x80 in the prefix
11836
+ * - If the corresponding public key is compressed the byte 33 must be 0x01
11837
+ * - checksum = first 4 bytes of
11838
+ * sha256(sha256(prefix + private key + compressed))
11839
+ *
11840
+ * See [Bitcoin WIF](https://en.bitcoin.it/wiki/Wallet_import_format).
11841
+ */
11842
+ function isChecksumWif(wif) {
11843
+ const bufferWif = typeof wif === "string" ? decodeBase58(wif) : wif;
11844
+ // it must have 37 or 38 bytes
11845
+ if (bufferWif.length !== 37 && bufferWif.length !== 38)
11846
+ return false;
11847
+ const compressed = bufferWif.length === 38;
11848
+ // if compressed then the last byte must be 0x01
11849
+ if (compressed && bufferWif[33] !== 1)
11850
+ return false;
11851
+ // it must have prefix version for private keys (0x80)
11852
+ if (bufferWif[0] !== 128)
11853
+ return false;
11854
+ return isChecksum(bufferWif);
11855
+ }
11856
+ exports.isChecksumWif = isChecksumWif;
11742
11857
  /**
11743
11858
  * Function to format a number in a decimal point number
11744
11859
  * @example
@@ -11796,7 +11911,7 @@ function copyValue(value) {
11796
11911
  }
11797
11912
  return JSON.parse(JSON.stringify(value));
11798
11913
  }
11799
- function btypeDecodeValue(valueEncoded, typeField) {
11914
+ function btypeDecodeValue(valueEncoded, typeField, verifyChecksum) {
11800
11915
  // No byte conversion
11801
11916
  if (typeField.type !== "bytes")
11802
11917
  return copyValue(valueEncoded);
@@ -11808,9 +11923,14 @@ function btypeDecodeValue(valueEncoded, typeField) {
11808
11923
  // Specific byte conversion
11809
11924
  switch (typeField.btype) {
11810
11925
  case "BASE58":
11926
+ return decodeBase58(value);
11811
11927
  case "CONTRACT_ID":
11812
11928
  case "ADDRESS":
11813
- return decodeBase58(value);
11929
+ const valueDecoded = decodeBase58(value);
11930
+ if (verifyChecksum && !isChecksumAddress(valueDecoded)) {
11931
+ throw new Error(`${value} is an invalid address`);
11932
+ }
11933
+ return valueDecoded;
11814
11934
  case "BASE64":
11815
11935
  return decodeBase64url(value);
11816
11936
  case "HEX":
@@ -11822,7 +11942,7 @@ function btypeDecodeValue(valueEncoded, typeField) {
11822
11942
  }
11823
11943
  }
11824
11944
  exports.btypeDecodeValue = btypeDecodeValue;
11825
- function btypeEncodeValue(valueDecoded, typeField) {
11945
+ function btypeEncodeValue(valueDecoded, typeField, verifyChecksum) {
11826
11946
  // No byte conversion
11827
11947
  if (typeField.type !== "bytes")
11828
11948
  return copyValue(valueDecoded);
@@ -11834,9 +11954,14 @@ function btypeEncodeValue(valueDecoded, typeField) {
11834
11954
  // Specific byte conversion
11835
11955
  switch (typeField.btype) {
11836
11956
  case "BASE58":
11957
+ return encodeBase58(value);
11837
11958
  case "CONTRACT_ID":
11838
11959
  case "ADDRESS":
11839
- return encodeBase58(value);
11960
+ const valueEncoded = encodeBase58(value);
11961
+ if (verifyChecksum && !isChecksumAddress(value)) {
11962
+ throw new Error(`${valueEncoded} is an invalid address`);
11963
+ }
11964
+ return valueEncoded;
11840
11965
  case "BASE64":
11841
11966
  return encodeBase64url(value);
11842
11967
  case "HEX":
@@ -11848,7 +11973,7 @@ function btypeEncodeValue(valueDecoded, typeField) {
11848
11973
  }
11849
11974
  }
11850
11975
  exports.btypeEncodeValue = btypeEncodeValue;
11851
- function btypeDecode(valueEncoded, fields) {
11976
+ function btypeDecode(valueEncoded, fields, verifyChecksum) {
11852
11977
  if (typeof valueEncoded !== "object")
11853
11978
  return valueEncoded;
11854
11979
  const valueDecoded = {};
@@ -11858,18 +11983,18 @@ function btypeDecode(valueEncoded, fields) {
11858
11983
  if (fields[name].rule === "repeated")
11859
11984
  valueDecoded[name] = valueEncoded[name].map((itemEncoded) => {
11860
11985
  if (fields[name].subtypes)
11861
- return btypeDecode(itemEncoded, fields[name].subtypes);
11862
- return btypeDecodeValue(itemEncoded, fields[name]);
11986
+ return btypeDecode(itemEncoded, fields[name].subtypes, verifyChecksum);
11987
+ return btypeDecodeValue(itemEncoded, fields[name], verifyChecksum);
11863
11988
  });
11864
11989
  else if (fields[name].subtypes)
11865
- valueDecoded[name] = btypeDecode(valueEncoded[name], fields[name].subtypes);
11990
+ valueDecoded[name] = btypeDecode(valueEncoded[name], fields[name].subtypes, verifyChecksum);
11866
11991
  else
11867
- valueDecoded[name] = btypeDecodeValue(valueEncoded[name], fields[name]);
11992
+ valueDecoded[name] = btypeDecodeValue(valueEncoded[name], fields[name], verifyChecksum);
11868
11993
  });
11869
11994
  return valueDecoded;
11870
11995
  }
11871
11996
  exports.btypeDecode = btypeDecode;
11872
- function btypeEncode(valueDecoded, fields) {
11997
+ function btypeEncode(valueDecoded, fields, verifyChecksum) {
11873
11998
  if (typeof valueDecoded !== "object")
11874
11999
  return valueDecoded;
11875
12000
  const valueEncoded = {};
@@ -11879,13 +12004,13 @@ function btypeEncode(valueDecoded, fields) {
11879
12004
  if (fields[name].rule === "repeated")
11880
12005
  valueEncoded[name] = valueDecoded[name].map((itemDecoded) => {
11881
12006
  if (fields[name].subtypes)
11882
- return btypeEncode(itemDecoded, fields[name].subtypes);
11883
- return btypeEncodeValue(itemDecoded, fields[name]);
12007
+ return btypeEncode(itemDecoded, fields[name].subtypes, verifyChecksum);
12008
+ return btypeEncodeValue(itemDecoded, fields[name], verifyChecksum);
11884
12009
  });
11885
12010
  else if (fields[name].subtypes)
11886
- valueEncoded[name] = btypeEncode(valueDecoded[name], fields[name].subtypes);
12011
+ valueEncoded[name] = btypeEncode(valueDecoded[name], fields[name].subtypes, verifyChecksum);
11887
12012
  else
11888
- valueEncoded[name] = btypeEncodeValue(valueDecoded[name], fields[name]);
12013
+ valueEncoded[name] = btypeEncodeValue(valueDecoded[name], fields[name], verifyChecksum);
11889
12014
  });
11890
12015
  return valueEncoded;
11891
12016
  }