trac-peer 0.3.0 → 0.4.0
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/.github/workflows/publish.yml +10 -1
- package/DOCS.md +2 -4
- package/README.md +2 -2
- package/{src/dev → dev}/pokemonContract.js +3 -3
- package/{src/dev → dev}/pokemonProtocol.js +17 -12
- package/package.json +9 -5
- package/rpc/services.js +13 -12
- package/scripts/run-peer.mjs +40 -21
- package/src/api.js +65 -65
- package/src/{contract.js → artifacts/contract.js} +14 -58
- package/src/{feature.js → artifacts/feature.js} +3 -4
- package/src/{protocol.js → artifacts/protocol.js} +18 -35
- package/src/base/check.js +115 -0
- package/src/config/config.js +149 -0
- package/src/config/env.js +63 -0
- package/src/contractCheck.js +90 -0
- package/src/index.js +124 -759
- package/src/msbClient.js +62 -38
- package/src/operations/addAdmin/index.js +44 -0
- package/src/operations/addIndexer/index.js +64 -0
- package/src/operations/addWriter/index.js +64 -0
- package/src/operations/autoAddWriter/index.js +48 -0
- package/src/operations/deleteMessage/index.js +83 -0
- package/src/operations/enableTransactions/index.js +58 -0
- package/src/operations/enableWhitelist/index.js +59 -0
- package/src/operations/feature/index.js +64 -0
- package/src/operations/index.js +52 -0
- package/src/operations/msg/index.js +108 -0
- package/src/operations/muteStatus/index.js +72 -0
- package/src/operations/pinMessage/index.js +82 -0
- package/src/operations/removeWriter/index.js +64 -0
- package/src/operations/setAutoAddWriters/index.js +65 -0
- package/src/operations/setChatStatus/index.js +62 -0
- package/src/operations/setMod/index.js +60 -0
- package/src/operations/setNick/index.js +89 -0
- package/src/operations/setWhitelistStatus/index.js +60 -0
- package/src/operations/tx/index.js +142 -0
- package/src/operations/unpinMessage/index.js +73 -0
- package/src/operations/updateAdmin/index.js +63 -0
- package/src/tasks/transactionObserver.js +91 -0
- package/src/tasks/updater.js +57 -0
- package/src/terminal/handlers.js +494 -0
- package/src/terminal/index.js +123 -0
- package/src/transaction/transactionPool.js +38 -0
- package/src/utils/scheduler.js +118 -0
- package/src/utils/types.js +81 -0
- package/src/wallet.js +2 -1
- package/tests/acceptance/acceptance.test.js +4 -1
- package/tests/acceptance/rpc.test.js +37 -82
- package/tests/helpers/tmpdir.js +58 -0
- package/tests/unit/applyGuards.test.js +23 -26
- package/tests/unit/baseContractProtocol.test.js +10 -9
- package/tests/unit/cliTx.test.js +113 -0
- package/tests/unit/operations.test.js +560 -0
- package/tests/unit/unit.test.js +2 -0
- package/src/check.js +0 -565
- package/src/cli.js +0 -275
- package/src/dev/HyperMallConctract.js +0 -990
- package/src/dev/HyperMallProtocol.js +0 -689
- package/src/functions.js +0 -495
- package/src/permissions.js +0 -63
|
@@ -22,7 +22,16 @@ jobs:
|
|
|
22
22
|
node-version: 22
|
|
23
23
|
cache: 'npm'
|
|
24
24
|
- run: npm ci
|
|
25
|
-
-
|
|
25
|
+
- name: Install bare
|
|
26
|
+
run: npm i -g bare
|
|
27
|
+
- name: Verify bare install
|
|
28
|
+
run: |
|
|
29
|
+
which bare
|
|
30
|
+
bare --version
|
|
31
|
+
- name: Unit tests (node + bare)
|
|
32
|
+
run: npm run test:unit:all
|
|
33
|
+
- name: Acceptance tests (node + bare)
|
|
34
|
+
run: npm run test:acceptance:all
|
|
26
35
|
release:
|
|
27
36
|
needs: test
|
|
28
37
|
if: startsWith(github.ref, 'refs/tags/')
|
package/DOCS.md
CHANGED
|
@@ -74,7 +74,7 @@ npm run peer:run -- --msb-bootstrap=<hex32> --msb-channel=<channel>
|
|
|
74
74
|
/deploy_subnet
|
|
75
75
|
/add_admin --address <your-peer-publicKey-hex>
|
|
76
76
|
/tx --command "ping hello"
|
|
77
|
-
/get --key app/ping/<tx-hash>
|
|
77
|
+
/get --key app/ping/<tx-hash> --confirmed false
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
---
|
|
@@ -422,11 +422,9 @@ npm run peer:pear-rpc -- \
|
|
|
422
422
|
- `POST /v1/contract/tx` body: `{ "tx": "<hex32>", "prepared_command": { ... }, "address": "<pubkey-hex32>", "signature": "<hex64>", "nonce": "<hex32>", "sim": true|false }`
|
|
423
423
|
|
|
424
424
|
Notes:
|
|
425
|
-
- To allow wallet tx submission, start the peer with `--api-tx-exposed` (or env `PEER_API_TX_EXPOSED=1`).
|
|
425
|
+
- To allow wallet tx submission, start the peer with `--rpc` and `--api-tx-exposed` (or env `PEER_API_TX_EXPOSED=1` + `PEER_RPC=1`).
|
|
426
426
|
- The peer must be subnet-writable (writer) to broadcast a tx.
|
|
427
427
|
|
|
428
|
-
---
|
|
429
|
-
|
|
430
428
|
## Building your own app (Protocol + Contract)
|
|
431
429
|
|
|
432
430
|
The runner uses demo protocol/contract files under `src/dev/` (wired in `scripts/run-peer.mjs`) so you can test quickly.
|
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ npm run peer:run -- \
|
|
|
68
68
|
The runner prints the Peer MSB address. Fund that address on MSB (so the node entry exists and fee checks pass), then in the peer console run:
|
|
69
69
|
- `/deploy_subnet`
|
|
70
70
|
- `/tx --command "ping hello"` (dev protocol)
|
|
71
|
-
- If you want to use admin-only commands (writer/indexer management, chat moderation), run `/add_admin --address "<peer-publicKey-hex>"` and verify with `/get --key admin`.
|
|
71
|
+
- If you want to use admin-only commands (writer/indexer management, chat moderation), run `/add_admin --address "<peer-publicKey-hex>"` and verify with `/get --key admin --confirmed false`.
|
|
72
72
|
|
|
73
73
|
Notes:
|
|
74
74
|
- The subnet bootstrap key is auto-generated the first time and persisted to `stores/<peer-store>/subnet-bootstrap.hex`.
|
|
@@ -115,5 +115,5 @@ Endpoints (all JSON):
|
|
|
115
115
|
- `POST /v1/contract/tx` body: `{ "tx": "<hex32>", "prepared_command": { ... }, "address": "<pubkey-hex32>", "signature": "<hex64>", "nonce": "<hex32>", "sim": true|false }`
|
|
116
116
|
|
|
117
117
|
Notes:
|
|
118
|
-
- To allow wallet tx submission, start the peer with `--api-tx-exposed` (or env `PEER_API_TX_EXPOSED=1`).
|
|
118
|
+
- To allow wallet tx submission, start the peer with `--rpc` and `--api-tx-exposed` (or env `PEER_API_TX_EXPOSED=1` + `PEER_RPC=1`).
|
|
119
119
|
- RPC request bodies are limited to `1_000_000` bytes by default (override with `--rpc-max-body-bytes`).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import BaseContract from "../contract.js";
|
|
1
|
+
import BaseContract from "../src/artifacts/contract.js";
|
|
2
2
|
|
|
3
3
|
export const GEN1_POKEMON = [
|
|
4
4
|
{ id: 1, name: "Bulbasaur" },
|
|
@@ -155,8 +155,8 @@ export const GEN1_POKEMON = [
|
|
|
155
155
|
];
|
|
156
156
|
|
|
157
157
|
class PokemonContract extends BaseContract {
|
|
158
|
-
constructor(protocol) {
|
|
159
|
-
super(protocol);
|
|
158
|
+
constructor(protocol, config) {
|
|
159
|
+
super(protocol, config);
|
|
160
160
|
this.addFunction("catch");
|
|
161
161
|
}
|
|
162
162
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import BaseProtocol from "../protocol.js";
|
|
1
|
+
import BaseProtocol from "../src/artifacts/protocol.js";
|
|
2
2
|
import { bufferToBigInt, bigIntToDecimalString } from "trac-msb/src/utils/amountSerialization.js";
|
|
3
3
|
|
|
4
4
|
class PokemonProtocol extends BaseProtocol {
|
|
@@ -30,31 +30,37 @@ class PokemonProtocol extends BaseProtocol {
|
|
|
30
30
|
|
|
31
31
|
async customCommand(input) {
|
|
32
32
|
if (typeof input !== "string") return;
|
|
33
|
+
|
|
33
34
|
if (input.startsWith("/get")) {
|
|
34
|
-
const m = input.match(/(?:^|\s)--key(?:=|\s+)(
|
|
35
|
+
const m = input.match(/(?:^|\s)--key(?:=|\s+)(\"[^\"]+\"|'[^']+'|\S+)/);
|
|
35
36
|
const raw = m ? m[1].trim() : null;
|
|
36
37
|
if (!raw) {
|
|
37
|
-
console.log('Usage: /get --key "<hyperbee-key>"');
|
|
38
|
+
console.log('Usage: /get --key "<hyperbee-key>" [--confirmed true|false] [--unconfirmed 1]');
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
40
41
|
const key = raw.replace(/^\"(.*)\"$/, "$1").replace(/^'(.*)'$/, "$1");
|
|
41
|
-
const
|
|
42
|
+
const confirmedMatch = input.match(/(?:^|\s)--confirmed(?:=|\s+)(\S+)/);
|
|
43
|
+
const unconfirmedMatch = input.match(/(?:^|\s)--unconfirmed(?:=|\s+)?(\S+)?/);
|
|
44
|
+
const confirmed = unconfirmedMatch ? false : confirmedMatch ? confirmedMatch[1] === "true" || confirmedMatch[1] === "1" : true;
|
|
45
|
+
const v = confirmed ? await this.getSigned(key) : await this.get(key);
|
|
42
46
|
console.log(v);
|
|
43
47
|
return;
|
|
44
48
|
}
|
|
49
|
+
|
|
45
50
|
if (input.startsWith("/msb")) {
|
|
46
51
|
const txv = await this.peer.msbClient.getTxvHex();
|
|
47
52
|
const peerMsbAddress = this.peer.msbClient.pubKeyHexToAddress(this.peer.wallet.publicKey);
|
|
48
|
-
const entry =
|
|
49
|
-
const balance = entry?.balance ? bigIntToDecimalString(bufferToBigInt(entry.balance)) :
|
|
50
|
-
const
|
|
51
|
-
const
|
|
53
|
+
const entry = await this.peer.msbClient.getNodeEntryUnsigned(peerMsbAddress);
|
|
54
|
+
const balance = entry?.balance ? bigIntToDecimalString(bufferToBigInt(entry.balance)) : 0;
|
|
55
|
+
const feeBuf = this.peer.msbClient.getFee();
|
|
56
|
+
const fee = feeBuf ? bigIntToDecimalString(bufferToBigInt(feeBuf)) : 0;
|
|
57
|
+
const validators = this.peer.msbClient.getConnectedValidatorsCount();
|
|
52
58
|
console.log({
|
|
53
59
|
networkId: this.peer.msbClient.networkId,
|
|
54
60
|
msbBootstrap: this.peer.msbClient.bootstrapHex,
|
|
55
61
|
txv,
|
|
56
|
-
msbSignedLength: this.peer.
|
|
57
|
-
msbUnsignedLength: this.peer.
|
|
62
|
+
msbSignedLength: this.peer.msbClient.getSignedLength(),
|
|
63
|
+
msbUnsignedLength: this.peer.msbClient.getUnsignedLength(),
|
|
58
64
|
connectedValidators: validators,
|
|
59
65
|
peerMsbAddress,
|
|
60
66
|
peerMsbBalance: balance,
|
|
@@ -68,7 +74,7 @@ class PokemonProtocol extends BaseProtocol {
|
|
|
68
74
|
console.log("");
|
|
69
75
|
console.log("- Dev commands:");
|
|
70
76
|
console.log('- /msb | prints MSB txv + lengths (local MSB node view).');
|
|
71
|
-
console.log('- /get --key "<key>" | reads
|
|
77
|
+
console.log('- /get --key "<key>" [--confirmed true|false] | reads subnet state key (confirmed defaults to true).');
|
|
72
78
|
console.log("");
|
|
73
79
|
console.log("- Dev TX examples:");
|
|
74
80
|
console.log('- /tx --command "ping hello"');
|
|
@@ -78,4 +84,3 @@ class PokemonProtocol extends BaseProtocol {
|
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
export default PokemonProtocol;
|
|
81
|
-
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trac-peer",
|
|
3
3
|
"main": "src/index.js",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"pear": {
|
|
7
7
|
"name": "trac-peer",
|
|
@@ -24,9 +24,13 @@
|
|
|
24
24
|
"peer:smoke": "node scripts/smoke-msb-sync.mjs",
|
|
25
25
|
"peer:pear": "pear run -d scripts/run-peer.mjs",
|
|
26
26
|
"peer:pear-rpc": "pear run -d scripts/run-peer.mjs --rpc",
|
|
27
|
-
"test:unit:node": "node tests/unit/unit.test.js",
|
|
28
|
-
"test:
|
|
29
|
-
"test:all": "npm run test:unit:node && npm run test:
|
|
27
|
+
"test:unit:node": "brittle-node -t 60000 tests/unit/unit.test.js",
|
|
28
|
+
"test:unit:bare": "brittle-bare -t 60000 tests/unit/unit.test.js",
|
|
29
|
+
"test:unit:all": "(npm run test:unit:node && npm run test:unit:bare) || exit 1",
|
|
30
|
+
"test:acceptance:node": "brittle-node -t 120000 tests/acceptance/acceptance.test.js",
|
|
31
|
+
"test:acceptance:bare": "brittle-bare -t 120000 tests/acceptance/acceptance.test.js",
|
|
32
|
+
"test:acceptance:all": "(npm run test:acceptance:node && npm run test:acceptance:bare) || exit 1",
|
|
33
|
+
"test:all": "npm run test:unit:all && npm run test:acceptance:all"
|
|
30
34
|
},
|
|
31
35
|
"dependencies": {
|
|
32
36
|
"@tracsystems/blake3": "^0.0.15",
|
|
@@ -96,7 +100,7 @@
|
|
|
96
100
|
"timers": "npm:bare-node-timers",
|
|
97
101
|
"tls": "npm:bare-node-tls",
|
|
98
102
|
"trac-crypto-api": "^0.1.3",
|
|
99
|
-
"trac-msb": "^0.2.
|
|
103
|
+
"trac-msb": "^0.2.9",
|
|
100
104
|
"trac-wallet": "^0.0.43-msb-r2.9",
|
|
101
105
|
"tty": "npm:bare-node-tty",
|
|
102
106
|
"url": "npm:bare-node-url",
|
package/rpc/services.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import b4a from "b4a";
|
|
2
2
|
import { fastestToJsonSchema } from "./utils/schemaToJson.js";
|
|
3
|
+
import { createHash } from "../src/utils/types.js";
|
|
3
4
|
|
|
4
5
|
const asHex32 = (value, field) => {
|
|
5
6
|
const hex = String(value ?? "").trim().toLowerCase();
|
|
@@ -10,7 +11,7 @@ const asHex32 = (value, field) => {
|
|
|
10
11
|
const isObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
11
12
|
|
|
12
13
|
const requireApi = (peer) => {
|
|
13
|
-
const api = peer?.
|
|
14
|
+
const api = peer?.protocol.instance?.api;
|
|
14
15
|
if (!api) throw new Error("Protocol API not initialized.");
|
|
15
16
|
return api;
|
|
16
17
|
};
|
|
@@ -22,7 +23,7 @@ export async function getStatus(peer) {
|
|
|
22
23
|
? String(peer.bootstrap)
|
|
23
24
|
: null;
|
|
24
25
|
|
|
25
|
-
const peerMsbAddress = peer.msbClient
|
|
26
|
+
const peerMsbAddress = peer.msbClient.pubKeyHexToAddress(peer.wallet.publicKey);
|
|
26
27
|
|
|
27
28
|
const admin = peer.base?.view ? await peer.base.view.get("admin") : null;
|
|
28
29
|
const chatStatus = peer.base?.view ? await peer.base.view.get("chat_status") : null;
|
|
@@ -43,10 +44,10 @@ export async function getStatus(peer) {
|
|
|
43
44
|
chatStatus: chatStatus?.value ?? null,
|
|
44
45
|
},
|
|
45
46
|
msb: {
|
|
46
|
-
ready:
|
|
47
|
-
bootstrapHex: peer.msbClient
|
|
48
|
-
networkId: peer.msbClient
|
|
49
|
-
signedLength: peer.msbClient
|
|
47
|
+
ready: true,
|
|
48
|
+
bootstrapHex: peer.msbClient.bootstrapHex,
|
|
49
|
+
networkId: peer.msbClient.networkId,
|
|
50
|
+
signedLength: peer.msbClient.getSignedLength()
|
|
50
51
|
},
|
|
51
52
|
};
|
|
52
53
|
}
|
|
@@ -78,7 +79,7 @@ const convertContractOpSchema = (fv) => {
|
|
|
78
79
|
};
|
|
79
80
|
|
|
80
81
|
export async function getContractSchema(peer) {
|
|
81
|
-
const contract = peer?.
|
|
82
|
+
const contract = peer?.contract?.instance;
|
|
82
83
|
if (!contract) throw new Error("Contract instance not initialized.");
|
|
83
84
|
|
|
84
85
|
const registrations = contract.metadata ?? {};
|
|
@@ -106,11 +107,11 @@ export async function getContractSchema(peer) {
|
|
|
106
107
|
schemaFormat: "json-schema",
|
|
107
108
|
contract: {
|
|
108
109
|
contractClass: contract.constructor?.name ?? null,
|
|
109
|
-
protocolClass: peer.
|
|
110
|
+
protocolClass: peer.protocol.instance?.constructor?.name ?? null,
|
|
110
111
|
txTypes,
|
|
111
112
|
ops,
|
|
112
113
|
},
|
|
113
|
-
api: peer.
|
|
114
|
+
api: peer.protocol.instance?.getApiSchema ? peer.protocol.instance.getApiSchema() : { methods: {} },
|
|
114
115
|
};
|
|
115
116
|
}
|
|
116
117
|
|
|
@@ -125,14 +126,14 @@ export async function contractPrepareTx(peer, { prepared_command, address, nonce
|
|
|
125
126
|
const addr = asHex32(address, "address");
|
|
126
127
|
const n = asHex32(nonce, "nonce");
|
|
127
128
|
|
|
128
|
-
if (peer?.
|
|
129
|
+
if (peer?.protocol.instance?.safeJsonStringify == null) {
|
|
129
130
|
throw new Error("safeJsonStringify is not available on protocol instance.");
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
const json = peer.
|
|
133
|
+
const json = peer.protocol.instance.safeJsonStringify(prepared_command);
|
|
133
134
|
if (json == null) throw new Error("Failed to stringify prepared_command.");
|
|
134
135
|
|
|
135
|
-
const command_hash = await
|
|
136
|
+
const command_hash = await createHash(json);
|
|
136
137
|
const tx = await api.generateTx(addr, command_hash, n);
|
|
137
138
|
return { tx, command_hash };
|
|
138
139
|
}
|
package/scripts/run-peer.mjs
CHANGED
|
@@ -2,15 +2,15 @@ import b4a from "b4a";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import PeerWallet from "trac-wallet";
|
|
5
|
-
import { Peer, Wallet } from "../src/index.js";
|
|
5
|
+
import { Peer, Wallet, createConfig as createPeerConfig, ENV as PEER_ENV } from "../src/index.js";
|
|
6
6
|
import { MainSettlementBus } from "trac-msb/src/index.js";
|
|
7
|
-
import { createConfig, ENV } from "trac-msb/src/config/env.js"
|
|
7
|
+
import { createConfig as createMsbConfig, ENV as MSB_ENV } from "trac-msb/src/config/env.js"
|
|
8
8
|
import { startRpcServer } from "../rpc/rpc_server.js";
|
|
9
9
|
import { DEFAULT_RPC_HOST, DEFAULT_RPC_PORT, DEFAULT_MAX_BODY_BYTES } from "../rpc/constants.js";
|
|
10
|
-
import {
|
|
10
|
+
import { Terminal } from "../src/terminal/index.js";
|
|
11
11
|
import { ensureTextCodecs } from "../src/textCodec.js";
|
|
12
|
-
import PokemonProtocol from "../
|
|
13
|
-
import PokemonContract from "../
|
|
12
|
+
import PokemonProtocol from "../dev/pokemonProtocol.js";
|
|
13
|
+
import PokemonContract from "../dev/pokemonContract.js";
|
|
14
14
|
|
|
15
15
|
let process = globalThis.process;
|
|
16
16
|
if (globalThis.Pear !== undefined) {
|
|
@@ -18,8 +18,13 @@ if (globalThis.Pear !== undefined) {
|
|
|
18
18
|
process = bareProcess;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
const pearApp = typeof Pear !== "undefined" ? (Pear.app ?? Pear.config) : undefined;
|
|
22
|
+
const runtimeArgs = typeof process !== "undefined" ? process.argv.slice(2) : [];
|
|
23
|
+
const argv = pearApp?.args ?? runtimeArgs;
|
|
24
|
+
const positionalStoreName = argv.find((a) => a !== undefined && !String(a).startsWith("--")) ?? null;
|
|
25
|
+
|
|
21
26
|
const createMsb = (options) => {
|
|
22
|
-
const config =
|
|
27
|
+
const config = createMsbConfig(MSB_ENV.MAINNET, options)
|
|
23
28
|
return new MainSettlementBus(config);
|
|
24
29
|
}
|
|
25
30
|
|
|
@@ -72,7 +77,7 @@ const readHexFile = (filePath, byteLength) => {
|
|
|
72
77
|
return null;
|
|
73
78
|
};
|
|
74
79
|
|
|
75
|
-
const args = toArgMap(
|
|
80
|
+
const args = toArgMap(argv);
|
|
76
81
|
|
|
77
82
|
const rpcEnabled =
|
|
78
83
|
args["rpc"] === true || args["rpc"] === "true" || process.env.PEER_RPC === "true" || process.env.PEER_RPC === "1";
|
|
@@ -102,6 +107,11 @@ const apiTxExposed =
|
|
|
102
107
|
process.env.PEER_API_TX_EXPOSED === "true" ||
|
|
103
108
|
process.env.PEER_API_TX_EXPOSED === "1";
|
|
104
109
|
|
|
110
|
+
const apiTxExposedEffective = rpcEnabled ? apiTxExposed : false;
|
|
111
|
+
if (!rpcEnabled && apiTxExposed) {
|
|
112
|
+
console.warn("Ignoring --api-tx-exposed because RPC is not enabled (use --rpc).");
|
|
113
|
+
}
|
|
114
|
+
|
|
105
115
|
const msbStoresDirectory =
|
|
106
116
|
(args["msb-stores-directory"] && String(args["msb-stores-directory"])) ||
|
|
107
117
|
process.env.MSB_STORES_DIRECTORY ||
|
|
@@ -110,7 +120,7 @@ const msbStoresDirectory =
|
|
|
110
120
|
const msbStoreName =
|
|
111
121
|
(args["msb-store-name"] && String(args["msb-store-name"])) ||
|
|
112
122
|
process.env.MSB_STORE_NAME ||
|
|
113
|
-
|
|
123
|
+
null;
|
|
114
124
|
|
|
115
125
|
const msbBootstrap =
|
|
116
126
|
(args["msb-bootstrap"] && String(args["msb-bootstrap"])) ||
|
|
@@ -130,8 +140,8 @@ const peerStoresDirectory =
|
|
|
130
140
|
const peerStoreNameRaw =
|
|
131
141
|
(args["peer-store-name"] && String(args["peer-store-name"])) ||
|
|
132
142
|
process.env.PEER_STORE_NAME ||
|
|
143
|
+
(positionalStoreName ? String(positionalStoreName) : null) ||
|
|
133
144
|
"peer";
|
|
134
|
-
const peerStoreName = ensureTrailingSlash(peerStoreNameRaw);
|
|
135
145
|
|
|
136
146
|
const subnetBootstrapHex =
|
|
137
147
|
(args["subnet-bootstrap"] && String(args["subnet-bootstrap"])) ||
|
|
@@ -161,13 +171,14 @@ if (!msbBootstrapHex || !msbChannel) {
|
|
|
161
171
|
// Important: this starts a *local MSB node* (its own store) that joins your already-running MSB network.
|
|
162
172
|
// trac-peer currently requires an MSB instance to broadcast and to observe confirmed state.
|
|
163
173
|
|
|
164
|
-
const
|
|
165
|
-
const
|
|
174
|
+
const effectiveMsbStoreName = msbStoreName ?? `${peerStoreNameRaw}-msb`;
|
|
175
|
+
const msbStoresFullPath = path.join(ensureTrailingSlash(msbStoresDirectory), effectiveMsbStoreName);
|
|
176
|
+
const msbKeyPairPath = path.join(msbStoresFullPath, "db", "keypair.json");
|
|
166
177
|
await ensureKeypairFile(msbKeyPairPath);
|
|
167
178
|
|
|
168
179
|
const peerKeyPairPath = path.join(
|
|
169
180
|
peerStoresDirectory,
|
|
170
|
-
|
|
181
|
+
peerStoreNameRaw,
|
|
171
182
|
"db",
|
|
172
183
|
"keypair.json"
|
|
173
184
|
);
|
|
@@ -197,22 +208,25 @@ if (subnetBootstrap) {
|
|
|
197
208
|
}
|
|
198
209
|
}
|
|
199
210
|
|
|
200
|
-
const msb = createMsb({ bootstrap: msbBootstrap, channel: msbChannel, storeName:
|
|
211
|
+
const msb = createMsb({ bootstrap: msbBootstrap, channel: msbChannel, storeName: effectiveMsbStoreName, storesDirectory: msbStoresDirectory})
|
|
201
212
|
await msb.ready();
|
|
202
213
|
|
|
203
214
|
// DevProtocol and DevContract moved to shared src files
|
|
215
|
+
const peerConfig = createPeerConfig(PEER_ENV.MAINNET, {
|
|
216
|
+
storesDirectory: ensureTrailingSlash(peerStoresDirectory),
|
|
217
|
+
storeName: peerStoreNameRaw,
|
|
218
|
+
bootstrap: subnetBootstrap ? b4a.from(subnetBootstrap, "hex") : null,
|
|
219
|
+
channel: subnetChannel,
|
|
220
|
+
enableInteractiveMode: rpcEnabled ? false : true,
|
|
221
|
+
apiTxExposed: apiTxExposedEffective,
|
|
222
|
+
});
|
|
204
223
|
|
|
205
224
|
const peer = new Peer({
|
|
206
|
-
|
|
207
|
-
store_name: peerStoreName,
|
|
225
|
+
config: peerConfig,
|
|
208
226
|
msb,
|
|
209
227
|
wallet: new Wallet(),
|
|
210
228
|
protocol: PokemonProtocol,
|
|
211
229
|
contract: PokemonContract,
|
|
212
|
-
bootstrap: subnetBootstrap ? b4a.from(subnetBootstrap, "hex") : null,
|
|
213
|
-
channel: subnetChannel,
|
|
214
|
-
enable_interactive_mode: true,
|
|
215
|
-
api_tx_exposed: apiTxExposed,
|
|
216
230
|
});
|
|
217
231
|
await peer.ready();
|
|
218
232
|
|
|
@@ -222,7 +236,7 @@ if (rpcEnabled) {
|
|
|
222
236
|
}
|
|
223
237
|
|
|
224
238
|
const peerMsbAddress = peer.msbClient.pubKeyHexToAddress(peer.wallet.publicKey);
|
|
225
|
-
const effectiveSubnetBootstrapHex = peer.base?.key ? b4a.toString(peer.base.key, "hex") : (b4a.isBuffer(peer.bootstrap) ? b4a.toString(peer.bootstrap, "hex") : String(peer.bootstrap));
|
|
239
|
+
const effectiveSubnetBootstrapHex = peer.base?.key ? b4a.toString(peer.base.key, "hex") : (b4a.isBuffer(peer.config.bootstrap) ? b4a.toString(peer.config.bootstrap, "hex") : String(peer.config.bootstrap));
|
|
226
240
|
if (!subnetBootstrap) {
|
|
227
241
|
fs.mkdirSync(path.dirname(subnetBootstrapFile), { recursive: true });
|
|
228
242
|
fs.writeFileSync(subnetBootstrapFile, `${effectiveSubnetBootstrapHex}\n`);
|
|
@@ -256,7 +270,12 @@ console.log(' - /get --key "txl"');
|
|
|
256
270
|
console.log("==========================================================");
|
|
257
271
|
console.log("");
|
|
258
272
|
|
|
259
|
-
|
|
273
|
+
if (peer.config.enableInteractiveMode) {
|
|
274
|
+
const terminal = new Terminal(peer);
|
|
275
|
+
await terminal.start();
|
|
276
|
+
} else {
|
|
277
|
+
console.log("Interactive CLI disabled.");
|
|
278
|
+
}
|
|
260
279
|
|
|
261
280
|
process.on("SIGINT", async () => {
|
|
262
281
|
if (rpcServer) await new Promise((resolve) => rpcServer.close(resolve));
|