@keetanetwork/keetanet-client 0.12.2 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) 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/benchmarking/test.d.ts +4 -0
  6. package/client/builder.d.ts +6 -4
  7. package/client/client_common_tests.d.ts +18 -0
  8. package/client/index-browser.d.ts +42 -14
  9. package/client/index-browser.js +2068 -640
  10. package/client/index.d.ts +42 -14
  11. package/client/index.js +1964 -550
  12. package/config/index.d.ts +2 -0
  13. package/docs/assets/hierarchy.js +1 -1
  14. package/docs/assets/navigation.js +1 -1
  15. package/docs/assets/search.js +1 -1
  16. package/docs/classes/KeetaNetSDK.Client.html +14 -10
  17. package/docs/classes/KeetaNetSDK.Referenced.BaseSet.html +2 -2
  18. package/docs/classes/KeetaNetSDK.Referenced.BaseVoteBuilder.html +10 -0
  19. package/docs/classes/KeetaNetSDK.Referenced.Block.html +9 -5
  20. package/docs/classes/KeetaNetSDK.Referenced.BlockBuilder.html +3 -2
  21. package/docs/classes/KeetaNetSDK.Referenced.BlockHash.html +1 -1
  22. package/docs/classes/KeetaNetSDK.Referenced.BlockOperation.html +1 -1
  23. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationCREATE_IDENTIFIER.html +4 -4
  24. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationMANAGE_CERTIFICATE.html +1 -1
  25. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationMODIFY_PERMISSIONS.html +1 -1
  26. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationRECEIVE.html +1 -1
  27. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationSEND.html +1 -1
  28. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationSET_INFO.html +1 -1
  29. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationSET_REP.html +1 -1
  30. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationTOKEN_ADMIN_MODIFY_BALANCE.html +1 -1
  31. package/docs/classes/KeetaNetSDK.Referenced.BlockOperationTOKEN_ADMIN_SUPPLY.html +1 -1
  32. package/docs/classes/KeetaNetSDK.Referenced.Certificate.html +6 -2
  33. package/docs/classes/KeetaNetSDK.Referenced.CertificateHash.html +1 -1
  34. package/docs/classes/KeetaNetSDK.Referenced.ECDSAKeyPair.html +1 -1
  35. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1KeyPair.html +1 -1
  36. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1PrivateKey.html +1 -1
  37. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1PublicKey.html +1 -1
  38. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256K1Signature.html +1 -1
  39. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1KeyPair.html +1 -1
  40. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1PrivateKey.html +1 -1
  41. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1PublicKey.html +1 -1
  42. package/docs/classes/KeetaNetSDK.Referenced.ECDSASECP256R1Signature.html +1 -1
  43. package/docs/classes/KeetaNetSDK.Referenced.ED25519KeyPair.html +1 -1
  44. package/docs/classes/KeetaNetSDK.Referenced.ED25519PrivateKey.html +1 -1
  45. package/docs/classes/KeetaNetSDK.Referenced.ED25519PublicKey.html +1 -1
  46. package/docs/classes/KeetaNetSDK.Referenced.ED25519Signature.html +1 -1
  47. package/docs/classes/KeetaNetSDK.Referenced.ExternalKeyPair.html +1 -1
  48. package/docs/classes/KeetaNetSDK.Referenced.ExternalSet.html +1 -1
  49. package/docs/classes/KeetaNetSDK.Referenced.IdentifierKey.html +1 -1
  50. package/docs/classes/KeetaNetSDK.Referenced.IdentifierKeyPair.html +1 -1
  51. package/docs/classes/KeetaNetSDK.Referenced.KeetaNetError.html +1 -1
  52. package/docs/classes/KeetaNetSDK.Referenced.KeyInterface.html +1 -1
  53. package/docs/classes/KeetaNetSDK.Referenced.KeyStorage.html +1 -1
  54. package/docs/classes/KeetaNetSDK.Referenced.Ledger.html +5 -2
  55. package/docs/classes/KeetaNetSDK.Referenced.LedgerAtomicInterface.html +3 -1
  56. package/docs/classes/KeetaNetSDK.Referenced.P2PSwitch.html +6 -2
  57. package/docs/classes/KeetaNetSDK.Referenced.PermissionSetHolder.html +1 -1
  58. package/docs/classes/KeetaNetSDK.Referenced.PossiblyExpiredVote.html +31 -27
  59. package/docs/classes/KeetaNetSDK.Referenced.SignatureStorage.html +1 -1
  60. package/docs/classes/KeetaNetSDK.Referenced.UserClientBuilder.html +4 -3
  61. package/docs/classes/KeetaNetSDK.Referenced.Vote.html +7 -3
  62. package/docs/classes/KeetaNetSDK.Referenced.VoteBlockBundle.html +3 -3
  63. package/docs/classes/KeetaNetSDK.Referenced.VoteBlockHash.html +2 -2
  64. package/docs/classes/KeetaNetSDK.Referenced.VoteBuilder.html +10 -8
  65. package/docs/classes/KeetaNetSDK.Referenced.VoteHash.html +2 -2
  66. package/docs/classes/KeetaNetSDK.Referenced.VoteLikeBase.html +32 -0
  67. package/docs/classes/KeetaNetSDK.Referenced.VoteQuote.html +34 -0
  68. package/docs/classes/KeetaNetSDK.Referenced.VoteQuoteBuilder.html +11 -0
  69. package/docs/classes/KeetaNetSDK.Referenced.VoteStaple.html +3 -3
  70. package/docs/classes/KeetaNetSDK.Referenced.VoteStapleHash.html +2 -2
  71. package/docs/classes/KeetaNetSDK.Referenced.src_lib_utils_asn1.ValidateASN1.html +2 -2
  72. package/docs/classes/KeetaNetSDK.Referenced.src_lib_utils_buffer.BufferStorage.html +1 -1
  73. package/docs/classes/KeetaNetSDK.UserClient.html +7 -2
  74. package/docs/enums/KeetaNetSDK.Referenced.BaseFlag.html +2 -1
  75. package/docs/enums/KeetaNetSDK.Referenced.BasePermissionGroup.html +3 -1
  76. package/docs/enums/KeetaNetSDK.Referenced.BlockPurpose.html +3 -0
  77. package/docs/functions/KeetaNetSDK.Referenced.src_lib_utils_helper.bufferToBigInt.html +1 -0
  78. package/docs/hierarchy.html +1 -1
  79. package/docs/interfaces/KeetaNetSDK.PublishOptions.html +5 -0
  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.ComputedBlocksEffectFields.html +3 -2
  107. package/docs/interfaces/KeetaNetSDK.Referenced.Constructor.html +1 -1
  108. package/docs/interfaces/KeetaNetSDK.Referenced.CreateIdentifierRequest.html +4 -0
  109. package/docs/interfaces/KeetaNetSDK.Referenced.DisposableTimingHandle.html +1 -1
  110. package/docs/interfaces/KeetaNetSDK.Referenced.ExternalKeyPairFunctionsNoEncryption.html +1 -1
  111. package/docs/interfaces/KeetaNetSDK.Referenced.ExternalKeyPairFunctionsSupportsEncryption.html +1 -1
  112. package/docs/interfaces/KeetaNetSDK.Referenced.InitialConfigSupply.html +1 -1
  113. package/docs/interfaces/KeetaNetSDK.Referenced.InstanceSet.html +1 -1
  114. package/docs/interfaces/KeetaNetSDK.Referenced.KVGenericOptionsType.html +1 -1
  115. package/docs/interfaces/KeetaNetSDK.Referenced.KVSetOptionsType.html +1 -1
  116. package/docs/interfaces/KeetaNetSDK.Referenced.LedgerConfig.html +5 -3
  117. package/docs/interfaces/KeetaNetSDK.Referenced.LedgerStorageAPI.html +3 -3
  118. package/docs/interfaces/KeetaNetSDK.Referenced.ModifyTokenBalanceEntry.html +1 -1
  119. package/docs/interfaces/KeetaNetSDK.Referenced.MultiSigIdentifierCreateArguments.html +5 -0
  120. package/docs/interfaces/KeetaNetSDK.Referenced.MultisigConfig.html +3 -0
  121. package/docs/interfaces/KeetaNetSDK.Referenced.NumericValueEntry.html +1 -1
  122. package/docs/interfaces/KeetaNetSDK.Referenced.P2PConfig.html +4 -2
  123. package/docs/interfaces/KeetaNetSDK.Referenced.P2PPeerBase.html +1 -1
  124. package/docs/interfaces/KeetaNetSDK.Referenced.P2PPeerListener.html +1 -1
  125. package/docs/interfaces/KeetaNetSDK.Referenced.P2PPeerRepBase.html +4 -2
  126. package/docs/interfaces/KeetaNetSDK.Referenced.PrincipalACLWithInfoParsed.html +1 -0
  127. package/docs/interfaces/KeetaNetSDK.Referenced.PublicKeyStorage.html +1 -1
  128. package/docs/interfaces/KeetaNetSDK.Referenced.RequestTokenReceiveEntry.html +1 -1
  129. package/docs/interfaces/KeetaNetSDK.Referenced.TokenNumericEntry.html +1 -1
  130. package/docs/interfaces/KeetaNetSDK.Referenced.UserClientConfig.html +5 -3
  131. package/docs/interfaces/KeetaNetSDK.Referenced.UserClientOptions.html +4 -2
  132. package/docs/interfaces/KeetaNetSDK.Referenced.VoteJSON.html +3 -2
  133. package/docs/interfaces/KeetaNetSDK.Referenced.VoteStapleJSON.html +2 -2
  134. package/docs/interfaces/KeetaNetSDK.Referenced.WithIsInstance.html +1 -1
  135. package/docs/interfaces/KeetaNetSDK.Referenced.src_config.ValidationConfig.html +2 -2
  136. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1BitString.html +1 -1
  137. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1Date.html +1 -1
  138. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1OID.html +1 -1
  139. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1Set.html +1 -1
  140. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_asn1.ASN1String.html +1 -1
  141. package/docs/interfaces/KeetaNetSDK.Referenced.src_lib_utils_helper.InstanceSetConstructor.html +2 -2
  142. package/docs/modules/KeetaNetSDK.Referenced.html +1 -1
  143. package/docs/modules/KeetaNetSDK.Referenced.src_lib_utils_helper.html +1 -1
  144. package/docs/modules/KeetaNetSDK.html +2 -2
  145. package/docs/types/KeetaNetSDK.Referenced.BlockASN1SchemaWithoutSignature.html +1 -0
  146. package/docs/types/KeetaNetSDK.Referenced.BlockJSON.html +1 -0
  147. package/docs/types/KeetaNetSDK.Referenced.BlockJSONIncomplete.html +1 -1
  148. package/docs/types/KeetaNetSDK.Referenced.BlockOperationASN1SchemaType.html +1 -0
  149. package/docs/types/KeetaNetSDK.Referenced.BlockOperationTypes.html +1 -0
  150. package/docs/types/KeetaNetSDK.Referenced.BlockSignature.html +2 -0
  151. package/docs/types/KeetaNetSDK.Referenced.BlockSignatureField.html +1 -0
  152. package/docs/types/KeetaNetSDK.Referenced.BlockSignerField.html +1 -0
  153. package/docs/types/KeetaNetSDK.Referenced.BlockSignerFieldJSON.html +1 -0
  154. package/docs/types/KeetaNetSDK.Referenced.BlockV1ASN1WithoutSignature.html +1 -0
  155. package/docs/types/KeetaNetSDK.Referenced.BlockV2ASN1WithoutSignature.html +1 -0
  156. package/docs/types/KeetaNetSDK.Referenced.CertificateBuilderParams.html +8 -3
  157. package/docs/types/KeetaNetSDK.Referenced.ComputedEffectOfBlocks.html +2 -2
  158. package/docs/types/KeetaNetSDK.Referenced.GetAccountStateAPIResponseFormatted.html +1 -0
  159. package/docs/types/KeetaNetSDK.Referenced.HashNames.html +1 -0
  160. package/docs/types/KeetaNetSDK.Referenced.MultisigAddress.html +1 -0
  161. package/docs/types/KeetaNetSDK.Referenced.MultisigSignerField.html +1 -0
  162. package/docs/types/KeetaNetSDK.Referenced.MultisigSignerFieldJSON.html +1 -0
  163. package/docs/types/KeetaNetSDK.Referenced.OmitLastArrayValue.html +1 -0
  164. package/docs/types/KeetaNetSDK.Referenced.P2PUpdateOptions.html +1 -0
  165. package/docs/types/KeetaNetSDK.Referenced.UserEditableAccountInfo.html +1 -0
  166. package/docs/types/KeetaNetSDK.Referenced.src_config.NetworkConfig.html +1 -1
  167. package/docs/types/KeetaNetSDK.Referenced.src_lib_utils_asn1.ValidateASN1.Schema.html +1 -1
  168. package/docs/types/KeetaNetSDK.Referenced.src_lib_utils_asn1.ValidateASN1.SchemaMap.html +1 -1
  169. package/docs/variables/KeetaNetSDK.Referenced.BlockErrorCodes.html +1 -1
  170. package/docs/variables/KeetaNetSDK.Referenced.BlockOperationASN1Schema.html +2 -0
  171. package/docs/variables/KeetaNetSDK.Referenced.LedgerErrorCodes.html +1 -1
  172. package/docs/variables/KeetaNetSDK.Referenced.VoteErrorCodes.html +1 -1
  173. package/lib/block/index.d.ts +104 -36
  174. package/lib/block/operations.d.ts +31 -3
  175. package/lib/error/block.d.ts +1 -1
  176. package/lib/error/ledger.d.ts +1 -1
  177. package/lib/error/vote.d.ts +1 -1
  178. package/lib/ledger/common.d.ts +14 -1
  179. package/lib/ledger/db_dynamodb.d.ts +2 -2
  180. package/lib/ledger/db_postgres.d.ts +1 -1
  181. package/lib/ledger/db_spanner.d.ts +1 -1
  182. package/lib/ledger/db_spanner_helper.d.ts +28 -5
  183. package/lib/ledger/db_sqlite.d.ts +1 -1
  184. package/lib/ledger/effects.d.ts +10 -9
  185. package/lib/ledger/index.d.ts +17 -8
  186. package/lib/ledger/types.d.ts +10 -1
  187. package/lib/node/utils.d.ts +5 -0
  188. package/lib/p2p.d.ts +32 -0
  189. package/lib/permissions.d.ts +5 -2
  190. package/lib/utils/asn1.d.ts +4 -4
  191. package/lib/utils/certificate.d.ts +38 -1
  192. package/lib/utils/helper.d.ts +2 -1
  193. package/lib/vote.d.ts +55 -20
  194. package/package.json +1 -1
  195. package/version.d.ts +1 -1
  196. package/docs/interfaces/KeetaNetSDK.Referenced.BlockJSON.html +0 -11
  197. package/docs/interfaces/KeetaNetSDK.Referenced.BlockUnsignedCanonical.html +0 -11
  198. 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
  }
@@ -64030,34 +64809,37 @@ function ExportBlockOperations(operations) {
64030
64809
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
64031
64810
  return container;
64032
64811
  }
