trac-msb 0.2.7 → 0.2.9

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 (187) hide show
  1. package/.github/workflows/publish.yml +8 -16
  2. package/msb.mjs +13 -25
  3. package/package.json +8 -4
  4. package/proto/network.proto +74 -0
  5. package/rpc/{create_server.mjs → create_server.js} +4 -4
  6. package/rpc/{handlers.mjs → handlers.js} +7 -7
  7. package/rpc/routes/{index.mjs → index.js} +1 -1
  8. package/rpc/routes/{v1.mjs → v1.js} +1 -1
  9. package/rpc/rpc_server.js +10 -0
  10. package/rpc/rpc_services.js +48 -7
  11. package/rpc/utils/{helpers.mjs → helpers.js} +1 -1
  12. package/src/config/config.js +137 -0
  13. package/src/config/env.js +63 -0
  14. package/src/core/network/Network.js +133 -119
  15. package/src/core/network/identity/NetworkWalletFactory.js +5 -6
  16. package/src/core/network/protocols/LegacyProtocol.js +67 -0
  17. package/src/core/network/protocols/NetworkMessages.js +48 -0
  18. package/src/core/network/protocols/ProtocolInterface.js +31 -0
  19. package/src/core/network/protocols/ProtocolSession.js +59 -0
  20. package/src/core/network/protocols/V1Protocol.js +64 -0
  21. package/src/core/network/protocols/legacy/NetworkMessageRouter.js +84 -0
  22. package/src/core/network/protocols/legacy/handlers/GetRequestHandler.js +53 -0
  23. package/src/core/network/protocols/legacy/handlers/ResponseHandler.js +37 -0
  24. package/src/core/network/{messaging → protocols/legacy}/validators/ValidatorResponse.js +2 -2
  25. package/src/core/network/{messaging → protocols/legacy}/validators/base/BaseResponse.js +13 -6
  26. package/src/core/network/protocols/shared/handlers/RoleOperationHandler.js +88 -0
  27. package/src/core/network/protocols/shared/handlers/SubnetworkOperationHandler.js +93 -0
  28. package/src/core/network/protocols/shared/handlers/TransferOperationHandler.js +57 -0
  29. package/src/core/network/{messaging → protocols/shared}/handlers/base/BaseOperationHandler.js +21 -26
  30. package/src/core/network/{messaging → protocols/shared}/validators/PartialBootstrapDeployment.js +3 -3
  31. package/src/core/network/{messaging → protocols/shared}/validators/PartialRoleAccess.js +15 -12
  32. package/src/core/network/{messaging → protocols/shared}/validators/PartialTransaction.js +10 -11
  33. package/src/core/network/{messaging → protocols/shared}/validators/PartialTransfer.js +10 -7
  34. package/src/core/network/{messaging → protocols/shared}/validators/base/PartialOperation.js +40 -22
  35. package/src/core/network/protocols/v1/NetworkMessageRouter.js +15 -0
  36. package/src/core/network/services/ConnectionManager.js +13 -19
  37. package/src/core/network/services/MessageOrchestrator.js +10 -22
  38. package/src/core/network/services/TransactionPoolService.js +10 -10
  39. package/src/core/network/services/TransactionRateLimiterService.js +5 -3
  40. package/src/core/network/services/ValidatorObserverService.js +46 -21
  41. package/src/core/state/State.js +137 -141
  42. package/src/core/state/utils/address.js +18 -16
  43. package/src/core/state/utils/adminEntry.js +17 -16
  44. package/src/core/state/utils/deploymentEntry.js +15 -15
  45. package/src/core/state/utils/transaction.js +3 -95
  46. package/src/index.js +250 -325
  47. package/src/messages/network/v1/NetworkMessageBuilder.js +325 -0
  48. package/src/messages/network/v1/NetworkMessageDirector.js +137 -0
  49. package/src/messages/network/v1/networkMessageFactory.js +12 -0
  50. package/src/messages/state/ApplyStateMessageBuilder.js +661 -0
  51. package/src/messages/state/ApplyStateMessageDirector.js +516 -0
  52. package/src/messages/state/applyStateMessageFactory.js +12 -0
  53. package/src/utils/buffer.js +53 -1
  54. package/src/utils/check.js +21 -17
  55. package/src/utils/cli.js +0 -8
  56. package/src/utils/cliCommands.js +11 -11
  57. package/src/utils/constants.js +36 -24
  58. package/src/utils/fileUtils.js +1 -4
  59. package/src/utils/helpers.js +9 -20
  60. package/src/utils/migrationUtils.js +2 -2
  61. package/src/utils/normalizers.js +94 -11
  62. package/src/utils/protobuf/network.cjs +840 -0
  63. package/src/utils/protobuf/operationHelpers.js +10 -0
  64. package/tests/acceptance/v1/account/account.test.mjs +2 -2
  65. package/tests/acceptance/v1/balance/balance.test.mjs +1 -1
  66. package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +11 -2
  67. package/tests/acceptance/v1/rpc.test.mjs +10 -10
  68. package/tests/acceptance/v1/tx/tx.test.mjs +4 -2
  69. package/tests/acceptance/v1/tx-details/tx-details.test.mjs +7 -3
  70. package/tests/fixtures/check.fixtures.js +42 -42
  71. package/tests/fixtures/networkV1.fixtures.js +84 -0
  72. package/tests/fixtures/protobuf.fixtures.js +110 -26
  73. package/tests/helpers/StateNetworkFactory.js +3 -5
  74. package/tests/helpers/autobaseTestHelpers.js +1 -2
  75. package/tests/helpers/config.js +3 -0
  76. package/tests/helpers/setupApplyTests.js +113 -99
  77. package/tests/helpers/transactionPayloads.mjs +26 -12
  78. package/tests/unit/messages/messages.test.js +12 -0
  79. package/tests/unit/messages/network/NetworkMessageBuilder.test.js +276 -0
  80. package/tests/unit/messages/network/NetworkMessageDirector.test.js +203 -0
  81. package/tests/unit/messages/state/applyStateMessageBuilder.complete.test.js +521 -0
  82. package/tests/unit/messages/state/applyStateMessageBuilder.partial.test.js +233 -0
  83. package/tests/unit/network/ConnectionManager.test.js +10 -7
  84. package/tests/unit/network/NetworkWalletFactory.test.js +14 -14
  85. package/tests/unit/network/networkModule.test.js +3 -2
  86. package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +10 -6
  87. package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +11 -8
  88. package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +11 -7
  89. package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +18 -20
  90. package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +57 -48
  91. package/tests/unit/state/apply/addWriter/addWriterValidatorRewardScenario.js +2 -1
  92. package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +72 -57
  93. package/tests/unit/state/apply/adminRecovery/state.apply.adminRecovery.test.js +3 -7
  94. package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +12 -14
  95. package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +18 -13
  96. package/tests/unit/state/apply/balanceInitialization/nodeEntryBalanceUpdateFailureScenario.js +2 -1
  97. package/tests/unit/state/apply/banValidator/banValidatorBanAndReWhitelistScenario.js +2 -1
  98. package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +27 -30
  99. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentDuplicateRegistrationScenario.js +2 -1
  100. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +24 -21
  101. package/tests/unit/state/apply/common/access-control/adminConsistencyMismatchScenario.js +5 -4
  102. package/tests/unit/state/apply/common/access-control/adminPublicKeyDecodeFailureScenario.js +4 -3
  103. package/tests/unit/state/apply/common/balances/base/requesterBalanceScenarioBase.js +2 -1
  104. package/tests/unit/state/apply/common/commonScenarioHelper.js +16 -16
  105. package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +10 -5
  106. package/tests/unit/state/apply/common/payload-structure/invalidHashValidationScenario.js +2 -2
  107. package/tests/unit/state/apply/common/requester/requesterNodeEntryBufferMissingScenario.js +2 -1
  108. package/tests/unit/state/apply/common/requester/requesterNodeEntryDecodeFailureScenario.js +2 -1
  109. package/tests/unit/state/apply/common/validatorConsistency/base/validatorConsistencyScenarioBase.js +2 -1
  110. package/tests/unit/state/apply/common/validatorEntryValidation/base/validatorEntryValidationScenarioBase.js +2 -1
  111. package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +16 -9
  112. package/tests/unit/state/apply/removeIndexer/removeIndexerScenarioHelpers.js +6 -5
  113. package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +23 -19
  114. package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +45 -36
  115. package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +48 -45
  116. package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +32 -29
  117. package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardScenarioFactory.js +2 -1
  118. package/tests/unit/state/stateModule.test.js +0 -1
  119. package/tests/unit/state/stateTestUtils.js +7 -3
  120. package/tests/unit/state/utils/address.test.js +3 -3
  121. package/tests/unit/state/utils/adminEntry.test.js +10 -9
  122. package/tests/unit/unit.test.js +1 -1
  123. package/tests/unit/utils/buffer/buffer.test.js +62 -1
  124. package/tests/unit/utils/check/adminControlOperation.test.js +3 -3
  125. package/tests/unit/utils/check/balanceInitializationOperation.test.js +2 -2
  126. package/tests/unit/utils/check/bootstrapDeploymentOperation.test.js +2 -3
  127. package/tests/unit/utils/check/common.test.js +7 -6
  128. package/tests/unit/utils/check/coreAdminOperation.test.js +3 -3
  129. package/tests/unit/utils/check/roleAccessOperation.test.js +3 -2
  130. package/tests/unit/utils/check/transactionOperation.test.js +3 -3
  131. package/tests/unit/utils/check/transferOperation.test.js +3 -3
  132. package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +2 -1
  133. package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +2 -1
  134. package/tests/unit/utils/migrationUtils/validateAddressFromIncomingFile.test.js +7 -0
  135. package/tests/unit/utils/normalizers/normalizers.test.js +469 -0
  136. package/tests/unit/utils/protobuf/operationHelpers.test.js +120 -2
  137. package/tests/unit/utils/utils.test.js +0 -1
  138. package/rpc/rpc_server.mjs +0 -10
  139. package/src/core/network/messaging/NetworkMessages.js +0 -63
  140. package/src/core/network/messaging/handlers/GetRequestHandler.js +0 -112
  141. package/src/core/network/messaging/handlers/ResponseHandler.js +0 -108
  142. package/src/core/network/messaging/handlers/RoleOperationHandler.js +0 -116
  143. package/src/core/network/messaging/handlers/SubnetworkOperationHandler.js +0 -143
  144. package/src/core/network/messaging/handlers/TransferOperationHandler.js +0 -52
  145. package/src/core/network/messaging/routes/NetworkMessageRouter.js +0 -94
  146. package/src/core/network/messaging/validators/AdminResponse.js +0 -58
  147. package/src/core/network/messaging/validators/CustomNodeResponse.js +0 -46
  148. package/src/core/state/utils/indexerEntry.js +0 -105
  149. package/src/messages/base/StateBuilder.js +0 -25
  150. package/src/messages/completeStateMessages/CompleteStateMessageBuilder.js +0 -421
  151. package/src/messages/completeStateMessages/CompleteStateMessageDirector.js +0 -252
  152. package/src/messages/completeStateMessages/CompleteStateMessageOperations.js +0 -299
  153. package/src/messages/partialStateMessages/PartialStateMessageBuilder.js +0 -272
  154. package/src/messages/partialStateMessages/PartialStateMessageDirector.js +0 -137
  155. package/src/messages/partialStateMessages/PartialStateMessageOperations.js +0 -131
  156. package/src/utils/crypto.js +0 -11
  157. package/tests/integration/apply/addAdmin/addAdminBasic.test.js +0 -68
  158. package/tests/integration/apply/addAdmin/addAdminRecovery.test.js +0 -125
  159. package/tests/integration/apply/addIndexer.test.js +0 -237
  160. package/tests/integration/apply/addWhitelist.test.js +0 -53
  161. package/tests/integration/apply/addWriter.test.js +0 -244
  162. package/tests/integration/apply/apply.test.js +0 -19
  163. package/tests/integration/apply/banValidator.test.js +0 -109
  164. package/tests/integration/apply/postTx/invalidSubValues.test.js +0 -103
  165. package/tests/integration/apply/postTx/postTx.test.js +0 -222
  166. package/tests/integration/apply/removeIndexer.test.js +0 -128
  167. package/tests/integration/apply/removeWriter.test.js +0 -167
  168. package/tests/integration/apply/transfer.test.js +0 -81
  169. package/tests/integration/integration.test.js +0 -9
  170. package/tests/unit/messageOperations/assembleAddIndexerMessage.test.js +0 -21
  171. package/tests/unit/messageOperations/assembleAddWriterMessage.test.js +0 -16
  172. package/tests/unit/messageOperations/assembleAdminMessage.test.js +0 -69
  173. package/tests/unit/messageOperations/assembleBanWriterMessage.test.js +0 -16
  174. package/tests/unit/messageOperations/assemblePostTransaction.test.js +0 -442
  175. package/tests/unit/messageOperations/assembleRemoveIndexerMessage.test.js +0 -19
  176. package/tests/unit/messageOperations/assembleRemoveWriterMessage.test.js +0 -17
  177. package/tests/unit/messageOperations/assembleWhitelistMessages.test.js +0 -58
  178. package/tests/unit/messageOperations/commonsStateMessageOperationsTest.js +0 -277
  179. package/tests/unit/messageOperations/stateMessageOperations.test.js +0 -19
  180. package/tests/unit/state/utils/indexerEntry.test.js +0 -83
  181. package/tests/unit/state/utils/transaction.test.js +0 -97
  182. package/tests/unit/utils/crypto/createHash.test.js +0 -15
  183. /package/rpc/{constants.mjs → constants.js} +0 -0
  184. /package/rpc/{cors.mjs → cors.js} +0 -0
  185. /package/rpc/utils/{confirmedParameter.mjs → confirmedParameter.js} +0 -0
  186. /package/rpc/utils/{url.mjs → url.js} +0 -0
  187. /package/src/utils/{operations.js → applyOperations.js} +0 -0
