solforge 0.2.4 → 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.
Files changed (82) hide show
  1. package/README.md +471 -79
  2. package/cli.cjs +106 -78
  3. package/package.json +1 -1
  4. package/scripts/install.sh +1 -1
  5. package/scripts/postinstall.cjs +69 -61
  6. package/server/lib/base58.ts +1 -1
  7. package/server/methods/account/get-account-info.ts +3 -7
  8. package/server/methods/account/get-balance.ts +3 -7
  9. package/server/methods/account/get-multiple-accounts.ts +2 -1
  10. package/server/methods/account/get-parsed-account-info.ts +3 -7
  11. package/server/methods/account/parsers/index.ts +2 -2
  12. package/server/methods/account/parsers/loader-upgradeable.ts +14 -1
  13. package/server/methods/account/parsers/spl-token.ts +29 -10
  14. package/server/methods/account/request-airdrop.ts +44 -31
  15. package/server/methods/block/get-block.ts +3 -7
  16. package/server/methods/block/get-blocks-with-limit.ts +3 -7
  17. package/server/methods/block/is-blockhash-valid.ts +3 -7
  18. package/server/methods/get-address-lookup-table.ts +3 -7
  19. package/server/methods/program/get-program-accounts.ts +9 -9
  20. package/server/methods/program/get-token-account-balance.ts +3 -7
  21. package/server/methods/program/get-token-accounts-by-delegate.ts +4 -3
  22. package/server/methods/program/get-token-accounts-by-owner.ts +61 -35
  23. package/server/methods/program/get-token-largest-accounts.ts +3 -2
  24. package/server/methods/program/get-token-supply.ts +3 -2
  25. package/server/methods/solforge/index.ts +9 -6
  26. package/server/methods/transaction/get-parsed-transaction.ts +3 -7
  27. package/server/methods/transaction/get-signature-statuses.ts +14 -7
  28. package/server/methods/transaction/get-signatures-for-address.ts +3 -7
  29. package/server/methods/transaction/get-transaction.ts +167 -81
  30. package/server/methods/transaction/send-transaction.ts +29 -16
  31. package/server/methods/transaction/simulate-transaction.ts +3 -2
  32. package/server/rpc-server.ts +47 -34
  33. package/server/types.ts +9 -6
  34. package/server/ws-server.ts +15 -8
  35. package/src/api-server-entry.ts +91 -91
  36. package/src/cli/commands/airdrop.ts +2 -2
  37. package/src/cli/commands/config.ts +2 -2
  38. package/src/cli/commands/mint.ts +3 -3
  39. package/src/cli/commands/program-clone.ts +9 -11
  40. package/src/cli/commands/program-load.ts +3 -3
  41. package/src/cli/commands/rpc-start.ts +8 -5
  42. package/src/cli/commands/token-adopt-authority.ts +1 -1
  43. package/src/cli/commands/token-clone.ts +5 -6
  44. package/src/cli/commands/token-create.ts +5 -5
  45. package/src/cli/main.ts +38 -37
  46. package/src/cli/run-solforge.ts +20 -6
  47. package/src/cli/setup-wizard.ts +8 -6
  48. package/src/commands/add-program.ts +324 -328
  49. package/src/commands/init.ts +106 -106
  50. package/src/commands/list.ts +125 -125
  51. package/src/commands/mint.ts +247 -248
  52. package/src/commands/start.ts +837 -833
  53. package/src/commands/status.ts +80 -80
  54. package/src/commands/stop.ts +381 -382
  55. package/src/config/index.ts +33 -17
  56. package/src/config/manager.ts +150 -150
  57. package/src/db/index.ts +2 -2
  58. package/src/db/tx-store.ts +12 -8
  59. package/src/gui/public/app.css +1556 -1
  60. package/src/gui/public/build/main.css +1569 -1
  61. package/src/gui/server.ts +21 -22
  62. package/src/gui/src/api.ts +1 -1
  63. package/src/gui/src/app.tsx +96 -45
  64. package/src/gui/src/components/airdrop-mint-form.tsx +49 -19
  65. package/src/gui/src/components/clone-program-modal.tsx +31 -12
  66. package/src/gui/src/components/clone-token-modal.tsx +32 -13
  67. package/src/gui/src/components/modal.tsx +18 -11
  68. package/src/gui/src/components/programs-panel.tsx +27 -15
  69. package/src/gui/src/components/status-panel.tsx +32 -18
  70. package/src/gui/src/components/tokens-panel.tsx +25 -19
  71. package/src/gui/src/index.css +491 -463
  72. package/src/index.ts +177 -149
  73. package/src/rpc/start.ts +1 -1
  74. package/src/services/api-server.ts +494 -475
  75. package/src/services/port-manager.ts +164 -167
  76. package/src/services/process-registry.ts +144 -145
  77. package/src/services/program-cloner.ts +312 -312
  78. package/src/services/token-cloner.ts +799 -797
  79. package/src/services/validator.ts +288 -290
  80. package/src/types/config.ts +72 -72
  81. package/src/utils/shell.ts +75 -75
  82. package/src/utils/token-loader.ts +78 -78
