@keetanetwork/keetanet-client 0.14.13 → 0.14.14

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 (123) hide show
  1. package/client/index-browser.d.ts +3 -1
  2. package/client/index-browser.js +167 -49
  3. package/client/index.d.ts +3 -1
  4. package/client/index.js +166 -50
  5. package/config/index.d.ts +3 -0
  6. package/docs/assets/hierarchy.js +1 -1
  7. package/docs/assets/search.js +1 -1
  8. package/docs/classes/KeetaNetSDK.Client.html +4 -3
  9. package/docs/classes/KeetaNetSDK.Referenced.BaseSet.html +1 -1
  10. package/docs/classes/KeetaNetSDK.Referenced.BaseVoteBuilder.html +1 -1
  11. package/docs/classes/KeetaNetSDK.Referenced.BlockHash.html +2 -2
  12. package/docs/classes/KeetaNetSDK.Referenced.BlockOperation.html +1 -1
  13. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationCREATE_IDENTIFIER.html +1 -1
  14. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationMANAGE_CERTIFICATE.html +1 -1
  15. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationMODIFY_PERMISSIONS.html +1 -1
  16. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationRECEIVE.html +1 -1
  17. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationSEND.html +1 -1
  18. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationSET_INFO.html +1 -1
  19. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationSET_REP.html +1 -1
  20. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationTOKEN_ADMIN_MODIFY_BALANCE.html +1 -1
  21. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationTOKEN_ADMIN_SUPPLY.html +1 -1
  22. package/docs/classes/KeetaNetSDK.Referenced.CertificateHash.html +2 -2
  23. package/docs/classes/KeetaNetSDK.Referenced.ECDSAKeyPair.html +1 -1
  24. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1KeyPair.html +1 -1
  25. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1PrivateKey.html +3 -2
  26. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1PublicKey.html +3 -2
  27. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1Signature.html +3 -2
  28. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1KeyPair.html +1 -1
  29. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1PrivateKey.html +3 -2
  30. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1PublicKey.html +3 -2
  31. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1Signature.html +3 -2
  32. package/docs/classes/KeetaNetSDK.Referenced.ED25519KeyPair.html +1 -1
  33. package/docs/classes/KeetaNetSDK.Referenced.ED25519PrivateKey.html +3 -2
  34. package/docs/classes/KeetaNetSDK.Referenced.ED25519PublicKey.html +3 -2
  35. package/docs/classes/KeetaNetSDK.Referenced.ED25519Signature.html +3 -2
  36. package/docs/classes/KeetaNetSDK.Referenced.ExternalKeyPair.html +1 -1
  37. package/docs/classes/KeetaNetSDK.Referenced.ExternalSet.html +1 -1
  38. package/docs/classes/KeetaNetSDK.Referenced.IdempotentKey.html +2 -2
  39. package/docs/classes/KeetaNetSDK.Referenced.IdentifierKey.html +3 -2
  40. package/docs/classes/KeetaNetSDK.Referenced.IdentifierKeyPair.html +1 -1
  41. package/docs/classes/KeetaNetSDK.Referenced.KeetaNetError.html +1 -1
  42. package/docs/classes/KeetaNetSDK.Referenced.KeetaNetErrorBase.html +1 -1
  43. package/docs/classes/KeetaNetSDK.Referenced.KeetaNetLedgerError.html +1 -1
  44. package/docs/classes/KeetaNetSDK.Referenced.KeetaNetLedgerIdempotentKeyError.html +1 -1
  45. package/docs/classes/KeetaNetSDK.Referenced.KeetaNetLedgerVoteError.html +1 -1
  46. package/docs/classes/KeetaNetSDK.Referenced.KeyInterface.html +1 -1
  47. package/docs/classes/KeetaNetSDK.Referenced.KeyStorage.html +3 -2
  48. package/docs/classes/KeetaNetSDK.Referenced.Log.html +15 -3
  49. package/docs/classes/KeetaNetSDK.Referenced.PermissionSetHolder.html +1 -1
  50. package/docs/classes/KeetaNetSDK.Referenced.PossiblyExpiredVote.html +1 -1
  51. package/docs/classes/KeetaNetSDK.Referenced.SignatureStorage.html +3 -2
  52. package/docs/classes/KeetaNetSDK.Referenced.Stats.html +1 -1
  53. package/docs/classes/KeetaNetSDK.Referenced.StatsPending.html +1 -1
  54. package/docs/classes/KeetaNetSDK.Referenced.Vote.html +1 -1
  55. package/docs/classes/KeetaNetSDK.Referenced.VoteBlockBundle.html +1 -1
  56. package/docs/classes/KeetaNetSDK.Referenced.VoteBlockHash.html +3 -2
  57. package/docs/classes/KeetaNetSDK.Referenced.VoteBuilder.html +1 -1
  58. package/docs/classes/KeetaNetSDK.Referenced.VoteHash.html +3 -2
  59. package/docs/classes/KeetaNetSDK.Referenced.VoteLikeBase.html +1 -1
  60. package/docs/classes/KeetaNetSDK.Referenced.VoteQuote.html +1 -1
  61. package/docs/classes/KeetaNetSDK.Referenced.VoteQuoteBuilder.html +1 -1
  62. package/docs/classes/KeetaNetSDK.Referenced.VoteStaple.html +1 -1
  63. package/docs/classes/KeetaNetSDK.Referenced.VoteStapleHash.html +3 -2
  64. package/docs/classes/KeetaNetSDK.Referenced.src_lib_utils_buffer.BufferStorage.html +3 -2
  65. package/docs/classes/KeetaNetSDK.UserClient.html +2 -2
  66. package/docs/hierarchy.html +1 -1
  67. package/docs/interfaces/KeetaNetSDK.Referenced.ACLEntry.html +1 -1
  68. package/docs/interfaces/KeetaNetSDK.Referenced.ACLUpdate.html +1 -1
  69. package/docs/interfaces/KeetaNetSDK.Referenced.ASN1ExplicitContextTag.html +1 -1
  70. package/docs/interfaces/KeetaNetSDK.Referenced.ASN1ImplicitContextTag.html +1 -1
  71. package/docs/interfaces/KeetaNetSDK.Referenced.ASN1Object.html +1 -1
  72. package/docs/interfaces/KeetaNetSDK.Referenced.BaseExternalKeyPairFunctions.html +1 -1
  73. package/docs/interfaces/KeetaNetSDK.Referenced.BaseGenerationConfig.html +1 -1
  74. package/docs/interfaces/KeetaNetSDK.Referenced.BaseIdentifierCreateArguments.html +1 -1
  75. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperation.html +1 -1
  76. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationCREATE_IDENTIFIER.html +1 -1
  77. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationMANAGE_CERTIFICATE.html +1 -1
  78. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationMANAGE_CERTIFICATESerializable.html +1 -1
  79. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationMODIFY_PERMISSIONS.html +1 -1
  80. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationRECEIVE.html +1 -1
  81. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationSEND.html +1 -1
  82. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationSET_INFO.html +1 -1
  83. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationSET_REP.html +1 -1
  84. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationTOKEN_ADMIN_MODIFY_BALANCE.html +1 -1
  85. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationTOKEN_ADMIN_SUPPLY.html +1 -1
  86. package/docs/interfaces/KeetaNetSDK.Referenced.BlockV1Canonical.html +1 -1
  87. package/docs/interfaces/KeetaNetSDK.Referenced.BlockV2Canonical.html +1 -1
  88. package/docs/interfaces/KeetaNetSDK.Referenced.Constructor.html +1 -1
  89. package/docs/interfaces/KeetaNetSDK.Referenced.DisposableTimingHandle.html +1 -1
  90. package/docs/interfaces/KeetaNetSDK.Referenced.ExternalKeyPairFunctionsNoEncryption.html +1 -1
  91. package/docs/interfaces/KeetaNetSDK.Referenced.ExternalKeyPairFunctionsSupportsEncryption.html +1 -1
  92. package/docs/interfaces/KeetaNetSDK.Referenced.InitialConfigSupply.html +1 -1
  93. package/docs/interfaces/KeetaNetSDK.Referenced.InstanceSet.html +1 -1
  94. package/docs/interfaces/KeetaNetSDK.Referenced.KVGenericOptionsType.html +1 -1
  95. package/docs/interfaces/KeetaNetSDK.Referenced.KVSetOptionsType.html +1 -1
  96. package/docs/interfaces/KeetaNetSDK.Referenced.ModifyTokenBalanceEntry.html +1 -1
  97. package/docs/interfaces/KeetaNetSDK.Referenced.MultiSigIdentifierCreateArguments.html +1 -1
  98. package/docs/interfaces/KeetaNetSDK.Referenced.MultisigConfig.html +1 -1
  99. package/docs/interfaces/KeetaNetSDK.Referenced.NumericValueEntry.html +1 -1
  100. package/docs/interfaces/KeetaNetSDK.Referenced.P2PPeerBase.html +1 -1
  101. package/docs/interfaces/KeetaNetSDK.Referenced.P2PPeerListener.html +1 -1
  102. package/docs/interfaces/KeetaNetSDK.Referenced.P2PPeerRepBase.html +1 -1
  103. package/docs/interfaces/KeetaNetSDK.Referenced.PublicKeyStorage.html +3 -2
  104. package/docs/interfaces/KeetaNetSDK.Referenced.PublishOptions.html +1 -1
  105. package/docs/interfaces/KeetaNetSDK.Referenced.RequestTokenReceiveEntry.html +1 -1
  106. package/docs/interfaces/KeetaNetSDK.Referenced.TokenNumericEntry.html +1 -1
  107. package/docs/interfaces/KeetaNetSDK.Referenced.UserClientConfig.html +1 -1
  108. package/docs/interfaces/KeetaNetSDK.Referenced.UserClientOptions.html +1 -1
  109. package/docs/interfaces/KeetaNetSDK.Referenced.WithIsInstance.html +1 -1
  110. package/docs/interfaces/KeetaNetSDK.Referenced.src_config.ValidationConfig.html +2 -2
  111. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1BitString.html +1 -1
  112. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1Date.html +1 -1
  113. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1OID.html +1 -1
  114. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1Set.html +1 -1
  115. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1String.html +1 -1
  116. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1Struct.html +1 -1
  117. package/docs/types/KeetaNetSDK.Referenced.src_config.NetworkConfig.html +1 -1
  118. package/lib/ledger/common.d.ts +3 -0
  119. package/lib/log/index.d.ts +20 -0
  120. package/lib/utils/buffer.d.ts +1 -0
  121. package/npm-shrinkwrap.json +2 -2
  122. package/package.json +1 -1
  123. package/version.d.ts +1 -1