@@ -0,0 +1,661 @@
1
+ import b4a from 'b4a';
2
+ import PeerWallet from 'trac-wallet';
3
+
4
+ import { createMessage } from '../../utils/buffer.js';
5
+ import { OperationType } from '../../utils/constants.js';
6
+ import { addressToBuffer, bufferToAddress } from '../../core/state/utils/address.js';
7
+ import { isAddressValid } from "../../core/state/utils/address.js";
8
+ import {
9
+ isAdminControl,
10
+ isBalanceInitialization,
11
+ isBootstrapDeployment,
12
+ isCoreAdmin,
13
+ isRoleAccess,
14
+ isTransaction,
15
+ isTransfer,
16
+ operationToPayload
17
+ } from '../../utils/applyOperations.js';
18
+ import { isHexString } from '../../utils/helpers.js';
19
+
20
+ // Single use per transaction: reuse of this instance needs mutex/queue or fail-fast and can delay validation or break validation rule.
21
+ // A fresh instance is effectively zero-cost, so no reset() is provided.
22
+
23
+ /**
24
+ * Builder for partial/complete ApplyState messages.
25
+ * @param {PeerWallet} wallet
26
+ * @param {object} config
27
+ */
28
+ class ApplyStateMessageBuilder {
29
+ #address;
30
+ #amount;
31
+ #channel;
32
+ #config
33
+ #contentHash;
34
+ #externalBootstrap;
35
+ #incomingAddress;
36
+ #incomingNonce;
37
+ #incomingSignature;
38
+ #incomingWriterKey;
39
+ #msbBootstrap;
40
+ #operationType;
41
+ #payload;
42
+ #txHash;
43
+ #txValidity;
44
+ #wallet;
45
+ #writingKey;
46
+ #phase;
47
+ #output;
48
+ #payloadKey;
49
+ #built=false;
50
+
51
+ constructor(wallet, config) {
52
+ this.#config = config;
53
+ if (!wallet || typeof wallet !== 'object') {
54
+ throw new Error('Wallet must be a valid wallet object');
55
+ }
56
+ if (!isAddressValid(wallet.address, this.#config.addressPrefix)) {
57
+ throw new Error('Wallet should have a valid TRAC address.');
58
+ }
59
+
60
+ this.#wallet = wallet;
61
+ }
62
+
63
+ setPhase(phase) {
64
+ if (!['partial', 'complete'].includes(phase)) {
65
+ throw new Error(`Invalid phase: ${phase}`);
66
+ }
67
+ this.#phase = phase;
68
+ return this;
69
+ }
70
+
71
+ setOutput(output) {
72
+ if (!['json', 'buffer'].includes(output)) {
73
+ throw new Error(`Invalid output format: ${output}`);
74
+ }
75
+ this.#output = output;
76
+ return this;
77
+ }
78
+
79
+ setOperationType(operationType) {
80
+ if (!Object.values(OperationType).includes(operationType)) {
81
+ throw new Error(`Invalid operation type: ${operationType}`);
82
+ }
83
+ this.#operationType = operationType;
84
+ return this;
85
+ }
86
+
87
+ setAddress(address) {
88
+ const addressBuffer = this.#normalizeAddress(address);
89
+ if (!addressBuffer) {
90
+ throw new Error(`Address field must be a valid TRAC bech32m address with length ${this.#config.addressLength}.`);
91
+ }
92
+
93
+ this.#address = addressBuffer;
94
+ return this;
95
+ }
96
+
97
+ setWriterKey(writingKey) {
98
+ this.#writingKey = this.#normalizeHexBuffer(writingKey, 32, 'Writer key');
99
+ return this;
100
+ }
101
+
102
+ setTxHash(txHash) {
103
+ this.#txHash = this.#normalizeHexBuffer(txHash, 32, 'Transaction hash');
104
+ return this;
105
+ }
106
+
107
+ setIncomingAddress(address) {
108
+ const addressBuffer = this.#normalizeAddress(address);
109
+ if (!addressBuffer) {
110
+ throw new Error(`Address field must be a valid TRAC bech32m address with length ${this.#config.addressLength}.`);
111
+ }
112
+
113
+ this.#incomingAddress = addressBuffer;
114
+ return this;
115
+ }
116
+
117
+ setIncomingWriterKey(writerKey) {
118
+ this.#incomingWriterKey = this.#normalizeHexBuffer(writerKey, 32, 'Incoming writer key');
119
+ return this;
120
+ }
121
+
122
+ setIncomingNonce(nonce) {
123
+ this.#incomingNonce = this.#normalizeHexBuffer(nonce, 32, 'Incoming nonce');
124
+ return this;
125
+ }
126
+
127
+ setContentHash(contentHash) {
128
+ this.#contentHash = this.#normalizeHexBuffer(contentHash, 32, 'Content hash');
129
+ return this;
130
+ }
131
+
132
+ setIncomingSignature(signature) {
133
+ this.#incomingSignature = this.#normalizeHexBuffer(signature, 64, 'Incoming signature');
134
+ return this;
135
+ }
136
+
137
+ setExternalBootstrap(bootstrapKey) {
138
+ this.#externalBootstrap = this.#normalizeHexBuffer(bootstrapKey, 32, 'Bootstrap key');
139
+ return this;
140
+ }
141
+
142
+ setMsbBootstrap(msbBootstrap) {
143
+ this.#msbBootstrap = this.#normalizeHexBuffer(msbBootstrap, 32, 'MSB bootstrap');
144
+ return this;
145
+ }
146
+
147
+ setChannel(channel) {
148
+ this.#channel = this.#normalizeHexBuffer(channel, 32, 'Channel');
149
+ return this;
150
+ }
151
+
152
+ setTxValidity(txValidity) {
153
+ this.#txValidity = this.#normalizeHexBuffer(txValidity, 32, 'Transaction validity');
154
+ return this;
155
+ }
156
+
157
+ setAmount(amount) {
158
+ this.#amount = this.#normalizeHexBuffer(amount, 16, 'Amount');
159
+ return this;
160
+ }
161
+
162
+ #requireFields(fields) {
163
+ for (const [value, name] of fields) {
164
+ if (!value) {
165
+ throw new Error(`${name} must be set before build.`);
166
+ }
167
+ }
168
+ }
169
+
170
+ async build() {
171
+ this.#assertPhaseAndOutput();
172
+
173
+ if (!this.#operationType) {
174
+ throw new Error('Operation type must be set before build.');
175
+ }
176
+
177
+ if (!this.#address) {
178
+ throw new Error('Address must be set before build.');
179
+ }
180
+
181
+ const payloadKey = operationToPayload(this.#operationType);
182
+ if (!payloadKey) {
183
+ throw new Error(`Unsupported operation type: ${this.#operationType}`);
184
+ }
185
+
186
+ let body;
187
+ if (this.#phase === 'partial') {
188
+ body = await this.#buildPartialBody();
189
+ } else {
190
+ body = await this.#buildCompleteBody();
191
+ }
192
+
193
+ this.#payloadKey = payloadKey;
194
+ this.#payload = {
195
+ type: this.#operationType,
196
+ address: this.#address,
197
+ [payloadKey]: body
198
+ };
199
+ this.#built = true;
200
+ return this;
201
+ }
202
+
203
+ getPayload() {
204
+ if (!this.#built || !this.#payload) {
205
+ throw new Error('Payload has not been built.');
206
+ }
207
+ return this.#output === 'json' ? this.#encodePayloadJson(this.#payload) : this.#payload;
208
+ }
209
+
210
+ #assertPhaseAndOutput() {
211
+ if (!this.#phase) {
212
+ throw new Error('Phase must be set before build.');
213
+ }
214
+
215
+ if (!this.#output) {
216
+ throw new Error('Output format must be set before build.');
217
+ }
218
+
219
+ // We assume that complete phase only supports buffer output. So this check will be enforced
220
+ if (this.#phase === 'complete' && this.#output !== 'buffer') {
221
+ throw new Error('Complete phase only supports buffer output.');
222
+ }
223
+ }
224
+
225
+ #normalizeHexBuffer(value, expectedBytes, fieldName) {
226
+ // with normalizer built in builder, we can remove other normalizers later.
227
+ if (b4a.isBuffer(value)) {
228
+ if (value.length !== expectedBytes) {
229
+ throw new Error(`${fieldName} must be a ${expectedBytes}-byte buffer.`);
230
+ }
231
+ return value;
232
+ }
233
+ if (typeof value === 'string') {
234
+ const expectedLength = expectedBytes * 2;
235
+ if (!isHexString(value) || value.length !== expectedLength) {
236
+ throw new Error(`${fieldName} must be a ${expectedLength}-length hexstring.`);
237
+ }
238
+ return b4a.from(value, 'hex');
239
+ }
240
+ throw new Error(`${fieldName} must be a ${expectedBytes}-byte buffer or ${expectedBytes * 2}-length hexstring.`);
241
+ }
242
+
243
+ #normalizeAddress(address) {
244
+ if (b4a.isBuffer(address)) {
245
+ const addr = bufferToAddress(address, this.#config.addressPrefix);
246
+ return addr ? address : null;
247
+ }
248
+ if (!isAddressValid(address, this.#config.addressPrefix)) {
249
+ return null;
250
+ }
251
+ return addressToBuffer(address, this.#config.addressPrefix);
252
+ }
253
+
254
+ async #buildPartialBody() {
255
+ if (!isRoleAccess(this.#operationType) && !isTransaction(this.#operationType) &&
256
+ !isBootstrapDeployment(this.#operationType) && !isTransfer(this.#operationType)) {
257
+ throw new Error(`Operation type ${this.#operationType} is not supported for partial build.`);
258
+ }
259
+
260
+ const nonce = PeerWallet.generateNonce();
261
+ let msg;
262
+
263
+ switch (this.#operationType) {
264
+ case OperationType.ADD_WRITER:
265
+ case OperationType.REMOVE_WRITER:
266
+ case OperationType.ADMIN_RECOVERY:
267
+ this.#requireFields([
268
+ [this.#txValidity, 'Transaction validity'],
269
+ [this.#writingKey, 'Writer key']
270
+ ]);
271
+ msg = createMessage(
272
+ this.#config.networkId,
273
+ this.#txValidity,
274
+ this.#writingKey,
275
+ nonce,
276
+ this.#operationType
277
+ );
278
+ break;
279
+ case OperationType.BOOTSTRAP_DEPLOYMENT:
280
+ this.#requireFields([
281
+ [this.#txValidity, 'Transaction validity'],
282
+ [this.#externalBootstrap, 'External bootstrap'],
283
+ [this.#channel, 'Channel']
284
+ ]);
285
+ msg = createMessage(
286
+ this.#config.networkId,
287
+ this.#txValidity,
288
+ this.#externalBootstrap,
289
+ this.#channel,
290
+ nonce,
291
+ OperationType.BOOTSTRAP_DEPLOYMENT
292
+ );
293
+ break;
294
+ case OperationType.TX:
295
+ this.#requireFields([
296
+ [this.#txValidity, 'Transaction validity'],
297
+ [this.#writingKey, 'Writer key'],
298
+ [this.#contentHash, 'Content hash'],
299
+ [this.#externalBootstrap, 'External bootstrap'],
300
+ [this.#msbBootstrap, 'MSB bootstrap']
301
+ ]);
302
+ msg = createMessage(
303
+ this.#config.networkId,
304
+ this.#txValidity,
305
+ this.#writingKey,
306
+ this.#contentHash,
307
+ this.#externalBootstrap,
308
+ this.#msbBootstrap,
309
+ nonce,
310
+ OperationType.TX
311
+ );
312
+ break;
313
+ case OperationType.TRANSFER:
314
+ this.#requireFields([
315
+ [this.#txValidity, 'Transaction validity'],
316
+ [this.#incomingAddress, 'Incoming address'],
317
+ [this.#amount, 'Amount']
318
+ ]);
319
+ msg = createMessage(
320
+ this.#config.networkId,
321
+ this.#txValidity,
322
+ this.#incomingAddress,
323
+ this.#amount,
324
+ nonce,
325
+ OperationType.TRANSFER
326
+ );
327
+ break;
328
+ default:
329
+ throw new Error(`Unsupported operation type: ${this.#operationType}`);
330
+ }
331
+
332
+ const tx = await PeerWallet.blake3(msg);
333
+ const signature = this.#wallet.sign(tx);
334
+
335
+ if (isBootstrapDeployment(this.#operationType)) {
336
+ return {
337
+ tx,
338
+ txv: this.#txValidity,
339
+ bs: this.#externalBootstrap,
340
+ ic: this.#channel,
341
+ in: nonce,
342
+ is: signature
343
+ };
344
+ }
345
+ if (isRoleAccess(this.#operationType)) {
346
+ return {
347
+ tx,
348
+ txv: this.#txValidity,
349
+ iw: this.#writingKey,
350
+ in: nonce,
351
+ is: signature
352
+ };
353
+ }
354
+ if (isTransaction(this.#operationType)) {
355
+ return {
356
+ tx,
357
+ txv: this.#txValidity,
358
+ iw: this.#writingKey,
359
+ ch: this.#contentHash,
360
+ bs: this.#externalBootstrap,
361
+ mbs: this.#msbBootstrap,
362
+ in: nonce,
363
+ is: signature,
364
+ };
365
+ }
366
+ if (isTransfer(this.#operationType)) {
367
+ return {
368
+ tx,
369
+ txv: this.#txValidity,
370
+ to: this.#incomingAddress,
371
+ am: this.#amount,
372
+ in: nonce,
373
+ is: signature
374
+ };
375
+ }
376
+
377
+ throw new Error(`No corresponding value type for operation: ${this.#operationType}`);
378
+ }
379
+
380
+ async #buildCompleteBody() {
381
+ const nonce = PeerWallet.generateNonce();
382
+ let msg;
383
+
384
+ switch (this.#operationType) {
385
+ case OperationType.ADD_ADMIN:
386
+ case OperationType.DISABLE_INITIALIZATION:
387
+ this.#requireFields([
388
+ [this.#txValidity, 'Transaction validity'],
389
+ [this.#writingKey, 'Writer key']
390
+ ]);
391
+ msg = createMessage(
392
+ this.#config.networkId,
393
+ this.#txValidity,
394
+ this.#writingKey,
395
+ nonce,
396
+ this.#operationType
397
+ );
398
+ break;
399
+ case OperationType.BALANCE_INITIALIZATION:
400
+ this.#requireFields([
401
+ [this.#txValidity, 'Transaction validity'],
402
+ [this.#incomingAddress, 'Incoming address'],
403
+ [this.#amount, 'Amount']
404
+ ]);
405
+ msg = createMessage(
406
+ this.#config.networkId,
407
+ this.#txValidity,
408
+ this.#incomingAddress,
409
+ this.#amount,
410
+ nonce,
411
+ this.#operationType
412
+ );
413
+ break;
414
+ case OperationType.APPEND_WHITELIST:
415
+ case OperationType.ADD_INDEXER:
416
+ case OperationType.REMOVE_INDEXER:
417
+ case OperationType.BAN_VALIDATOR: {
418
+ this.#requireFields([
419
+ [this.#txValidity, 'Transaction validity'],
420
+ [this.#incomingAddress, 'Incoming address']
421
+ ]);
422
+ const incomingAddress = bufferToAddress(this.#incomingAddress, this.#config.addressPrefix);
423
+ if (incomingAddress && this.#wallet.address === incomingAddress) {
424
+ throw new Error('Address must not be the same as the wallet address for basic operations.');
425
+ }
426
+ msg = createMessage(
427
+ this.#config.networkId,
428
+ this.#txValidity,
429
+ this.#incomingAddress,
430
+ nonce,
431
+ this.#operationType
432
+ );
433
+ break;
434
+ }
435
+ case OperationType.ADD_WRITER:
436
+ case OperationType.REMOVE_WRITER:
437
+ case OperationType.ADMIN_RECOVERY:
438
+ this.#requireFields([
439
+ [this.#txHash, 'Transaction hash'],
440
+ [this.#txValidity, 'Transaction validity'],
441
+ [this.#incomingWriterKey, 'Incoming writer key'],
442
+ [this.#incomingNonce, 'Incoming nonce'],
443
+ [this.#incomingSignature, 'Incoming signature']
444
+ ]);
445
+ msg = createMessage(
446
+ this.#config.networkId,
447
+ this.#txHash,
448
+ nonce,
449
+ this.#operationType
450
+ );
451
+ break;
452
+ case OperationType.BOOTSTRAP_DEPLOYMENT:
453
+ this.#requireFields([
454
+ [this.#txHash, 'Transaction hash'],
455
+ [this.#txValidity, 'Transaction validity'],
456
+ [this.#externalBootstrap, 'External bootstrap'],
457
+ [this.#channel, 'Channel'],
458
+ [this.#incomingNonce, 'Incoming nonce'],
459
+ [this.#incomingSignature, 'Incoming signature']
460
+ ]);
461
+ msg = createMessage(
462
+ this.#config.networkId,
463
+ this.#txHash,
464
+ nonce,
465
+ this.#operationType
466
+ );
467
+ break;
468
+ case OperationType.TX:
469
+ this.#requireFields([
470
+ [this.#txHash, 'Transaction hash'],
471
+ [this.#txValidity, 'Transaction validity'],
472
+ [this.#incomingWriterKey, 'Incoming writer key'],
473
+ [this.#incomingNonce, 'Incoming nonce'],
474
+ [this.#incomingSignature, 'Incoming signature'],
475
+ [this.#contentHash, 'Content hash'],
476
+ [this.#externalBootstrap, 'External bootstrap'],
477
+ [this.#msbBootstrap, 'MSB bootstrap']
478
+ ]);
479
+ msg = createMessage(
480
+ this.#config.networkId,
481
+ this.#txHash,
482
+ nonce,
483
+ this.#operationType
484
+ );
485
+ break;
486
+ case OperationType.TRANSFER:
487
+ this.#requireFields([
488
+ [this.#txHash, 'Transaction hash'],
489
+ [this.#txValidity, 'Transaction validity'],
490
+ [this.#incomingAddress, 'Incoming address'],
491
+ [this.#amount, 'Amount'],
492
+ [this.#incomingNonce, 'Incoming nonce'],
493
+ [this.#incomingSignature, 'Incoming signature']
494
+ ]);
495
+ msg = createMessage(
496
+ this.#config.networkId,
497
+ this.#txHash,
498
+ nonce,
499
+ this.#operationType
500
+ );
501
+ break;
502
+ default:
503
+ throw new Error(`Unsupported operation type: ${this.#operationType}`);
504
+ }
505
+
506
+ const tx = await PeerWallet.blake3(msg);
507
+ const signature = this.#wallet.sign(tx);
508
+ const validatorAddress = addressToBuffer(this.#wallet.address, this.#config.addressPrefix);
509
+
510
+ if (isCoreAdmin(this.#operationType)) {
511
+ return {
512
+ tx,
513
+ txv: this.#txValidity,
514
+ iw: this.#writingKey,
515
+ in: nonce,
516
+ is: signature
517
+ };
518
+ }
519
+ if (isAdminControl(this.#operationType)) {
520
+ return {
521
+ tx,
522
+ txv: this.#txValidity,
523
+ ia: this.#incomingAddress,
524
+ in: nonce,
525
+ is: signature
526
+ };
527
+ }
528
+ if (isRoleAccess(this.#operationType)) {
529
+ return {
530
+ tx: this.#txHash,
531
+ txv: this.#txValidity,
532
+ iw: this.#incomingWriterKey,
533
+ in: this.#incomingNonce,
534
+ is: this.#incomingSignature,
535
+ va: validatorAddress,
536
+ vn: nonce,
537
+ vs: signature,
538
+ };
539
+ }
540
+ if (isTransaction(this.#operationType)) {
541
+ return {
542
+ tx: this.#txHash,
543
+ txv: this.#txValidity,
544
+ iw: this.#incomingWriterKey,
545
+ ch: this.#contentHash,
546
+ bs: this.#externalBootstrap,
547
+ mbs: this.#msbBootstrap,
548
+ in: this.#incomingNonce,
549
+ is: this.#incomingSignature,
550
+ va: validatorAddress,
551
+ vn: nonce,
552
+ vs: signature,
553
+ };
554
+ }
555
+ if (isBootstrapDeployment(this.#operationType)) {
556
+ return {
557
+ tx: this.#txHash,
558
+ txv: this.#txValidity,
559
+ bs: this.#externalBootstrap,
560
+ ic: this.#channel,
561
+ in: this.#incomingNonce,
562
+ is: this.#incomingSignature,
563
+ va: validatorAddress,
564
+ vn: nonce,
565
+ vs: signature
566
+ };
567
+ }
568
+ if (isTransfer(this.#operationType)) {
569
+ return {
570
+ tx: this.#txHash,
571
+ txv: this.#txValidity,
572
+ to: this.#incomingAddress,
573
+ am: this.#amount,
574
+ in: this.#incomingNonce,
575
+ is: this.#incomingSignature,
576
+ va: validatorAddress,
577
+ vn: nonce,
578
+ vs: signature
579
+ };
580
+ }
581
+ if (isBalanceInitialization(this.#operationType)) {
582
+ return {
583
+ tx,
584
+ txv: this.#txValidity,
585
+ ia: this.#incomingAddress,
586
+ am: this.#amount,
587
+ in: nonce,
588
+ is: signature
589
+ };
590
+ }
591
+
592
+ throw new Error(`No corresponding value type for operation: ${this.#operationType}`);
593
+ }
594
+
595
+ #encodePayloadJson(payload) {
596
+ const toHex = buffer => buffer.toString('hex');
597
+ const address = bufferToAddress(payload.address, this.#config.addressPrefix);
598
+ if (!address) {
599
+ throw new Error('Payload address is invalid.');
600
+ }
601
+
602
+ const body = payload[this.#payloadKey];
603
+ const base = { type: payload.type, address };
604
+
605
+ switch (this.#payloadKey) {
606
+ case 'rao':
607
+ return {
608
+ ...base,
609
+ rao: {
610
+ tx: toHex(body.tx),
611
+ txv: toHex(body.txv),
612
+ iw: toHex(body.iw),
613
+ in: toHex(body.in),
614
+ is: toHex(body.is)
615
+ }
616
+ };
617
+ case 'txo':
618
+ return {
619
+ ...base,
620
+ txo: {
621
+ tx: toHex(body.tx),
622
+ txv: toHex(body.txv),
623
+ iw: toHex(body.iw),
624
+ ch: toHex(body.ch),
625
+ bs: toHex(body.bs),
626
+ mbs: toHex(body.mbs),
627
+ in: toHex(body.in),
628
+ is: toHex(body.is)
629
+ }
630
+ };
631
+ case 'bdo':
632
+ return {
633
+ ...base,
634
+ bdo: {
635
+ tx: toHex(body.tx),
636
+ txv: toHex(body.txv),
637
+ bs: toHex(body.bs),
638
+ ic: toHex(body.ic),
639
+ in: toHex(body.in),
640
+ is: toHex(body.is)
641
+ }
642
+ };
643
+ case 'tro':
644
+ return {
645
+ ...base,
646
+ tro: {
647
+ tx: toHex(body.tx),
648
+ txv: toHex(body.txv),
649
+ to: bufferToAddress(body.to, this.#config.addressPrefix),
650
+ am: toHex(body.am),
651
+ in: toHex(body.in),
652
+ is: toHex(body.is)
653
+ }
654
+ };
655
+ default:
656
+ throw new Error(`JSON output is not supported for payload ${this.#payloadKey}.`);
657
+ }
658
+ }
659
+ }
660
+
661
+ export default ApplyStateMessageBuilder;