64812
+ function assertExplicitContextValueLike(input) {
64813
+ if (typeof input !== 'object' || input === null) {
64814
+ throw (new Error(`Found entry which is not a context ${String(input)}`));
64815
+ }
64816
+ if (!('type' in input) || input.type !== 'context') {
64817
+ throw (new Error(`Found entry which is not a context ${String(input)}`));
64818
+ }
64819
+ if (!('kind' in input) || input.kind !== 'explicit') {
64820
+ throw (new Error(`Found entry which is not an explicit context ${String(input)}`));
64821
+ }
64822
+ if (!('value' in input)) {
64823
+ throw (new Error(`Found entry which is not a numeric explicit context ${String(input)}`));
64824
+ }
64825
+ const typeInput = input.value;
64826
+ if (typeof typeInput !== 'number') {
64827
+ throw (new Error(`Found entry which is not a numeric explicit context ${String(input)}`));
64828
+ }
64829
+ if (!('contains' in input)) {
64830
+ throw (new Error(`Found entry which which lacks contains ${JSON.stringify(input)}`));
64831
+ }
64832
+ if (!Array.isArray(input.contains)) {
64833
+ throw (new Error(`Found entry which is not a Sequence ${input.contains}`));
64834
+ }
64835
+ }
64033
64836
  function ImportOperationsASN1(input, network) {
64034
64837
  const retval = [];
64035
64838
  for (const entryWrapper of input) {
64036
64839
  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)}`));
64056
- }
64840
+ assertExplicitContextValueLike(entryWrapper);
64841
+ const type = assertOperationType(entryWrapper.value);
64057
64842
  const entry = entryWrapper.contains;
64058
- if (!Array.isArray(entry)) {
64059
- throw (new Error(`Found entry which is not a Sequence ${entry}`));
64060
- }
64061
64843
  const typeStr = operationTypeToString(type);
64062
64844
  const operationSchema = BlockOperationASN1SchemaBase[typeStr];
64063
64845
  if (!operationSchema) {
@@ -64088,6 +64870,22 @@ function ImportOperationsASN1(input, network) {
64088
64870
  newKeyValue.validate(network);
64089
64871
  keyValueOut = newKeyValue;
64090
64872
  }
64873
+ else if (key === 'createArguments' && typeStr === 'CREATE_IDENTIFIER') {
64874
+ assertExplicitContextValueLike(keyValueIn);
64875
+ if (keyValueIn.value !== account_1.AccountKeyAlgorithm.MULTISIG) {
64876
+ throw (new Error('unrecognized type for multisig create arguments'));
64877
+ }
64878
+ if (keyValueIn.contains.length !== 2 || !Array.isArray(keyValueIn.contains[0])) {
64879
+ throw (new Error('Invalid createArgs container'));
64880
+ }
64881
+ keyValueOut = {
64882
+ type: keyValueIn.value,
64883
+ signers: keyValueIn.contains[0].map(function (value) {
64884
+ return (account_1.default.fromPublicKeyAndType(value));
64885
+ }),
64886
+ quorum: keyValueIn.contains[1]
64887
+ };
64888
+ }
64091
64889
  else if (Array.isArray(keyValueIn) && key === 'intermediateCertificates') {
64092
64890
  keyValueOut = new certificate_1.CertificateBundle(keyValueIn.map(function (certificate) {
64093
64891
  return (new certificate_1.Certificate(certificate));
@@ -64095,7 +64893,7 @@ function ImportOperationsASN1(input, network) {
64095
64893
  }
64096
64894
  else if ((0, helper_1.isBuffer)(keyValueIn)) {
64097
64895
  if (type === OperationType.MANAGE_CERTIFICATE && key === 'certificateOrHash') {
64098
- const method = (0, _1.assertAdjustMethod)(operation['method'], true);
64896
+ const method = (0, _1.toAdjustMethod)(operation['method']);
64099
64897
  if (method === _2.AdjustMethod.SUBTRACT) {
64100
64898
  keyValueOut = new certificate_1.CertificateHash(keyValueIn);
64101
64899
  }
@@ -64187,6 +64985,13 @@ const BlockErrorCodes = [
64187
64985
  'ONLY_IDENTIFIER_OP',
64188
64986
  'NO_TOKEN_OP',
64189
64987
  'NO_IDENTIFIER_OP',
64988
+ 'INVALID_SIGNER',
64989
+ 'INVALID_PURPOSE_VALIDATION',
64990
+ 'INVALID_MULTISIG_QUORUM',
64991
+ 'INVALID_MULTISIG_SIGNER_DEPTH',
64992
+ 'INVALID_MULTISIG_SIGNER_COUNT',
64993
+ 'INVALID_MULTISIG_SIGNER_DUPLICATE',
64994
+ 'INVALID_CREATE_IDENTIFIER_ARGS',
64190
64995
  'NO_MULTISIG_OP',
64191
64996
  'IDENTIFIER_INVALID',
64192
64997
  'GENERAL_FIELD_INVALID',
@@ -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
  */
@@ -65335,18 +66170,24 @@ class LedgerStorageBase {
65335
66170
  }
65336
66171
  ret.defaultPermission = new permissions_1.Permissions(baseSet, externalSet);
65337
66172
  }
65338
- if (account.keyType === account_1.AccountKeyAlgorithm.TOKEN) {
66173
+ if (account.isToken()) {
65339
66174
  ret.supply = BigInt(row.supply ?? 0);
65340
66175
  }
66176
+ if (account.isMultisig() && row.multisigQuorum !== undefined) {
66177
+ ret.multisigQuorum = BigInt(row.multisigQuorum);
66178
+ }
65341
66179
  return (ret);
65342
66180
  }
65343
66181
  _validateAccountInfoKeys(account, info) {
65344
66182
  const validKeys = ['name', 'description', 'metadata'];
65345
66183
  if (account.isIdentifier()) {
65346
66184
  validKeys.push('defaultPermission');
65347
- }
65348
- if (account.keyType === account_1.AccountKeyAlgorithm.TOKEN) {
65349
- validKeys.push('supply');
66185
+ if (account.isToken()) {
66186
+ validKeys.push('supply');
66187
+ }
66188
+ if (account.isMultisig()) {
66189
+ validKeys.push('multisigQuorum');
66190
+ }
65350
66191
  }
65351
66192
  const keys = Object.keys(info);
65352
66193
  const foundBannedKey = keys.find(function (key) {
@@ -65356,6 +66197,33 @@ class LedgerStorageBase {
65356
66197
  throw (new ledger_1.default('LEDGER_INVALID_ACCOUNT_INFO_KEY', `Invalid AccountInfo field ${foundBannedKey}`));
65357
66198
  }
65358
66199
  }
66200
+ /**
66201
+ * @param moment - The date to use as the base for the timestamp.
66202
+ * @param momentBits - The number of bits to use for the timestamp
66203
+ * @param totalLength - The total length of the generated number in bits
66204
+ * @param randomData - A hexadecimal string to use as the random data.
66205
+ * @param timestampFuzzMS - The number of milliseconds to fuzz the timestamp by, defaults to 1n (precise).
66206
+ * @param optimistic - If true, the timestamp will be incremented by 1 quanta, defaults to false.
66207
+ * @returns A bigint representing the noisy timestamp.
66208
+ */
66209
+ _generateNoisyTimestamp(moment, momentBits, totalLength, randomData, timestampFuzzMS = 1, optimistic = false) {
66210
+ if (timestampFuzzMS > Number.MAX_SAFE_INTEGER) {
66211
+ throw (new Error('timestampFuzzMs is too large'));
66212
+ }
66213
+ const timestampFuzz = BigInt(Math.ceil(Math.log2(Number(timestampFuzzMS))));
66214
+ const length = totalLength - momentBits;
66215
+ if (BigInt(randomData.length * 8) < (length + timestampFuzz)) {
66216
+ throw (new Error('randomData is too short for the specified bit length'));
66217
+ }
66218
+ if (length < 0n) {
66219
+ throw (new Error('momentBits should be less than totalLength'));
66220
+ }
66221
+ const timestamp = BigInt(moment.valueOf()) >> timestampFuzz;
66222
+ const mask = (1n << (length + timestampFuzz)) - 1n;
66223
+ const upperBits = (timestamp + (optimistic ? 1n : 0n)) << (length + timestampFuzz);
66224
+ const lowerBits = (0, helper_1.bufferToBigInt)(randomData) & mask;
66225
+ return (upperBits | lowerBits);
66226
+ }
65359
66227
  async getHeadBlock(transaction, account, from) {
65360
66228
  const response = await this.getHeadBlocks(transaction, [account], from);
65361
66229
  const pubKey = account.publicKeyString.get();
@@ -65372,9 +66240,9 @@ class LedgerStorageBase {
65372
66240
  }
65373
66241
  return (null);
65374
66242
  }
65375
- async gc(transaction) {
66243
+ async gc(transaction, timeLimitMS = 280000) {
65376
66244
  let lastGCResult = false;
65377
- for (const startTime = Date.now(); Date.now() - startTime < 280000;) {
66245
+ for (const startTime = Date.now(); Date.now() - startTime < timeLimitMS;) {
65378
66246
  const gcResult = await this.gcBatch(transaction);
65379
66247
  lastGCResult = gcResult;
65380
66248
  if (!gcResult) {
@@ -65434,8 +66302,38 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
65434
66302
  exports.computeEffectOfBlocks = computeEffectOfBlocks;
65435
66303
  const account_1 = __importStar(__webpack_require__(9415));
65436
66304
  const block_1 = __webpack_require__(6158);
66305
+ const operations_1 = __webpack_require__(2778);
65437
66306
  const permissions_1 = __webpack_require__(5860);
65438
66307
  const certificate_1 = __webpack_require__(5661);
66308
+ ;
66309
+ /**
66310
+ * Base Fee Units per Block
66311
+ */
66312
+ const baseBlockFeeUnit = 1000n;
66313
+ /**
66314
+ * Fee Unit for an Opening Block
66315
+ */
66316
+ const openingBlockFeeUnit = 10000n;
66317
+ /**
66318
+ * Operation specific Fee Units
66319
+ */
66320
+ const operationFeeUnitOverrides = {
66321
+ [operations_1.OperationType.SEND]: 10n,
66322
+ [operations_1.OperationType.SET_REP]: 20n,
66323
+ [operations_1.OperationType.SET_INFO]: 100n,
66324
+ [operations_1.OperationType.MODIFY_PERMISSIONS]: 20n,
66325
+ [operations_1.OperationType.CREATE_IDENTIFIER]: 200n,
66326
+ [operations_1.OperationType.TOKEN_ADMIN_SUPPLY]: 10n,
66327
+ [operations_1.OperationType.TOKEN_ADMIN_MODIFY_BALANCE]: 10n,
66328
+ [operations_1.OperationType.RECEIVE]: 10n,
66329
+ [operations_1.OperationType.MANAGE_CERTIFICATE]: 100n
66330
+ };
66331
+ /**
66332
+ * Get the Fee Unit for a given operation type
66333
+ */
66334
+ function getOperationFeeUnit(operation) {
66335
+ return (operationFeeUnitOverrides[operation]);
66336
+ }
65439
66337
  function addOrCombineRequirements(existing, addition, alwaysCombine) {
65440
66338
  const resp = [...existing];
65441
66339
  let additionTarget;
@@ -65538,6 +66436,19 @@ function addPermissionRequirement(state, requirement) {
65538
66436
  const existing = state.accounts[principalPubKey].fields.permissionRequirements ?? [];
65539
66437
  state.accounts[principalPubKey].fields.permissionRequirements = addOrCombineRequirements(existing, requirement, true);
65540
66438
  }
66439
+ function updateMinSignerSetLength(state, multisigAccount, count) {
66440
+ const multisigPublicKey = multisigAccount.publicKeyString.get();
66441
+ if (state.accounts[multisigPublicKey] === undefined) {
66442
+ state.accounts[multisigPublicKey] = {
66443
+ account: multisigAccount,
66444
+ fields: {}
66445
+ };
66446
+ }
66447
+ const current = state.accounts[multisigPublicKey].fields.minSignerSetLength;
66448
+ if (current === undefined || current > count) {
66449
+ state.accounts[multisigPublicKey].fields.minSignerSetLength = count;
66450
+ }
66451
+ }
65541
66452
  function modifyBalanceInState(balanceState) {
65542
66453
  const { state, account, token, method, amount, otherAccount } = balanceState;
65543
66454
  const accountPubKey = account.publicKeyString.get();
@@ -65582,6 +66493,32 @@ function modifyBalanceInState(balanceState) {
65582
66493
  }
65583
66494
  accountBalanceInfo[tokenPubKey] = tokenField;
65584
66495
  }
66496
+ function updateAccountInfoInState(state, account, info) {
66497
+ const accountPubKey = account.publicKeyString.get();
66498
+ const toUpdate = {
66499
+ name: info.name,
66500
+ description: info.description,
66501
+ metadata: info.metadata
66502
+ };
66503
+ if (account.isIdentifier()) {
66504
+ if (info.defaultPermission !== undefined) {
66505
+ toUpdate.defaultPermission = info.defaultPermission;
66506
+ }
66507
+ if (account.isMultisig() && info.multisigQuorum !== undefined) {
66508
+ toUpdate.multisigQuorum = info.multisigQuorum;
66509
+ }
66510
+ }
66511
+ else {
66512
+ state.possibleNewAccounts.add(account);
66513
+ }
66514
+ if (!state.accounts[accountPubKey]) {
66515
+ state.accounts[accountPubKey] = {
66516
+ account: account,
66517
+ fields: {}
66518
+ };
66519
+ }
66520
+ state.accounts[accountPubKey].fields.info = toUpdate;
66521
+ }
65585
66522
  /**
65586
66523
  * Compute the effect of a SEND operation
65587
66524
  */
@@ -65709,34 +66646,39 @@ function computeEffectOfOperationCREATE_IDENTIFIER(state, block, operation, cont
65709
66646
  }
65710
66647
  state.possibleNewAccounts.add(operation.identifier);
65711
66648
  state.accounts[accountPubKey].fields.createRequests?.push({
65712
- previousBlockHash: block.previous,
65713
- account: block.account,
65714
- requestedIdentifier: operation.identifier,
65715
- operationIndex: context.operationIndex
66649
+ createdIdentifier: operation.identifier,
66650
+ createArguments: operation.createArguments
65716
66651
  });
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'])
65722
- });
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;
66652
+ if (operation.identifier.isMultisig()) {
66653
+ if (!operation.createArguments || operation.createArguments.type !== account_1.AccountKeyAlgorithm.MULTISIG) {
66654
+ throw (new Error('Invalid identifier creation arguments'));
66655
+ }
66656
+ updateAccountInfoInState(state, operation.identifier, { multisigQuorum: operation.createArguments.quorum });
66657
+ for (const multisigSigner of operation.createArguments.signers) {
66658
+ addPermission(state, {
66659
+ principal: multisigSigner,
66660
+ entity: operation.identifier,
66661
+ method: block_1.Block.AdjustMethod.SET,
66662
+ permissions: new permissions_1.Permissions(['MULTISIG_SIGNER'])
66663
+ });
65734
66664
  }
65735
66665
  }
65736
66666
  else {
65737
- state.possibleNewAccounts.add(block.account);
66667
+ addPermission(state, {
66668
+ principal: block.account,
66669
+ entity: operation.identifier,
66670
+ method: block_1.Block.AdjustMethod.SET,
66671
+ permissions: new permissions_1.Permissions(['OWNER'])
66672
+ });
65738
66673
  }
65739
- state.accounts[accountPubKey].fields.info = toUpdate;
66674
+ }
66675
+ function computeEffectOfOperationSET_INFO(state, block, operation) {
66676
+ updateAccountInfoInState(state, block.account, {
66677
+ name: operation.name,
66678
+ description: operation.description,
66679
+ metadata: operation.metadata,
66680
+ defaultPermission: operation.defaultPermission
66681
+ });
65740
66682
  }
65741
66683
  function computeEffectOfOperationMODIFY_PERMISSIONS(state, block, operation) {
65742
66684
  state.possibleNewAccounts.add(operation.principal);
@@ -65977,7 +66919,7 @@ function computePermissionEffect(state, type, effect, block, operation, context)
65977
66919
  };
65978
66920
  switch (type) {
65979
66921
  case 'SIGNER':
65980
- baseRequirement.principal = block.signer;
66922
+ baseRequirement.principal = block.principal;
65981
66923
  baseRequirement.entity = block.account;
65982
66924
  break;
65983
66925
  case 'ACCOUNT':
@@ -66033,7 +66975,8 @@ function computeEffectOfBlocks(blocks, ledger) {
66033
66975
  possibleNewAccounts: new account_1.default.Set(),
66034
66976
  metadata: {
66035
66977
  blockCount: 0,
66036
- operationCount: 0
66978
+ operationCount: 0,
66979
+ feeUnits: 0n
66037
66980
  }
66038
66981
  };
66039
66982
  let onlyReturnTouched = false;
@@ -66048,13 +66991,26 @@ function computeEffectOfBlocks(blocks, ledger) {
66048
66991
  */
66049
66992
  for (const block of blocks) {
66050
66993
  accumulatedEffects.metadata.blockCount++;
66994
+ accumulatedEffects.metadata.feeUnits += baseBlockFeeUnit;
66051
66995
  const blockAccountPubKey = block.account.publicKeyString.get();
66052
- accumulatedEffects.touched.add(block.signer);
66996
+ const signerQueue = [block.signer];
66997
+ while (signerQueue.length > 0) {
66998
+ // We can assume that the signerFieldQueue is not empty here since the loop condition checks it
66999
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67000
+ const signer = signerQueue.shift();
67001
+ if (account_1.default.isInstance(signer)) {
67002
+ accumulatedEffects.touched.add(signer);
67003
+ continue;
67004
+ }
67005
+ accumulatedEffects.touched.add(signer[0]);
67006
+ signerQueue.push(...signer[1]);
67007
+ }
66053
67008
  if (block.$opening) {
66054
67009
  accumulatedEffects.possibleNewAccounts.add(block.account);
67010
+ accumulatedEffects.metadata.feeUnits += openingBlockFeeUnit;
66055
67011
  }
66056
- if (!(block.signer.comparePublicKey(block.account))) {
66057
- accumulatedEffects.possibleNewAccounts.add(block.signer);
67012
+ if (!(block.principal.comparePublicKey(block.account))) {
67013
+ accumulatedEffects.possibleNewAccounts.add(block.principal);
66058
67014
  }
66059
67015
  if (accumulatedEffects.accounts[blockAccountPubKey] === undefined) {
66060
67016
  accumulatedEffects.accounts[blockAccountPubKey] = {
@@ -66069,12 +67025,13 @@ function computeEffectOfBlocks(blocks, ledger) {
66069
67025
  const context = {
66070
67026
  ledger,
66071
67027
  operationIndex: Number(operationIndex),
66072
- signedByDifferent: !block.account.comparePublicKey(block.signer),
67028
+ signedByDifferent: !block.account.comparePublicKey(block.principal),
66073
67029
  openingBlock: block.$opening
66074
67030
  };
66075
67031
  const operation = block.operations[operationIndex];
66076
67032
  const handler = operationHandlers[operation.type];
66077
67033
  accumulatedEffects.metadata.operationCount++;
67034
+ accumulatedEffects.metadata.feeUnits += getOperationFeeUnit(operation.type);
66078
67035
  if (handler.accountPermissionACL) {
66079
67036
  computePermissionEffect(accumulatedEffects, 'ACCOUNT', handler.accountPermissionACL, block, operation, context);
66080
67037
  }
@@ -66084,6 +67041,30 @@ function computeEffectOfBlocks(blocks, ledger) {
66084
67041
  permissionEffect = handler.signerPermissionACL;
66085
67042
  }
66086
67043
  computePermissionEffect(accumulatedEffects, 'SIGNER', permissionEffect, block, operation, context);
67044
+ if (Array.isArray(block.signer)) {
67045
+ const signerFieldQueue = [block.signer];
67046
+ while (signerFieldQueue.length > 0) {
67047
+ // We can assume that the signerFieldQueue is not empty here since the loop condition checks it
67048
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67049
+ const [multisig, signers] = signerFieldQueue.shift();
67050
+ updateMinSignerSetLength(accumulatedEffects, multisig, BigInt(signers.length));
67051
+ for (const signer of signers) {
67052
+ let principal;
67053
+ if (account_1.default.isInstance(signer)) {
67054
+ principal = signer;
67055
+ }
67056
+ else {
67057
+ principal = signer[0];
67058
+ signerFieldQueue.push(signer);
67059
+ }
67060
+ addPermissionRequirement(accumulatedEffects, {
67061
+ entity: multisig,
67062
+ principal: principal,
67063
+ permissions: new permissions_1.Permissions(['MULTISIG_SIGNER'])
67064
+ });
67065
+ }
67066
+ }
67067
+ }
66087
67068
  }
66088
67069
  handler.effectGenerator(accumulatedEffects, block, operation, context);
66089
67070
  }
@@ -66197,7 +67178,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
66197
67178
  var __importDefault = (this && this.__importDefault) || function (mod) {
66198
67179
  return (mod && mod.__esModule) ? mod : { "default": mod };
66199
67180
  };
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;
67181
+ 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
67182
  Object.defineProperty(exports, "__esModule", ({ value: true }));
66202
67183
  exports.Ledger = exports.LedgerKind = void 0;
66203
67184
  const vote_1 = __webpack_require__(1130);
@@ -66211,6 +67192,7 @@ const effects_1 = __webpack_require__(7346);
66211
67192
  const conversion_1 = __webpack_require__(2360);
66212
67193
  const cache_1 = __importDefault(__webpack_require__(5834));
66213
67194
  const timing_1 = __webpack_require__(2895);
67195
+ const operations_1 = __webpack_require__(2778);
66214
67196
  /**
66215
67197
  * Kind of ledger
66216
67198
  */
@@ -66229,14 +67211,16 @@ class LedgerAtomicInterface {
66229
67211
  _LedgerAtomicInterface_subnet.set(this, void 0);
66230
67212
  _LedgerAtomicInterface_kind.set(this, void 0);
66231
67213
  _LedgerAtomicInterface_privateKey.set(this, void 0);
67214
+ _LedgerAtomicInterface_computeFeeFromBlocks.set(this, void 0);
66232
67215
  _LedgerAtomicInterface_storage.set(this, void 0);
66233
- _LedgerAtomicInterface_transaction.set(this, void 0);
66234
67216
  _LedgerAtomicInterface_ledger.set(this, void 0);
66235
67217
  _LedgerAtomicInterface_cache.set(this, void 0);
67218
+ _LedgerAtomicInterface_transaction.set(this, void 0);
66236
67219
  __classPrivateFieldSet(this, _LedgerAtomicInterface_network, config.network, "f");
66237
67220
  __classPrivateFieldSet(this, _LedgerAtomicInterface_subnet, config.subnet, "f");
66238
67221
  __classPrivateFieldSet(this, _LedgerAtomicInterface_kind, config.kind, "f");
66239
67222
  __classPrivateFieldSet(this, _LedgerAtomicInterface_privateKey, config.privateKey, "f");
67223
+ __classPrivateFieldSet(this, _LedgerAtomicInterface_computeFeeFromBlocks, config.computeFeeFromBlocks, "f");
66240
67224
  __classPrivateFieldSet(this, _LedgerAtomicInterface_ledger, ledger, "f");
66241
67225
  __classPrivateFieldSet(this, _LedgerAtomicInterface_storage, storage, "f");
66242
67226
  __classPrivateFieldSet(this, _LedgerAtomicInterface_transaction, transaction, "f");
@@ -66264,16 +67248,27 @@ class LedgerAtomicInterface {
66264
67248
  __classPrivateFieldSet(this, _LedgerAtomicInterface_transaction, null, "f");
66265
67249
  await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").abortTransaction(transaction);
66266
67250
  }
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`));
67251
+ async vote(blocks, otherVotes, quote) {
67252
+ if (blocks.length === 0) {
67253
+ throw (new ledger_1.default('LEDGER_MISSING_BLOCKS', 'At least one block is required to issue a vote'));
66271
67254
  }
66272
67255
  if (!__classPrivateFieldGet(this, _LedgerAtomicInterface_privateKey, "f")) {
66273
67256
  throw (new Error('Cannot vote on block, no private key loaded'));
66274
67257
  }
67258
+ if (__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode !== 'read-write') {
67259
+ throw (new Error(`May not issue votes in read-only mode, in ${__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode} mode`));
67260
+ }
66275
67261
  const privateKey = __classPrivateFieldGet(this, _LedgerAtomicInterface_privateKey, "f");
66276
67262
  const ledgerPubKey = privateKey.publicKeyString.get();
67263
+ if (quote !== undefined) {
67264
+ if (otherVotes !== undefined) {
67265
+ throw (new ledger_1.default('LEDGER_PERM_VOTE_WITH_QUOTE', 'Quote should not be included when requesting permanent votes'));
67266
+ }
67267
+ if (!quote.issuer.comparePublicKey(ledgerPubKey)) {
67268
+ throw (new ledger_1.default('LEDGER_QUOTE_MISMATCH', 'Provided quote does not match issuer public key'));
67269
+ }
67270
+ }
67271
+ const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66277
67272
  /**
66278
67273
  * If there are other votes, ensure one of them was issued by
66279
67274
  * us and the blocks are in the same order as the set of
@@ -66283,7 +67278,18 @@ class LedgerAtomicInterface {
66283
67278
  let foundOurVote = false;
66284
67279
  const seenVoteUIDs = new Set();
66285
67280
  const seenVoteIssuers = new account_1.default.Set();
67281
+ const possibleFeeBlock = blocks.at(-1);
67282
+ let hasFeeBlock = false;
67283
+ let blockCount = blocks.length;
67284
+ if (possibleFeeBlock?.purpose === block_1.BlockPurpose.FEE) {
67285
+ hasFeeBlock = true;
67286
+ blockCount--;
67287
+ }
67288
+ const requiredFees = new Map();
66286
67289
  for (const checkVote of otherVotes) {
67290
+ if (checkVote.quote === true) {
67291
+ throw (new ledger_1.default('LEDGER_PERM_VOTE_WITH_QUOTE', 'Cannot request permanent votes with quotes'));
67292
+ }
66287
67293
  if (seenVoteUIDs.has(checkVote.$id)) {
66288
67294
  throw (new ledger_1.default('LEDGER_DUPLICATE_VOTE_FOUND', 'Duplicate vote UID found'));
66289
67295
  }
@@ -66292,13 +67298,16 @@ class LedgerAtomicInterface {
66292
67298
  }
66293
67299
  seenVoteIssuers.add(checkVote.issuer);
66294
67300
  seenVoteUIDs.add(checkVote.$id);
67301
+ if (checkVote.fee !== undefined) {
67302
+ requiredFees.set(checkVote.issuer, checkVote.fee);
67303
+ }
66295
67304
  if (checkVote.$permanent) {
66296
67305
  throw (new ledger_1.default('LEDGER_CANNOT_EXCHANGE_PERM_VOTE', 'Asked to exchange a permanent vote for a permanent vote'));
66297
67306
  }
66298
- let blocksDifferFromVoteBlocks = checkVote.blocks.length !== blocks.length;
67307
+ let blocksDifferFromVoteBlocks = checkVote.blocks.length !== blockCount;
66299
67308
  /* If they do not differ from length alone, compare block hashes */
66300
67309
  if (!blocksDifferFromVoteBlocks) {
66301
- for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) {
67310
+ for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
66302
67311
  if (!blocks[blockIndex].hash.compareHexString(checkVote.blocks[blockIndex])) {
66303
67312
  blocksDifferFromVoteBlocks = true;
66304
67313
  break;
@@ -66312,69 +67321,43 @@ class LedgerAtomicInterface {
66312
67321
  foundOurVote = true;
66313
67322
  }
66314
67323
  }
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`));
67324
+ if (requiredFees.size > 0) {
67325
+ if (!hasFeeBlock) {
67326
+ throw (new ledger_1.default('LEDGER_MISSING_REQUIRED_FEE_BLOCK', 'Missing fee block but votes require it'));
67327
+ }
67328
+ if (requiredFees.size !== possibleFeeBlock?.operations.length) {
67329
+ throw (new ledger_1.default('LEDGER_REQUIRED_FEE_MISMATCH', 'Fee Block Operations do not match required fees'));
67330
+ }
66342
67331
  }
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`));
67332
+ // Verify that all required fees have been included in the fee block
67333
+ for (const [issuer, fee] of requiredFees) {
67334
+ const foundFee = possibleFeeBlock?.operations.find((operation) => {
67335
+ const expectedPayTo = fee.payTo ?? issuer;
67336
+ const expectedToken = fee.token ?? __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").baseToken;
67337
+ if (operation.type === operations_1.OperationType.SEND && operation.to.comparePublicKey(expectedPayTo)) {
67338
+ if (operation.amount !== fee.amount) {
67339
+ throw (new ledger_1.default('LEDGER_FEE_AMOUNT_MISMATCH', `Fee Amount Mismatch, found: ${operation.amount} expected: ${fee.amount}`));
67340
+ }
67341
+ if (!operation.token.comparePublicKey(expectedToken)) {
67342
+ throw (new ledger_1.default('LEDGER_FEE_TOKEN_MISMATCH', `Fee Token Mismatch, found: ${operation.token.publicKeyString.get()} expected: ${expectedToken.publicKeyString.get()}`));
67343
+ }
67344
+ return (true);
66360
67345
  }
67346
+ return (false);
67347
+ });
67348
+ if (foundFee === undefined) {
67349
+ throw (new ledger_1.default('LEDGER_FEE_MISSING', `Missing Required Fee for ${fee.payTo?.publicKeyString.get() ?? issuer.publicKeyString.get()}`));
66361
67350
  }
66362
67351
  }