@@ -8,7 +8,7 @@ import { parseFlags } from "../utils/args";
8
8
  // solforge token clone <mint> --to <owner> --ui-amount <num> --decimals <d>
9
9
  export async function tokenCloneCommand(args: string[]) {
10
10
  const { flags, rest } = parseFlags(args);
11
- const mint = ((rest[0] as string) || (flags["mint"] as string) || "").trim();
11
+ const mint = ((rest[0] as string) || (flags.mint as string) || "").trim();
12
12
  if (!mint) {
13
13
  p.log.error(
14
14
  "Usage: solforge token clone <mint> [--amount <baseUnits> | --ui-amount <num>] [--endpoint URL]",
@@ -16,10 +16,10 @@ export async function tokenCloneCommand(args: string[]) {
16
16
  return;
17
17
  }
18
18
 
19
- const owner = flags["to"] as string | undefined; // optional; defaults to faucet on server
20
- const configPath = flags["config"] as string | undefined;
19
+ const _owner = flags.to as string | undefined; // optional; defaults to faucet on server
20
+ const configPath = flags.config as string | undefined;
21
21
  const cfg = await readConfig(configPath);
22
- const endpoint = (flags["endpoint"] as string) || cfg.clone.endpoint;
22
+ const endpoint = (flags.endpoint as string) || cfg.clone.endpoint;
23
23
  const url = `http://localhost:${cfg.server.rpcPort}`;
24
24
  const s = p.spinner();
25
25
  s.start("Cloning mint into LiteSVM...");
@@ -75,7 +75,7 @@ export async function tokenCloneCommand(args: string[]) {
75
75
  ),
76
76
  );
77
77
  return;
78
- } catch (adoptErr: any) {
78
+ } catch (adoptErr: unknown) {
79
79
  p.log.warn(
80
80
  `Adopt authority failed: ${adoptErr?.message || String(adoptErr)}`,
81
81
  );
@@ -85,7 +85,6 @@ export async function tokenCloneCommand(args: string[]) {
85
85
  );
86
86
  return;
87
87
  }
88
- return;
89
88
  } catch (e) {
90
89
  s.stop("Clone failed");
91
90
  p.log.error(String(e));
@@ -8,13 +8,13 @@ import { parseFlags } from "../utils/args";
8
8
  // solforge token create --decimals <d> --owner <pubkey> [--mint <pubkey>] [--amount <baseUnits> | --ui-amount <num>]
9
9
  export async function tokenCreateCommand(args: string[]) {
10
10
  const { flags } = parseFlags(args);
11
- const decimals = flags["decimals"] ? Number(flags["decimals"]) : NaN;
12
- const owner = flags["owner"] as string | undefined;
13
- const mint = flags["mint"] as string | undefined;
14
- const amountBase = flags["amount"] as string | undefined;
11
+ const decimals = flags.decimals ? Number(flags.decimals) : NaN;
12
+ const owner = flags.owner as string | undefined;
13
+ const mint = flags.mint as string | undefined;
14
+ const amountBase = flags.amount as string | undefined;
15
15
  const uiAmount = flags["ui-amount"] as string | undefined;
16
16
 
17
- if (!isFinite(decimals)) {
17
+ if (!Number.isFinite(decimals)) {
18
18
  p.log.error("--decimals is required (0-18)");
19
19
  return;
20
20
  }
package/src/cli/main.ts CHANGED
@@ -1,24 +1,23 @@
1
1
  // Minimal, fast CLI router with @clack/prompts for UX
2
2
  import * as p from "@clack/prompts";
3
- // Load version for --version in both bun script and compiled binary
4
- // eslint-disable-next-line @typescript-eslint/consistent-type-imports
5
- import pkg from "../../package.json" assert { type: "json" };
3
+ // CLI version string; keep in sync with package.json if possible
4
+ const VERSION = "0.2.4";
6
5
 
7
6
  // Robust arg parsing for both bun script and compiled binary
8
7
  const known = new Set([
9
- "help",
10
- "-h",
11
- "--help",
12
- "version",
13
- "-v",
14
- "--version",
15
- "rpc",
16
- "start",
17
- "config",
18
- "airdrop",
19
- "mint",
20
- "token",
21
- "program",
8
+ "help",
9
+ "-h",
10
+ "--help",
11
+ "version",
12
+ "-v",
13
+ "--version",
14
+ "rpc",
15
+ "start",
16
+ "config",
17
+ "airdrop",
18
+ "mint",
19
+ "token",
20
+ "program",
22
21
  ]);
23
22
  const raw = Bun.argv.slice(1);
24
23
  const firstIdx = raw.findIndex((a) => known.has(String(a)));
@@ -27,26 +26,28 @@ const argv = firstIdx >= 0 ? raw.slice(firstIdx) : [];
27
26
  async function main() {
28
27
  const [cmd, sub, ...rest] = argv;
29
28
 
30
- if (!cmd) {
31
- const { runSolforge } = await import("./run-solforge");
32
- await runSolforge();
33
- return;
34
- }
29
+ if (!cmd) {
30
+ const { runSolforge } = await import("./run-solforge");
31
+ // Pass through any flags provided when no explicit command was given
32
+ await runSolforge(raw);
33
+ return;
34
+ }
35
35
 
36
- if (cmd === "help" || cmd === "-h" || cmd === "--help") {
37
- printHelp();
38
- return;
39
- }
36
+ if (cmd === "help" || cmd === "-h" || cmd === "--help") {
37
+ printHelp();
38
+ return;
39
+ }
40
40
 
41
- if (cmd === "version" || cmd === "-v" || cmd === "--version") {
42
- printVersion();
43
- return;
44
- }
41
+ if (cmd === "version" || cmd === "-v" || cmd === "--version") {
42
+ printVersion();
43
+ return;
44
+ }
45
45
 
46
46
  // Alias: solforge start -> solforge rpc start
47
47
  if (cmd === "start") {
48
- const { rpcStartCommand } = await import("./commands/rpc-start");
49
- await rpcStartCommand(rest);
48
+ // Run the full Solforge flow (config ensure + bootstrap + servers)
49
+ const { runSolforge } = await import("./run-solforge");
50
+ await runSolforge(rest);
50
51
  return;
51
52
  }
52
53
 
@@ -115,7 +116,7 @@ async function main() {
115
116
  }
116
117
 
117
118
  function printHelp() {
118
- console.log(`
119
+ console.log(`
119
120
  solforge <command>
120
121
 
121
122
  Commands:
@@ -134,18 +135,18 @@ Commands:
134
135
  Options:
135
136
  -h, --help Show help
136
137
  -v, --version Show version
138
+ --network Bind servers to 0.0.0.0 (LAN access)
139
+ -y, --ci Non-interactive; auto-accept prompts (use existing config)
137
140
  `);
138
141
  }
139
142
 
140
143
  async function unknownCommand(parts: (string | undefined)[]) {
141
- p.log.error(`Unknown command: ${parts.filter(Boolean).join(" ")}`);
142
- printHelp();
144
+ p.log.error(`Unknown command: ${parts.filter(Boolean).join(" ")}`);
145
+ printHelp();
143
146
  }
144
147
 
145
148
  function printVersion() {
146
- // Prefer package.json version if available
147
- const v = (pkg as any)?.version ?? "";
148
- console.log(String(v));
149
+ console.log(String(VERSION));
149
150
  }
150
151
 
151
152
  main();
@@ -9,17 +9,25 @@ import { startRpcServers } from "../rpc/start";
9
9
  import { bootstrapEnvironment } from "./bootstrap";
10
10
  import { cancelSetup } from "./setup-utils";
11
11
  import { runSetupWizard } from "./setup-wizard";
12
+ import { parseFlags } from "./utils/args";
12
13
 
13
14
  const CONFIG_PATH = "sf.config.json";
14
15
 
15
- export async function runSolforge() {
16
- const config = await ensureConfig();
17
- await startWithConfig(config);
16
+ export async function runSolforge(args: string[] = []) {
17
+ const { flags } = parseFlags(args);
18
+ const ci = flags.ci === true || flags.y === true;
19
+ const config = await ensureConfig(ci);
20
+ await startWithConfig(config, args);
18
21
  }
19
22
 
20
- async function ensureConfig(): Promise<SolforgeConfig> {
23
+ async function ensureConfig(ci = false): Promise<SolforgeConfig> {
21
24
  const exists = await Bun.file(CONFIG_PATH).exists();
22
25
  if (!exists) {
26
+ if (ci) {
27
+ // Non-interactive: write defaults and continue
28
+ await saveConfig(defaultConfig);
29
+ return defaultConfig;
30
+ }
23
31
  p.intro("Solforge setup");
24
32
  const config = await runSetupWizard();
25
33
  await saveConfig(config);
@@ -28,6 +36,7 @@ async function ensureConfig(): Promise<SolforgeConfig> {
28
36
  }
29
37
 
30
38
  const current = await readConfig(CONFIG_PATH);
39
+ if (ci) return current; // Non-interactive: always reuse existing config
31
40
  const reuse = await p.confirm({
32
41
  message: `Use existing config at ${CONFIG_PATH}?`,
33
42
  initialValue: true,
@@ -41,8 +50,13 @@ async function ensureConfig(): Promise<SolforgeConfig> {
41
50
  return updated;
42
51
  }
43
52
 
44
- async function startWithConfig(config: SolforgeConfig) {
45
- const host = String(process.env.RPC_HOST || "127.0.0.1");
53
+ async function startWithConfig(config: SolforgeConfig, args: string[] = []) {
54
+ const { flags } = parseFlags(args);
55
+ const host = String(
56
+ flags.network === true
57
+ ? "0.0.0.0"
58
+ : ((flags.host as string) ?? process.env.RPC_HOST ?? "127.0.0.1"),
59
+ );
46
60
  const rpcPort = Number(config.server.rpcPort || defaultConfig.server.rpcPort);
47
61
  const wsPort = Number(config.server.wsPort || rpcPort + 1);
48
62
  const guiEnabled = config.gui?.enabled !== false;
@@ -170,9 +170,10 @@ async function resolveTokens(selections: string[], existing: string[] = []) {
170
170
  const set = new Set(existing);
171
171
  for (const selection of selections) {
172
172
  if (selection === "__custom__") {
173
- (await collectCustomEntries("token mint address")).forEach((value) =>
174
- set.add(value),
175
- );
173
+ {
174
+ const values = await collectCustomEntries("token mint address");
175
+ for (const value of values) set.add(value);
176
+ }
176
177
  continue;
177
178
  }
178
179
  const preset = TOKEN_PRESETS.find((token) => token.value === selection);
@@ -193,9 +194,10 @@ async function resolvePrograms(selections: string[], existing: string[] = []) {
193
194
  const set = new Set(existing);
194
195
  for (const selection of selections) {
195
196
  if (selection === "__custom__") {
196
- (await collectCustomEntries("program id")).forEach((value) =>
197
- set.add(value),
198
- );
197
+ {
198
+ const values = await collectCustomEntries("program id");
199
+ for (const value of values) set.add(value);
200
+ }
199
201
  continue;
200
202
  }
201
203
  const preset = PROGRAM_PRESETS.find(