trac-msb 0.2.9 → 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 (59) 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 +4 -21
  9. package/package.json +8 -9
  10. package/rpc/handlers.js +163 -90
  11. package/rpc/routes/v1.js +3 -1
  12. package/rpc/rpc_server.js +3 -3
  13. package/rpc/rpc_services.js +25 -29
  14. package/rpc/utils/helpers.js +82 -51
  15. package/src/config/args.js +46 -0
  16. package/src/config/config.js +78 -5
  17. package/src/config/env.js +69 -4
  18. package/src/core/network/Network.js +6 -10
  19. package/src/core/network/protocols/NetworkMessages.js +1 -1
  20. package/src/core/network/protocols/legacy/NetworkMessageRouter.js +1 -1
  21. package/src/core/network/protocols/legacy/validators/base/BaseResponse.js +1 -1
  22. package/src/core/network/protocols/shared/handlers/RoleOperationHandler.js +2 -2
  23. package/src/core/network/protocols/shared/handlers/SubnetworkOperationHandler.js +1 -1
  24. package/src/core/network/protocols/shared/handlers/TransferOperationHandler.js +1 -1
  25. package/src/core/network/protocols/shared/handlers/base/BaseOperationHandler.js +5 -6
  26. package/src/core/network/services/ConnectionManager.js +1 -1
  27. package/src/core/network/services/MessageOrchestrator.js +1 -1
  28. package/src/core/network/services/TransactionPoolService.js +4 -4
  29. package/src/core/network/services/TransactionRateLimiterService.js +8 -11
  30. package/src/core/network/services/ValidatorObserverService.js +5 -6
  31. package/src/core/state/State.js +2 -3
  32. package/src/index.js +3 -1
  33. package/src/messages/network/v1/NetworkMessageBuilder.js +2 -2
  34. package/src/messages/state/ApplyStateMessageBuilder.js +1 -1
  35. package/src/utils/check.js +1 -1
  36. package/src/utils/constants.js +0 -17
  37. package/src/utils/fileUtils.js +13 -0
  38. package/src/utils/type.js +26 -0
  39. package/tests/acceptance/v1/balance/balance.test.mjs +1 -2
  40. package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +26 -30
  41. package/tests/acceptance/v1/health/health.test.mjs +33 -0
  42. package/tests/acceptance/v1/rpc.test.mjs +3 -2
  43. package/tests/acceptance/v1/tx/tx.test.mjs +27 -16
  44. package/tests/acceptance/v1/tx-details/tx-details.test.mjs +26 -12
  45. package/tests/fixtures/check.fixtures.js +33 -32
  46. package/tests/fixtures/networkV1.fixtures.js +3 -2
  47. package/tests/fixtures/protobuf.fixtures.js +33 -32
  48. package/tests/helpers/StateNetworkFactory.js +2 -2
  49. package/tests/helpers/address.js +6 -0
  50. package/tests/helpers/autobaseTestHelpers.js +2 -1
  51. package/tests/helpers/config.js +2 -1
  52. package/tests/helpers/setupApplyTests.js +6 -10
  53. package/tests/unit/messages/network/NetworkMessageBuilder.test.js +3 -3
  54. package/tests/unit/messages/network/NetworkMessageDirector.test.js +3 -5
  55. package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +4 -3
  56. package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +3 -2
  57. package/tests/unit/utils/migrationUtils/validateAddressFromIncomingFile.test.js +3 -2
  58. package/tests/unit/utils/type/type.test.js +25 -0
  59. package/tests/unit/utils/utils.test.js +1 -0
@@ -1,74 +1,105 @@
1
1
  import b4a from "b4a"
2
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,5 +1,6 @@
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',
@@ -7,9 +8,45 @@ export const ENV = {
7
8
  TESTNET1: 'testnet1'
8
9
  }
9
10
  // TODO: CREATE TEST ENV CONFIG SIMILAR TO MAINNET AND USE IT IN TESTS.
