quantumcoin 7.0.11 → 7.0.12

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.
@@ -56,6 +56,7 @@ const BASE_SEED_BYTES_HYBRIDEDMLDSASLHDSA = 64;
56
56
  const MIN_PASSPHRASE_LENGTH = 12;
57
57
  const INVALID_KEY_TYPE = -1001;
58
58
  const CIRCL_CRYPTO_FAILURE = -1002;
59
+ const EXPECTED_WASM_SHA256 = "bcab6389db37af9cc6538fb54a872f416131392d3ad5ea23a0969d8aac3b1c85";
59
60
 
60
61
  /**
61
62
  * @class
@@ -122,9 +123,10 @@ class Wallet {
122
123
  * Creates a Wallet class. The constructor does not verify the wallet. To verify a wallet, call the verifyWallet function explicitly.
123
124
  * @param {string} address - Address of the wallet
124
125
  * @param {number[]} privateKey - Private Key byte array of the wallet
125
- * @param {number[]} publicKey - The chain id of the blockchain. Mainnet chainId is 123123. Testnet T4 chainId is 310324.
126
+ * @param {number[]} publicKey - Public Key byte array of the wallet
127
+ * @param {Uint8Array|number[]|null} [preExpansionSeed=null] - Optional pre-expansion seed bytes. Non-null only for seed-derived wallets.
126
128
  */
127
- constructor(address, privateKey, publicKey) {
129
+ constructor(address, privateKey, publicKey, preExpansionSeed) {
128
130
 
129
131
  /**
130
132
  * Address of the wallet. Is 66 bytes in length including 0x (if the wallet is valid).
@@ -146,6 +148,13 @@ class Wallet {
146
148
  * @public
147
149
  */
148
150
  this.publicKey = publicKey;
151
+
152
+ /**
153
+ * Pre-expansion seed bytes. Can be null if the wallet was not created from a seed.
154
+ * @type {Uint8Array|number[]|null}
155
+ * @public
156
+ */
157
+ this.preExpansionSeed = preExpansionSeed || null;
149
158
  }
150
159
  }
151
160
 
@@ -841,6 +850,10 @@ function isLargeNumber(val) {
841
850
  return false;
842
851
  }
843
852
 
853
+ function getGlobalObject() {
854
+ return (typeof globalThis !== 'undefined' ? globalThis : typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this);
855
+ }
856
+
844
857
  async function InitAccountsWebAssembly() {
845
858
  const go = new global.Go();
846
859
  let mod, inst;
@@ -851,14 +864,75 @@ async function InitAccountsWebAssembly() {
851
864
  throw new Error("Error parsing base64");
852
865
  }
853
866
  const wasmBytes = Uint8Array.from(atob(base64wasm), c => c.charCodeAt(0));
867
+
868
+ const hashHex = crypto.createHash('sha256').update(wasmBytes).digest('hex');
869
+ if (hashHex !== EXPECTED_WASM_SHA256) {
870
+ throw new Error("WASM integrity check failed");
871
+ }
872
+
873
+ const g = getGlobalObject();
874
+ if (g) {
875
+ delete g.circl;
876
+ }
877
+
854
878
  let result = await WebAssembly.instantiate(wasmBytes, go.importObject);
855
879
  mod = result.module;
856
880
  inst = result.instance;
857
881
  go.run(inst);
858
- const g = (typeof globalThis !== 'undefined' ? globalThis : typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this);
882
+
859
883
  if (g && g.circl) {
860
884
  circl = g.circl;
885
+ delete g.circl;
886
+ if (circl.hybridedmldsaslhdsa) Object.freeze(circl.hybridedmldsaslhdsa);
887
+ if (circl.hybridedmldsaslhdsa5) Object.freeze(circl.hybridedmldsaslhdsa5);
888
+ if (circl.hybridedmldsaslhds5) Object.freeze(circl.hybridedmldsaslhds5);
889
+ if (circl.hybrideds) Object.freeze(circl.hybrideds);
890
+ Object.freeze(circl);
891
+ }
892
+ }
893
+
894
+ function validateCryptoRandom() {
895
+ if (!circl || !circl.cryptoRandom) {
896
+ return false;
897
+ }
898
+
899
+ const sampleSize = 64;
900
+ const res1 = circl.cryptoRandom(sampleSize);
901
+ const res2 = circl.cryptoRandom(sampleSize);
902
+
903
+ if (!res1 || res1.error || !res1.result || res1.result.length !== sampleSize) {
904
+ return false;
905
+ }
906
+ if (!res2 || res2.error || !res2.result || res2.result.length !== sampleSize) {
907
+ return false;
908
+ }
909
+
910
+ const a = res1.result instanceof Uint8Array ? res1.result : new Uint8Array(res1.result);
911
+ const b = res2.result instanceof Uint8Array ? res2.result : new Uint8Array(res2.result);
912
+
913
+ let identical = true;
914
+ for (let i = 0; i < sampleSize; i++) {
915
+ if (a[i] !== b[i]) { identical = false; break; }
916
+ }
917
+ if (identical) {
918
+ return false;
919
+ }
920
+
921
+ let aAllZero = true, bAllZero = true;
922
+ for (let i = 0; i < sampleSize; i++) {
923
+ if (a[i] !== 0) aAllZero = false;
924
+ if (b[i] !== 0) bAllZero = false;
925
+ }
926
+ if (aAllZero || bAllZero) {
927
+ return false;
928
+ }
929
+
930
+ const seen = new Set(a);
931
+ if (seen.size < 48) {
932
+ return false;
861
933
  }
934
+
935
+ return true;
862
936
  }
