trac-msb 0.2.3 → 0.2.5

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 (235) hide show
  1. package/.dockerignore +16 -0
  2. package/.github/workflows/acceptance-tests.yml +7 -0
  3. package/.github/workflows/publish.yml +40 -0
  4. package/.github/workflows/{CI.yml → unit-tests.yml} +1 -1
  5. package/README.md +175 -50
  6. package/docker-compose.yml +16 -0
  7. package/dockerfile +41 -0
  8. package/docs/fee_distribution.md +89 -0
  9. package/msb.mjs +6 -4
  10. package/package.json +8 -4
  11. package/rpc/constants.mjs +4 -1
  12. package/rpc/handlers.mjs +95 -45
  13. package/rpc/routes/v1.mjs +3 -1
  14. package/rpc/utils/confirmedParameter.mjs +17 -0
  15. package/rpc/utils/url.mjs +38 -0
  16. package/src/core/network/Network.js +27 -10
  17. package/src/core/network/identity/NetworkWalletFactory.js +78 -0
  18. package/src/core/network/services/ConnectionManager.js +2 -2
  19. package/src/core/network/services/ValidatorObserverService.js +7 -4
  20. package/src/core/state/State.js +28 -22
  21. package/src/utils/constants.js +3 -1
  22. package/tests/acceptance/v1/account/account.test.mjs +123 -0
  23. package/tests/acceptance/v1/balance/balance.test.mjs +55 -0
  24. package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +114 -0
  25. package/tests/acceptance/v1/confirmed-length/confirmed-length.test.mjs +19 -0
  26. package/tests/acceptance/v1/fee/fee.test.mjs +11 -0
  27. package/tests/acceptance/v1/rpc.test.mjs +62 -291
  28. package/tests/acceptance/v1/tx/tx.test.mjs +103 -0
  29. package/tests/acceptance/v1/tx-details/tx-details.test.mjs +203 -0
  30. package/tests/acceptance/v1/tx-hashes/tx-hashes.test.mjs +72 -0
  31. package/tests/acceptance/v1/tx-payloads-bulk/tx-payloads-bulk.test.mjs +27 -0
  32. package/tests/acceptance/v1/txv/txv.test.mjs +11 -0
  33. package/tests/acceptance/v1/unconfirmed-length/unconfirmed-length.test.mjs +11 -0
  34. package/tests/helpers/StateNetworkFactory.js +157 -0
  35. package/tests/helpers/autobaseTestHelpers.js +369 -0
  36. package/tests/helpers/createTestSignature.js +12 -0
  37. package/tests/unit/network/NetworkWalletFactory.test.js +156 -0
  38. package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +38 -0
  39. package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +273 -0
  40. package/tests/unit/state/apply/addAdmin/adminEntryEncodingFailureScenario.js +30 -0
  41. package/tests/unit/state/apply/addAdmin/adminEntryExistsScenario.js +78 -0
  42. package/tests/unit/state/apply/addAdmin/nodeEntryInitializationFailureScenario.js +30 -0
  43. package/tests/unit/state/apply/addAdmin/nonBootstrapNodeScenario.js +68 -0
  44. package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +155 -0
  45. package/tests/unit/state/apply/addIndexer/addIndexerHappyPathScenario.js +39 -0
  46. package/tests/unit/state/apply/addIndexer/addIndexerMultipleIndexersInTheNetworkScenario.js +167 -0
  47. package/tests/unit/state/apply/addIndexer/addIndexerPretenderAlreadyIndexerScenario.js +21 -0
  48. package/tests/unit/state/apply/addIndexer/addIndexerPretenderNotWriterScenario.js +21 -0
  49. package/tests/unit/state/apply/addIndexer/addIndexerRemoveAndReAddScenario.js +186 -0
  50. package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +445 -0
  51. package/tests/unit/state/apply/addIndexer/addIndexerWriterKeyAlreadyRegisteredScenario.js +32 -0
  52. package/tests/unit/state/apply/addIndexer/state.apply.addIndexer.test.js +297 -0
  53. package/tests/unit/state/apply/addWriter/addWriterHappyPathScenario.js +41 -0
  54. package/tests/unit/state/apply/addWriter/addWriterInvalidValidatorSignatureScenario.js +32 -0
  55. package/tests/unit/state/apply/addWriter/addWriterNewWkScenario.js +149 -0
  56. package/tests/unit/state/apply/addWriter/addWriterRequesterAlreadyWriterScenario.js +21 -0
  57. package/tests/unit/state/apply/addWriter/addWriterRequesterBalanceInsufficientScenario.js +21 -0
  58. package/tests/unit/state/apply/addWriter/addWriterRequesterEntryDecodeFailureScenario.js +19 -0
  59. package/tests/unit/state/apply/addWriter/addWriterRequesterEntryMissingScenario.js +19 -0
  60. package/tests/unit/state/apply/addWriter/addWriterRequesterIndexerScenario.js +21 -0
  61. package/tests/unit/state/apply/addWriter/addWriterRequesterNotWhitelistedScenario.js +21 -0
  62. package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +757 -0
  63. package/tests/unit/state/apply/addWriter/addWriterStakeBalanceUpdateFailureScenario.js +50 -0
  64. package/tests/unit/state/apply/addWriter/addWriterStakeInsufficientBalanceScenario.js +29 -0
  65. package/tests/unit/state/apply/addWriter/addWriterStakeInvalidBalanceScenario.js +29 -0
  66. package/tests/unit/state/apply/addWriter/addWriterStakeInvalidEntryScenario.js +21 -0
  67. package/tests/unit/state/apply/addWriter/addWriterStakeStakedBalanceFailureScenario.js +37 -0
  68. package/tests/unit/state/apply/addWriter/addWriterStakeSubtractFailureScenario.js +42 -0
  69. package/tests/unit/state/apply/addWriter/addWriterValidatorRewardScenario.js +105 -0
  70. package/tests/unit/state/apply/addWriter/addWriterWriterKeyMismatchScenario.js +54 -0
  71. package/tests/unit/state/apply/addWriter/addWriterWriterKeyOwnershipScenario.js +54 -0
  72. package/tests/unit/state/apply/addWriter/addWriterZeroWriterKeyScenario.js +29 -0
  73. package/tests/unit/state/apply/addWriter/state.apply.addWriter.test.js +309 -0
  74. package/tests/unit/state/apply/adminRecovery/adminRecoveryHappyPathScenario.js +30 -0
  75. package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +866 -0
  76. package/tests/unit/state/apply/adminRecovery/state.apply.adminRecovery.test.js +439 -0
  77. package/tests/unit/state/apply/appendWhitelist/appendWhitelistBanAndReapplyScenario.js +78 -0
  78. package/tests/unit/state/apply/appendWhitelist/appendWhitelistExistingReaderHappyPathScenario.js +98 -0
  79. package/tests/unit/state/apply/appendWhitelist/appendWhitelistFeeAfterDisableScenario.js +66 -0
  80. package/tests/unit/state/apply/appendWhitelist/appendWhitelistHappyPathScenario.js +55 -0
  81. package/tests/unit/state/apply/appendWhitelist/appendWhitelistInsufficientAdminBalanceScenario.js +103 -0
  82. package/tests/unit/state/apply/appendWhitelist/appendWhitelistNodeAlreadyWhitelistedScenario.js +60 -0
  83. package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +191 -0
  84. package/tests/unit/state/apply/appendWhitelist/state.apply.appendWhitelist.test.js +220 -0
  85. package/tests/unit/state/apply/balanceInitialization/balanceInitializationHappyPathScenario.js +82 -0
  86. package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +106 -0
  87. package/tests/unit/state/apply/balanceInitialization/invalidAmountScenario.js +45 -0
  88. package/tests/unit/state/apply/balanceInitialization/nodeEntryBalanceUpdateFailureScenario.js +81 -0
  89. package/tests/unit/state/apply/balanceInitialization/state.apply.balanceInitialization.test.js +189 -0
  90. package/tests/unit/state/apply/banValidator/banValidatorBanAndReWhitelistScenario.js +155 -0
  91. package/tests/unit/state/apply/banValidator/banValidatorHappyPathScenario.js +36 -0
  92. package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +534 -0
  93. package/tests/unit/state/apply/banValidator/banValidatorSequentialBansScenario.js +74 -0
  94. package/tests/unit/state/apply/banValidator/banValidatorTargetDecodeFailureScenario.js +19 -0
  95. package/tests/unit/state/apply/banValidator/banValidatorTargetIndexerScenario.js +32 -0
  96. package/tests/unit/state/apply/banValidator/banValidatorTargetNodeEntryMissingScenario.js +19 -0
  97. package/tests/unit/state/apply/banValidator/banValidatorTargetRoleUpdateFailureScenario.js +19 -0
  98. package/tests/unit/state/apply/banValidator/banValidatorWhitelistedNonWriterScenario.js +38 -0
  99. package/tests/unit/state/apply/banValidator/banValidatorWhitelistedZeroBalanceScenario.js +91 -0
  100. package/tests/unit/state/apply/banValidator/banValidatorWithdrawFailureScenario.js +19 -0
  101. package/tests/unit/state/apply/banValidator/state.apply.banValidator.test.js +266 -0
  102. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentDuplicateRegistrationScenario.js +142 -0
  103. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentHappyPathScenario.js +26 -0
  104. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentIncompleteOperationScenario.js +94 -0
  105. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentInvalidDeploymentEntryScenario.js +37 -0
  106. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentMultipleBootstrapScenario.js +86 -0
  107. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +344 -0
  108. package/tests/unit/state/apply/bootstrapDeployment/invalidValidatorNodeEntryScenario.js +57 -0
  109. package/tests/unit/state/apply/bootstrapDeployment/state.apply.bootstrapDeployment.test.js +429 -0
  110. package/tests/unit/state/apply/common/access-control/adminConsistencyMismatchScenario.js +119 -0
  111. package/tests/unit/state/apply/common/access-control/adminEntryDecodeFailureScenario.js +130 -0
  112. package/tests/unit/state/apply/common/access-control/adminEntryExistsScenario.js +93 -0
  113. package/tests/unit/state/apply/common/access-control/adminEntryMissingScenario.js +108 -0
  114. package/tests/unit/state/apply/common/access-control/adminOnlyGuardScenario.js +126 -0
  115. package/tests/unit/state/apply/common/access-control/adminPublicKeyDecodeFailureScenario.js +120 -0
  116. package/tests/unit/state/apply/common/access-control/roleAccessOperationValidationScenario.js +50 -0
  117. package/tests/unit/state/apply/common/adminControlOperationValidationScenario.js +56 -0
  118. package/tests/unit/state/apply/common/balances/adminEntryUpdateFailureScenario.js +52 -0
  119. package/tests/unit/state/apply/common/balances/base/requesterBalanceScenarioBase.js +197 -0
  120. package/tests/unit/state/apply/common/balances/feeDecodeFailureScenario.js +52 -0
  121. package/tests/unit/state/apply/common/balances/requesterBalanceDecodeFailureScenario.js +15 -0
  122. package/tests/unit/state/apply/common/balances/requesterBalanceFeeApplicationFailureScenario.js +11 -0
  123. package/tests/unit/state/apply/common/balances/requesterBalanceInsufficientScenario.js +15 -0
  124. package/tests/unit/state/apply/common/balances/requesterBalanceUpdateFailureScenario.js +11 -0
  125. package/tests/unit/state/apply/common/balances/validatorEntryRewardFailureScenario.js +11 -0
  126. package/tests/unit/state/apply/common/balances/validatorEntryUpdateFailureScenario.js +11 -0
  127. package/tests/unit/state/apply/common/balances/validatorNodeEntryDecodeFailureScenario.js +40 -0
  128. package/tests/unit/state/apply/common/base/OperationValidationScenarioBase.js +114 -0
  129. package/tests/unit/state/apply/common/commonScenarioHelper.js +103 -0
  130. package/tests/unit/state/apply/common/indexer/indexerNodeEntryDecodeFailureScenario.js +36 -0
  131. package/tests/unit/state/apply/common/indexer/indexerNodeEntryMissingScenario.js +36 -0
  132. package/tests/unit/state/apply/common/indexer/indexerRoleUpdateFailureScenario.js +29 -0
  133. package/tests/unit/state/apply/common/indexer/indexerSequenceStateInvalidScenario.js +66 -0
  134. package/tests/unit/state/apply/common/invalidMessageComponentValidationScenario.js +84 -0
  135. package/tests/unit/state/apply/common/nodeEntryInitializationFailureScenario.js +47 -0
  136. package/tests/unit/state/apply/common/operationAlreadyAppliedScenario.js +85 -0
  137. package/tests/unit/state/apply/common/payload-structure/addressWithInvalidPublicKeyScenario.js +52 -0
  138. package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +49 -0
  139. package/tests/unit/state/apply/common/payload-structure/invalidAddressValidationScenario.js +73 -0
  140. package/tests/unit/state/apply/common/payload-structure/invalidHashValidationScenario.js +71 -0
  141. package/tests/unit/state/apply/common/payload-structure/invalidPayloadValidationScenario.js +31 -0
  142. package/tests/unit/state/apply/common/payload-structure/invalidSignatureValidationScenario.js +142 -0
  143. package/tests/unit/state/apply/common/payload-structure/partialOperationValidationScenario.js +87 -0
  144. package/tests/unit/state/apply/common/requester/requesterNodeEntryBufferMissingScenario.js +70 -0
  145. package/tests/unit/state/apply/common/requester/requesterNodeEntryDecodeFailureScenario.js +72 -0
  146. package/tests/unit/state/apply/common/requester/requesterNodeEntryMissingScenario.js +36 -0
  147. package/tests/unit/state/apply/common/requesterAddressValidationScenario.js +44 -0
  148. package/tests/unit/state/apply/common/requesterPublicKeyValidationScenario.js +25 -0
  149. package/tests/unit/state/apply/common/transactionValidityMismatchScenario.js +98 -0
  150. package/tests/unit/state/apply/common/validatorConsistency/base/validatorConsistencyScenarioBase.js +201 -0
  151. package/tests/unit/state/apply/common/validatorConsistency/validatorEntryDecodeFailureScenario.js +17 -0
  152. package/tests/unit/state/apply/common/validatorConsistency/validatorEntryMissingScenario.js +44 -0
  153. package/tests/unit/state/apply/common/validatorConsistency/validatorInactiveScenario.js +19 -0
  154. package/tests/unit/state/apply/common/validatorConsistency/validatorWriterKeyMismatchScenario.js +18 -0
  155. package/tests/unit/state/apply/common/validatorEntryValidation/base/validatorEntryValidationScenarioBase.js +314 -0
  156. package/tests/unit/state/apply/common/validatorEntryValidation/validatorEntryInvalidBalanceScenario.js +18 -0
  157. package/tests/unit/state/apply/common/writerKeyExistsValidationScenario.js +43 -0
  158. package/tests/unit/state/apply/disableInitialization/disableInitializationAlreadyDisabledScenario.js +53 -0
  159. package/tests/unit/state/apply/disableInitialization/disableInitializationHappyPathScenario.js +24 -0
  160. package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +197 -0
  161. package/tests/unit/state/apply/disableInitialization/state.apply.disableInitialization.test.js +161 -0
  162. package/tests/unit/state/apply/missing-tests.md +18 -0
  163. package/tests/unit/state/apply/removeIndexer/removeIndexerHappyPathScenario.js +58 -0
  164. package/tests/unit/state/apply/removeIndexer/removeIndexerReAddAndRemoveAgainScenario.js +98 -0
  165. package/tests/unit/state/apply/removeIndexer/removeIndexerRemoveMultipleIndexersScenario.js +167 -0
  166. package/tests/unit/state/apply/removeIndexer/removeIndexerScenarioHelpers.js +428 -0
  167. package/tests/unit/state/apply/removeIndexer/removeIndexerTargetNotIndexerScenario.js +22 -0
  168. package/tests/unit/state/apply/removeIndexer/removeIndexerWriterKeyMissingScenario.js +20 -0
  169. package/tests/unit/state/apply/removeIndexer/state.apply.removeIndexer.test.js +291 -0
  170. package/tests/unit/state/apply/removeWriter/removeWriterAndAddWriterAgainScenario.js +87 -0
  171. package/tests/unit/state/apply/removeWriter/removeWriterHappyPathScenario.js +38 -0
  172. package/tests/unit/state/apply/removeWriter/removeWriterInvalidValidatorSignatureScenario.js +32 -0
  173. package/tests/unit/state/apply/removeWriter/removeWriterRequesterBalanceInsufficientScenario.js +21 -0
  174. package/tests/unit/state/apply/removeWriter/removeWriterRequesterEntryDecodeFailureScenario.js +19 -0
  175. package/tests/unit/state/apply/removeWriter/removeWriterRequesterEntryMissingScenario.js +19 -0
  176. package/tests/unit/state/apply/removeWriter/removeWriterRequesterIndexerScenario.js +21 -0
  177. package/tests/unit/state/apply/removeWriter/removeWriterRequesterNotWriterScenario.js +21 -0
  178. package/tests/unit/state/apply/removeWriter/removeWriterRequesterRoleUpdateFailureScenario.js +19 -0
  179. package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +344 -0
  180. package/tests/unit/state/apply/removeWriter/removeWriterThroughWriterValidatorScenario.js +113 -0
  181. package/tests/unit/state/apply/removeWriter/removeWriterUnstakeFailureScenario.js +33 -0
  182. package/tests/unit/state/apply/removeWriter/removeWriterWriterKeyMismatchScenario.js +21 -0
  183. package/tests/unit/state/apply/removeWriter/removeWriterWriterKeyOwnershipScenario.js +26 -0
  184. package/tests/unit/state/apply/removeWriter/removeWriterWriterKeyRegistryMissingScenario.js +22 -0
  185. package/tests/unit/state/apply/removeWriter/state.apply.removeWriter.test.js +307 -0
  186. package/tests/unit/state/apply/state.apply.test.js +24 -0
  187. package/tests/unit/state/apply/transfer/state.apply.transfer.test.js +819 -0
  188. package/tests/unit/state/apply/transfer/transferContractSchemaValidationScenario.js +22 -0
  189. package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +137 -0
  190. package/tests/unit/state/apply/transfer/transferDoubleSpendSameBatchScenario.js +63 -0
  191. package/tests/unit/state/apply/transfer/transferDoubleSpendSingleValidatorScenario.js +67 -0
  192. package/tests/unit/state/apply/transfer/transferExistingRecipientAmountScenario.js +31 -0
  193. package/tests/unit/state/apply/transfer/transferExistingRecipientZeroAmountScenario.js +31 -0
  194. package/tests/unit/state/apply/transfer/transferHandlerGuardScenarios.js +22 -0
  195. package/tests/unit/state/apply/transfer/transferHappyPathScenario.js +8 -0
  196. package/tests/unit/state/apply/transfer/transferInvalidIncomingDataScenario.js +66 -0
  197. package/tests/unit/state/apply/transfer/transferNewRecipientAmountScenario.js +31 -0
  198. package/tests/unit/state/apply/transfer/transferNewRecipientZeroAmountScenario.js +31 -0
  199. package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +1167 -0
  200. package/tests/unit/state/apply/transfer/transferSelfTransferAmountScenario.js +38 -0
  201. package/tests/unit/state/apply/transfer/transferSelfTransferZeroAmountScenario.js +38 -0
  202. package/tests/unit/state/apply/transfer/transferValidatorRecipientAmountScenario.js +38 -0
  203. package/tests/unit/state/apply/transfer/transferValidatorRecipientZeroAmountScenario.js +38 -0
  204. package/tests/unit/state/apply/txOperation/state.apply.txOperation.test.js +318 -0
  205. package/tests/unit/state/apply/txOperation/txOperationBootstrapNotRegisteredScenario.js +70 -0
  206. package/tests/unit/state/apply/txOperation/txOperationDifferentValidatorCreatorHappyPathScenario.js +23 -0
  207. package/tests/unit/state/apply/txOperation/txOperationInvalidDeploymentEntryScenario.js +48 -0
  208. package/tests/unit/state/apply/txOperation/txOperationInvalidFeeAmountScenario.js +39 -0
  209. package/tests/unit/state/apply/txOperation/txOperationInvalidSubnetCreatorAddressScenario.js +46 -0
  210. package/tests/unit/state/apply/txOperation/txOperationRequesterCreatorHappyPathScenario.js +21 -0
  211. package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +429 -0
  212. package/tests/unit/state/apply/txOperation/txOperationStandardHappyPathScenario.js +21 -0
  213. package/tests/unit/state/apply/txOperation/txOperationTransferFeeAddCreatorBalanceFailureScenario.js +26 -0
  214. package/tests/unit/state/apply/txOperation/txOperationTransferFeeAddValidatorBalanceFailureScenario.js +25 -0
  215. package/tests/unit/state/apply/txOperation/txOperationTransferFeeAddValidatorBonusFailureScenario.js +27 -0
  216. package/tests/unit/state/apply/txOperation/txOperationTransferFeeDecodeCreatorEntryScenario.js +18 -0
  217. package/tests/unit/state/apply/txOperation/txOperationTransferFeeDecodeRequesterEntryScenario.js +17 -0
  218. package/tests/unit/state/apply/txOperation/txOperationTransferFeeDecodeValidatorEntryScenario.js +31 -0
  219. package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardBypassScenario.js +49 -0
  220. package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardScenarioFactory.js +92 -0
  221. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInsufficientRequesterBalanceScenario.js +28 -0
  222. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidCreatorBalanceScenario.js +29 -0
  223. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidRequesterBalanceScenario.js +28 -0
  224. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidRequesterEntryScenario.js +17 -0
  225. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidValidatorBalanceScenario.js +33 -0
  226. package/tests/unit/state/apply/txOperation/txOperationTransferFeeMissingCreatorEntryScenario.js +18 -0
  227. package/tests/unit/state/apply/txOperation/txOperationTransferFeeSubtractFailureScenario.js +25 -0
  228. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateCreatorBalanceFailureScenario.js +26 -0
  229. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateFailureScenario.js +25 -0
  230. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateValidatorBalanceFailureScenario.js +26 -0
  231. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateValidatorBonusFailureScenario.js +27 -0
  232. package/tests/unit/state/apply/txOperation/txOperationValidatorCreatorHappyPathScenario.js +21 -0
  233. package/tests/unit/state/stateModule.test.js +1 -0
  234. package/tests/unit/state/stateTestUtils.js +5 -1
  235. package/.env +0 -0