66363
- if (!predecessorBeingVotedOn) {
66364
- const pubKey = block.account.publicKeyString.get();
66365
- needToGetHeadFor.add(block.account);
66366
- expectedHead[pubKey] = block;
67352
+ if (!foundOurVote) {
67353
+ throw (new ledger_1.default('LEDGER_NO_PERM_WITHOUT_SELF_TEMP', 'Asked to give a permanent vote without a temporary vote from us'));
66367
67354
  }
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
67355
  }
67356
+ const allLedgerHeads = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_validateBlocksForVote).call(this, blocks);
67357
+ const needToGetHeadFor = new account_1.default.Set(allLedgerHeads.keys());
66374
67358
  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];
67359
+ for (const [account, expectedBlock] of allLedgerHeads.entries()) {
67360
+ const accountHead = allHeads[account.publicKeyString.get()];
66378
67361
  if (accountHead === null) {
66379
67362
  if (!expectedBlock.$opening) {
66380
67363
  throw (new ledger_1.default('LEDGER_NOT_OPENING', 'Cannot vote on non-opening block for an empty account'));
@@ -66388,9 +67371,13 @@ class LedgerAtomicInterface {
66388
67371
  throw (new ledger_1.default('LEDGER_NOT_SUCCESSOR', 'The block is not the successor to the account head block'));
66389
67372
  }
66390
67373
  }
66391
- const previousToCheckFor = blocksToCheckOurVotesFor.map(b => b.previous);
67374
+ /**
67375
+ * Ensure we have no active vote for another conflicting successor of this block's parent (previous),
67376
+ * which could cause a fork
67377
+ */
67378
+ const previousToCheckFor = blocks.map(b => b.previous);
66392
67379
  const allPrevious = await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").getVotesFromMultiplePrevious(transaction, previousToCheckFor, 'both', account_1.default.toAccount(ledgerPubKey));
66393
- for (const block of blocksToCheckOurVotesFor) {
67380
+ for (const block of blocks) {
66394
67381
  const previousVotes = allPrevious[block.previous.toString()];
66395
67382
  if (previousVotes !== null && previousVotes.length > 0) {
66396
67383
  /**
@@ -66413,32 +67400,7 @@ class LedgerAtomicInterface {
66413
67400
  * If no other votes have been supplied, validate that the blocks are valid, and issue a short vote
66414
67401
  */
66415
67402
  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);
67403
+ const vote = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_voteOrQuoteWithFees).call(this, blocks, 'VOTE', quote);
66442
67404
  const blocksAndVote = vote_1.VoteStaple.fromVotesAndBlocks([vote], blocks);
66443
67405
  await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").addPendingVote(transaction, blocksAndVote);
66444
67406
  return (vote);
@@ -66468,6 +67430,11 @@ class LedgerAtomicInterface {
66468
67430
  await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").addPendingVote(transaction, blocksAndVote);
66469
67431
  return (vote);
66470
67432
  }
67433
+ async quote(blocks) {
67434
+ await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_validateBlocksForVote).call(this, blocks);
67435
+ const quote = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_voteOrQuoteWithFees).call(this, blocks, 'QUOTE');
67436
+ return (quote);
67437
+ }
66471
67438
  async add(votesAndBlocks, from) {
66472
67439
  const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66473
67440
  switch (__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode) {
@@ -66787,9 +67754,13 @@ class LedgerAtomicInterface {
66787
67754
  }
66788
67755
  return (retval);
66789
67756
  }
66790
- async gc() {
67757
+ async gc(timeLimitMS) {
66791
67758
  const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66792
- return (await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").gc(transaction));
67759
+ return (await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").gc(transaction, timeLimitMS));
67760
+ }
67761
+ async getFee(blocks, effectsInput) {
67762
+ const effects = effectsInput ?? (0, effects_1.computeEffectOfBlocks)(blocks, __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f"));
67763
+ return (__classPrivateFieldGet(this, _LedgerAtomicInterface_computeFeeFromBlocks, "f").call(this, __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f"), blocks, effects));
66793
67764
  }
66794
67765
  async _testingRunStorageFunction(code) {
66795
67766
  const transaction = __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
@@ -66797,7 +67768,7 @@ class LedgerAtomicInterface {
66797
67768
  return (retval);
66798
67769
  }
66799
67770
  }
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() {
67771
+ _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
67772
  if (__classPrivateFieldGet(this, _LedgerAtomicInterface_transaction, "f") === null) {
66802
67773
  throw (new Error('Attempt to use closed transaction'));
66803
67774
  }
@@ -66864,36 +67835,56 @@ _LedgerAtomicInterface_network = new WeakMap(), _LedgerAtomicInterface_subnet =
66864
67835
  throw (new ledger_1.default('LEDGER_INVALID_PERMISSIONS', `${accountPubKey} does not have required permissions to perform action on ${reqEntityKey}/${reqTargetKey} -- needs [${baseFlagsStr}]/[${externalOffsetsStr}]`));
66865
67836
  }
66866
67837
  }
66867
- }, _LedgerAtomicInterface_checkPermissionRequirements = async function _LedgerAtomicInterface_checkPermissionRequirements(allRequirements) {
67838
+ }, _LedgerAtomicInterface_checkPermissionRequirements = async function _LedgerAtomicInterface_checkPermissionRequirements(effects) {
66868
67839
  __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
66869
67840
  const newOwners = {};
66870
67841
  const requirementsByPrincipal = {};
66871
67842
  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
- };
67843
+ const allAccountsChanges = Object.values(effects);
67844
+ const foundMultisigSignerLengths = [];
67845
+ for (const { account, fields } of allAccountsChanges) {
67846
+ if (account.isMultisig()) {
67847
+ if (fields.minSignerSetLength !== undefined) {
67848
+ needToGetAccountInfoFor.add(account);
67849
+ foundMultisigSignerLengths.push([account, fields.minSignerSetLength]);
67850
+ }
67851
+ }
67852
+ for (const singleRequirement of fields.permissionRequirements ?? []) {
67853
+ const principal = singleRequirement.principal;
67854
+ const principalPubKey = principal.publicKeyString.get();
67855
+ if (!requirementsByPrincipal[principalPubKey]) {
67856
+ requirementsByPrincipal[principalPubKey] = [];
67857
+ }
67858
+ requirementsByPrincipal[principalPubKey].push(singleRequirement);
67859
+ const { entity, permissions } = singleRequirement;
67860
+ const entityKey = entity.publicKeyString.get();
67861
+ if (permissions === null) {
67862
+ continue;
67863
+ }
67864
+ if (permissions.has(['OWNER'])) {
67865
+ if (newOwners[entityKey] === undefined) {
67866
+ newOwners[entityKey] = {
67867
+ entity, owners: []
67868
+ };
67869
+ }
67870
+ newOwners[entityKey].owners.push(principal);
67871
+ }
67872
+ if (permissions.base.isValidForDefault && entity.isIdentifier()) {
67873
+ needToGetAccountInfoFor.add(entity);
66889
67874
  }
66890
- newOwners[entityKey].owners.push(principal);
66891
- }
66892
- if (permissions.base.isValidForDefault && entity.isIdentifier()) {
66893
- needToGetAccountInfoFor.add(entity);
66894
67875
  }
66895
67876
  }
66896
67877
  const foundAccountInfo = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_listAccountInfo).call(this, needToGetAccountInfoFor);
67878
+ for (const [multisig, foundSingerLength] of foundMultisigSignerLengths) {
67879
+ const multisigPubKey = multisig.publicKeyString.get();
67880
+ const foundInfo = foundAccountInfo[multisigPubKey];
67881
+ if (!foundInfo?.multisigQuorum) {
67882
+ throw (new Error(`Multisig quorum not found for ${multisigPubKey}`));
67883
+ }
67884
+ if (foundInfo.multisigQuorum > foundSingerLength) {
67885
+ throw (new ledger_1.default('LEDGER_INVALID_PERMISSIONS', `Quorum of ${foundInfo.multisigQuorum} not reached for ${multisigPubKey} -- got ${foundSingerLength}`));
67886
+ }
67887
+ }
66897
67888
  const checkPromises = [];
66898
67889
  for (const principalPubKey in requirementsByPrincipal) {
66899
67890
  const accountRequirements = requirementsByPrincipal[principalPubKey];
@@ -66914,7 +67905,7 @@ async function _LedgerAtomicInterface_validateLedgerOutcome(blocks) {
66914
67905
  const ownersByIdentifier = {};
66915
67906
  // 'ADD' or 'REMOVE' an owner from ownersByIdentifier
66916
67907
  const modifyOwners = (method, entity, principal) => {
66917
- if (entity.isIdentifier() === false) {
67908
+ if (entity.isIdentifier() === false || entity.isMultisig()) {
66918
67909
  return;
66919
67910
  }
66920
67911
  const entityPubKey = entity.assertIdentifier().publicKeyString.get();
@@ -66934,18 +67925,14 @@ async function _LedgerAtomicInterface_validateLedgerOutcome(blocks) {
66934
67925
  break;
66935
67926
  }
66936
67927
  };
66937
- const accountEffects = (0, effects_1.computeEffectOfBlocks)(blocks, __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f")).accounts;
67928
+ const effects = (0, effects_1.computeEffectOfBlocks)(blocks, __classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f"));
67929
+ const accountEffects = effects.accounts;
66938
67930
  const allAccountsChanges = Object.values(accountEffects);
66939
67931
  /**
66940
67932
  * Ensure all required permissions are met
66941
67933
  * See which accounts are now owners, and add those accounts to the set that we have
66942
67934
  */
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);
67935
+ const { newOwners } = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_checkPermissionRequirements).call(this, accountEffects);
66949
67936
  for (const entityPubKey in newOwners) {
66950
67937
  const { entity, owners } = newOwners[entityPubKey];
66951
67938
  for (const newOwner of owners) {
@@ -66959,7 +67946,7 @@ async function _LedgerAtomicInterface_validateLedgerOutcome(blocks) {
66959
67946
  */
66960
67947
  const createRequests = fields.createRequests ?? [];
66961
67948
  for (const createRequest of createRequests) {
66962
- modifyOwners('ADD', createRequest.requestedIdentifier, account);
67949
+ modifyOwners('ADD', createRequest.createdIdentifier, account);
66963
67950
  }
66964
67951
  /**
66965
67952
  * If an account was granted permissions, we should take that into effect
@@ -67011,6 +67998,98 @@ async function _LedgerAtomicInterface_validateLedgerOutcome(blocks) {
67011
67998
  }
67012
67999
  }
67013
68000
  }
68001
+ return (effects);
68002
+ }, _LedgerAtomicInterface_validateBlocksForVote = async function _LedgerAtomicInterface_validateBlocksForVote(blocks) {
68003
+ /**
68004
+ * Create a map of all blocks by their hash
68005
+ */
68006
+ const blockHashMap = {};
68007
+ for (const block of blocks) {
68008
+ blockHashMap[block.hash.toString()] = block;
68009
+ }
68010
+ const seenBlockHashes = new block_1.BlockHash.Set();
68011
+ const usedPreviousBlockHashes = new block_1.BlockHash.Set();
68012
+ const allLedgerHeads = new Map();
68013
+ for (const block of blocks) {
68014
+ const prevBlockHash = block.previous;
68015
+ seenBlockHashes.add(block.hash);
68016
+ if (block.network !== __classPrivateFieldGet(this, _LedgerAtomicInterface_network, "f")) {
68017
+ throw (new ledger_1.default('LEDGER_INVALID_NETWORK', 'Cannot vote on block for a different network'));
68018
+ }
68019
+ if (block.subnet !== __classPrivateFieldGet(this, _LedgerAtomicInterface_subnet, "f")) {
68020
+ throw (new ledger_1.default('LEDGER_INVALID_SUBNET', 'Cannot vote on block for a different subnet'));
68021
+ }
68022
+ if (usedPreviousBlockHashes.has(prevBlockHash)) {
68023
+ throw (new ledger_1.default('LEDGER_PREVIOUS_ALREADY_USED', `Invalid reference to block, previous: ${prevBlockHash} has already been used`));
68024
+ }
68025
+ usedPreviousBlockHashes.add(prevBlockHash);
68026
+ /**
68027
+ * Only allow this vote if it is the successor the current
68028
+ * HEAD block for the account, or if no blocks exist on the
68029
+ * account and its an opening block, or if the predecessor
68030
+ * block is also being voted on
68031
+ */
68032
+ let predecessorBeingVotedOn = false;
68033
+ if (!block.$opening) {
68034
+ const prevBlock = blockHashMap[prevBlockHash.toString()];
68035
+ if (prevBlock !== undefined) {
68036
+ predecessorBeingVotedOn = true;
68037
+ if (!(prevBlock.account.comparePublicKey(block.account))) {
68038
+ throw (new ledger_1.default('LEDGER_INVALID_CHAIN', 'Invalid chain, changes accounts'));
68039
+ }
68040
+ if (!seenBlockHashes.has(prevBlockHash)) {
68041
+ throw (new ledger_1.default('LEDGER_PREVIOUS_NOT_SEEN', `Invalid reference to block, out-of-order: ${prevBlockHash} has not already been seen`));
68042
+ }
68043
+ }
68044
+ }
68045
+ if (!predecessorBeingVotedOn) {
68046
+ allLedgerHeads.set(block.account, block);
68047
+ }
68048
+ }
68049
+ return (allLedgerHeads);
68050
+ }, _LedgerAtomicInterface_voteOrQuoteWithFees = async function _LedgerAtomicInterface_voteOrQuoteWithFees(blocks, type, quote) {
68051
+ if (__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode !== 'read-write') {
68052
+ throw (new Error(`May not issue votes in read-only mode, in ${__classPrivateFieldGet(this, _LedgerAtomicInterface_ledger, "f").ledgerWriteMode} mode`));
68053
+ }
68054
+ if (!__classPrivateFieldGet(this, _LedgerAtomicInterface_privateKey, "f")) {
68055
+ throw (new Error('Cannot vote on block, no private key loaded'));
68056
+ }
68057
+ __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_assertTransaction).call(this);
68058
+ const effects = await __classPrivateFieldGet(this, _LedgerAtomicInterface_instances, "m", _LedgerAtomicInterface_validateLedgerOutcome).call(this, blocks);
68059
+ const now = Date.now();
68060
+ for (const block of blocks) {
68061
+ const blockDate = block.date.valueOf();
68062
+ const timeOffset = 5 /* m */ * 60 /* s */ * 1000 /* ms */;
68063
+ /**
68064
+ * Do not allow short votes on blocks from the distant past
68065
+ */
68066
+ if (blockDate < (now - timeOffset) || blockDate > (now + timeOffset)) {
68067
+ throw (new Error(`Refusing to issue vote for block dated ${block.date.toISOString()}`));
68068
+ }
68069
+ }
68070
+ /**
68071
+ * Serial number
68072
+ */
68073
+ const serial = await __classPrivateFieldGet(this, _LedgerAtomicInterface_storage, "f").getNextSerialNumber(__classPrivateFieldGet(this, _LedgerAtomicInterface_transaction, "f"));
68074
+ /**
68075
+ * Short expiry (5 minutes)
68076
+ */
68077
+ const pendingVoteExpiry = new Date();
68078
+ pendingVoteExpiry.setUTCMinutes(pendingVoteExpiry.getUTCMinutes() + 5);
68079
+ const builderType = (type === 'QUOTE') ? vote_1.VoteQuoteBuilder : vote_1.VoteBuilder;
68080
+ const builder = new builderType(__classPrivateFieldGet(this, _LedgerAtomicInterface_privateKey, "f"));
68081
+ for (const block of blocks) {
68082
+ builder.addBlock(block);
68083
+ }
68084
+ /**
68085
+ * If a quote was provided use it as the fee, otherwise generate new fee
68086
+ */
68087
+ const fee = quote?.fee ?? await this.getFee(blocks, effects);
68088
+ if (fee !== null) {
68089
+ builder.addFee(fee);
68090
+ }
68091
+ const voteOrQuote = await builder.seal(serial, pendingVoteExpiry);
68092
+ return (voteOrQuote);
67014
68093
  };
67015
68094
  /**
67016
68095
  * The core Ledger components
@@ -67047,6 +68126,26 @@ class Ledger {
67047
68126
  copy(newNode) {
67048
68127
  return (new Ledger(__classPrivateFieldGet(this, _Ledger_config, "f"), newNode, __classPrivateFieldGet(this, _Ledger_storage, "f")));
67049
68128
  }
68129
+ getFeePayToAndToken(accounts, token) {
68130
+ const retval = {};
68131
+ if (accounts !== undefined && accounts.length > 0) {
68132
+ // Get a random fee account from the set of possible accounts
68133
+ const feeAccount = accounts[Math.floor(Math.random() * accounts.length)];
68134
+ // If the fee account matches the ledger private key then we can omit the account
68135
+ // Fee is then paid to the vote issuer
68136
+ if (!feeAccount.comparePublicKey(__classPrivateFieldGet(this, _Ledger_config, "f").privateKey?.publicKeyString.get())) {
68137
+ retval.payTo = feeAccount;
68138
+ }
68139
+ }
68140
+ if (token !== undefined) {
68141
+ // If base token matches ledger fee token then we can omit the token
68142
+ // Fee is then paid using the base token
68143
+ if (!this.baseToken.comparePublicKey(token)) {
68144
+ retval.token = token;
68145
+ }
68146
+ }
68147
+ return (retval);
68148
+ }
67050
68149
  /**
67051
68150
  * Execute some code with a transaction held, if the code fails the
67052
68151
  * transaction is aborted, otherwise it is committed
@@ -67168,6 +68267,11 @@ class Ledger {
67168
68267
  return (await transaction.vote(...args));
67169
68268
  }));
67170
68269
  }
68270
+ async quote(...args) {
68271
+ return (await this.run('db-quote', async function (transaction) {
68272
+ return (await transaction.quote(...args));
68273
+ }));
68274
+ }
67171
68275
  async add(...args) {
67172
68276
  return (await this.run('db-add', async function (transaction) {
67173
68277
  return (await transaction.add(...args));
@@ -67278,6 +68382,11 @@ class Ledger {
67278
68382
  return (await transaction.gc(...args));
67279
68383
  }));
67280
68384
  }
68385
+ async getFee(...args) {
68386
+ return (await this.run('db-getFee', async function (transaction) {
68387
+ return (await transaction.getFee(...args));
68388
+ }));
68389
+ }
67281
68390
  async stats() {
67282
68391
  const env_2 = { stack: [], error: void 0, hasError: false };
67283
68392
  try {
@@ -67825,9 +68934,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
67825
68934
  var __importDefault = (this && this.__importDefault) || function (mod) {
67826
68935
  return (mod && mod.__esModule) ? mod : { "default": mod };
67827
68936
  };
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;
68937
+ 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_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
68938
  Object.defineProperty(exports, "__esModule", ({ value: true }));
67830
- exports.Testing = exports.P2PSwitch = exports.P2PWebSocket = void 0;
68939
+ exports.Testing = exports.P2PSwitch = exports.P2PWebSocket = exports.P2PHttpConnection = void 0;
67831
68940
  exports.generateP2PPeerSigned = generateP2PPeerSigned;
67832
68941
  exports.P2PPeerFromJSO = P2PPeerFromJSO;
67833
68942
  exports.P2PPeerToJSO = P2PPeerToJSO;
@@ -67844,6 +68953,7 @@ const helper_1 = __webpack_require__(3208);
67844
68953
  const kv_memory_1 = __importDefault(__webpack_require__(1557));
67845
68954
  const vote_1 = __webpack_require__(1130);
67846
68955
  const effects_1 = __webpack_require__(7346);
68956
+ const version_1 = __webpack_require__(5672);
67847
68957
  const defaultP2PConfig = {
67848
68958
  timeoutIdle: 10 /* s */ * 1000 /* ms */,
67849
68959
  timeoutIdleGreeting: 5 /* s */ * 1000 /* ms */,
@@ -67852,12 +68962,13 @@ const defaultP2PConfig = {
67852
68962
  manualPeersCheckInFreq: 10 /* m */ * 60 /* s */ * 1000 /* ms */,
67853
68963
  seenMessageTTL: 1 /* m */ * 60 /* s */ * 1000 /* ms */,
67854
68964
  forwardingPeerCount: 16,
67855
- kv: null
68965
+ kv: null,
68966
+ useHTTPRepublish: false
67856
68967
  };
67857
68968
  /**
67858
68969
  * Convert a peer to a printable string
67859
68970
  */
67860
- function printablePeer(peer) {
68971
+ function printablePeer(peer, endpoint) {
67861
68972
  if (peer === null) {
67862
68973
  return ('null (not yet greeted)');
67863
68974
  }
@@ -67865,7 +68976,7 @@ function printablePeer(peer) {
67865
68976
  case node_1.NodeKind.PARTICIPANT:
67866
68977
  return (`listener_${peer.id}`);
67867
68978
  case node_1.NodeKind.REPRESENTATIVE:
67868
- return (`rep_${peer.key.publicKeyString.get()}@${peer.endpoints.p2p}`);
68979
+ return (`rep_${peer.key.publicKeyString.get()}@${endpoint ?? peer.endpoints.p2p}`);
67869
68980
  }
67870
68981
  return (null);
67871
68982
  }
@@ -67899,6 +69010,7 @@ function validateP2PPeer(peer) {
67899
69010
  checkVersion,
67900
69011
  peer.endpoints.p2p,
67901
69012
  peer.endpoints.api,
69013
+ peer.preferUpdates,
67902
69014
  peer.kind,
67903
69015
  peer.key.publicKeyAndType
67904
69016
  ];
@@ -67922,6 +69034,7 @@ async function generateP2PPeerSignature(peer) {
67922
69034
  version,
67923
69035
  peer.endpoints.p2p,
67924
69036
  peer.endpoints.api,
69037
+ peer.preferUpdates,
67925
69038
  peer.kind,
67926
69039
  peer.key.publicKeyAndType
67927
69040
  ];
@@ -67973,13 +69086,20 @@ function P2PPeerFromJSO(object) {
67973
69086
  if (typeof endpoints.p2p !== 'string' || typeof endpoints.api !== 'string') {
67974
69087
  return (null);
67975
69088
  }
69089
+ if (typeof object.preferUpdates !== 'string') {
69090
+ return (null);
69091
+ }
69092
+ if (object.preferUpdates !== 'http' && object.preferUpdates !== 'websocket') {
69093
+ return (null);
69094
+ }
67976
69095
  if (typeof object.key !== 'string') {
67977
69096
  return (null);
67978
69097
  }
67979
69098
  const retvalUnsigned = {
67980
69099
  kind: node_1.NodeKind.REPRESENTATIVE,
67981
69100
  key: account_1.default.fromPublicKeyString(object.key).assertAccount(),
67982
- endpoints: endpoints
69101
+ endpoints: endpoints,
69102
+ preferUpdates: object.preferUpdates
67983
69103
  };
67984
69104
  let retval;
67985
69105
  if (typeof object.signature === 'string') {
@@ -68041,6 +69161,7 @@ function P2PPeerToJSO(peer) {
68041
69161
  return ({
68042
69162
  kind: peer.kind,
68043
69163
  endpoints: peer.endpoints,
69164
+ preferUpdates: peer.preferUpdates,
68044
69165
  key: peer.key.publicKeyString.get(),
68045
69166
  ...additionalAttributes
68046
69167
  });
@@ -68073,6 +69194,12 @@ function isP2PPeer(checkObject) {
68073
69194
  if (!('p2p' in checkObject.endpoints) || !('api' in checkObject.endpoints)) {
68074
69195
  return (false);
68075
69196
  }
69197
+ if (!('preferUpdates' in checkObject)) {
69198
+ return (false);
69199
+ }
69200
+ if (checkObject.preferUpdates !== 'http' && checkObject.preferUpdates !== 'websocket') {
69201
+ return (false);
69202
+ }
68076
69203
  if (!('key' in checkObject)) {
68077
69204
  return (false);
68078
69205
  }
@@ -68182,6 +69309,78 @@ async function waitForPeer(conn) {
68182
69309
  }, 10);
68183
69310
  })));
68184
69311
  }
69312
+ class P2PHttpConnection {
69313
+ /**
69314
+ * Initiate an outbound http connection and attach it to the specified switch
69315
+ */
69316
+ static async initiate(peer, p2pSwitch) {
69317
+ if (!('endpoints' in peer)) {
69318
+ return (null);
69319
+ }
69320
+ if (!('api' in peer.endpoints)) {
69321
+ return (null);
69322
+ }
69323
+ if (!('preferUpdates' in peer) || peer.preferUpdates !== 'http') {
69324
+ return (null);
69325
+ }
69326
+ const conn = new P2PHttpConnection(peer, p2pSwitch);
69327
+ await p2pSwitch.registerConnection(conn);
69328
+ return (conn);
69329
+ }
69330
+ constructor(peer, p2pSwitch) {
69331
+ _P2PHttpConnection_switch.set(this, void 0);
69332
+ this.abort = false;
69333
+ this.validatedPeer = null;
69334
+ this.timeout = 0;
69335
+ this.peer = peer;
69336
+ __classPrivateFieldSet(this, _P2PHttpConnection_switch, p2pSwitch, "f");
69337
+ }
69338
+ get connString() {
69339
+ if (this.peerString === null) {
69340
+ throw (new Error('HTTP Connection should have a peerString'));
69341
+ }
69342
+ return (this.peerString);
69343
+ }
69344
+ get peerString() {
69345
+ if (this.peer.kind === node_1.NodeKind.PARTICIPANT) {
69346
+ throw (new Error('HTTP Connections cannot be participants'));
69347
+ }
69348
+ return (printablePeer(this.peer, this.peer.endpoints.api));
69349
+ }
69350
+ async send(messageBuffer) {
69351
+ if (this.peer.kind !== node_1.NodeKind.REPRESENTATIVE) {
69352
+ return (false);
69353
+ }
69354
+ __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f")._log.debug(`Called send on http connection: ${this.peerString}`);
69355
+ const localGreetingInfo = await __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f").getOutgoingGreetingInfo();
69356
+ const fetchURL = `${this.peer.endpoints.api}/p2p/message`;
69357
+ try {
69358
+ await fetch(fetchURL, {
69359
+ method: 'POST',
69360
+ headers: {
69361
+ 'content-type': 'application/json',
69362
+ 'user-agent': `KeetaNet/v${version_1.version} (JS)`
69363
+ },
69364
+ body: JSON.stringify({
69365
+ message: messageBuffer.toString(),
69366
+ greeting: localGreetingInfo
69367
+ })
69368
+ });
69369
+ }
69370
+ catch (postMessageError) {
69371
+ __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f")._log.debug(`Failed to post message: ${postMessageError}`);
69372
+ }
69373
+ return (true);
69374
+ }
69375
+ async close() {
69376
+ this.abort = true;
69377
+ __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f")._log.debug(`Called close on http connection: ${this.peerString}`);
69378
+ await __classPrivateFieldGet(this, _P2PHttpConnection_switch, "f").unregisterConnection(this);
69379
+ }
69380
+ }
69381
+ exports.P2PHttpConnection = P2PHttpConnection;
69382
+ _P2PHttpConnection_switch = new WeakMap();
69383
+ P2PHttpConnection.isInstance = (0, helper_1.checkableGenerator)(P2PHttpConnection);
68185
69384
  /**
68186
69385
  * A P2PConnection using the "ws" package
68187
69386
  */
@@ -68476,7 +69675,12 @@ class P2PSwitch {
68476
69675
  * been confirmed
68477
69676
  */
68478
69677
  const repLastSeenLimit = Math.max(this.config.timeoutIdle, this.config.manualPeersCheckInFreq) * 10;
68479
- let knownPeers = await this.config.kv.getAll('knownPeers');
69678
+ const potentialKnownPeers = await this.config.kv.getAll('knownPeers');
69679
+ // Filter for only valid entries in case the format becomes invalidated in the future
69680
+ let knownPeers = Object.fromEntries(Object.entries(potentialKnownPeers).filter(([_, value]) => {
69681
+ const peer = P2PPeerFromJSO(value);
69682
+ return (peer !== null);
69683
+ }));
68480
69684
  const lastSeenPeers = await this.config.kv.getAll('lastSeenPeers');
68481
69685
  const retval = [];
68482
69686
  /**
@@ -68730,6 +69934,13 @@ class P2PSwitch {
68730
69934
  async selfPeer() {
68731
69935
  return (await __classPrivateFieldGet(this, _P2PSwitch_instances, "m", _P2PSwitch_getLocalPeerInfo).call(this));
68732
69936
  }
69937
+ async getOutgoingGreetingInfo() {
69938
+ const greetingInfo = await __classPrivateFieldGet(this, _P2PSwitch_instances, "m", _P2PSwitch_getLocalPeerInfo).call(this);
69939
+ if (greetingInfo === null) {
69940
+ throw (new Error('Invalid NodeKind for emitting outgoing greeting'));
69941
+ }
69942
+ return (P2PPeerToJSO(greetingInfo));
69943
+ }
68733
69944
  /**
68734
69945
  * Receive a message from a connection
68735
69946
  *
@@ -68780,7 +69991,7 @@ class P2PSwitch {
68780
69991
  let forward = true;
68781
69992
  let acceptable = true;
68782
69993
  let rebroadcastOnly = false;
68783
- if (from.peer === null) {
69994
+ if (from.peer === null || (P2PHttpConnection.isInstance(from) && message.type === 'greeting')) {
68784
69995
  /**
68785
69996
  * By default do not forward messages from un-greeted peers
68786
69997
  */
@@ -69237,6 +70448,23 @@ class P2PSwitch {
69237
70448
  }
69238
70449
  return (false);
69239
70450
  }
70451
+ /**
70452
+ * TODO - make this private after refactoring websockets to handle higher load
70453
+ * https://github.com/KeetaNetwork/node/issues/785
70454
+ */
70455
+ async haveAnyFilter(data) {
70456
+ const kvFilters = await this.config.kv.getAll('messageFilters');
70457
+ for (const key in kvFilters) {
70458
+ const kvFilter = kvFilters[key];
70459
+ if (kvFilter && typeof kvFilter === 'string') {
70460
+ const filter = account_1.default.fromPublicKeyAndType(kvFilter);
70461
+ const voteStaple = new vote_1.VoteStaple(data);
70462
+ const { touched } = (0, effects_1.computeEffectOfBlocks)(voteStaple.blocks);
70463
+ return (touched.has(filter));
70464
+ }
70465
+ }
70466
+ return (false);
70467
+ }
69240
70468
  }
69241
70469
  exports.P2PSwitch = P2PSwitch;
69242
70470
  _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 =
@@ -69408,7 +70636,8 @@ async function _P2PSwitch_relayActiveState(conn) {
69408
70636
  endpoints: {
69409
70637
  p2p: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.p2p,
69410
70638
  api: __classPrivateFieldGet(this, _P2PSwitch_localNode, "f").config.endpoints.api
69411
- }
70639
+ },
70640
+ preferUpdates: this.config.useHTTPRepublish ? 'http' : 'websocket'
69412
70641
  });
69413
70642
  if (greetingInfoSigned === null) {
69414
70643
  throw (new Error('internal error: Could not generate signature'));
@@ -69422,11 +70651,7 @@ async function _P2PSwitch_relayActiveState(conn) {
69422
70651
  return (greetingInfo);
69423
70652
  }, _P2PSwitch_emitOutgoingGreeting = async function _P2PSwitch_emitOutgoingGreeting(to) {
69424
70653
  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);
70654
+ const greeting = await this.getOutgoingGreetingInfo();
69430
70655
  this._log.debug('Sending greeting to', to.connString);
69431
70656
  return (await this.sendMessage(to, messageID, 'greeting', greeting, 0));
69432
70657
  }, _P2PSwitch_localNodeKeyOrNull = async function _P2PSwitch_localNodeKeyOrNull() {
@@ -69489,23 +70714,28 @@ async function _P2PSwitch_relayActiveState(conn) {
69489
70714
  }
69490
70715
  }, _P2PSwitch_connectToPeer = async function _P2PSwitch_connectToPeer(peer, logId) {
69491
70716
  this._log.debug(`[${logId}]`, 'Trying to connect to peer', printablePeer(peer));
69492
- let ws = null;
69493
- try {
69494
- ws = await P2PWebSocket.initiate(peer, this);
70717
+ let p2pConnection = null;
70718
+ if (peer.kind === node_1.NodeKind.REPRESENTATIVE && peer.preferUpdates === 'http') {
70719
+ p2pConnection = await P2PHttpConnection.initiate(peer, this);
69495
70720
  }
69496
- catch (connectError) {
69497
- /* Ignored */
70721
+ else {
70722
+ try {
70723
+ p2pConnection = await P2PWebSocket.initiate(peer, this);
70724
+ }
70725
+ catch (connectError) {
70726
+ /* Ignored */
70727
+ }
69498
70728
  }
69499
- if (ws === null) {
70729
+ if (p2pConnection === null) {
69500
70730
  return (null);
69501
70731
  }
69502
70732
  /**
69503
70733
  * Since we established an outbound connection to this
69504
70734
  * peer we already know their information
69505
70735
  */
69506
- ws.validatedPeer = peer;
69507
- await this.registerConnection(ws);
69508
- await waitForPeer(ws);
70736
+ p2pConnection.validatedPeer = peer;
70737
+ await this.registerConnection(p2pConnection);
70738
+ await waitForPeer(p2pConnection);
69509
70739
  /*
69510
70740
  * Since we successfully connected to the peer, update the
69511
70741
  * last seen information
@@ -69523,7 +70753,7 @@ async function _P2PSwitch_relayActiveState(conn) {
69523
70753
  catch (addPeerError) {
69524
70754
  this._log.error('Failed to add peer:', addPeerError);
69525
70755
  }
69526
- return (ws);
70756
+ return (p2pConnection);
69527
70757
  }, _P2PSwitch_passesFilter = async function _P2PSwitch_passesFilter(target, data) {
69528
70758
  let filter = __classPrivateFieldGet(this, _P2PSwitch_messageFilterCache, "f")[target.connString];
69529
70759
  if (filter === undefined) {
@@ -69600,7 +70830,8 @@ var BaseFlag;
69600
70830
  BaseFlag[BaseFlag["TOKEN_ADMIN_MODIFY_BALANCE"] = 7] = "TOKEN_ADMIN_MODIFY_BALANCE";
69601
70831
  BaseFlag[BaseFlag["PERMISSION_DELEGATE_ADD"] = 11] = "PERMISSION_DELEGATE_ADD";
69602
70832
  BaseFlag[BaseFlag["PERMISSION_DELEGATE_REMOVE"] = 12] = "PERMISSION_DELEGATE_REMOVE";
69603
- BaseFlag[BaseFlag["MANAGE_CERTIFICATE"] = 13] = "MANAGE_CERTIFICATE"; /* 0x2000 */
70833
+ BaseFlag[BaseFlag["MANAGE_CERTIFICATE"] = 13] = "MANAGE_CERTIFICATE";
70834
+ BaseFlag[BaseFlag["MULTISIG_SIGNER"] = 14] = "MULTISIG_SIGNER"; /* 0x4000 */
69604
70835
  })(BaseFlag || (BaseFlag = {}));
69605
70836
  /**
69606
70837
  * Handles what flags are in what groups, groups cannot be mixed (except BASE)
@@ -69614,6 +70845,8 @@ var BasePermissionGroup;
69614
70845
  BasePermissionGroup[BasePermissionGroup["NETWORK"] = 3] = "NETWORK";
69615
70846
  BasePermissionGroup[BasePermissionGroup["TOKEN"] = 4] = "TOKEN";
69616
70847
  BasePermissionGroup[BasePermissionGroup["STORAGE"] = 5] = "STORAGE";
70848
+ BasePermissionGroup[BasePermissionGroup["NONIDENTIFIER_OR_MULTISIG"] = 6] = "NONIDENTIFIER_OR_MULTISIG";
70849
+ BasePermissionGroup[BasePermissionGroup["MULTISIG"] = 7] = "MULTISIG";
69617
70850
  })(BasePermissionGroup || (BasePermissionGroup = {}));
69618
70851
  const basePermissionRules = {
69619
70852
  ACCESS: {
@@ -69699,6 +70932,12 @@ const basePermissionRules = {
69699
70932
  entity: BasePermissionGroup.ANY,
69700
70933
  principal: BasePermissionGroup.ANY,
69701
70934
  target: BasePermissionGroup.NEVER
70935
+ },
70936
+ MULTISIG_SIGNER: {
70937
+ canBeDefault: false,
70938
+ entity: BasePermissionGroup.MULTISIG,
70939
+ principal: BasePermissionGroup.NONIDENTIFIER_OR_MULTISIG,
70940
+ target: BasePermissionGroup.NEVER
69702
70941
  }
69703
70942
  };
69704
70943
  const basePermissionSetOffsets = {};
@@ -69839,6 +71078,10 @@ class BaseSet extends PermissionSetHolder {
69839
71078
  return (true);
69840
71079
  case _a.BasePermissionGroup.NEVER:
69841
71080
  return (false);
71081
+ case _a.BasePermissionGroup.NONIDENTIFIER_OR_MULTISIG:
71082
+ return (account.isAccount() || account.isMultisig());
71083
+ case _a.BasePermissionGroup.MULTISIG:
71084
+ return (account.isMultisig());
69842
71085
  }
69843
71086
  return (false);
69844
71087
  }
@@ -71162,7 +72405,11 @@ class ValidateASN1 {
71162
72405
  * Given a schema, validate the ASN.1 object against it and return the
71163
72406
  * object as the validated type
71164
72407
  */
71165
- static againstSchema(input, schema) {
72408
+ static againstSchema(input, schemaIn) {
72409
+ let schema = schemaIn;
72410
+ if (typeof schema === 'function') {
72411
+ schema = schema();
72412
+ }
71166
72413
  let needsMoreAnalysis = false;
71167
72414
  if (util_1.types.isDate(input) && schema === ValidateASN1.IsDate) {
71168
72415
  /* XXX:TODO */
@@ -72055,17 +73302,45 @@ function fromDNSequenceToString(dn) {
72055
73302
  const retval = parts.join(', ');
72056
73303
  return (retval);
72057
73304
  }
73305
+ const defaultHashName = HashLib.HashFunctionName;
72058
73306
  class CertificateBuilder {
72059
73307
  constructor(params) {
72060
73308
  _CertificateBuilder_params.set(this, void 0);
72061
73309
  __classPrivateFieldSet(this, _CertificateBuilder_params, {
72062
- hashLib: {
72063
- hash: HashLib.Hash,
72064
- name: HashLib.HashFunctionName
72065
- },
72066
73310
  ...params
72067
73311
  }, "f");
72068
73312
  }
73313
+ static hashName(params, purpose) {
73314
+ const hashLib = params.hashLib;
73315
+ if (hashLib !== undefined) {
73316
+ switch (hashLib.name) {
73317
+ case 'sha256':
73318
+ case 'sha3-256':
73319
+ return (hashLib.name);
73320
+ default:
73321
+ throw (new Error(`Unsupported hash algorithm "${hashLib.name}"`));
73322
+ }
73323
+ }
73324
+ const hashName = params.hashParams?.defaults?.[purpose] ?? defaultHashName;
73325
+ return (hashName);
73326
+ }
73327
+ static hash(params, purpose, ...data) {
73328
+ /*
73329
+ * If the deprecated hashLib parameter is set, then use it
73330
+ * regardless of the algo parameter for backwards compatibility
73331
+ * even though it is not recommended to use it anymore
73332
+ */
73333
+ const hashLib = params.hashLib;
73334
+ if (hashLib !== undefined) {
73335
+ return (hashLib.hash(...data));
73336
+ }
73337
+ const hashName = this.hashName(params, purpose);
73338
+ const hashFunction = params.hashParams.functions?.[hashName];
73339
+ if (hashFunction === undefined) {
73340
+ throw (new Error(`Hash function "${hashName}" not found for purpose "${purpose}"`));
73341
+ }
73342
+ return (hashFunction(...data));
73343
+ }
72069
73344
  /**
72070
73345
  * Construct an extension
72071
73346
  */
@@ -72084,12 +73359,8 @@ class CertificateBuilder {
72084
73359
  /**
72085
73360
  * Convert a KeetaNet Account to a Key ID (for Subject Key Identifier)
72086
73361
  */
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([
73362
+ accountToKeyId(params, account, purpose) {
73363
+ return (Buffer.from(CertificateBuilder.hash(params, purpose, Buffer.concat([
72093
73364
  Buffer.from('KeetaKey', 'utf-8'),
72094
73365
  account.publicKeyAndType
72095
73366
  ]), 20)));
@@ -72153,10 +73424,11 @@ class CertificateBuilder {
72153
73424
  extensions.push(
72154
73425
  /** Extension: Authority Key Identifier */
72155
73426
  CertificateBuilder.extension('2.5.29.35', [
72156
- { type: 'context', value: 0, kind: 'implicit', contains: this.accountToKeyId(params.issuer) }
73427
+ /** XXX:TODO: Copy the key ID from the issuer certificate's Subject Key Identifier if known */
73428
+ { type: 'context', value: 0, kind: 'implicit', contains: this.accountToKeyId(params, params.issuer, 'aki') }
72157
73429
  ]),
72158
73430
  /** Extension: Subject Key Identifier */
72159
- CertificateBuilder.extension('2.5.29.14', this.accountToKeyId(params.subjectPublicKey)));
73431
+ CertificateBuilder.extension('2.5.29.14', this.accountToKeyId(params, params.subjectPublicKey, 'ski')));
72160
73432
  return (extensions);
72161
73433
  }
72162
73434
  /**
@@ -72165,7 +73437,26 @@ class CertificateBuilder {
72165
73437
  getFinalParams(params) {
72166
73438
  const finalParams = {
72167
73439
  ...__classPrivateFieldGet(this, _CertificateBuilder_params, "f"),
72168
- ...params
73440
+ ...params,
73441
+ hashParams: {
73442
+ ...__classPrivateFieldGet(this, _CertificateBuilder_params, "f")?.hashParams,
73443
+ ...params?.hashParams,
73444
+ functions: {
73445
+ 'sha256': function (data, len) {
73446
+ throw (new Error('not implemented, please provide an implementation'));
73447
+ },
73448
+ [defaultHashName]: HashLib.Hash,
73449
+ ...__classPrivateFieldGet(this, _CertificateBuilder_params, "f")?.hashParams?.functions,
73450
+ ...params?.hashParams?.functions
73451
+ },
73452
+ defaults: {
73453
+ signature: defaultHashName,
73454
+ ski: defaultHashName,
73455
+ aki: defaultHashName,
73456
+ ...__classPrivateFieldGet(this, _CertificateBuilder_params, "f")?.hashParams?.defaults,
73457
+ ...params?.hashParams?.defaults
73458
+ }
73459
+ }
72169
73460
  };
72170
73461
  /* Validate that required parameters are set */
72171
73462
  const issuer = finalParams.issuer;
@@ -72189,8 +73480,9 @@ class CertificateBuilder {
72189
73480
  throw (new Error('"serialNumber" not set'));
72190
73481
  }
72191
73482
  const hashLib = finalParams.hashLib;
72192
- if (hashLib === undefined) {
72193
- throw (new Error('"hashLib" not set'));
73483
+ const hashParams = finalParams.hashParams;
73484
+ if (hashParams === undefined) {
73485
+ throw (new Error('"hashParams" not set'));
72194
73486
  }
72195
73487
  return ({
72196
73488
  ...finalParams,
@@ -72199,7 +73491,8 @@ class CertificateBuilder {
72199
73491
  validFrom,
72200
73492
  validTo,
72201
73493
  serial,
72202
- hashLib
73494
+ hashLib,
73495
+ hashParams
72203
73496
  });
72204
73497
  }
72205
73498
  /**
@@ -72207,13 +73500,13 @@ class CertificateBuilder {
72207
73500
  */
72208
73501
  async buildDER(params) {
72209
73502
  const finalParams = this.getFinalParams(params);
72210
- const hashLib = finalParams.hashLib;
72211
73503
  const { oid: signatureAlgorithmOID, hashData: hashData } = (function () {
73504
+ const hashName = CertificateBuilder.hashName(finalParams, 'signature');
72212
73505
  switch (finalParams.issuer.keyType) {
72213
73506
  case account_1.AccountKeyAlgorithm.ECDSA_SECP256K1:
72214
73507
  case account_1.AccountKeyAlgorithm.ECDSA_SECP256R1:
72215
73508
  return ({
72216
- oid: `${hashLib.name}WithEcDSA`,
73509
+ oid: `${hashName}WithEcDSA`,
72217
73510
  hashData: true
72218
73511
  });
72219
73512
  case account_1.AccountKeyAlgorithm.ED25519:
@@ -72281,7 +73574,7 @@ class CertificateBuilder {
72281
73574
  */
72282
73575
  let toSign;
72283
73576
  if (hashData) {
72284
- toSign = Buffer.from(hashLib.hash(tbsCertificateBuffer));
73577
+ toSign = Buffer.from(CertificateBuilder.hash(finalParams, 'signature', tbsCertificateBuffer));
72285
73578
  }
72286
73579
  else {
72287
73580
  toSign = tbsCertificateBuffer;
@@ -72872,6 +74165,18 @@ class Certificate {
72872
74165
  }
72873
74166
  return (issuerCert.subjectPublicKey);
72874
74167
  }
74168
+ /**
74169
+ * Get the extensions present in the certificate -- this is the raw
74170
+ * extensions as they were parsed from the certificate, and may
74171
+ * contain extensions that are not processed by this class.
74172
+ */
74173
+ getExtensions() {
74174
+ this.assertConstructed();
74175
+ if (__classPrivateFieldGet(this, _Certificate_extensionsRaw, "f") === undefined) {
74176
+ return (undefined);
74177
+ }
74178
+ return (__classPrivateFieldGet(this, _Certificate_extensionsRaw, "f"));
74179
+ }
72875
74180
  assertConstructed() {
72876
74181
  if (!__classPrivateFieldGet(this, _Certificate_finalizeConstructionCalled, "f")) {
72877
74182
  throw (new Error('finalizeConstruction not called'));
@@ -73738,6 +75043,7 @@ var _AsyncDisposableStackPolyfill_instances, _AsyncDisposableStackPolyfill_toDis
73738
75043
  Object.defineProperty(exports, "__esModule", ({ value: true }));
73739
75044
  exports.crypto = exports.AsyncDisposableStack = void 0;
73740
75045
  exports.bufferToArrayBuffer = bufferToArrayBuffer;
75046
+ exports.bufferToBigInt = bufferToBigInt;
73741
75047
  exports.isIntegerOrBigInt = isIntegerOrBigInt;
73742
75048
  exports.isBuffer = isBuffer;
73743
75049
  exports.arrayRepeat = arrayRepeat;
@@ -73773,6 +75079,13 @@ function bufferToArrayBuffer(input) {
73773
75079
  }
73774
75080
  return (out);
73775
75081
  }
75082
+ function bufferToBigInt(buffer) {
75083
+ let result = 0n;
75084
+ for (const byte of buffer) {
75085
+ result = (result << 8n) + BigInt(byte);
75086
+ }
75087
+ return (result);
75088
+ }
73776
75089
  /**
73777
75090
  * Check if a value is an integer or a bigint.
73778
75091
  */
@@ -74132,7 +75445,11 @@ function setGenerator(parent, rawEncode, rawDecode) {
74132
75445
  _map.set(this, void 0);
74133
75446
  this[_b] = `${parent.name}Set`;
74134
75447
  __classPrivateFieldSet(this, _map, new Map(), "f");
74135
- __classPrivateFieldSet(this, _set, new Set(data.map(item => encode(item, __classPrivateFieldGet(this, _map, "f")))), "f");
75448
+ __classPrivateFieldSet(this, _set, new Set, "f");
75449
+ // Use a loop since data could be an Iterable not always an array
75450
+ for (const item of data) {
75451
+ __classPrivateFieldGet(this, _set, "f").add(encode(item, __classPrivateFieldGet(this, _map, "f")));
75452
+ }
74136
75453
  }
74137
75454
  // Fit with new JS spec
74138
75455
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isSubsetOf
@@ -74350,7 +75667,7 @@ async function generateInitialVoteStaple(options) {
74350
75667
  blocks.recipientSupply = blocks.recipient;
74351
75668
  blocks.recipient = await new block_1.default.Builder({
74352
75669
  network: network,
74353
- signer: recipient,
75670
+ account: recipient,
74354
75671
  previous: getPrevious(recipient),
74355
75672
  operations: [{
74356
75673
  type: block_1.default.OperationType.SET_REP,
@@ -74454,9 +75771,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
74454
75771
  var __importDefault = (this && this.__importDefault) || function (mod) {
74455
75772
  return (mod && mod.__esModule) ? mod : { "default": mod };
74456
75773
  };
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;
75774
+ 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
75775
  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;
75776
+ 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
75777
  const block_1 = __webpack_require__(6158);
74461
75778
  const hash_1 = __webpack_require__(7908);
74462
75779
  const account_1 = __importStar(__webpack_require__(9415));
@@ -74478,6 +75795,7 @@ const feeExtensionSchema = {
74478
75795
  value: 0,
74479
75796
  kind: 'explicit',
74480
75797
  contains: [
75798
+ asn1_1.ValidateASN1.IsBoolean,
74481
75799
  asn1_1.ValidateASN1.IsInteger,
74482
75800
  { optional: { type: 'context', value: 0, kind: 'implicit', contains: asn1_1.ValidateASN1.IsOctetString } },
74483
75801
  { optional: { type: 'context', value: 1, kind: 'implicit', contains: asn1_1.ValidateASN1.IsOctetString } }
@@ -74578,29 +75896,35 @@ function feeFromVote(input) {
74578
75896
  }
74579
75897
  })();
74580
75898
  const feeData = feeInformation.contains;
74581
- const retval = { amount: feeData[0] };
74582
- const payToAsn1 = feeData[1];
75899
+ const quote = feeData[0];
75900
+ const retval = {
75901
+ quote: quote,
75902
+ fee: {
75903
+ amount: feeData[1]
75904
+ }
75905
+ };
75906
+ const payToAsn1 = feeData[2];
74583
75907
  if (payToAsn1 !== undefined) {
74584
75908
  const payTo = account_1.default.fromPublicKeyAndType(Buffer.from(payToAsn1.contains));
74585
75909
  if (payTo.isStorage()) {
74586
- retval.payTo = payTo;
75910
+ retval.fee.payTo = payTo;
74587
75911
  }
74588
75912
  else {
74589
75913
  try {
74590
- retval.payTo = payTo.assertAccount();
75914
+ retval.fee.payTo = payTo.assertAccount();
74591
75915
  }
74592
75916
  catch {
74593
75917
  throw (new vote_1.default('VOTE_MALFORMED_FEES_PAY_TO_INVALID', 'internal error: payTo is not an Account or Storage Address'));
74594
75918
  }
74595
75919
  }
74596
75920
  }
74597
- const tokenAsn1 = feeData[2];
75921
+ const tokenAsn1 = feeData[3];
74598
75922
  if (tokenAsn1 !== undefined) {
74599
75923
  const token = account_1.default.fromPublicKeyAndType(Buffer.from(tokenAsn1.contains));
74600
75924
  if (!token.isToken()) {
74601
75925
  throw (new vote_1.default('VOTE_MALFORMED_FEES_TOKEN_NOT_TOKEN', 'internal error: fees extension token is not a valid token'));
74602
75926
  }
74603
- retval.token = token;
75927
+ retval.fee.token = token;
74604
75928
  }
74605
75929
  return (retval);
74606
75930
  }
@@ -74734,7 +76058,11 @@ class VoteBlockHash extends buffer_1.BufferStorage {
74734
76058
  exports.VoteBlockHash = VoteBlockHash;
74735
76059
  VoteBlockHash.isInstance = (0, helper_1.checkableGenerator)(VoteBlockHash);
74736
76060
  VoteBlockHash.Map = VoteBlockHashMap;
74737
- class PossiblyExpiredVote {
76061
+ class VoteLikeBase {
76062
+ getClass() {
76063
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
76064
+ return this.constructor;
76065
+ }
74738
76066
  static isValidJSON(voteJSON) {
74739
76067
  for (const checkField of ['issuer', 'serial', 'blocks', 'validityFrom', 'validityTo', 'signature']) {
74740
76068
  if (voteJSON[checkField] === undefined) {
@@ -74756,10 +76084,15 @@ class PossiblyExpiredVote {
74756
76084
  return (false);
74757
76085
  }
74758
76086
  }
76087
+ if ('quote' in voteJSON) {
76088
+ if (voteJSON['quote'] === undefined) {
76089
+ return (false);
76090
+ }
76091
+ }
74759
76092
  return (true);
74760
76093
  }
74761
76094
  static fromJSON(voteJSON, options = {}) {
74762
- if (!PossiblyExpiredVote.isValidJSON(voteJSON)) {
76095
+ if (!VoteLikeBase.isValidJSON(voteJSON)) {
74763
76096
  throw (new vote_1.default('VOTE_INVALID_CONSTRUCTION_JSON', 'Cannot construct vote, it is not a valid vote JSON object'));
74764
76097
  }
74765
76098
  const issuer = account_1.default.toAccount(voteJSON.issuer);
@@ -74778,22 +76111,29 @@ class PossiblyExpiredVote {
74778
76111
  const validTo = new Date(voteJSON.validityTo);
74779
76112
  const validFrom = new Date(voteJSON.validityFrom);
74780
76113
  const signatureStorage = new buffer_1.BufferStorage(signature, signature.byteLength);
76114
+ if (this.expectedQuoteValue !== (voteJSON.quote ?? false)) {
76115
+ throw (new vote_1.default('VOTE_MALFORMED_FEES_QUOTE_INVALID', `internal error: fee quote mismatch found ${voteJSON.quote} - expected ${this.expectedQuoteValue}`));
76116
+ }
76117
+ if (voteJSON.quote === true && voteJSON.fee === undefined) {
76118
+ throw (new vote_1.default('VOTE_FEE_QUOTE_MISSING_FEES', 'internal error: requested quote but no fees provided'));
76119
+ }
74781
76120
  if (voteJSON.fee !== undefined) {
74782
76121
  voteBuilder.addFee(voteJSON.fee);
74783
76122
  }
74784
76123
  const { voteData, tbsCertificate, signatureInfo } = voteBuilder.generateVoteData(BigInt(voteJSON.serial), validTo, validFrom);
74785
- const vote = voteBuilder.createVote(voteData, tbsCertificate, signatureInfo, signatureStorage, options);
74786
- return (vote);
76124
+ const vote = voteBuilder.createVote(voteData, tbsCertificate, signatureInfo, signatureStorage);
76125
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
76126
+ return new this(vote, options);
74787
76127
  }
74788
76128
  constructor(vote, options = {}) {
74789
76129
  this.$trusted = false;
74790
76130
  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)) {
76131
+ _VoteLikeBase_vote.set(this, void 0);
76132
+ _VoteLikeBase_options.set(this, void 0);
76133
+ _VoteLikeBase__hash.set(this, void 0);
76134
+ _VoteLikeBase__blocksHash.set(this, void 0);
76135
+ __classPrivateFieldSet(this, _VoteLikeBase_options, { ...options }, "f");
76136
+ if (VoteLikeBase.isInstance(vote, false)) {
74797
76137
  this.issuer = vote.issuer;
74798
76138
  this.serial = vote.serial;
74799
76139
  this.blocks = vote.blocks;
@@ -74801,12 +76141,13 @@ class PossiblyExpiredVote {
74801
76141
  this.validityTo = vote.validityTo;
74802
76142
  this.signature = vote.signature;
74803
76143
  this.fee = vote.fee;
76144
+ this.quote = vote.quote;
74804
76145
  this.$trusted = vote.$trusted;
74805
76146
  this.$permanent = vote.$permanent;
74806
76147
  this.$uid = vote.$uid;
74807
76148
  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");
76149
+ __classPrivateFieldSet(this, _VoteLikeBase_vote, __classPrivateFieldGet(vote, _VoteLikeBase_vote, "f"), "f");
76150
+ __classPrivateFieldSet(this, _VoteLikeBase_options, __classPrivateFieldGet(vote, _VoteLikeBase_options, "f"), "f");
74810
76151
  return;
74811
76152
  }
74812
76153
  if (typeof vote === 'string') {
@@ -74819,18 +76160,18 @@ class PossiblyExpiredVote {
74819
76160
  vote = (0, helper_1.bufferToArrayBuffer)(vote);
74820
76161
  }
74821
76162
  if (!(util_1.types.isArrayBuffer(vote))) {
74822
- if (PossiblyExpiredVote.isValidJSON(vote)) {
74823
- vote = PossiblyExpiredVote.fromJSON(vote).toBytes();
76163
+ if (VoteLikeBase.isValidJSON(vote)) {
76164
+ vote = VoteLikeBase.fromJSON(vote).toBytes();
74824
76165
  }
74825
76166
  else {
74826
- throw (new vote_1.default('VOTE_INVALID_CONSTRUCTION', 'internal error: invalid vote constructor argument in PossiblyExpiredVote'));
76167
+ throw (new vote_1.default('VOTE_INVALID_CONSTRUCTION', 'internal error: invalid vote constructor argument in VoteLikeBase'));
74827
76168
  }
74828
76169
  }
74829
- __classPrivateFieldSet(this, _PossiblyExpiredVote_vote, vote, "f");
76170
+ __classPrivateFieldSet(this, _VoteLikeBase_vote, vote, "f");
74830
76171
  /**
74831
76172
  * Vote Wrapper contains the vote, signature info, and signature
74832
76173
  */
74833
- const voteWrapper = (0, asn1_1.ASN1toJS)(__classPrivateFieldGet(this, _PossiblyExpiredVote_vote, "f"));
76174
+ const voteWrapper = (0, asn1_1.ASN1toJS)(__classPrivateFieldGet(this, _VoteLikeBase_vote, "f"));
74834
76175
  if (!Array.isArray(voteWrapper)) {
74835
76176
  throw (new vote_1.default('VOTE_MALFORMED_WRAPPER', 'internal error: Malformed vote wrapper (must be a sequence)'));
74836
76177
  }
@@ -74930,13 +76271,13 @@ class PossiblyExpiredVote {
74930
76271
  * Votes must not be expired
74931
76272
  */
74932
76273
  const expirationCheckMomentISO = new Date(expirationCheckMoment).toISOString();
74933
- if (expirationCheckMoment < (this.validityFrom.valueOf() - PossiblyExpiredVote.allowedSlop)) {
76274
+ if (expirationCheckMoment < (this.validityFrom.valueOf() - VoteLikeBase.allowedSlop)) {
74934
76275
  throw (new vote_1.default('VOTE_MOMENT_BEFORE_VALIDITY_FROM', `Vote was issued in the future (issued on ${validFrom.toISOString()}; moment: ${expirationCheckMomentISO})`));
74935
76276
  }
74936
76277
  /**
74937
76278
  * If the vote is forever viable, it is a permanent vote
74938
76279
  */
74939
- if (this.validityTo.valueOf() > (expirationCheckMoment + PossiblyExpiredVote.permanentVoteThreshold)) {
76280
+ if (this.validityTo.valueOf() > (expirationCheckMoment + VoteLikeBase.permanentVoteThreshold)) {
74940
76281
  this.$permanent = true;
74941
76282
  }
74942
76283
  /**
@@ -75001,7 +76342,7 @@ class PossiblyExpiredVote {
75001
76342
  throw (new vote_1.default('VOTE_MALFORMED_VOTE_EXTENSIONS', 'internal error: Expected extensions to be a Sequence'));
75002
76343
  }
75003
76344
  let blocks;
75004
- let fee;
76345
+ let feeAndKind;
75005
76346
  for (const extensionInfo of extensions) {
75006
76347
  if (!Array.isArray(extensionInfo)) {
75007
76348
  throw (new vote_1.default('VOTE_MALFORMED_VOTE_EXTENSIONS_VALUE', 'internal error: Expected each extension to be a Sequence'));
@@ -75034,7 +76375,7 @@ class PossiblyExpiredVote {
75034
76375
  break;
75035
76376
  case '1.3.6.1.4.1.62675.0.1.0':
75036
76377
  case 'fees': // replace with fees 1.3.6.1.4.1.62675.0.1.0
75037
- fee = feeFromVote(extensionData);
76378
+ feeAndKind = feeFromVote(extensionData);
75038
76379
  break;
75039
76380
  default:
75040
76381
  if (critical) {
@@ -75049,11 +76390,16 @@ class PossiblyExpiredVote {
75049
76390
  throw (new vote_1.default('VOTE_MALFORMED_VOTE_NO_BLOCKS_FOUND', 'No block hashes found within vote'));
75050
76391
  }
75051
76392
  this.blocks = blocks;
75052
- if (fee !== undefined) {
76393
+ if (feeAndKind !== undefined) {
75053
76394
  if (this.$permanent) {
75054
76395
  throw (new vote_1.default('VOTE_MALFORMED_FEES_IN_PERMANENT_VOTE', 'Permanent Vote cannot have fees'));
75055
76396
  }
75056
- this.fee = fee;
76397
+ // Get the expected quote value from any child instances and compare
76398
+ if (feeAndKind.quote !== this.getClass().expectedQuoteValue) {
76399
+ throw (new vote_1.default('VOTE_MALFORMED_FEES_QUOTE_INVALID', `internal error: fee quote mismatch found ${feeAndKind.quote} - expected ${this.getClass().expectedQuoteValue}`));
76400
+ }
76401
+ this.fee = feeAndKind.fee;
76402
+ this.quote = feeAndKind.quote;
75057
76403
  }
75058
76404
  /**
75059
76405
  * Get the signature data
@@ -75141,19 +76487,19 @@ class PossiblyExpiredVote {
75141
76487
  }
75142
76488
  }
75143
76489
  toBytes() {
75144
- return (__classPrivateFieldGet(this, _PossiblyExpiredVote_vote, "f"));
76490
+ return (__classPrivateFieldGet(this, _VoteLikeBase_vote, "f"));
75145
76491
  }
75146
76492
  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");
76493
+ if (!__classPrivateFieldGet(this, _VoteLikeBase__hash, "f")) {
76494
+ __classPrivateFieldSet(this, _VoteLikeBase__hash, new VoteHash((0, hash_1.Hash)(Buffer.from(this.toBytes()))), "f");
75149
76495
  }
75150
- return (__classPrivateFieldGet(this, _PossiblyExpiredVote__hash, "f"));
76496
+ return (__classPrivateFieldGet(this, _VoteLikeBase__hash, "f"));
75151
76497
  }
75152
76498
  get blocksHash() {
75153
- if (!__classPrivateFieldGet(this, _PossiblyExpiredVote__blocksHash, "f")) {
75154
- __classPrivateFieldSet(this, _PossiblyExpiredVote__blocksHash, VoteBlockHash.fromVote(this), "f");
76499
+ if (!__classPrivateFieldGet(this, _VoteLikeBase__blocksHash, "f")) {
76500
+ __classPrivateFieldSet(this, _VoteLikeBase__blocksHash, VoteBlockHash.fromVote(this), "f");
75155
76501
  }
75156
- return (__classPrivateFieldGet(this, _PossiblyExpiredVote__blocksHash, "f"));
76502
+ return (__classPrivateFieldGet(this, _VoteLikeBase__blocksHash, "f"));
75157
76503
  }
75158
76504
  toString() {
75159
76505
  return (Buffer.from(this.toBytes()).toString('base64'));
@@ -75166,6 +76512,9 @@ class PossiblyExpiredVote {
75166
76512
  if (this.fee !== undefined) {
75167
76513
  additionalFields['fee'] = this.fee;
75168
76514
  }
76515
+ if (this.quote !== undefined) {
76516
+ additionalFields['quote'] = this.quote;
76517
+ }
75169
76518
  return ({
75170
76519
  issuer: this.issuer,
75171
76520
  serial: this.serial,
@@ -75182,8 +76531,8 @@ class PossiblyExpiredVote {
75182
76531
  }
75183
76532
  expirationCheckMoment() {
75184
76533
  let now;
75185
- if (__classPrivateFieldGet(this, _PossiblyExpiredVote_options, "f").now) {
75186
- now = __classPrivateFieldGet(this, _PossiblyExpiredVote_options, "f").now.valueOf();
76534
+ if (__classPrivateFieldGet(this, _VoteLikeBase_options, "f").now) {
76535
+ now = __classPrivateFieldGet(this, _VoteLikeBase_options, "f").now.valueOf();
75187
76536
  }
75188
76537
  else {
75189
76538
  now = Date.now();
@@ -75194,17 +76543,27 @@ class PossiblyExpiredVote {
75194
76543
  const now = this.expirationCheckMoment();
75195
76544
  const from = this.validityFrom.valueOf();
75196
76545
  const to = this.validityTo.valueOf();
75197
- if ((now + PossiblyExpiredVote.allowedSlop) < from || (now - PossiblyExpiredVote.allowedSlop) > to) {
76546
+ if ((now + VoteLikeBase.allowedSlop) < from || (now - VoteLikeBase.allowedSlop) > to) {
75198
76547
  return (true);
75199
76548
  }
75200
76549
  return (false);
75201
76550
  }
75202
76551
  }
76552
+ _VoteLikeBase_vote = new WeakMap(), _VoteLikeBase_options = new WeakMap(), _VoteLikeBase__hash = new WeakMap(), _VoteLikeBase__blocksHash = new WeakMap();
76553
+ VoteLikeBase.expectedQuoteValue = false;
76554
+ VoteLikeBase.allowedSlop = 60 /* s */ * 1000 /* ms */;
76555
+ VoteLikeBase.permanentVoteThreshold = 100 /* y */ * 365 /* d */ * 86400 /* s */ * 1000 /* ms */;
76556
+ VoteLikeBase.VoteBlocksHash = VoteBlockHash;
76557
+ VoteLikeBase.isInstance = (0, helper_1.checkableGenerator)(VoteLikeBase);
76558
+ class PossiblyExpiredVote extends VoteLikeBase {
76559
+ constructor(vote, options = {}) {
76560
+ super(vote, options);
76561
+ if (this.quote === true) {
76562
+ throw (new vote_1.default('VOTE_FEE_IS_QUOTE', `Tried to construct a vote but fee kind is QUOTE`));
76563
+ }
76564
+ }
76565
+ }
75203
76566
  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
76567
  PossiblyExpiredVote.isInstance = (0, helper_1.checkableGenerator)(PossiblyExpiredVote);
75209
76568
  /**
75210
76569
  * A vote is a certificate issued indicating that the issuer "vouches" for the
@@ -75223,6 +76582,26 @@ class Vote extends PossiblyExpiredVote {
75223
76582
  }
75224
76583
  exports.Vote = Vote;
75225
76584
  Vote.isInstance = (0, helper_1.checkableGenerator)(Vote);
76585
+ /**
76586
+ * A VoteQuote is a certificate issued indicating what the issuer will charge for fees
76587
+ */
76588
+ class VoteQuote extends VoteLikeBase {
76589
+ constructor(vote, options = {}) {
76590
+ super(vote, options);
76591
+ // We add this so both classes have different signatures
76592
+ this.isVoteQuote = true;
76593
+ if (this.expired) {
76594
+ const expirationCheckMomentISO = new Date(this.expirationCheckMoment()).toISOString();
76595
+ throw (new vote_1.default('VOTE_EXPIRED', `VoteQuote is expired (expired on ${this.validityTo.toISOString()}; issued on ${this.validityFrom.toISOString()}; moment: ${expirationCheckMomentISO})`));
76596
+ }
76597
+ if (!this.quote) {
76598
+ throw (new vote_1.default('VOTE_FEE_NOT_QUOTE', `Tried to construct a quote but fee kind is note QUOTE`));
76599
+ }
76600
+ }
76601
+ }
76602
+ exports.VoteQuote = VoteQuote;
76603
+ VoteQuote.expectedQuoteValue = true;
76604
+ VoteQuote.isInstance = (0, helper_1.checkableGenerator)(VoteQuote);
75226
76605
  /**
75227
76606
  * A vote staple is a distributable block consisting of one or more blocks
75228
76607
  * and one or more votes.
@@ -75440,8 +76819,11 @@ class VoteBlockBundle {
75440
76819
  votesStapled = (0, helper_1.bufferToArrayBuffer)(votesStapled);
75441
76820
  }
75442
76821
  if (!(util_1.types.isArrayBuffer(votesStapled))) {
75443
- if (VoteBlockBundle.isValidJSON(votesStapled)) {
75444
- votesStapled = VoteBlockBundle.fromJSON(votesStapled).toBytes(true);
76822
+ if (votesStapled instanceof VoteBlockBundle) {
76823
+ votesStapled = votesStapled.toBytes(true);
76824
+ }
76825
+ else if (VoteBlockBundle.isValidJSON(votesStapled)) {
76826
+ votesStapled = VoteBlockBundle.fromJSON(votesStapled, voteOptions).toBytes(true);
75445
76827
  }
75446
76828
  else {
75447
76829
  throw (new vote_1.default('VOTE_STAPLE_INVALID_CONSTRUCTION', 'internal error: votesStapled must be an ArrayBuffer'));
@@ -75648,33 +77030,34 @@ class VoteStaple extends VoteBlockBundle {
75648
77030
  }
75649
77031
  exports.VoteStaple = VoteStaple;
75650
77032
  VoteStaple.isInstance = (0, helper_1.checkableGenerator)(VoteStaple);
75651
- class VoteBuilder {
77033
+ class BaseVoteBuilder {
75652
77034
  constructor(account, blocks = [], options) {
75653
- _VoteBuilder_account.set(this, void 0);
75654
- _VoteBuilder_blocks.set(this, void 0);
75655
- _VoteBuilder_fee.set(this, undefined);
77035
+ _BaseVoteBuilder_account.set(this, void 0);
77036
+ _BaseVoteBuilder_blocks.set(this, void 0);
77037
+ _BaseVoteBuilder_fee.set(this, undefined);
77038
+ this.quote = false;
75656
77039
  if (!account_1.default.isInstance(account)) {
75657
77040
  throw (new vote_1.default('VOTE_BUILDER_INVALID_CONSTRUCTION', 'internal error: account must be an Account'));
75658
77041
  }
75659
- __classPrivateFieldSet(this, _VoteBuilder_account, account, "f");
75660
- __classPrivateFieldSet(this, _VoteBuilder_blocks, [], "f");
75661
- __classPrivateFieldSet(this, _VoteBuilder_fee, options?.fee, "f");
77042
+ __classPrivateFieldSet(this, _BaseVoteBuilder_account, account, "f");
77043
+ __classPrivateFieldSet(this, _BaseVoteBuilder_blocks, [], "f");
77044
+ __classPrivateFieldSet(this, _BaseVoteBuilder_fee, options?.fee, "f");
75662
77045
  this.addBlocks(blocks);
75663
77046
  }
75664
77047
  addBlocks(blocks) {
75665
77048
  for (const block of blocks) {
75666
77049
  if (block_1.Block.isInstance(block)) {
75667
- __classPrivateFieldGet(this, _VoteBuilder_blocks, "f").push(block.hash);
77050
+ __classPrivateFieldGet(this, _BaseVoteBuilder_blocks, "f").push(block.hash);
75668
77051
  continue;
75669
77052
  }
75670
77053
  if (typeof block === 'string') {
75671
- __classPrivateFieldGet(this, _VoteBuilder_blocks, "f").push(new block_1.BlockHash(block));
77054
+ __classPrivateFieldGet(this, _BaseVoteBuilder_blocks, "f").push(new block_1.BlockHash(block));
75672
77055
  continue;
75673
77056
  }
75674
77057
  if (!block_1.BlockHash.isInstance(block)) {
75675
77058
  throw (new vote_1.default('VOTE_BUILDER_INVALID_BLOCK_TYPE', 'internal error: block must be Block, BlockHash, or string'));
75676
77059
  }
75677
- __classPrivateFieldGet(this, _VoteBuilder_blocks, "f").push(block);
77060
+ __classPrivateFieldGet(this, _BaseVoteBuilder_blocks, "f").push(block);
75678
77061
  }
75679
77062
  }
75680
77063
  addBlock(block) {
@@ -75691,14 +77074,16 @@ class VoteBuilder {
75691
77074
  fee.payTo = payTo.assertAccount();
75692
77075
  }
75693
77076
  }
75694
- const token = account_1.default.toAccount(fee.token);
77077
+ const token = account_1.default.toAccount(feeInput.token);
75695
77078
  if (token !== undefined) {
75696
77079
  if (token.isToken()) {
75697
77080
  fee.token = token;
75698
77081
  }
75699
- throw (new vote_1.default('VOTE_MALFORMED_FEES_TOKEN_NOT_TOKEN', 'Fee Token should be of type TOKEN'));
77082
+ else {
77083
+ throw (new vote_1.default('VOTE_MALFORMED_FEES_TOKEN_NOT_TOKEN', 'Fee Token should be of type TOKEN'));
77084
+ }
75700
77085
  }
75701
- __classPrivateFieldSet(this, _VoteBuilder_fee, fee, "f");
77086
+ __classPrivateFieldSet(this, _BaseVoteBuilder_fee, fee, "f");
75702
77087
  }
75703
77088
  generateVoteData(serial, validTo, validFrom) {
75704
77089
  /**
@@ -75709,8 +77094,9 @@ class VoteBuilder {
75709
77094
  * Whether or not to hash the data we are signing
75710
77095
  */
75711
77096
  let hashData = false;
75712
- switch (__classPrivateFieldGet(this, _VoteBuilder_account, "f").keyType) {
77097
+ switch (__classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").keyType) {
75713
77098
  case account_1.AccountKeyAlgorithm.ECDSA_SECP256K1:
77099
+ case account_1.AccountKeyAlgorithm.ECDSA_SECP256R1:
75714
77100
  {
75715
77101
  /*
75716
77102
  * Use the default hashing function
@@ -75732,22 +77118,22 @@ class VoteBuilder {
75732
77118
  break;
75733
77119
  }
75734
77120
  /** Public Key */
75735
- const publicKey = __classPrivateFieldGet(this, _VoteBuilder_account, "f").publicKey.ASN1.getASN1();
77121
+ const publicKey = __classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").publicKey.ASN1.getASN1();
75736
77122
  /** Signature Information */
75737
77123
  const signatureInfo = [
75738
77124
  { type: 'oid', oid: signatureInfoOID }
75739
77125
  ];
75740
77126
  let feeExtension = undefined;
75741
- if (__classPrivateFieldGet(this, _VoteBuilder_fee, "f") !== undefined) {
77127
+ if (__classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f") !== undefined) {
75742
77128
  /** Amount for this vote */
75743
- const feeData = [__classPrivateFieldGet(this, _VoteBuilder_fee, "f").amount];
77129
+ const feeData = [this.quote, __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f").amount];
75744
77130
  /** Account to pay the fee too */
75745
- const payToPublicKey = __classPrivateFieldGet(this, _VoteBuilder_fee, "f").payTo?.publicKeyAndType;
77131
+ const payToPublicKey = __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f").payTo?.publicKeyAndType;
75746
77132
  if (payToPublicKey !== undefined) {
75747
77133
  feeData.push({ type: 'context', value: 0, kind: 'implicit', contains: payToPublicKey });
75748
77134
  }
75749
77135
  /** Token in which to pay the fee */
75750
- const tokenPublicKey = __classPrivateFieldGet(this, _VoteBuilder_fee, "f").token?.publicKeyAndType;
77136
+ const tokenPublicKey = __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f").token?.publicKeyAndType;
75751
77137
  if (tokenPublicKey !== undefined) {
75752
77138
  feeData.push({ type: 'context', value: 1, kind: 'implicit', contains: tokenPublicKey });
75753
77139
  }
@@ -75784,7 +77170,7 @@ class VoteBuilder {
75784
77170
  type: 'oid',
75785
77171
  oid: 'commonName'
75786
77172
  },
75787
- value: { type: 'string', kind: 'utf8', value: __classPrivateFieldGet(this, _VoteBuilder_account, "f").publicKeyString.get() }
77173
+ value: { type: 'string', kind: 'utf8', value: __classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").publicKeyString.get() }
75788
77174
  }
75789
77175
  ],
75790
77176
  /** Validity */
@@ -75834,7 +77220,7 @@ class VoteBuilder {
75834
77220
  /** Hash algorithm used to hash blocks */
75835
77221
  { type: 'oid', oid: hash_1.Hash.functionName },
75836
77222
  /** List of block hashes */
75837
- __classPrivateFieldGet(this, _VoteBuilder_blocks, "f").map(function (blockhash) {
77223
+ __classPrivateFieldGet(this, _BaseVoteBuilder_blocks, "f").map(function (blockhash) {
75838
77224
  return (blockhash.getBuffer());
75839
77225
  })
75840
77226
  ]
@@ -75858,11 +77244,11 @@ class VoteBuilder {
75858
77244
  signatureInfo: signatureInfo
75859
77245
  });
75860
77246
  }
75861
- createVote(voteData, tbsCertificate, signatureInfo, signature, voteOptions = {}) {
77247
+ createVote(voteData, tbsCertificate, signatureInfo, signature) {
75862
77248
  /**
75863
77249
  * Double-check that the signature we just created is valid for the data
75864
77250
  */
75865
- const verification = __classPrivateFieldGet(this, _VoteBuilder_account, "f").verify(voteData, signature, {
77251
+ const verification = __classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").verify(voteData, signature, {
75866
77252
  raw: true,
75867
77253
  forCert: true
75868
77254
  });
@@ -75881,16 +77267,16 @@ class VoteBuilder {
75881
77267
  * Vote: A DER-encoded certificate
75882
77268
  */
75883
77269
  const vote = certificate.toBER(false);
75884
- return (new Vote(vote, voteOptions));
77270
+ return (vote);
75885
77271
  }
75886
- async seal(serial, validTo, validFrom, voteOptions = {}) {
77272
+ async generate(serial, validTo, validFrom) {
75887
77273
  if (validFrom === undefined) {
75888
77274
  validFrom = new Date();
75889
77275
  }
75890
77276
  if (typeof serial !== 'bigint') {
75891
77277
  throw (new vote_1.default('VOTE_BUILDER_INVALID_SERIAL', `internal error: serial must be a bigint, instead got ${serial}`));
75892
77278
  }
75893
- if (validTo === null && __classPrivateFieldGet(this, _VoteBuilder_fee, "f") !== undefined) {
77279
+ if (validTo === null && __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f") !== undefined) {
75894
77280
  throw (new vote_1.default('VOTE_MALFORMED_FEES_IN_PERMANENT_VOTE', 'internal error: permanent votes should not have fees'));
75895
77281
  }
75896
77282
  if (validTo === null) {
@@ -75904,20 +77290,48 @@ class VoteBuilder {
75904
77290
  if (!(util_1.types.isDate(validFrom)) || !(util_1.types.isDate(validTo))) {
75905
77291
  throw (new vote_1.default('VOTE_BUILDER_INVALID_VALID_TO_FROM', 'internal error: validFrom must be Date'));
75906
77292
  }
77293
+ if (this.quote && __classPrivateFieldGet(this, _BaseVoteBuilder_fee, "f") === undefined) {
77294
+ throw (new vote_1.default('VOTE_FEE_QUOTE_MISSING_FEES', 'internal error: requested quote but no fees provided'));
77295
+ }
75907
77296
  const { voteData, tbsCertificate, signatureInfo } = this.generateVoteData(serial, validTo, validFrom);
75908
- const signature = await __classPrivateFieldGet(this, _VoteBuilder_account, "f").sign(voteData, {
77297
+ const signature = await __classPrivateFieldGet(this, _BaseVoteBuilder_account, "f").sign(voteData, {
75909
77298
  raw: true,
75910
77299
  forCert: true
75911
77300
  });
75912
- const vote = this.createVote(voteData, tbsCertificate, signatureInfo, signature, voteOptions);
77301
+ const voteLike = this.createVote(voteData, tbsCertificate, signatureInfo, signature);
77302
+ return (voteLike);
77303
+ }
77304
+ }
77305
+ exports.BaseVoteBuilder = BaseVoteBuilder;
77306
+ _BaseVoteBuilder_account = new WeakMap(), _BaseVoteBuilder_blocks = new WeakMap(), _BaseVoteBuilder_fee = new WeakMap();
77307
+ BaseVoteBuilder.isInstance = (0, helper_1.checkableGenerator)(BaseVoteBuilder);
77308
+ class VoteBuilder extends BaseVoteBuilder {
77309
+ async seal(serial, validTo, validFrom, voteOptions = {}) {
77310
+ const vote = await super.generate(serial, validTo, validFrom);
75913
77311
  return (new Vote(vote, voteOptions));
75914
77312
  }
75915
77313
  }
75916
77314
  exports.VoteBuilder = VoteBuilder;
75917
- _VoteBuilder_account = new WeakMap(), _VoteBuilder_blocks = new WeakMap(), _VoteBuilder_fee = new WeakMap();
75918
77315
  VoteBuilder.isInstance = (0, helper_1.checkableGenerator)(VoteBuilder);
75919
- PossiblyExpiredVote.Staple = VoteStaple;
75920
- PossiblyExpiredVote.Builder = VoteBuilder;
77316
+ class VoteQuoteBuilder extends BaseVoteBuilder {
77317
+ constructor() {
77318
+ super(...arguments);
77319
+ this.quote = true;
77320
+ }
77321
+ async seal(serial, validTo, validFrom, voteOptions = {}) {
77322
+ const voteQuote = await super.generate(serial, validTo, validFrom);
77323
+ return (new VoteQuote(voteQuote, voteOptions));
77324
+ }
77325
+ }
77326
+ exports.VoteQuoteBuilder = VoteQuoteBuilder;
77327
+ VoteQuoteBuilder.isInstance = (0, helper_1.checkableGenerator)(VoteQuoteBuilder);
77328
+ // Add respective builders to each
77329
+ VoteLikeBase.Builder = BaseVoteBuilder;
77330
+ VoteQuote.Builder = VoteQuoteBuilder;
77331
+ Vote.Builder = VoteBuilder;
77332
+ // Add to default export
77333
+ Vote.Staple = VoteStaple;
77334
+ Vote.Quote = VoteQuote;
75921
77335
  exports["default"] = Vote;
75922
77336
  /** @internal */
75923
77337
  exports.Testing = { findRDN, blockHashesFromVote, feeFromVote };
@@ -75932,7 +77346,7 @@ exports.Testing = { findRDN, blockHashesFromVote, feeFromVote };
75932
77346
 
75933
77347
  Object.defineProperty(exports, "__esModule", ({ value: true }));
75934
77348
  exports.version = void 0;
75935
- exports.version = '0.12.2+g77a8a16ada9dfab5604b605cbe69d373a414d204';
77349
+ exports.version = '0.14.0+g8b0bdc16c0cba85135437a9ffb3a8cea2dae170d';
75936
77350
  exports["default"] = exports.version;
75937
77351
 
75938
77352