863
937
 
864
938
  /**
@@ -879,7 +953,10 @@ async function initialize(clientConfig) {
879
953
  if (clientConfig.readUrl === null || clientConfig.writeUrl === null || clientConfig.chainId === null) {
880
954
  return false;
881
955
  }
882
- await InitAccountsWebAssembly();
956
+ await InitAccountsWebAssembly();
957
+ if (!validateCryptoRandom()) {
958
+ throw new Error("CSPRNG validation failed");
959
+ }
883
960
  config = clientConfig;
884
961
  isInitialized = await seedwords.initialize();
885
962
 
@@ -1004,13 +1081,13 @@ function newWallet(keyType) {
1004
1081
  }
1005
1082
 
1006
1083
  /**
1007
- * The newWalletSeed function creates a new Wallet seed word list. The return array can then be passed to the openWalletFromSeedWords function to create a new wallet.
1084
+ * The newWalletSeedWords function creates a new wallet seed word list. The returned array can then be passed to the openWalletFromSeedWords function to create a new wallet.
1008
1085
  *
1009
- * @function newWalletSeed
1086
+ * @function newWalletSeedWords
1010
1087
  * @param {number|null} keyType - Optional. KEY_TYPE_HYBRIDEDMLDSASLHDSA (3) or KEY_TYPE_HYBRIDEDMLDSASLHDSA5 (5). null/undefined defaults to 3.
1011
- * @return {array|number|null} Returns an array of seed words (32 or 36 words). Returns -1000 if not initialized, null on failure.
1088
+ * @return {string[]|number|null} Returns an array of seed words (32 or 36 words depending on keyType). Returns -1000 if not initialized, null on failure.
1012
1089
  */
