trac-msb 0.2.5 → 0.2.6

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.
package/msb.mjs CHANGED
@@ -1,12 +1,13 @@
1
- import {MainSettlementBus} from './src/index.js';
1
+ import { MainSettlementBus } from './src/index.js';
2
2
 
3
3
  const pearApp = typeof Pear !== 'undefined' ? (Pear.app ?? Pear.config) : undefined;
4
4
  const runtimeArgs = typeof process !== 'undefined' ? process.argv.slice(2) : [];
5
5
  const args = pearApp?.args ?? runtimeArgs;
6
+ const runRpc = args.includes('--rpc');
6
7
 
7
8
  const opts = {
8
- stores_directory : 'stores/',
9
- store_name : pearApp?.args?.[0] ?? runtimeArgs[0],
9
+ stores_directory: 'stores/',
10
+ store_name: pearApp?.args?.[0] ?? runtimeArgs[0],
10
11
  bootstrap: 'acbc3a4344d3a804101d40e53db1dda82b767646425af73599d4cd6577d69685',
11
12
  channel: '0000trac0network0msb0mainnet0000',
12
13
  enable_role_requester: false,
@@ -23,15 +24,12 @@ const rpc_opts = {
23
24
  enable_tx_apply_logs: false,
24
25
  enable_error_apply_logs: false,
25
26
  enable_wallet: false,
26
- enable_interactive_mode: true,
27
-
28
- }
27
+ enable_interactive_mode: false,
28
+ };
29
29
 
30
- const msb = new MainSettlementBus(args.includes('--rpc') ? rpc_opts : opts);
30
+ const msb = new MainSettlementBus(runRpc ? rpc_opts : opts);
31
31
 
