trac-msb 0.2.8 → 0.2.10

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 (151) hide show
  1. package/.github/workflows/acceptance-tests.yml +7 -11
  2. package/.github/workflows/lint-pr-title.yml +26 -0
  3. package/.github/workflows/unit-tests.yml +2 -8
  4. package/CODE_OF_CONDUCT.md +128 -0
  5. package/README.md +33 -18
  6. package/docker-compose.yml +1 -0
  7. package/docs/trac_network_http_api.openapi.yaml +889 -0
  8. package/msb.mjs +5 -22
  9. package/package.json +14 -10
  10. package/proto/network.proto +74 -0
  11. package/rpc/create_server.js +2 -2
  12. package/rpc/handlers.js +165 -92
  13. package/rpc/routes/v1.js +3 -1
  14. package/rpc/rpc_server.js +4 -4
  15. package/rpc/rpc_services.js +62 -25
  16. package/rpc/utils/helpers.js +83 -52
  17. package/src/config/args.js +46 -0
  18. package/src/config/config.js +78 -5
  19. package/src/config/env.js +70 -3
  20. package/src/core/network/Network.js +34 -70
  21. package/src/core/network/identity/NetworkWalletFactory.js +2 -2
  22. package/src/core/network/protocols/LegacyProtocol.js +67 -0
  23. package/src/core/network/protocols/NetworkMessages.js +48 -0
  24. package/src/core/network/protocols/ProtocolInterface.js +31 -0
  25. package/src/core/network/protocols/ProtocolSession.js +59 -0
  26. package/src/core/network/protocols/V1Protocol.js +64 -0
  27. package/src/core/network/protocols/legacy/NetworkMessageRouter.js +84 -0
  28. package/src/core/network/protocols/legacy/handlers/GetRequestHandler.js +53 -0
  29. package/src/core/network/protocols/legacy/handlers/ResponseHandler.js +37 -0
  30. package/src/core/network/{messaging → protocols/legacy}/validators/base/BaseResponse.js +2 -3
  31. package/src/core/network/protocols/shared/handlers/RoleOperationHandler.js +88 -0
  32. package/src/core/network/protocols/shared/handlers/SubnetworkOperationHandler.js +93 -0
  33. package/src/core/network/{messaging → protocols/shared}/handlers/TransferOperationHandler.js +17 -16
  34. package/src/core/network/{messaging → protocols/shared}/handlers/base/BaseOperationHandler.js +10 -15
  35. package/src/core/network/{messaging → protocols/shared}/validators/PartialBootstrapDeployment.js +2 -2
  36. package/src/core/network/{messaging → protocols/shared}/validators/PartialRoleAccess.js +5 -5
  37. package/src/core/network/{messaging → protocols/shared}/validators/PartialTransaction.js +4 -4
  38. package/src/core/network/{messaging → protocols/shared}/validators/PartialTransfer.js +4 -4
  39. package/src/core/network/{messaging → protocols/shared}/validators/base/PartialOperation.js +14 -12
  40. package/src/core/network/protocols/v1/NetworkMessageRouter.js +15 -0
  41. package/src/core/network/services/ConnectionManager.js +5 -5
  42. package/src/core/network/services/MessageOrchestrator.js +2 -2
  43. package/src/core/network/services/TransactionPoolService.js +5 -6
  44. package/src/core/network/services/TransactionRateLimiterService.js +12 -13
  45. package/src/core/network/services/ValidatorObserverService.js +5 -6
  46. package/src/core/state/State.js +3 -5
  47. package/src/index.js +156 -181
  48. package/src/messages/network/v1/NetworkMessageBuilder.js +325 -0
  49. package/src/messages/network/v1/NetworkMessageDirector.js +137 -0
  50. package/src/messages/network/v1/networkMessageFactory.js +12 -0
  51. package/src/messages/state/ApplyStateMessageBuilder.js +661 -0
  52. package/src/messages/state/ApplyStateMessageDirector.js +516 -0
  53. package/src/messages/state/applyStateMessageFactory.js +12 -0
  54. package/src/utils/buffer.js +53 -1
  55. package/src/utils/check.js +1 -1
  56. package/src/utils/cli.js +0 -8
  57. package/src/utils/constants.js +33 -30
  58. package/src/utils/fileUtils.js +13 -0
  59. package/src/utils/normalizers.js +84 -2
  60. package/src/utils/protobuf/network.cjs +840 -0
  61. package/src/utils/protobuf/operationHelpers.js +10 -0
  62. package/src/utils/type.js +26 -0
  63. package/tests/acceptance/v1/balance/balance.test.mjs +1 -2
  64. package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +26 -30
  65. package/tests/acceptance/v1/health/health.test.mjs +33 -0
  66. package/tests/acceptance/v1/rpc.test.mjs +4 -3
  67. package/tests/acceptance/v1/tx/tx.test.mjs +27 -16
  68. package/tests/acceptance/v1/tx-details/tx-details.test.mjs +26 -12
  69. package/tests/fixtures/check.fixtures.js +33 -32
  70. package/tests/fixtures/networkV1.fixtures.js +85 -0
  71. package/tests/fixtures/protobuf.fixtures.js +109 -25
  72. package/tests/helpers/StateNetworkFactory.js +2 -2
  73. package/tests/helpers/address.js +6 -0
  74. package/tests/helpers/autobaseTestHelpers.js +2 -1
  75. package/tests/helpers/config.js +2 -1
  76. package/tests/helpers/setupApplyTests.js +59 -56
  77. package/tests/unit/messages/messages.test.js +12 -0
  78. package/tests/unit/messages/network/NetworkMessageBuilder.test.js +276 -0
  79. package/tests/unit/messages/network/NetworkMessageDirector.test.js +201 -0
  80. package/tests/unit/messages/state/applyStateMessageBuilder.complete.test.js +521 -0
  81. package/tests/unit/messages/state/applyStateMessageBuilder.partial.test.js +233 -0
  82. package/tests/unit/network/ConnectionManager.test.js +6 -5
  83. package/tests/unit/network/networkModule.test.js +3 -2
  84. package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +10 -6
  85. package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +9 -6
  86. package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +10 -7
  87. package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +18 -21
  88. package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +53 -38
  89. package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +46 -35
  90. package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +13 -16
  91. package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +17 -11
  92. package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +11 -12
  93. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +9 -7
  94. package/tests/unit/state/apply/common/commonScenarioHelper.js +15 -14
  95. package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +9 -4
  96. package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +17 -11
  97. package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +19 -14
  98. package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +37 -29
  99. package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +9 -7
  100. package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +11 -9
  101. package/tests/unit/unit.test.js +1 -1
  102. package/tests/unit/utils/buffer/buffer.test.js +62 -1
  103. package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +4 -3
  104. package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +3 -2
  105. package/tests/unit/utils/migrationUtils/validateAddressFromIncomingFile.test.js +3 -2
  106. package/tests/unit/utils/normalizers/normalizers.test.js +469 -0
  107. package/tests/unit/utils/protobuf/operationHelpers.test.js +120 -2
  108. package/tests/unit/utils/type/type.test.js +25 -0
  109. package/tests/unit/utils/utils.test.js +1 -0
  110. package/docs/networking-dualstack-plan.md +0 -75
  111. package/docs/networking-layer-redesign.md +0 -155
  112. package/src/core/network/messaging/NetworkMessages.js +0 -64
  113. package/src/core/network/messaging/handlers/GetRequestHandler.js +0 -113
  114. package/src/core/network/messaging/handlers/ResponseHandler.js +0 -107
  115. package/src/core/network/messaging/handlers/RoleOperationHandler.js +0 -114
  116. package/src/core/network/messaging/handlers/SubnetworkOperationHandler.js +0 -149
  117. package/src/core/network/messaging/routes/NetworkMessageRouter.js +0 -98
  118. package/src/core/network/messaging/validators/AdminResponse.js +0 -58
  119. package/src/core/network/messaging/validators/CustomNodeResponse.js +0 -46
  120. package/src/messages/base/StateBuilder.js +0 -25
  121. package/src/messages/completeStateMessages/CompleteStateMessageBuilder.js +0 -425
  122. package/src/messages/completeStateMessages/CompleteStateMessageDirector.js +0 -252
  123. package/src/messages/completeStateMessages/CompleteStateMessageOperations.js +0 -296
  124. package/src/messages/partialStateMessages/PartialStateMessageBuilder.js +0 -272
  125. package/src/messages/partialStateMessages/PartialStateMessageDirector.js +0 -137
  126. package/src/messages/partialStateMessages/PartialStateMessageOperations.js +0 -138
  127. package/tests/integration/apply/addAdmin/addAdminBasic.test.js +0 -69
  128. package/tests/integration/apply/addAdmin/addAdminRecovery.test.js +0 -126
  129. package/tests/integration/apply/addIndexer.test.js +0 -239
  130. package/tests/integration/apply/addWhitelist.test.js +0 -53
  131. package/tests/integration/apply/addWriter.test.js +0 -245
  132. package/tests/integration/apply/apply.test.js +0 -19
  133. package/tests/integration/apply/banValidator.test.js +0 -116
  134. package/tests/integration/apply/postTx/invalidSubValues.test.js +0 -103
  135. package/tests/integration/apply/postTx/postTx.test.js +0 -196
  136. package/tests/integration/apply/removeIndexer.test.js +0 -132
  137. package/tests/integration/apply/removeWriter.test.js +0 -168
  138. package/tests/integration/apply/transfer.test.js +0 -83
  139. package/tests/integration/integration.test.js +0 -9
  140. package/tests/unit/messageOperations/assembleAddIndexerMessage.test.js +0 -21
  141. package/tests/unit/messageOperations/assembleAddWriterMessage.test.js +0 -17
  142. package/tests/unit/messageOperations/assembleAdminMessage.test.js +0 -68
  143. package/tests/unit/messageOperations/assembleBanWriterMessage.test.js +0 -17
  144. package/tests/unit/messageOperations/assemblePostTransaction.test.js +0 -424
  145. package/tests/unit/messageOperations/assembleRemoveIndexerMessage.test.js +0 -19
  146. package/tests/unit/messageOperations/assembleRemoveWriterMessage.test.js +0 -17
  147. package/tests/unit/messageOperations/assembleWhitelistMessages.test.js +0 -59
  148. package/tests/unit/messageOperations/commonsStateMessageOperationsTest.js +0 -278
  149. package/tests/unit/messageOperations/stateMessageOperations.test.js +0 -19
  150. /package/src/core/network/{messaging → protocols/legacy}/validators/ValidatorResponse.js +0 -0
  151. /package/src/utils/{operations.js → applyOperations.js} +0 -0