1013
- function newWalletSeed(keyType) {
1090
+ function newWalletSeedWords(keyType) {
1014
1091
  if (isInitialized === false) {
1015
1092
  return -1000;
1016
1093
  }
@@ -1046,7 +1123,7 @@ function newWalletSeed(keyType) {
1046
1123
  *
1047
1124
  * @function openWalletFromSeed
1048
1125
  * @param {Array<number>|Uint8Array} seedArray - The raw seed bytes. Length 96, 72, or 64 depending on scheme.
1049
- * @return {Wallet|number} Returns a Wallet object. Returns -1000 if not initialized, null if the operation failed.
1126
+ * @return {Wallet|number|null} Returns a Wallet object. Returns -1000 if not initialized, null if the operation failed.
1050
1127
  */
1051
1128
  function openWalletFromSeed(seedArray) {
1052
1129
  if (isInitialized === false) {
@@ -1092,7 +1169,7 @@ function openWalletFromSeed(seedArray) {
1092
1169
  const publicKey = keyPairRes.result.publicKey instanceof Uint8Array ? Array.from(keyPairRes.result.publicKey) : keyPairRes.result.publicKey;
1093
1170
  const privateKey = keyPairRes.result.privateKey instanceof Uint8Array ? Array.from(keyPairRes.result.privateKey) : keyPairRes.result.privateKey;
1094
1171
  const address = PublicKeyToAddress(publicKey);
1095
- return new Wallet(address, privateKey, publicKey);
1172
+ return new Wallet(address, privateKey, publicKey, seedU8);
1096
1173
  }
1097
1174
 
1098
1175
  /**
@@ -1100,8 +1177,8 @@ function openWalletFromSeed(seedArray) {
1100
1177
  * Supports 48 words (hybrideds), 36 words (hybrid5), or 32 words (hybrid) per seed length.
1101
1178
  *
1102
1179
  * @function openWalletFromSeedWords
1103
- * @param {array} seedWordList - An array of seed words. Length 48, 36, or 32 depending on scheme.
1104
- * @return {Wallet|number} Returns a Wallet object. Returns -1000 if not initialized, null if the operation failed.
1180
+ * @param {string[]} seedWordList - An array of seed words. Length 48, 36, or 32 depending on scheme.
1181
+ * @return {Wallet|number|null} Returns a Wallet object. Returns -1000 if not initialized, null if the operation failed.
1105
1182
  */
1106
1183
  function openWalletFromSeedWords(seedWordList) {
1107
1184
  if (isInitialized === false) {
@@ -1115,7 +1192,7 @@ function openWalletFromSeedWords(seedWordList) {
1115
1192
  return null;
1116
1193
  }
1117
1194
  const seedArray = seedwords.getSeedArrayFromWordList(seedWordList);
1118
- if (seedArray == null || seedArray.length == null) {
1195
+ if (seedArray == null || seedArray.length === undefined) {
1119
1196
  return null;
1120
1197
  }
1121
1198
  return openWalletFromSeed(seedArray);
@@ -1131,26 +1208,22 @@ function openWalletFromSeedWords(seedWordList) {
1131
1208
  */
1132
1209
  function deserializeEncryptedWallet(walletJsonString, passphrase) {
1133
1210
  if (isInitialized === false) {
1134
- console.error('deserializeEncryptedWallet: SDK not initialized');
1135
1211
  return -1000;
1136
1212
  }
1137
1213
 
1138
1214
  if (walletJsonString == null || passphrase == null) {
1139
- console.error('deserializeEncryptedWallet: walletJsonString or passphrase is null');
1140
1215
  return null;
1141
1216
  }
1142
1217
 
1143
1218
  if (typeof walletJsonString === 'string' || walletJsonString instanceof String) {
1144
1219
 
1145
1220
  } else {
1146
- console.error('deserializeEncryptedWallet: walletJsonString is not a string');
1147
1221
  return null;
1148
1222
  }
1149
1223
 
1150
1224
  if (typeof passphrase === 'string' || passphrase instanceof String) {
1151
1225
 
1152
1226
  } else {
1153
- console.error('deserializeEncryptedWallet: passphrase is not a string');
1154
1227
  return null;
1155
1228
  }
1156
1229
 
@@ -1158,54 +1231,50 @@ function deserializeEncryptedWallet(walletJsonString, passphrase) {
1158
1231
  try {
1159
1232
  walletJsonObj = JSON.parse(walletJsonString);
1160
1233
  } catch (e) {
1161
- console.error('deserializeEncryptedWallet: JSON parse failed', e.message);
1162
1234
  return null;
1163
1235
  }
1164
1236
 
1165
1237
  if (walletJsonObj == null) {
1166
- console.error('deserializeEncryptedWallet: parsed JSON is null');
1167
1238
  return null;
1168
1239
  }
1169
1240
 
1170
1241
  if (walletJsonObj.address == null) {
1171
- console.error('deserializeEncryptedWallet: wallet JSON missing address');
1172
1242
  return null;
1173
1243
  }
1174
1244
 
1175
1245
  let keyPairString = JsonToWalletKeyPair(walletJsonString, passphrase);
1176
1246
  if (keyPairString == null) {
1177
- console.error('deserializeEncryptedWallet: failed to derive key pair (wrong passphrase or invalid crypto)');
1178
1247
  return null;
1179
1248
  }
1180
1249
 
1181
1250
  let keyPairSplit = keyPairString.split(",");
1182
1251
  if (keyPairSplit.length < 2) {
1183
- console.error('deserializeEncryptedWallet: key pair format invalid');
1184
1252
  return null;
1185
1253
  }
1186
1254
 
1187
1255
  let privateKeyArray = base64ToBytes(keyPairSplit[0]);
1188
1256
  let publicKeyArray = base64ToBytes(keyPairSplit[1]);
1257
+ let preExpansionSeed = null;
1258
+ if (keyPairSplit.length >= 3 && keyPairSplit[2].length > 0) {
1259
+ preExpansionSeed = base64ToBytes(keyPairSplit[2]);
1260
+ }
1189
1261
  let address = PublicKeyToAddress(publicKeyArray);
1190
1262
  if (address == null) {
1191
- console.error('deserializeEncryptedWallet: failed to derive address from public key');
1192
1263
  return null;
1193
1264
  }
1194
1265
 
1195
1266
  if (typeof address === 'string' || address instanceof String) {
1196
1267
 
1197
1268
  } else {
1198
- console.error('deserializeEncryptedWallet: address is not a string');
1199
1269
  return null;
1200
1270
  }
1201
1271
 
1202
1272
  let addressCheck = "0x" + walletJsonObj.address.toLowerCase();
1203
- if (addressCheck != address.toLowerCase()) {
1204
- console.error('deserializeEncryptedWallet: address mismatch with wallet JSON');
1273
+ if (addressCheck !== address.toLowerCase()) {
1205
1274
  return null;
1206
1275
  }
1207
1276
 
1208
- let wallet = new Wallet(address, privateKeyArray, publicKeyArray);
1277
+ let wallet = new Wallet(address, privateKeyArray, publicKeyArray, preExpansionSeed);
1209
1278
 
1210
1279
  return wallet;
1211
1280
  }
@@ -1237,11 +1306,21 @@ function serializeEncryptedWallet(wallet, passphrase) {
1237
1306
  return null;
1238
1307
  }
1239
1308
 
1240
- let walletJsonString = KeyPairToWalletJson(wallet.privateKey, wallet.publicKey, passphrase);
1309
+ let walletJsonString;
1310
+ if (wallet.preExpansionSeed != null && wallet.preExpansionSeed.length > 0) {
1311
+ const seedU8 = wallet.preExpansionSeed instanceof Uint8Array ? wallet.preExpansionSeed : new Uint8Array(wallet.preExpansionSeed);
1312
+ const result = EncryptPreExpansionSeed(seedU8, passphrase);
1313
+ if (result == null || result instanceof Error) {
1314
+ return null;
1315
+ }
1316
+ walletJsonString = result;
1317
+ } else {
1318
+ walletJsonString = KeyPairToWalletJson(wallet.privateKey, wallet.publicKey, passphrase);
1319
+ }
1241
1320
 
1242
1321
  let walletJson = JSON.parse(walletJsonString);
1243
1322
  let addressCheck = "0x" + walletJson.address;
1244
- if (addressCheck.toLowerCase() != wallet.address.toLowerCase()) {
1323
+ if (addressCheck.toLowerCase() !== wallet.address.toLowerCase()) {
1245
1324
  return null;
1246
1325
  }
1247
1326
 
@@ -1319,43 +1398,34 @@ function isByteArray(array) {
1319
1398
  */
1320
1399
  function verifyWallet(wallet) {
1321
1400
  if (isInitialized === false) {
1322
- console.log('[verifyWallet] FAIL: not initialized');
1323
1401
  return -1000;
1324
1402
  }
1325
1403
  if (wallet === null || wallet.address === null || wallet.privateKey === null || wallet.publicKey === null) {
1326
- console.log('[verifyWallet] FAIL: wallet or wallet.address/privateKey/publicKey is null');
1327
1404
  return false;
1328
1405
  }
1329
1406
  if (isAddressValid(wallet.address) === false) {
1330
- console.log('[verifyWallet] FAIL: isAddressValid(wallet.address) === false');
1331
1407
  return false;
1332
1408
  }
1333
1409
  if (isByteArray(wallet.privateKey) === false) {
1334
- console.log('[verifyWallet] FAIL: isByteArray(wallet.privateKey) === false');
1335
1410
  return false;
1336
1411
  }
1337
1412
  if (isByteArray(wallet.publicKey) === false) {
1338
- console.log('[verifyWallet] FAIL: isByteArray(wallet.publicKey) === false');
1339
1413
  return false;
1340
1414
  }
1341
1415
  const keyType = getKeyTypeFromPrivateKey(wallet.privateKey);
1342
1416
  if (keyType == null) {
1343
- console.log('[verifyWallet] FAIL: getKeyTypeFromPrivateKey returned null (privateKey.length=' + wallet.privateKey.length + ', circl.hybridedmldsaslhdsa.PrivateKeySize=' + (circl && circl.hybridedmldsaslhdsa ? circl.hybridedmldsaslhdsa.PrivateKeySize : 'N/A') + ', hybrid5.PrivateKeySize=' + (circl && (circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5) ? (circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5).PrivateKeySize : 'N/A') + ')');
1344
1417
  return false;
1345
1418
  }
1346
1419
  const hybridNs = circl && circl.hybridedmldsaslhdsa;
1347
1420
  const hybrid5Ns = circl && (circl.hybridedmldsaslhdsa5 || circl.hybridedmldsaslhds5);
1348
1421
  if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA && hybridNs && wallet.privateKey.length !== hybridNs.PrivateKeySize) {
1349
- console.log('[verifyWallet] FAIL: keyType 3 but privateKey.length !== hybridNs.PrivateKeySize');
1350
1422
  return false;
1351
1423
  }
1352
1424
  if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5 && hybrid5Ns && wallet.privateKey.length !== hybrid5Ns.PrivateKeySize) {
1353
- console.log('[verifyWallet] FAIL: keyType 5 but privateKey.length !== hybrid5Ns.PrivateKeySize');
1354
1425
  return false;
1355
1426
  }
1356
1427
  const address = PublicKeyToAddress(wallet.publicKey);
1357
1428
  if (address !== wallet.address) {
1358
- console.log('[verifyWallet] FAIL: PublicKeyToAddress(wallet.publicKey) !== wallet.address');
1359
1429
  return false;
1360
1430
  }
1361
1431
  const message = new TextEncoder().encode("verifyverifyverifyverifyverifyok");
@@ -1366,27 +1436,22 @@ function verifyWallet(wallet) {
1366
1436
  if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA && hybridNs) {
1367
1437
  sigRes = hybridNs.sign(privU8, message);
1368
1438
  if (sigRes && sigRes.error) {
1369
- console.log('[verifyWallet] FAIL: hybridNs.sign returned error:', sigRes.error);
1370
1439
  return false;
1371
1440
  }
1372
1441
  verRes = hybridNs.verify(pubU8, message, sigRes.result);
1373
1442
  } else if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5 && hybrid5Ns) {
1374
1443
  sigRes = hybrid5Ns.sign(privU8, message);
1375
1444
  if (sigRes && sigRes.error) {
1376
- console.log('[verifyWallet] FAIL: hybrid5Ns.sign returned error:', sigRes.error);
1377
1445
  return false;
1378
1446
  }
1379
1447
  verRes = hybrid5Ns.verify(pubU8, message, sigRes.result);
1380
1448
  } else {
1381
- console.log('[verifyWallet] FAIL: no CIRCL namespace for keyType (keyType=' + keyType + ', hybridNs=' + !!hybridNs + ', hybrid5Ns=' + !!hybrid5Ns + ')');
1382
1449
  return false;
1383
1450
  }
1384
1451
  if (verRes && verRes.error) {
1385
- console.log('[verifyWallet] FAIL: verify returned error:', verRes.error);
1386
1452
  return false;
1387
1453
  }
1388
1454
  if (!(verRes && verRes.result === true)) {
1389
- console.log('[verifyWallet] FAIL: verRes.result !== true (verRes=', verRes, ')');
1390
1455
  return false;
1391
1456
  }
1392
1457
  return true;
@@ -1414,6 +1479,10 @@ function serializeWallet(wallet) {
1414
1479
  "publicKey": bytesToBase64(wallet.publicKey),
1415
1480
  }
1416
1481
 
1482
+ if (wallet.preExpansionSeed != null && wallet.preExpansionSeed.length > 0) {
1483
+ walletJson.preExpansionSeed = bytesToBase64(wallet.preExpansionSeed);
1484
+ }
1485
+
1417
1486
  return JSON.stringify(walletJson);
1418
1487
  }
1419
1488
 
@@ -1421,23 +1490,35 @@ function serializeWallet(wallet) {
1421
1490
  * The deserializeWallet function creates a Wallet object from a JSON string.
1422
1491
  *
1423
1492
  * @function deserializeWallet
1424
- * @param {string} walletJson - A Wallet object representing the wallet to deserialize.
1425
- * @return {Wallet} Returns the Wallet corresponding to the walletJson. If the wallet is invalid, null is returned.
1493
+ * @param {string} walletJson - A JSON string representing the wallet to deserialize.
1494
+ * @return {Wallet|null} Returns the Wallet corresponding to the walletJson. If the wallet is invalid or the JSON is malformed, null is returned.
1426
1495
  */
1427
1496
  function deserializeWallet(walletJson) {
1428
1497
  if (isInitialized === false) {
1429
1498
  return -1000;
1430
1499
  }
1431
1500
 
1432
- var tempWallet = JSON.parse(walletJson);
1501
+ try {
1502
+ var tempWallet = JSON.parse(walletJson);
1503
+ if (tempWallet == null || typeof tempWallet !== 'object') {
1504
+ return null;
1505
+ }
1506
+
1507
+ var preExpansionSeed = null;
1508
+ if (tempWallet.preExpansionSeed != null && tempWallet.preExpansionSeed.length > 0) {
1509
+ preExpansionSeed = base64ToBytes(tempWallet.preExpansionSeed);
1510
+ }
1511
+
1512
+ var wallet = new Wallet(tempWallet.address, base64ToBytes(tempWallet.privateKey), base64ToBytes(tempWallet.publicKey), preExpansionSeed);
1433
1513
 
1434
- var wallet = new Wallet(tempWallet.address, base64ToBytes(tempWallet.privateKey), base64ToBytes(tempWallet.publicKey));
1514
+ if (verifyWallet(wallet) === false) {
1515
+ return null;
1516
+ }
1435
1517
 
1436
- if (verifyWallet(wallet) == false) {
1518
+ return wallet;
1519
+ } catch (e) {
1437
1520
  return null;
1438
1521
  }
1439
-
1440
- return wallet;
1441
1522
  }
1442
1523
 
1443
1524
  function transactionGetSigningHash(fromaddress, nonce, toaddress, amount, gas, chainid, data) {
@@ -1482,7 +1563,6 @@ function transactionGetData(fromaddress, nonce, toaddress, amount, gas, chainid,
1482
1563
  function transactionGetSigningHash2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext) {
1483
1564
  let messageDataReturn = TxnSigningHash2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext);
1484
1565
  if (messageDataReturn && messageDataReturn.error) {
1485
- console.log('[transactionGetSigningHash2] FAIL: messageDataReturn returned error:', messageDataReturn.error);
1486
1566
  return null;
1487
1567
  }
1488
1568
  var messageData = messageDataReturn.result;
@@ -1506,7 +1586,6 @@ function transactionGetTransactionHash2(fromaddress, nonce, toaddress, valueInWe
1506
1586
  }
1507
1587
  var txnHashReturn = TxnHash2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext, typedPkArray, typedSigArray)
1508
1588
  if (txnHashReturn && txnHashReturn.error) {
1509
- console.log('[transactionGetTransactionHash2] FAIL: TxnHash2 returned error:', txnHashReturn.error);
1510
1589
  return null;
1511
1590
  }
1512
1591
  return txnHashReturn.result;
@@ -1525,7 +1604,6 @@ function transactionGetData2(fromaddress, nonce, toaddress, valueInWeiHex, gas,
1525
1604
  }
1526
1605
  var txnDataReturn = TxnData2(fromaddress, nonce, toaddress, valueInWeiHex, gas, chainid, data, remarks, signingContext, typedPkArray, typedSigArray)
1527
1606
  if (txnDataReturn && txnDataReturn.error) {
1528
- console.log('[transactionGetData2] FAIL: TxnData2 returned error:', txnDataReturn.error);
1529
1607
  return null;
1530
1608
  }
1531
1609
  return txnDataReturn.result;
@@ -1573,7 +1651,7 @@ async function postTransaction(txnData) {
1573
1651
  return new SendResult(-601, null, null, requestId);
1574
1652
  }
1575
1653
 
1576
- if (response.status == 200 || response.status == 204) {
1654
+ if (response.status === 200 || response.status === 204) {
1577
1655
  return new SendResult(0, null, response, requestId);
1578
1656
  }
1579
1657
 
@@ -1588,7 +1666,7 @@ async function postTransaction(txnData) {
1588
1666
  *
1589
1667
  * @async
1590
1668
  * @function getLatestBlockDetails
1591
- * @return {Promise<LatestBlockDetailsResult>} Returns a promise of an object of type BlockDetailsResult.
1669
+ * @return {Promise<LatestBlockDetailsResult>} Returns a promise of an object of type LatestBlockDetailsResult.
1592
1670
  */
1593
1671
  async function getLatestBlockDetails() {
1594
1672
  if (isInitialized === false) {
@@ -1634,7 +1712,7 @@ async function getLatestBlockDetails() {
1634
1712
  }
1635
1713
 
1636
1714
  let blockNumber = parseInt(result.blockNumber);
1637
- if (Number.isInteger(blockNumber) == false) {
1715
+ if (Number.isInteger(blockNumber) === false) {
1638
1716
  return new LatestBlockDetailsResult(-105, null, response, requestId);
1639
1717
  }
1640
1718
 
@@ -1661,7 +1739,7 @@ async function getAccountDetails(address) {
1661
1739
  if (address == null) {
1662
1740
  return new AccountDetailsResult(-200, null, null, null);
1663
1741
  }
1664
- if (isAddressValid(address) == false) {
1742
+ if (isAddressValid(address) === false) {
1665
1743
  return new AccountDetailsResult(-201, null, null, null);
1666
1744
  }
1667
1745
 
@@ -1706,7 +1784,7 @@ async function getAccountDetails(address) {
1706
1784
  }
1707
1785
 
1708
1786
  let blockNumber = parseInt(result.blockNumber);
1709
- if (Number.isInteger(blockNumber) == false) {
1787
+ if (Number.isInteger(blockNumber) === false) {
1710
1788
  return new AccountDetailsResult(-207, null, response, requestId);
1711
1789
  }
1712
1790
 
@@ -1714,7 +1792,7 @@ async function getAccountDetails(address) {
1714
1792
  nonce = 0;
1715
1793
  } else {
1716
1794
  let tempNonce = parseInt(result.nonce);
1717
- if (Number.isInteger(tempNonce) == true) {
1795
+ if (Number.isInteger(tempNonce) === true) {
1718
1796
  nonce = tempNonce;
1719
1797
  if (nonce < 0) {
1720
1798
  return new AccountDetailsResult(-208, null, response, requestId);
@@ -1725,7 +1803,7 @@ async function getAccountDetails(address) {
1725
1803
  }
1726
1804
 
1727
1805
  if (result.balance != null) {
1728
- if (isLargeNumber(result.balance) == false) {
1806
+ if (isLargeNumber(result.balance) === false) {
1729
1807
  return new AccountDetailsResult(-210, null, response, requestId);
1730
1808
  } else {
1731
1809
  balance = result.balance;
@@ -1736,7 +1814,7 @@ async function getAccountDetails(address) {
1736
1814
  return new AccountDetailsResult(0, accountDetails, response, requestId);
1737
1815
 
1738
1816
  } catch (error) {
1739
- return new AccountDetailsResult(0, null, null, requestId, error);
1817
+ return new AccountDetailsResult(-10000, null, null, requestId, error);
1740
1818
  }
1741
1819
  }
1742
1820
 
@@ -1750,7 +1828,7 @@ async function getAccountDetails(address) {
1750
1828
  * @async
1751
1829
  * @function getTransactionDetails
1752
1830
  * @param {string} txnHash - The hash of the transaction to retrieve.
1753
- * @return {Promise<TransactionDetailsResult>} Returns a promise of type type TransactionDetailsResult.
1831
+ * @return {Promise<TransactionDetailsResult>} Returns a promise of type TransactionDetailsResult.
1754
1832
  */
1755
1833
  async function getTransactionDetails(txnHash) {
1756
1834
  if (isInitialized === false) {
@@ -1760,7 +1838,7 @@ async function getTransactionDetails(txnHash) {
1760
1838
  if (txnHash == null) {
1761
1839
  return new TransactionDetailsResult(-300, null, null, null);
1762
1840
  }
1763
- if (isAddressValid(txnHash) == false) {
1841
+ if (isAddressValid(txnHash) === false) {
1764
1842
  return new TransactionDetailsResult(-301, null, null, null);
1765
1843
  }
1766
1844
 
@@ -1802,7 +1880,7 @@ async function getTransactionDetails(txnHash) {
1802
1880
 
1803
1881
  if (result.blockNumber !== null) {
1804
1882
  let tempBlockNumber = parseInt(result.blockNumber);
1805
- if (Number.isInteger(tempBlockNumber) == true) {
1883
+ if (Number.isInteger(tempBlockNumber) === true) {
1806
1884
  transactionDetails.blockNumber = tempBlockNumber;
1807
1885
  }
1808
1886
  if (tempBlockNumber < 0) {
@@ -1832,7 +1910,7 @@ async function getTransactionDetails(txnHash) {
1832
1910
 
1833
1911
  return new TransactionDetailsResult(0, transactionDetails, response, requestId);
1834
1912
  } catch (error) {
1835
- return new TransactionDetailsResult(0, null, null, requestId, error);
1913
+ return new TransactionDetailsResult(-10000, null, null, requestId, error);
1836
1914
  }
1837
1915
  }
1838
1916
 
@@ -1841,14 +1919,14 @@ async function getTransactionDetails(txnHash) {
1841
1919
  * Transactions may take a while to get registered in the blockchain. After a transaction is submitted, it may take a while before it is available for listing.
1842
1920
  * Some transactions that have lower balance than the minimum required for gas fees may be discarded.
1843
1921
  * In these cases, the transactions may not be returned when invoking the listAccountTransactions function.
1844
- * You should consider the transaction as succeeded only if the status field AccountDetailsCompact object is 0x1 (success).
1922
+ * You should consider the transaction as succeeded only if the status field of the AccountTransactionCompact object is 0x1 (success).
1845
1923
  * Both transactions from and transactions to the address will be returned in the list.
1846
1924
  * Use the getTransactionDetails function, passing the hash of the transaction to get detailed information about the transaction.
1847
1925
  * @async
1848
1926
  * @function listAccountTransactions
1849
1927
  * @param {string} address - The address for which the transactions have to be listed.
1850
1928
  * @param {number} pageNumber - The page number for which the transactions has to be listed for the account. Pass 0 to list the latest page. Pass 1 to list the oldest page. A maximum of 20 transactions are returned in each page. The response of this API includes a field that shows the pageCount (total number of pages available). You can pass any number between 1 to pageCount to get the corresponding page.
1851
- * @return {Promise<ListAccountTransactionsResponse>} Returns a promise of type type ListAccountTransactionsResponse.
1929
+ * @return {Promise<AccountTransactionsResult>} Returns a promise of type AccountTransactionsResult.
1852
1930
  */
1853
1931
  async function listAccountTransactions(address, pageNumber) {
1854
1932
  if (isInitialized === false) {
@@ -1929,7 +2007,7 @@ async function listAccountTransactions(address, pageNumber) {
1929
2007
 
1930
2008
  return new AccountTransactionsResult(0, listAccountDetailsResponse, response, requestId);
1931
2009
  } catch (error) {
1932
- return new AccountTransactionsResult(0, null, null, requestId, error);
2010
+ return new AccountTransactionsResult(-10000, null, null, requestId, error);
1933
2011
  }
1934
2012
  }
1935
2013
 
@@ -1945,7 +2023,7 @@ async function listAccountTransactions(address, pageNumber) {
1945
2023
  * @param {string} toAddress - The address to which the coins should be sent.
1946
2024
  * @param {string} coins - The string representing the number of coins (in ether) to send. To convert between ethers and wei, see https://docs.ethers.org/v4/api-utils.html#ether-strings-and-wei
1947
2025
  * @param {number} nonce - The nonce of the account retrieved by invoking the getAccountDetails function. You have to carefully manage state of the nonce to avoid sending the coins multiple times, such as when retrying sendCoins after a network error.
1948
- * @return {SignResult} Returns a promise of type SignResult.
2026
+ * @return {Promise<SignResult>} Returns a promise of type SignResult.
1949
2027
  */
1950
2028
  async function signSendCoinTransaction(wallet, toAddress, coins, nonce) {
1951
2029
  if (isInitialized === false) {
@@ -1956,20 +2034,20 @@ async function signSendCoinTransaction(wallet, toAddress, coins, nonce) {
1956
2034
  return new SignResult(-500, null, null);
1957
2035
  }
1958
2036
 
1959
- if (isAddressValid(toAddress) == false) {
2037
+ if (isAddressValid(toAddress) === false) {
1960
2038
  return new SignResult(-501, null, null);
1961
2039
  }
1962
2040
 
1963
- if (verifyWallet(wallet) == false) {
2041
+ if (verifyWallet(wallet) === false) {
1964
2042
  return new SignResult(-502, null, null);
1965
2043
  }
1966
2044
 
1967
- if (isLargeNumber(coins) == false) {
2045
+ if (isLargeNumber(coins) === false) {
1968
2046
  return new SignResult(-503, null, null);
1969
2047
  }
1970
2048
 
1971
2049
  let tempNonce = parseInt(nonce);
1972
- if (Number.isInteger(tempNonce) == false) {
2050
+ if (Number.isInteger(tempNonce) === false) {
1973
2051
  return new SignResult(-504, null, null);
1974
2052
  }
1975
2053
  nonce = tempNonce;
@@ -2026,8 +2104,8 @@ async function signSendCoinTransaction(wallet, toAddress, coins, nonce) {
2026
2104
  * @param {string} toAddress - The address to which the coins should be sent.
2027
2105
  * @param {string} coins - The string representing the number of coins (in ether) to send. To convert between ethers and wei, see https://docs.ethers.org/v4/api-utils.html#ether-strings-and-wei
2028
2106
  * @param {number} nonce - The nonce of the account retrieved by invoking the getAccountDetails function. You have to carefully manage state of the nonce to avoid sending the coins multiple times, such as when retrying sendCoins after a network error.
2029
- * @param {number} data - The data to be signed.
2030
- * @return {SignResult} Returns a promise of type SignResult.
2107
+ * @param {string} data - Ignored. This parameter is accepted but not used. Use signRawTransaction to pass contract data.
2108
+ * @return {Promise<SignResult>} Returns a promise of type SignResult.
2031
2109
  */
2032
2110
  async function signTransaction(wallet, toAddress, coins, nonce, data) {
2033
2111
  if (isInitialized === false) {
@@ -2038,20 +2116,20 @@ async function signTransaction(wallet, toAddress, coins, nonce, data) {
2038
2116
  return new SignResult(-500, null, null);
2039
2117
  }
2040
2118
 
2041
- if (isAddressValid(toAddress) == false) {
2119
+ if (isAddressValid(toAddress) === false) {
2042
2120
  return new SignResult(-501, null, null);
2043
2121
  }
2044
2122
 
2045
- if (verifyWallet(wallet) == false) {
2123
+ if (verifyWallet(wallet) === false) {
2046
2124
  return new SignResult(-502, null, null);
2047
2125
  }
2048
2126
 
2049
- if (isLargeNumber(coins) == false) {
2127
+ if (isLargeNumber(coins) === false) {
2050
2128
  return new SignResult(-503, null, null);
2051
2129
  }
2052
2130
 
2053
2131
  let tempNonce = parseInt(nonce);
2054
- if (Number.isInteger(tempNonce) == false) {
2132
+ if (Number.isInteger(tempNonce) === false) {
2055
2133
  return new SignResult(-504, null, null);
2056
2134
  }
2057
2135
  nonce = tempNonce;
@@ -2112,6 +2190,10 @@ function hexStringToUint8Array(hex) {
2112
2190
  hex = hex.slice(2);
2113
2191
  }
2114
2192
 
2193
+ if (/[^0-9a-fA-F]/.test(hex)) {
2194
+ return new Uint8Array(0);
2195
+ }
2196
+
2115
2197
  // Ensure even length (pad with leading zero if needed)
2116
2198
  if (hex.length % 2 !== 0) {
2117
2199
  hex = '0' + hex;
@@ -2162,7 +2244,7 @@ function signRawTransaction(transactionSigningRequest) {
2162
2244
  // Convert BigInt to hex string
2163
2245
  valueInWeiHex = '0x' + transactionSigningRequest.valueInWei.toString(16);
2164
2246
  } else if (typeof transactionSigningRequest.valueInWei === 'string') {
2165
- if (transactionSigningRequest.valueInWei.startsWith('0x') === false) {
2247
+ if (transactionSigningRequest.valueInWei.startsWith('0x') === false || /[^0-9a-fA-F]/.test(transactionSigningRequest.valueInWei.slice(2))) {
2166
2248
  return new SignResult(-903, null, null);
2167
2249
  }
2168
2250
  valueInWeiHex = transactionSigningRequest.valueInWei;
@@ -2182,7 +2264,7 @@ function signRawTransaction(transactionSigningRequest) {
2182
2264
 
2183
2265
  let data = null;
2184
2266
  if (transactionSigningRequest.data !== null) {
2185
- if (typeof transactionSigningRequest.data !== 'string' || transactionSigningRequest.data.startsWith('0x') === false) {
2267
+ if (typeof transactionSigningRequest.data !== 'string' || transactionSigningRequest.data.startsWith('0x') === false || /[^0-9a-fA-F]/.test(transactionSigningRequest.data.slice(2))) {
2186
2268
  return new SignResult(-906, null, null);
2187
2269
  }
2188
2270
  data = hexStringToUint8Array(transactionSigningRequest.data);
@@ -2199,7 +2281,7 @@ function signRawTransaction(transactionSigningRequest) {
2199
2281
 
2200
2282
  let remarks = null;
2201
2283
  if (transactionSigningRequest.remarks !== null) {
2202
- if (typeof transactionSigningRequest.remarks !== 'string' || transactionSigningRequest.remarks.startsWith('0x') === false) {
2284
+ if (typeof transactionSigningRequest.remarks !== 'string' || transactionSigningRequest.remarks.startsWith('0x') === false || /[^0-9a-fA-F]/.test(transactionSigningRequest.remarks.slice(2))) {
2203
2285
  return new SignResult(-909, null, null);
2204
2286
  }
2205
2287
  remarks = hexStringToUint8Array(transactionSigningRequest.remarks);
@@ -2399,20 +2481,20 @@ async function sendCoins(wallet, toAddress, coins, nonce) {
2399
2481
  return new SendResult(-1, null, null, null);
2400
2482
  }
2401
2483
 
2402
- if (isAddressValid(toAddress) == false) {
2484
+ if (isAddressValid(toAddress) === false) {
2403
2485
  return new SendResult(-2, null, null, null);
2404
2486
  }
2405
2487
 
2406
- if (verifyWallet(wallet) == false) {
2488
+ if (verifyWallet(wallet) === false) {
2407
2489
  return new SendResult(-3, null, null, null);
2408
2490
  }
2409
2491
 
2410
- if (isLargeNumber(coins) == false) {
2492
+ if (isLargeNumber(coins) === false) {
2411
2493
  return new SendResult(-4, null, null, null);
2412
2494
  }
2413
2495
 
2414
2496
  let tempNonce = parseInt(nonce);
2415
- if (Number.isInteger(tempNonce) == false) {
2497
+ if (Number.isInteger(tempNonce) === false) {
2416
2498
  return new SendResult(-5, null, null, null);
2417
2499
  }
2418
2500
  nonce = tempNonce;
@@ -3037,7 +3119,7 @@ module.exports = {
3037
3119
  AccountTransactionsResult,
3038
3120
  ListAccountTransactionsResponse,
3039
3121
  AccountTransactionCompact,
3040
- newWalletSeed,
3122
+ newWalletSeedWords,
3041
3123
  openWalletFromSeed,
3042
3124
  openWalletFromSeedWords,
3043
3125
  publicKeyFromSignature,