32
32
  msb.ready().then(async () => {
33
- const runRpc = args.includes('--rpc');
34
-
35
33
  if (runRpc) {
36
34
  console.log('Starting RPC server...');
37
35
  const portIndex = args.indexOf('--port');
@@ -42,8 +40,6 @@ msb.ready().then(async () => {
42
40
  const {startRpcServer} = await import('./rpc/rpc_server.mjs');
43
41
  startRpcServer(msb, host, port);
44
42
  } else {
45
- console.log('RPC server will not be started.');
43
+ msb.interactiveMode();
46
44
  }
47
-
48
- msb.interactiveMode();
49
45
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "trac-msb",
3
3
  "main": "msb.mjs",
4
- "version": "0.2.5",
4
+ "version": "0.2.6",
5
5
  "pear": {
6
6
  "name": "trac-msb",
7
7
  "type": "terminal"
package/rpc/handlers.mjs CHANGED
@@ -2,6 +2,18 @@ import { decodeBase64Payload, isBase64, sanitizeBulkPayloadsRequestBody, sanitiz
2
2
  import { MAX_SIGNED_LENGTH, ZERO_WK } from "./constants.mjs";
3
3
  import { buildRequestUrl } from "./utils/url.mjs";
4
4
  import { isHexString } from "../src/utils/helpers.js";
5
+ import {
6
+ getBalance,
7
+ getTxv,
8
+ getFee,
9
+ getConfirmedLength,
10
+ getUnconfirmedLength,
11
+ broadcastTransaction,
12
+ getTxHashes,
13
+ getTxDetails,
14
+ fetchBulkTxPayloads,
15
+ getExtendedTxDetails
16
+ } from "./rpc_services.js";
5
17
  import { bufferToBigInt, licenseBufferToBigInt } from "../src/utils/amountSerialization.js";
6
18
  import { isAddressValid } from "../src/core/state/utils/address.js";
7
19
  import { getConfirmedParameter } from "./utils/confirmedParameter.mjs";
@@ -20,28 +32,23 @@ export async function handleBalance({ req, respond, msbInstance }) {
20
32
  return;
21
33
  }
22
34
 
23
- const commandString = `/get_balance ${address} ${confirmed}`;
24
- const nodeInfo = await msbInstance.handleCommand(commandString);
35
+ const nodeInfo = await getBalance(msbInstance, address, confirmed);
25
36
  const balance = nodeInfo?.balance || 0;
26
37
  respond(200, { address, balance });
27
38
  }
28
39
 
29
40
  export async function handleTxv({ msbInstance, respond }) {
30
- const commandString = '/get_txv';
31
- const txvRaw = await msbInstance.handleCommand(commandString);
32
- const txv = txvRaw.toString('hex');
41
+ const txv = await getTxv(msbInstance);
33
42
  respond(200, { txv });
34
43
  }
35
44
 
36
45
  export async function handleFee({ msbInstance, respond }) {
37
- const commandString = '/get_fee';
38
- const fee = await msbInstance.handleCommand(commandString);
46
+ const fee = await getFee(msbInstance);
39
47
  respond(200, { fee });
40
48
  }
41
49
 
42
50
  export async function handleConfirmedLength({ msbInstance, respond }) {
43
- const commandString = '/confirmed_length';
44
- const confirmed_length = await msbInstance.handleCommand(commandString);
51
+ const confirmed_length = await getConfirmedLength(msbInstance);
45
52
  respond(200, { confirmed_length });
46
53
  }
47
54
 
@@ -65,7 +72,7 @@ export async function handleBroadcastTransaction({ msbInstance, respond, req })
65
72
  const decodedPayload = decodeBase64Payload(payload);
66
73
  validatePayloadStructure(decodedPayload);
67
74
  const sanitizedPayload = sanitizeTransferPayload(decodedPayload);
68
- const result = await msbInstance.handleCommand('/broadcast_transaction', null, sanitizedPayload);
75
+ const result = await broadcastTransaction(msbInstance, sanitizedPayload);
69
76
  respond(200, { result });
70
77
  } catch (error) {
71
78
  let code = error instanceof SyntaxError ? 400 : 500;
@@ -118,33 +125,25 @@ export async function handleTxHashes({ msbInstance, respond, req }) {
118
125
  }
119
126
 
120
127
  // 4. Get current confirmed length
121
- const currentConfirmedLength = await msbInstance.handleCommand('/confirmed_length');
128
+ const currentConfirmedLength = await getConfirmedLength(msbInstance);
122
129
 
123
130
  // 5. Adjust the end index to not exceed the confirmed length.
124
131
  const adjustedEndLength = Math.min(endSignedLength, currentConfirmedLength)
125
132
 
126
133
  // 6. Fetch txs hashes for the adjusted range, assuming the command takes start and end index.
127
- const commandString = `/get_txs_hashes ${startSignedLength} ${adjustedEndLength}`;
128
- const { hashes } = await msbInstance.handleCommand(commandString);
134
+ const { hashes } = await getTxHashes(msbInstance, startSignedLength, adjustedEndLength);
129
135
  respond(200, { hashes });
130
136
  }
131
137
 
132
138
  export async function handleUnconfirmedLength({ msbInstance, respond }) {
133
- // TODO: VALIDATION?
134
- const commandString = '/unconfirmed_length';
135
- const unconfirmed_length = await msbInstance.handleCommand(commandString);
139
+ const unconfirmed_length = await getUnconfirmedLength(msbInstance);
136
140
  respond(200, { unconfirmed_length });
137
141
  }
138
142
 
139
143
  export async function handleTransactionDetails({ msbInstance, respond, req }) {
140
- // TODO: VALIDATION?
141
- const url = buildRequestUrl(req);
142
- const pathParts = url.pathname.split('/').filter(Boolean);
143
- const hash = pathParts[2];
144
-
145
- const commandString = `/get_tx_details ${hash}`;
146
- const txDetails = await msbInstance.handleCommand(commandString);
147
- respond(txDetails === null ? 404 : 200, { txDetails });
144
+ const hash = req.url.split('/')[3];
145
+ const txDetails = await getTxDetails(msbInstance, hash);
146
+ respond(txDetails === null ? 404 : 200 , { txDetails });
148
147
  }
149
148
 
150
149
  export async function handleFetchBulkTxPayloads({ msbInstance, respond, req }) {
@@ -193,7 +192,7 @@ export async function handleFetchBulkTxPayloads({ msbInstance, respond, req }) {
193
192
 
194
193
  const uniqueHashes = [...new Set(hashes)];
195
194
 
196
- const commandResult = await msbInstance.handleCommand(`/get_tx_payloads_bulk`, null, uniqueHashes)
195
+ const commandResult = await fetchBulkTxPayloads(msbInstance, uniqueHashes);
197
196
 
198
197
  const responseString = JSON.stringify(commandResult);
199
198
  if (Buffer.byteLength(responseString, 'utf8') > 2_000_000) {
@@ -234,14 +233,8 @@ export async function handleTransactionExtendedDetails({ msbInstance, respond, r
234
233
  }
235
234
 
236
235
  try {
237
- let txDetails;
238
- const commandString = `/get_extended_tx_details ${hash} ${confirmed}`;
239
- txDetails = await msbInstance.handleCommand(commandString);
240
- if (txDetails === null) {
241
- respond(404, { error: `No payload found for tx hash: ${hash}` });
242
- } else {
243
- respond(200, txDetails);
244
- }
236
+ const details = await getExtendedTxDetails(msbInstance, hash, confirmed);
237
+ respond(200, details);
245
238
  } catch (error) {
246
239
  if (error.message?.includes('No payload found for tx hash')) {
247
240
  respond(404, { error: error.message });
@@ -0,0 +1,126 @@
1
+ import { bufferToBigInt } from "../src/utils/amountSerialization.js";
2
+ import { normalizeDecodedPayloadForJson } from "../src/utils/normalizers.js";
3
+ import { get_confirmed_tx_info, get_unconfirmed_tx_info } from "../src/utils/cli.js";
4
+
5
+ export async function getBalance(msbInstance, address, confirmed) {
6
+ const state = msbInstance.state;
7
+ const useUnconfirmed = confirmed === false;
8
+
9
+ const nodeEntry = useUnconfirmed
10
+ ? await state.getNodeEntryUnsigned(address)
11
+ : await state.getNodeEntry(address);
12
+
13
+ if (!nodeEntry) return undefined;
14
+
15
+ return {
16
+ address,
17
+ balance: bufferToBigInt(nodeEntry.balance).toString(),
18
+ };
19
+ }
20
+
21
+ export async function getTxv(msbInstance) {
22
+ const txv = await msbInstance.state.getIndexerSequenceState();
23
+ return txv.toString("hex");
24
+ }
25
+
26
+ export async function getFee(msbInstance) {
27
+ const feeBuffer = msbInstance.state.getFee();
28
+ return bufferToBigInt(feeBuffer).toString();
29
+ }
30
+
31
+ export async function getConfirmedLength(msbInstance) {
32
+ return msbInstance.state.getSignedLength();
33
+ }
34
+
35
+ export async function getUnconfirmedLength(msbInstance) {
36
+ return msbInstance.state.getUnsignedLength();
37
+ }
38
+
39
+ export async function broadcastTransaction(msbInstance, payload) {
40
+ return msbInstance.broadcastTransactionCommand(payload);
41
+ }
42
+
43
+ export async function getTxHashes(msbInstance, start, end) {
44
+ const hashes = await msbInstance.state.confirmedTransactionsBetween(start, end);
45
+ return { hashes };
46
+ }
47
+
48
+ export async function getTxDetails(msbInstance, hash) {
49
+ const rawPayload = await get_confirmed_tx_info(msbInstance.state, hash);
50
+ if (!rawPayload) {
51
+ return null;
52
+ }
53
+
54
+ return normalizeDecodedPayloadForJson(rawPayload.decoded);
55
+ }
56
+
57
+ export async function fetchBulkTxPayloads(msbInstance, hashes) {
58
+ if (!Array.isArray(hashes) || hashes.length === 0) {
59
+ throw new Error("Missing hash list.");
60
+ }
61
+
62
+ if (hashes.length > 1500) {
63
+ throw new Error("Length of input tx hashes exceeded.");
64
+ }
65
+
66
+ const res = { results: [], missing: [] };
67
+
68
+ const promises = hashes.map((hash) => get_confirmed_tx_info(msbInstance.state, hash));
69
+ const results = await Promise.all(promises);
70
+
71
+ results.forEach((result, index) => {
72
+ const hash = hashes[index];
73
+ if (result === null || result === undefined) {
74
+ res.missing.push(hash);
75
+ } else {
76
+ const decodedResult = normalizeDecodedPayloadForJson(result.decoded);
77
+ res.results.push({ hash, payload: decodedResult });
78
+ }
79
+ });
80
+
81
+ return res;
82
+ }
83
+
84
+ export async function getExtendedTxDetails(msbInstance, hash, confirmed) {
85
+ const state = msbInstance.state;
86
+
87
+ 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, true);
97
+ const feeBuffer = state.getFee();
98
+ return {
99
+ txDetails: normalizedPayload,
100
+ confirmed_length: confirmedLength,
101
+ fee: bufferToBigInt(feeBuffer).toString(),
102
+ };
103
+ }
104
+
105
+ const rawPayload = await get_unconfirmed_tx_info(state, hash);
106
+ if (!rawPayload) {
107
+ throw new Error(`No payload found for tx hash: ${hash}`);
108
+ }
109
+
110
+ const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded, true);
111
+ const length = await state.getTransactionConfirmedLength(hash);
112
+ if (length === null) {
113
+ return {
114
+ txDetails: normalizedPayload,
115
+ confirmed_length: 0,
116
+ fee: "0",
117
+ };
118
+ }
119
+
120
+ const feeBuffer = state.getFee();
121
+ return {
122
+ txDetails: normalizedPayload,
123
+ confirmed_length: length,
124
+ fee: bufferToBigInt(feeBuffer).toString(),
125
+ };
126
+ }