package/client/index.js CHANGED
@@ -58806,11 +58806,12 @@ class Client {
58806
58806
  * @param account The account to get the history for -- if null then the history for all accounts will be returned
58807
58807
  * @param options The options to use for the request
58808
58808
  * @param options.startBlocksHash The block hash to start from -- this is used to paginate the request
58809
- * @param options.depth The maximum number of vote staples to return -- this is used to limit the number of vote staples returned
58809
+ * @param options.depth The maximum number of vote staples to return -- this is used to limit the number of vote staples returned, default is everything)
58810
+ * @param options.pageSize How large of a page size to request at a given time (default is 200)
58810
58811
  * @return The history of vote staples for the given account, in reverse order starting with the most recent vote staple
58811
58812
  */
58812
58813
  async getHistory(account, options = {}) {
58813
- const { depth = Infinity, startBlocksHash } = options;
58814
+ const { depth = Infinity, pageSize = 200, startBlocksHash } = options;
58814
58815
  account = account_1.default.toPublicKeyString(account);
58815
58816
  let startVoteStapleID = undefined;
58816
58817
  if (startBlocksHash !== undefined) {
@@ -58823,7 +58824,7 @@ class Client {
58823
58824
  }
58824
58825
  const retval = [];
58825
58826
  while (retval.length < depth) {
58826
- const limit = Math.min(depth - retval.length, 200);
58827
+ const limit = Math.min(depth - retval.length, pageSize);
58827
58828
  const query = {
58828
58829
  limit: String(limit)
58829
58830
  };
@@ -58861,7 +58862,16 @@ class Client {
58861
58862
  break;
58862
58863
  }
58863
58864
  }
58864
- startVoteStapleID = history.history.slice(-1)[0]['$id'];
58865
+ if (typeof history.nextKey === 'string' || history.nextKey === null) {
58866
+ if (history.nextKey === null) {
58867
+ break;
58868
+ }
58869
+ startVoteStapleID = history.nextKey;
58870
+ }
58871
+ else {
58872
+ /* @deprecated -- workaround broken API */
58873
+ startVoteStapleID = history.history.slice(-1)[0]['$id'];
58874
+ }
58865
58875
  }
58866
58876
  return (retval);
58867
58877
  }
