@keetanetwork/keetanet-client 0.12.2 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/api/index.d.ts +23 -2
  2. package/api/node.d.ts +7 -1
  3. package/api/p2p.d.ts +13 -0
  4. package/api/vote.d.ts +10 -0
  5. package/client/builder.d.ts +13 -6
  6. package/client/client_common_tests.d.ts +18 -0
  7. package/client/index-browser.d.ts +42 -14
  8. package/client/index-browser.js +2899 -1382
  9. package/client/index.d.ts +42 -14
  10. package/client/index.js +2138 -655
  11. package/config/index.d.ts +2 -0
  12. package/docs/assets/hierarchy.js +1 -1
  13. package/docs/assets/search.js +1 -1
  14. package/docs/classes/KeetaNetSDK.Client.html +14 -10
  15. package/docs/classes/KeetaNetSDK.Referenced.BaseSet.html +2 -2
  16. package/docs/classes/KeetaNetSDK.Referenced.BaseVoteBuilder.html +10 -0
  17. package/docs/classes/KeetaNetSDK.Referenced.Block.html +9 -5
  18. package/docs/classes/KeetaNetSDK.Referenced.BlockBuilder.html +3 -2
  19. package/docs/classes/KeetaNetSDK.Referenced.BlockHash.html +1 -1
  20. package/docs/classes/KeetaNetSDK.Referenced.BlockOperation.html +1 -1
  21. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationCREATE_IDENTIFIER.html +4 -4
  22. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationMANAGE_CERTIFICATE.html +1 -1
  23. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationMODIFY_PERMISSIONS.html +1 -1
  24. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationRECEIVE.html +1 -1
  25. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationSEND.html +1 -1
  26. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationSET_INFO.html +1 -1
  27. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationSET_REP.html +1 -1
  28. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationTOKEN_ADMIN_MODIFY_BALANCE.html +1 -1
  29. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationTOKEN_ADMIN_SUPPLY.html +1 -1
  30. package/docs/classes/KeetaNetSDK.Referenced.Certificate.html +6 -2
  31. package/docs/classes/KeetaNetSDK.Referenced.CertificateHash.html +1 -1
  32. package/docs/classes/KeetaNetSDK.Referenced.ECDSAKeyPair.html +1 -1
  33. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1KeyPair.html +1 -1
  34. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1PrivateKey.html +1 -1
  35. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1PublicKey.html +1 -1
  36. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1Signature.html +1 -1
  37. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1KeyPair.html +1 -1
  38. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1PrivateKey.html +1 -1
  39. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1PublicKey.html +1 -1
  40. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1Signature.html +1 -1
  41. package/docs/classes/KeetaNetSDK.Referenced.ED25519KeyPair.html +1 -1
  42. package/docs/classes/KeetaNetSDK.Referenced.ED25519PrivateKey.html +1 -1
  43. package/docs/classes/KeetaNetSDK.Referenced.ED25519PublicKey.html +1 -1
  44. package/docs/classes/KeetaNetSDK.Referenced.ED25519Signature.html +1 -1
  45. package/docs/classes/KeetaNetSDK.Referenced.ExternalKeyPair.html +1 -1
  46. package/docs/classes/KeetaNetSDK.Referenced.ExternalSet.html +1 -1
  47. package/docs/classes/KeetaNetSDK.Referenced.IdentifierKey.html +1 -1
  48. package/docs/classes/KeetaNetSDK.Referenced.IdentifierKeyPair.html +1 -1
  49. package/docs/classes/KeetaNetSDK.Referenced.KeetaNetError.html +1 -1
  50. package/docs/classes/KeetaNetSDK.Referenced.KeyInterface.html +1 -1
  51. package/docs/classes/KeetaNetSDK.Referenced.KeyStorage.html +1 -1
  52. package/docs/classes/KeetaNetSDK.Referenced.Ledger.html +5 -2
  53. package/docs/classes/KeetaNetSDK.Referenced.LedgerAtomicInterface.html +3 -1
  54. package/docs/classes/KeetaNetSDK.Referenced.LedgerStorageTransactionBase.html +8 -0
  55. package/docs/classes/KeetaNetSDK.Referenced.P2PSwitch.html +6 -2
  56. package/docs/classes/KeetaNetSDK.Referenced.PermissionSetHolder.html +1 -1
  57. package/docs/classes/KeetaNetSDK.Referenced.PossiblyExpiredVote.html +31 -27
  58. package/docs/classes/KeetaNetSDK.Referenced.SignatureStorage.html +1 -1
  59. package/docs/classes/KeetaNetSDK.Referenced.Stats.html +10 -4
  60. package/docs/classes/KeetaNetSDK.Referenced.StatsPending.html +10 -0
  61. package/docs/classes/KeetaNetSDK.Referenced.UserClientBuilder.html +4 -3
  62. package/docs/classes/KeetaNetSDK.Referenced.Vote.html +7 -3
  63. package/docs/classes/KeetaNetSDK.Referenced.VoteBlockBundle.html +3 -3
  64. package/docs/classes/KeetaNetSDK.Referenced.VoteBlockHash.html +2 -2
  65. package/docs/classes/KeetaNetSDK.Referenced.VoteBuilder.html +10 -8
  66. package/docs/classes/KeetaNetSDK.Referenced.VoteHash.html +2 -2
  67. package/docs/classes/KeetaNetSDK.Referenced.VoteLikeBase.html +32 -0
  68. package/docs/classes/KeetaNetSDK.Referenced.VoteQuote.html +34 -0
  69. package/docs/classes/KeetaNetSDK.Referenced.VoteQuoteBuilder.html +11 -0
  70. package/docs/classes/KeetaNetSDK.Referenced.VoteStaple.html +3 -3
  71. package/docs/classes/KeetaNetSDK.Referenced.VoteStapleHash.html +2 -2
  72. package/docs/classes/KeetaNetSDK.Referenced.src_lib_utils_asn1.ValidateASN1.html +2 -2
  73. package/docs/classes/KeetaNetSDK.Referenced.src_lib_utils_buffer.BufferStorage.html +1 -1
  74. package/docs/classes/KeetaNetSDK.UserClient.html +7 -2
  75. package/docs/enums/KeetaNetSDK.Referenced.BaseFlag.html +2 -1
  76. package/docs/enums/KeetaNetSDK.Referenced.BasePermissionGroup.html +3 -1
  77. package/docs/enums/KeetaNetSDK.Referenced.BlockPurpose.html +3 -0
  78. package/docs/functions/KeetaNetSDK.Referenced.src_lib_utils_helper.bufferToBigInt.html +1 -0
  79. package/docs/hierarchy.html +1 -1
  80. package/docs/interfaces/KeetaNetSDK.Referenced.ACLEntry.html +1 -1
  81. package/docs/interfaces/KeetaNetSDK.Referenced.ACLUpdate.html +1 -1
  82. package/docs/interfaces/KeetaNetSDK.Referenced.ASN1ExplicitContextTag.html +1 -1
  83. package/docs/interfaces/KeetaNetSDK.Referenced.ASN1ImplicitContextTag.html +1 -1
  84. package/docs/interfaces/KeetaNetSDK.Referenced.ASN1Object.html +1 -1
  85. package/docs/interfaces/KeetaNetSDK.Referenced.AccountInfo.html +4 -2
  86. package/docs/interfaces/KeetaNetSDK.Referenced.BaseExternalKeyPairFunctions.html +1 -1
  87. package/docs/interfaces/KeetaNetSDK.Referenced.BaseGenerationConfig.html +1 -1
  88. package/docs/interfaces/KeetaNetSDK.Referenced.BaseIdentifierCreateArguments.html +3 -0
  89. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperation.html +1 -1
  90. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationCREATE_IDENTIFIER.html +3 -3
  91. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationMANAGE_CERTIFICATE.html +1 -1
  92. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationMANAGE_CERTIFICATESerializable.html +1 -1
  93. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationMODIFY_PERMISSIONS.html +1 -1
  94. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationRECEIVE.html +1 -1
  95. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationSEND.html +1 -1
  96. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationSET_INFO.html +1 -1
  97. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationSET_REP.html +1 -1
  98. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationTOKEN_ADMIN_MODIFY_BALANCE.html +1 -1
  99. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSONOperationTOKEN_ADMIN_SUPPLY.html +1 -1
  100. package/docs/interfaces/{KeetaNetSDK.Referenced.BlockCanonical.html → KeetaNetSDK.Referenced.BlockV1Canonical.html} +1 -1
  101. package/docs/interfaces/KeetaNetSDK.Referenced.BlockV1JSON.html +12 -0
  102. package/docs/interfaces/KeetaNetSDK.Referenced.BlockV1UnsignedCanonical.html +11 -0
  103. package/docs/interfaces/KeetaNetSDK.Referenced.BlockV2Canonical.html +11 -0
  104. package/docs/interfaces/KeetaNetSDK.Referenced.BlockV2JSON.html +12 -0
  105. package/docs/interfaces/KeetaNetSDK.Referenced.BlockV2UnsignedCanonical.html +11 -0
  106. package/docs/interfaces/KeetaNetSDK.Referenced.BuilderBlockOptions.html +3 -0
  107. package/docs/interfaces/KeetaNetSDK.Referenced.ComputedBlocksEffectFields.html +3 -2
  108. package/docs/interfaces/KeetaNetSDK.Referenced.Constructor.html +1 -1
  109. package/docs/interfaces/KeetaNetSDK.Referenced.CreateIdentifierRequest.html +4 -0
  110. package/docs/interfaces/KeetaNetSDK.Referenced.DisposableTimingHandle.html +1 -1
  111. package/docs/interfaces/KeetaNetSDK.Referenced.ExternalKeyPairFunctionsNoEncryption.html +1 -1
  112. package/docs/interfaces/KeetaNetSDK.Referenced.ExternalKeyPairFunctionsSupportsEncryption.html +1 -1
  113. package/docs/interfaces/KeetaNetSDK.Referenced.InitialConfigSupply.html +1 -1
  114. package/docs/interfaces/KeetaNetSDK.Referenced.InstanceSet.html +1 -1
  115. package/docs/interfaces/KeetaNetSDK.Referenced.KVGenericOptionsType.html +1 -1
  116. package/docs/interfaces/KeetaNetSDK.Referenced.KVSetOptionsType.html +1 -1
  117. package/docs/interfaces/KeetaNetSDK.Referenced.LedgerConfig.html +5 -3
  118. package/docs/interfaces/KeetaNetSDK.Referenced.LedgerStorageAPI.html +4 -4
  119. package/docs/interfaces/KeetaNetSDK.Referenced.LedgerStorageTransactionBaseOptions.html +6 -0
  120. package/docs/interfaces/KeetaNetSDK.Referenced.ModifyTokenBalanceEntry.html +1 -1
  121. package/docs/interfaces/KeetaNetSDK.Referenced.MultiSigIdentifierCreateArguments.html +5 -0
  122. package/docs/interfaces/KeetaNetSDK.Referenced.MultisigConfig.html +3 -0
  123. package/docs/interfaces/KeetaNetSDK.Referenced.NumericValueEntry.html +1 -1
  124. package/docs/interfaces/KeetaNetSDK.Referenced.P2PConfig.html +4 -2
  125. package/docs/interfaces/KeetaNetSDK.Referenced.P2PPeerBase.html +1 -1
  126. package/docs/interfaces/KeetaNetSDK.Referenced.P2PPeerListener.html +1 -1
  127. package/docs/interfaces/KeetaNetSDK.Referenced.P2PPeerRepBase.html +4 -2
  128. package/docs/interfaces/KeetaNetSDK.Referenced.PrincipalACLWithInfoParsed.html +1 -0
  129. package/docs/interfaces/KeetaNetSDK.Referenced.PublicKeyStorage.html +1 -1
  130. package/docs/interfaces/KeetaNetSDK.Referenced.PublishOptions.html +5 -0
  131. package/docs/interfaces/KeetaNetSDK.Referenced.RequestTokenReceiveEntry.html +1 -1
  132. package/docs/interfaces/KeetaNetSDK.Referenced.TokenNumericEntry.html +1 -1
  133. package/docs/interfaces/KeetaNetSDK.Referenced.UserClientConfig.html +5 -3
  134. package/docs/interfaces/KeetaNetSDK.Referenced.UserClientOptions.html +4 -2
  135. package/docs/interfaces/KeetaNetSDK.Referenced.VoteJSON.html +3 -2
  136. package/docs/interfaces/KeetaNetSDK.Referenced.VoteStapleJSON.html +2 -2
  137. package/docs/interfaces/KeetaNetSDK.Referenced.WithIsInstance.html +1 -1
  138. package/docs/interfaces/KeetaNetSDK.Referenced.src_config.ValidationConfig.html +2 -2
  139. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1BitString.html +1 -1
  140. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1Date.html +1 -1
  141. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1OID.html +1 -1
  142. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1Set.html +1 -1
  143. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1String.html +1 -1
  144. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_helper.InstanceSetConstructor.html +2 -2
  145. package/docs/modules/KeetaNetSDK.Referenced.html +1 -1
  146. package/docs/modules/KeetaNetSDK.Referenced.src_lib_utils_asn1.html +1 -1
  147. package/docs/modules/KeetaNetSDK.Referenced.src_lib_utils_helper.html +1 -1
  148. package/docs/types/KeetaNetSDK.Referenced.BlockASN1SchemaWithoutSignature.html +1 -0
  149. package/docs/types/KeetaNetSDK.Referenced.BlockJSON.html +1 -0
  150. package/docs/types/KeetaNetSDK.Referenced.BlockJSONIncomplete.html +1 -1
  151. package/docs/types/KeetaNetSDK.Referenced.BlockOperationASN1SchemaType.html +1 -0
  152. package/docs/types/KeetaNetSDK.Referenced.BlockOperationTypes.html +1 -0
  153. package/docs/types/KeetaNetSDK.Referenced.BlockSignature.html +2 -0
  154. package/docs/types/KeetaNetSDK.Referenced.BlockSignatureField.html +1 -0
  155. package/docs/types/KeetaNetSDK.Referenced.BlockSignerField.html +1 -0
  156. package/docs/types/KeetaNetSDK.Referenced.BlockSignerFieldJSON.html +1 -0
  157. package/docs/types/KeetaNetSDK.Referenced.BlockV1ASN1WithoutSignature.html +1 -0
  158. package/docs/types/KeetaNetSDK.Referenced.BlockV2ASN1WithoutSignature.html +1 -0
  159. package/docs/types/KeetaNetSDK.Referenced.CertificateBuilderParams.html +8 -3
  160. package/docs/types/KeetaNetSDK.Referenced.ComputedEffectOfBlocks.html +2 -2
  161. package/docs/types/KeetaNetSDK.Referenced.GetAccountStateAPIResponseFormatted.html +1 -0
  162. package/docs/types/KeetaNetSDK.Referenced.HashNames.html +1 -0
  163. package/docs/types/KeetaNetSDK.Referenced.MultisigAddress.html +1 -0
  164. package/docs/types/KeetaNetSDK.Referenced.MultisigSignerField.html +1 -0
  165. package/docs/types/KeetaNetSDK.Referenced.MultisigSignerFieldJSON.html +1 -0
  166. package/docs/types/KeetaNetSDK.Referenced.OmitLastArrayValue.html +1 -0
  167. package/docs/types/KeetaNetSDK.Referenced.P2PUpdateOptions.html +1 -0
  168. package/docs/types/KeetaNetSDK.Referenced.UserEditableAccountInfo.html +1 -0
  169. package/docs/types/KeetaNetSDK.Referenced.src_config.NetworkConfig.html +1 -1
  170. package/docs/types/KeetaNetSDK.Referenced.src_lib_utils_asn1.ValidateASN1.Schema.html +1 -1
  171. package/docs/types/KeetaNetSDK.Referenced.src_lib_utils_asn1.ValidateASN1.SchemaMap.html +1 -1
  172. package/docs/variables/KeetaNetSDK.Referenced.BlockErrorCodes-1.html +1 -1
  173. package/docs/variables/KeetaNetSDK.Referenced.BlockErrorCodes.html +1 -1
  174. package/docs/variables/KeetaNetSDK.Referenced.BlockOperationASN1Schema.html +2 -0
  175. package/docs/variables/KeetaNetSDK.Referenced.LedgerErrorCodes.html +1 -1
  176. package/docs/variables/KeetaNetSDK.Referenced.VoteErrorCodes.html +1 -1
  177. package/docs/variables/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1CheckUtilities.html +1 -0
  178. package/lib/block/index.d.ts +104 -36
  179. package/lib/block/operations.d.ts +31 -3
  180. package/lib/error/block.d.ts +1 -1
  181. package/lib/error/certificate.d.ts +1 -1
  182. package/lib/error/ledger.d.ts +1 -1
  183. package/lib/error/vote.d.ts +1 -1
  184. package/lib/ledger/common.d.ts +14 -1
  185. package/lib/ledger/db_dynamodb.d.ts +7 -11
  186. package/lib/ledger/db_postgres.d.ts +12 -4
  187. package/lib/ledger/db_spanner.d.ts +6 -13
  188. package/lib/ledger/db_spanner_helper.d.ts +29 -6
  189. package/lib/ledger/db_sqlite.d.ts +12 -4
  190. package/lib/ledger/effects.d.ts +10 -9
  191. package/lib/ledger/index.d.ts +28 -10
  192. package/lib/ledger/types.d.ts +10 -1
  193. package/lib/node/utils.d.ts +5 -0
  194. package/lib/p2p.d.ts +32 -0
  195. package/lib/permissions.d.ts +5 -2
  196. package/lib/stats.d.ts +22 -3
  197. package/lib/utils/asn1.d.ts +22 -5
  198. package/lib/utils/certificate.d.ts +38 -1
  199. package/lib/utils/helper.d.ts +2 -1
  200. package/lib/utils/static-types.d.ts +11 -0
  201. package/lib/vote.d.ts +55 -20
  202. package/package.json +1 -1
  203. package/version.d.ts +1 -1
  204. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSON.html +0 -11
  205. package/docs/interfaces/KeetaNetSDK.Referenced.BlockUnsignedCanonical.html +0 -11
  206. package/docs/interfaces/KeetaNetSDK.Referenced.LedgerStorageTransactionBase.html +0 -6
  207. package/docs/types/KeetaNetSDK.Referenced.CreateIdentifierRequest.html +0 -6
package/client/index.js CHANGED
@@ -57274,6 +57274,7 @@ exports.UserClientBuilder = exports.PendingAccount = void 0;
57274
57274
  const lib_1 = __importDefault(__webpack_require__(8568));
57275
57275
  const account_1 = __webpack_require__(9415);
57276
57276
  const block_1 = __webpack_require__(6158);
57277
+ const operations_1 = __webpack_require__(2778);
57277
57278
  const client_1 = __importDefault(__webpack_require__(3642));
57278
57279
  const permissions_1 = __webpack_require__(5860);
57279
57280
  const conversion_1 = __webpack_require__(2360);
@@ -57519,7 +57520,7 @@ class UserClientBuilder {
57519
57520
  });
57520
57521
  return (await _a.FromPendingJSON(__classPrivateFieldGet(this, _UserClientBuilder_defaultOptions, "f"), getPrivateKey, [this.pendingToJSON()]));
57521
57522
  }