10
- // TODO: CREATE TESTNET1 ENV CONFIG and update npm scripts to run node witn mainnet or testnet1.
11
11
 
12
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
+ },
13
50
  [ENV.MAINNET]: {
14
51
  addressLength: 63,
15
52
  addressPrefix: TRAC_NETWORK_MSB_MAINNET_PREFIX,
@@ -30,8 +67,22 @@ const configData = {
30
67
  messageThreshold: 3,
31
68
  messageValidatorRetryDelay: 1000, //How long to wait before retrying (ms) MESSAGE_VALIDATOR_RETRY_DELAY_MS
32
69
  messageValidatorResponseTimeout: 3 * 3 * 1000, //Overall timeout for sending a message (ms). This is 3 * maxRetries * messageValidatorRetryDelay;
33
- 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
34
84
  storesDirectory: 'stores/',
85
+ storeName: 'mainnet',
35
86
  },
36
87
  [ENV.DEVELOPMENT]: {
37
88
  addressLength: 63,
@@ -53,8 +104,22 @@ const configData = {
53
104
  messageThreshold: 1000,
54
105
  messageValidatorRetryDelay: 1000, //How long to wait before retrying (ms) MESSAGE_VALIDATOR_RETRY_DELAY_MS
55
106
  messageValidatorResponseTimeout: 3 * 3 * 1000, //Overall timeout for sending a message (ms). This is 3 * maxRetries * messageValidatorRetryDelay;
56
- 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
57
121
  storesDirectory : 'stores/',
122
+ storeName: 'development',
58
123
  }
59
124
  }
60
125
 
@@ -8,10 +8,6 @@ import NetworkMessages from './protocols/NetworkMessages.js';
8
8
  import { sleep } from '../../utils/helpers.js';
9
9
  import {
10
10
  TRAC_NAMESPACE,
11
- MAX_PEERS,
12
- MAX_PARALLEL,
13
- MAX_SERVER_CONNECTIONS,
14
- MAX_CLIENT_CONNECTIONS,
15
11
  NETWORK_MESSAGE_TYPES
16
12
  } from '../../utils/constants.js';
17
13
  import ConnectionManager from './services/ConnectionManager.js';
@@ -47,7 +43,7 @@ class Network extends ReadyResource {
47
43
 
48
44
  /**
49
45
  * @param {State} state
50
- * @param {object} config
46
+ * @param {Config} config
51
47
  * @param {string} address
52
48
  **/
53
49
  constructor(state, config, address = null) {
@@ -154,13 +150,13 @@ class Network extends ReadyResource {
154
150
  this.#swarm = new Hyperswarm({
155
151
  keyPair,
156
152
  bootstrap: this.#config.dhtBootstrap,
157
- maxPeers: MAX_PEERS,
158
- maxParallel: MAX_PARALLEL,
159
- maxServerConnections: MAX_SERVER_CONNECTIONS,
160
- maxClientConnections: MAX_CLIENT_CONNECTIONS
153
+ maxPeers: this.#config.maxPeers,
154
+ maxParallel: this.#config.maxParallel,
155
+ maxServerConnections: this.#config.maxServerConnections,
156
+ maxClientConnections: this.#config.maxClientConnections
161
157
  });
162
158
 
163
- this.#rateLimiter = new TransactionRateLimiterService(this.#swarm);
159
+ this.#rateLimiter = new TransactionRateLimiterService(this.#swarm, this.#config);
164
160
  this.#networkMessages = new NetworkMessages(
165
161
  state,
166
162
  wrappedWallet,
@@ -11,7 +11,7 @@ class NetworkMessages {
11
11
  #config;
12
12
 
13
13
  /**
14
- * @param {object} config
14
+ * @param {Config} config
15
15
  **/
16
16
  constructor(state, wallet, rateLimiterService, txPoolService, connectionManager, config) {
17
17
  this.#config = config;
@@ -19,7 +19,7 @@ class NetworkMessageRouter {
19
19
  * @param {TransactionRateLimiterService} rateLimiterService
20
20
  * @param {TransactionPoolService} txPoolService
21
21
  * @param {ConnectionManager} connectionManager
22
- * @param {object} config
22
+ * @param {Config} config
23
23
  **/
24
24
  constructor(state, wallet, rateLimiterService, txPoolService, connectionManager, config) {
25
25
  this.#config = config;
@@ -15,7 +15,7 @@ class BaseResponse {
15
15
  *
16
16
  * @param {State} state
17
17
  * @param {PeerWallet} wallet
18
- * @param {object} config
18
+ * @param {Config} config
19
19
  */
20
20
  constructor(state, wallet, config) {
21
21
  this.#state = state;
@@ -16,9 +16,9 @@ class RoleOperationHandler extends BaseOperationHandler {
16
16
  * @param {PeerWallet} wallet
17
17
  * @param {TransactionRateLimiterService} rateLimiter
18
18
  * @param {TransactionPoolService} txPoolService
19
- * @param {object} config
19
+ * @param {Config} config
20
20
  **/
21
- constructor(state, wallet, rateLimiter, txPoolService ,config) {
21
+ constructor(state, wallet, rateLimiter, txPoolService, config) {
22
22
  super(state, wallet, rateLimiter, txPoolService, config);
23
23
  this.#wallet = wallet;
24
24
  this.#config = config;
@@ -24,7 +24,7 @@ class SubnetworkOperationHandler extends BaseOperationHandler {
24
24
  * @param {PeerWallet} wallet
25
25
  * @param {TransactionRateLimiterService} rateLimiter
26
26
  * @param {TransactionPoolService} txPoolService
27
- * @param {object} config
27
+ * @param {Config} config
28
28
  **/
29
29
  constructor( state, wallet, rateLimiter, txPoolService, config) {
30
30
  super(state, wallet, rateLimiter, txPoolService, config);
@@ -15,7 +15,7 @@ class TransferOperationHandler extends BaseOperationHandler {
15
15
  * @param {State} state
16
16
  * @param {PeerWallet} wallet
17
17
  * @param {TransactionRateLimiterService} rateLimiter
18
- * @param {object} config
18
+ * @param {Config} config
19
19
  **/
20
20
  constructor(state, wallet, rateLimiter, txPoolService, config) {
21
21
  super(state, wallet, rateLimiter, txPoolService, config);
@@ -1,5 +1,4 @@
1
1
  import b4a from 'b4a';
2
- import {MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE, TRANSACTION_POOL_SIZE} from '../../../../../../utils/constants.js';
3
2
 
4
3
  class BaseOperationHandler {
5
4
  #state;
@@ -13,7 +12,7 @@ class BaseOperationHandler {
13
12
  * @param {PeerWallet} wallet
14
13
  * @param {TransactionRateLimiterService} rateLimiter
15
14
  * @param {TransactionPoolService} txPoolService
16
- * @param {object} config
15
+ * @param {Config} config
17
16
  **/
18
17
  constructor(state, wallet, rateLimiter, txPoolService, config) {
19
18
  if (new.target === BaseOperationHandler) {
@@ -30,7 +29,7 @@ class BaseOperationHandler {
30
29
  // Validate if operation can be processed:
31
30
  // - Non-writable nodes cannot process operations
32
31
  // - Regular indexers cannot process operations
33
- // - Admin-indexer can process operations only when network has less than MAX_WRITERS_FOR_ADMIN_INDEXER_CONNECTION writers
32
+ // - Admin-indexer can process operations only when network has less than maxWritersForAdminIndexerConnection writers
34
33
  const isAllowedToValidate = await this.#state.allowedToValidate(this.#wallet.address);
35
34
  const isAdminAllowedToValidate = await this.#state.isAdminAllowedToValidate();
36
35
  const canValidate = isAllowedToValidate || isAdminAllowedToValidate;
@@ -38,12 +37,12 @@ class BaseOperationHandler {
38
37
  throw new Error('OperationHandler: State is not writable or is an indexer without admin privileges.');
39
38
  }
40
39
 
41
- if (this.#txPoolService.tx_pool.length >= TRANSACTION_POOL_SIZE) {
40
+ if (this.#txPoolService.tx_pool.length >= this.#config.transactionPoolSize) {
42
41
  throw new Error("OperationHandler: Transaction pool is full, ignoring incoming transaction.");
43
42
  }
44
43
 
45
- if (b4a.byteLength(JSON.stringify(payload)) > MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE) {
46
- throw new Error(`OperationHandler: Payload size exceeds maximum limit of ${MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE} bytes by ${b4a.byteLength(JSON.stringify(payload)) - MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE} bytes.`);
44
+ if (b4a.byteLength(JSON.stringify(payload)) > this.#config.maxPartialTxPayloadByteSize) {
45
+ throw new Error(`OperationHandler: Payload size exceeds maximum limit of ${this.#config.maxPartialTxPayloadByteSize} bytes by ${b4a.byteLength(JSON.stringify(payload)) - this.#config.maxPartialTxPayloadByteSize} bytes.`);
47
46
  }
48
47
 
49
48
  if (!this.#config.disableRateLimit) {
@@ -20,7 +20,7 @@ class ConnectionManager {
20
20
  // As Buffers are objects, we will rely on internal conversions done by JS to compare them.
21
21
  // It would be better to handle these conversions manually by using hex strings as keys to avoid issues
22
22
  /**
23
- * @param {object} config
23
+ * @param {Config} config
24
24
  **/
25
25
  constructor(config) {
26
26
  this.#validators = new Map();
@@ -10,7 +10,7 @@ class MessageOrchestrator {
10
10
  * Attempts to send a message to validators with retries and state checks.
11
11
  * @param {ConnectionManager} connectionManager - The connection manager instance
12
12
  * @param {object} state - The state to look for the message outcome
13
- * @param {object} config - Configuration options:
13
+ * @param {Config} config - Configuration options:
14
14
  */
15
15
  constructor(connectionManager, state, config) {
16
16
  this.connectionManager = connectionManager;
@@ -1,5 +1,5 @@
1
1
  // PoolService.js
2
- import { BATCH_SIZE, PROCESS_INTERVAL_MS } from '../../../utils/constants.js';
2
+ import { BATCH_SIZE } from '../../../utils/constants.js';
3
3
  import Scheduler from '../../../utils/Scheduler.js';
4
4
 
5
5
  class TransactionPoolService {
@@ -12,7 +12,7 @@ class TransactionPoolService {
12
12
  /**
13
13
  * @param {State} state
14
14
  * @param {string} address
15
- * @param {object} config
15
+ * @param {Config} config
16
16
  **/
17
17
  constructor(state, address, config) {
18
18
  this.#state = state;
@@ -52,7 +52,7 @@ class TransactionPoolService {
52
52
  if (this.#tx_pool.length > 0) {
53
53
  next(0);
54
54
  } else {
55
- next(PROCESS_INTERVAL_MS);
55
+ next(this.#config.processIntervalMs);
56
56
  }
57
57
  } catch (error) {
58
58
  throw new Error(`TransactionPoolService worker error: ${error.message}`);
@@ -60,7 +60,7 @@ class TransactionPoolService {
60
60
  }
61
61
 
62
62
  #createScheduler() {
63
- return new Scheduler((next) => this.#worker(next), PROCESS_INTERVAL_MS);
63
+ return new Scheduler((next) => this.#worker(next), this.#config.processIntervalMs);
64
64
  }
65
65
 
66
66
  async #processTransactions() {