@@ -61090,6 +61100,9 @@ exports.baseValidationConfig = {
61090
61100
  maxLength: 256,
61091
61101
  regex: /^[-_A-Za-z0-9+/= ]+$/,
61092
61102
  canBeEmpty: true
61103
+ },
61104
+ validateNumericValues: {
61105
+ cutoffEpoch: 1763683200000n // 2025-11-21T00:00:00.000Z
61093
61106
  }
61094
61107
  },
61095
61108
  idempotentKey: {
@@ -63842,11 +63855,10 @@ class BlockBuilder {
63842
63855
  __classPrivateFieldSet(this, _BlockBuilder_block, new Block(block), "f");
63843
63856
  }
63844
63857
  else {
63845
- const incompleteBlockJSON = {
63846
- date: (new Date()).toISOString(),
63847
- version: 1,
63848
- ...block
63849
- };
63858
+ const incompleteBlockJSON = { version: 1, ...block };
63859
+ if (incompleteBlockJSON.date === undefined) {
63860
+ incompleteBlockJSON.date = (new Date()).toISOString();
63861
+ }
63850
63862
  /*
63851
63863
  * Map input to our values
63852
63864
  */
@@ -64397,11 +64409,7 @@ class BlockOperation {
64397
64409
  if (amount === undefined || amount === null) {
64398
64410
  throw (new Error('internal error: "amount" is invalid'));
64399
64411
  }
64400
- const bigintAmount = BigInt(amount);
64401
- if (bigintAmount < 0n) {
64402
- throw (new block_1.default('BLOCK_AMOUNT_BELOW_ZERO', 'value cannot be negative'));
64403
- }
64404
- return (bigintAmount);
64412
+ return (BigInt(amount));
64405
64413
  }
64406
64414
  }
64407
64415
  BlockOperation.isInstance = (0, helper_1.checkableGenerator)(BlockOperation);
@@ -64442,6 +64450,7 @@ class BlockOperationSEND extends BlockOperation {
64442
64450
  validate(context) {
64443
64451
  const { block } = context;
64444
64452
  const account = block.account;
64453
+ (0, common_1.validateNumericValue)(this.amount, block, 'amount');
64445
64454
  // Only allow tokens to use send if they are the token being sent
64446
64455
  if (account.keyType === account_1.AccountKeyAlgorithm.TOKEN && this.token.comparePublicKey(account) === false) {
64447
64456
  throw (new block_1.default('BLOCK_NO_TOKEN_OP', 'Tokens cannot use SEND, did you mean to use TOKEN_ADMIN_MODIFY_BALANCE'));
@@ -64540,6 +64549,7 @@ class BlockOperationRECEIVE extends BlockOperation {
64540
64549
  validate(context) {
64541
64550
  const { block } = context;
64542
64551
  const account = block.account;
64552
+ (0, common_1.validateNumericValue)(this.amount, block, 'amount');
64543
64553
  if (account.isToken()) {
64544
64554
  throw (new block_1.default('BLOCK_NO_TOKEN_OP', 'Token addresses cannot use RECEIVE'));
64545
64555
  }
@@ -64619,6 +64629,7 @@ class BlockOperationTOKEN_ADMIN_MODIFY_BALANCE extends BlockOperation {
64619
64629
  }
64620
64630
  validate(context) {
64621
64631
  const { block } = context;
64632
+ (0, common_1.validateNumericValue)(__classPrivateFieldGet(this, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_amount, "f"), block, 'amount');
64622
64633
  if (block.account.keyType === account_1.AccountKeyAlgorithm.TOKEN) {
64623
64634
  throw (new block_1.default('BLOCK_NO_TOKEN_OP', 'You cannot use TOKEN_ADMIN_MODIFY_BALANCE on a token account'));
64624
64635
  }
@@ -65019,6 +65030,7 @@ class BlockOperationTOKEN_ADMIN_SUPPLY extends BlockOperation {
65019
65030
  }
65020
65031
  validate(context) {
65021
65032
  const { block } = context;
65033
+ (0, common_1.validateNumericValue)(__classPrivateFieldGet(this, _BlockOperationTOKEN_ADMIN_SUPPLY_amount, "f"), block, 'amount');
65022
65034
  if (block.account.keyType !== account_1.AccountKeyAlgorithm.TOKEN) {
65023
65035
  throw (new block_1.default('BLOCK_ONLY_TOKEN_OP', 'Only token accounts can use TOKEN_ADMIN_SUPPLY'));
65024
65036
  }
@@ -66492,6 +66504,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
66492
66504
  exports.LedgerStorageBase = void 0;
66493
66505
  exports.findPermissionMatch = findPermissionMatch;
66494
66506
  exports.validateSupply = validateSupply;
66507
+ exports.validateNumericValue = validateNumericValue;
66495
66508
  exports.validateBlockSignerCount = validateBlockSignerCount;
66496
66509
  exports.validateBlockSignerDepth = validateBlockSignerDepth;
66497
66510
  exports.computeLedgerEffect = computeLedgerEffect;
@@ -66533,6 +66546,16 @@ function validateSupply(amount, network) {
66533
66546
  throw (new block_2.default('BLOCK_SUPPLY_INVALID', `supply does not fit proper format -- GOT: '${amount}' MaxValue: ${maxValue}`));
66534
66547
  }
66535
66548
  }
66549
+ function validateNumericValue(value, block, fieldName, context) {
66550
+ if (value >= 0n) {
66551
+ return;
66552
+ }
66553
+ const config = (0, config_1.getValidation)(block.network).blockOperations.validateNumericValues;
66554
+ if (BigInt(block.date.valueOf()) < config.cutoffEpoch) {
66555
+ return;
66556
+ }
66557
+ throw (new block_2.default('BLOCK_AMOUNT_BELOW_ZERO', `${fieldName ?? 'value'} cannot be negative`));
66558
+ }
66536
66559
  function validateBlockSignerCount(amount, network) {
66537
66560
  const { maxValue } = (0, config_1.getValidation)(network).accountInfoFieldRules['blockSignerCount'];
66538
66561
  if (amount > maxValue || amount < 1n) {
@@ -67386,9 +67409,6 @@ function updateAccountInfoInState(state, account, info) {
67386
67409
  * Compute the effect of a SEND operation
67387
67410
  */
67388
67411
  function computeEffectOfOperationSEND(state, block, operation) {
67389
- if (operation.amount < 0n) {
67390
- throw (new Error('Internal error: SEND operation with negative amount'));
67391
- }
67392
67412
  // Decrement sender balance
67393
67413
  const senderChange = {
67394
67414
  state,
@@ -67416,9 +67436,6 @@ function computeEffectOfOperationSEND(state, block, operation) {
67416
67436
  * Compute the effect of a RECEIVE operation
67417
67437
  */
67418
67438
  function computeEffectOfOperationRECEIVE(state, block, operation) {
67419
- if (operation.amount < 0n) {
67420
- throw (new Error('Internal error: RECEIVE operation with negative amount'));
67421
- }
67422
67439
  // Increment recipient balance
67423
67440
  const recipientChange = {
67424
67441
  state,
@@ -67454,9 +67471,6 @@ function computeEffectOfOperationRECEIVE(state, block, operation) {
67454
67471
  }
67455
67472
  }
67456
67473
  function computeEffectOfOperationTOKEN_ADMIN_MODIFY_BALANCE(state, block, operation) {
67457
- if (operation.amount < 0n) {
67458
- throw (new Error('Internal error: TOKEN_ADMIN_MODIFY_BALANCE operation with negative amount'));
67459
- }
67460
67474
  if (operation.method === block_1.Block.AdjustMethod.SET) {
67461
67475
  const setChange = {
67462
67476
  state,
@@ -67570,9 +67584,6 @@ function computeEffectOfOperationMODIFY_PERMISSIONS(state, block, operation) {
67570
67584
  });
67571
67585
  }
67572
67586
  function computeEffectOfOperationTOKEN_ADMIN_SUPPLY(state, block, operation) {
67573
- if (operation.amount < 0n) {
67574
- throw (new Error('Internal error: TOKEN_ADMIN_SUPPLY operation with negative amount'));
67575
- }
67576
67587
  const tokenPubKey = block.account.publicKeyString.get();
67577
67588
  let value = 0n;
67578
67589
  switch (operation.method) {
@@ -68970,6 +68981,13 @@ _LedgerAtomicInterface_network = new WeakMap(), _LedgerAtomicInterface_subnet =
68970
68981
  for (const block of blocks) {
68971
68982
  for (const operation of block.operations) {
68972
68983
  switch (operation.type) {
68984
+ case block_1.Block.OperationType.RECEIVE:
68985
+ case block_1.Block.OperationType.SEND:
68986
+ case block_1.Block.OperationType.TOKEN_ADMIN_SUPPLY:
68987
+ if (operation.amount < 0n) {
68988
+ throw (new Error(`Operation amount cannot be negative: ${operation.amount}`));
68989
+ }
68990
+ break;
68973
68991
  case block_1.Block.OperationType.SET_REP:
68974
68992
  if (__classPrivateFieldGet(this, _LedgerAtomicInterface_operations, "f").setRep !== undefined) {
68975
68993
  const validRep = await __classPrivateFieldGet(this, _LedgerAtomicInterface_operations, "f").setRep(block.account, operation.to);
@@ -68982,6 +69000,9 @@ _LedgerAtomicInterface_network = new WeakMap(), _LedgerAtomicInterface_subnet =
68982
69000
  if (!__classPrivateFieldGet(this, _LedgerAtomicInterface_operations, "f").enableTokenAdminModifyBalance) {
68983
69001
  throw (new ledger_1.KeetaNetLedgerError('LEDGER_OPERATION_NOT_SUPPORTED', 'TOKEN_ADMIN_MODIFY_BALANCE operation not supported'));
68984
69002
  }
69003
+ if (operation.amount < 0n) {
69004
+ throw (new Error(`Operation amount cannot be negative: ${operation.amount}`));
69005
+ }
68985
69006
  break;
68986
69007
  default:
68987
69008
  break;
@@ -69821,6 +69842,10 @@ class Log {
69821
69842
  * The maximum number of log entries to send to each target at a time
69822
69843
  */
69823
69844
  this.batchSize = 10;
69845
+ /**
69846
+ * Parent logger, if any -- used for creating hierarchical loggers
69847
+ */
69848
+ this.parent = null;
69824
69849
  if (options?.logDebugTracing !== undefined) {
69825
69850
  __classPrivateFieldSet(this, _Log_logDebugTracing, options.logDebugTracing, "f");
69826
69851
  }
@@ -69853,9 +69878,15 @@ class Log {
69853
69878
  if (__classPrivateFieldGet(this, _Log_destroyed, "f")) {
69854
69879
  throw (new Error('Cannot register target on destroyed Log instance'));
69855
69880
  }
69856
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
69857
- const id = Symbol('LogTargetID');
69858
- __classPrivateFieldGet(this, _Log_targets, "f").set(id, target);
69881
+ let id;
69882
+ if (this.parent) {
69883
+ id = this.parent.registerTarget(target);
69884
+ }
69885
+ else {
69886
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
69887
+ id = Symbol('LogTargetID');
69888
+ __classPrivateFieldGet(this, _Log_targets, "f").set(id, target);
69889
+ }
69859
69890
  return (id);
69860
69891
  }
69861
69892
  /**
@@ -69875,7 +69906,46 @@ class Log {
69875
69906
  if (__classPrivateFieldGet(this, _Log_destroyed, "f")) {
69876
69907
  return;
69877
69908
  }
69878
- __classPrivateFieldGet(this, _Log_targets, "f").delete(id);
69909
+ if (this.parent) {
69910
+ this.parent.unregisterTarget(id);
69911
+ }
69912
+ else {
69913
+ __classPrivateFieldGet(this, _Log_targets, "f").delete(id);
69914
+ }
69915
+ }
69916
+ /**
69917
+ * Get the currently registered log targets.
69918
+ *
69919
+ * If this is a child logger, this will return the parent's targets
69920
+ * because child loggers share the same targets as their parent.
69921
+ */
69922
+ get targets() {
69923
+ if (__classPrivateFieldGet(this, _Log_destroyed, "f")) {
69924
+ return ([]);
69925
+ }
69926
+ if (this.parent) {
69927
+ return (this.parent.targets);
69928
+ }
69929
+ return (Array.from(__classPrivateFieldGet(this, _Log_targets, "f").values()));
69930
+ }
69931
+ /**
69932
+ * Create a child logger instance that shares the same targets as this instance
69933
+ * but has its own log queue, this is useful for creating hierarchical loggers
69934
+ * which can call sync independently.
69935
+ *
69936
+ * Since the child shares the same targets, registering or unregistering targets
69937
+ * from either the parent or child will affect both.
69938
+ */
69939
+ createChild() {
69940
+ const child = new Log({
69941
+ logDebugTracing: __classPrivateFieldGet(this, _Log_logDebugTracing, "f")
69942
+ });
69943
+ /**
69944
+ * Attach child nodes to our own parent to collapse
69945
+ * chains of loggers
69946
+ */
69947
+ child.parent = this.parent ?? this;
69948
+ return (child);
69879
69949
  }
69880
69950
  /**
69881
69951
  * Emit a set of logs to all registered targets
@@ -69921,7 +69991,7 @@ class Log {
69921
69991
  * in case a target is added later; However, if there are
69922
69992
  * too many logs, drop the oldest ones
69923
69993
  */
69924
- if (__classPrivateFieldGet(this, _Log_targets, "f").size === 0) {
69994
+ if (this.targets.length === 0) {
69925
69995
  if (__classPrivateFieldGet(this, _Log_logs, "f").length > MAX_LOGS_TO_ENQUEUE_WITH_NO_TARGETS) {
69926
69996
  __classPrivateFieldGet(this, _Log_logs, "f").splice(0, __classPrivateFieldGet(this, _Log_logs, "f").length - MAX_LOGS_TO_ENQUEUE_WITH_NO_TARGETS);
69927
69997
  }
@@ -69944,7 +70014,7 @@ class Log {
69944
70014
  * while a sync is in progress -- they will continue to be sent
69945
70015
  * to the registered targets at the time of the sync
69946
70016
  */
69947
- const targets = Array.from(__classPrivateFieldGet(this, _Log_targets, "f").values());
70017
+ const targets = [...this.targets];
69948
70018
  do {
69949
70019
  try {
69950
70020
  __classPrivateFieldSet(this, _Log_shouldSyncAgain, false, "f");
@@ -73372,6 +73442,7 @@ const util_2 = __importDefault(__webpack_require__(9023));
73372
73442
  * native bindings.
73373
73443
  */
73374
73444
  const ASN1_ENCODE_DECODE_PARANOID = process.env['KEETANET_NODE_ASN1_ENCODE_DECODE_PARANOID'] === '1';
73445
+ const MAXIMUM_BIGINT_BYTE_LENGTH = 1024;
73375
73446
  function jsBigIntToBuffer(value) {
73376
73447
  /**
73377
73448
  * Convert value to Hex
@@ -73391,38 +73462,80 @@ function jsBigIntToBuffer(value) {
73391
73462
  if (valueStr.length % 2 !== 0) {
73392
73463
  valueStr = '0' + valueStr;
73393
73464
  }
73394
- /*
73395
- * Pad with a leading 0 byte if the MSB is 1 to avoid writing a
73396
- * negative number
73397
- */
73398
- const leader = valueStr.slice(0, 2);
73399
- const leaderValue = Number(`0x${leader}`);
73400
- if (!isNegative) {
73401
- if (leaderValue > 127) {
73402
- valueStr = '00' + valueStr;
73465
+ if (isNegative) {
73466
+ // Convert to minimal two's complement
73467
+ let n = BigInt('0x' + valueStr);
73468
+ n = -n;
73469
+ // Find minimal byte length
73470
+ const leader = Number('0x' + valueStr.slice(0, 2));
73471
+ let extraByteLength = 0;
73472
+ if (leader > 0x80) {
73473
+ extraByteLength = 1;
73474
+ }
73475
+ const byteLength = valueStr.length / 2 + extraByteLength;
73476
+ // Compute two's complement
73477
+ const mod = 1n << (BigInt(8 * byteLength));
73478
+ const twos = mod + n;
73479
+ let hex = twos.toString(16);
73480
+ if (hex.length % 2 !== 0) {
73481
+ hex = '0' + hex;
73403
73482
  }
73483
+ // Remove redundant leading ff bytes
73484
+ while (hex.length > 2 && hex.startsWith('ff') && Number.parseInt(hex.slice(2, 4), 16) >= 0x80) {
73485
+ hex = hex.slice(2);
73486
+ }
73487
+ valueStr = hex;
73404
73488
  }
73405
73489
  else {
73406
- if (leaderValue <= 127) {
73407
- valueStr = 'FF' + valueStr;
73490
+ const leader = valueStr.slice(0, 2);
73491
+ const leaderValue = Number(`0x${leader}`);
73492
+ if (leaderValue > 127) {
73493
+ valueStr = '00' + valueStr;
73408
73494
  }
73409
73495
  }
73496
+ if (valueStr.length / 2 >= MAXIMUM_BIGINT_BYTE_LENGTH) {
73497
+ throw (new Error(`jsBigIntToBuffer: Unable to encode bigint, too large, goes over maximum byte length of ${MAXIMUM_BIGINT_BYTE_LENGTH}`));
73498
+ }
73410
73499
  /*
73411
73500
  * Convert to a buffer
73412
73501
  */
73413
73502
  const valueBuffer = Buffer.from(valueStr, 'hex');
73414
73503
  return (valueBuffer);
73415
73504
  }
73416
- /* XXX:TODO: This does not correctly deal with negative values */
73505
+ function assertDERInteger(data) {
73506
+ const buf = Buffer.from(data.valueBlock.valueHex);
73507
+ // Check for zero-length integer
73508
+ if (buf.length === 0) {
73509
+ throw (new Error('Invalid DER: Integer has zero length'));
73510
+ }
73511
+ // Check for unnecessary leading zeros (positive numbers)
73512
+ // Only check multi-byte integers
73513
+ if (buf.length > 1 && buf[0] === 0x00 && (buf[1] & 0x80) === 0) {
73514
+ throw (new Error('Invalid DER: Integer has unnecessary leading zero byte'));
73515
+ }
73516
+ // Check for unnecessary leading 0xFF (negative numbers)
73517
+ // Only check multi-byte integers
73518
+ if (buf.length > 1 && buf[0] === 0xFF && (buf[1] & 0x80) !== 0) {
73519
+ throw (new Error('Invalid DER: Integer has unnecessary leading 0xFF byte'));
73520
+ }
73521
+ }
73417
73522
  function jsIntegerToBigInt(value) {
73418
- let valueStr;
73419
- if (value instanceof asn1js.Integer) {
73420
- valueStr = value.toString().split(':')[1].trim();
73523
+ if (typeof value === 'number') {
73524
+ return (BigInt(value));
73525
+ }
73526
+ assertDERInteger(value);
73527
+ const buf = Buffer.from(value.valueBlock.valueHex);
73528
+ const isNegative = (buf[0] & 0x80) !== 0;
73529
+ if (!isNegative) {
73530
+ return (BigInt('0x' + buf.toString('hex')));
73421
73531
  }
73422
73532
  else {
73423
- valueStr = value;
73533
+ // Two's complement: value = unsigned - 2^(8*len)
73534
+ const unsigned = BigInt('0x' + buf.toString('hex'));
73535
+ const bits = BigInt(buf.length * 8);
73536
+ const twosComp = unsigned - (1n << bits);
73537
+ return (twosComp);
73424
73538
  }
73425
- return (BigInt(valueStr));
73426
73539
  }
73427
73540
  function isASN1Object(input) {
73428
73541
  if (input === null || input === undefined || typeof input !== 'object') {
@@ -75530,6 +75643,9 @@ class BufferStorage {
75530
75643
  throw (new Error(`Unsupported conversion: ${encoding}`));
75531
75644
  }
75532
75645
  }
75646
+ toJSON() {
75647
+ return (this.toString('hex'));
75648
+ }
75533
75649
  toBigInt() {
75534
75650
  const hex_value = `0x${this.toString('hex')}`;
75535
75651
  const value = BigInt(hex_value);
@@ -79766,7 +79882,7 @@ exports.Testing = { findRDN, blockHashesFromVote, feeFromVote };
79766
79882
 
79767
79883
  Object.defineProperty(exports, "__esModule", ({ value: true }));
79768
79884
  exports.version = void 0;
79769
- exports.version = '0.14.13+g566b8de2c01660608e6eb5257113db271d7fc075';
79885
+ exports.version = '0.14.14+gdd8e58acb0e1edfb9050da584aaa65b7e5f722a2';
79770
79886
  exports["default"] = exports.version;
79771
79887
 
79772
79888
 
package/config/index.d.ts CHANGED
@@ -72,6 +72,9 @@ export interface ValidationConfig {
72
72
  };
73
73
  blockOperations: {
74
74
  external: TextValidationRule;
75
+ validateNumericValues: {
76
+ cutoffEpoch: bigint;
77
+ };
75
78
  };
76
79
  idempotentKey: {
77
80
  maxByteLength: number;
@@ -1 +1 @@
1
- window.hierarchyData = "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"
1
+ window.hierarchyData = "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"