57522
- async publish(client) {
57523
+ async publish(options, client) {
57523
57524
  if (client === undefined) {
57524
57525
  client = __classPrivateFieldGet(this, _UserClientBuilder_userClient, "f");
57525
57526
  }
@@ -57532,10 +57533,58 @@ class UserClientBuilder {
57532
57533
  }
57533
57534
  else {
57534
57535
  const blocks = await this.computeBlocks(client);
57535
- retval = await client.client.transmit(blocks.blocks);
57536
+ retval = await client.client.transmit(blocks.blocks, options);
57536
57537
  }
57537
57538
  return (retval);
57538
57539
  }
57540
+ async computeFeeBlock(staple, options = {}, renderOptions) {
57541
+ __classPrivateFieldGet(this, _UserClientBuilder_instances, "m", _UserClientBuilder_useOptions).call(this, options);
57542
+ if (renderOptions === undefined) {
57543
+ renderOptions = __classPrivateFieldGet(this, _UserClientBuilder_userClient, "f");
57544
+ }
57545
+ if (renderOptions === undefined) {
57546
+ throw (new client_1.default('CLIENT_BUILDER_USER_CLIENT_REQUIRED', 'UserClient is required to compute blocks'));
57547
+ }
57548
+ if (!('getPrevious' in renderOptions)) {
57549
+ renderOptions = __classPrivateFieldGet(this, _UserClientBuilder_instances, "m", _UserClientBuilder_getRenderOptionsFromClient).call(this, renderOptions);
57550
+ }
57551
+ const previousByKey = {};
57552
+ for (const existing of staple.blocks) {
57553
+ const previous = existing.previous.toString();
57554
+ const pubKey = existing.account.publicKeyString.get();
57555
+ if (!previousByKey[pubKey] || previousByKey[pubKey].toString() === previous) {
57556
+ previousByKey[pubKey] = existing.hash.toString();
57557
+ }
57558
+ }
57559
+ const { account, signer } = __classPrivateFieldGet(this, _UserClientBuilder_pendingOptions, "f");
57560
+ const accountPubKey = account.publicKeyString.get();
57561
+ let previous = previousByKey[accountPubKey];
57562
+ if (!previous) {
57563
+ previous = await renderOptions.getPrevious(account) ?? block_1.Block.NO_PREVIOUS;
57564
+ }
57565
+ const { baseToken } = lib_1.default.Account.generateBaseAddresses(renderOptions.network);
57566
+ const operations = [];
57567
+ for (const vote of staple.votes) {
57568
+ if (vote.fee !== undefined) {
57569
+ operations.push({
57570
+ type: operations_1.OperationType.SEND,
57571
+ amount: vote.fee.amount,
57572
+ to: vote.fee.payTo ?? vote.issuer,
57573
+ token: vote.fee.token ?? baseToken
57574
+ });
57575
+ }
57576
+ }
57577
+ const block = await new block_1.Block.Builder({
57578
+ version: 2,
57579
+ purpose: block_1.BlockPurpose.FEE,
57580
+ account: account,
57581
+ signer: signer,
57582
+ network: renderOptions.network,
57583
+ previous: previous,
57584
+ operations: operations
57585
+ }).seal();
57586
+ return (block);
57587
+ }
57539
57588
  async computeBlocks(renderOptions) {
57540
57589
  if (this.rendered) {
57541
57590
  return ({ blocks: this.blocks });
@@ -57973,7 +58022,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
57973
58022
  var __importDefault = (this && this.__importDefault) || function (mod) {
57974
58023
  return (mod && mod.__esModule) ? mod : { "default": mod };
57975
58024
  };
57976
- var _Client_instances, _Client_reps, _Client_weightOrderedReps, _Client_intervals, _Client_updateRepsPromise, _Client_apiRaw, _Client_api, _Client_requestVotes, _Client_getVotes, _Client_getBuilderRenderOptions, _Client_urlSeparatedAccounts, _Client_formatAllBalances, _Client_parseResponsePermissions, _Client_formatAccountInfo, _Client_parseAccountInfo, _Client_parsePermissionEntries, _Client_mapCertificateWithBundleResult, _Client_parseRepInfo, _UserClient_instances, _UserClient_config, _UserClient_client, _UserClient_listeners, _UserClient_intervals, _UserClient_previousAccountChangeData, _UserClient_socketPromise, _UserClient_filteredWebSocket, _UserClient_changePromise, _UserClient_reconnectAttempts, _UserClient_RECONNECT_TIMEOUT, _UserClient_transientUserClients, _UserClient_getAccount, _UserClient_publishAidURL_get, _UserClient_publishWithPublishAid, _UserClient_reconnectWebSocket, _UserClient_setupFilteredWebSocket, _UserClient_emit, _UserClient_emitAccountInfoIfChanged;
58025
+ var _Client_instances, _Client_reps, _Client_weightOrderedReps, _Client_intervals, _Client_updateRepsPromise, _Client_apiRaw, _Client_api, _Client_requestVoteOrQuote, _Client_requestQuotes, _Client_requestVotes, _Client_getVotes, _Client_getBuilderRenderOptions, _Client_urlSeparatedAccounts, _Client_formatAllBalances, _Client_parseResponsePermissions, _Client_formatAccountInfo, _Client_parseAccountInfo, _Client_parsePermissionEntries, _Client_mapCertificateWithBundleResult, _Client_parseRepInfo, _UserClient_instances, _UserClient_config, _UserClient_client, _UserClient_listeners, _UserClient_intervals, _UserClient_previousAccountChangeData, _UserClient_socketPromise, _UserClient_filteredWebSocket, _UserClient_changePromise, _UserClient_reconnectAttempts, _UserClient_RECONNECT_TIMEOUT, _UserClient_transientUserClients, _UserClient_getAccount, _UserClient_publishAidURL_get, _UserClient_publishWithPublishAid, _UserClient_reconnectWebSocket, _UserClient_setupFilteredWebSocket, _UserClient_emit, _UserClient_emitAccountInfoIfChanged;
57977
58026
  Object.defineProperty(exports, "__esModule", ({ value: true }));
57978
58027
  exports.lib = exports.UserClient = exports.Client = void 0;
57979
58028
  exports.blockGenerator = blockGenerator;
@@ -58009,6 +58058,7 @@ const effects_1 = __webpack_require__(7346);
58009
58058
  const client_1 = __importDefault(__webpack_require__(3642));
58010
58059
  const certificate_1 = __webpack_require__(5661);
58011
58060
  const certificate_2 = __webpack_require__(5661);
58061
+ const vote_1 = __webpack_require__(1130);
58012
58062
  function isGetAccountStateAPIResponseFailure(object) {
58013
58063
  if (typeof object !== 'object' || object === null) {
58014
58064
  return (false);
@@ -58192,23 +58242,42 @@ class Client {
58192
58242
  * votes and permanent votes for the blocks and then publish them to
58193
58243
  * the network.
58194
58244
  *
58195
- * If `blocks` is a {@link UserClientBuilder} then the blocks will be
58196
- * computed and then transmitted. If `blocks` is an array of blocks
58197
- * then they will be transmitted as-is.
58245
+ * The `blocks` builder will be computed using {@link computeBuilderBlocks} and then transmitted.
58198
58246
  *
58199
- * @param blocks The blocks or UserClientBuilder to transmit
58247
+ * @param builder The UserClientBuilder to compute and transmit transmit
58200
58248
  * @param network The network to use for the builder (if using a builder)
58201
58249
  * @return The result of the publish operation
58202
58250
  */
58203
- async transmit(blocks, network) {
58204
- if (builder_1.UserClientBuilder.isInstance(blocks)) {
58205
- if (network === undefined) {
58206
- throw (new Error('Network must be defined when using transmit() with a builder'));
58251
+ async transmitBuilder(builder, network, options) {
58252
+ const blocks = await this.computeBuilderBlocks(network, builder);
58253
+ return (await this.transmit(blocks.blocks, options));
58254
+ }
58255
+ /**
58256
+ * Transmit a set of blocks to the network. This will request short
58257
+ * votes and permanent votes for the blocks and then publish them to
58258
+ * the network. Optionally it will generate a fee block from a user
58259
+ * provided function if fees are required.
58260
+ *
58261
+ * @param blocks The blocks to transmit
58262
+ * @param options User provided options {@link PublishOptions }
58263
+ * @return The result of the publish operation
58264
+ */
58265
+ async transmit(blocks, options) {
58266
+ const tempVotes = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_requestVotes).call(this, blocks, undefined, undefined, options?.quotes);
58267
+ let requiresFee = false;
58268
+ for (const vote of tempVotes) {
58269
+ if (vote.fee !== undefined) {
58270
+ requiresFee = true;
58271
+ }
58272
+ }
58273
+ if (requiresFee) {
58274
+ if (options?.generateFeeBlock === undefined) {
58275
+ throw (new Error('Votes require fees but generateFeeBlock was not defined'));
58207
58276
  }
58208
- await this.computeBuilderBlocks(network, blocks);
58209
- blocks = blocks.blocks;
58277
+ const staple = vote_1.VoteStaple.fromVotesAndBlocks(tempVotes, blocks);
58278
+ const feeBlock = await options.generateFeeBlock(staple);
58279
+ blocks.push(feeBlock);
58210
58280
  }
58211
- const tempVotes = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_requestVotes).call(this, blocks);
58212
58281
  const permVotes = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_requestVotes).call(this, blocks, tempVotes);
58213
58282
  const votesAndBlocks = lib_1.default.Vote.Staple.fromVotesAndBlocks(permVotes, blocks);
58214
58283
  return (await this.transmitStaple(votesAndBlocks));
@@ -58658,7 +58727,7 @@ class Client {
58658
58727
  * that it will always return at least 1 vote staple if there are any
58659
58728
  * vote staples available.
58660
58729
  *
58661
- * @param account The account to get the history for
58730
+ * @param account The account to get the history for -- if null then the history for all accounts will be returned
58662
58731
  * @param options The options to use for the request
58663
58732
  * @param options.startBlocksHash The block hash to start from -- this is used to paginate the request
58664
58733
  * @param options.depth The maximum number of vote staples to return -- this is used to limit the number of vote staples returned
@@ -58682,20 +58751,19 @@ class Client {
58682
58751
  const query = {
58683
58752
  limit: String(limit)
58684
58753
  };
58754
+ if (startVoteStapleID !== undefined) {
58755
+ query.start = startVoteStapleID;
58756
+ }
58685
58757
  let history;
58686
- if (startVoteStapleID === undefined) {
58687
- history = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_api).call(this, 'ANY', 'GET /node/ledger/account/:account/history', {
58688
- args: {
58689
- account
58690
- },
58758
+ if (account === null) {
58759
+ history = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_api).call(this, 'ANY', 'GET /node/ledger/history', {
58691
58760
  queryParams: query
58692
58761
  });
58693
58762
  }
58694
58763
  else {
58695
- history = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_api).call(this, 'ANY', 'GET /node/ledger/account/:account/history/start/:block', {
58764
+ history = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_api).call(this, 'ANY', 'GET /node/ledger/account/:account/history', {
58696
58765
  args: {
58697
- account: account,
58698
- block: startVoteStapleID
58766
+ account
58699
58767
  },
58700
58768
  queryParams: query
58701
58769
  });
@@ -58705,7 +58773,7 @@ class Client {
58705
58773
  }
58706
58774
  for (const historyEntry of history.history) {
58707
58775
  const voteStapleInfo = historyEntry.voteStaple;
58708
- if (!voteStapleInfo['$binary']) {
58776
+ if (voteStapleInfo['$binary'] === undefined) {
58709
58777
  throw (new Error('Vote Staple is missing binary data'));
58710
58778
  }
58711
58779
  const voteStapleBinary = Buffer.from(voteStapleInfo['$binary'], 'base64');
@@ -59117,6 +59185,9 @@ class Client {
59117
59185
  }
59118
59186
  return (voteStaple);
59119
59187
  }
59188
+ async getVoteQuotes(blocks) {
59189
+ return (await __classPrivateFieldGet(this, _Client_instances, "m", _Client_requestQuotes).call(this, blocks));
59190
+ }
59120
59191
  /** Work in progress */
59121
59192
  async getLedgerChecksum(rep = 'ANY') {
59122
59193
  const checksumResponse = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_api).call(this, rep, 'GET /node/ledger/checksum');
@@ -59285,54 +59356,27 @@ async function _Client_apiRaw(rep, api, method, options = {}) {
59285
59356
  }
59286
59357
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
59287
59358
  return await __classPrivateFieldGet(this, _Client_instances, "m", _Client_apiRaw).call(this, rep, path, method, options);
59288
- }, _Client_requestVotes = async function _Client_requestVotes(blocks, otherVotes, reps = __classPrivateFieldGet(this, _Client_reps, "f")) {
59289
- // Wait for reps promise to ensure we have the right list of reps and their weight
59290
- await __classPrivateFieldGet(this, _Client_updateRepsPromise, "f");
59291
- const request = {
59292
- blocks: blocks.map(function (block) {
59293
- return (Buffer.from(block.toBytes()).toString('base64'));
59294
- })
59295
- };
59296
- if (otherVotes !== undefined) {
59297
- if (otherVotes.length === 0) {
59298
- throw (new Error('requestVotes() otherVotes must not have a length of 0'));
59299
- }
59300
- request.votes = otherVotes.map(function (vote) {
59301
- return (Buffer.from(vote.toBytes()).toString('base64'));
59302
- });
59303
- if (reps === __classPrivateFieldGet(this, _Client_reps, "f")) {
59304
- reps = otherVotes.map((vote) => {
59305
- const voteRepPubKey = vote.issuer.publicKeyString.get();
59306
- return (__classPrivateFieldGet(this, _Client_reps, "f").find(function (rep) {
59307
- const checkRepPubKey = rep.key.publicKeyString.get();
59308
- if (checkRepPubKey === voteRepPubKey) {
59309
- return (true);
59310
- }
59311
- return (false);
59312
- }));
59313
- }).filter(function (rep) {
59314
- if (rep === undefined) {
59315
- return (false);
59316
- }
59317
- return (true);
59318
- });
59319
- }
59320
- }
59359
+ }, _Client_requestVoteOrQuote = async function _Client_requestVoteOrQuote(api, request, reps = __classPrivateFieldGet(this, _Client_reps, "f"), quotes = []) {
59321
59360
  let recentVotingError;
59322
59361
  let recentVotingErrorWeight;
59362
+ const quoteMap = new Map();
59363
+ for (const quote of quotes) {
59364
+ quoteMap.set(quote.issuer.publicKeyAndTypeString, quote);
59365
+ }
59323
59366
  const votePromises = [];
59324
59367
  for (const rep of reps) {
59368
+ const quote = quoteMap.get(rep.key.publicKeyAndTypeString);
59369
+ if (quote !== undefined) {
59370
+ request.quote = Buffer.from(quote.toBytes()).toString('base64');
59371
+ }
59325
59372
  votePromises.push((async () => {
59326
59373
  try {
59327
- const apiResult = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_api).call(this, rep, 'POST /vote/_root', {
59374
+ const apiResult = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_api).call(this, rep, api, {
59328
59375
  body: request
59329
59376
  });
59330
59377
  return (apiResult);
59331
59378
  }
59332
59379
  catch (voteError) {
59333
- if (otherVotes !== undefined) {
59334
- throw (voteError);
59335
- }
59336
59380
  const weight = rep.weight ?? 0n;
59337
59381
  if (recentVotingErrorWeight === undefined || weight > recentVotingErrorWeight) {
59338
59382
  recentVotingError = voteError;
@@ -59354,9 +59398,21 @@ async function _Client_apiRaw(rep, api, method, options = {}) {
59354
59398
  if (voteObjectWrapper === undefined) {
59355
59399
  continue;
59356
59400
  }
59357
- const voteObject = voteObjectWrapper['vote'];
59358
- const voteBin = Buffer.from(voteObject['$binary'], 'base64');
59359
- retval.push(new lib_1.default.Vote(voteBin));
59401
+ if ('vote' in voteObjectWrapper) {
59402
+ const voteObject = voteObjectWrapper['vote'];
59403
+ const voteBin = Buffer.from(voteObject['$binary'], 'base64');
59404
+ const vote = new lib_1.default.Vote(voteBin);
59405
+ retval.push(vote);
59406
+ }
59407
+ else if ('quote' in voteObjectWrapper) {
59408
+ const voteObject = voteObjectWrapper['quote'];
59409
+ const quoteBin = Buffer.from(voteObject['$binary'], 'base64');
59410
+ const quote = new lib_1.default.Vote.Quote(quoteBin);
59411
+ retval.push(quote);
59412
+ }
59413
+ else {
59414
+ throw (new Error('Vote or Quote not in response'));
59415
+ }
59360
59416
  }
59361
59417
  if (retval.length === 0 && recentVotingError !== undefined) {
59362
59418
  if (recentVotingError !== undefined) {
@@ -59378,6 +59434,51 @@ async function _Client_apiRaw(rep, api, method, options = {}) {
59378
59434
  }
59379
59435
  }
59380
59436
  return (retval);
59437
+ }, _Client_requestQuotes = async function _Client_requestQuotes(blocks, reps = __classPrivateFieldGet(this, _Client_reps, "f")) {
59438
+ // Wait for reps promise to ensure we have the right list of reps and their weight
59439
+ await __classPrivateFieldGet(this, _Client_updateRepsPromise, "f");
59440
+ const request = {
59441
+ blocks: blocks.map(function (block) {
59442
+ return (Buffer.from(block.toBytes()).toString('base64'));
59443
+ })
59444
+ };
59445
+ const quotes = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_requestVoteOrQuote).call(this, 'POST /vote/quote', request, reps);
59446
+ return (quotes);
59447
+ }, _Client_requestVotes = async function _Client_requestVotes(blocks, otherVotes, reps = __classPrivateFieldGet(this, _Client_reps, "f"), quotes) {
59448
+ // Wait for reps promise to ensure we have the right list of reps and their weight
59449
+ await __classPrivateFieldGet(this, _Client_updateRepsPromise, "f");
59450
+ const request = {
59451
+ blocks: blocks.map(function (block) {
59452
+ return (Buffer.from(block.toBytes()).toString('base64'));
59453
+ })
59454
+ };
59455
+ if (otherVotes !== undefined) {
59456
+ if (otherVotes.length === 0) {
59457
+ throw (new Error('requestVotes() otherVotes must not have a length of 0'));
59458
+ }
59459
+ request.votes = otherVotes.map(function (vote) {
59460
+ return (Buffer.from(vote.toBytes()).toString('base64'));
59461
+ });
59462
+ if (reps === __classPrivateFieldGet(this, _Client_reps, "f")) {
59463
+ reps = otherVotes.map((vote) => {
59464
+ const voteRepPubKey = vote.issuer.publicKeyString.get();
59465
+ return (__classPrivateFieldGet(this, _Client_reps, "f").find(function (rep) {
59466
+ const checkRepPubKey = rep.key.publicKeyString.get();
59467
+ if (checkRepPubKey === voteRepPubKey) {
59468
+ return (true);
59469
+ }
59470
+ return (false);
59471
+ }));
59472
+ }).filter(function (rep) {
59473
+ if (rep === undefined) {
59474
+ return (false);
59475
+ }
59476
+ return (true);
59477
+ });
59478
+ }
59479
+ }
59480
+ const votes = await __classPrivateFieldGet(this, _Client_instances, "m", _Client_requestVoteOrQuote).call(this, 'POST /vote/_root', request, reps, quotes);
59481
+ return (votes);
59381
59482
  }, _Client_getVotes = async function _Client_getVotes(blockhash, side = 'main', rep = 'ANY') {
59382
59483
  const query = {
59383
59484
  side: (0, common_1.assertLedgerStorage)(side)
@@ -59742,7 +59843,14 @@ class UserClient {
59742
59843
  const { networkAddress, baseToken } = lib_1.default.Account.generateBaseAddresses(config.network);
59743
59844
  this.networkAddress = networkAddress;
59744
59845
  this.baseToken = baseToken;
59745
- __classPrivateFieldSet(this, _UserClient_config, config, "f");
59846
+ __classPrivateFieldSet(this, _UserClient_config, {
59847
+ generateFeeBlock: async (staple) => {
59848
+ const builder = this.initBuilder();
59849
+ const block = await builder.computeFeeBlock(staple);
59850
+ return (block);
59851
+ },
59852
+ ...config
59853
+ }, "f");
59746
59854
  // For event listeners/polling
59747
59855
  __classPrivateFieldSet(this, _UserClient_listeners, {}, "f");
59748
59856
  __classPrivateFieldSet(this, _UserClient_intervals, {}, "f");
@@ -59864,11 +59972,12 @@ class UserClient {
59864
59972
  * instead of this one.
59865
59973
  *
59866
59974
  * @param builder The builder to publish
59975
+ * @param options options for publishing {@link PublishOptions }
59867
59976
  * @return The vote staple that was generated and whether it was able to be published
59868
59977
  */
59869
- async publishBuilder(builder) {
59978
+ async publishBuilder(builder, options = { generateFeeBlock: __classPrivateFieldGet(this, _UserClient_config, "f").generateFeeBlock }) {
59870
59979
  if (!__classPrivateFieldGet(this, _UserClient_config, "f").usePublishAid) {
59871
- return (await __classPrivateFieldGet(this, _UserClient_client, "f").transmit(builder, this.network));
59980
+ return (await __classPrivateFieldGet(this, _UserClient_client, "f").transmitBuilder(builder, this.network, options));
59872
59981
  }
59873
59982
  await __classPrivateFieldGet(this, _UserClient_client, "f").computeBuilderBlocks(this.network, builder);
59874
59983
  const retval = await __classPrivateFieldGet(this, _UserClient_instances, "m", _UserClient_publishWithPublishAid).call(this, builder.blocks);
@@ -59941,6 +60050,14 @@ class UserClient {
59941
60050
  }
59942
60051
  throw (new Error('Unreachable code reached in UserClient.send'));
59943
60052
  }
60053
+ /**
60054
+ * Gets a quote for the cost for a given set of blocks from each representative
60055
+ * @param blocks
60056
+ * @returns A list of quotes from representatives the client knows about
60057
+ */
60058
+ async getQuotes(blocks) {
60059
+ return (await __classPrivateFieldGet(this, _UserClient_client, "f").getVoteQuotes(blocks));
60060
+ }
59944
60061
  /**
59945
60062
  * Generate a new identifier for the given type and publish the blocks
59946
60063
  *
@@ -60543,7 +60660,9 @@ exports.baseValidationConfig = {
60543
60660
  },
60544
60661
  supply: {
60545
60662
  maxValue: (10n ** 200n) - 1n
60546
- }
60663
+ },
60664
+ blockSignerCount: { maxValue: 16n },
60665
+ blockSignerDepth: { maxValue: 3n }
60547
60666
  },
60548
60667
  permissions: {
60549
60668
  maxExternalOffset: 32
@@ -62308,25 +62427,25 @@ var __importStar = (this && this.__importStar) || function (mod) {
62308
62427
  __setModuleDefault(result, mod);
62309
62428
  return result;
62310
62429
  };
62430
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
62431
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
62432
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
62433
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
62434
+ };
62311
62435
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
62312
62436
  if (kind === "m") throw new TypeError("Private method is not writable");
62313
62437
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
62314
62438
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
62315
62439
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
62316
62440
  };
62317
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
62318
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
62319
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
62320
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
62321
- };
62322
62441
  var __importDefault = (this && this.__importDefault) || function (mod) {
62323
62442
  return (mod && mod.__esModule) ? mod : { "default": mod };
62324
62443
  };
62325
- var _Block_instances, _Block_valueBytes, _Block_valueHash, _Block_validateOperations, _Block_validateSignature, _BlockBuilder_block;
62444
+ var _Block_instances, _a, _Block_valueBytes, _Block_valueHash, _Block_getSortedRequiredSigners, _Block_validateOperationsPurpose, _Block_validateSignerField, _Block_validateSignatures, _BlockBuilder_block;
62326
62445
  Object.defineProperty(exports, "__esModule", ({ value: true }));
62327
- exports.BlockBuilder = exports.Block = exports.BlockHash = exports.AdjustMethod = void 0;
62328
- exports.assertAdjustMethod = assertAdjustMethod;
62329
- const account_1 = __importDefault(__webpack_require__(9415));
62446
+ exports.BlockBuilder = exports.Block = exports.BlockHash = exports.AdjustMethod = exports.BlockPurpose = void 0;
62447
+ exports.toAdjustMethod = toAdjustMethod;
62448
+ const account_1 = __importStar(__webpack_require__(9415));
62330
62449
  const buffer_1 = __webpack_require__(3310);
62331
62450
  const hash_1 = __webpack_require__(7908);
62332
62451
  const ASN1 = __importStar(__webpack_require__(6045));
@@ -62334,17 +62453,42 @@ const helper_1 = __webpack_require__(3208);
62334
62453
  const util_1 = __webpack_require__(9023);
62335
62454
  const Operations = __importStar(__webpack_require__(2778));
62336
62455
  const block_1 = __importDefault(__webpack_require__(7412));
62456
+ const common_1 = __webpack_require__(5663);
62337
62457
  const NO_PREVIOUS = '9bd05fa2-8e59-42a2-8153-26d8e8c10143:NO_PREVIOUS';
62458
+ var BlockPurpose;
62459
+ (function (BlockPurpose) {
62460
+ BlockPurpose[BlockPurpose["GENERIC"] = 0] = "GENERIC";
62461
+ BlockPurpose[BlockPurpose["FEE"] = 1] = "FEE";
62462
+ })(BlockPurpose || (exports.BlockPurpose = BlockPurpose = {}));
62463
+ function toBlockPurpose(value) {
62464
+ if (typeof value === 'bigint') {
62465
+ value = Number(value);
62466
+ }
62467
+ if (typeof value !== 'number') {
62468
+ throw (new Error(`Invalid BlockPurpose supplied: got ${value} -- ${typeof value}`));
62469
+ }
62470
+ // We add this type assertion to make sure the switch is exhaustive
62471
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62472
+ switch (value) {
62473
+ case BlockPurpose.GENERIC:
62474
+ case BlockPurpose.FEE:
62475
+ return (value);
62476
+ }
62477
+ throw (new Error(`Invalid BlockPurpose supplied: got ${value} -- ${typeof value}`));
62478
+ }
62338
62479
  var AdjustMethod;
62339
62480
  (function (AdjustMethod) {
62340
62481
  AdjustMethod[AdjustMethod["ADD"] = 0] = "ADD";
62341
62482
  AdjustMethod[AdjustMethod["SUBTRACT"] = 1] = "SUBTRACT";
62342
62483
  AdjustMethod[AdjustMethod["SET"] = 2] = "SET";
62343
62484
  })(AdjustMethod || (exports.AdjustMethod = AdjustMethod = {}));
62344
- function assertAdjustMethod(value, bigintOkay) {
62345
- if (bigintOkay && typeof value === 'bigint') {
62485
+ function toAdjustMethod(value) {
62486
+ if (typeof value === 'bigint') {
62346
62487
  value = Number(value);
62347
62488
  }
62489
+ if (typeof value !== 'number') {
62490
+ throw (new Error(`Invalid AdjustMethod supplied: got ${value} -- ${typeof value}`));
62491
+ }
62348
62492
  // We add this type assertion to make sure the switch is exhaustive
62349
62493
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62350
62494
  switch (value) {
@@ -62388,7 +62532,7 @@ BlockHash.Set = (0, helper_1.setGenerator)(BlockHash, function (value) {
62388
62532
  return (new BlockHash(Buffer.from(value, 'hex')));
62389
62533
  });
62390
62534
  /** @internal */
62391
- const BlockASN1Schema = [
62535
+ const BlockV1ASN1Schema = [
62392
62536
  0n,
62393
62537
  ASN1.BufferStorageASN1.Validate.IsInteger,
62394
62538
  { choice: [ASN1.BufferStorageASN1.Validate.IsInteger, ASN1.BufferStorageASN1.Validate.IsNull] },
@@ -62399,28 +62543,154 @@ const BlockASN1Schema = [
62399
62543
  { sequenceOf: { choice: Object.values(Operations.BlockOperationASN1Schema) } },
62400
62544
  ASN1.BufferStorageASN1.Validate.IsOctetString
62401
62545
  ];
62546
+ const multisigSignerInfoASN1Schema = [
62547
+ ASN1.BufferStorageASN1.Validate.IsOctetString,
62548
+ {
62549
+ sequenceOf: {
62550
+ choice: [
62551
+ // XXX:TODO We need to use a type assertion here because the ASN1 schema does not support recursive types
62552
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62553
+ (() => multisigSignerInfoASN1Schema),
62554
+ ASN1.BufferStorageASN1.Validate.IsOctetString
62555
+ ]
62556
+ }
62557
+ }
62558
+ ];
62559
+ function parseBlockSignerFieldContainer(input, state) {
62560
+ if (!state) {
62561
+ state = { depth: 0 };
62562
+ }
62563
+ else if (state.depth > 3) {
62564
+ throw (new block_1.default('BLOCK_INVALID_MULTISIG_SIGNER_DEPTH', 'Multisig signer depth exceeded maximum allowed depth'));
62565
+ }
62566
+ const multisigAccount = account_1.default.fromPublicKeyAndType(input[0]).assertKeyType(account_1.AccountKeyAlgorithm.MULTISIG);
62567
+ const signers = [];
62568
+ // XXX:TODO We need to use a type assertion here because the ASN1 schema does not support recursive types properly
62569
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62570
+ for (const signer of input[1]) {
62571
+ let parsedSigner;
62572
+ if (Buffer.isBuffer(signer)) {
62573
+ parsedSigner = account_1.default.fromPublicKeyAndType(signer).assertAccount();
62574
+ }
62575
+ else if (signer && Array.isArray(signer)) {
62576
+ if (signer.length !== 2) {
62577
+ throw (new Error('Multisig signer must have two items'));
62578
+ }
62579
+ if (!Buffer.isBuffer(signer[0])) {
62580
+ throw (new Error('Multisig signer first item must be a buffer'));
62581
+ }
62582
+ if (!Array.isArray(signer[1])) {
62583
+ throw (new Error('Multisig signer second item must be an array'));
62584
+ }
62585
+ // XXX:TODO We need to use a type assertion here because we are not asserting the type recursively
62586
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62587
+ const inner = parseBlockSignerFieldContainer(signer, { depth: state.depth + 1 });
62588
+ parsedSigner = inner.parsed;
62589
+ }
62590
+ else {
62591
+ throw (new Error('Multisig signer must be a buffer or an array'));
62592
+ }
62593
+ signers.push(parsedSigner);
62594
+ }
62595
+ return ({
62596
+ parsed: [multisigAccount, signers],
62597
+ depth: state.depth
62598
+ });
62599
+ }
62600
+ function getMultisigSignerContainer(input) {
62601
+ const out = [input[0].publicKeyAndType, []];
62602
+ for (const signer of input[1]) {
62603
+ let parsed;
62604
+ if (Array.isArray(signer)) {
62605
+ parsed = getMultisigSignerContainer(signer);
62606
+ }
62607
+ else {
62608
+ parsed = signer.publicKeyAndType;
62609
+ }
62610
+ out[1].push(parsed);
62611
+ }
62612
+ // XXX:TODO We need to use a type assertion here because the ASN1 schema does not support recursive types properly
62613
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62614
+ return out;
62615
+ }
62616
+ /** @internal */
62617
+ const BlockV2ASN1Schema = {
62618
+ type: 'context',
62619
+ kind: 'explicit',
62620
+ value: 1,
62621
+ contains: [
62622
+ ASN1.BufferStorageASN1.Validate.IsInteger,
62623
+ { optional: ASN1.BufferStorageASN1.Validate.IsInteger },
62624
+ { type: 'date', kind: 'general' },
62625
+ ASN1.BufferStorageASN1.Validate.IsInteger,
62626
+ ASN1.BufferStorageASN1.Validate.IsOctetString,
62627
+ {
62628
+ choice: [
62629
+ ASN1.BufferStorageASN1.Validate.IsNull,
62630
+ // If principal has a private key, the signature of principal
62631
+ ASN1.BufferStorageASN1.Validate.IsOctetString,
62632
+ // If principal does not have private key, list of accounts signing on behalf of principal and their signatures
62633
+ multisigSignerInfoASN1Schema
62634
+ ]
62635
+ },
62636
+ ASN1.BufferStorageASN1.Validate.IsOctetString,
62637
+ { sequenceOf: { choice: Object.values(Operations.BlockOperationASN1Schema) } },
62638
+ {
62639
+ choice: [
62640
+ // If principal has a private key, the signature of principal
62641
+ ASN1.BufferStorageASN1.Validate.IsOctetString,
62642
+ // If principal does not have private key, list of accounts signing on behalf of principal and their signatures
62643
+ { sequenceOf: ASN1.BufferStorageASN1.Validate.IsOctetString }
62644
+ ]
62645
+ }
62646
+ ]
62647
+ };
62648
+ const BlockASN1Schema = {
62649
+ choice: [
62650
+ BlockV1ASN1Schema,
62651
+ BlockV2ASN1Schema
62652
+ ]
62653
+ };
62654
+ function parseBlockSignerFieldJSON(input) {
62655
+ if (!Array.isArray(input)) {
62656
+ return (account_1.default.toAccount(input).assertAccount());
62657
+ }
62658
+ if (input.length !== 2) {
62659
+ throw (new Error('Multisig signer field must have two items'));
62660
+ }
62661
+ const signer = account_1.default.toAccount(input[0]).assertKeyType(account_1.AccountKeyAlgorithm.MULTISIG);
62662
+ const innerSigners = [];
62663
+ for (const signer of input[1]) {
62664
+ innerSigners.push(parseBlockSignerFieldJSON(signer));
62665
+ }
62666
+ return ([signer, innerSigners]);
62667
+ }
62402
62668
  /**
62403
62669
  * Statically assert that the BlockASN1 type is compatible with BlockASN1Schema
62404
62670
  * @internal
62405
62671
  */
62406
62672
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
62407
62673
  function _ignore_static_checks() {
62674
+ // V1 Checks
62408
62675
  // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/consistent-type-assertions
62409
- const _ignore_check_blockasn1_forward_1 = {};
62676
+ const _ignore_check_blockasn1v1_forward_1 = {};
62410
62677
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
62411
- const _ignore_check_blockasn1_forward_2 = _ignore_check_blockasn1_forward_1;
62678
+ const _ignore_check_blockasn1v1_forward_2 = _ignore_check_blockasn1v1_forward_1;
62412
62679
  // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/consistent-type-assertions
62413
- const _ignore_check_blockasn1_reverse_1 = {};
62680
+ const _ignore_check_blockasn1v1_reverse_1 = {};
62414
62681
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
62415
- const _ignore_check_blockasn1_reverse_2 = _ignore_check_blockasn1_reverse_1;
62416
- }
62417
- function assertBlockBlockCanonicalVersion(input) {
62418
- const expected = 1;
62419
- if (input !== expected) {
62420
- throw (new Error('Invalid block version'));
62421
- }
62682
+ const _ignore_check_blockasn1v1_reverse_2 = _ignore_check_blockasn1v1_reverse_1;
62683
+ // V2 Checks
62684
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/consistent-type-assertions
62685
+ const _ignore_check_blockasn1v2_forward_1 = {};
62686
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
62687
+ const _ignore_check_blockasn1v2_forward_2 = _ignore_check_blockasn1v2_forward_1;
62688
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/consistent-type-assertions
62689
+ const _ignore_check_blockasn1v2_reverse_1 = {};
62690
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
62691
+ const _ignore_check_blockasn1v2_reverse_2 = _ignore_check_blockasn1v2_reverse_1;
62422
62692
  }
62423
- function MapInputValues(input) {
62693
+ function MapV1InputValues(input) {
62424
62694
  const output = {};
62425
62695
  if (input.version !== 1) {
62426
62696
  throw (new Error('MapInputValues should not be called with version != 1'));
@@ -62433,6 +62703,9 @@ function MapInputValues(input) {
62433
62703
  * Import account
62434
62704
  */
62435
62705
  output.account = account_1.default.toAccount(input.account) ?? undefined;
62706
+ if (Array.isArray(input.signer)) {
62707
+ throw (new Error('V1 block signer must not be a multisig signer'));
62708
+ }
62436
62709
  output.signer = account_1.default.toAccount(input.signer);
62437
62710
  if (!output.signer && output.account?.isAccount()) {
62438
62711
  output.signer = output.account;
@@ -62485,125 +62758,300 @@ function MapInputValues(input) {
62485
62758
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62486
62759
  return output;
62487
62760
  }
62488
- /**
62489
- * Block: An item which contains a number of operations (transactions) which
62490
- * originated from an account at a particular instant
62491
- */
62492
- class Block {
62493
- static async fromUnsignedJSON(input) {
62494
- const inputCheck = input;
62495
- if (typeof inputCheck === 'object' && inputCheck !== null) {
62496
- if ('signature' in inputCheck) {
62497
- throw (new Error('fromUnsignedJSON() was called when a signature already exists'));
62498
- }
62499
- }
62500
- const container = Block.getASN1ContainerWithoutSignature(input);
62501
- const bytes = ASN1.JStoASN1(container).toBER(false);
62502
- const hash = new BlockHash((0, hash_1.Hash)(Buffer.from(bytes)));
62503
- const signature = await input.signer.sign(hash.getBuffer());
62504
- return (new Block({
62505
- version: input.version,
62506
- date: input.date,
62507
- previous: input.previous,
62508
- account: input.account,
62509
- signer: input.signer,
62510
- operations: input.operations,
62511
- network: input.network,
62512
- subnet: input.subnet,
62513
- signature: signature.getBuffer()
62514
- }));
62761
+ function MapV2InputValues(input) {
62762
+ const output = {};
62763
+ if (input.version !== 2) {
62764
+ throw (new Error('MapInputValues should not be called with version != 2'));
62515
62765
  }
62516
- static isValidJSON(block) {
62517
- for (const checkField of ['version', 'date', 'previous', 'network', 'network', 'account', 'signer', 'signature', 'operations']) {
62518
- if (block[checkField] === undefined) {
62519
- return (false);
62520
- }
62521
- }
62522
- return (true);
62766
+ output.version = input.version;
62767
+ output.purpose = input.purpose;
62768
+ if (input.date !== undefined) {
62769
+ output.date = new Date(input.date);
62523
62770
  }
62524
- constructor(input) {
62525
- _Block_instances.add(this);
62526
- _Block_valueBytes.set(this, void 0);
62527
- _Block_valueHash.set(this, void 0);
62528
- // Extra attributes
62529
- this.$signatureValid = true;
62530
- this.$opening = false;
62531
- if (typeof input === 'string') {
62532
- input = Buffer.from(input, 'base64');
62771
+ /*
62772
+ * Import account
62773
+ */
62774
+ output.account = account_1.default.toAccount(input.account) ?? undefined;
62775
+ /*
62776
+ * Import previous block hash
62777
+ */
62778
+ if (input.previous !== undefined) {
62779
+ if (BlockHash.isInstance(input.previous)) {
62780
+ output.previous = input.previous;
62533
62781
  }
62534
- if ((0, helper_1.isBuffer)(input)) {
62535
- input = (0, helper_1.bufferToArrayBuffer)(input);
62782
+ else if (input.previous === NO_PREVIOUS) {
62783
+ if (output.account) {
62784
+ output.previous = BlockHash.getAccountOpeningHash(output.account);
62785
+ }
62536
62786
  }
62537
- if (util_1.types.isArrayBuffer(input)) {
62538
- /*
62539
- * TypeScript cannot deal with this complex type, so we have to manually
62540
- * specify the type -- this might be fixed in TypeScript 5.7+
62541
- */
62542
- // @ts-ignore
62787
+ else {
62788
+ output.previous = new BlockHash(input.previous);
62789
+ }
62790
+ }
62791
+ /*
62792
+ * Import network
62793
+ */
62794
+ if (input.network !== undefined) {
62795
+ output.network = BigInt(input.network);
62796
+ }
62797
+ /*
62798
+ * Import Subnet
62799
+ */
62800
+ if (input.subnet !== undefined) {
62801
+ output.subnet = BigInt(input.subnet);
62802
+ }
62803
+ /*
62804
+ * Import operations from JSON
62805
+ */
62806
+ if (input.operations !== undefined) {
62807
+ output.operations = Operations.ImportOperationsJSON(input.operations);
62808
+ }
62809
+ if (input.signer !== undefined) {
62810
+ output.signer = parseBlockSignerFieldJSON(input.signer);
62811
+ }
62812
+ // This is valid, the compiler does not understand that we are adding all of the values in this function
62813
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62814
+ return output;
62815
+ }
62816
+ function assertBlockSignatureField(input) {
62817
+ if (input.length < 1) {
62818
+ throw (new Error('Input must include 1+ signatures'));
62819
+ }
62820
+ }
62821
+ /**
62822
+ * Block: An item which contains a number of operations (transactions) which
62823
+ * originated from an account at a particular instant
62824
+ */
62825
+ class Block {
62826
+ get principal() {
62827
+ if (Array.isArray(this.signer)) {
62828
+ return (this.signer[0]);
62829
+ }
62830
+ else {
62831
+ return (this.signer);
62832
+ }
62833
+ }
62834
+ static async fromUnsignedJSON(input) {
62835
+ const inputCheck = input;
62836
+ if (typeof inputCheck === 'object' && inputCheck !== null) {
62837
+ if ('signature' in inputCheck || 'signatures' in inputCheck) {
62838
+ throw (new Error('fromUnsignedJSON() was called when a signature(s) already exists'));
62839
+ }
62840
+ }
62841
+ const container = this.getASN1ContainerWithoutSignature(input);
62842
+ // We have to ignore the type here because the ASN1.JStoASN1 function does not handle recursive types well
62843
+ // @ts-ignore
62844
+ const bytes = ASN1.JStoASN1(container).toBER(false);
62845
+ const hash = new BlockHash((0, hash_1.Hash)(Buffer.from(bytes)));
62846
+ const signers = __classPrivateFieldGet(this, _a, "m", _Block_getSortedRequiredSigners).call(this, input.signer);
62847
+ const signatures = await Promise.all(signers.map(async function (signer) {
62848
+ const signature = await signer.sign(hash.getBuffer());
62849
+ return (signature.getBuffer());
62850
+ }));
62851
+ let blockInput;
62852
+ if (input.version === 1) {
62853
+ blockInput = { ...input, signature: signatures[0] };
62854
+ }
62855
+ else {
62856
+ blockInput = { ...input, signatures };
62857
+ }
62858
+ return (new _a(blockInput));
62859
+ }
62860
+ static isValidJSON(block, version) {
62861
+ if (!block || typeof block !== 'object' || Array.isArray(block)) {
62862
+ return (false);
62863
+ }
62864
+ if (!('version' in block)) {
62865
+ return (false);
62866
+ }
62867
+ if (version !== undefined && block.version !== version) {
62868
+ return (false);
62869
+ }
62870
+ const checkFields = ['date', 'previous', 'network', 'network', 'account', 'signer', 'operations'];
62871
+ if (block.version === 1) {
62872
+ checkFields.push('signature');
62873
+ }
62874
+ else if (block.version === 2) {
62875
+ checkFields.push('signatures');
62876
+ checkFields.push('purpose');
62877
+ }
62878
+ else {
62879
+ return (false);
62880
+ }
62881
+ for (const checkField of checkFields) {
62882
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62883
+ if (!(checkField in block) || block[checkField] === undefined) {
62884
+ return (false);
62885
+ }
62886
+ }
62887
+ return (true);
62888
+ }
62889
+ constructor(input) {
62890
+ _Block_instances.add(this);
62891
+ _Block_valueBytes.set(this, void 0);
62892
+ _Block_valueHash.set(this, void 0);
62893
+ // Extra attributes
62894
+ this.$opening = false;
62895
+ if (typeof input === 'string') {
62896
+ input = Buffer.from(input, 'base64');
62897
+ }
62898
+ if ((0, helper_1.isBuffer)(input)) {
62899
+ input = (0, helper_1.bufferToArrayBuffer)(input);
62900
+ }
62901
+ if (util_1.types.isArrayBuffer(input)) {
62543
62902
  const data = new ASN1.BufferStorageASN1(input, BlockASN1Schema).getASN1();
62544
- if (data[0] !== 0n) {
62545
- throw (new block_1.default('BLOCK_INVALID_VERSION', 'Only version 1 is supported'));
62546
- }
62547
- const version = Number(data[0]) + 1;
62548
- assertBlockBlockCanonicalVersion(version);
62549
- this.version = version;
62550
- this.network = data[1];
62551
- this.subnet = data[2] ?? undefined;
62552
- this.date = data[3].date;
62553
- const signerPubKey = data[4];
62554
- this.signer = account_1.default.fromPublicKeyAndType(signerPubKey).assertAccount();
62555
- const acctItem = data[5];
62556
- if (acctItem === null) {
62557
- this.account = this.signer;
62903
+ if (Array.isArray(data)) {
62904
+ if (data[0] !== 0n) {
62905
+ throw (new Error('Invalid block version without context tag'));
62906
+ }
62907
+ this.version = 1;
62908
+ this.purpose = BlockPurpose.GENERIC;
62909
+ this.network = data[1];
62910
+ this.subnet = data[2] ?? undefined;
62911
+ this.date = data[3].date;
62912
+ const signerContainer = data[4];
62913
+ this.signer = account_1.default.fromPublicKeyAndType(signerContainer).assertAccount();
62914
+ const acctItem = data[5];
62915
+ if (acctItem === null) {
62916
+ this.account = this.signer;
62917
+ }
62918
+ else {
62919
+ this.account = account_1.default.fromPublicKeyAndType(acctItem);
62920
+ if (this.account.comparePublicKey(this.signer)) {
62921
+ throw (new Error('Account should not be in block when it is same as signer, we cannot use this block'));
62922
+ }
62923
+ }
62924
+ const prevHashBuf = data[6];
62925
+ this.previous = new BlockHash(prevHashBuf);
62926
+ this.operations = Operations.ImportOperationsASN1(data[7], this.network);
62927
+ this.signatures = [data[8]];
62928
+ }
62929
+ else if (data.value === 1) {
62930
+ this.version = 2;
62931
+ const container = data.contains;
62932
+ this.network = container[0];
62933
+ this.subnet = container[1] ?? undefined;
62934
+ this.date = container[2].date;
62935
+ this.purpose = toBlockPurpose(container[3]);
62936
+ this.account = account_1.default.fromPublicKeyAndType(container[4]);
62937
+ const signersContainer = container[5];
62938
+ if (signersContainer === null) {
62939
+ this.signer = this.account.assertAccount();
62940
+ }
62941
+ else if (Buffer.isBuffer(signersContainer)) {
62942
+ this.signer = account_1.default.fromPublicKeyAndType(signersContainer).assertAccount();
62943
+ if (this.account.comparePublicKey(this.signer)) {
62944
+ throw (new Error('Signer should not be in block when it is same as account, we cannot use this block'));
62945
+ }
62946
+ }
62947
+ else {
62948
+ this.signer = parseBlockSignerFieldContainer(signersContainer).parsed;
62949
+ }
62950
+ this.previous = new BlockHash(container[6]);
62951
+ this.operations = Operations.ImportOperationsASN1(container[7], this.network);
62952
+ const signatureContainer = container[8];
62953
+ if (Buffer.isBuffer(signatureContainer)) {
62954
+ this.signatures = [signatureContainer];
62955
+ }
62956
+ else {
62957
+ if (signatureContainer.length <= 1) {
62958
+ throw (new Error('Signature field invalid, must be greater than one when using sequence of'));
62959
+ }
62960
+ assertBlockSignatureField(signatureContainer);
62961
+ this.signatures = signatureContainer;
62962
+ }
62558
62963
  }
62559
62964
  else {
62560
- this.account = account_1.default.fromPublicKeyAndType(acctItem);
62561
- if (this.account.comparePublicKey(this.signer)) {
62562
- throw (new Error('Account should not be in block when it is same as signer, we cannot use this block'));
62563
- }
62965
+ throw (new Error('Unknown block version'));
62564
62966
  }
62565
- const prevHashBuf = data[6];
62566
- this.previous = new BlockHash(prevHashBuf);
62567
- this.operations = Operations.ImportOperationsASN1(data[7], this.network);
62568
- this.signature = data[8];
62569
62967
  __classPrivateFieldSet(this, _Block_valueBytes, input, "f");
62570
62968
  }
62571
62969
  else {
62572
- if (!Block.isValidJSON(input)) {
62573
- throw (new Error('Cannot construct block, it is not a valid Block JSON object'));
62574
- }
62575
- /* XXX:TODO: Verify that no extra keys were passed in */
62576
- /*
62577
- * Map input to our values
62578
- */
62579
- const { version, date, previous, network, subnet, account, operations, signer } = MapInputValues(input);
62580
- this.version = version;
62581
- this.date = date;
62582
- this.previous = previous;
62583
- this.network = network;
62584
- this.subnet = subnet;
62585
- this.account = account;
62586
- this.signer = signer;
62587
- this.operations = operations;
62588
- /*
62589
- * We must handle the signature last because we will
62590
- * sign the hash of the block based on what has been
62591
- * processed
62592
- */
62593
- if (input.signature === undefined) {
62594
- throw (new Error('Cannot construct block without a signature and explicit direction to sign'));
62970
+ if (_a.isInstance(input)) {
62971
+ this.version = input.version;
62972
+ this.purpose = input.purpose;
62973
+ this.date = input.date;
62974
+ this.previous = input.previous;
62975
+ this.network = input.network;
62976
+ this.subnet = input.subnet;
62977
+ this.account = input.account;
62978
+ this.operations = input.operations;
62979
+ this.signer = input.signer;
62980
+ this.signatures = input.signatures;
62981
+ }
62982
+ else if (_a.isValidJSON(input, 1)) {
62983
+ /*
62984
+ * Map input to our values
62985
+ */
62986
+ const { version, date, previous, network, subnet, account, operations, signer } = MapV1InputValues(input);
62987
+ this.version = version;
62988
+ this.purpose = BlockPurpose.GENERIC;
62989
+ this.date = date;
62990
+ this.previous = previous;
62991
+ this.network = network;
62992
+ this.subnet = subnet;
62993
+ this.account = account;
62994
+ this.operations = operations;
62995
+ this.signer = signer;
62996
+ /*
62997
+ * We must handle the signature last because we will
62998
+ * sign the hash of the block based on what has been
62999
+ * processed
63000
+ */
63001
+ if (input.signature === undefined) {
63002
+ throw (new Error('Cannot construct block without a signature and explicit direction to sign'));
63003
+ }
63004
+ let signature;
63005
+ if (typeof input.signature === 'string') {
63006
+ signature = Buffer.from(input.signature, 'hex');
63007
+ }
63008
+ else {
63009
+ signature = Buffer.from(input.signature);
63010
+ }
63011
+ this.signatures = [signature];
62595
63012
  }
62596
- if (typeof input.signature === 'string') {
62597
- this.signature = Buffer.from(input.signature, 'hex');
63013
+ else if (_a.isValidJSON(input, 2)) {
63014
+ /*
63015
+ * Map input to our values
63016
+ */
63017
+ const { version, date, previous, network, subnet, account, operations, signer, purpose } = MapV2InputValues(input);
63018
+ this.version = version;
63019
+ this.purpose = purpose;
63020
+ this.date = date;
63021
+ this.previous = previous;
63022
+ this.network = network;
63023
+ this.subnet = subnet;
63024
+ this.account = account;
63025
+ this.signer = signer;
63026
+ this.operations = operations;
63027
+ /*
63028
+ * We must handle the signature last because we will
63029
+ * sign the hash of the block based on what has been
63030
+ * processed
63031
+ */
63032
+ if (input.signatures === undefined) {
63033
+ throw (new Error('Cannot construct block without a signature and explicit direction to sign'));
63034
+ }
63035
+ const signatures = input.signatures.map(function (signature) {
63036
+ if (typeof signature === 'string') {
63037
+ return (Buffer.from(signature, 'hex'));
63038
+ }
63039
+ else {
63040
+ return (Buffer.from(signature));
63041
+ }
63042
+ });
63043
+ assertBlockSignatureField(signatures);
63044
+ this.signatures = signatures;
62598
63045
  }
62599
63046
  else {
62600
- this.signature = Buffer.from(input.signature);
63047
+ throw (new Error('Cannot construct block, it is not a valid Block JSON object'));
62601
63048
  }
63049
+ /* XXX:TODO: Verify that no extra keys were passed in */
62602
63050
  }
62603
63051
  if (this.previous.compareHexString(this.hash)) {
62604
63052
  throw (new block_1.default('BLOCK_PREVIOUS_SELF', 'internal error: Block references itself'));
62605
63053
  }
62606
- const checkAccountOpening = Block.getAccountOpeningHash(this.account);
63054
+ const checkAccountOpening = _a.getAccountOpeningHash(this.account);
62607
63055
  this.$opening = this.previous.compareHexString(checkAccountOpening);
62608
63056
  if (this.network < 0n) {
62609
63057
  throw (new Error('Network ID must be a positive number'));
@@ -62613,35 +63061,91 @@ class Block {
62613
63061
  throw (new Error('Subnet ID must be a positive number'));
62614
63062
  }
62615
63063
  }
62616
- if (this.version !== 1) {
62617
- throw (new Error('We only support Blocks with Version 1'));
63064
+ if (this.version !== 1 && this.version !== 2) {
63065
+ throw (new block_1.default('BLOCK_INVALID_VERSION', 'We only support Blocks Version 1-2'));
63066
+ }
63067
+ if (this.account.isMultisig()) {
63068
+ throw (new block_1.default('BLOCK_NO_MULTISIG_OP', 'Cannot create a block for a multisig account'));
62618
63069
  }
62619
63070
  if (this.account.isMultisig()) {
62620
63071
  throw (new block_1.default('BLOCK_NO_MULTISIG_OP', 'Cannot create a block for a multisig account'));
62621
63072
  }
62622
- __classPrivateFieldGet(this, _Block_instances, "m", _Block_validateOperations).call(this);
62623
- __classPrivateFieldGet(this, _Block_instances, "m", _Block_validateSignature).call(this);
63073
+ __classPrivateFieldGet(this, _Block_instances, "m", _Block_validateSignerField).call(this);
63074
+ __classPrivateFieldGet(this, _Block_instances, "m", _Block_validateOperationsPurpose).call(this);
63075
+ __classPrivateFieldGet(this, _Block_instances, "m", _Block_validateSignatures).call(this);
62624
63076
  }
62625
63077
  static getAccountOpeningHash(account) {
62626
63078
  return (BlockHash.getAccountOpeningHash(account));
62627
63079
  }
62628
- toBytes(includeSignature = true) {
62629
- if (__classPrivateFieldGet(this, _Block_valueBytes, "f") !== undefined) {
62630
- if (includeSignature) {
62631
- return (__classPrivateFieldGet(this, _Block_valueBytes, "f"));
63080
+ toBytes(includeSignatures = true) {
63081
+ if (__classPrivateFieldGet(this, _Block_valueBytes, "f") !== undefined && includeSignatures) {
63082
+ return (__classPrivateFieldGet(this, _Block_valueBytes, "f"));
63083
+ }
63084
+ const sharedBlockValues = {
63085
+ previous: this.previous,
63086
+ operations: this.operations,
63087
+ account: this.account,
63088
+ network: this.network,
63089
+ subnet: this.subnet,
63090
+ date: this.date
63091
+ };
63092
+ let container;
63093
+ if (this.version === 1) {
63094
+ if (Array.isArray(this.signer) || this.signatures.length !== 1) {
63095
+ throw (new Error('Block v1 only supports single signer'));
63096
+ }
63097
+ container = _a.getV1ASN1ContainerWithoutSignature({
63098
+ ...sharedBlockValues,
63099
+ version: 1,
63100
+ signer: this.signer
63101
+ });
63102
+ if (includeSignatures) {
63103
+ container.push(this.signatures[0]);
62632
63104
  }
62633
63105
  }
62634
- const container = Block.getASN1ContainerWithoutSignature(this);
62635
- if (includeSignature) {
62636
- container.push(this.signature);
63106
+ else {
63107
+ const versionTag = this.version - 1;
63108
+ if (versionTag !== 1) {
63109
+ // We only support version 2
63110
+ throw (new block_1.default('BLOCK_INVALID_VERSION', 'We only support version 1/2 blocks'));
63111
+ }
63112
+ const v2Container = _a.getV2ASN1ContainerWithoutSignature({
63113
+ ...sharedBlockValues,
63114
+ purpose: this.purpose,
63115
+ version: this.version,
63116
+ signer: this.signer
63117
+ });
63118
+ const baseContextTag = {
63119
+ type: 'context',
63120
+ kind: 'explicit',
63121
+ value: versionTag
63122
+ };
63123
+ if (includeSignatures) {
63124
+ let signatureContainer;
63125
+ if (this.signatures.length > 1) {
63126
+ signatureContainer = this.signatures;
63127
+ }
63128
+ else if (this.signatures.length === 1) {
63129
+ signatureContainer = this.signatures[0];
63130
+ }
63131
+ else {
63132
+ throw (new Error('Block has not been signed'));
63133
+ }
63134
+ container = { ...baseContextTag, contains: [...v2Container, signatureContainer] };
63135
+ }
63136
+ else {
63137
+ container = { ...baseContextTag, contains: v2Container };
63138
+ }
62637
63139
  }
63140
+ // We know the container is valid because of the container type, but the ASN1.JStoASN1 function does not handle recursive types well
63141
+ // @ts-ignore
62638
63142
  const retval = ASN1.JStoASN1(container).toBER(false);
62639
- if (includeSignature) {
63143
+ if (includeSignatures) {
62640
63144
  __classPrivateFieldSet(this, _Block_valueBytes, retval, "f");
62641
63145
  }
62642
63146
  return (retval);
62643
63147
  }
62644
- static getASN1ContainerWithoutSignature(input) {
63148
+ static getV1ASN1ContainerWithoutSignature(input) {
62645
63149
  let outputAccount;
62646
63150
  if (input.account.comparePublicKey(input.signer)) {
62647
63151
  outputAccount = null;
@@ -62652,7 +63156,7 @@ class Block {
62652
63156
  if (input.version !== 1) {
62653
63157
  throw (new Error('Cannot call getASN1ContainerWithoutSignature when version != 1'));
62654
63158
  }
62655
- const container = [
63159
+ return ([
62656
63160
  0n,
62657
63161
  input.network,
62658
63162
  input.subnet ?? null,
@@ -62661,21 +63165,72 @@ class Block {
62661
63165
  outputAccount,
62662
63166
  Buffer.from(input.previous.get()),
62663
63167
  Operations.ExportBlockOperations([...input.operations])
62664
- ];
62665
- return (container);
63168
+ ]);
63169
+ }
63170
+ static getV2ASN1ContainerWithoutSignature(input) {
63171
+ if (input.version !== 2) {
63172
+ throw (new Error('Only version 2 supported'));
63173
+ }
63174
+ let signerContainer;
63175
+ if (Array.isArray(input.signer)) {
63176
+ signerContainer = getMultisigSignerContainer(input.signer);
63177
+ }
63178
+ else if (input.signer.comparePublicKey(input.account)) {
63179
+ signerContainer = null;
63180
+ }
63181
+ else {
63182
+ signerContainer = input.signer.publicKeyAndType;
63183
+ }
63184
+ return ([
63185
+ input.network,
63186
+ input.subnet,
63187
+ { type: 'date', kind: 'general', date: input.date },
63188
+ BigInt(input.purpose),
63189
+ input.account.publicKeyAndType,
63190
+ signerContainer,
63191
+ Buffer.from(input.previous.get()),
63192
+ Operations.ExportBlockOperations([...input.operations])
63193
+ ]);
63194
+ }
63195
+ static getASN1ContainerWithoutSignature(input) {
63196
+ if (input.version === 1) {
63197
+ return (this.getV1ASN1ContainerWithoutSignature(input));
63198
+ }
63199
+ else if (input.version === 2) {
63200
+ return ({
63201
+ type: 'context',
63202
+ kind: 'explicit',
63203
+ value: 1,
63204
+ contains: this.getV2ASN1ContainerWithoutSignature(input)
63205
+ });
63206
+ }
63207
+ else {
63208
+ throw (new block_1.default('BLOCK_INVALID_VERSION', 'Invalid Version'));
63209
+ }
62666
63210
  }
62667
63211
  toJSON(options) {
62668
63212
  const additionalFields = {};
62669
63213
  if (options?.addBinary) {
62670
63214
  additionalFields['$binary'] = Buffer.from(this.toBytes()).toString('base64');
62671
63215
  }
63216
+ const signatures = this.signatures.map(function (signature) {
63217
+ return (signature.toString('hex').toUpperCase());
63218
+ });
63219
+ if (this.version === 1) {
63220
+ additionalFields.signature = signatures[0];
63221
+ }
63222
+ else {
63223
+ additionalFields.signatures = signatures;
63224
+ }
62672
63225
  return ({
62673
63226
  version: this.version,
62674
63227
  date: this.date,
62675
63228
  previous: this.previous,
62676
63229
  account: this.account,
63230
+ purpose: this.purpose,
63231
+ // XXX:TODO We need to use a type assertion here because toJSONSerializable does not support recursive types
63232
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62677
63233
  signer: this.signer,
62678
- signature: this.signature.toString('hex').toUpperCase(),
62679
63234
  network: this.network,
62680
63235
  subnet: this.subnet,
62681
63236
  operations: Operations.ExportOperationsJSON(this.operations),
@@ -62702,7 +63257,27 @@ class Block {
62702
63257
  }
62703
63258
  }
62704
63259
  exports.Block = Block;
62705
- _Block_valueBytes = new WeakMap(), _Block_valueHash = new WeakMap(), _Block_instances = new WeakSet(), _Block_validateOperations = function _Block_validateOperations() {
63260
+ _a = Block, _Block_valueBytes = new WeakMap(), _Block_valueHash = new WeakMap(), _Block_instances = new WeakSet(), _Block_getSortedRequiredSigners = function _Block_getSortedRequiredSigners(input) {
63261
+ const queue = [input];
63262
+ const visited = new account_1.default.Set();
63263
+ const out = [];
63264
+ while (queue.length > 0) {
63265
+ // We can assume that the signerFieldQueue is not empty here since the loop condition checks it
63266
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
63267
+ const cur = queue.shift();
63268
+ if (account_1.default.isInstance(cur)) {
63269
+ if (visited.has(cur)) {
63270
+ continue;
63271
+ }
63272
+ visited.add(cur);
63273
+ out.push(cur);
63274
+ }
63275
+ else {
63276
+ queue.unshift(...cur[1]);
63277
+ }
63278
+ }
63279
+ return (out);
63280
+ }, _Block_validateOperationsPurpose = function _Block_validateOperationsPurpose() {
62706
63281
  /**
62707
63282
  * Do not allow blocks to contain invalid constructions
62708
63283
  */
@@ -62711,23 +63286,63 @@ _Block_valueBytes = new WeakMap(), _Block_valueHash = new WeakMap(), _Block_inst
62711
63286
  operationIndex: 0
62712
63287
  };
62713
63288
  for (const operation of this.operations) {
63289
+ if (this.purpose === BlockPurpose.FEE) {
63290
+ if (operation.type !== Operations.OperationType.SEND) {
63291
+ throw (new block_1.default('BLOCK_INVALID_PURPOSE_VALIDATION', `Block purpose is FEE, but operation at index ${context.operationIndex} is not a SEND operation`));
63292
+ }
63293
+ }
62714
63294
  operation.validate(context);
62715
63295
  context.operationIndex++;
62716
63296
  }
62717
- }, _Block_validateSignature = function _Block_validateSignature() {
62718
- /* XXX:TODO: 64 is the size of signatures right now but this shouldn't be hard-coded */
62719
- const signature = new buffer_1.BufferStorage(this.signature, 64);
62720
- const valid = this.signer.verify(this.hash.get(), signature.get());
62721
- if (valid !== true) {
62722
- throw (new Error(`Unable to validate signature of ${this.hash.toString()} against signature ${this.signature}`));
63297
+ }, _Block_validateSignerField = function _Block_validateSignerField() {
63298
+ if (!Array.isArray(this.signer)) {
63299
+ return;
63300
+ }
63301
+ const queue = [[1n, this.signer]];
63302
+ while (queue.length > 0) {
63303
+ // We can assume that the signerFieldQueue is not empty here since the loop condition checks it
63304
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
63305
+ const [depth, cur] = queue.shift();
63306
+ (0, common_1.validateBlockSignerDepth)(depth, this.network);
63307
+ if (Array.isArray(cur)) {
63308
+ (0, common_1.validateBlockSignerCount)(BigInt(cur[1].length), this.network);
63309
+ const seen = new account_1.default.Set();
63310
+ for (const innerSigner of cur[1]) {
63311
+ let signer;
63312
+ if (Array.isArray(innerSigner)) {
63313
+ signer = innerSigner[0];
63314
+ queue.push([depth + 1n, innerSigner]);
63315
+ }
63316
+ else {
63317
+ signer = innerSigner;
63318
+ }
63319
+ if (seen.has(signer)) {
63320
+ throw (new block_1.default('BLOCK_INVALID_MULTISIG_SIGNER_DUPLICATE', `Multisig signer at depth ${depth} has duplicate signer ${signer.publicKeyString.get()}`));
63321
+ }
63322
+ seen.add(signer);
63323
+ }
63324
+ }
63325
+ }
63326
+ }, _Block_validateSignatures = function _Block_validateSignatures() {
63327
+ const signers = __classPrivateFieldGet(_a, _a, "m", _Block_getSortedRequiredSigners).call(_a, this.signer);
63328
+ if (this.signatures.length !== signers.length) {
63329
+ throw (new block_1.default('BLOCK_INVALID_SIGNER', 'Signer count does not match signature count'));
63330
+ }
63331
+ for (let i = 0; i < signers.length; i++) {
63332
+ const signature = new buffer_1.BufferStorage(this.signatures[i], 64);
63333
+ const valid = signers[i].verify(this.hash.get(), signature.get());
63334
+ if (valid !== true) {
63335
+ throw (new Error(`Unable to validate signature of ${this.hash.toString()} against signature ${this.signatures[i]} for account ${signers[i].publicKeyString.get()}`));
63336
+ }
62723
63337
  }
62724
63338
  };
62725
- Block.isInstance = (0, helper_1.checkableGenerator)(Block);
63339
+ Block.isInstance = (0, helper_1.checkableGenerator)(_a);
62726
63340
  Block.Hash = BlockHash;
62727
63341
  Block.OperationType = Operations.OperationType;
62728
63342
  Block.Operation = Operations.Operation;
62729
63343
  Block.NO_PREVIOUS = NO_PREVIOUS;
62730
63344
  Block.AdjustMethod = AdjustMethod;
63345
+ Block.Purpose = BlockPurpose;
62731
63346
  class BlockBuilder {
62732
63347
  constructor(block) {
62733
63348
  _BlockBuilder_block.set(this, void 0);
@@ -62745,13 +63360,13 @@ class BlockBuilder {
62745
63360
  __classPrivateFieldSet(this, _BlockBuilder_block, new Block(block), "f");
62746
63361
  }
62747
63362
  else {
62748
- if (block !== undefined && Block.isValidJSON(block)) {
63363
+ if (block !== undefined && Block.isValidJSON(block, 2)) {
62749
63364
  __classPrivateFieldSet(this, _BlockBuilder_block, new Block(block), "f");
62750
63365
  }
62751
63366
  else {
62752
63367
  const incompleteBlockJSON = {
62753
- version: 1,
62754
63368
  date: (new Date()).toISOString(),
63369
+ version: 1,
62755
63370
  ...block
62756
63371
  };
62757
63372
  /*
@@ -62761,7 +63376,18 @@ class BlockBuilder {
62761
63376
  if (incompleteBlockJSON.previous === BlockBuilder.NO_PREVIOUS) {
62762
63377
  setPreviousNoBlock = true;
62763
63378
  }
62764
- const newBlockJSON = MapInputValues(incompleteBlockJSON);
63379
+ let newBlockJSON;
63380
+ if (incompleteBlockJSON.version === 1) {
63381
+ // We have to use a type assertion here because the MapV1InputValues function does not support recursive types
63382
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
63383
+ newBlockJSON = MapV1InputValues({ ...incompleteBlockJSON, version: 1 });
63384
+ }
63385
+ else if (incompleteBlockJSON.version === 2) {
63386
+ newBlockJSON = MapV2InputValues({ ...incompleteBlockJSON, version: 2 });
63387
+ }
63388
+ else {
63389
+ throw (new Error('Cannot construct block, it is not a valid Block JSON object'));
63390
+ }
62765
63391
  if (setPreviousNoBlock) {
62766
63392
  newBlockJSON.previous = BlockBuilder.NO_PREVIOUS;
62767
63393
  }
@@ -62801,20 +63427,42 @@ class BlockBuilder {
62801
63427
  network: this.network,
62802
63428
  subnet: this.subnet,
62803
63429
  operations: this.operations,
63430
+ purpose: this.purpose,
62804
63431
  ['$opening']: this.$opening
62805
63432
  });
62806
63433
  }
62807
63434
  async seal() {
62808
- const block = await Block.fromUnsignedJSON(MapInputValues(this));
63435
+ if (this.version === undefined) {
63436
+ throw (new Error('Cannot seal block without version'));
63437
+ }
63438
+ let input;
63439
+ // There is no clean way to tell the compiler which version `this` is, so we have to use a type assertion
63440
+ if (this.version === 1) {
63441
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
63442
+ input = MapV1InputValues(this);
63443
+ }
63444
+ else {
63445
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
63446
+ input = MapV2InputValues(this);
63447
+ }
63448
+ const block = await Block.fromUnsignedJSON(input);
62809
63449
  __classPrivateFieldSet(this, _BlockBuilder_block, block, "f");
62810
63450
  return (block);
62811
63451
  }
62812
63452
  unseal() {
62813
63453
  let retval;
62814
63454
  if (Block.isInstance(__classPrivateFieldGet(this, _BlockBuilder_block, "f"))) {
62815
- __classPrivateFieldSet(this, _BlockBuilder_block, { ...__classPrivateFieldGet(this, _BlockBuilder_block, "f") }, "f");
63455
+ __classPrivateFieldSet(this, _BlockBuilder_block, {
63456
+ version: __classPrivateFieldGet(this, _BlockBuilder_block, "f").version,
63457
+ date: __classPrivateFieldGet(this, _BlockBuilder_block, "f").date,
63458
+ previous: __classPrivateFieldGet(this, _BlockBuilder_block, "f").previous,
63459
+ account: __classPrivateFieldGet(this, _BlockBuilder_block, "f").account,
63460
+ signer: __classPrivateFieldGet(this, _BlockBuilder_block, "f").signer,
63461
+ network: __classPrivateFieldGet(this, _BlockBuilder_block, "f").network,
63462
+ subnet: __classPrivateFieldGet(this, _BlockBuilder_block, "f").subnet,
63463
+ operations: [...__classPrivateFieldGet(this, _BlockBuilder_block, "f").operations]
63464
+ }, "f");
62816
63465
  retval = __classPrivateFieldGet(this, _BlockBuilder_block, "f");
62817
- delete retval['signature'];
62818
63466
  }
62819
63467
  else {
62820
63468
  retval = __classPrivateFieldGet(this, _BlockBuilder_block, "f");
@@ -62839,12 +63487,36 @@ class BlockBuilder {
62839
63487
  }
62840
63488
  }
62841
63489
  set signer(signer) {
62842
- this.currentWIP.signer = account_1.default.toAccount(signer);
63490
+ if (signer) {
63491
+ this.currentWIP.signer = parseBlockSignerFieldJSON(signer);
63492
+ }
63493
+ else {
63494
+ this.currentWIP.signer = undefined;
63495
+ }
62843
63496
  }
62844
63497
  get signer() {
62845
63498
  const signer = __classPrivateFieldGet(this, _BlockBuilder_block, "f").signer;
62846
- if (signer !== undefined && !account_1.default.isInstance(signer)) {
62847
- throw (new Error('internal error: We only represent signer as Account'));
63499
+ if (signer === undefined) {
63500
+ if (this.account && this.account.isAccount() && this.account.hasPrivateKey) {
63501
+ return (this.account);
63502
+ }
63503
+ }
63504
+ else {
63505
+ const queue = [signer];
63506
+ while (queue.length > 0) {
63507
+ const cur = queue.shift();
63508
+ let signer;
63509
+ if (Array.isArray(cur)) {
63510
+ signer = cur[0];
63511
+ queue.push(...cur[1]);
63512
+ }
63513
+ else {
63514
+ signer = cur;
63515
+ }
63516
+ if (!account_1.default.isInstance(signer)) {
63517
+ throw (new Error('internal error: We only represent signer/multisig-info as their constructed values'));
63518
+ }
63519
+ }
62848
63520
  }
62849
63521
  return (signer);
62850
63522
  }
@@ -62856,7 +63528,16 @@ class BlockBuilder {
62856
63528
  if (account !== undefined && !account_1.default.isInstance(account)) {
62857
63529
  throw (new Error('internal error: We only represent account as an Account'));
62858
63530
  }
62859
- return (account ?? this.signer);
63531
+ if (account === undefined && this.version === 1 || this.version === undefined) {
63532
+ if (Array.isArray(this.signer)) {
63533
+ throw (new Error('Cannot create a v1 block with a multisig signer'));
63534
+ }
63535
+ if (typeof this.signer === 'string') {
63536
+ throw (new Error('We should only represent signer as an Account'));
63537
+ }
63538
+ return (this.signer);
63539
+ }
63540
+ return (account);
62860
63541
  }
62861
63542
  set previous(blockhash) {
62862
63543
  const wip = this.currentWIP;
@@ -62929,6 +63610,18 @@ class BlockBuilder {
62929
63610
  get version() {
62930
63611
  return (this.currentBlock.version);
62931
63612
  }
63613
+ set purpose(purpose) {
63614
+ if (purpose !== undefined && purpose !== BlockPurpose.GENERIC && this.version === 1) {
63615
+ throw (new Error('Cannot set purpose (other than generic) on a v1 block'));
63616
+ }
63617
+ this.currentWIP.purpose = purpose;
63618
+ }
63619
+ get purpose() {
63620
+ if (this.currentBlock.purpose !== undefined) {
63621
+ return (this.currentBlock.purpose);
63622
+ }
63623
+ return (BlockPurpose.GENERIC);
63624
+ }
62932
63625
  set network(network) {
62933
63626
  this.currentWIP.network = network;
62934
63627
  }
@@ -63025,7 +63718,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
63025
63718
  var __importDefault = (this && this.__importDefault) || function (mod) {
63026
63719
  return (mod && mod.__esModule) ? mod : { "default": mod };
63027
63720
  };
63028
- var _BlockOperationSEND_instances, _BlockOperationSEND_to, _BlockOperationSEND_amount, _BlockOperationSEND_token, _BlockOperationSEND_computeToken, _BlockOperationRECEIVE_instances, _BlockOperationRECEIVE_amount, _BlockOperationRECEIVE_token, _BlockOperationRECEIVE_from, _BlockOperationRECEIVE_forward, _BlockOperationRECEIVE_exact, _BlockOperationRECEIVE_computeExact, _BlockOperationRECEIVE_computeForward, _BlockOperationRECEIVE_computeToken, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_instances, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_token, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_method, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_amount, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_computeToken, _BlockOperationSET_REP_to, _BlockOperationCREATE_IDENTIFIER_instances, _BlockOperationCREATE_IDENTIFIER_identifier, _BlockOperationCREATE_IDENTIFIER_computeIdentifier, _BlockOperationSET_INFO_instances, _BlockOperationSET_INFO_name, _BlockOperationSET_INFO_description, _BlockOperationSET_INFO_metadata, _BlockOperationSET_INFO_defaultPermission, _BlockOperationSET_INFO_validateNameDesc, _BlockOperationMODIFY_PERMISSIONS_instances, _BlockOperationMODIFY_PERMISSIONS_principal, _BlockOperationMODIFY_PERMISSIONS_target, _BlockOperationMODIFY_PERMISSIONS_method, _BlockOperationMODIFY_PERMISSIONS_permissions, _BlockOperationMODIFY_PERMISSIONS_computePermissions, _BlockOperationTOKEN_ADMIN_SUPPLY_instances, _BlockOperationTOKEN_ADMIN_SUPPLY_amount, _BlockOperationTOKEN_ADMIN_SUPPLY_method, _BlockOperationTOKEN_ADMIN_SUPPLY_computeSupplyMethod, _BlockOperationMANAGE_CERTIFICATE_instances, _BlockOperationMANAGE_CERTIFICATE_certificateOrHash, _BlockOperationMANAGE_CERTIFICATE_intermediateCertificates, _BlockOperationMANAGE_CERTIFICATE_method, _BlockOperationMANAGE_CERTIFICATE_asCertificate, _BlockOperationMANAGE_CERTIFICATE_asIntermediateCertificates, _BlockOperationMANAGE_CERTIFICATE_computeCertificateMethod;
63721
+ var _BlockOperationSEND_instances, _BlockOperationSEND_to, _BlockOperationSEND_amount, _BlockOperationSEND_token, _BlockOperationSEND_computeToken, _BlockOperationRECEIVE_instances, _BlockOperationRECEIVE_amount, _BlockOperationRECEIVE_token, _BlockOperationRECEIVE_from, _BlockOperationRECEIVE_forward, _BlockOperationRECEIVE_exact, _BlockOperationRECEIVE_computeExact, _BlockOperationRECEIVE_computeForward, _BlockOperationRECEIVE_computeToken, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_instances, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_token, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_method, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_amount, _BlockOperationTOKEN_ADMIN_MODIFY_BALANCE_computeToken, _BlockOperationSET_REP_to, _BlockOperationCREATE_IDENTIFIER_instances, _BlockOperationCREATE_IDENTIFIER_identifier, _BlockOperationCREATE_IDENTIFIER_createArguments, _BlockOperationCREATE_IDENTIFIER_computeIdentifier, _BlockOperationCREATE_IDENTIFIER_computeCreateArguments, _BlockOperationSET_INFO_instances, _BlockOperationSET_INFO_name, _BlockOperationSET_INFO_description, _BlockOperationSET_INFO_metadata, _BlockOperationSET_INFO_defaultPermission, _BlockOperationSET_INFO_validateNameDesc, _BlockOperationMODIFY_PERMISSIONS_instances, _BlockOperationMODIFY_PERMISSIONS_principal, _BlockOperationMODIFY_PERMISSIONS_target, _BlockOperationMODIFY_PERMISSIONS_method, _BlockOperationMODIFY_PERMISSIONS_permissions, _BlockOperationMODIFY_PERMISSIONS_computePermissions, _BlockOperationTOKEN_ADMIN_SUPPLY_instances, _BlockOperationTOKEN_ADMIN_SUPPLY_amount, _BlockOperationTOKEN_ADMIN_SUPPLY_method, _BlockOperationTOKEN_ADMIN_SUPPLY_computeSupplyMethod, _BlockOperationMANAGE_CERTIFICATE_instances, _BlockOperationMANAGE_CERTIFICATE_certificateOrHash, _BlockOperationMANAGE_CERTIFICATE_intermediateCertificates, _BlockOperationMANAGE_CERTIFICATE_method, _BlockOperationMANAGE_CERTIFICATE_asCertificate, _BlockOperationMANAGE_CERTIFICATE_asIntermediateCertificates, _BlockOperationMANAGE_CERTIFICATE_computeCertificateMethod;
63029
63722
  Object.defineProperty(exports, "__esModule", ({ value: true }));
63030
63723
  exports.Operation = exports.BlockOperationASN1Schema = exports.OperationType = void 0;
63031
63724
  exports.createBlockOperation = createBlockOperation;
@@ -63121,7 +63814,25 @@ const BlockOperationASN1SchemaBase = {
63121
63814
  { name: 'target', schema: { optional: asn1_1.ValidateASN1.IsOctetString } }
63122
63815
  ],
63123
63816
  'CREATE_IDENTIFIER': [
63124
- { name: 'identifier', schema: asn1_1.ValidateASN1.IsOctetString }
63817
+ { name: 'identifier', schema: asn1_1.ValidateASN1.IsOctetString },
63818
+ {
63819
+ name: 'createArguments',
63820
+ schema: {
63821
+ optional: {
63822
+ choice: [
63823
+ {
63824
+ type: 'context',
63825
+ kind: 'explicit',
63826
+ value: 7,
63827
+ contains: [
63828
+ { sequenceOf: asn1_1.ValidateASN1.IsOctetString },
63829
+ asn1_1.ValidateASN1.IsInteger
63830
+ ]
63831
+ }
63832
+ ]
63833
+ }
63834
+ }
63835
+ }
63125
63836
  ],
63126
63837
  'TOKEN_ADMIN_SUPPLY': [
63127
63838
  { name: 'amount', schema: asn1_1.ValidateASN1.IsInteger },
@@ -63469,10 +64180,12 @@ class BlockOperationCREATE_IDENTIFIER extends BlockOperation {
63469
64180
  _BlockOperationCREATE_IDENTIFIER_instances.add(this);
63470
64181
  this.type = OperationType.CREATE_IDENTIFIER;
63471
64182
  _BlockOperationCREATE_IDENTIFIER_identifier.set(this, void 0);
64183
+ _BlockOperationCREATE_IDENTIFIER_createArguments.set(this, void 0);
63472
64184
  if (input.type !== OperationType.CREATE_IDENTIFIER) {
63473
64185
  throw (new block_1.default('BLOCK_INVALID_TYPE', 'Invalid construction of BlockOperationCREATE_IDENTIFIER'));
63474
64186
  }
63475
64187
  __classPrivateFieldSet(this, _BlockOperationCREATE_IDENTIFIER_identifier, __classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_instances, "m", _BlockOperationCREATE_IDENTIFIER_computeIdentifier).call(this, input.identifier), "f");
64188
+ __classPrivateFieldSet(this, _BlockOperationCREATE_IDENTIFIER_createArguments, __classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_instances, "m", _BlockOperationCREATE_IDENTIFIER_computeCreateArguments).call(this, input.createArguments), "f");
63476
64189
  }
63477
64190
  set identifier(identifier) {
63478
64191
  __classPrivateFieldSet(this, _BlockOperationCREATE_IDENTIFIER_identifier, __classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_instances, "m", _BlockOperationCREATE_IDENTIFIER_computeIdentifier).call(this, identifier), "f");
@@ -63480,6 +64193,12 @@ class BlockOperationCREATE_IDENTIFIER extends BlockOperation {
63480
64193
  get identifier() {
63481
64194
  return (__classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_identifier, "f"));
63482
64195
  }
64196
+ set createArguments(input) {
64197
+ __classPrivateFieldSet(this, _BlockOperationCREATE_IDENTIFIER_createArguments, __classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_instances, "m", _BlockOperationCREATE_IDENTIFIER_computeCreateArguments).call(this, input), "f");
64198
+ }
64199
+ get createArguments() {
64200
+ return (__classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_createArguments, "f"));
64201
+ }
63483
64202
  validate(context) {
63484
64203
  const { block, operationIndex } = context;
63485
64204
  if (block.account.isIdentifier()) {
@@ -63493,24 +64212,65 @@ class BlockOperationCREATE_IDENTIFIER extends BlockOperation {
63493
64212
  if (this.identifier.comparePublicKey(validIdentifier) === false) {
63494
64213
  throw (new block_1.default('BLOCK_IDENTIFIER_INVALID', 'Requested token identifier is not valid'));
63495
64214
  }
64215
+ const keyTypesArgumentsRequired = [account_1.AccountKeyAlgorithm.MULTISIG];
64216
+ const shouldHaveCreateArguments = keyTypesArgumentsRequired.includes(this.identifier.keyType);
64217
+ if ((this.createArguments !== undefined) !== shouldHaveCreateArguments) {
64218
+ throw (new block_1.default('BLOCK_INVALID_CREATE_IDENTIFIER_ARGS', `Create arguments set/unset when should not be for key type ${this.identifier.keyType}`));
64219
+ }
64220
+ if (__classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_createArguments, "f")) {
64221
+ if (!__classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_identifier, "f").isKeyType(__classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_createArguments, "f").type)) {
64222
+ throw (new block_1.default('BLOCK_INVALID_CREATE_IDENTIFIER_ARGS', 'Invalid create arguments for key type'));
64223
+ }
64224
+ if (__classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_createArguments, "f").type === account_1.AccountKeyAlgorithm.MULTISIG) {
64225
+ const { signers, quorum } = __classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_createArguments, "f");
64226
+ (0, common_1.validateBlockSignerCount)(BigInt(signers.length), block.network);
64227
+ const signerSet = new account_1.default.Set(signers);
64228
+ if (signerSet.size !== signers.length) {
64229
+ throw (new block_1.default('BLOCK_INVALID_MULTISIG_SIGNER_DUPLICATE', `Duplicate signer found`));
64230
+ }
64231
+ if (quorum < 1n || quorum > signerSet.size) {
64232
+ throw (new block_1.default('BLOCK_INVALID_MULTISIG_QUORUM', `Quorum must be between [1, ${signerSet.size}], got ${quorum}`));
64233
+ }
64234
+ }
64235
+ else {
64236
+ throw (new Error('Unrecognized createArguments type'));
64237
+ }
64238
+ }
63496
64239
  }
63497
64240
  toJSON() {
63498
64241
  return ({
63499
64242
  type: this.type,
63500
- identifier: this.identifier
64243
+ identifier: this.identifier,
64244
+ createArguments: __classPrivateFieldGet(this, _BlockOperationCREATE_IDENTIFIER_createArguments, "f")
63501
64245
  });
63502
64246
  }
63503
64247
  }
63504
- _BlockOperationCREATE_IDENTIFIER_identifier = new WeakMap(), _BlockOperationCREATE_IDENTIFIER_instances = new WeakSet(), _BlockOperationCREATE_IDENTIFIER_computeIdentifier = function _BlockOperationCREATE_IDENTIFIER_computeIdentifier(identifierStr) {
64248
+ _BlockOperationCREATE_IDENTIFIER_identifier = new WeakMap(), _BlockOperationCREATE_IDENTIFIER_createArguments = new WeakMap(), _BlockOperationCREATE_IDENTIFIER_instances = new WeakSet(), _BlockOperationCREATE_IDENTIFIER_computeIdentifier = function _BlockOperationCREATE_IDENTIFIER_computeIdentifier(identifierStr) {
63505
64249
  const account = this.computeTo(identifierStr, true);
63506
64250
  if (account.keyType === account_1.AccountKeyAlgorithm.NETWORK) {
63507
64251
  throw (new Error('BlockOperationCREATE_IDENTIFIER must have a non-network identifier account'));
63508
64252
  }
63509
- // XXX:TODO Remove this once multisig account metadata is done
63510
- if (account.keyType === account_1.AccountKeyAlgorithm.MULTISIG) {
63511
- throw (new Error('Multisig accounts currently not supported'));
63512
- }
63513
64253
  return (account);
64254
+ }, _BlockOperationCREATE_IDENTIFIER_computeCreateArguments = function _BlockOperationCREATE_IDENTIFIER_computeCreateArguments(input) {
64255
+ if (input === undefined) {
64256
+ return (undefined);
64257
+ }
64258
+ if (input.type === account_1.AccountKeyAlgorithm.MULTISIG) {
64259
+ return ({
64260
+ type: account_1.AccountKeyAlgorithm.MULTISIG,
64261
+ quorum: BigInt(input.quorum),
64262
+ signers: input.signers.map(function (signerInput) {
64263
+ const signer = account_1.default.toAccount(signerInput);
64264
+ if (!signer.isMultisig() && !signer.isAccount()) {
64265
+ throw (new block_1.default('BLOCK_INVALID_CREATE_IDENTIFIER_ARGS', 'Unsupported key type for multisig signer'));
64266
+ }
64267
+ return (signer);
64268
+ })
64269
+ });
64270
+ }
64271
+ else {
64272
+ throw (new block_1.default('BLOCK_INVALID_CREATE_IDENTIFIER_ARGS', 'Unsupported key type for identifier creation args'));
64273
+ }
63514
64274
  };
63515
64275
  BlockOperationCREATE_IDENTIFIER.isInstance = (0, helper_1.checkableGenerator)(BlockOperationCREATE_IDENTIFIER);
63516
64276
  class BlockOperationSET_INFO extends BlockOperation {
@@ -63767,7 +64527,7 @@ class BlockOperationTOKEN_ADMIN_SUPPLY extends BlockOperation {
63767
64527
  }
63768
64528
  }
63769
64529
  _BlockOperationTOKEN_ADMIN_SUPPLY_amount = new WeakMap(), _BlockOperationTOKEN_ADMIN_SUPPLY_method = new WeakMap(), _BlockOperationTOKEN_ADMIN_SUPPLY_instances = new WeakSet(), _BlockOperationTOKEN_ADMIN_SUPPLY_computeSupplyMethod = function _BlockOperationTOKEN_ADMIN_SUPPLY_computeSupplyMethod(method) {
63770
- const numericMethod = (0, _1.assertAdjustMethod)(method, true);
64530
+ const numericMethod = (0, _1.toAdjustMethod)(method);
63771
64531
  if (numericMethod === _2.default.AdjustMethod.SET) {
63772
64532
  throw (new Error('Cannot use AdjustMethod.SET on a TOKEN_ADMIN_SUPPLY operation'));
63773
64533
  }
@@ -63925,7 +64685,7 @@ _BlockOperationMANAGE_CERTIFICATE_certificateOrHash = new WeakMap(), _BlockOpera
63925
64685
  }
63926
64686
  return (bundleObject);
63927
64687
  }, _BlockOperationMANAGE_CERTIFICATE_computeCertificateMethod = function _BlockOperationMANAGE_CERTIFICATE_computeCertificateMethod(method) {
63928
- const numericMethod = (0, _1.assertAdjustMethod)(method, true);
64688
+ const numericMethod = (0, _1.toAdjustMethod)(method);
63929
64689
  if (numericMethod === _2.default.AdjustMethod.SET) {
63930
64690
  throw (new Error('Cannot use AdjustMethod.SET on a MANAGE_CERTIFICATE operation.'));
63931
64691
  }
@@ -63993,11 +64753,30 @@ function ExportBlockOperations(operations) {
63993
64753
  }
63994
64754
  // We want to be able to read any key on the operation, so we need to cast it to any
63995
64755
  const unTypedEntry = entry;
63996
- for (const { name: key } of operationSchema) {
64756
+ for (const { name: key, schema } of operationSchema) {
63997
64757
  let valueToWrite = unTypedEntry[key];
63998
64758
  if (valueToWrite === undefined) {
64759
+ if (typeof schema === 'object' && schema && !('optional' in schema)) {
64760
+ throw (new Error(`Key ${key} for operation ${typeStr} is not optional but undefined value provided`));
64761
+ }
63999
64762
  continue;
64000
64763
  }
64764
+ else if (typeStr === 'CREATE_IDENTIFIER' && key === 'createArguments') {
64765
+ // We are checking this in other places, and if this argument changes there will be many other things that break beforehand
64766
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
64767
+ const typedValue = valueToWrite;
64768
+ valueToWrite = {
64769
+ type: 'context',
64770
+ kind: 'explicit',
64771
+ value: valueToWrite.type,
64772
+ contains: [
64773
+ typedValue.signers.map(function (signer) {
64774
+ return (signer.publicKeyAndType);
64775
+ }),
64776
+ typedValue.quorum
64777
+ ]
64778
+ };
64779
+ }
64001
64780
  else if (typeof valueToWrite === 'string') {
64002
64781
  valueToWrite = { type: 'string', kind: 'utf8', value: valueToWrite };
64003
64782
  }
@@ -64034,29 +64813,13 @@ function ImportOperationsASN1(input, network) {
64034
64813
  const retval = [];
64035
64814
  for (const entryWrapper of input) {
64036
64815
  const operation = {};
64037
- if (typeof entryWrapper !== 'object' || entryWrapper === null) {
64038
- throw (new Error(`Found entry which is not a context ${String(entryWrapper)}`));
64039
- }
64040
- if (!('type' in entryWrapper) || entryWrapper.type !== 'context') {
64041
- throw (new Error(`Found entry which is not a context ${String(entryWrapper)}`));
64042
- }
64043
- if (!('kind' in entryWrapper) || entryWrapper.kind !== 'explicit') {
64044
- throw (new Error(`Found entry which is not an explicit context ${String(entryWrapper)}`));
64045
- }
64046
- if (!('value' in entryWrapper)) {
64047
- throw (new Error(`Found entry which is not a numeric explicit context ${String(entryWrapper)}`));
64048
- }
64049
- const typeInput = entryWrapper.value;
64050
- if (typeof typeInput !== 'number') {
64051
- throw (new Error(`Found entry which is not a numeric explicit context ${String(entryWrapper)}`));
64052
- }
64053
- const type = assertOperationType(typeInput);
64054
- if (!('contains' in entryWrapper)) {
64055
- throw (new Error(`Found entry which which lacks contains ${JSON.stringify(entryWrapper)}`));
64816
+ if (!asn1_1.ASN1CheckUtilities.isASN1ContextTag(entryWrapper, 'explicit')) {
64817
+ throw (new Error('Invalid createArgs type for CREATE_IDENTIFIER operation'));
64056
64818
  }
64819
+ const type = assertOperationType(entryWrapper.value);
64057
64820
  const entry = entryWrapper.contains;
64058
64821
  if (!Array.isArray(entry)) {
64059
- throw (new Error(`Found entry which is not a Sequence ${entry}`));
64822
+ throw (new Error(`Found entry which is not a Sequence ${typeof entry}`));
64060
64823
  }
64061
64824
  const typeStr = operationTypeToString(type);
64062
64825
  const operationSchema = BlockOperationASN1SchemaBase[typeStr];
@@ -64088,6 +64851,30 @@ function ImportOperationsASN1(input, network) {
64088
64851
  newKeyValue.validate(network);
64089
64852
  keyValueOut = newKeyValue;
64090
64853
  }
64854
+ else if (key === 'createArguments' && typeStr === 'CREATE_IDENTIFIER') {
64855
+ if (!asn1_1.ASN1CheckUtilities.isASN1ContextTag(keyValueIn, 'explicit')) {
64856
+ throw (new Error('Invalid createArgs type for CREATE_IDENTIFIER operation'));
64857
+ }
64858
+ if (keyValueIn.value !== account_1.AccountKeyAlgorithm.MULTISIG) {
64859
+ throw (new Error('unrecognized type for multisig create arguments'));
64860
+ }
64861
+ if (!Array.isArray(keyValueIn.contains) || keyValueIn.contains.length !== 2) {
64862
+ throw (new Error('Invalid createArgs container'));
64863
+ }
64864
+ if (!Array.isArray(keyValueIn.contains[0])) {
64865
+ throw (new Error('Invalid createArgs container'));
64866
+ }
64867
+ keyValueOut = {
64868
+ type: keyValueIn.value,
64869
+ signers: keyValueIn.contains[0].map(function (value) {
64870
+ if (!Buffer.isBuffer(value)) {
64871
+ throw (new Error(`Invalid signer value, expected Buffer, got ${typeof value}`));
64872
+ }
64873
+ return (account_1.default.fromPublicKeyAndType(value));
64874
+ }),
64875
+ quorum: keyValueIn.contains[1]
64876
+ };
64877
+ }
64091
64878
  else if (Array.isArray(keyValueIn) && key === 'intermediateCertificates') {
64092
64879
  keyValueOut = new certificate_1.CertificateBundle(keyValueIn.map(function (certificate) {
64093
64880
  return (new certificate_1.Certificate(certificate));
@@ -64095,7 +64882,7 @@ function ImportOperationsASN1(input, network) {
64095
64882
  }
64096
64883
  else if ((0, helper_1.isBuffer)(keyValueIn)) {
64097
64884
  if (type === OperationType.MANAGE_CERTIFICATE && key === 'certificateOrHash') {
64098
- const method = (0, _1.assertAdjustMethod)(operation['method'], true);
64885
+ const method = (0, _1.toAdjustMethod)(operation['method']);
64099
64886
  if (method === _2.AdjustMethod.SUBTRACT) {
64100
64887
  keyValueOut = new certificate_1.CertificateHash(keyValueIn);
64101
64888
  }
@@ -64187,6 +64974,13 @@ const BlockErrorCodes = [
64187
64974
  'ONLY_IDENTIFIER_OP',
64188
64975
  'NO_TOKEN_OP',
64189
64976
  'NO_IDENTIFIER_OP',
64977
+ 'INVALID_SIGNER',
64978
+ 'INVALID_PURPOSE_VALIDATION',
64979
+ 'INVALID_MULTISIG_QUORUM',
64980
+ 'INVALID_MULTISIG_SIGNER_DEPTH',
64981
+ 'INVALID_MULTISIG_SIGNER_COUNT',
64982
+ 'INVALID_MULTISIG_SIGNER_DUPLICATE',
64983
+ 'INVALID_CREATE_IDENTIFIER_ARGS',
64190
64984
  'NO_MULTISIG_OP',
64191
64985
  'IDENTIFIER_INVALID',
64192
64986
  'GENERAL_FIELD_INVALID',
@@ -64234,7 +65028,17 @@ const BlockErrorCodes = [
64234
65028
  'DUPLICATE_INCLUDED',
64235
65029
  'ORPHAN_FOUND',
64236
65030
  'CYCLE_FOUND',
64237
- 'SECONDARY_GRAPH'
65031
+ 'SECONDARY_GRAPH',
65032
+ 'MISSING_FIELD',
65033
+ 'SIGNATURE_ALGORITHM_MISMATCH',
65034
+ 'SELF_SIGNED_VALIDATION_FAILED',
65035
+ 'CHAIN_VERIFICATION_FAILED',
65036
+ 'DUPLICATE_EXTENSION',
65037
+ 'EXTENSION_NOT_PROCESSED',
65038
+ 'INVALID_SIGNATURE_ALGORITHM',
65039
+ 'INVALID_GRAPH_COUNT',
65040
+ 'MOMENT_INVALID',
65041
+ 'INVALID_VERSION'
64238
65042
  ];
64239
65043
  class KeetaNetCertificateError extends _1.KeetaNetError {
64240
65044
  constructor(code, message) {
@@ -64326,6 +65130,7 @@ const _1 = __webpack_require__(5390);
64326
65130
  const helper_1 = __webpack_require__(3208);
64327
65131
  const LedgerErrorType = 'LEDGER';
64328
65132
  const LedgerErrorCodes = [
65133
+ 'BLOCK_ALREADY_EXISTS',
64329
65134
  'TRANSACTION_ABORTED',
64330
65135
  'INVALID_CHAIN',
64331
65136
  'INVALID_NETWORK',
@@ -64347,7 +65152,16 @@ const LedgerErrorCodes = [
64347
65152
  'BLOCKS_DIFFER_FROM_VOTED_ON',
64348
65153
  'NO_PERM_WITHOUT_SELF_TEMP',
64349
65154
  'DUPLICATE_VOTE_ISSUER_FOUND',
64350
- 'OTHER'
65155
+ 'OTHER',
65156
+ 'MISSING_BLOCKS',
65157
+ // Fee Errors
65158
+ 'FEE_AMOUNT_MISMATCH',
65159
+ 'FEE_TOKEN_MISMATCH',
65160
+ 'FEE_MISSING',
65161
+ 'MISSING_REQUIRED_FEE_BLOCK',
65162
+ 'PERM_VOTE_WITH_QUOTE',
65163
+ 'QUOTE_MISMATCH',
65164
+ 'REQUIRED_FEE_MISMATCH'
64351
65165
  ];
64352
65166
  class KeetaNetLedgerError extends _1.KeetaNetError {
64353
65167
  constructor(code, message, shouldRetry = false, retryDelay) {
@@ -64479,7 +65293,13 @@ const VoteErrorCodes = [
64479
65293
  'MALFORMED_FEES_FROM_VOTE_INVALID_INPUT',
64480
65294
  'MALFORMED_FEES_IN_PERMANENT_VOTE',
64481
65295
  'MALFORMED_FEES_PAY_TO_INVALID',
64482
- 'MALFORMED_FEES_TOKEN_NOT_TOKEN'
65296
+ 'MALFORMED_FEES_TOKEN_NOT_TOKEN',
65297
+ // Fee Quote Errors
65298
+ 'FEE_IS_QUOTE',
65299
+ 'FEE_QUOTE_MISSING_FEES',
65300
+ 'FEE_NOT_QUOTE',
65301
+ 'MALFORMED_FEES_KIND_MISSING',
65302
+ 'MALFORMED_FEES_QUOTE_INVALID'
64483
65303
  ];
64484
65304
  class KeetaNetVoteError extends _1.KeetaNetError {
64485
65305
  constructor(code, message) {
@@ -64835,6 +65655,8 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
64835
65655
  exports.LedgerStorageBase = void 0;
64836
65656
  exports.findPermissionMatch = findPermissionMatch;
64837
65657
  exports.validateSupply = validateSupply;
65658
+ exports.validateBlockSignerCount = validateBlockSignerCount;
65659
+ exports.validateBlockSignerDepth = validateBlockSignerDepth;
64838
65660
  exports.computeLedgerEffect = computeLedgerEffect;
64839
65661
  exports.addTimeStatistic = addTimeStatistic;
64840
65662
  exports.assertLedgerStorage = assertLedgerStorage;
@@ -64842,6 +65664,7 @@ const account_1 = __importStar(__webpack_require__(9415));
64842
65664
  const block_1 = __webpack_require__(6158);
64843
65665
  const permissions_1 = __webpack_require__(5860);
64844
65666
  const ledger_1 = __importDefault(__webpack_require__(452));
65667
+ const helper_1 = __webpack_require__(3208);
64845
65668
  const config_1 = __webpack_require__(1491);
64846
65669
  const block_2 = __importDefault(__webpack_require__(7412));
64847
65670
  function findPermissionMatch(lookingFor, entries) {
@@ -64873,6 +65696,18 @@ function validateSupply(amount, network) {
64873
65696
  throw (new block_2.default('BLOCK_SUPPLY_INVALID', `supply does not fit proper format -- GOT: '${amount}' MaxValue: ${maxValue}`));
64874
65697
  }
64875
65698
  }
65699
+ function validateBlockSignerCount(amount, network) {
65700
+ const { maxValue } = (0, config_1.getValidation)(network).accountInfoFieldRules['blockSignerCount'];
65701
+ if (amount > maxValue || amount < 1n) {
65702
+ throw (new block_2.default('BLOCK_INVALID_MULTISIG_SIGNER_COUNT', `signer count does not fit proper format -- GOT: '${amount}' MaxValue: ${maxValue}`));
65703
+ }
65704
+ }
65705
+ function validateBlockSignerDepth(depth, network) {
65706
+ const { maxValue } = (0, config_1.getValidation)(network).accountInfoFieldRules['blockSignerDepth'];
65707
+ if (depth > maxValue) {
65708
+ throw (new block_2.default('BLOCK_INVALID_MULTISIG_SIGNER_DEPTH', `signer depth does not fit proper format -- GOT: '${depth}' MaxValue: ${maxValue}`));
65709
+ }
65710
+ }
64876
65711
  /**
64877
65712
  * Compute effects on the ledger from block effects
64878
65713
  */
@@ -65274,6 +66109,16 @@ class LedgerStorageBase {
65274
66109
  })));
65275
66110
  }
65276
66111
  async preAdjust(input, mayDefer = true, transaction) {
66112
+ const allBlockHeightsToFetch = input.blocks.map(block => {
66113
+ return ({ blockHash: block.hash, account: block.account });
66114
+ });
66115
+ const allBlockHeights = await this.getBlockHeights(transaction, allBlockHeightsToFetch);
66116
+ // Check if any blocks already exist on the ledger that would cause this staple to fail and exit early
66117
+ for (const [blockHash, blockHeight] of Object.entries(allBlockHeights)) {
66118
+ if (blockHeight !== null) {
66119
+ throw (new ledger_1.default('LEDGER_BLOCK_ALREADY_EXISTS', `Block Already Exists: ${blockHash.toString()}`));
66120
+ }
66121
+ }
65277
66122
  const seenBlockHashes = new block_1.BlockHash.Set();
65278
66123
  const blockHeights = {};
65279
66124
  const toFetch = [];
@@ -65335,18 +66180,24 @@ class LedgerStorageBase {
65335
66180
  }
65336
66181
  ret.defaultPermission = new permissions_1.Permissions(baseSet, externalSet);
65337
66182
  }
65338
- if (account.keyType === account_1.AccountKeyAlgorithm.TOKEN) {
66183
+ if (account.isToken()) {
65339
66184
  ret.supply = BigInt(row.supply ?? 0);
65340
66185
  }
66186
+ if (account.isMultisig() && row.multisigQuorum !== undefined) {
66187
+ ret.multisigQuorum = BigInt(row.multisigQuorum);
66188
+ }
65341
66189
  return (ret);
65342
66190
  }
65343
66191
  _validateAccountInfoKeys(account, info) {
65344
66192
  const validKeys = ['name', 'description', 'metadata'];
65345
66193
  if (account.isIdentifier()) {
65346
66194
  validKeys.push('defaultPermission');
65347
- }
65348
- if (account.keyType === account_1.AccountKeyAlgorithm.TOKEN) {
65349
- validKeys.push('supply');
66195
+ if (account.isToken()) {
66196
+ validKeys.push('supply');
66197
+ }
66198
+ if (account.isMultisig()) {
66199
+ validKeys.push('multisigQuorum');
66200
+ }
65350
66201
  }
65351
66202
  const keys = Object.keys(info);
65352
66203
  const foundBannedKey = keys.find(function (key) {
@@ -65356,6 +66207,33 @@ class LedgerStorageBase {
65356
66207
  throw (new ledger_1.default('LEDGER_INVALID_ACCOUNT_INFO_KEY', `Invalid AccountInfo field ${foundBannedKey}`));
65357
66208
  }
65358
66209
  }
66210
+ /**
66211
+ * @param moment - The date to use as the base for the timestamp.
66212
+ * @param momentBits - The number of bits to use for the timestamp
66213
+ * @param totalLength - The total length of the generated number in bits
66214
+ * @param randomData - A hexadecimal string to use as the random data.
66215
+ * @param timestampFuzzMS - The number of milliseconds to fuzz the timestamp by, defaults to 1n (precise).
66216
+ * @param optimistic - If true, the timestamp will be incremented by 1 quanta, defaults to false.
66217
+ * @returns A bigint representing the noisy timestamp.
66218
+ */
66219
+ _generateNoisyTimestamp(moment, momentBits, totalLength, randomData, timestampFuzzMS = 1, optimistic = false) {
66220
+ if (timestampFuzzMS > Number.MAX_SAFE_INTEGER) {
66221
+ throw (new Error('timestampFuzzMs is too large'));
66222
+ }
66223
+ const timestampFuzz = BigInt(Math.ceil(Math.log2(Number(timestampFuzzMS))));
66224
+ const length = totalLength - momentBits;
66225
+ if (BigInt(randomData.length * 8) < (length + timestampFuzz)) {
66226
+ throw (new Error('randomData is too short for the specified bit length'));
66227
+ }
66228
+ if (length < 0n) {
66229
+ throw (new Error('momentBits should be less than totalLength'));
66230
+ }
66231
+ const timestamp = BigInt(moment.valueOf()) >> timestampFuzz;
66232
+ const mask = (1n << (length + timestampFuzz)) - 1n;
66233
+ const upperBits = (timestamp + (optimistic ? 1n : 0n)) << (length + timestampFuzz);
66234
+ const lowerBits = (0, helper_1.bufferToBigInt)(randomData) & mask;
66235
+ return (upperBits | lowerBits);
66236
+ }
65359
66237
  async getHeadBlock(transaction, account, from) {
65360
66238
  const response = await this.getHeadBlocks(transaction, [account], from);
65361
66239
  const pubKey = account.publicKeyString.get();
@@ -65372,9 +66250,9 @@ class LedgerStorageBase {
65372
66250
  }
65373
66251
  return (null);
65374
66252
  }
65375
- async gc(transaction) {
66253
+ async gc(transaction, timeLimitMS = 280000) {
65376
66254
  let lastGCResult = false;
65377
- for (const startTime = Date.now(); Date.now() - startTime < 280000;) {
66255
+ for (const startTime = Date.now(); Date.now() - startTime < timeLimitMS;) {
65378
66256
  const gcResult = await this.gcBatch(transaction);
65379
66257
  lastGCResult = gcResult;
65380
66258
  if (!gcResult) {
@@ -65434,8 +66312,38 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
65434
66312
  exports.computeEffectOfBlocks = computeEffectOfBlocks;
65435
66313
  const account_1 = __importStar(__webpack_require__(9415));
65436
66314
  const block_1 = __webpack_require__(6158);
66315
+ const operations_1 = __webpack_require__(2778);
65437
66316
  const permissions_1 = __webpack_require__(5860);
65438
66317
  const certificate_1 = __webpack_require__(5661);
66318
+ ;
66319
+ /**
66320
+ * Base Fee Units per Block
66321
+ */
66322
+ const baseBlockFeeUnit = 1000n;
66323
+ /**
66324
+ * Fee Unit for an Opening Block
66325
+ */
66326
+ const openingBlockFeeUnit = 10000n;
66327
+ /**
66328
+ * Operation specific Fee Units
66329
+ */
66330
+ const operationFeeUnitOverrides = {
66331
+ [operations_1.OperationType.SEND]: 10n,
66332
+ [operations_1.OperationType.SET_REP]: 20n,
66333
+ [operations_1.OperationType.SET_INFO]: 100n,
66334
+ [operations_1.OperationType.MODIFY_PERMISSIONS]: 20n,
66335
+ [operations_1.OperationType.CREATE_IDENTIFIER]: 200n,
66336
+ [operations_1.OperationType.TOKEN_ADMIN_SUPPLY]: 10n,
66337
+ [operations_1.OperationType.TOKEN_ADMIN_MODIFY_BALANCE]: 10n,
66338
+ [operations_1.OperationType.RECEIVE]: 10n,
66339
+ [operations_1.OperationType.MANAGE_CERTIFICATE]: 100n
66340
+ };
66341
+ /**
66342
+ * Get the Fee Unit for a given operation type
66343
+ */
66344
+ function getOperationFeeUnit(operation) {
66345
+ return (operationFeeUnitOverrides[operation]);
66346
+ }
65439
66347
  function addOrCombineRequirements(existing, addition, alwaysCombine) {
65440
66348
  const resp = [...existing];
65441
66349
  let additionTarget;
@@ -65538,6 +66446,19 @@ function addPermissionRequirement(state, requirement) {
65538
66446
  const existing = state.accounts[principalPubKey].fields.permissionRequirements ?? [];
65539
66447
  state.accounts[principalPubKey].fields.permissionRequirements = addOrCombineRequirements(existing, requirement, true);
65540
66448
  }
66449
+ function updateMinSignerSetLength(state, multisigAccount, count) {
66450
+ const multisigPublicKey = multisigAccount.publicKeyString.get();
66451
+ if (state.accounts[multisigPublicKey] === undefined) {
66452
+ state.accounts[multisigPublicKey] = {
66453
+ account: multisigAccount,
66454
+ fields: {}
66455
+ };
66456
+ }
66457
+ const current = state.accounts[multisigPublicKey].fields.minSignerSetLength;
66458
+ if (current === undefined || current > count) {
66459
+ state.accounts[multisigPublicKey].fields.minSignerSetLength = count;
66460
+ }
66461
+ }
65541
66462
  function modifyBalanceInState(balanceState) {
65542
66463
  const { state, account, token, method, amount, otherAccount } = balanceState;
65543
66464
  const accountPubKey = account.publicKeyString.get();
@@ -65582,6 +66503,32 @@ function modifyBalanceInState(balanceState) {
65582
66503
  }
65583
66504
  accountBalanceInfo[tokenPubKey] = tokenField;
65584
66505
  }
66506
+ function updateAccountInfoInState(state, account, info) {
66507
+ const accountPubKey = account.publicKeyString.get();
66508
+ const toUpdate = {
66509
+ name: info.name,
66510
+ description: info.description,
66511
+ metadata: info.metadata
66512
+ };
66513
+ if (account.isIdentifier()) {
66514
+ if (info.defaultPermission !== undefined) {
66515
+ toUpdate.defaultPermission = info.defaultPermission;
66516
+ }
66517
+ if (account.isMultisig() && info.multisigQuorum !== undefined) {
66518
+ toUpdate.multisigQuorum = info.multisigQuorum;
66519
+ }
66520
+ }
66521
+ else {
66522
+ state.possibleNewAccounts.add(account);
66523
+ }
66524
+ if (!state.accounts[accountPubKey]) {
66525
+ state.accounts[accountPubKey] = {
66526
+ account: account,
66527
+ fields: {}
66528
+ };
66529
+ }
66530
+ state.accounts[accountPubKey].fields.info = toUpdate;
66531
+ }
65585
66532
  /**
65586
66533
  * Compute the effect of a SEND operation
65587
66534
  */
@@ -65709,34 +66656,39 @@ function computeEffectOfOperationCREATE_IDENTIFIER(state, block, operation, cont
65709
66656
  }
65710
66657
  state.possibleNewAccounts.add(operation.identifier);
65711
66658
  state.accounts[accountPubKey].fields.createRequests?.push({
65712
- previousBlockHash: block.previous,
65713
- account: block.account,
65714
- requestedIdentifier: operation.identifier,
65715
- operationIndex: context.operationIndex
65716
- });
65717
- addPermission(state, {
65718
- principal: block.account,
65719
- entity: operation.identifier,
65720
- method: block_1.Block.AdjustMethod.SET,
65721
- permissions: new permissions_1.Permissions(['OWNER'])
66659
+ createdIdentifier: operation.identifier,
66660
+ createArguments: operation.createArguments
65722
66661
  });
65723
- }
65724
- function computeEffectOfOperationSET_INFO(state, block, operation) {
65725
- const accountPubKey = block.account.publicKeyString.get();
65726
- const toUpdate = {
65727
- name: operation.name,
65728
- description: operation.description,
65729
- metadata: operation.metadata
65730
- };
65731
- if (block.account.isIdentifier()) {
65732
- if (operation.defaultPermission !== undefined) {
65733
- toUpdate.defaultPermission = operation.defaultPermission;
66662
+ if (operation.identifier.isMultisig()) {
66663
+ if (!operation.createArguments || operation.createArguments.type !== account_1.AccountKeyAlgorithm.MULTISIG) {
66664
+ throw (new Error('Invalid identifier creation arguments'));
66665
+ }
66666
+ updateAccountInfoInState(state, operation.identifier, { multisigQuorum: operation.createArguments.quorum });
66667
+ for (const multisigSigner of operation.createArguments.signers) {
66668
+ addPermission(state, {
66669
+ principal: multisigSigner,
66670
+ entity: operation.identifier,
66671
+ method: block_1.Block.AdjustMethod.SET,
66672
+ permissions: new permissions_1.Permissions(['MULTISIG_SIGNER'])
66673
+ });
65734
66674
  }
65735
66675
  }
65736
66676
  else {
65737
- state.possibleNewAccounts.add(block.account);
66677
+ addPermission(state, {
66678
+ principal: block.account,
66679
+ entity: operation.identifier,
66680
+ method: block_1.Block.AdjustMethod.SET,
66681
+ permissions: new permissions_1.Permissions(['OWNER'])
66682
+ });
65738
66683
  }
65739
- state.accounts[accountPubKey].fields.info = toUpdate;
66684
+ }
66685
+ function computeEffectOfOperationSET_INFO(state, block, operation) {
66686
+ updateAccountInfoInState(state, block.account, {
66687
+ name: operation.name,
66688
+ description: operation.description,
66689
+ metadata: operation.metadata,
66690
+ defaultPermission: operation.defaultPermission
66691
+ });
65740
66692
  }
65741
66693
  function computeEffectOfOperationMODIFY_PERMISSIONS(state, block, operation) {
65742
66694
  state.possibleNewAccounts.add(operation.principal);
@@ -65977,7 +66929,7 @@ function computePermissionEffect(state, type, effect, block, operation, context)
65977
66929
  };
65978
66930
  switch (type) {
65979
66931
  case 'SIGNER':
65980
- baseRequirement.principal = block.signer;
66932
+ baseRequirement.principal = block.principal;
65981
66933
  baseRequirement.entity = block.account;
65982
66934
  break;
65983
66935
  case 'ACCOUNT':
@@ -66033,7 +66985,8 @@ function computeEffectOfBlocks(blocks, ledger) {
66033
66985
  possibleNewAccounts: new account_1.default.Set(),
66034
66986
  metadata: {
66035
66987
  blockCount: 0,
66036
- operationCount: 0
66988
+ operationCount: 0,
66989
+ feeUnits: 0n
66037
66990
  }
66038
66991
  };
66039
66992
  let onlyReturnTouched = false;
@@ -66048,13 +67001,26 @@ function computeEffectOfBlocks(blocks, ledger) {
66048
67001
  */
66049
67002
  for (const block of blocks) {
66050
67003
  accumulatedEffects.metadata.blockCount++;
67004
+ accumulatedEffects.metadata.feeUnits += baseBlockFeeUnit;
66051
67005
  const blockAccountPubKey = block.account.publicKeyString.get();
66052
- accumulatedEffects.touched.add(block.signer);
67006
+ const signerQueue = [block.signer];
67007
+ while (signerQueue.length > 0) {
67008
+ // We can assume that the signerFieldQueue is not empty here since the loop condition checks it
67009
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67010
+ const signer = signerQueue.shift();
67011
+ if (account_1.default.isInstance(signer)) {
67012
+ accumulatedEffects.touched.add(signer);
67013
+ continue;
67014
+ }
67015
+ accumulatedEffects.touched.add(signer[0]);
67016
+ signerQueue.push(...signer[1]);
67017
+ }
66053
67018
  if (block.$opening) {
66054
67019
  accumulatedEffects.possibleNewAccounts.add(block.account);
67020
+ accumulatedEffects.metadata.feeUnits += openingBlockFeeUnit;
66055
67021
  }
66056
- if (!(block.signer.comparePublicKey(block.account))) {
66057
- accumulatedEffects.possibleNewAccounts.add(block.signer);
67022
+ if (!(block.principal.comparePublicKey(block.account))) {
67023
+ accumulatedEffects.possibleNewAccounts.add(block.principal);
66058
67024
  }
66059
67025
  if (accumulatedEffects.accounts[blockAccountPubKey] === undefined) {
66060
67026
  accumulatedEffects.accounts[blockAccountPubKey] = {
@@ -66069,12 +67035,13 @@ function computeEffectOfBlocks(blocks, ledger) {
66069
67035
  const context = {
66070
67036
  ledger,
66071
67037
  operationIndex: Number(operationIndex),
66072
- signedByDifferent: !block.account.comparePublicKey(block.signer),
67038
+ signedByDifferent: !block.account.comparePublicKey(block.principal),
66073
67039
  openingBlock: block.$opening
66074
67040
  };
66075
67041
  const operation = block.operations[operationIndex];
66076
67042
  const handler = operationHandlers[operation.type];
66077
67043
  accumulatedEffects.metadata.operationCount++;
67044
+ accumulatedEffects.metadata.feeUnits += getOperationFeeUnit(operation.type);
66078
67045
  if (handler.accountPermissionACL) {
66079
67046
  computePermissionEffect(accumulatedEffects, 'ACCOUNT', handler.accountPermissionACL, block, operation, context);
66080
67047
  }
@@ -66084,6 +67051,30 @@ function computeEffectOfBlocks(blocks, ledger) {
66084
67051
  permissionEffect = handler.signerPermissionACL;
66085
67052
  }
66086
67053
  computePermissionEffect(accumulatedEffects, 'SIGNER', permissionEffect, block, operation, context);
67054
+ if (Array.isArray(block.signer)) {
67055
+ const signerFieldQueue = [block.signer];
67056
+ while (signerFieldQueue.length > 0) {
67057
+ // We can assume that the signerFieldQueue is not empty here since the loop condition checks it
67058
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67059
+ const [multisig, signers] = signerFieldQueue.shift();
67060
+ updateMinSignerSetLength(accumulatedEffects, multisig, BigInt(signers.length));
67061
+ for (const signer of signers) {
67062
+ let principal;
67063
+ if (account_1.default.isInstance(signer)) {
67064
+ principal = signer;
67065
+ }
67066
+ else {
67067
+ principal = signer[0];
67068
+ signerFieldQueue.push(signer);
67069
+ }
67070
+ addPermissionRequirement(accumulatedEffects, {
67071
+ entity: multisig,
67072
+ principal: principal,
67073
+ permissions: new permissions_1.Permissions(['MULTISIG_SIGNER'])
67074
+ });
67075
+ }
67076
+ }
67077
+ }
66087
67078
  }
66088
67079
  handler.effectGenerator(accumulatedEffects, block, operation, context);
66089
67080
  }
@@ -66197,9 +67188,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
66197
67188
  var __importDefault = (this && this.__importDefault) || function (mod) {
66198
67189
  return (mod && mod.__esModule) ? mod : { "default": mod };
66199
67190
  };
66200
- var _LedgerAtomicInterface_instances, _LedgerAtomicInterface_network, _LedgerAtomicInterface_subnet, _LedgerAtomicInterface_kind, _LedgerAtomicInterface_privateKey, _LedgerAtomicInterface_storage, _LedgerAtomicInterface_transaction, _LedgerAtomicInterface_ledger, _LedgerAtomicInterface_cache, _LedgerAtomicInterface_assertTransaction, _LedgerAtomicInterface_validateVotingWeight, _LedgerAtomicInterface_listAccountInfo, _LedgerAtomicInterface_checkSingleAccountPermissions, _LedgerAtomicInterface_checkPermissionRequirements, _LedgerAtomicInterface_validateLedgerOutcome, _Ledger_storage, _Ledger_config;
67191
+ var _LedgerAtomicInterface_instances, _LedgerAtomicInterface_network, _LedgerAtomicInterface_subnet, _LedgerAtomicInterface_kind, _LedgerAtomicInterface_privateKey, _LedgerAtomicInterface_computeFeeFromBlocks, _LedgerAtomicInterface_storage, _LedgerAtomicInterface_ledger, _LedgerAtomicInterface_cache, _LedgerAtomicInterface_transaction, _LedgerAtomicInterface_assertTransaction, _LedgerAtomicInterface_validateVotingWeight, _LedgerAtomicInterface_listAccountInfo, _LedgerAtomicInterface_checkSingleAccountPermissions, _LedgerAtomicInterface_checkPermissionRequirements, _LedgerAtomicInterface_validateLedgerOutcome, _LedgerAtomicInterface_validateBlocksForVote, _LedgerAtomicInterface_voteOrQuoteWithFees, _Ledger_storage, _Ledger_config;
66201
67192
  Object.defineProperty(exports, "__esModule", ({ value: true }));
66202
- exports.Ledger = exports.LedgerKind = void 0;
67193
+ exports.Ledger = exports.LedgerStorageTransactionBase = exports.LedgerKind = void 0;
66203
67194
  const vote_1 = __webpack_require__(1130);
66204
67195
  const block_1 = __webpack_require__(6158);
66205
67196
  const account_1 = __importDefault(__webpack_require__(9415));
@@ -66211,6 +67202,8 @@ const effects_1 = __webpack_require__(7346);
66211
67202
  const conversion_1 = __webpack_require__(2360);
66212
67203
  const cache_1 = __importDefault(__webpack_require__(5834));
66213
67204
  const timing_1 = __webpack_require__(2895);
67205
+ const operations_1 = __webpack_require__(2778);
67206
+ const stats_1 = __webpack_require__(2127);
66214
67207
  /**
66215
67208
  * Kind of ledger
66216
67209
  */
@@ -66219,6 +67212,16 @@ var LedgerKind;
66219
67212
  LedgerKind[LedgerKind["REPRESENTATIVE"] = 0] = "REPRESENTATIVE";
66220
67213
  LedgerKind[LedgerKind["ACCOUNT"] = 1] = "ACCOUNT";
66221
67214
  })(LedgerKind || (exports.LedgerKind = LedgerKind = {}));
67215
+ class LedgerStorageTransactionBase {
67216
+ constructor(options) {
67217
+ this.node = options.node;
67218
+ this.moment = options.moment ?? new Date();
67219
+ this.identifier = options.identifier;
67220
+ this.readOnly = options.readOnly ?? true;
67221
+ this.statsPending = new stats_1.StatsPending();
67222
+ }
67223
+ }
67224
+ exports.LedgerStorageTransactionBase = LedgerStorageTransactionBase;
66222
67225
  /**
66223
67226
  * Atomic transactional interface to a storage backend
66224
67227
  */
@@ -66229,14 +67232,16 @@ class LedgerAtomicInterface {
66229
67232
  _LedgerAtomicInterface_subnet.set(this, void 0);
66230
67233
  _LedgerAtomicInterface_kind.set(this, void 0);
66231
67234
  _LedgerAtomicInterface_privateKey.set(this, void 0);
67235
+ _LedgerAtomicInterface_computeFeeFromBlocks.set(this, void 0);
66232
67236
  _LedgerAtomicInterface_storage.set(this, void 0);
66233
- _LedgerAtomicInterface_transaction.set(this, void 0);
66234
67237
  _LedgerAtomicInterface_ledger.set(this, void 0);
66235
67238
  _LedgerAtomicInterface_cache.set(this, void 0);
67239
+ _LedgerAtomicInterface_transaction.set(this, void 0);
66236
67240
  __classPrivateFieldSet(this, _LedgerAtomicInterface_network, config.network, "f");
66237
67241
  __classPrivateFieldSet(this, _LedgerAtomicInterface_subnet, config.subnet, "f");
66238
67242
  __classPrivateFieldSet(this, _LedgerAtomicInterface_kind, config.kind, "f");
66239
67243
  __classPrivateFieldSet(this, _LedgerAtomicInterface_privateKey, config.privateKey, "f");
67244
+ __classPrivateFieldSet(this, _LedgerAtomicInterface_computeFeeFromBlocks, config.computeFeeFromBlocks, "f");
66240
67245
  __classPrivateFieldSet(this, _LedgerAtomicInterface_ledger, ledger, "f");
66241
67246
  __classPrivateFieldSet(this, _LedgerAtomicInterface_storage, storage, "f");
66242
67247
  __classPrivateFieldSet(this, _LedgerAtomicInterface_transaction, transaction, "f");
@@ -66258,22 +67263,34 @@ class LedgerAtomicInterface {
66258
67263
  const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66259
67264
  __classPrivateFieldSet(this, _LedgerAtomicInterface_transaction, null, "f");
66260
67265
  await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").commitTransaction(transaction);
67266
+ __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").node?.stats.merge(transaction.statsPending);
66261
67267
  }
66262
67268
  async abort() {
66263
67269
  const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66264
67270
  __classPrivateFieldSet(this, _LedgerAtomicInterface_transaction, null, "f");
66265
67271
  await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").abortTransaction(transaction);
66266
67272
  }
66267
- async vote(blocks, otherVotes) {
66268
- const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66269
- if (__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode !== 'read-write') {
66270
- throw (new Error(`May not issue votes in read-only mode, in ${__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode} mode`));
67273
+ async vote(blocks, otherVotes, quote) {
67274
+ if (blocks.length === 0) {
67275
+ throw (new ledger_1.default('LEDGER_MISSING_BLOCKS', 'At least one block is required to issue a vote'));
66271
67276
  }
66272
67277
  if (!__classPrivateFieldGet(this, _LedgerAtomicInterface_privateKey, "f")) {
66273
67278
  throw (new Error('Cannot vote on block, no private key loaded'));
66274
67279
  }
67280
+ if (__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode !== 'read-write') {
67281
+ throw (new Error(`May not issue votes in read-only mode, in ${__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode} mode`));
67282
+ }
66275
67283
  const privateKey = __classPrivateFieldGet(this, _LedgerAtomicInterface_privateKey, "f");
66276
67284
  const ledgerPubKey = privateKey.publicKeyString.get();
67285
+ if (quote !== undefined) {
67286
+ if (otherVotes !== undefined) {
67287
+ throw (new ledger_1.default('LEDGER_PERM_VOTE_WITH_QUOTE', 'Quote should not be included when requesting permanent votes'));
67288
+ }
67289
+ if (!quote.issuer.comparePublicKey(ledgerPubKey)) {
67290
+ throw (new ledger_1.default('LEDGER_QUOTE_MISMATCH', 'Provided quote does not match issuer public key'));
67291
+ }
67292
+ }
67293
+ const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66277
67294
  /**
66278
67295
  * If there are other votes, ensure one of them was issued by
66279
67296
  * us and the blocks are in the same order as the set of
@@ -66283,7 +67300,18 @@ class LedgerAtomicInterface {
66283
67300
  let foundOurVote = false;
66284
67301
  const seenVoteUIDs = new Set();
66285
67302
  const seenVoteIssuers = new account_1.default.Set();
67303
+ const possibleFeeBlock = blocks.at(-1);
67304
+ let hasFeeBlock = false;
67305
+ let blockCount = blocks.length;
67306
+ if (possibleFeeBlock?.purpose === block_1.BlockPurpose.FEE) {
67307
+ hasFeeBlock = true;
67308
+ blockCount--;
67309
+ }
67310
+ const requiredFees = new Map();
66286
67311
  for (const checkVote of otherVotes) {
67312
+ if (checkVote.quote === true) {
67313
+ throw (new ledger_1.default('LEDGER_PERM_VOTE_WITH_QUOTE', 'Cannot request permanent votes with quotes'));
67314
+ }
66287
67315
  if (seenVoteUIDs.has(checkVote.$id)) {
66288
67316
  throw (new ledger_1.default('LEDGER_DUPLICATE_VOTE_FOUND', 'Duplicate vote UID found'));
66289
67317
  }
@@ -66292,13 +67320,16 @@ class LedgerAtomicInterface {
66292
67320
  }
66293
67321
  seenVoteIssuers.add(checkVote.issuer);
66294
67322
  seenVoteUIDs.add(checkVote.$id);
67323
+ if (checkVote.fee !== undefined) {
67324
+ requiredFees.set(checkVote.issuer, checkVote.fee);
67325
+ }
66295
67326
  if (checkVote.$permanent) {
66296
67327
  throw (new ledger_1.default('LEDGER_CANNOT_EXCHANGE_PERM_VOTE', 'Asked to exchange a permanent vote for a permanent vote'));
66297
67328
  }
66298
- let blocksDifferFromVoteBlocks = checkVote.blocks.length !== blocks.length;
67329
+ let blocksDifferFromVoteBlocks = checkVote.blocks.length !== blockCount;
66299
67330
  /* If they do not differ from length alone, compare block hashes */
66300
67331
  if (!blocksDifferFromVoteBlocks) {
66301
- for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) {
67332
+ for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
66302
67333
  if (!blocks[blockIndex].hash.compareHexString(checkVote.blocks[blockIndex])) {
66303
67334
  blocksDifferFromVoteBlocks = true;
66304
67335
  break;
@@ -66312,69 +67343,43 @@ class LedgerAtomicInterface {
66312
67343
  foundOurVote = true;
66313
67344
  }
66314
67345
  }
66315
- if (!foundOurVote) {
66316
- throw (new ledger_1.default('LEDGER_NO_PERM_WITHOUT_SELF_TEMP', 'Asked to give a permanent vote without a temporary vote from us'));
66317
- }
66318
- }
66319
- /**
66320
- * Create a map of all blocks by their hash
66321
- */
66322
- const blockHashMap = {};
66323
- for (const block of blocks) {
66324
- blockHashMap[block.hash.toString()] = block;
66325
- }
66326
- const seenBlockHashes = new block_1.BlockHash.Set();
66327
- const usedPreviousBlockHashes = new block_1.BlockHash.Set();
66328
- const blocksToCheckOurVotesFor = [];
66329
- const needToGetHeadFor = new account_1.default.Set();
66330
- const expectedHead = {};
66331
- for (const block of blocks) {
66332
- const prevBlockHash = block.previous;
66333
- seenBlockHashes.add(block.hash);
66334
- if (block.network !== __classPrivateFieldGet(this, _LedgerAtomicInterface_network, "f")) {
66335
- throw (new ledger_1.default('LEDGER_INVALID_NETWORK', 'Cannot vote on block for a different network'));
66336
- }
66337
- if (block.subnet !== __classPrivateFieldGet(this, _LedgerAtomicInterface_subnet, "f")) {
66338
- throw (new ledger_1.default('LEDGER_INVALID_SUBNET', 'Cannot vote on block for a different subnet'));
66339
- }
66340
- if (usedPreviousBlockHashes.has(prevBlockHash)) {
66341
- throw (new ledger_1.default('LEDGER_PREVIOUS_ALREADY_USED', `Invalid reference to block, previous: ${prevBlockHash} has already been used`));
67346
+ if (requiredFees.size > 0) {
67347
+ if (!hasFeeBlock) {
67348
+ throw (new ledger_1.default('LEDGER_MISSING_REQUIRED_FEE_BLOCK', 'Missing fee block but votes require it'));
67349
+ }
67350
+ if (requiredFees.size !== possibleFeeBlock?.operations.length) {
67351
+ throw (new ledger_1.default('LEDGER_REQUIRED_FEE_MISMATCH', 'Fee Block Operations do not match required fees'));
67352
+ }
66342
67353
  }
66343
- usedPreviousBlockHashes.add(prevBlockHash);
66344
- /**
66345
- * Only allow this vote if it is the successor the current
66346
- * HEAD block for the account, or if no blocks exist on the
66347
- * account and its an opening block, or if the predecessor
66348
- * block is also being voted on
66349
- */
66350
- let predecessorBeingVotedOn = false;
66351
- if (!block.$opening) {
66352
- const prevBlock = blockHashMap[prevBlockHash.toString()];
66353
- if (prevBlock !== undefined) {
66354
- predecessorBeingVotedOn = true;
66355
- if (!(prevBlock.account.comparePublicKey(block.account))) {
66356
- throw (new ledger_1.default('LEDGER_INVALID_CHAIN', 'Invalid chain, changes accounts'));
66357
- }
66358
- if (!seenBlockHashes.has(prevBlockHash)) {
66359
- throw (new ledger_1.default('LEDGER_PREVIOUS_NOT_SEEN', `Invalid reference to block, out-of-order: ${prevBlockHash} has not already been seen`));
67354
+ // Verify that all required fees have been included in the fee block
67355
+ for (const [issuer, fee] of requiredFees) {
67356
+ const foundFee = possibleFeeBlock?.operations.find((operation) => {
67357
+ const expectedPayTo = fee.payTo ?? issuer;
67358
+ const expectedToken = fee.token ?? __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").baseToken;
67359
+ if (operation.type === operations_1.OperationType.SEND && operation.to.comparePublicKey(expectedPayTo)) {
67360
+ if (operation.amount !== fee.amount) {
67361
+ throw (new ledger_1.default('LEDGER_FEE_AMOUNT_MISMATCH', `Fee Amount Mismatch, found: ${operation.amount} expected: ${fee.amount}`));
67362
+ }
67363
+ if (!operation.token.comparePublicKey(expectedToken)) {
67364
+ throw (new ledger_1.default('LEDGER_FEE_TOKEN_MISMATCH', `Fee Token Mismatch, found: ${operation.token.publicKeyString.get()} expected: ${expectedToken.publicKeyString.get()}`));
67365
+ }
67366
+ return (true);
66360
67367
  }
67368
+ return (false);
67369
+ });
67370
+ if (foundFee === undefined) {
67371
+ throw (new ledger_1.default('LEDGER_FEE_MISSING', `Missing Required Fee for ${fee.payTo?.publicKeyString.get() ?? issuer.publicKeyString.get()}`));
66361
67372
  }
66362
67373
  }
66363
- if (!predecessorBeingVotedOn) {
66364
- const pubKey = block.account.publicKeyString.get();
66365
- needToGetHeadFor.add(block.account);
66366
- expectedHead[pubKey] = block;
67374
+ if (!foundOurVote) {
67375
+ throw (new ledger_1.default('LEDGER_NO_PERM_WITHOUT_SELF_TEMP', 'Asked to give a permanent vote without a temporary vote from us'));
66367
67376
  }
66368
- /**
66369
- * Ensure we have no active vote for another conflicting successor of this block's parent (previous),
66370
- * which could cause a fork
66371
- */
66372
- blocksToCheckOurVotesFor.push(block);
66373
67377
  }
67378
+ const allLedgerHeads = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_validateBlocksForVote).call(this, blocks);
67379
+ const needToGetHeadFor = new account_1.default.Set(allLedgerHeads.keys());
66374
67380
  const allHeads = await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").getHeadBlockHashes(transaction, needToGetHeadFor);
66375
- for (const pubKey in expectedHead) {
66376
- const expectedBlock = expectedHead[pubKey];
66377
- const accountHead = allHeads[pubKey];
67381
+ for (const [account, expectedBlock] of allLedgerHeads.entries()) {
67382
+ const accountHead = allHeads[account.publicKeyString.get()];
66378
67383
  if (accountHead === null) {
66379
67384
  if (!expectedBlock.$opening) {
66380
67385
  throw (new ledger_1.default('LEDGER_NOT_OPENING', 'Cannot vote on non-opening block for an empty account'));
@@ -66388,9 +67393,13 @@ class LedgerAtomicInterface {
66388
67393
  throw (new ledger_1.default('LEDGER_NOT_SUCCESSOR', 'The block is not the successor to the account head block'));
66389
67394
  }
66390
67395
  }
66391
- const previousToCheckFor = blocksToCheckOurVotesFor.map(b => b.previous);
67396
+ /**
67397
+ * Ensure we have no active vote for another conflicting successor of this block's parent (previous),
67398
+ * which could cause a fork
67399
+ */
67400
+ const previousToCheckFor = blocks.map(b => b.previous);
66392
67401
  const allPrevious = await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").getVotesFromMultiplePrevious(transaction, previousToCheckFor, 'both', account_1.default.toAccount(ledgerPubKey));
66393
- for (const block of blocksToCheckOurVotesFor) {
67402
+ for (const block of blocks) {
66394
67403
  const previousVotes = allPrevious[block.previous.toString()];
66395
67404
  if (previousVotes !== null && previousVotes.length > 0) {
66396
67405
  /**
@@ -66413,32 +67422,7 @@ class LedgerAtomicInterface {
66413
67422
  * If no other votes have been supplied, validate that the blocks are valid, and issue a short vote
66414
67423
  */
66415
67424
  if (otherVotes === undefined) {
66416
- await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_validateLedgerOutcome).call(this, blocks);
66417
- const now = Date.now();
66418
- for (const block of blocks) {
66419
- const blockDate = block.date.valueOf();
66420
- const timeOffset = 5 /* m */ * 60 /* s */ * 1000 /* ms */;
66421
- /**
66422
- * Do not allow short votes on blocks from the distant past
66423
- */
66424
- if (blockDate < (now - timeOffset) || blockDate > (now + timeOffset)) {
66425
- throw (new Error(`Refusing to issue vote for block dated ${block.date.toISOString()}`));
66426
- }
66427
- }
66428
- /**
66429
- * Serial number
66430
- */
66431
- const serial = await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").getNextSerialNumber(__classPrivateFieldGet(this, _LedgerAtomicInterface_transaction, "f"));
66432
- /**
66433
- * Short expiry (5 minutes)
66434
- */
66435
- const pendingVoteExpiry = new Date();
66436
- pendingVoteExpiry.setUTCMinutes(pendingVoteExpiry.getUTCMinutes() + 5);
66437
- const wipVote = new vote_1.VoteBuilder(privateKey);
66438
- for (const block of blocks) {
66439
- wipVote.addBlock(block);
66440
- }
66441
- const vote = await wipVote.seal(serial, pendingVoteExpiry);
67425
+ const vote = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_voteOrQuoteWithFees).call(this, blocks, 'VOTE', quote);
66442
67426
  const blocksAndVote = vote_1.VoteStaple.fromVotesAndBlocks([vote], blocks);
66443
67427
  await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").addPendingVote(transaction, blocksAndVote);
66444
67428
  return (vote);
@@ -66468,6 +67452,11 @@ class LedgerAtomicInterface {
66468
67452
  await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").addPendingVote(transaction, blocksAndVote);
66469
67453
  return (vote);
66470
67454
  }
67455
+ async quote(blocks) {
67456
+ await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_validateBlocksForVote).call(this, blocks);
67457
+ const quote = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_voteOrQuoteWithFees).call(this, blocks, 'QUOTE');
67458
+ return (quote);
67459
+ }
66471
67460
  async add(votesAndBlocks, from) {
66472
67461
  const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66473
67462
  switch (__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode) {
@@ -66517,12 +67506,9 @@ class LedgerAtomicInterface {
66517
67506
  /**
66518
67507
  * Add all the block hashes to the node checksum
66519
67508
  */
66520
- const ourNode = __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").node;
66521
- if (ourNode) {
66522
- for (const staple of voteStaples) {
66523
- for (const block of staple.blocks) {
66524
- ourNode.stats.xor('ledgerChecksum', block.hash);
66525
- }
67509
+ for (const staple of voteStaples) {
67510
+ for (const block of staple.blocks) {
67511
+ transaction.statsPending.xor('ledgerChecksum', block.hash);
66526
67512
  }
66527
67513
  }
66528
67514
  postambleTiming?.end();
@@ -66787,9 +67773,13 @@ class LedgerAtomicInterface {
66787
67773
  }
66788
67774
  return (retval);
66789
67775
  }
66790
- async gc() {
67776
+ async gc(timeLimitMS) {
66791
67777
  const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66792
- return (await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").gc(transaction));
67778
+ return (await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").gc(transaction, timeLimitMS));
67779
+ }
67780
+ async getFee(blocks, effectsInput) {
67781
+ const effects = effectsInput ?? (0, effects_1.computeEffectOfBlocks)(blocks, __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f"));
67782
+ return (__classPrivateFieldGet(this, _LedgerAtomicInterface_computeFeeFromBlocks, "f").call(this, __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f"), blocks, effects));
66793
67783
  }
66794
67784
  async _testingRunStorageFunction(code) {
66795
67785
  const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
@@ -66797,7 +67787,7 @@ class LedgerAtomicInterface {
66797
67787
  return (retval);
66798
67788
  }
66799
67789
  }
66800
- _LedgerAtomicInterface_network = new WeakMap(), _LedgerAtomicInterface_subnet = new WeakMap(), _LedgerAtomicInterface_kind = new WeakMap(), _LedgerAtomicInterface_privateKey = new WeakMap(), _LedgerAtomicInterface_storage = new WeakMap(), _LedgerAtomicInterface_transaction = new WeakMap(), _LedgerAtomicInterface_ledger = new WeakMap(), _LedgerAtomicInterface_cache = new WeakMap(), _LedgerAtomicInterface_instances = new WeakSet(), _LedgerAtomicInterface_assertTransaction = function _LedgerAtomicInterface_assertTransaction() {
67790
+ _LedgerAtomicInterface_network = new WeakMap(), _LedgerAtomicInterface_subnet = new WeakMap(), _LedgerAtomicInterface_kind = new WeakMap(), _LedgerAtomicInterface_privateKey = new WeakMap(), _LedgerAtomicInterface_computeFeeFromBlocks = new WeakMap(), _LedgerAtomicInterface_storage = new WeakMap(), _LedgerAtomicInterface_ledger = new WeakMap(), _LedgerAtomicInterface_cache = new WeakMap(), _LedgerAtomicInterface_transaction = new WeakMap(), _LedgerAtomicInterface_instances = new WeakSet(), _LedgerAtomicInterface_assertTransaction = function _LedgerAtomicInterface_assertTransaction() {
66801
67791
  if (__classPrivateFieldGet(this, _LedgerAtomicInterface_transaction, "f") === null) {
66802
67792
  throw (new Error('Attempt to use closed transaction'));
66803
67793
  }
@@ -66864,36 +67854,56 @@ _LedgerAtomicInterface_network = new WeakMap(), _LedgerAtomicInterface_subnet =
66864
67854
  throw (new ledger_1.default('LEDGER_INVALID_PERMISSIONS', `${accountPubKey} does not have required permissions to perform action on ${reqEntityKey}/${reqTargetKey} -- needs [${baseFlagsStr}]/[${externalOffsetsStr}]`));
66865
67855
  }
66866
67856
  }
66867
- }, _LedgerAtomicInterface_checkPermissionRequirements = async function _LedgerAtomicInterface_checkPermissionRequirements(allRequirements) {
67857
+ }, _LedgerAtomicInterface_checkPermissionRequirements = async function _LedgerAtomicInterface_checkPermissionRequirements(effects) {
66868
67858
  __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66869
67859
  const newOwners = {};
66870
67860
  const requirementsByPrincipal = {};
66871
67861
  const needToGetAccountInfoFor = new account_1.default.Set();
66872
- for (const singleRequirement of allRequirements) {
66873
- const principal = singleRequirement.principal;
66874
- const principalPubKey = principal.publicKeyString.get();
66875
- if (!requirementsByPrincipal[principalPubKey]) {
66876
- requirementsByPrincipal[principalPubKey] = [];
66877
- }
66878
- requirementsByPrincipal[principalPubKey].push(singleRequirement);
66879
- const { entity, permissions } = singleRequirement;
66880
- const entityKey = entity.publicKeyString.get();
66881
- if (permissions === null) {
66882
- continue;
66883
- }
66884
- if (permissions.has(['OWNER'])) {
66885
- if (newOwners[entityKey] === undefined) {
66886
- newOwners[entityKey] = {
66887
- entity, owners: []
66888
- };
67862
+ const allAccountsChanges = Object.values(effects);
67863
+ const foundMultisigSignerLengths = [];
67864
+ for (const { account, fields } of allAccountsChanges) {
67865
+ if (account.isMultisig()) {
67866
+ if (fields.minSignerSetLength !== undefined) {
67867
+ needToGetAccountInfoFor.add(account);
67868
+ foundMultisigSignerLengths.push([account, fields.minSignerSetLength]);
67869
+ }
67870
+ }
67871
+ for (const singleRequirement of fields.permissionRequirements ?? []) {
67872
+ const principal = singleRequirement.principal;
67873
+ const principalPubKey = principal.publicKeyString.get();
67874
+ if (!requirementsByPrincipal[principalPubKey]) {
67875
+ requirementsByPrincipal[principalPubKey] = [];
67876
+ }
67877
+ requirementsByPrincipal[principalPubKey].push(singleRequirement);
67878
+ const { entity, permissions } = singleRequirement;
67879
+ const entityKey = entity.publicKeyString.get();
67880
+ if (permissions === null) {
67881
+ continue;
67882
+ }
67883
+ if (permissions.has(['OWNER'])) {
67884
+ if (newOwners[entityKey] === undefined) {
67885
+ newOwners[entityKey] = {
67886
+ entity, owners: []
67887
+ };
67888
+ }
67889
+ newOwners[entityKey].owners.push(principal);
67890
+ }
67891
+ if (permissions.base.isValidForDefault && entity.isIdentifier()) {
67892
+ needToGetAccountInfoFor.add(entity);
66889
67893
  }
66890
- newOwners[entityKey].owners.push(principal);
66891
- }
66892
- if (permissions.base.isValidForDefault && entity.isIdentifier()) {
66893
- needToGetAccountInfoFor.add(entity);
66894
67894
  }
66895
67895
  }
66896
67896
  const foundAccountInfo = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_listAccountInfo).call(this, needToGetAccountInfoFor);
67897
+ for (const [multisig, foundSingerLength] of foundMultisigSignerLengths) {
67898
+ const multisigPubKey = multisig.publicKeyString.get();
67899
+ const foundInfo = foundAccountInfo[multisigPubKey];
67900
+ if (!foundInfo?.multisigQuorum) {
67901
+ throw (new Error(`Multisig quorum not found for ${multisigPubKey}`));
67902
+ }
67903
+ if (foundInfo.multisigQuorum > foundSingerLength) {
67904
+ throw (new ledger_1.default('LEDGER_INVALID_PERMISSIONS', `Quorum of ${foundInfo.multisigQuorum} not reached for ${multisigPubKey} -- got ${foundSingerLength}`));
67905
+ }
67906
+ }
66897
67907
  const checkPromises = [];
66898
67908
  for (const principalPubKey in requirementsByPrincipal) {
66899
67909
  const accountRequirements = requirementsByPrincipal[principalPubKey];
@@ -66914,7 +67924,7 @@ async function _LedgerAtomicInterface_validateLedgerOutcome(blocks) {
66914
67924
  const ownersByIdentifier = {};
66915
67925
  // 'ADD' or 'REMOVE' an owner from ownersByIdentifier
66916
67926
  const modifyOwners = (method, entity, principal) => {
66917
- if (entity.isIdentifier() === false) {
67927
+ if (entity.isIdentifier() === false || entity.isMultisig()) {
66918
67928
  return;
66919
67929
  }
66920
67930
  const entityPubKey = entity.assertIdentifier().publicKeyString.get();
@@ -66934,18 +67944,14 @@ async function _LedgerAtomicInterface_validateLedgerOutcome(blocks) {
66934
67944
  break;
66935
67945
  }
66936
67946
  };
66937
- const accountEffects = (0, effects_1.computeEffectOfBlocks)(blocks, __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f")).accounts;
67947
+ const effects = (0, effects_1.computeEffectOfBlocks)(blocks, __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f"));
67948
+ const accountEffects = effects.accounts;
66938
67949
  const allAccountsChanges = Object.values(accountEffects);
66939
67950
  /**
66940
67951
  * Ensure all required permissions are met
66941
67952
  * See which accounts are now owners, and add those accounts to the set that we have
66942
67953
  */
66943
- const allPermissionRequirements = [];
66944
- for (const accountChanges of allAccountsChanges) {
66945
- const requirements = accountChanges.fields.permissionRequirements ?? [];
66946
- allPermissionRequirements.push(...requirements);
66947
- }
66948
- const { newOwners } = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_checkPermissionRequirements).call(this, allPermissionRequirements);
67954
+ const { newOwners } = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_checkPermissionRequirements).call(this, accountEffects);
66949
67955
  for (const entityPubKey in newOwners) {
66950
67956
  const { entity, owners } = newOwners[entityPubKey];
66951
67957
  for (const newOwner of owners) {
@@ -66959,7 +67965,7 @@ async function _LedgerAtomicInterface_validateLedgerOutcome(blocks) {
66959
67965
  */
66960
67966
  const createRequests = fields.createRequests ?? [];
66961
67967
  for (const createRequest of createRequests) {
66962
- modifyOwners('ADD', createRequest.requestedIdentifier, account);
67968
+ modifyOwners('ADD', createRequest.createdIdentifier, account);
66963
67969
  }
66964
67970
  /**
66965
67971
  * If an account was granted permissions, we should take that into effect
@@ -67011,6 +68017,98 @@ async function _LedgerAtomicInterface_validateLedgerOutcome(blocks) {
67011
68017
  }
67012
68018
  }
67013
68019
  }
68020
+ return (effects);
68021
+ }, _LedgerAtomicInterface_validateBlocksForVote = async function _LedgerAtomicInterface_validateBlocksForVote(blocks) {
68022
+ /**
68023
+ * Create a map of all blocks by their hash
68024
+ */
68025
+ const blockHashMap = {};
68026
+ for (const block of blocks) {
68027
+ blockHashMap[block.hash.toString()] = block;
68028
+ }
68029
+ const seenBlockHashes = new block_1.BlockHash.Set();
68030
+ const usedPreviousBlockHashes = new block_1.BlockHash.Set();
68031
+ const allLedgerHeads = new Map();
68032
+ for (const block of blocks) {
68033
+ const prevBlockHash = block.previous;
68034
+ seenBlockHashes.add(block.hash);
68035
+ if (block.network !== __classPrivateFieldGet(this, _LedgerAtomicInterface_network, "f")) {
68036
+ throw (new ledger_1.default('LEDGER_INVALID_NETWORK', 'Cannot vote on block for a different network'));
68037
+ }
68038
+ if (block.subnet !== __classPrivateFieldGet(this, _LedgerAtomicInterface_subnet, "f")) {
68039
+ throw (new ledger_1.default('LEDGER_INVALID_SUBNET', 'Cannot vote on block for a different subnet'));
68040
+ }
68041
+ if (usedPreviousBlockHashes.has(prevBlockHash)) {
68042
+ throw (new ledger_1.default('LEDGER_PREVIOUS_ALREADY_USED', `Invalid reference to block, previous: ${prevBlockHash} has already been used`));
68043
+ }
68044
+ usedPreviousBlockHashes.add(prevBlockHash);
68045
+ /**
68046
+ * Only allow this vote if it is the successor the current
68047
+ * HEAD block for the account, or if no blocks exist on the
68048
+ * account and its an opening block, or if the predecessor
68049
+ * block is also being voted on
68050
+ */
68051
+ let predecessorBeingVotedOn = false;
68052
+ if (!block.$opening) {
68053
+ const prevBlock = blockHashMap[prevBlockHash.toString()];
68054
+ if (prevBlock !== undefined) {
68055
+ predecessorBeingVotedOn = true;
68056
+ if (!(prevBlock.account.comparePublicKey(block.account))) {
68057
+ throw (new ledger_1.default('LEDGER_INVALID_CHAIN', 'Invalid chain, changes accounts'));
68058
+ }
68059
+ if (!seenBlockHashes.has(prevBlockHash)) {
68060
+ throw (new ledger_1.default('LEDGER_PREVIOUS_NOT_SEEN', `Invalid reference to block, out-of-order: ${prevBlockHash} has not already been seen`));
68061
+ }
68062
+ }
68063
+ }
68064
+ if (!predecessorBeingVotedOn) {
68065
+ allLedgerHeads.set(block.account, block);
68066
+ }
68067
+ }
68068
+ return (allLedgerHeads);
68069
+ }, _LedgerAtomicInterface_voteOrQuoteWithFees = async function _LedgerAtomicInterface_voteOrQuoteWithFees(blocks, type, quote) {
68070
+ if (__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode !== 'read-write') {
68071
+ throw (new Error(`May not issue votes in read-only mode, in ${__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode} mode`));
68072
+ }
68073
+ if (!__classPrivateFieldGet(this, _LedgerAtomicInterface_privateKey, "f")) {
68074
+ throw (new Error('Cannot vote on block, no private key loaded'));
68075
+ }
68076
+ __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
68077
+ const effects = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_validateLedgerOutcome).call(this, blocks);
68078
+ const now = Date.now();
68079
+ for (const block of blocks) {
68080
+ const blockDate = block.date.valueOf();
68081
+ const timeOffset = 5 /* m */ * 60 /* s */ * 1000 /* ms */;
68082
+ /**
68083
+ * Do not allow short votes on blocks from the distant past
68084
+ */
68085
+ if (blockDate < (now - timeOffset) || blockDate > (now + timeOffset)) {
68086
+ throw (new Error(`Refusing to issue vote for block dated ${block.date.toISOString()}`));
68087
+ }
68088
+ }
68089
+ /**
68090
+ * Serial number
68091
+ */
68092
+ const serial = await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").getNextSerialNumber(__classPrivateFieldGet(this, _LedgerAtomicInterface_transaction, "f"));
68093
+ /**
68094
+ * Short expiry (5 minutes)
68095
+ */
68096
+ const pendingVoteExpiry = new Date();
68097
+ pendingVoteExpiry.setUTCMinutes(pendingVoteExpiry.getUTCMinutes() + 5);
68098
+ const builderType = (type === 'QUOTE') ? vote_1.VoteQuoteBuilder : vote_1.VoteBuilder;
68099
+ const builder = new builderType(__classPrivateFieldGet(this, _LedgerAtomicInterface_privateKey, "f"));
68100
+ for (const block of blocks) {
68101
+ builder.addBlock(block);
68102
+ }
68103
+ /**
68104
+ * If a quote was provided use it as the fee, otherwise generate new fee
68105
+ */
68106
+ const fee = quote?.fee ?? await this.getFee(blocks, effects);
68107
+ if (fee !== null) {
68108
+ builder.addFee(fee);
68109
+ }
68110
+ const voteOrQuote = await builder.seal(serial, pendingVoteExpiry);
68111
+ return (voteOrQuote);
67014
68112
  };
67015
68113
  /**
67016
68114
  * The core Ledger components
@@ -67047,6 +68145,26 @@ class Ledger {
67047
68145
  copy(newNode) {
67048
68146
  return (new Ledger(__classPrivateFieldGet(this, _Ledger_config, "f"), newNode, __classPrivateFieldGet(this, _Ledger_storage, "f")));
67049
68147
  }
68148
+ getFeePayToAndToken(accounts, token) {
68149
+ const retval = {};
68150
+ if (accounts !== undefined && accounts.length > 0) {
68151
+ // Get a random fee account from the set of possible accounts
68152
+ const feeAccount = accounts[Math.floor(Math.random() * accounts.length)];
68153
+ // If the fee account matches the ledger private key then we can omit the account
68154
+ // Fee is then paid to the vote issuer
68155
+ if (!feeAccount.comparePublicKey(__classPrivateFieldGet(this, _Ledger_config, "f").privateKey?.publicKeyString.get())) {
68156
+ retval.payTo = feeAccount;
68157
+ }
68158
+ }
68159
+ if (token !== undefined) {
68160
+ // If base token matches ledger fee token then we can omit the token
68161
+ // Fee is then paid using the base token
68162
+ if (!this.baseToken.comparePublicKey(token)) {
68163
+ retval.token = token;
68164
+ }
68165
+ }
68166
+ return (retval);
68167
+ }
67050
68168
  /**
67051
68169
  * Execute some code with a transaction held, if the code fails the
67052
68170
  * transaction is aborted, otherwise it is committed
@@ -67154,13 +68272,7 @@ class Ledger {
67154
68272
  return (await this.run(identifier, code, true));
67155
68273
  }
67156
68274
  async beginTransaction(identifier, readOnly = false) {
67157
- const transactionBase = {
67158
- node: this.node,
67159
- moment: new Date(),
67160
- identifier,
67161
- readOnly
67162
- };
67163
- const transaction = await __classPrivateFieldGet(this, _Ledger_storage, "f").beginTransaction(transactionBase);
68275
+ const transaction = await __classPrivateFieldGet(this, _Ledger_storage, "f").beginTransaction({ node: this.node, moment: new Date(), identifier, readOnly });
67164
68276
  return (new LedgerAtomicInterface(transaction, __classPrivateFieldGet(this, _Ledger_storage, "f"), __classPrivateFieldGet(this, _Ledger_config, "f"), this));
67165
68277
  }
67166
68278
  async vote(...args) {
@@ -67168,6 +68280,11 @@ class Ledger {
67168
68280
  return (await transaction.vote(...args));
67169
68281
  }));
67170
68282
  }
68283
+ async quote(...args) {
68284
+ return (await this.run('db-quote', async function (transaction) {
68285
+ return (await transaction.quote(...args));
68286
+ }));
68287
+ }
67171
68288
  async add(...args) {
67172
68289
  return (await this.run('db-add', async function (transaction) {
67173
68290
  return (await transaction.add(...args));
@@ -67278,6 +68395,11 @@ class Ledger {
67278
68395
  return (await transaction.gc(...args));
67279
68396
  }));
67280
68397
  }
68398
+ async getFee(...args) {
68399
+ return (await this.runReadOnly('db-getFee', async function (transaction) {
68400
+ return (await transaction.getFee(...args));
68401
+ }));
68402
+ }
67281
68403
  async stats() {
67282
68404
  const env_2 = { stack: [], error: void 0, hasError: false };
67283
68405
  try {
@@ -67825,9 +68947,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
67825
68947
  var __importDefault = (this && this.__importDefault) || function (mod) {
67826
68948
  return (mod && mod.__esModule) ? mod : { "default": mod };
67827
68949
  };
67828
- var _P2PWebSocket_underlyingSocket, _P2PWebSocket_socket, _P2PWebSocket_switch, _P2PSwitch_instances, _P2PSwitch_connectedPeersCleanup, _P2PSwitch_connectedPeersRemote, _P2PSwitch_connectedPeersLocal, _P2PSwitch_localNode, _P2PSwitch_manualPeersCheckIntervals, _P2PSwitch_asyncSends, _P2PSwitch_messageFilterCache, _P2PSwitch_connectedPeerConnection, _P2PSwitch_connectedPeers, _P2PSwitch_updateLastSeenPeer, _P2PSwitch_peersCacheSet, _P2PSwitch_peersCached, _P2PSwitch_relayActiveState, _P2PSwitch_performPeerCleanup, _P2PSwitch_getLocalPeerInfo, _P2PSwitch_emitOutgoingGreeting, _P2PSwitch_localNodeKeyOrNull, _P2PSwitch_handleIncomingGreeting, _P2PSwitch_updateConnTimeout, _P2PSwitch_connectToPeer, _P2PSwitch_passesFilter;
68950
+ var _P2PHttpConnection_switch, _P2PWebSocket_underlyingSocket, _P2PWebSocket_socket, _P2PWebSocket_switch, _P2PSwitch_instances, _P2PSwitch_connectedPeersCleanup, _P2PSwitch_connectedPeersRemote, _P2PSwitch_connectedPeersLocal, _P2PSwitch_localNode, _P2PSwitch_manualPeersCheckIntervals, _P2PSwitch_asyncSends, _P2PSwitch_messageFilterCache, _P2PSwitch_cachedLocalPeerInfo, _P2PSwitch_cachedLocalPeerSerialized, _P2PSwitch_connectedPeerConnection, _P2PSwitch_connectedPeers, _P2PSwitch_updateLastSeenPeer, _P2PSwitch_peersCacheSet, _P2PSwitch_peersCached, _P2PSwitch_relayActiveState, _P2PSwitch_performPeerCleanup, _P2PSwitch_getLocalPeerInfo, _P2PSwitch_emitOutgoingGreeting, _P2PSwitch_localNodeKeyOrNull, _P2PSwitch_handleIncomingGreeting, _P2PSwitch_updateConnTimeout, _P2PSwitch_connectToPeer, _P2PSwitch_passesFilter;
67829
68951
  Object.defineProperty(exports, "__esModule", ({ value: true }));
67830
- exports.Testing = exports.P2PSwitch = exports.P2PWebSocket = void 0;
68952
+ exports.Testing = exports.P2PSwitch = exports.P2PWebSocket = exports.P2PHttpConnection = void 0;
67831
68953
  exports.generateP2PPeerSigned = generateP2PPeerSigned;
67832
68954
  exports.P2PPeerFromJSO = P2PPeerFromJSO;
67833
68955
  exports.P2PPeerToJSO = P2PPeerToJSO;
@@ -67844,6 +68966,7 @@ const helper_1 = __webpack_require__(3208);
67844
68966
  const kv_memory_1 = __importDefault(__webpack_require__(1557));
67845
68967
  const vote_1 = __webpack_require__(1130);
67846
68968
  const effects_1 = __webpack_require__(7346);
68969
+ const version_1 = __webpack_require__(5672);
67847
68970
  const defaultP2PConfig = {
67848
68971
  timeoutIdle: 10 /* s */ * 1000 /* ms */,
67849
68972
  timeoutIdleGreeting: 5 /* s */ * 1000 /* ms */,
@@ -67852,12 +68975,13 @@ const defaultP2PConfig = {
67852
68975
  manualPeersCheckInFreq: 10 /* m */ * 60 /* s */ * 1000 /* ms */,
67853
68976
  seenMessageTTL: 1 /* m */ * 60 /* s */ * 1000 /* ms */,
67854
68977
  forwardingPeerCount: 16,
67855
- kv: null
68978
+ kv: null,
68979
+ useHTTPRepublish: false
67856
68980
  };
67857
68981
  /**
67858
68982
  * Convert a peer to a printable string
67859
68983
  */
67860
- function printablePeer(peer) {
68984
+ function printablePeer(peer, endpoint) {
67861
68985
  if (peer === null) {
67862
68986
  return ('null (not yet greeted)');
67863
68987
  }
@@ -67865,7 +68989,7 @@ function printablePeer(peer) {
67865
68989
  case node_1.NodeKind.PARTICIPANT:
67866
68990
  return (`listener_${peer.id}`);
67867
68991
  case node_1.NodeKind.REPRESENTATIVE:
67868
- return (`rep_${peer.key.publicKeyString.get()}@${peer.endpoints.p2p}`);
68992
+ return (`rep_${peer.key.publicKeyString.get()}@${endpoint ?? peer.endpoints.p2p}`);
67869
68993
  }
67870
68994
  return (null);
67871
68995
  }
@@ -67899,6 +69023,7 @@ function validateP2PPeer(peer) {
67899
69023
  checkVersion,
67900
69024
  peer.endpoints.p2p,
67901
69025
  peer.endpoints.api,
69026
+ peer.preferUpdates,
67902
69027
  peer.kind,
67903
69028
  peer.key.publicKeyAndType
67904
69029
  ];
@@ -67922,6 +69047,7 @@ async function generateP2PPeerSignature(peer) {
67922
69047
  version,
67923
69048
  peer.endpoints.p2p,
67924
69049
  peer.endpoints.api,
69050
+ peer.preferUpdates,
67925
69051
  peer.kind,
67926
69052
  peer.key.publicKeyAndType
67927
69053
  ];
@@ -67973,13 +69099,20 @@ function P2PPeerFromJSO(object) {
67973
69099
  if (typeof endpoints.p2p !== 'string' || typeof endpoints.api !== 'string') {
67974
69100
  return (null);
67975
69101
  }
69102
+ if (typeof object.preferUpdates !== 'string') {
69103
+ return (null);
69104
+ }
69105
+ if (object.preferUpdates !== 'http' && object.preferUpdates !== 'websocket') {
69106
+ return (null);
69107
+ }
67976
69108
  if (typeof object.key !== 'string') {
67977
69109
  return (null);
67978
69110
  }
67979
69111
  const retvalUnsigned = {
67980
69112
  kind: node_1.NodeKind.REPRESENTATIVE,
67981
69113
  key: account_1.default.fromPublicKeyString(object.key).assertAccount(),
67982
- endpoints: endpoints
69114
+ endpoints: endpoints,
69115
+ preferUpdates: object.preferUpdates
67983
69116
  };
67984
69117
  let retval;
67985
69118
  if (typeof object.signature === 'string') {
@@ -68041,6 +69174,7 @@ function P2PPeerToJSO(peer) {
68041
69174
  return ({
68042
69175
  kind: peer.kind,
68043
69176
  endpoints: peer.endpoints,
69177
+ preferUpdates: peer.preferUpdates,
68044
69178
  key: peer.key.publicKeyString.get(),
68045
69179
  ...additionalAttributes
68046
69180
  });
@@ -68073,6 +69207,12 @@ function isP2PPeer(checkObject) {
68073
69207
  if (!('p2p' in checkObject.endpoints) || !('api' in checkObject.endpoints)) {
68074
69208
  return (false);
68075
69209
  }
69210
+ if (!('preferUpdates' in checkObject)) {
69211
+ return (false);
69212
+ }
69213
+ if (checkObject.preferUpdates !== 'http' && checkObject.preferUpdates !== 'websocket') {
69214
+ return (false);
69215
+ }
68076
69216
  if (!('key' in checkObject)) {
68077
69217
  return (false);
68078
69218
  }
@@ -68182,6 +69322,78 @@ async function waitForPeer(conn) {
68182
69322
  }, 10);
68183
69323
  })));
68184
69324
  }
69325
+ class P2PHttpConnection {
69326
+ /**
69327
+ * Initiate an outbound http connection and attach it to the specified switch
69328
+ */
69329
+ static async initiate(peer, p2pSwitch) {
69330
+ if (!('endpoints' in peer)) {
69331
+ return (null);
69332
+ }
69333
+ if (!('api' in peer.endpoints)) {
69334
+ return (null);
69335
+ }
69336
+ if (!('preferUpdates' in peer) || peer.preferUpdates !== 'http') {
69337
+ return (null);
69338
+ }
69339
+ const conn = new P2PHttpConnection(peer, p2pSwitch);
69340
+ await p2pSwitch.registerConnection(conn);
69341
+ return (conn);
69342
+ }
69343
+ constructor(peer, p2pSwitch) {
69344
+ _P2PHttpConnection_switch.set(this, void 0);
69345
+ this.abort = false;
69346
+ this.validatedPeer = null;
69347
+ this.timeout = 0;
69348
+ this.peer = peer;
69349
+ __classPrivateFieldSet(this, _P2PHttpConnection_switch, p2pSwitch, "f");
69350
+ }
69351
+ get connString() {
69352
+ if (this.peerString === null) {
69353
+ throw (new Error('HTTP Connection should have a peerString'));
69354
+ }
69355
+ return (this.peerString);
69356
+ }
69357
+ get peerString() {
69358
+ if (this.peer.kind === node_1.NodeKind.PARTICIPANT) {
69359
+ throw (new Error('HTTP Connections cannot be participants'));
69360
+ }
69361
+ return (printablePeer(this.peer, this.peer.endpoints.api));
69362
+ }
69363
+ async send(messageBuffer) {
69364
+ if (this.peer.kind !== node_1.NodeKind.REPRESENTATIVE) {
69365
+ return (false);
69366
+ }
69367
+ __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f")._log.debug(`Called send on http connection: ${this.peerString}`);
69368
+ const localGreetingInfo = await __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f").getOutgoingGreetingInfo();
69369
+ const fetchURL = `${this.peer.endpoints.api}/p2p/message`;
69370
+ try {
69371
+ await fetch(fetchURL, {
69372
+ method: 'POST',
69373
+ headers: {
69374
+ 'content-type': 'application/json',
69375
+ 'user-agent': `KeetaNet/v${version_1.version} (JS)`
69376
+ },
69377
+ body: JSON.stringify({
69378
+ message: messageBuffer.toString(),
69379
+ greeting: localGreetingInfo
69380
+ })
69381
+ });
69382
+ }
69383
+ catch (postMessageError) {
69384
+ __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f")._log.debug(`Failed to post message: ${postMessageError}`);
69385
+ }
69386
+ return (true);
69387
+ }
69388
+ async close() {
69389
+ this.abort = true;
69390
+ __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f")._log.debug(`Called close on http connection: ${this.peerString}`);
69391
+ await __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f").unregisterConnection(this);
69392
+ }
69393
+ }
69394
+ exports.P2PHttpConnection = P2PHttpConnection;
69395
+ _P2PHttpConnection_switch = new WeakMap();
69396
+ P2PHttpConnection.isInstance = (0, helper_1.checkableGenerator)(P2PHttpConnection);
68185
69397
  /**
68186
69398
  * A P2PConnection using the "ws" package
68187
69399
  */
@@ -68429,6 +69641,8 @@ class P2PSwitch {
68429
69641
  _P2PSwitch_manualPeersCheckIntervals.set(this, void 0);
68430
69642
  _P2PSwitch_asyncSends.set(this, []);
68431
69643
  _P2PSwitch_messageFilterCache.set(this, {});
69644
+ _P2PSwitch_cachedLocalPeerInfo.set(this, undefined);
69645
+ _P2PSwitch_cachedLocalPeerSerialized.set(this, undefined);
68432
69646
  /**
68433
69647
  * Write a debug or error message to the connected node.
68434
69648
  *
@@ -68476,7 +69690,12 @@ class P2PSwitch {
68476
69690
  * been confirmed
68477
69691
  */
68478
69692
  const repLastSeenLimit = Math.max(this.config.timeoutIdle, this.config.manualPeersCheckInFreq) * 10;
68479
- let knownPeers = await this.config.kv.getAll('knownPeers');
69693
+ const potentialKnownPeers = await this.config.kv.getAll('knownPeers');
69694
+ // Filter for only valid entries in case the format becomes invalidated in the future
69695
+ let knownPeers = Object.fromEntries(Object.entries(potentialKnownPeers).filter(([_, value]) => {
69696
+ const peer = P2PPeerFromJSO(value);
69697
+ return (peer !== null);
69698
+ }));
68480
69699
  const lastSeenPeers = await this.config.kv.getAll('lastSeenPeers');
68481
69700
  const retval = [];
68482
69701
  /**
@@ -68730,6 +69949,16 @@ class P2PSwitch {
68730
69949
  async selfPeer() {
68731
69950
  return (await __classPrivateFieldGet(this, _P2PSwitch_instances, "m", _P2PSwitch_getLocalPeerInfo).call(this));
68732
69951
  }
69952
+ async getOutgoingGreetingInfo() {
69953
+ if (__classPrivateFieldGet(this, _P2PSwitch_cachedLocalPeerSerialized, "f") === undefined) {
69954
+ const greetingInfo = await __classPrivateFieldGet(this, _P2PSwitch_instances, "m", _P2PSwitch_getLocalPeerInfo).call(this);
69955
+ if (greetingInfo === null) {
69956
+ throw (new Error('Invalid NodeKind for emitting outgoing greeting'));
69957
+ }
69958
+ __classPrivateFieldSet(this, _P2PSwitch_cachedLocalPeerSerialized, P2PPeerToJSO(greetingInfo), "f");
69959
+ }
69960
+ return (__classPrivateFieldGet(this, _P2PSwitch_cachedLocalPeerSerialized, "f"));
69961
+ }
68733
69962
  /**
68734
69963
  * Receive a message from a connection
68735
69964
  *
@@ -68780,7 +70009,7 @@ class P2PSwitch {
68780
70009
  let forward = true;
68781
70010
  let acceptable = true;
68782
70011
  let rebroadcastOnly = false;
68783
- if (from.peer === null) {
70012
+ if (from.peer === null || (P2PHttpConnection.isInstance(from) && message.type === 'greeting')) {
68784
70013
  /**
68785
70014
  * By default do not forward messages from un-greeted peers
68786
70015
  */
@@ -69237,9 +70466,26 @@ class P2PSwitch {
69237
70466
  }
69238
70467
  return (false);
69239
70468
  }
70469
+ /**
70470
+ * TODO - make this private after refactoring websockets to handle higher load
70471
+ * https://github.com/KeetaNetwork/node/issues/785
70472
+ */
70473
+ async haveAnyFilter(data) {
70474
+ const kvFilters = await this.config.kv.getAll('messageFilters');
70475
+ for (const key in kvFilters) {
70476
+ const kvFilter = kvFilters[key];
70477
+ if (kvFilter && typeof kvFilter === 'string') {
70478
+ const filter = account_1.default.fromPublicKeyAndType(kvFilter);
70479
+ const voteStaple = new vote_1.VoteStaple(data);
70480
+ const { touched } = (0, effects_1.computeEffectOfBlocks)(voteStaple.blocks);
70481
+ return (touched.has(filter));
70482
+ }
70483
+ }
70484
+ return (false);
70485
+ }
69240
70486
  }
69241
70487
  exports.P2PSwitch = P2PSwitch;
69242
- _P2PSwitch_connectedPeersCleanup = new WeakMap(), _P2PSwitch_connectedPeersRemote = new WeakMap(), _P2PSwitch_connectedPeersLocal = new WeakMap(), _P2PSwitch_localNode = new WeakMap(), _P2PSwitch_manualPeersCheckIntervals = new WeakMap(), _P2PSwitch_asyncSends = new WeakMap(), _P2PSwitch_messageFilterCache = new WeakMap(), _P2PSwitch_peersCacheSet = new WeakMap(), _P2PSwitch_instances = new WeakSet(), _P2PSwitch_connectedPeerConnection =
70488
+ _P2PSwitch_connectedPeersCleanup = new WeakMap(), _P2PSwitch_connectedPeersRemote = new WeakMap(), _P2PSwitch_connectedPeersLocal = new WeakMap(), _P2PSwitch_localNode = new WeakMap(), _P2PSwitch_manualPeersCheckIntervals = new WeakMap(), _P2PSwitch_asyncSends = new WeakMap(), _P2PSwitch_messageFilterCache = new WeakMap(), _P2PSwitch_cachedLocalPeerInfo = new WeakMap(), _P2PSwitch_cachedLocalPeerSerialized = new WeakMap(), _P2PSwitch_peersCacheSet = new WeakMap(), _P2PSwitch_instances = new WeakSet(), _P2PSwitch_connectedPeerConnection =
69243
70489
  /**
69244
70490
  * Get the connection for a given peer or PeerID
69245
70491
  */
@@ -69380,53 +70626,53 @@ async function _P2PSwitch_relayActiveState(conn) {
69380
70626
  */
69381
70627
  /** XXX:TODO */
69382
70628
  }, _P2PSwitch_getLocalPeerInfo = async function _P2PSwitch_getLocalPeerInfo() {
69383
- let greetingInfo;
69384
- switch (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.kind) {
69385
- case node_1.NodeKind.PARTICIPANT:
69386
- greetingInfo = {
69387
- kind: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.kind,
69388
- id: 'unused'
69389
- };
69390
- break;
69391
- case node_1.NodeKind.REPRESENTATIVE:
69392
- {
69393
- if (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints === undefined) {
69394
- throw (new Error('internal error: Our endpoints are not defined'));
69395
- }
69396
- if (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.p2p === undefined) {
69397
- throw (new Error('internal error: Our endpoint (p2p) is not defined'));
69398
- }
69399
- if (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.api === undefined) {
69400
- throw (new Error('internal error: Our endpoint (api) is not defined'));
69401
- }
69402
- if (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.ledgerPrivateKey === undefined) {
69403
- throw (new Error('internal error: Our ledger key is not defined'));
69404
- }
69405
- const greetingInfoSigned = await generateP2PPeerSigned({
70629
+ if (__classPrivateFieldGet(this, _P2PSwitch_cachedLocalPeerInfo, "f") === undefined) {
70630
+ let greetingInfo;
70631
+ switch (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.kind) {
70632
+ case node_1.NodeKind.PARTICIPANT:
70633
+ greetingInfo = {
69406
70634
  kind: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.kind,
69407
- key: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.ledgerPrivateKey,
69408
- endpoints: {
69409
- p2p: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.p2p,
69410
- api: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.api
70635
+ id: 'unused'
70636
+ };
70637
+ break;
70638
+ case node_1.NodeKind.REPRESENTATIVE:
70639
+ {
70640
+ if (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints === undefined) {
70641
+ throw (new Error('internal error: Our endpoints are not defined'));
69411
70642
  }
69412
- });
69413
- if (greetingInfoSigned === null) {
69414
- throw (new Error('internal error: Could not generate signature'));
70643
+ if (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.p2p === undefined) {
70644
+ throw (new Error('internal error: Our endpoint (p2p) is not defined'));
70645
+ }
70646
+ if (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.api === undefined) {
70647
+ throw (new Error('internal error: Our endpoint (api) is not defined'));
70648
+ }
70649
+ if (__classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.ledgerPrivateKey === undefined) {
70650
+ throw (new Error('internal error: Our ledger key is not defined'));
70651
+ }
70652
+ const greetingInfoSigned = await generateP2PPeerSigned({
70653
+ kind: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.kind,
70654
+ key: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.ledgerPrivateKey,
70655
+ endpoints: {
70656
+ p2p: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.p2p,
70657
+ api: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.api
70658
+ },
70659
+ preferUpdates: this.config.useHTTPRepublish ? 'http' : 'websocket'
70660
+ });
70661
+ if (greetingInfoSigned === null) {
70662
+ throw (new Error('internal error: Could not generate signature'));
70663
+ }
70664
+ greetingInfo = greetingInfoSigned;
70665
+ break;
69415
70666
  }
69416
- greetingInfo = greetingInfoSigned;
69417
- break;
69418
- }
69419
- default:
69420
- return (null);
70667
+ default:
70668
+ return (null);
70669
+ }
70670
+ __classPrivateFieldSet(this, _P2PSwitch_cachedLocalPeerInfo, greetingInfo, "f");
69421
70671
  }
69422
- return (greetingInfo);
70672
+ return (__classPrivateFieldGet(this, _P2PSwitch_cachedLocalPeerInfo, "f"));
69423
70673
  }, _P2PSwitch_emitOutgoingGreeting = async function _P2PSwitch_emitOutgoingGreeting(to) {
69424
70674
  const messageID = uuid.v4();
69425
- const greetingInfo = await __classPrivateFieldGet(this, _P2PSwitch_instances, "m", _P2PSwitch_getLocalPeerInfo).call(this);
69426
- if (greetingInfo === null) {
69427
- throw (new Error('Invalid NodeKind for emitting outgoing greeting'));
69428
- }
69429
- const greeting = P2PPeerToJSO(greetingInfo);
70675
+ const greeting = await this.getOutgoingGreetingInfo();
69430
70676
  this._log.debug('Sending greeting to', to.connString);
69431
70677
  return (await this.sendMessage(to, messageID, 'greeting', greeting, 0));
69432
70678
  }, _P2PSwitch_localNodeKeyOrNull = async function _P2PSwitch_localNodeKeyOrNull() {
@@ -69489,23 +70735,28 @@ async function _P2PSwitch_relayActiveState(conn) {
69489
70735
  }
69490
70736
  }, _P2PSwitch_connectToPeer = async function _P2PSwitch_connectToPeer(peer, logId) {
69491
70737
  this._log.debug(`[${logId}]`, 'Trying to connect to peer', printablePeer(peer));
69492
- let ws = null;
69493
- try {
69494
- ws = await P2PWebSocket.initiate(peer, this);
70738
+ let p2pConnection = null;
70739
+ if (peer.kind === node_1.NodeKind.REPRESENTATIVE && peer.preferUpdates === 'http') {
70740
+ p2pConnection = await P2PHttpConnection.initiate(peer, this);
69495
70741
  }
69496
- catch (connectError) {
69497
- /* Ignored */
70742
+ else {
70743
+ try {
70744
+ p2pConnection = await P2PWebSocket.initiate(peer, this);
70745
+ }
70746
+ catch (connectError) {
70747
+ /* Ignored */
70748
+ }
69498
70749
  }
69499
- if (ws === null) {
70750
+ if (p2pConnection === null) {
69500
70751
  return (null);
69501
70752
  }
69502
70753
  /**
69503
70754
  * Since we established an outbound connection to this
69504
70755
  * peer we already know their information
69505
70756
  */
69506
- ws.validatedPeer = peer;
69507
- await this.registerConnection(ws);
69508
- await waitForPeer(ws);
70757
+ p2pConnection.validatedPeer = peer;
70758
+ await this.registerConnection(p2pConnection);
70759
+ await waitForPeer(p2pConnection);
69509
70760
  /*
69510
70761
  * Since we successfully connected to the peer, update the
69511
70762
  * last seen information
@@ -69523,7 +70774,7 @@ async function _P2PSwitch_relayActiveState(conn) {
69523
70774
  catch (addPeerError) {
69524
70775
  this._log.error('Failed to add peer:', addPeerError);
69525
70776
  }
69526
- return (ws);
70777
+ return (p2pConnection);
69527
70778
  }, _P2PSwitch_passesFilter = async function _P2PSwitch_passesFilter(target, data) {
69528
70779
  let filter = __classPrivateFieldGet(this, _P2PSwitch_messageFilterCache, "f")[target.connString];
69529
70780
  if (filter === undefined) {
@@ -69600,7 +70851,8 @@ var BaseFlag;
69600
70851
  BaseFlag[BaseFlag["TOKEN_ADMIN_MODIFY_BALANCE"] = 7] = "TOKEN_ADMIN_MODIFY_BALANCE";
69601
70852
  BaseFlag[BaseFlag["PERMISSION_DELEGATE_ADD"] = 11] = "PERMISSION_DELEGATE_ADD";
69602
70853
  BaseFlag[BaseFlag["PERMISSION_DELEGATE_REMOVE"] = 12] = "PERMISSION_DELEGATE_REMOVE";
69603
- BaseFlag[BaseFlag["MANAGE_CERTIFICATE"] = 13] = "MANAGE_CERTIFICATE"; /* 0x2000 */
70854
+ BaseFlag[BaseFlag["MANAGE_CERTIFICATE"] = 13] = "MANAGE_CERTIFICATE";
70855
+ BaseFlag[BaseFlag["MULTISIG_SIGNER"] = 14] = "MULTISIG_SIGNER"; /* 0x4000 */
69604
70856
  })(BaseFlag || (BaseFlag = {}));
69605
70857
  /**
69606
70858
  * Handles what flags are in what groups, groups cannot be mixed (except BASE)
@@ -69614,6 +70866,8 @@ var BasePermissionGroup;
69614
70866
  BasePermissionGroup[BasePermissionGroup["NETWORK"] = 3] = "NETWORK";
69615
70867
  BasePermissionGroup[BasePermissionGroup["TOKEN"] = 4] = "TOKEN";
69616
70868
  BasePermissionGroup[BasePermissionGroup["STORAGE"] = 5] = "STORAGE";
70869
+ BasePermissionGroup[BasePermissionGroup["NONIDENTIFIER_OR_MULTISIG"] = 6] = "NONIDENTIFIER_OR_MULTISIG";
70870
+ BasePermissionGroup[BasePermissionGroup["MULTISIG"] = 7] = "MULTISIG";
69617
70871
  })(BasePermissionGroup || (BasePermissionGroup = {}));
69618
70872
  const basePermissionRules = {
69619
70873
  ACCESS: {
@@ -69699,6 +70953,12 @@ const basePermissionRules = {
69699
70953
  entity: BasePermissionGroup.ANY,
69700
70954
  principal: BasePermissionGroup.ANY,
69701
70955
  target: BasePermissionGroup.NEVER
70956
+ },
70957
+ MULTISIG_SIGNER: {
70958
+ canBeDefault: false,
70959
+ entity: BasePermissionGroup.MULTISIG,
70960
+ principal: BasePermissionGroup.NONIDENTIFIER_OR_MULTISIG,
70961
+ target: BasePermissionGroup.NEVER
69702
70962
  }
69703
70963
  };
69704
70964
  const basePermissionSetOffsets = {};
@@ -69839,6 +71099,10 @@ class BaseSet extends PermissionSetHolder {
69839
71099
  return (true);
69840
71100
  case _a.BasePermissionGroup.NEVER:
69841
71101
  return (false);
71102
+ case _a.BasePermissionGroup.NONIDENTIFIER_OR_MULTISIG:
71103
+ return (account.isAccount() || account.isMultisig());
71104
+ case _a.BasePermissionGroup.MULTISIG:
71105
+ return (account.isMultisig());
69842
71106
  }
69843
71107
  return (false);
69844
71108
  }
@@ -70129,9 +71393,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
70129
71393
  var __importDefault = (this && this.__importDefault) || function (mod) {
70130
71394
  return (mod && mod.__esModule) ? mod : { "default": mod };
70131
71395
  };
70132
- var _Stats_instances, _a, _Stats_localDBIncr, _Stats_localDBXOR, _Stats_syncPromise, _Stats_kv, _Stats_compoundKey, _Stats_assertDurationBreakdowns, _Stats_getDurationRange;
71396
+ var _a, _Stats_syncPromise, _Stats_kv, _Stats_assertDurationBreakdowns, _Stats_getDurationRange;
70133
71397
  Object.defineProperty(exports, "__esModule", ({ value: true }));
70134
- exports.Stats = void 0;
71398
+ exports.Stats = exports.StatsPending = void 0;
70135
71399
  const kv_memory_1 = __importDefault(__webpack_require__(1557));
70136
71400
  const buffer_1 = __webpack_require__(3310);
70137
71401
  const hash_1 = __webpack_require__(7908);
@@ -70161,11 +71425,57 @@ const durationRanges = {
70161
71425
  '100000ms': [10001, 100000],
70162
71426
  'ExtraLong': [100000, Number.MAX_SAFE_INTEGER]
70163
71427
  };
70164
- class Stats {
71428
+ class StatsPending {
71429
+ constructor() {
71430
+ this.localDBIncr = {};
71431
+ this.localDBXOR = {};
71432
+ }
71433
+ consume() {
71434
+ const incrChanges = this.localDBIncr;
71435
+ this.localDBIncr = {};
71436
+ const xorChanges = this.localDBXOR;
71437
+ this.localDBXOR = {};
71438
+ return ({ incrChanges, xorChanges });
71439
+ }
71440
+ compoundKey(arena, key) {
71441
+ const compoundKey = [arena, key].join('|');
71442
+ return (compoundKey);
71443
+ }
71444
+ incrCompoundKey(compoundKey, change) {
71445
+ if (this.localDBIncr[compoundKey] === undefined) {
71446
+ this.localDBIncr[compoundKey] = 0;
71447
+ }
71448
+ this.localDBIncr[compoundKey] += change;
71449
+ }
71450
+ incr(arena, key, change = 1) {
71451
+ const compoundKey = this.compoundKey(arena, key);
71452
+ this.incrCompoundKey(compoundKey, change);
71453
+ }
71454
+ xor(key, change) {
71455
+ const changeValue = typeof change === 'bigint' ? change : change.toBigInt();
71456
+ const existingValue = this.localDBXOR[key];
71457
+ if (existingValue === undefined) {
71458
+ this.localDBXOR[key] = changeValue;
71459
+ return;
71460
+ }
71461
+ this.localDBXOR[key] ^= changeValue;
71462
+ }
71463
+ merge(pending) {
71464
+ const { incrChanges, xorChanges } = pending.consume();
71465
+ // Merge incr changes
71466
+ for (const [key, value] of Object.entries(incrChanges)) {
71467
+ this.incrCompoundKey(key, value);
71468
+ }
71469
+ // Merge xor changes
71470
+ for (const [key, value] of Object.entries(xorChanges)) {
71471
+ this.xor(key, value);
71472
+ }
71473
+ }
71474
+ }
71475
+ exports.StatsPending = StatsPending;
71476
+ class Stats extends StatsPending {
70165
71477
  constructor(config) {
70166
- _Stats_instances.add(this);
70167
- _Stats_localDBIncr.set(this, {});
70168
- _Stats_localDBXOR.set(this, {});
71478
+ super();
70169
71479
  _Stats_syncPromise.set(this, void 0);
70170
71480
  _Stats_kv.set(this, void 0);
70171
71481
  let kv = config.kv;
@@ -70208,22 +71518,6 @@ class Stats {
70208
71518
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
70209
71519
  return ret;
70210
71520
  }
70211
- incr(arena, key, change = 1) {
70212
- const compoundKey = __classPrivateFieldGet(this, _Stats_instances, "m", _Stats_compoundKey).call(this, arena, key);
70213
- if (__classPrivateFieldGet(this, _Stats_localDBIncr, "f")[compoundKey] === undefined) {
70214
- __classPrivateFieldGet(this, _Stats_localDBIncr, "f")[compoundKey] = 0;
70215
- }
70216
- __classPrivateFieldGet(this, _Stats_localDBIncr, "f")[compoundKey] += change;
70217
- }
70218
- xor(key, change) {
70219
- const changeValue = change.toBigInt();
70220
- const existingValue = __classPrivateFieldGet(this, _Stats_localDBXOR, "f")[key];
70221
- if (existingValue === undefined) {
70222
- __classPrivateFieldGet(this, _Stats_localDBXOR, "f")[key] = changeValue;
70223
- return;
70224
- }
70225
- __classPrivateFieldGet(this, _Stats_localDBXOR, "f")[key] ^= changeValue;
70226
- }
70227
71521
  async getXor(key) {
70228
71522
  await __classPrivateFieldGet(this, _Stats_syncPromise, "f");
70229
71523
  const bufferKey = `@buffer:${key}`;
@@ -70233,8 +71527,8 @@ class Stats {
70233
71527
  base = BigInt(`0x${baseString}`);
70234
71528
  }
70235
71529
  let local = 0n;
70236
- if (__classPrivateFieldGet(this, _Stats_localDBXOR, "f")[key] !== undefined) {
70237
- local = __classPrivateFieldGet(this, _Stats_localDBXOR, "f")[key];
71530
+ if (this.localDBXOR[key] !== undefined) {
71531
+ local = this.localDBXOR[key];
70238
71532
  }
70239
71533
  const computed = base ^ local;
70240
71534
  const retval = new buffer_1.BufferStorage(computed, XOR_BUFFER_SIZE);
@@ -70260,7 +71554,7 @@ class Stats {
70260
71554
  }
70261
71555
  async get(arena, key) {
70262
71556
  await __classPrivateFieldGet(this, _Stats_syncPromise, "f");
70263
- const compoundKey = __classPrivateFieldGet(this, _Stats_instances, "m", _Stats_compoundKey).call(this, arena, key);
71557
+ const compoundKey = this.compoundKey(arena, key);
70264
71558
  let base = await __classPrivateFieldGet(this, _Stats_kv, "f").get('stats', compoundKey);
70265
71559
  if (base === undefined) {
70266
71560
  base = 0;
@@ -70272,8 +71566,8 @@ class Stats {
70272
71566
  throw (new Error('internal error: corrupt data in stats table'));
70273
71567
  }
70274
71568
  let local = 0;
70275
- if (__classPrivateFieldGet(this, _Stats_localDBIncr, "f")[compoundKey] !== undefined) {
70276
- local = __classPrivateFieldGet(this, _Stats_localDBIncr, "f")[compoundKey];
71569
+ if (this.localDBIncr[compoundKey] !== undefined) {
71570
+ local = this.localDBIncr[compoundKey];
70277
71571
  }
70278
71572
  return (base + local);
70279
71573
  }
@@ -70301,20 +71595,17 @@ class Stats {
70301
71595
  return (retval);
70302
71596
  }
70303
71597
  async sync() {
70304
- const localDBIncr = Object.entries(__classPrivateFieldGet(this, _Stats_localDBIncr, "f"));
70305
- const localDBXOR = Object.entries(__classPrivateFieldGet(this, _Stats_localDBXOR, "f"));
70306
- __classPrivateFieldSet(this, _Stats_localDBIncr, {}, "f");
70307
- __classPrivateFieldSet(this, _Stats_localDBXOR, {}, "f");
71598
+ const { incrChanges, xorChanges } = this.consume();
70308
71599
  await __classPrivateFieldGet(this, _Stats_syncPromise, "f");
70309
71600
  __classPrivateFieldSet(this, _Stats_syncPromise, (async () => {
70310
71601
  const updatePromises = [];
70311
- for (const [key, value] of localDBIncr) {
71602
+ for (const [key, value] of Object.entries(incrChanges)) {
70312
71603
  if (value === undefined) {
70313
71604
  continue;
70314
71605
  }
70315
71606
  updatePromises.push(__classPrivateFieldGet(this, _Stats_kv, "f").incr('stats', key, value));
70316
71607
  }
70317
- for (const [key, value] of localDBXOR) {
71608
+ for (const [key, value] of Object.entries(xorChanges)) {
70318
71609
  if (value === undefined) {
70319
71610
  continue;
70320
71611
  }
@@ -70329,10 +71620,7 @@ class Stats {
70329
71620
  }
70330
71621
  }
70331
71622
  exports.Stats = Stats;
70332
- _a = Stats, _Stats_localDBIncr = new WeakMap(), _Stats_localDBXOR = new WeakMap(), _Stats_syncPromise = new WeakMap(), _Stats_kv = new WeakMap(), _Stats_instances = new WeakSet(), _Stats_compoundKey = function _Stats_compoundKey(arena, key) {
70333
- const compoundKey = [arena, key].join('|');
70334
- return (compoundKey);
70335
- }, _Stats_assertDurationBreakdowns = function _Stats_assertDurationBreakdowns(durations) {
71623
+ _a = Stats, _Stats_syncPromise = new WeakMap(), _Stats_kv = new WeakMap(), _Stats_assertDurationBreakdowns = function _Stats_assertDurationBreakdowns(durations) {
70336
71624
  for (const duration of durations) {
70337
71625
  this.assertDurationBreakdown(duration);
70338
71626
  }
@@ -70394,7 +71682,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
70394
71682
  };
70395
71683
  var _ValidateASN1_schema, _BufferStorageASN1_data;
70396
71684
  Object.defineProperty(exports, "__esModule", ({ value: true }));
70397
- exports._Testing = exports.ASN1BigIntToBuffer = exports.ASN1IntegerToBigInt = exports.JStoASN1 = exports.ASN1toJS = exports.BufferStorageASN1 = exports.ValidateASN1 = exports.asn1 = void 0;
71685
+ exports._Testing = exports.ASN1BigIntToBuffer = exports.ASN1IntegerToBigInt = exports.JStoASN1 = exports.ASN1toJS = exports.BufferStorageASN1 = exports.ValidateASN1 = exports.ASN1CheckUtilities = exports.asn1 = void 0;
70398
71686
  exports.isASN1Object = isASN1Object;
70399
71687
  exports.isValidSequenceSchema = isValidSequenceSchema;
70400
71688
  const asn1js = __importStar(__webpack_require__(7813));
@@ -70525,7 +71813,16 @@ function isASN1Set(input) {
70525
71813
  }
70526
71814
  return (true);
70527
71815
  }
70528
- function isASN1ContextTag(input) {
71816
+ function isASN1ContextTagKind(input) {
71817
+ if (typeof input !== 'string') {
71818
+ return (false);
71819
+ }
71820
+ if (!(['explicit', 'implicit'].includes(input))) {
71821
+ return (false);
71822
+ }
71823
+ return (true);
71824
+ }
71825
+ function isASN1ContextTag(input, tagKind) {
70529
71826
  if (!isASN1Object(input)) {
70530
71827
  return (false);
70531
71828
  }
@@ -70538,6 +71835,12 @@ function isASN1ContextTag(input) {
70538
71835
  if (!('contains' in input) || input.contains === undefined) {
70539
71836
  return (false);
70540
71837
  }
71838
+ if (!('kind' in input) || !isASN1ContextTagKind(input.kind)) {
71839
+ return (false);
71840
+ }
71841
+ if (tagKind !== undefined && input.kind !== tagKind) {
71842
+ return (false);
71843
+ }
70541
71844
  return (true);
70542
71845
  }
70543
71846
  function isASN1BitString(input) {
@@ -70594,6 +71897,15 @@ function isStringValidForKind(input, kind) {
70594
71897
  }
70595
71898
  return (false);
70596
71899
  }
71900
+ exports.ASN1CheckUtilities = {
71901
+ isASN1Object,
71902
+ isASN1OID,
71903
+ isASN1String,
71904
+ isASN1Set,
71905
+ isASN1ContextTag,
71906
+ isASN1BitString,
71907
+ isASN1Date
71908
+ };
70597
71909
  /**
70598
71910
  * Checks if an ASN.1 sequence is valid based on a provided validation schema.
70599
71911
  */
@@ -71162,7 +72474,11 @@ class ValidateASN1 {
71162
72474
  * Given a schema, validate the ASN.1 object against it and return the
71163
72475
  * object as the validated type
71164
72476
  */
71165
- static againstSchema(input, schema) {
72477
+ static againstSchema(input, schemaIn) {
72478
+ let schema = schemaIn;
72479
+ if (typeof schema === 'function') {
72480
+ schema = schema();
72481
+ }
71166
72482
  let needsMoreAnalysis = false;
71167
72483
  if (util_1.types.isDate(input) && schema === ValidateASN1.IsDate) {
71168
72484
  /* XXX:TODO */
@@ -72055,17 +73371,45 @@ function fromDNSequenceToString(dn) {
72055
73371
  const retval = parts.join(', ');
72056
73372
  return (retval);
72057
73373
  }
73374
+ const defaultHashName = HashLib.HashFunctionName;
72058
73375
  class CertificateBuilder {
72059
73376
  constructor(params) {
72060
73377
  _CertificateBuilder_params.set(this, void 0);
72061
73378
  __classPrivateFieldSet(this, _CertificateBuilder_params, {
72062
- hashLib: {
72063
- hash: HashLib.Hash,
72064
- name: HashLib.HashFunctionName
72065
- },
72066
73379
  ...params
72067
73380
  }, "f");
72068
73381
  }
73382
+ static hashName(params, purpose) {
73383
+ const hashLib = params.hashLib;
73384
+ if (hashLib !== undefined) {
73385
+ switch (hashLib.name) {
73386
+ case 'sha256':
73387
+ case 'sha3-256':
73388
+ return (hashLib.name);
73389
+ default:
73390
+ throw (new Error(`internal error: Unsupported hash algorithm "${hashLib.name}"`));
73391
+ }
73392
+ }
73393
+ const hashName = params.hashParams?.defaults?.[purpose] ?? defaultHashName;
73394
+ return (hashName);
73395
+ }
73396
+ static hash(params, purpose, ...data) {
73397
+ /*
73398
+ * If the deprecated hashLib parameter is set, then use it
73399
+ * regardless of the algo parameter for backwards compatibility
73400
+ * even though it is not recommended to use it anymore
73401
+ */
73402
+ const hashLib = params.hashLib;
73403
+ if (hashLib !== undefined) {
73404
+ return (hashLib.hash(...data));
73405
+ }
73406
+ const hashName = this.hashName(params, purpose);
73407
+ const hashFunction = params.hashParams.functions?.[hashName];
73408
+ if (hashFunction === undefined) {
73409
+ throw (new Error(`internal error: Hash function "${hashName}" not found for purpose "${purpose}"`));
73410
+ }
73411
+ return (hashFunction(...data));
73412
+ }
72069
73413
  /**
72070
73414
  * Construct an extension
72071
73415
  */
@@ -72084,12 +73428,8 @@ class CertificateBuilder {
72084
73428
  /**
72085
73429
  * Convert a KeetaNet Account to a Key ID (for Subject Key Identifier)
72086
73430
  */
72087
- accountToKeyId(account) {
72088
- const hashLib = __classPrivateFieldGet(this, _CertificateBuilder_params, "f").hashLib;
72089
- if (hashLib === undefined) {
72090
- throw (new Error('"hashLib" not set'));
72091
- }
72092
- return (Buffer.from(hashLib.hash(Buffer.concat([
73431
+ accountToKeyId(params, account, purpose) {
73432
+ return (Buffer.from(CertificateBuilder.hash(params, purpose, Buffer.concat([
72093
73433
  Buffer.from('KeetaKey', 'utf-8'),
72094
73434
  account.publicKeyAndType
72095
73435
  ]), 20)));
@@ -72153,10 +73493,11 @@ class CertificateBuilder {
72153
73493
  extensions.push(
72154
73494
  /** Extension: Authority Key Identifier */
72155
73495
  CertificateBuilder.extension('2.5.29.35', [
72156
- { type: 'context', value: 0, kind: 'implicit', contains: this.accountToKeyId(params.issuer) }
73496
+ /** XXX:TODO: Copy the key ID from the issuer certificate's Subject Key Identifier if known */
73497
+ { type: 'context', value: 0, kind: 'implicit', contains: this.accountToKeyId(params, params.issuer, 'aki') }
72157
73498
  ]),
72158
73499
  /** Extension: Subject Key Identifier */
72159
- CertificateBuilder.extension('2.5.29.14', this.accountToKeyId(params.subjectPublicKey)));
73500
+ CertificateBuilder.extension('2.5.29.14', this.accountToKeyId(params, params.subjectPublicKey, 'ski')));
72160
73501
  return (extensions);
72161
73502
  }
72162
73503
  /**
@@ -72165,32 +73506,52 @@ class CertificateBuilder {
72165
73506
  getFinalParams(params) {
72166
73507
  const finalParams = {
72167
73508
  ...__classPrivateFieldGet(this, _CertificateBuilder_params, "f"),
72168
- ...params
73509
+ ...params,
73510
+ hashParams: {
73511
+ ...__classPrivateFieldGet(this, _CertificateBuilder_params, "f")?.hashParams,
73512
+ ...params?.hashParams,
73513
+ functions: {
73514
+ 'sha256': function (data, len) {
73515
+ throw (new Error('not implemented, please provide an implementation'));
73516
+ },
73517
+ [defaultHashName]: HashLib.Hash,
73518
+ ...__classPrivateFieldGet(this, _CertificateBuilder_params, "f")?.hashParams?.functions,
73519
+ ...params?.hashParams?.functions
73520
+ },
73521
+ defaults: {
73522
+ signature: defaultHashName,
73523
+ ski: defaultHashName,
73524
+ aki: defaultHashName,
73525
+ ...__classPrivateFieldGet(this, _CertificateBuilder_params, "f")?.hashParams?.defaults,
73526
+ ...params?.hashParams?.defaults
73527
+ }
73528
+ }
72169
73529
  };
72170
73530
  /* Validate that required parameters are set */
72171
73531
  const issuer = finalParams.issuer;
72172
73532
  if (issuer === undefined) {
72173
- throw (new Error('"issuer" not set'));
73533
+ throw (new certificate_1.default('CERTIFICATE_MISSING_FIELD', '"issuer" not set'));
72174
73534
  }
72175
73535
  const subjectPublicKey = finalParams.subjectPublicKey;
72176
73536
  if (subjectPublicKey === undefined) {
72177
- throw (new Error('"subject" not set'));
73537
+ throw (new certificate_1.default('CERTIFICATE_MISSING_FIELD', '"subject" not set'));
72178
73538
  }
72179
73539
  const validFrom = finalParams.validFrom;
72180
73540
  if (validFrom === undefined) {
72181
- throw (new Error('"validFrom" not set'));
73541
+ throw (new certificate_1.default('CERTIFICATE_MISSING_FIELD', '"validFrom" not set'));
72182
73542
  }
72183
73543
  const validTo = finalParams.validTo;
72184
73544
  if (validTo === undefined) {
72185
- throw (new Error('"validTo" not set'));
73545
+ throw (new certificate_1.default('CERTIFICATE_MISSING_FIELD', '"validTo" not set'));
72186
73546
  }
72187
73547
  const serial = finalParams.serial;
72188
73548
  if (serial === undefined) {
72189
- throw (new Error('"serialNumber" not set'));
73549
+ throw (new certificate_1.default('CERTIFICATE_MISSING_FIELD', '"serialNumber" not set'));
72190
73550
  }
72191
73551
  const hashLib = finalParams.hashLib;
72192
- if (hashLib === undefined) {
72193
- throw (new Error('"hashLib" not set'));
73552
+ const hashParams = finalParams.hashParams;
73553
+ if (hashParams === undefined) {
73554
+ throw (new certificate_1.default('CERTIFICATE_MISSING_FIELD', '"hashParams" not set'));
72194
73555
  }
72195
73556
  return ({
72196
73557
  ...finalParams,
@@ -72199,7 +73560,8 @@ class CertificateBuilder {
72199
73560
  validFrom,
72200
73561
  validTo,
72201
73562
  serial,
72202
- hashLib
73563
+ hashLib,
73564
+ hashParams
72203
73565
  });
72204
73566
  }
72205
73567
  /**
@@ -72207,13 +73569,13 @@ class CertificateBuilder {
72207
73569
  */
72208
73570
  async buildDER(params) {
72209
73571
  const finalParams = this.getFinalParams(params);
72210
- const hashLib = finalParams.hashLib;
72211
73572
  const { oid: signatureAlgorithmOID, hashData: hashData } = (function () {
73573
+ const hashName = CertificateBuilder.hashName(finalParams, 'signature');
72212
73574
  switch (finalParams.issuer.keyType) {
72213
73575
  case account_1.AccountKeyAlgorithm.ECDSA_SECP256K1:
72214
73576
  case account_1.AccountKeyAlgorithm.ECDSA_SECP256R1:
72215
73577
  return ({
72216
- oid: `${hashLib.name}WithEcDSA`,
73578
+ oid: `${hashName}WithEcDSA`,
72217
73579
  hashData: true
72218
73580
  });
72219
73581
  case account_1.AccountKeyAlgorithm.ED25519:
@@ -72281,7 +73643,7 @@ class CertificateBuilder {
72281
73643
  */
72282
73644
  let toSign;
72283
73645
  if (hashData) {
72284
- toSign = Buffer.from(hashLib.hash(tbsCertificateBuffer));
73646
+ toSign = Buffer.from(CertificateBuilder.hash(finalParams, 'signature', tbsCertificateBuffer));
72285
73647
  }
72286
73648
  else {
72287
73649
  toSign = tbsCertificateBuffer;
@@ -72503,7 +73865,7 @@ class Certificate {
72503
73865
  const tbsCertificate = parts[0];
72504
73866
  const [version, serialNumber, signatureAlgorithmSigned, issuer, [notBefore, notAfter], subject, subjectPublicKey, extensions] = tbsCertificate;
72505
73867
  if (version.contains !== 2n) {
72506
- throw (new Error('Only X509v3 certificates are supported'));
73868
+ throw (new certificate_1.default('CERTIFICATE_INVALID_VERSION', 'Only X509v3 certificates are supported'));
72507
73869
  }
72508
73870
  const signatureAlgorithm = parts[1];
72509
73871
  /**
@@ -72543,7 +73905,7 @@ class Certificate {
72543
73905
  const signatureAlgorithmSignedBuffer = new ASN1.BufferStorageASN1(signatureAlgorithmSigned).getDERBuffer();
72544
73906
  const signatureAlgorithmBuffer = new ASN1.BufferStorageASN1(signatureAlgorithm).getDERBuffer();
72545
73907
  if (!signatureAlgorithmSignedBuffer.equals(signatureAlgorithmBuffer)) {
72546
- throw (new Error('Signature algorithm mismatch'));
73908
+ throw (new certificate_1.default('CERTIFICATE_SIGNATURE_ALGORITHM_MISMATCH', 'Signature algorithm mismatch between signature and certificate'));
72547
73909
  }
72548
73910
  /*
72549
73911
  * Process the extensions base extensions, which can be critical for
@@ -72573,7 +73935,7 @@ class Certificate {
72573
73935
  }
72574
73936
  });
72575
73937
  if (!found) {
72576
- throw (new Error('Self-signed certificate is not a root CA in the Root CA store'));
73938
+ throw (new certificate_1.default('CERTIFICATE_SELF_SIGNED_VALIDATION_FAILED', 'Self-signed certificate is not a root CA in the Root CA store'));
72577
73939
  }
72578
73940
  this.chain = [this];
72579
73941
  }
@@ -72582,7 +73944,7 @@ class Certificate {
72582
73944
  this.chain = [this];
72583
73945
  }
72584
73946
  if (!this.verify(this)) {
72585
- throw (new Error('Self-signed certificate signature verification failed'));
73947
+ throw (new certificate_1.default('CERTIFICATE_SELF_SIGNED_VALIDATION_FAILED', 'Self-signed certificate signature verification failed'));
72586
73948
  }
72587
73949
  }
72588
73950
  else {
@@ -72592,7 +73954,7 @@ class Certificate {
72592
73954
  if (options?.store !== undefined) {
72593
73955
  const chain = this.verifyChain(options.store);
72594
73956
  if (chain === null || chain.length === 0) {
72595
- throw (new Error('Certificate chain verification failed'));
73957
+ throw (new certificate_1.default('CERTIFICATE_CHAIN_VERIFICATION_FAILED', 'Certificate chain verification failed'));
72596
73958
  }
72597
73959
  this.chain = chain;
72598
73960
  }
@@ -72657,7 +74019,7 @@ class Certificate {
72657
74019
  compatibleKeyTypes = [account_1.default.AccountKeyAlgorithm.ED25519];
72658
74020
  break;
72659
74021
  default:
72660
- throw (new Error(`Unsupported signature algorithm ${signatureAlgorithm}`));
74022
+ throw (new certificate_1.default('CERTIFICATE_INVALID_SIGNATURE_ALGORITHM', `Unsupported signature algorithm ${signatureAlgorithm}`));
72661
74023
  }
72662
74024
  let hashAlgorithm;
72663
74025
  switch (signatureAlgorithm) {
@@ -72671,7 +74033,7 @@ class Certificate {
72671
74033
  hashAlgorithm = null;
72672
74034
  break;
72673
74035
  default:
72674
- throw (new Error(`Unsupported signature algorithm ${signatureAlgorithm}`));
74036
+ throw (new certificate_1.default('CERTIFICATE_INVALID_SIGNATURE_ALGORITHM', `Unsupported signature algorithm ${signatureAlgorithm}`));
72675
74037
  }
72676
74038
  let accountIsCompatible = false;
72677
74039
  for (const checkCompatibleKeyType of compatibleKeyTypes) {
@@ -72681,7 +74043,7 @@ class Certificate {
72681
74043
  }
72682
74044
  }
72683
74045
  if (!accountIsCompatible) {
72684
- throw (new Error(`Account does not have a compatible key type for signature algorithm ${signatureAlgorithm}`));
74046
+ throw (new certificate_1.default('CERTIFICATE_INVALID_SIGNATURE_ALGORITHM', `Account does not have a compatible key type for signature algorithm ${signatureAlgorithm}`));
72685
74047
  }
72686
74048
  let dataToVerify;
72687
74049
  if (hashAlgorithm !== null) {
@@ -72708,7 +74070,7 @@ class Certificate {
72708
74070
  return (true);
72709
74071
  }
72710
74072
  if (certificates.size > 10) {
72711
- throw (new Error('Cannot currently handle more than 10 certificates in a graph'));
74073
+ throw (new certificate_1.default('CERTIFICATE_INVALID_GRAPH_COUNT', 'Cannot currently handle more than 10 certificates in a graph'));
72712
74074
  }
72713
74075
  const issuersFrom = [];
72714
74076
  const issuersTo = [];
@@ -72821,7 +74183,7 @@ class Certificate {
72821
74183
  assertValid(moment) {
72822
74184
  const valid = this.checkValid(moment, true);
72823
74185
  if (!valid.valid) {
72824
- throw (new Error(`Certificate is not valid: ${valid.reason}`));
74186
+ throw (new certificate_1.default('CERTIFICATE_MOMENT_INVALID', `Certificate is not valid: ${valid.reason}`));
72825
74187
  }
72826
74188
  }
72827
74189
  checkIssued(issuer, reason) {
@@ -72872,9 +74234,21 @@ class Certificate {
72872
74234
  }
72873
74235
  return (issuerCert.subjectPublicKey);
72874
74236
  }
74237
+ /**
74238
+ * Get the extensions present in the certificate -- this is the raw
74239
+ * extensions as they were parsed from the certificate, and may
74240
+ * contain extensions that are not processed by this class.
74241
+ */
74242
+ getExtensions() {
74243
+ this.assertConstructed();
74244
+ if (__classPrivateFieldGet(this, _Certificate_extensionsRaw, "f") === undefined) {
74245
+ return (undefined);
74246
+ }
74247
+ return (__classPrivateFieldGet(this, _Certificate_extensionsRaw, "f"));
74248
+ }
72875
74249
  assertConstructed() {
72876
74250
  if (!__classPrivateFieldGet(this, _Certificate_finalizeConstructionCalled, "f")) {
72877
- throw (new Error('finalizeConstruction not called'));
74251
+ throw (new Error('internal error: finalizeConstruction not called'));
72878
74252
  }
72879
74253
  }
72880
74254
  /**
@@ -73005,7 +74379,7 @@ _Certificate_raw = new WeakMap(), _Certificate_hash = new WeakMap(), _Certificat
73005
74379
  for (const extension of extensions) {
73006
74380
  const id = extension[0].oid;
73007
74381
  if (seenExtensions.has(id)) {
73008
- throw (new Error(`Duplicate extension ${id}`));
74382
+ throw (new certificate_1.default('CERTIFICATE_DUPLICATE_EXTENSION', `Duplicate extension ${id}`));
73009
74383
  }
73010
74384
  seenExtensions.add(id);
73011
74385
  }
@@ -73060,7 +74434,7 @@ _Certificate_raw = new WeakMap(), _Certificate_hash = new WeakMap(), _Certificat
73060
74434
  [id] = extension;
73061
74435
  }
73062
74436
  if (critical && !__classPrivateFieldGet(this, _Certificate_extensionsProcessed, "f").has(id.oid)) {
73063
- throw (new Error(`Critical extension ${id.oid} not processed`));
74437
+ throw (new certificate_1.default('CERTIFICATE_EXTENSION_NOT_PROCESSED', `Critical extension ${id.oid} not processed`));
73064
74438
  }
73065
74439
  }
73066
74440
  }, _Certificate_checkValid = function _Certificate_checkValid(moment) {
@@ -73738,6 +75112,7 @@ var _AsyncDisposableStackPolyfill_instances, _AsyncDisposableStackPolyfill_toDis
73738
75112
  Object.defineProperty(exports, "__esModule", ({ value: true }));
73739
75113
  exports.crypto = exports.AsyncDisposableStack = void 0;
73740
75114
  exports.bufferToArrayBuffer = bufferToArrayBuffer;
75115
+ exports.bufferToBigInt = bufferToBigInt;
73741
75116
  exports.isIntegerOrBigInt = isIntegerOrBigInt;
73742
75117
  exports.isBuffer = isBuffer;
73743
75118
  exports.arrayRepeat = arrayRepeat;
@@ -73773,6 +75148,13 @@ function bufferToArrayBuffer(input) {
73773
75148
  }
73774
75149
  return (out);
73775
75150
  }
75151
+ function bufferToBigInt(buffer) {
75152
+ let result = 0n;
75153
+ for (const byte of buffer) {
75154
+ result = (result << 8n) + BigInt(byte);
75155
+ }
75156
+ return (result);
75157
+ }
73776
75158
  /**
73777
75159
  * Check if a value is an integer or a bigint.
73778
75160
  */
@@ -74132,7 +75514,11 @@ function setGenerator(parent, rawEncode, rawDecode) {
74132
75514
  _map.set(this, void 0);
74133
75515
  this[_b] = `${parent.name}Set`;
74134
75516
  __classPrivateFieldSet(this, _map, new Map(), "f");
74135
- __classPrivateFieldSet(this, _set, new Set(data.map(item => encode(item, __classPrivateFieldGet(this, _map, "f")))), "f");
75517
+ __classPrivateFieldSet(this, _set, new Set, "f");
75518
+ // Use a loop since data could be an Iterable not always an array
75519
+ for (const item of data) {
75520
+ __classPrivateFieldGet(this, _set, "f").add(encode(item, __classPrivateFieldGet(this, _map, "f")));
75521
+ }
74136
75522
  }
74137
75523
  // Fit with new JS spec
74138
75524
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isSubsetOf
@@ -74350,7 +75736,7 @@ async function generateInitialVoteStaple(options) {
74350
75736
  blocks.recipientSupply = blocks.recipient;
74351
75737
  blocks.recipient = await new block_1.default.Builder({
74352
75738
  network: network,
74353
- signer: recipient,
75739
+ account: recipient,
74354
75740
  previous: getPrevious(recipient),
74355
75741
  operations: [{
74356
75742
  type: block_1.default.OperationType.SET_REP,
@@ -74454,9 +75840,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
74454
75840
  var __importDefault = (this && this.__importDefault) || function (mod) {
74455
75841
  return (mod && mod.__esModule) ? mod : { "default": mod };
74456
75842
  };
74457
- var _VoteBlockHashMap_instances, _VoteBlockHashMap_valueMap, _VoteBlockHashMap_keyMap, _VoteBlockHashMap_getLookupKey, _a, _PossiblyExpiredVote_vote, _PossiblyExpiredVote_options, _PossiblyExpiredVote__hash, _PossiblyExpiredVote__blocksHash, _VoteBlockBundle_value, _VoteBlockBundle_valueCompressed, _VoteBlockBundle__hash, _VoteBlockBundle__blocksHash, _VoteBuilder_account, _VoteBuilder_blocks, _VoteBuilder_fee;
75843
+ var _VoteBlockHashMap_instances, _VoteBlockHashMap_valueMap, _VoteBlockHashMap_keyMap, _VoteBlockHashMap_getLookupKey, _a, _VoteLikeBase_vote, _VoteLikeBase_options, _VoteLikeBase__hash, _VoteLikeBase__blocksHash, _VoteBlockBundle_value, _VoteBlockBundle_valueCompressed, _VoteBlockBundle__hash, _VoteBlockBundle__blocksHash, _BaseVoteBuilder_account, _BaseVoteBuilder_blocks, _BaseVoteBuilder_fee;
74458
75844
  Object.defineProperty(exports, "__esModule", ({ value: true }));
74459
- exports.Testing = exports.VoteBuilder = exports.VoteStaple = exports.VoteBlockBundle = exports.Vote = exports.PossiblyExpiredVote = exports.VoteBlockHash = exports.VoteBlockHashMap = void 0;
75845
+ exports.Testing = exports.VoteQuoteBuilder = exports.VoteBuilder = exports.BaseVoteBuilder = exports.VoteStaple = exports.VoteBlockBundle = exports.VoteQuote = exports.Vote = exports.PossiblyExpiredVote = exports.VoteBlockHash = exports.VoteBlockHashMap = void 0;
74460
75846
  const block_1 = __webpack_require__(6158);
74461
75847
  const hash_1 = __webpack_require__(7908);
74462
75848
  const account_1 = __importStar(__webpack_require__(9415));
@@ -74478,6 +75864,7 @@ const feeExtensionSchema = {
74478
75864
  value: 0,
74479
75865
  kind: 'explicit',
74480
75866
  contains: [
75867
+ asn1_1.ValidateASN1.IsBoolean,
74481
75868
  asn1_1.ValidateASN1.IsInteger,
74482
75869
  { optional: { type: 'context', value: 0, kind: 'implicit', contains: asn1_1.ValidateASN1.IsOctetString } },
74483
75870
  { optional: { type: 'context', value: 1, kind: 'implicit', contains: asn1_1.ValidateASN1.IsOctetString } }
@@ -74578,29 +75965,35 @@ function feeFromVote(input) {
74578
75965
  }
74579
75966
  })();
74580
75967
  const feeData = feeInformation.contains;
74581
- const retval = { amount: feeData[0] };
74582
- const payToAsn1 = feeData[1];
75968
+ const quote = feeData[0];
75969
+ const retval = {
75970
+ quote: quote,
75971
+ fee: {
75972
+ amount: feeData[1]
75973
+ }
75974
+ };
75975
+ const payToAsn1 = feeData[2];
74583
75976
  if (payToAsn1 !== undefined) {
74584
75977
  const payTo = account_1.default.fromPublicKeyAndType(Buffer.from(payToAsn1.contains));
74585
75978
  if (payTo.isStorage()) {
74586
- retval.payTo = payTo;
75979
+ retval.fee.payTo = payTo;
74587
75980
  }
74588
75981
  else {
74589
75982
  try {
74590
- retval.payTo = payTo.assertAccount();
75983
+ retval.fee.payTo = payTo.assertAccount();
74591
75984
  }
74592
75985
  catch {
74593
75986
  throw (new vote_1.default('VOTE_MALFORMED_FEES_PAY_TO_INVALID', 'internal error: payTo is not an Account or Storage Address'));
74594
75987
  }
74595
75988
  }
74596
75989
  }
74597
- const tokenAsn1 = feeData[2];
75990
+ const tokenAsn1 = feeData[3];
74598
75991
  if (tokenAsn1 !== undefined) {
74599
75992
  const token = account_1.default.fromPublicKeyAndType(Buffer.from(tokenAsn1.contains));
74600
75993
  if (!token.isToken()) {
74601
75994
  throw (new vote_1.default('VOTE_MALFORMED_FEES_TOKEN_NOT_TOKEN', 'internal error: fees extension token is not a valid token'));
74602
75995
  }
74603
- retval.token = token;
75996
+ retval.fee.token = token;
74604
75997
  }
74605
75998
  return (retval);
74606
75999
  }
@@ -74734,7 +76127,11 @@ class VoteBlockHash extends buffer_1.BufferStorage {
74734
76127
  exports.VoteBlockHash = VoteBlockHash;
74735
76128
  VoteBlockHash.isInstance = (0, helper_1.checkableGenerator)(VoteBlockHash);
74736
76129
  VoteBlockHash.Map = VoteBlockHashMap;
74737
- class PossiblyExpiredVote {
76130
+ class VoteLikeBase {
76131
+ getClass() {
76132
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
76133
+ return this.constructor;
76134
+ }
74738
76135
  static isValidJSON(voteJSON) {
74739
76136
  for (const checkField of ['issuer', 'serial', 'blocks', 'validityFrom', 'validityTo', 'signature']) {
74740
76137
  if (voteJSON[checkField] === undefined) {
@@ -74756,10 +76153,15 @@ class PossiblyExpiredVote {
74756
76153
  return (false);
74757
76154
  }
74758
76155
  }
76156
+ if ('quote' in voteJSON) {
76157
+ if (voteJSON['quote'] === undefined) {
76158
+ return (false);
76159
+ }
76160
+ }
74759
76161
  return (true);
74760
76162
  }
74761
76163
  static fromJSON(voteJSON, options = {}) {
74762
- if (!PossiblyExpiredVote.isValidJSON(voteJSON)) {
76164
+ if (!VoteLikeBase.isValidJSON(voteJSON)) {
74763
76165
  throw (new vote_1.default('VOTE_INVALID_CONSTRUCTION_JSON', 'Cannot construct vote, it is not a valid vote JSON object'));
74764
76166
  }
74765
76167
  const issuer = account_1.default.toAccount(voteJSON.issuer);
@@ -74778,22 +76180,29 @@ class PossiblyExpiredVote {
74778
76180
  const validTo = new Date(voteJSON.validityTo);
74779
76181
  const validFrom = new Date(voteJSON.validityFrom);
74780
76182
  const signatureStorage = new buffer_1.BufferStorage(signature, signature.byteLength);
76183
+ if (this.expectedQuoteValue !== (voteJSON.quote ?? false)) {
76184
+ throw (new vote_1.default('VOTE_MALFORMED_FEES_QUOTE_INVALID', `internal error: fee quote mismatch found ${voteJSON.quote} - expected ${this.expectedQuoteValue}`));
76185
+ }
76186
+ if (voteJSON.quote === true && voteJSON.fee === undefined) {
76187
+ throw (new vote_1.default('VOTE_FEE_QUOTE_MISSING_FEES', 'internal error: requested quote but no fees provided'));
76188
+ }
74781
76189
  if (voteJSON.fee !== undefined) {
74782
76190
  voteBuilder.addFee(voteJSON.fee);
74783
76191
  }
74784
76192
  const { voteData, tbsCertificate, signatureInfo } = voteBuilder.generateVoteData(BigInt(voteJSON.serial), validTo, validFrom);
74785
- const vote = voteBuilder.createVote(voteData, tbsCertificate, signatureInfo, signatureStorage, options);
74786
- return (vote);
76193
+ const vote = voteBuilder.createVote(voteData, tbsCertificate, signatureInfo, signatureStorage);
76194
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
76195
+ return new this(vote, options);
74787
76196
  }
74788
76197
  constructor(vote, options = {}) {
74789
76198
  this.$trusted = false;
74790
76199
  this.$permanent = false;
74791
- _PossiblyExpiredVote_vote.set(this, void 0);
74792
- _PossiblyExpiredVote_options.set(this, void 0);
74793
- _PossiblyExpiredVote__hash.set(this, void 0);
74794
- _PossiblyExpiredVote__blocksHash.set(this, void 0);
74795
- __classPrivateFieldSet(this, _PossiblyExpiredVote_options, { ...options }, "f");
74796
- if (PossiblyExpiredVote.isInstance(vote, false)) {
76200
+ _VoteLikeBase_vote.set(this, void 0);
76201
+ _VoteLikeBase_options.set(this, void 0);
76202
+ _VoteLikeBase__hash.set(this, void 0);
76203
+ _VoteLikeBase__blocksHash.set(this, void 0);
76204
+ __classPrivateFieldSet(this, _VoteLikeBase_options, { ...options }, "f");
76205
+ if (VoteLikeBase.isInstance(vote, false)) {
74797
76206
  this.issuer = vote.issuer;
74798
76207
  this.serial = vote.serial;
74799
76208
  this.blocks = vote.blocks;
@@ -74801,12 +76210,13 @@ class PossiblyExpiredVote {
74801
76210
  this.validityTo = vote.validityTo;
74802
76211
  this.signature = vote.signature;
74803
76212
  this.fee = vote.fee;
76213
+ this.quote = vote.quote;
74804
76214
  this.$trusted = vote.$trusted;
74805
76215
  this.$permanent = vote.$permanent;
74806
76216
  this.$uid = vote.$uid;
74807
76217
  this.$id = vote.$id;
74808
- __classPrivateFieldSet(this, _PossiblyExpiredVote_vote, __classPrivateFieldGet(vote, _PossiblyExpiredVote_vote, "f"), "f");
74809
- __classPrivateFieldSet(this, _PossiblyExpiredVote_options, __classPrivateFieldGet(vote, _PossiblyExpiredVote_options, "f"), "f");
76218
+ __classPrivateFieldSet(this, _VoteLikeBase_vote, __classPrivateFieldGet(vote, _VoteLikeBase_vote, "f"), "f");
76219
+ __classPrivateFieldSet(this, _VoteLikeBase_options, __classPrivateFieldGet(vote, _VoteLikeBase_options, "f"), "f");
74810
76220
  return;
74811
76221
  }
74812
76222
  if (typeof vote === 'string') {
@@ -74819,18 +76229,18 @@ class PossiblyExpiredVote {
74819
76229
  vote = (0, helper_1.bufferToArrayBuffer)(vote);
74820
76230
  }
74821
76231
  if (!(util_1.types.isArrayBuffer(vote))) {
74822
- if (PossiblyExpiredVote.isValidJSON(vote)) {
74823
- vote = PossiblyExpiredVote.fromJSON(vote).toBytes();
76232
+ if (VoteLikeBase.isValidJSON(vote)) {
76233
+ vote = VoteLikeBase.fromJSON(vote).toBytes();
74824
76234
  }
74825
76235
  else {
74826
- throw (new vote_1.default('VOTE_INVALID_CONSTRUCTION', 'internal error: invalid vote constructor argument in PossiblyExpiredVote'));
76236
+ throw (new vote_1.default('VOTE_INVALID_CONSTRUCTION', 'internal error: invalid vote constructor argument in VoteLikeBase'));
74827
76237
  }
74828
76238
  }
74829
- __classPrivateFieldSet(this, _PossiblyExpiredVote_vote, vote, "f");
76239
+ __classPrivateFieldSet(this, _VoteLikeBase_vote, vote, "f");
74830
76240
  /**
74831
76241
  * Vote Wrapper contains the vote, signature info, and signature
74832
76242
  */
74833
- const voteWrapper = (0, asn1_1.ASN1toJS)(__classPrivateFieldGet(this, _PossiblyExpiredVote_vote, "f"));
76243
+ const voteWrapper = (0, asn1_1.ASN1toJS)(__classPrivateFieldGet(this, _VoteLikeBase_vote, "f"));
74834
76244
  if (!Array.isArray(voteWrapper)) {
74835
76245
  throw (new vote_1.default('VOTE_MALFORMED_WRAPPER', 'internal error: Malformed vote wrapper (must be a sequence)'));
74836
76246
  }
@@ -74930,13 +76340,13 @@ class PossiblyExpiredVote {
74930
76340
  * Votes must not be expired
74931
76341
  */
74932
76342
  const expirationCheckMomentISO = new Date(expirationCheckMoment).toISOString();
74933
- if (expirationCheckMoment < (this.validityFrom.valueOf() - PossiblyExpiredVote.allowedSlop)) {
76343
+ if (expirationCheckMoment < (this.validityFrom.valueOf() - VoteLikeBase.allowedSlop)) {
74934
76344
  throw (new vote_1.default('VOTE_MOMENT_BEFORE_VALIDITY_FROM', `Vote was issued in the future (issued on ${validFrom.toISOString()}; moment: ${expirationCheckMomentISO})`));
74935
76345
  }
74936
76346
  /**
74937
76347
  * If the vote is forever viable, it is a permanent vote
74938
76348
  */
74939
- if (this.validityTo.valueOf() > (expirationCheckMoment + PossiblyExpiredVote.permanentVoteThreshold)) {
76349
+ if (this.validityTo.valueOf() > (expirationCheckMoment + VoteLikeBase.permanentVoteThreshold)) {
74940
76350
  this.$permanent = true;
74941
76351
  }
74942
76352
  /**
@@ -75001,7 +76411,7 @@ class PossiblyExpiredVote {
75001
76411
  throw (new vote_1.default('VOTE_MALFORMED_VOTE_EXTENSIONS', 'internal error: Expected extensions to be a Sequence'));
75002
76412
  }
75003
76413
  let blocks;
75004
- let fee;
76414
+ let feeAndKind;
75005
76415
  for (const extensionInfo of extensions) {
75006
76416
  if (!Array.isArray(extensionInfo)) {
75007
76417
  throw (new vote_1.default('VOTE_MALFORMED_VOTE_EXTENSIONS_VALUE', 'internal error: Expected each extension to be a Sequence'));
@@ -75034,7 +76444,7 @@ class PossiblyExpiredVote {
75034
76444
  break;
75035
76445
  case '1.3.6.1.4.1.62675.0.1.0':
75036
76446
  case 'fees': // replace with fees 1.3.6.1.4.1.62675.0.1.0
75037
- fee = feeFromVote(extensionData);
76447
+ feeAndKind = feeFromVote(extensionData);
75038
76448
  break;
75039
76449
  default:
75040
76450
  if (critical) {
@@ -75049,11 +76459,16 @@ class PossiblyExpiredVote {
75049
76459
  throw (new vote_1.default('VOTE_MALFORMED_VOTE_NO_BLOCKS_FOUND', 'No block hashes found within vote'));
75050
76460
  }
75051
76461
  this.blocks = blocks;
75052
- if (fee !== undefined) {
76462
+ if (feeAndKind !== undefined) {
75053
76463
  if (this.$permanent) {
75054
76464
  throw (new vote_1.default('VOTE_MALFORMED_FEES_IN_PERMANENT_VOTE', 'Permanent Vote cannot have fees'));
75055
76465
  }
75056
- this.fee = fee;
76466
+ // Get the expected quote value from any child instances and compare
76467
+ if (feeAndKind.quote !== this.getClass().expectedQuoteValue) {
76468
+ throw (new vote_1.default('VOTE_MALFORMED_FEES_QUOTE_INVALID', `internal error: fee quote mismatch found ${feeAndKind.quote} - expected ${this.getClass().expectedQuoteValue}`));
76469
+ }
76470
+ this.fee = feeAndKind.fee;
76471
+ this.quote = feeAndKind.quote;
75057
76472
  }
75058
76473
  /**
75059
76474
  * Get the signature data
@@ -75141,19 +76556,19 @@ class PossiblyExpiredVote {
75141
76556
  }
75142
76557
  }
75143
76558
  toBytes() {
75144
- return (__classPrivateFieldGet(this, _PossiblyExpiredVote_vote, "f"));
76559
+ return (__classPrivateFieldGet(this, _VoteLikeBase_vote, "f"));
75145
76560
  }
75146
76561
  get hash() {
75147
- if (!__classPrivateFieldGet(this, _PossiblyExpiredVote__hash, "f")) {
75148
- __classPrivateFieldSet(this, _PossiblyExpiredVote__hash, new VoteHash((0, hash_1.Hash)(Buffer.from(this.toBytes()))), "f");
76562
+ if (!__classPrivateFieldGet(this, _VoteLikeBase__hash, "f")) {
76563
+ __classPrivateFieldSet(this, _VoteLikeBase__hash, new VoteHash((0, hash_1.Hash)(Buffer.from(this.toBytes()))), "f");
75149
76564
  }
75150
- return (__classPrivateFieldGet(this, _PossiblyExpiredVote__hash, "f"));
76565
+ return (__classPrivateFieldGet(this, _VoteLikeBase__hash, "f"));
75151
76566
  }
75152
76567
  get blocksHash() {
75153
- if (!__classPrivateFieldGet(this, _PossiblyExpiredVote__blocksHash, "f")) {
75154
- __classPrivateFieldSet(this, _PossiblyExpiredVote__blocksHash, VoteBlockHash.fromVote(this), "f");
76568
+ if (!__classPrivateFieldGet(this, _VoteLikeBase__blocksHash, "f")) {
76569
+ __classPrivateFieldSet(this, _VoteLikeBase__blocksHash, VoteBlockHash.fromVote(this), "f");
75155
76570
  }
75156
- return (__classPrivateFieldGet(this, _PossiblyExpiredVote__blocksHash, "f"));
76571
+ return (__classPrivateFieldGet(this, _VoteLikeBase__blocksHash, "f"));
75157
76572
  }
75158
76573
  toString() {
75159
76574
  return (Buffer.from(this.toBytes()).toString('base64'));
@@ -75166,6 +76581,9 @@ class PossiblyExpiredVote {
75166
76581
  if (this.fee !== undefined) {
75167
76582
  additionalFields['fee'] = this.fee;
75168
76583
  }
76584
+ if (this.quote !== undefined) {
76585
+ additionalFields['quote'] = this.quote;
76586
+ }
75169
76587
  return ({
75170
76588
  issuer: this.issuer,
75171
76589
  serial: this.serial,
@@ -75182,8 +76600,8 @@ class PossiblyExpiredVote {
75182
76600
  }
75183
76601
  expirationCheckMoment() {
75184
76602
  let now;
75185
- if (__classPrivateFieldGet(this, _PossiblyExpiredVote_options, "f").now) {
75186
- now = __classPrivateFieldGet(this, _PossiblyExpiredVote_options, "f").now.valueOf();
76603
+ if (__classPrivateFieldGet(this, _VoteLikeBase_options, "f").now) {
76604
+ now = __classPrivateFieldGet(this, _VoteLikeBase_options, "f").now.valueOf();
75187
76605
  }
75188
76606
  else {
75189
76607
  now = Date.now();
@@ -75194,17 +76612,27 @@ class PossiblyExpiredVote {
75194
76612
  const now = this.expirationCheckMoment();
75195
76613
  const from = this.validityFrom.valueOf();
75196
76614
  const to = this.validityTo.valueOf();
75197
- if ((now + PossiblyExpiredVote.allowedSlop) < from || (now - PossiblyExpiredVote.allowedSlop) > to) {
76615
+ if ((now + VoteLikeBase.allowedSlop) < from || (now - VoteLikeBase.allowedSlop) > to) {
75198
76616
  return (true);
75199
76617
  }
75200
76618
  return (false);
75201
76619
  }
75202
76620
  }
76621
+ _VoteLikeBase_vote = new WeakMap(), _VoteLikeBase_options = new WeakMap(), _VoteLikeBase__hash = new WeakMap(), _VoteLikeBase__blocksHash = new WeakMap();
76622
+ VoteLikeBase.expectedQuoteValue = false;
76623
+ VoteLikeBase.allowedSlop = 60 /* s */ * 1000 /* ms */;
76624
+ VoteLikeBase.permanentVoteThreshold = 100 /* y */ * 365 /* d */ * 86400 /* s */ * 1000 /* ms */;
76625
+ VoteLikeBase.VoteBlocksHash = VoteBlockHash;
76626
+ VoteLikeBase.isInstance = (0, helper_1.checkableGenerator)(VoteLikeBase);
76627
+ class PossiblyExpiredVote extends VoteLikeBase {
76628
+ constructor(vote, options = {}) {
76629
+ super(vote, options);
76630
+ if (this.quote === true) {
76631
+ throw (new vote_1.default('VOTE_FEE_IS_QUOTE', `Tried to construct a vote but fee kind is QUOTE`));
76632
+ }
76633
+ }
76634
+ }
75203
76635
  exports.PossiblyExpiredVote = PossiblyExpiredVote;
75204
- _PossiblyExpiredVote_vote = new WeakMap(), _PossiblyExpiredVote_options = new WeakMap(), _PossiblyExpiredVote__hash = new WeakMap(), _PossiblyExpiredVote__blocksHash = new WeakMap();
75205
- PossiblyExpiredVote.allowedSlop = 60 /* s */ * 1000 /* ms */;
75206
- PossiblyExpiredVote.permanentVoteThreshold = 100 /* y */ * 365 /* d */ * 86400 /* s */ * 1000 /* ms */;
75207
- PossiblyExpiredVote.VoteBlocksHash = VoteBlockHash;
75208
76636
  PossiblyExpiredVote.isInstance = (0, helper_1.checkableGenerator)(PossiblyExpiredVote);
75209
76637
  /**
75210
76638
  * A vote is a certificate issued indicating that the issuer "vouches" for the
@@ -75223,6 +76651,26 @@ class Vote extends PossiblyExpiredVote {
75223
76651
  }
75224
76652
  exports.Vote = Vote;
75225
76653
  Vote.isInstance = (0, helper_1.checkableGenerator)(Vote);
76654
+ /**
76655
+ * A VoteQuote is a certificate issued indicating what the issuer will charge for fees
76656
+ */
76657
+ class VoteQuote extends VoteLikeBase {
76658
+ constructor(vote, options = {}) {
76659
+ super(vote, options);
76660
+ // We add this so both classes have different signatures
76661
+ this.isVoteQuote = true;
76662
+ if (this.expired) {
76663
+ const expirationCheckMomentISO = new Date(this.expirationCheckMoment()).toISOString();
76664
+ throw (new vote_1.default('VOTE_EXPIRED', `VoteQuote is expired (expired on ${this.validityTo.toISOString()}; issued on ${this.validityFrom.toISOString()}; moment: ${expirationCheckMomentISO})`));
76665
+ }
76666
+ if (!this.quote) {
76667
+ throw (new vote_1.default('VOTE_FEE_NOT_QUOTE', `Tried to construct a quote but fee kind is note QUOTE`));
76668
+ }
76669
+ }
76670
+ }
76671
+ exports.VoteQuote = VoteQuote;
76672
+ VoteQuote.expectedQuoteValue = true;
76673
+ VoteQuote.isInstance = (0, helper_1.checkableGenerator)(VoteQuote);
75226
76674
  /**
75227
76675
  * A vote staple is a distributable block consisting of one or more blocks
75228
76676
  * and one or more votes.
@@ -75440,8 +76888,11 @@ class VoteBlockBundle {
75440
76888
  votesStapled = (0, helper_1.bufferToArrayBuffer)(votesStapled);
75441
76889
  }
75442
76890
  if (!(util_1.types.isArrayBuffer(votesStapled))) {
75443
- if (VoteBlockBundle.isValidJSON(votesStapled)) {
75444
- votesStapled = VoteBlockBundle.fromJSON(votesStapled).toBytes(true);
76891
+ if (votesStapled instanceof VoteBlockBundle) {
76892
+ votesStapled = votesStapled.toBytes(true);
76893
+ }
76894
+ else if (VoteBlockBundle.isValidJSON(votesStapled)) {
76895
+ votesStapled = VoteBlockBundle.fromJSON(votesStapled, voteOptions).toBytes(true);
75445
76896
  }
75446
76897
  else {
75447
76898
  throw (new vote_1.default('VOTE_STAPLE_INVALID_CONSTRUCTION', 'internal error: votesStapled must be an ArrayBuffer'));
@@ -75648,33 +77099,34 @@ class VoteStaple extends VoteBlockBundle {
75648
77099
  }
75649
77100
  exports.VoteStaple = VoteStaple;
75650
77101
  VoteStaple.isInstance = (0, helper_1.checkableGenerator)(VoteStaple);
75651
- class VoteBuilder {
77102
+ class BaseVoteBuilder {
75652
77103
  constructor(account, blocks = [], options) {
75653
- _VoteBuilder_account.set(this, void 0);
75654
- _VoteBuilder_blocks.set(this, void 0);
75655
- _VoteBuilder_fee.set(this, undefined);
77104
+ _BaseVoteBuilder_account.set(this, void 0);
77105
+ _BaseVoteBuilder_blocks.set(this, void 0);
77106
+ _BaseVoteBuilder_fee.set(this, undefined);
77107
+ this.quote = false;
75656
77108
  if (!account_1.default.isInstance(account)) {
75657
77109
  throw (new vote_1.default('VOTE_BUILDER_INVALID_CONSTRUCTION', 'internal error: account must be an Account'));
75658
77110
  }
75659
- __classPrivateFieldSet(this, _VoteBuilder_account, account, "f");
75660
- __classPrivateFieldSet(this, _VoteBuilder_blocks, [], "f");
75661
- __classPrivateFieldSet(this, _VoteBuilder_fee, options?.fee, "f");
77111
+ __classPrivateFieldSet(this, _BaseVoteBuilder_account, account, "f");
77112
+ __classPrivateFieldSet(this, _BaseVoteBuilder_blocks, [], "f");
77113
+ __classPrivateFieldSet(this, _BaseVoteBuilder_fee, options?.fee, "f");
75662
77114
  this.addBlocks(blocks);
75663
77115
  }
75664
77116
  addBlocks(blocks) {
75665
77117
  for (const block of blocks) {
75666
77118
  if (block_1.Block.isInstance(block)) {
75667
- __classPrivateFieldGet(this, _VoteBuilder_blocks, "f").push(block.hash);
77119
+ __classPrivateFieldGet(this, _BaseVoteBuilder_blocks, "f").push(block.hash);
75668
77120
  continue;
75669
77121
  }
75670
77122
  if (typeof block === 'string') {
75671
- __classPrivateFieldGet(this, _VoteBuilder_blocks, "f").push(new block_1.BlockHash(block));
77123
+ __classPrivateFieldGet(this, _BaseVoteBuilder_blocks, "f").push(new block_1.BlockHash(block));
75672
77124
  continue;
75673
77125
  }
75674
77126
  if (!block_1.BlockHash.isInstance(block)) {
75675
77127
  throw (new vote_1.default('VOTE_BUILDER_INVALID_BLOCK_TYPE', 'internal error: block must be Block, BlockHash, or string'));
75676
77128
  }
75677
- __classPrivateFieldGet(this, _VoteBuilder_blocks, "f").push(block);
77129
+ __classPrivateFieldGet(this, _BaseVoteBuilder_blocks, "f").push(block);
75678
77130
  }
75679
77131
  }
75680
77132
  addBlock(block) {
@@ -75691,14 +77143,16 @@ class VoteBuilder {
75691
77143
  fee.payTo = payTo.assertAccount();
75692
77144
  }
75693
77145
  }
75694
- const token = account_1.default.toAccount(fee.token);
77146
+ const token = account_1.default.toAccount(feeInput.token);
75695
77147
  if (token !== undefined) {
75696
77148
  if (token.isToken()) {
75697
77149
  fee.token = token;
75698
77150
  }
75699
- throw (new vote_1.default('VOTE_MALFORMED_FEES_TOKEN_NOT_TOKEN', 'Fee Token should be of type TOKEN'));
77151
+ else {
77152
+ throw (new vote_1.default('VOTE_MALFORMED_FEES_TOKEN_NOT_TOKEN', 'Fee Token should be of type TOKEN'));
77153
+ }
75700
77154
  }
75701
- __classPrivateFieldSet(this, _VoteBuilder_fee, fee, "f");
77155
+ __classPrivateFieldSet(this, _BaseVoteBuilder_fee, fee, "f");
75702
77156
  }
75703
77157
  generateVoteData(serial, validTo, validFrom) {
75704
77158
  /**
@@ -75709,8 +77163,9 @@ class VoteBuilder {
75709
77163
  * Whether or not to hash the data we are signing
75710
77164
  */
75711
77165
  let hashData = false;
75712
- switch (__classPrivateFieldGet(this, _VoteBuilder_account, "f").keyType) {
77166
+ switch (__classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").keyType) {
75713
77167
  case account_1.AccountKeyAlgorithm.ECDSA_SECP256K1:
77168
+ case account_1.AccountKeyAlgorithm.ECDSA_SECP256R1:
75714
77169
  {
75715
77170
  /*
75716
77171
  * Use the default hashing function
@@ -75732,22 +77187,22 @@ class VoteBuilder {
75732
77187
  break;
75733
77188
  }
75734
77189
  /** Public Key */
75735
- const publicKey = __classPrivateFieldGet(this, _VoteBuilder_account, "f").publicKey.ASN1.getASN1();
77190
+ const publicKey = __classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").publicKey.ASN1.getASN1();
75736
77191
  /** Signature Information */
75737
77192
  const signatureInfo = [
75738
77193
  { type: 'oid', oid: signatureInfoOID }
75739
77194
  ];
75740
77195
  let feeExtension = undefined;
75741
- if (__classPrivateFieldGet(this, _VoteBuilder_fee, "f") !== undefined) {
77196
+ if (__classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f") !== undefined) {
75742
77197
  /** Amount for this vote */
75743
- const feeData = [__classPrivateFieldGet(this, _VoteBuilder_fee, "f").amount];
77198
+ const feeData = [this.quote, __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f").amount];
75744
77199
  /** Account to pay the fee too */
75745
- const payToPublicKey = __classPrivateFieldGet(this, _VoteBuilder_fee, "f").payTo?.publicKeyAndType;
77200
+ const payToPublicKey = __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f").payTo?.publicKeyAndType;
75746
77201
  if (payToPublicKey !== undefined) {
75747
77202
  feeData.push({ type: 'context', value: 0, kind: 'implicit', contains: payToPublicKey });
75748
77203
  }
75749
77204
  /** Token in which to pay the fee */
75750
- const tokenPublicKey = __classPrivateFieldGet(this, _VoteBuilder_fee, "f").token?.publicKeyAndType;
77205
+ const tokenPublicKey = __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f").token?.publicKeyAndType;
75751
77206
  if (tokenPublicKey !== undefined) {
75752
77207
  feeData.push({ type: 'context', value: 1, kind: 'implicit', contains: tokenPublicKey });
75753
77208
  }
@@ -75784,7 +77239,7 @@ class VoteBuilder {
75784
77239
  type: 'oid',
75785
77240
  oid: 'commonName'
75786
77241
  },
75787
- value: { type: 'string', kind: 'utf8', value: __classPrivateFieldGet(this, _VoteBuilder_account, "f").publicKeyString.get() }
77242
+ value: { type: 'string', kind: 'utf8', value: __classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").publicKeyString.get() }
75788
77243
  }
75789
77244
  ],
75790
77245
  /** Validity */
@@ -75834,7 +77289,7 @@ class VoteBuilder {
75834
77289
  /** Hash algorithm used to hash blocks */
75835
77290
  { type: 'oid', oid: hash_1.Hash.functionName },
75836
77291
  /** List of block hashes */
75837
- __classPrivateFieldGet(this, _VoteBuilder_blocks, "f").map(function (blockhash) {
77292
+ __classPrivateFieldGet(this, _BaseVoteBuilder_blocks, "f").map(function (blockhash) {
75838
77293
  return (blockhash.getBuffer());
75839
77294
  })
75840
77295
  ]
@@ -75858,11 +77313,11 @@ class VoteBuilder {
75858
77313
  signatureInfo: signatureInfo
75859
77314
  });
75860
77315
  }
75861
- createVote(voteData, tbsCertificate, signatureInfo, signature, voteOptions = {}) {
77316
+ createVote(voteData, tbsCertificate, signatureInfo, signature) {
75862
77317
  /**
75863
77318
  * Double-check that the signature we just created is valid for the data
75864
77319
  */
75865
- const verification = __classPrivateFieldGet(this, _VoteBuilder_account, "f").verify(voteData, signature, {
77320
+ const verification = __classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").verify(voteData, signature, {
75866
77321
  raw: true,
75867
77322
  forCert: true
75868
77323
  });
@@ -75881,16 +77336,16 @@ class VoteBuilder {
75881
77336
  * Vote: A DER-encoded certificate
75882
77337
  */
75883
77338
  const vote = certificate.toBER(false);
75884
- return (new Vote(vote, voteOptions));
77339
+ return (vote);
75885
77340
  }
75886
- async seal(serial, validTo, validFrom, voteOptions = {}) {
77341
+ async generate(serial, validTo, validFrom) {
75887
77342
  if (validFrom === undefined) {
75888
77343
  validFrom = new Date();
75889
77344
  }
75890
77345
  if (typeof serial !== 'bigint') {
75891
77346
  throw (new vote_1.default('VOTE_BUILDER_INVALID_SERIAL', `internal error: serial must be a bigint, instead got ${serial}`));
75892
77347
  }
75893
- if (validTo === null && __classPrivateFieldGet(this, _VoteBuilder_fee, "f") !== undefined) {
77348
+ if (validTo === null && __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f") !== undefined) {
75894
77349
  throw (new vote_1.default('VOTE_MALFORMED_FEES_IN_PERMANENT_VOTE', 'internal error: permanent votes should not have fees'));
75895
77350
  }
75896
77351
  if (validTo === null) {
@@ -75904,20 +77359,48 @@ class VoteBuilder {
75904
77359
  if (!(util_1.types.isDate(validFrom)) || !(util_1.types.isDate(validTo))) {
75905
77360
  throw (new vote_1.default('VOTE_BUILDER_INVALID_VALID_TO_FROM', 'internal error: validFrom must be Date'));
75906
77361
  }
77362
+ if (this.quote && __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f") === undefined) {
77363
+ throw (new vote_1.default('VOTE_FEE_QUOTE_MISSING_FEES', 'internal error: requested quote but no fees provided'));
77364
+ }
75907
77365
  const { voteData, tbsCertificate, signatureInfo } = this.generateVoteData(serial, validTo, validFrom);
75908
- const signature = await __classPrivateFieldGet(this, _VoteBuilder_account, "f").sign(voteData, {
77366
+ const signature = await __classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").sign(voteData, {
75909
77367
  raw: true,
75910
77368
  forCert: true
75911
77369
  });
75912
- const vote = this.createVote(voteData, tbsCertificate, signatureInfo, signature, voteOptions);
77370
+ const voteLike = this.createVote(voteData, tbsCertificate, signatureInfo, signature);
77371
+ return (voteLike);
77372
+ }
77373
+ }
77374
+ exports.BaseVoteBuilder = BaseVoteBuilder;
77375
+ _BaseVoteBuilder_account = new WeakMap(), _BaseVoteBuilder_blocks = new WeakMap(), _BaseVoteBuilder_fee = new WeakMap();
77376
+ BaseVoteBuilder.isInstance = (0, helper_1.checkableGenerator)(BaseVoteBuilder);
77377
+ class VoteBuilder extends BaseVoteBuilder {
77378
+ async seal(serial, validTo, validFrom, voteOptions = {}) {
77379
+ const vote = await super.generate(serial, validTo, validFrom);
75913
77380
  return (new Vote(vote, voteOptions));
75914
77381
  }
75915
77382
  }
75916
77383
  exports.VoteBuilder = VoteBuilder;
75917
- _VoteBuilder_account = new WeakMap(), _VoteBuilder_blocks = new WeakMap(), _VoteBuilder_fee = new WeakMap();
75918
77384
  VoteBuilder.isInstance = (0, helper_1.checkableGenerator)(VoteBuilder);
75919
- PossiblyExpiredVote.Staple = VoteStaple;
75920
- PossiblyExpiredVote.Builder = VoteBuilder;
77385
+ class VoteQuoteBuilder extends BaseVoteBuilder {
77386
+ constructor() {
77387
+ super(...arguments);
77388
+ this.quote = true;
77389
+ }
77390
+ async seal(serial, validTo, validFrom, voteOptions = {}) {
77391
+ const voteQuote = await super.generate(serial, validTo, validFrom);
77392
+ return (new VoteQuote(voteQuote, voteOptions));
77393
+ }
77394
+ }
77395
+ exports.VoteQuoteBuilder = VoteQuoteBuilder;
77396
+ VoteQuoteBuilder.isInstance = (0, helper_1.checkableGenerator)(VoteQuoteBuilder);
77397
+ // Add respective builders to each
77398
+ VoteLikeBase.Builder = BaseVoteBuilder;
77399
+ VoteQuote.Builder = VoteQuoteBuilder;
77400
+ Vote.Builder = VoteBuilder;
77401
+ // Add to default export
77402
+ Vote.Staple = VoteStaple;
77403
+ Vote.Quote = VoteQuote;
75921
77404
  exports["default"] = Vote;
75922
77405
  /** @internal */
75923
77406
  exports.Testing = { findRDN, blockHashesFromVote, feeFromVote };
@@ -75932,7 +77415,7 @@ exports.Testing = { findRDN, blockHashesFromVote, feeFromVote };
75932
77415
 
75933
77416
  Object.defineProperty(exports, "__esModule", ({ value: true }));
75934
77417
  exports.version = void 0;
75935
- exports.version = '0.12.2+g77a8a16ada9dfab5604b605cbe69d373a414d204';
77418
+ exports.version = '0.14.2+g68f40cc8d6fed6135fa06451bd1fb0691868e25f';
75936
77419
  exports["default"] = exports.version;
75937
77420
 
75938
77421