@@ -1,6 +1,15 @@
1
1
  import { bufferToBigInt } from "../src/utils/amountSerialization.js";
2
- import { normalizeDecodedPayloadForJson } from "../src/utils/normalizers.js";
2
+ import {
3
+ normalizeDecodedPayloadForJson,
4
+ normalizeTransactionOperation,
5
+ normalizeTransferOperation
6
+ } from "../src/utils/normalizers.js";
3
7
  import { get_confirmed_tx_info, get_unconfirmed_tx_info } from "../src/utils/cli.js";
8
+ import { OperationType } from "../src/utils/constants.js";
9
+ import b4a from "b4a";
10
+ import PartialTransaction from "../src/core/network/protocols/shared/validators/PartialTransaction.js";
11
+ import PartialTransfer from "../src/core/network/protocols/shared/validators/PartialTransfer.js";
12
+ import { ValidationError, BroadcastError, NotFoundError } from "./utils/helpers.js";
4
13
 
5
14
  export async function getBalance(msbInstance, address, confirmed) {
6
15
  const state = msbInstance.state;
@@ -36,8 +45,47 @@ export async function getUnconfirmedLength(msbInstance) {
36
45
  return msbInstance.state.getUnsignedLength();
37
46
  }
38
47
 
39
- export async function broadcastTransaction(msbInstance, payload) {
40
- return msbInstance.broadcastTransactionCommand(payload);
48
+ export async function broadcastTransaction(msbInstance, config, payload) {
49
+ if (!payload) {
50
+ throw new ValidationError("Transaction payload is required for broadcasting.");
51
+ }
52
+
53
+ let normalizedPayload;
54
+ let isValid = false;
55
+ let hash;
56
+
57
+ const partialTransferValidator = new PartialTransfer(msbInstance.state, null, config);
58
+ const partialTransactionValidator = new PartialTransaction(msbInstance.state, null, config);
59
+
60
+ if (payload.type === OperationType.TRANSFER) {
61
+ normalizedPayload = normalizeTransferOperation(payload, config);
62
+ isValid = await partialTransferValidator.validate(normalizedPayload);
63
+ hash = b4a.toString(normalizedPayload.tro.tx, "hex");
64
+ } else if (payload.type === OperationType.TX) {
65
+ normalizedPayload = normalizeTransactionOperation(payload, config);
66
+ isValid = await partialTransactionValidator.validate(normalizedPayload);
67
+ hash = b4a.toString(normalizedPayload.txo.tx, "hex");
68
+ }
69
+
70
+ if (!isValid) {
71
+ throw new ValidationError("Invalid transaction payload.");
72
+ }
73
+
74
+ const success = await msbInstance.broadcastPartialTransaction(payload);
75
+
76
+ if (!success) {
77
+ throw new BroadcastError("Failed to broadcast transaction after multiple attempts.");
78
+ }
79
+
80
+ const signedLength = msbInstance.state.getSignedLength();
81
+ const unsignedLength = msbInstance.state.getUnsignedLength();
82
+
83
+ return {
84
+ message: "Transaction broadcasted successfully.",
85
+ signedLength,
86
+ unsignedLength,
87
+ tx: hash
88
+ };
41
89
  }
42
90
 
43
91
  export async function getTxHashes(msbInstance, start, end) {
@@ -48,7 +96,7 @@ export async function getTxHashes(msbInstance, start, end) {
48
96
  export async function getTxDetails(msbInstance, hash) {
49
97
  const rawPayload = await get_confirmed_tx_info(msbInstance.state, hash);
50
98
  if (!rawPayload) {
51
- return null;
99
+ throw new NotFoundError(`Transaction ${hash} not found.`);
52
100
  }
53
101
 
54
102
  return normalizeDecodedPayloadForJson(rawPayload.decoded, msbInstance.config);
@@ -56,11 +104,11 @@ export async function getTxDetails(msbInstance, hash) {
56
104
 
57
105
  export async function fetchBulkTxPayloads(msbInstance, hashes) {
58
106
  if (!Array.isArray(hashes) || hashes.length === 0) {
59
- throw new Error("Missing hash list.");
107
+ throw new ValidationError("Missing hash list.");
60
108
  }
61
109
 
62
110
  if (hashes.length > 1500) {
63
- throw new Error("Length of input tx hashes exceeded.");
111
+ throw new ValidationError("Length of input tx hashes exceeded.");
64
112
  }
65
113
 
66
114
  const res = { results: [], missing: [] };
@@ -70,7 +118,7 @@ export async function fetchBulkTxPayloads(msbInstance, hashes) {
70
118
 
71
119
  results.forEach((result, index) => {
72
120
  const hash = hashes[index];
73
- if (result === null || result === undefined) {
121
+ if (!result) {
74
122
  res.missing.push(hash);
75
123
  } else {
76
124
  const decodedResult = normalizeDecodedPayloadForJson(result.decoded, msbInstance.config);
@@ -83,32 +131,21 @@ export async function fetchBulkTxPayloads(msbInstance, hashes) {
83
131
 
84
132
  export async function getExtendedTxDetails(msbInstance, hash, confirmed) {
85
133
  const state = msbInstance.state;
134
+ let rawPayload;
86
135
 
87
136
  if (confirmed) {
88
- const rawPayload = await get_confirmed_tx_info(state, hash);
89
- if (!rawPayload) {
90
- throw new Error(`No payload found for tx hash: ${hash}`);
91
- }
92
- const confirmedLength = await state.getTransactionConfirmedLength(hash);
93
- if (confirmedLength === null) {
94
- throw new Error(`No confirmed length found for tx hash: ${hash} in confirmed mode`);
95
- }
96
- const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded, msbInstance.config);
97
- const feeBuffer = state.getFee();
98
- return {
99
- txDetails: normalizedPayload,
100
- confirmed_length: confirmedLength,
101
- fee: bufferToBigInt(feeBuffer).toString(),
102
- };
137
+ rawPayload = await get_confirmed_tx_info(state, hash);
138
+ } else {
139
+ rawPayload = await get_unconfirmed_tx_info(state, hash);
103
140
  }
104
141
 
105
- const rawPayload = await get_unconfirmed_tx_info(state, hash);
106
142
  if (!rawPayload) {
107
- throw new Error(`No payload found for tx hash: ${hash}`);
143
+ throw new NotFoundError(`No payload found for tx hash: ${hash}`);
108
144
  }
109
145
 
110
146
  const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded, msbInstance.config);
111
147
  const length = await state.getTransactionConfirmedLength(hash);
148
+
112
149
  if (length === null) {
113
150
  return {
114
151
  txDetails: normalizedPayload,
@@ -123,4 +160,4 @@ export async function getExtendedTxDetails(msbInstance, hash, confirmed) {
123
160
  confirmed_length: length,
124
161
  fee: bufferToBigInt(feeBuffer).toString(),
125
162
  };
126
- }
163
+ }
@@ -1,74 +1,105 @@
1
1
  import b4a from "b4a"
2
- import { operationToPayload } from "../../src/utils/operations.js"
2
+ import { operationToPayload } from "../../src/utils/applyOperations.js"
3
+ import { isHexString } from "../../src/utils/helpers.js";
4
+
5
+ export class ValidationError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = "ValidationError";
9
+ }
10
+ }
11
+
12
+ export class BroadcastError extends Error {
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = "BroadcastError";
16
+ }
17
+ }
18
+
19
+ export class NotFoundError extends Error {
20
+ constructor(message) {
21
+ super(message);
22
+ this.name = "NotFoundError";
23
+ }
24
+ }
25
+
3
26
  export function decodeBase64Payload(base64) {
4
- let decodedPayloadString
5
- try {
6
- decodedPayloadString = b4a.from(base64, "base64").toString("utf-8")
7
- } catch (err) {
8
- throw new Error("Failed to decode base64 payload.")
9
- }
10
-
11
- try {
12
- return JSON.parse(decodedPayloadString)
13
- } catch (err) {
14
- throw new Error("Decoded payload is not valid JSON.")
15
- }
27
+ let decodedPayloadString
28
+ try {
29
+ decodedPayloadString = b4a.from(base64, "base64").toString("utf-8")
30
+ } catch (err) {
31
+ throw new ValidationError("Failed to decode base64 payload.")
32
+ }
33
+
34
+ try {
35
+ return JSON.parse(decodedPayloadString)
36
+ } catch (err) {
37
+ throw new ValidationError("Decoded payload is not valid JSON.")
38
+ }
16
39
  }
17
40
 
18
41
  export function isBase64(str) {
19
- const base64Regex =
20
- /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/
21
- return base64Regex.test(str)
42
+ const base64Regex =
43
+ /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/
44
+ return base64Regex.test(str)
22
45
  }
23
46
 
24
47
  export function validatePayloadStructure(payload) {
25
- if (
26
- typeof payload !== "object" ||
27
- payload === null ||
28
- typeof payload.type !== "number" ||
29
- typeof payload.address !== "string" ||
30
- !["txo", "tro"].some((key) => key in payload && typeof payload[key] === "object")
31
- ) {
32
- throw new Error("Invalid payload structure.")
33
- }
48
+ if (
49
+ typeof payload !== "object" ||
50
+ payload === null ||
51
+ typeof payload.type !== "number" ||
52
+ typeof payload.address !== "string" ||
53
+ !["txo", "tro"].some((key) => key in payload && typeof payload[key] === "object")
54
+ ) {
55
+ throw new ValidationError("Invalid payload structure.")
56
+ }
34
57
  }
35
58
 
36
59
  export function sanitizeTransferPayload(payload) {
37
- const operationKey = operationToPayload(payload.type);
60
+ const operationKey = operationToPayload(payload.type);
38
61
 
39
- if (operationKey !== 'tro' && operationKey !== 'txo') {
40
- throw new Error('Payload is not a transfer/transaction operation.');
41
- }
62
+ if (operationKey !== 'tro' && operationKey !== 'txo') {
63
+ throw new ValidationError('Payload is not a transfer/transaction operation.');
64
+ }
42
65
 
43
- const operation = payload[operationKey];
44
- if (payload.address && typeof payload.address === "string") {
45
- payload.address = payload.address.trim()
46
- }
66
+ const operation = payload[operationKey];
67
+ if (payload.address && typeof payload.address === "string") {
68
+ payload.address = payload.address.trim()
69
+ }
47
70
 
48
- if (operation && typeof operation === "object") {
49
- for (const [key, value] of Object.entries(operation)) {
50
- if (typeof value === "string") {
51
- let sanitized = value.trim()
71
+ if (operation && typeof operation === "object") {
72
+ for (const [key, value] of Object.entries(operation)) {
73
+ if (typeof value === "string") {
74
+ let sanitized = value.trim()
52
75
 
53
- // normalize hex-like strings
54
- if (/^[0-9A-F]+$/i.test(sanitized)) {
55
- sanitized = sanitized.toLowerCase()
56
- }
76
+ // normalize hex-like strings
77
+ if (/^[0-9A-F]+$/i.test(sanitized)) {
78
+ sanitized = sanitized.toLowerCase()
79
+ }
57
80
 
58
- payload[operationKey][key] = sanitized
59
- }
60
- }
61
- }
81
+ payload[operationKey][key] = sanitized
82
+ }
83
+ }
84
+ }
62
85
 
63
- return payload
86
+ return payload
64
87
  }
65
88
 
66
89
  export function sanitizeBulkPayloadsRequestBody(body) {
67
- const cleanBody = body
68
- .replace(/^\uFEFF/, '')
69
- .replace(/\r/g, '')
70
- .replace(/\0/g, '')
71
- .trim();
90
+ const cleanBody = body
91
+ .replace(/^\uFEFF/, '')
92
+ .replace(/\r/g, '')
93
+ .replace(/\0/g, '')
94
+ .trim();
72
95
 
73
- return JSON.parse(cleanBody);
96
+ return JSON.parse(cleanBody);
74
97
  }
98
+
99
+ export function isValidTxHash(hash) {
100
+ return isHexString(hash) && hash?.length === 64;
101
+ }
102
+
103
+ export function hasSpacesInUrl(url) {
104
+ return url.includes('%20') || url.includes(' ');
105
+ }
@@ -0,0 +1,46 @@
1
+ import { createConfig, ENV } from './env.js';
2
+
3
+ const getArguments = () => {
4
+ const pearApp = typeof Pear !== 'undefined' ? (Pear.app ?? Pear.config) : undefined;
5
+ const runtimeArgs = typeof process !== 'undefined' ? process.argv.slice(2) : [];
6
+ return pearApp?.args ?? runtimeArgs;
7
+ };
8
+
9
+ export const resolveEnvironment = (args = []) => {
10
+ const networkIndex = args.indexOf('--network');
11
+ const network = (networkIndex !== -1 && args[networkIndex + 1]) ? args[networkIndex + 1] : undefined;
12
+
13
+ if (network === ENV.MAINNET) return ENV.MAINNET;
14
+ if (network === ENV.DEVELOPMENT) return ENV.DEVELOPMENT;
15
+ if (network === ENV.TESTNET1 || network === 'testnet') return ENV.TESTNET1;
16
+ return ENV.MAINNET;
17
+ };
18
+
19
+ export const isRpcEnabled = () => {
20
+ const args = getArguments();
21
+ return args.includes('--rpc');
22
+ };
23
+
24
+ export const resolveConfig = () => {
25
+ const args = getArguments();
26
+ const runRpc = isRpcEnabled();
27
+ const selectedEnv = resolveEnvironment(args);
28
+ const storesDirectoryIndex = args.indexOf('--stores-directory');
29
+ const storesDirectory = (storesDirectoryIndex !== -1 && args[storesDirectoryIndex + 1]) ? args[storesDirectoryIndex + 1] : undefined;
30
+ const hostIndex = args.indexOf('--host');
31
+ const host = (hostIndex !== -1 && args[hostIndex + 1]) ? args[hostIndex + 1] : undefined;
32
+ const portIndex = args.indexOf('--port');
33
+ const port = (portIndex !== -1 && args[portIndex + 1]) ? parseInt(args[portIndex + 1], 10) : undefined;
34
+
35
+ const rpc = {
36
+ storesDirectory,
37
+ enableWallet: false,
38
+ enableInteractiveMode: false,
39
+ host,
40
+ port
41
+ };
42
+
43
+ const options = runRpc ? rpc : { storesDirectory };
44
+
45
+ return createConfig(selectedEnv, options);
46
+ };
@@ -1,4 +1,6 @@
1
1
  import b4a from 'b4a'
2
+ import { isDefined } from '../utils/type.js'
3
+ import _ from 'lodash'
2
4
 
3
5
  export class Config {
4
6
  #options
@@ -80,7 +82,7 @@ export class Config {
80
82
  }
81
83
 
82
84
  get isAdminMode() {
83
- return this.#options.storeName === 'admin'
85
+ return _.endsWith(this.storesDirectory, '/admin')
84
86
  }
85
87
 
86
88
  get keyPairPath() {
@@ -97,17 +99,73 @@ export class Config {
97
99
  return this.#config.maxValidators
98
100
  }
99
101
 
102
+ get maxPeers() {
103
+ if (this.#isOverriden('maxPeers')) return this.#options.maxPeers
104
+ return this.#config.maxPeers
105
+ }
106
+
107
+ get maxParallel() {
108
+ if (this.#isOverriden('maxParallel')) return this.#options.maxParallel
109
+ return this.#config.maxParallel
110
+ }
111
+
112
+ get maxServerConnections() {
113
+ if (this.#isOverriden('maxServerConnections')) return this.#options.maxServerConnections
114
+ return this.#config.maxServerConnections
115
+ }
116
+
117
+ get maxClientConnections() {
118
+ if (this.#isOverriden('maxClientConnections')) return this.#options.maxClientConnections
119
+ return this.#config.maxClientConnections
120
+ }
121
+
122
+ get maxWritersForAdminIndexerConnection() {
123
+ if (this.#isOverriden('maxWritersForAdminIndexerConnection')) return this.#options.maxWritersForAdminIndexerConnection
124
+ return this.#config.maxWritersForAdminIndexerConnection
125
+ }
126
+
127
+ get processIntervalMs() {
128
+ if (this.#isOverriden('processIntervalMs')) return this.#options.processIntervalMs
129
+ return this.#config.processIntervalMs
130
+ }
131
+
132
+ get maxPartialTxPayloadByteSize() {
133
+ if (this.#isOverriden('maxPartialTxPayloadByteSize')) return this.#options.maxPartialTxPayloadByteSize
134
+ return this.#config.maxPartialTxPayloadByteSize
135
+ }
136
+
137
+ get transactionPoolSize() {
138
+ if (this.#isOverriden('transactionPoolSize')) return this.#options.transactionPoolSize
139
+ return this.#config.transactionPoolSize
140
+ }
141
+
100
142
  get networkId() {
101
143
  return this.#config.networkId
102
144
  }
103
145
 
146
+ get host() {
147
+ if (this.#isOverriden('host')) return this.#options.host
148
+ return this.#config.host
149
+ }
150
+
151
+ get port() {
152
+ if (this.#isOverriden('port')) return this.#options.port
153
+ return this.#config.port
154
+ }
155
+
104
156
  get storesDirectory() {
105
- if (this.#isOverriden('storesDirectory')) return this.#options.storesDirectory
106
- return this.#config.storesDirectory
157
+ const storesDirectory = this.#isOverriden('storesDirectory') ?
158
+ this.#options.storesDirectory : this.#config.storesDirectory
159
+
160
+ return _.trimEnd(storesDirectory, '/')
161
+ }
162
+
163
+ get storeName() {
164
+ return this.#config.storeName
107
165
  }
108
166
 
109
167
  get storesFullPath() {
110
- return `${this.storesDirectory}${this.#options.storeName}`
168
+ return `${this.storesDirectory}/${this.storeName}`
111
169
  }
112
170
 
113
171
  get messageThreshold() {
@@ -122,9 +180,24 @@ export class Config {
122
180
  return this.#config.messageValidatorResponseTimeout
123
181
  }
124
182
 
183
+ get rateLimitCleanupIntervalMs() {
184
+ if (this.#isOverriden('rateLimitCleanupIntervalMs')) return this.#options.rateLimitCleanupIntervalMs
185
+ return this.#config.rateLimitCleanupIntervalMs
186
+ }
187
+
188
+ get rateLimitConnectionTimeoutMs() {
189
+ if (this.#isOverriden('rateLimitConnectionTimeoutMs')) return this.#options.rateLimitConnectionTimeoutMs
190
+ return this.#config.rateLimitConnectionTimeoutMs
191
+ }
192
+
193
+ get rateLimitMaxTransactionsPerSecond() {
194
+ if (this.#isOverriden('rateLimitMaxTransactionsPerSecond')) return this.#options.rateLimitMaxTransactionsPerSecond
195
+ return this.#config.rateLimitMaxTransactionsPerSecond
196
+ }
197
+
125
198
  // Most of these properties are boolean
126
199
  #isOverriden(prop) {
127
- return this.#options.hasOwnProperty(prop)
200
+ return this.#options.hasOwnProperty(prop) && isDefined(this.#options[prop])
128
201
  }
129
202
 
130
203
  #validate(options, config) {
package/src/config/env.js CHANGED
@@ -1,13 +1,52 @@
1
- import { TRAC_NETWORK_MSB_MAINNET_PREFIX } from 'trac-wallet/constants.js';
1
+ import { TRAC_NETWORK_MSB_MAINNET_PREFIX, TRAC_NETWORK_MSB_TESTNET1_PREFIX } from 'trac-wallet/constants.js';
2
2
  import { Config } from './config.js';
3
+ import { TRAC_NETWORK_TESTNET_ID, TRAC_NETWORK_MAINNET_ID } from 'trac-crypto-api/constants.js';
3
4
 
4
5
  export const ENV = {
5
6
  MAINNET: 'mainnet',
6
7
  DEVELOPMENT: 'development',
7
8
  TESTNET1: 'testnet1'
8
9
  }
10
+ // TODO: CREATE TEST ENV CONFIG SIMILAR TO MAINNET AND USE IT IN TESTS.
9
11
 
10
12
  const configData = {
13
+ [ENV.TESTNET1]: {
14
+ addressLength: 67,
15
+ addressPrefix: TRAC_NETWORK_MSB_TESTNET1_PREFIX,
16
+ addressPrefixLength: TRAC_NETWORK_MSB_TESTNET1_PREFIX.length,
17
+ bech32mHrpLength: TRAC_NETWORK_MSB_TESTNET1_PREFIX.length + 1, // len(addressPrefix + separator)
18
+ bootstrap: 'a7c0c2cf8e4722129097f89b2a29a092f23d6268fcca3fd9570ba5b702b99b95',
19
+ channel: '1111trac1network1msb1testnet1111',
20
+ dhtBootstrap: ['116.202.214.149:10001', '157.180.12.214:10001', 'node1.hyperdht.org:49737', 'node2.hyperdht.org:49737', 'node3.hyperdht.org:49737'], // these are used to peer discovery
21
+ disableRateLimit: false,
22
+ enableErrorApplyLogs: true,
23
+ enableInteractiveMode: true,
24
+ enableRoleRequester: false,
25
+ enableTxApplyLogs: true,
26
+ enableValidatorObserver: true,
27
+ enableWallet: true,
28
+ maxValidators: 6,
29
+ maxRetries: 1,
30
+ messageThreshold: 1000,
31
+ messageValidatorRetryDelay: 1000, //How long to wait before retrying (ms) MESSAGE_VALIDATOR_RETRY_DELAY_MS
32
+ messageValidatorResponseTimeout: 3 * 3 * 1000, //Overall timeout for sending a message (ms). This is 3 * maxRetries * messageValidatorRetryDelay;
33
+ host: 'localhost',
34
+ port: 5000,
35
+ networkId: TRAC_NETWORK_TESTNET_ID,
36
+ maxPeers: 64, // Connectivity constants
37
+ maxParallel: 64, // Connectivity constants
38
+ maxServerConnections: Infinity, // Connectivity constants
39
+ maxClientConnections: Infinity, // Connectivity constants
40
+ maxWritersForAdminIndexerConnection: 10, // Connectivity constants
41
+ processIntervalMs: 50, // Pool constants
42
+ maxPartialTxPayloadByteSize: 3072, // Operation handler constants
43
+ transactionPoolSize: 1000, // Operation handler constants
44
+ rateLimitCleanupIntervalMs: 120_000, // Rate limiting constants
45
+ rateLimitConnectionTimeoutMs: 60_000, // Rate limiting constants
46
+ rateLimitMaxTransactionsPerSecond: 50, // Rate limiting constants
47
+ storesDirectory : 'stores/',
48
+ storeName: 'testnet',
49
+ },
11
50
  [ENV.MAINNET]: {
12
51
  addressLength: 63,
13
52
  addressPrefix: TRAC_NETWORK_MSB_MAINNET_PREFIX,
@@ -28,8 +67,22 @@ const configData = {
28
67
  messageThreshold: 3,
29
68
  messageValidatorRetryDelay: 1000, //How long to wait before retrying (ms) MESSAGE_VALIDATOR_RETRY_DELAY_MS
30
69
  messageValidatorResponseTimeout: 3 * 3 * 1000, //Overall timeout for sending a message (ms). This is 3 * maxRetries * messageValidatorRetryDelay;
31
- networkId: 918,
70
+ host: 'localhost',
71
+ port: 5000,
72
+ networkId: TRAC_NETWORK_MAINNET_ID,
73
+ maxPeers: 64, // Connectivity constants
74
+ maxParallel: 64, // Connectivity constants
75
+ maxServerConnections: Infinity, // Connectivity constants
76
+ maxClientConnections: Infinity, // Connectivity constants
77
+ maxWritersForAdminIndexerConnection: 10, // Connectivity constants
78
+ processIntervalMs: 50, // Pool constants
79
+ maxPartialTxPayloadByteSize: 3072, // Operation handler constants
80
+ transactionPoolSize: 1000, // Operation handler constants
81
+ rateLimitCleanupIntervalMs: 120_000, // Rate limiting constants
82
+ rateLimitConnectionTimeoutMs: 60_000, // Rate limiting constants
83
+ rateLimitMaxTransactionsPerSecond: 50, // Rate limiting constants
32
84
  storesDirectory: 'stores/',
85
+ storeName: 'mainnet',
33
86
  },
34
87
  [ENV.DEVELOPMENT]: {
35
88
  addressLength: 63,
@@ -51,8 +104,22 @@ const configData = {
51
104
  messageThreshold: 1000,
52
105
  messageValidatorRetryDelay: 1000, //How long to wait before retrying (ms) MESSAGE_VALIDATOR_RETRY_DELAY_MS
53
106
  messageValidatorResponseTimeout: 3 * 3 * 1000, //Overall timeout for sending a message (ms). This is 3 * maxRetries * messageValidatorRetryDelay;
54
- networkId: 918,
107
+ host: 'localhost',
108
+ port: 5000,
109
+ networkId: TRAC_NETWORK_TESTNET_ID,
110
+ maxPeers: 64, // Connectivity constants
111
+ maxParallel: 64, // Connectivity constants
112
+ maxServerConnections: Infinity, // Connectivity constants
113
+ maxClientConnections: Infinity, // Connectivity constants
114
+ maxWritersForAdminIndexerConnection: 10, // Connectivity constants
115
+ processIntervalMs: 50, // Pool constants
116
+ maxPartialTxPayloadByteSize: 3072, // Operation handler constants
117
+ transactionPoolSize: 1000, // Operation handler constants
118
+ rateLimitCleanupIntervalMs: 120_000, // Rate limiting constants
119
+ rateLimitConnectionTimeoutMs: 60_000, // Rate limiting constants
120
+ rateLimitMaxTransactionsPerSecond: 50, // Rate limiting constants
55
121
  storesDirectory : 'stores/',
122
+ storeName: 'development',
56
123
  }
57
124
  }
58
125