@@ -74,7 +74,7 @@ class State extends ReadyResource {
74
74
  bigBatches: false,
75
75
  optimistic: false,
76
76
  open: this.#setupHyperbee.bind(this),
77
- apply: this.#apply.bind(this),
77
+ apply: this.applyHandler,
78
78
  })
79
79
  }
80
80
 
@@ -90,6 +90,10 @@ class State extends ReadyResource {
90
90
  return this.#bootstrap;
91
91
  }
92
92
 
93
+ get applyHandler() {
94
+ return this.#apply.bind(this);
95
+ }
96
+
93
97
  async _open() {
94
98
  console.log("State initialization...")
95
99
  await this.#base.ready();
@@ -259,7 +263,7 @@ class State extends ReadyResource {
259
263
  // Retrieve the flag to verify if initialization is allowed
260
264
  let initialization = await this.getSigned(EntryType.INITIALIZATION);
261
265
 
262
- if (null === initialization) {
266
+ if (initialization === null) {
263
267
  return false
264
268
  } else {
265
269
  return b4a.equals(initialization, safeWriteUInt32BE(0, 0))
@@ -397,7 +401,7 @@ class State extends ReadyResource {
397
401
  }
398
402
  if (invalidOperations > 0) {
399
403
  await this.#validatorPenaltyApply(batchInvoker, batch, base, invalidOperations);
400
- console.info(`Applied with ${invalidOperations} invalid operations.`);
404
+ this.#safeLogApply(`Applied with ${invalidOperations} invalid operations.`)
401
405
  }
402
406
 
403
407
  await batch.flush();
@@ -999,7 +1003,7 @@ class State extends ReadyResource {
999
1003
  // charging fee from the requester (admin)
1000
1004
  const decodedAdminNodeEntry = nodeEntryUtils.decode(newAdminNodeEntry)
1001
1005
  if (decodedAdminNodeEntry === null) {
1002
- this.#safeLogApply(OperationType.ADMIN_RECOVERY, "Failed to decode admin entry.", node.from.key)
1006
+ this.#safeLogApply(OperationType.ADMIN_RECOVERY, "Failed to decode node entry.", node.from.key)
1003
1007
  return Status.FAILURE;
1004
1008
  }
1005
1009
 
@@ -1532,7 +1536,7 @@ class State extends ReadyResource {
1532
1536
  // Charging fee from the requester
1533
1537
  const requesterBalance = toBalance(decodedRequesterNodeEntry.balance)
1534
1538
  if (requesterBalance === null) {
1535
- this.#safeLogApply(OperationType.ADD_WRITER, "Failed to verify requester balance.", node.from.key)
1539
+ this.#safeLogApply(OperationType.ADD_WRITER, "Invalid requester balance.", node.from.key)
1536
1540
  return null;
1537
1541
  };
1538
1542
 
@@ -1543,7 +1547,7 @@ class State extends ReadyResource {
1543
1547
 
1544
1548
  const updatedBalance = requesterBalance.sub(BALANCE_FEE) // Remove the fee
1545
1549
  if (updatedBalance === null) {
1546
- this.#safeLogApply(OperationType.ADD_WRITER, "Failed to apply fee to node.", node.from.key)
1550
+ this.#safeLogApply(OperationType.ADD_WRITER, "Failed to apply fee to requester balance.", node.from.key)
1547
1551
  return null;
1548
1552
  };
1549
1553
 
@@ -1834,7 +1838,7 @@ class State extends ReadyResource {
1834
1838
  };
1835
1839
  const chargedNodeEntry = updatedBalance.update(updatedNodeEntry);
1836
1840
  if (chargedNodeEntry === null) {
1837
- this.#safeLogApply(OperationType.REMOVE_WRITER, "Failed to update node entry.", node.from.key)
1841
+ this.#safeLogApply(OperationType.REMOVE_WRITER, "Failed to update node balance.", node.from.key)
1838
1842
  return null;
1839
1843
  };
1840
1844
 
@@ -2009,7 +2013,7 @@ class State extends ReadyResource {
2009
2013
 
2010
2014
  const pretenderNodeEntry = await this.#getEntryApply(pretendingAddressString, batch);
2011
2015
  if (pretenderNodeEntry === null) {
2012
- this.#safeLogApply(OperationType.ADD_INDEXER, "Failed to verify pretender indexer entry.", node.from.key)
2016
+ this.#safeLogApply(OperationType.ADD_INDEXER, "Failed to verify target indexer entry.", node.from.key)
2013
2017
  return null;
2014
2018
  };
2015
2019
 
@@ -2074,7 +2078,7 @@ class State extends ReadyResource {
2074
2078
  // 100% fee charged from admin will be burned
2075
2079
  const newAdminBalance = adminBalance.sub(feeAmount);
2076
2080
  if (newAdminBalance === null) {
2077
- this.#safeLogApply(OperationType.ADD_INDEXER, "Failed to apply fee to requester balance", node.from.key)
2081
+ this.#safeLogApply(OperationType.ADD_INDEXER, "Failed to apply fee to requester balance.", node.from.key)
2078
2082
  return null;
2079
2083
  };
2080
2084
 
@@ -2280,7 +2284,7 @@ class State extends ReadyResource {
2280
2284
  // 100% fee will be burned
2281
2285
  const newAdminBalance = adminBalance.sub(BALANCE_FEE)
2282
2286
  if (newAdminBalance === null) {
2283
- this.#safeLogApply(OperationType.REMOVE_INDEXER, "Failed to apply fee to requester balance", node.from.key)
2287
+ this.#safeLogApply(OperationType.REMOVE_INDEXER, "Failed to apply fee to requester balance.", node.from.key)
2284
2288
  return null;
2285
2289
  };
2286
2290
 
@@ -2793,13 +2797,13 @@ class State extends ReadyResource {
2793
2797
  // validate invoker signature
2794
2798
  const requesterAddressBuffer = op.address;
2795
2799
  const requesterAddressString = addressUtils.bufferToAddress(requesterAddressBuffer);
2796
- if (null === requesterAddressString) {
2800
+ if (requesterAddressString === null) {
2797
2801
  this.#safeLogApply(OperationType.TX, "Invalid requester address.", node.from.key)
2798
2802
  return Status.FAILURE;
2799
2803
  };
2800
2804
 
2801
2805
  const requesterPublicKey = PeerWallet.decodeBech32mSafe(requesterAddressString);
2802
- if (null === requesterPublicKey) {
2806
+ if (requesterPublicKey === null) {
2803
2807
  this.#safeLogApply(OperationType.TX, "Failed to decode requester public key.", node.from.key)
2804
2808
  return Status.FAILURE;
2805
2809
  };
@@ -2834,13 +2838,13 @@ class State extends ReadyResource {
2834
2838
  //second signature
2835
2839
  const validatorAddressBuffer = op.txo.va;
2836
2840
  const validatorAddressString = addressUtils.bufferToAddress(validatorAddressBuffer);
2837
- if (null === validatorAddressString) {
2841
+ if (validatorAddressString === null) {
2838
2842
  this.#safeLogApply(OperationType.TX, "Invalid validator address.", node.from.key)
2839
2843
  return Status.FAILURE;
2840
2844
  };
2841
2845
 
2842
2846
  const validatorPublicKey = PeerWallet.decodeBech32mSafe(validatorAddressString);
2843
- if (null === validatorPublicKey) {
2847
+ if (validatorPublicKey === null) {
2844
2848
  this.#safeLogApply(OperationType.TX, "Failed to decode validator public key.", node.from.key)
2845
2849
  return Status.FAILURE;
2846
2850
  };
@@ -2899,7 +2903,7 @@ class State extends ReadyResource {
2899
2903
  // point to payload, which is pointing to the txHash.
2900
2904
  const bootstrapHasBeenRegistered = await this.#getDeploymentEntryApply(op.txo.bs.toString('hex'), batch);
2901
2905
  if (bootstrapHasBeenRegistered === null) {
2902
- this.#safeLogApply(OperationType.TX, "Bootstrap already registered.", node.from.key)
2906
+ this.#safeLogApply(OperationType.TX, "Bootstrap has not been registered.", node.from.key)
2903
2907
  return Status.FAILURE;
2904
2908
  };
2905
2909
 
@@ -2931,7 +2935,8 @@ class State extends ReadyResource {
2931
2935
  batch,
2932
2936
  node
2933
2937
  );
2934
-
2938
+
2939
+ // TODO: cover next 4 guards below with tests
2935
2940
  if (transferFeeTxOperationResult === null) {
2936
2941
  this.#safeLogApply(OperationType.TX, "Fee transfer operation failed completely.", node.from.key);
2937
2942
  return Status.FAILURE;
@@ -3148,7 +3153,7 @@ class State extends ReadyResource {
3148
3153
  };
3149
3154
 
3150
3155
  if (!isSelfTransfer) {
3151
- if (null === transferResult.recipientEntry) {
3156
+ if (transferResult.recipientEntry === null) {
3152
3157
  this.#safeLogApply(OperationType.TRANSFER, "Invalid recipient entry.", node.from.key)
3153
3158
  return Status.FAILURE;
3154
3159
  };
@@ -3401,7 +3406,7 @@ class State extends ReadyResource {
3401
3406
  async #isApplyInitalizationDisabled(batch) {
3402
3407
  // Retrieve the flag to verify if initialization is allowed
3403
3408
  let initialization = await this.#getEntryApply(EntryType.INITIALIZATION, batch);
3404
- if (null === initialization) {
3409
+ if (initialization === null) {
3405
3410
  return false
3406
3411
  } else {
3407
3412
  return b4a.equals(initialization, safeWriteUInt32BE(0, 0))
@@ -3412,7 +3417,7 @@ class State extends ReadyResource {
3412
3417
  // Retrieve and increment the writers length entry
3413
3418
  let length = await this.#getEntryApply(EntryType.WRITERS_LENGTH, batch);
3414
3419
  let incrementedLength = null;
3415
- if (null === length) {
3420
+ if (length === null) {
3416
3421
  // Initialize the writers length entry if it does not exist
3417
3422
  const bufferedLength = lengthEntryUtils.init(0);
3418
3423
  length = lengthEntryUtils.decodeBE(bufferedLength);
@@ -3596,8 +3601,8 @@ class State extends ReadyResource {
3596
3601
  return;
3597
3602
  }
3598
3603
 
3599
- const deductedStakedBalance = penalty.greaterThanOrEquals(stakedBalance) ? BALANCE_ZERO : stakedBalance.sub(penalty);
3600
-
3604
+ const deductedStakedBalance = penalty.greaterThanOrEquals(stakedBalance) ? BALANCE_ZERO : stakedBalance.sub(penalty);
3605
+
3601
3606
  if (deductedStakedBalance === null) {
3602
3607
  this.#safeLogApply("ValidatorPenalty", `Failed to subtract penalty from staked balance for validator address: ${validatorAddressString}`, writingKeyBuffer);
3603
3608
  return;
@@ -3668,7 +3673,7 @@ class State extends ReadyResource {
3668
3673
  async #applyAssignNewLicense(batch) {
3669
3674
  let licenseCount = await this.#applyGetLicenseCount(batch)
3670
3675
  let newLicenseLength;
3671
- if (null === licenseCount) {
3676
+ if (licenseCount === null) {
3672
3677
  // Initialize the writers length entry if it does not exist
3673
3678
  const bufferedLength = lengthEntryUtils.init(0);
3674
3679
  licenseCount = lengthEntryUtils.decodeBE(bufferedLength);
@@ -3841,6 +3846,7 @@ class State extends ReadyResource {
3841
3846
  subnetworkCreatorEntry: updatedSubnetworkCreatorNodeEntry
3842
3847
  };
3843
3848
  }
3849
+
3844
3850
  }
3845
3851
 
3846
3852
  export default State;
@@ -124,4 +124,6 @@ export const TRAC_ADDRESS_SIZE = 63; // TODO: Change this to config().addressLe
124
124
  export const NETWORK_ID = 918; // TODO: Change this to config().network_id || 918
125
125
 
126
126
  export const MAX_VALIDATORS = 50
127
- export const MAX_RETRIES = 3
127
+ export const MAX_RETRIES = 3
128
+
129
+ export const MAX_REQUEST_COUNT = 5;
@@ -0,0 +1,123 @@
1
+ import request from "supertest"
2
+ import { bufferToBigInt, licenseBufferToBigInt } from "../../../../src/utils/amountSerialization.js"
3
+ import { ZERO_WK } from "../../../../rpc/constants.mjs"
4
+ import { ADMIN_INITIAL_STAKED_BALANCE } from "../../../../src/utils/constants.js"
5
+ import { BALANCE_TO_STAKE } from "../../../../src/core/state/utils/balance.js"
6
+ import { randomAddress } from "../../../unit/state/stateTestUtils.js"
7
+
8
+ export const registerAccountTests = (context) => {
9
+ const formatNodeEntryResponse = (address, entry) => {
10
+ const licenseValue = licenseBufferToBigInt(entry.license)
11
+ return {
12
+ address,
13
+ writingKey: entry.wk.toString('hex'),
14
+ isWhitelisted: entry.isWhitelisted,
15
+ isValidator: entry.isWriter,
16
+ isIndexer: entry.isIndexer,
17
+ license: licenseValue === 0n ? null : licenseValue.toString(),
18
+ balance: bufferToBigInt(entry.balance).toString(),
19
+ stakedBalance: bufferToBigInt(entry.stakedBalance).toString(),
20
+ }
21
+ }
22
+
23
+ describe("GET /v1/account", () => {
24
+ it("returns admin account details", async () => {
25
+ const adminEntry = await context.rpcMsb.state.getNodeEntry(context.adminWallet.address)
26
+ expect(adminEntry).toBeTruthy()
27
+
28
+ const res = await request(context.server).get(`/v1/account/${context.adminWallet.address}`)
29
+ expect(res.statusCode).toBe(200)
30
+ expect(res.body).toEqual(formatNodeEntryResponse(context.adminWallet.address, adminEntry))
31
+ expect(res.body).toMatchObject({
32
+ isWhitelisted: true,
33
+ isValidator: true,
34
+ isIndexer: true,
35
+ stakedBalance: bufferToBigInt(ADMIN_INITIAL_STAKED_BALANCE).toString(),
36
+ license: '1',
37
+ })
38
+ })
39
+
40
+ it("returns validator account details", async () => {
41
+ const writerEntry = await context.rpcMsb.state.getNodeEntry(context.wallet.address)
42
+ expect(writerEntry).toBeTruthy()
43
+
44
+ const res = await request(context.server).get(`/v1/account/${context.wallet.address}`)
45
+ expect(res.statusCode).toBe(200)
46
+ expect(res.body).toEqual(formatNodeEntryResponse(context.wallet.address, writerEntry))
47
+ expect(res.body).toMatchObject({
48
+ isWhitelisted: true,
49
+ isValidator: true,
50
+ stakedBalance: bufferToBigInt(BALANCE_TO_STAKE.value).toString(),
51
+ })
52
+ expect(res.body.license).not.toBeNull()
53
+ expect(res.body.license).not.toBe('1')
54
+ })
55
+
56
+ it("returns validator account details when confirmed=true", async () => {
57
+ const confirmedEntry = await context.rpcMsb.state.getNodeEntry(context.wallet.address)
58
+ expect(confirmedEntry).toBeTruthy()
59
+
60
+ const res = await request(context.server).get(`/v1/account/${context.wallet.address}?confirmed=true`)
61
+ expect(res.statusCode).toBe(200)
62
+ expect(res.body).toEqual(formatNodeEntryResponse(context.wallet.address, confirmedEntry))
63
+ })
64
+
65
+ it("returns validator account details (unconfirmed view)", async () => {
66
+ const unsignedEntry = await context.rpcMsb.state.getNodeEntryUnsigned(context.wallet.address)
67
+ expect(unsignedEntry).toBeTruthy()
68
+
69
+ const res = await request(context.server).get(`/v1/account/${context.wallet.address}?confirmed=false`)
70
+ expect(res.statusCode).toBe(200)
71
+ expect(res.body).toEqual(formatNodeEntryResponse(context.wallet.address, unsignedEntry))
72
+ })
73
+
74
+ it("returns default state for non-existent node", async () => {
75
+ const address = randomAddress()
76
+
77
+ const res = await request(context.server).get(`/v1/account/${address}`)
78
+ expect(res.statusCode).toBe(200)
79
+ expect(res.body).toEqual({
80
+ address: address,
81
+ writingKey: ZERO_WK.toString('hex'),
82
+ isWhitelisted: false,
83
+ isValidator: false,
84
+ isIndexer: false,
85
+ license: null,
86
+ balance: '0',
87
+ stakedBalance: '0',
88
+ })
89
+ })
90
+
91
+ it("returns 400 when address is missing", async () => {
92
+ const res = await request(context.server).get("/v1/account")
93
+ expect(res.statusCode).toBe(400)
94
+ expect(res.body).toEqual({ error: "Account address is required" })
95
+ })
96
+
97
+ it("returns 400 for invalid address format", async () => {
98
+ const res = await request(context.server).get("/v1/account/not-a-valid-address")
99
+ expect(res.statusCode).toBe(400)
100
+ expect(res.body).toEqual({ error: "Invalid account address format" })
101
+ })
102
+
103
+ it("returns 400 for invalid confirmed parameter", async () => {
104
+ const res = await request(context.server).get(`/v1/account/${context.wallet.address}?confirmed=test`)
105
+ expect(res.statusCode).toBe(400)
106
+ expect(res.body).toEqual({ error: 'Parameter "confirmed" must be exactly "true" or "false"' })
107
+ })
108
+
109
+ it("returns 500 on internal error", async () => {
110
+ const originalGetNodeEntry = context.rpcMsb.state.getNodeEntry
111
+
112
+ context.rpcMsb.state.getNodeEntry = async () => { throw new Error("test") }
113
+
114
+ try {
115
+ const res = await request(context.server).get(`/v1/account/${context.wallet.address}`)
116
+ expect(res.statusCode).toBe(500)
117
+ expect(res.body).toEqual({ error: 'An error occurred processing the request.' })
118
+ } finally {
119
+ context.rpcMsb.state.getNodeEntry = originalGetNodeEntry
120
+ }
121
+ })
122
+ })
123
+ }
@@ -0,0 +1,55 @@
1
+ import request from "supertest"
2
+ import { randomAddress } from "../../../unit/state/stateTestUtils.js"
3
+
4
+ export const registerBalanceTests = (context) => {
5
+ let expectedBalance
6
+ describe("GET /v1/balance", () => {
7
+ it("returns balance for confirmed view by default", async () => {
8
+ const res = await request(context.server).get(`/v1/balance/${context.wallet.address}`)
9
+ expect(res.statusCode).toBe(200)
10
+ expect(res.body.address).toBe(context.wallet.address)
11
+ expect(typeof res.body.balance).toBe("string")
12
+ expectedBalance = res.body.balance
13
+ })
14
+
15
+ it("returns balance for unconfirmed view", async () => {
16
+ const res = await request(context.server).get(`/v1/balance/${context.wallet.address}?confirmed=false`)
17
+ expect(res.statusCode).toBe(200)
18
+ expect(res.body).toEqual({ address: context.wallet.address, balance: expectedBalance })
19
+ })
20
+
21
+ it("returns balance when confirmed flag is explicitly true", async () => {
22
+ const res = await request(context.server).get(`/v1/balance/${context.wallet.address}?confirmed=true`)
23
+ expect(res.statusCode).toBe(200)
24
+ expect(res.body).toEqual({ address: context.wallet.address, balance: expectedBalance })
25
+ })
26
+
27
+ it("falls back to unconfirmed view on invalid confirmed flag", async () => {
28
+ const res = await request(context.server).get(`/v1/balance/${context.wallet.address}?confirmed=test`)
29
+ expect(res.statusCode).toBe(200)
30
+ expect(res.body).toEqual({ address: context.wallet.address, balance: expectedBalance })
31
+ })
32
+
33
+ it("returns 400 when address is missing", async () => {
34
+ const res = await request(context.server).get("/v1/balance")
35
+ expect(res.statusCode).toBe(400)
36
+ expect(res.body).toEqual({ error: "Wallet address is required" })
37
+ })
38
+
39
+ it("returns zero balance for an unknown address", async () => {
40
+ const address = randomAddress()
41
+ const res = await request(context.server).get(`/v1/balance/${address}`)
42
+ expect(res.statusCode).toBe(200)
43
+ expect(res.body.address).toBe(address)
44
+ expect(BigInt(res.body.balance)).toBe(0n)
45
+ })
46
+
47
+ //TODO: This test should return 400, but for backward compatibility reasons it currently returns 200 with zero balance. Please fix this.
48
+ it.skip("returns zero balance for an invalid address format", async () => {
49
+ const invalidAddress = "not-a-valid-address"
50
+ const res = await request(context.server).get(`/v1/balance/${invalidAddress}`)
51
+ expect(res.statusCode).toBe(400)
52
+ expect(res.body).toEqual({ error: "Invalid account address format" })
53
+ })
54
+ })
55
+ }
@@ -0,0 +1,114 @@
1
+ import request from "supertest"
2
+ import tracCrypto from "trac-crypto-api"
3
+ import b4a from "b4a"
4
+ import { $TNK } from "../../../../src/core/state/utils/balance.js"
5
+
6
+ const toBase64 = (value) => b4a.toString(b4a.from(JSON.stringify(value)), "base64")
7
+
8
+ export const registerBroadcastTransactionTests = (context) => {
9
+ describe("POST /v1/broadcast-transaction", () => {
10
+ it("broadcasts transaction and returns lengths", async () => {
11
+ const txData = await tracCrypto.transaction.preBuild(
12
+ context.wallet.address,
13
+ context.wallet.address,
14
+ b4a.toString($TNK(1n), 'hex'),
15
+ b4a.toString(await context.rpcMsb.state.getIndexerSequenceState(), 'hex')
16
+ )
17
+
18
+ const payload = tracCrypto.transaction.build(txData, b4a.from(context.wallet.secretKey, 'hex'))
19
+ const res = await request(context.server)
20
+ .post("/v1/broadcast-transaction")
21
+ .set("Accept", "application/json")
22
+ .send(JSON.stringify({ payload }))
23
+
24
+ expect(res.statusCode).toBe(200)
25
+ expect(res.body).toMatchObject({
26
+ result: {
27
+ message: "Transaction broadcasted successfully.",
28
+ signedLength: expect.any(Number),
29
+ unsignedLength: expect.any(Number),
30
+ tx: expect.any(String)
31
+ }
32
+ })
33
+ })
34
+
35
+ it("returns 400 when payload is missing", async () => {
36
+ const res = await request(context.server)
37
+ .post("/v1/broadcast-transaction")
38
+ .set("Accept", "application/json")
39
+ .send(JSON.stringify({}))
40
+
41
+ expect(res.statusCode).toBe(400)
42
+ expect(res.body).toEqual({ error: "Payload is missing." })
43
+ })
44
+
45
+ it("returns 400 when payload is not base64", async () => {
46
+ const res = await request(context.server)
47
+ .post("/v1/broadcast-transaction")
48
+ .set("Accept", "application/json")
49
+ .send(JSON.stringify({ payload: "not-base64" }))
50
+
51
+ expect(res.statusCode).toBe(400)
52
+ expect(res.body).toEqual({ error: "Payload must be a valid base64 string." })
53
+ })
54
+
55
+ // TODO: enable once handler returns 400 for client-side decode errors
56
+ it.skip("returns 400 when decoded payload is not valid JSON", async () => {
57
+ const invalidJsonBase64 = b4a.toString(b4a.from("{{invalid"), "base64")
58
+ const res = await request(context.server)
59
+ .post("/v1/broadcast-transaction")
60
+ .set("Accept", "application/json")
61
+ .send(JSON.stringify({ payload: invalidJsonBase64 }))
62
+
63
+ expect(res.statusCode).toBe(400)
64
+ expect(res.body).toEqual({ error: "Decoded payload is not valid JSON." })
65
+ })
66
+
67
+ // TODO: enable once handler returns 400 for client-side validation errors
68
+ it.skip("returns 400 for invalid transaction structure", async () => {
69
+ const invalidStructure = {
70
+ type: 1,
71
+ address: context.wallet.address,
72
+ }
73
+ const res = await request(context.server)
74
+ .post("/v1/broadcast-transaction")
75
+ .set("Accept", "application/json")
76
+ .send(JSON.stringify({ payload: toBase64(invalidStructure) }))
77
+
78
+ expect(res.statusCode).toBe(400)
79
+ expect(res.body).toEqual({ error: "Invalid payload structure." })
80
+ })
81
+
82
+ // TODO: AFTER REFACTORIZATION IMPROVE THESE IMPLEMENTATIONS ENDPOINT TO COVER THESE TESTS.
83
+ it.skip("returns 413 when payload exceeds size limit", async () => {
84
+ const largeString = "a".repeat(3_000_000)
85
+ const payload = toBase64({ type: 1, address: context.wallet.address, txo: { large: largeString } })
86
+
87
+ const res = await request(context.server)
88
+ .post("/v1/broadcast-transaction")
89
+ .set("Accept", "application/json")
90
+ .send(JSON.stringify({ payload }))
91
+
92
+ expect(res.statusCode).toBe(413)
93
+ })
94
+
95
+ it.skip("returns 429 on repeated broadcast failures", async () => {
96
+ // TODO: Would require forcing msb to throw 'Failed to broadcast transaction after multiple attempts.'
97
+ const txData = await tracCrypto.transaction.preBuild(
98
+ context.wallet.address,
99
+ context.wallet.address,
100
+ b4a.toString($TNK(1n), 'hex'),
101
+ b4a.toString(await context.rpcMsb.state.getIndexerSequenceState(), 'hex')
102
+ )
103
+
104
+ const payload = tracCrypto.transaction.build(txData, b4a.from(context.wallet.secretKey, 'hex'))
105
+ const res = await request(context.server)
106
+ .post("/v1/broadcast-transaction")
107
+ .set("Accept", "application/json")
108
+ .send(JSON.stringify({ payload }))
109
+
110
+ expect(res.statusCode).toBe(429)
111
+ expect(res.body).toEqual({ error: "Failed to broadcast transaction after multiple attempts." })
112
+ })
113
+ })
114
+ }
@@ -0,0 +1,19 @@
1
+ import request from "supertest"
2
+
3
+ export const registerConfirmedLengthTests = (context) => {
4
+ describe("GET /v1/confirmed-length", () => {
5
+ it("returns confirmed length", async () => {
6
+ const res = await request(context.server).get("/v1/confirmed-length")
7
+ expect(res.statusCode).toBe(200)
8
+ expect(res.body).toEqual({ confirmed_length: expect.any(Number) })
9
+ })
10
+
11
+ it("matches signed length from state", async () => {
12
+ const res = await request(context.server).get("/v1/confirmed-length")
13
+ expect(res.statusCode).toBe(200)
14
+
15
+ const signedLength = context.rpcMsb.state.getSignedLength()
16
+ expect(res.body).toEqual({ confirmed_length: signedLength })
17
+ })
18
+ })
19
+ }
@@ -0,0 +1,11 @@
1
+ import request from "supertest"
2
+
3
+ export const registerFeeTests = (context) => {
4
+ describe("GET /v1/fee", () => {
5
+ it("returns fee", async () => {
6
+ const res = await request(context.server).get("/v1/fee")
7
+ expect(res.statusCode).toBe(200)
8
+ expect(res.body).toEqual({ fee: expect.stringMatching(/^-?\d+(\.\d+)?$/) })
9
+ })
10
+ })
11
+ }