solforge 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.
Files changed (73) hide show
  1. package/package.json +1 -1
  2. package/scripts/postinstall.cjs +3 -3
  3. package/server/lib/base58.ts +1 -1
  4. package/server/methods/account/get-account-info.ts +3 -7
  5. package/server/methods/account/get-balance.ts +3 -7
  6. package/server/methods/account/get-multiple-accounts.ts +2 -1
  7. package/server/methods/account/get-parsed-account-info.ts +3 -7
  8. package/server/methods/account/parsers/index.ts +2 -2
  9. package/server/methods/account/parsers/loader-upgradeable.ts +14 -1
  10. package/server/methods/account/parsers/spl-token.ts +29 -10
  11. package/server/methods/account/request-airdrop.ts +44 -31
  12. package/server/methods/block/get-block.ts +3 -7
  13. package/server/methods/block/get-blocks-with-limit.ts +3 -7
  14. package/server/methods/block/is-blockhash-valid.ts +3 -7
  15. package/server/methods/get-address-lookup-table.ts +3 -7
  16. package/server/methods/program/get-program-accounts.ts +9 -9
  17. package/server/methods/program/get-token-account-balance.ts +3 -7
  18. package/server/methods/program/get-token-accounts-by-delegate.ts +4 -3
  19. package/server/methods/program/get-token-accounts-by-owner.ts +54 -33
  20. package/server/methods/program/get-token-largest-accounts.ts +3 -2
  21. package/server/methods/program/get-token-supply.ts +3 -2
  22. package/server/methods/solforge/index.ts +9 -6
  23. package/server/methods/transaction/get-parsed-transaction.ts +3 -7
  24. package/server/methods/transaction/get-signature-statuses.ts +14 -7
  25. package/server/methods/transaction/get-signatures-for-address.ts +3 -7
  26. package/server/methods/transaction/get-transaction.ts +167 -81
  27. package/server/methods/transaction/send-transaction.ts +29 -16
  28. package/server/methods/transaction/simulate-transaction.ts +3 -2
  29. package/server/rpc-server.ts +47 -34
  30. package/server/types.ts +9 -6
  31. package/server/ws-server.ts +11 -7
  32. package/src/api-server-entry.ts +5 -5
  33. package/src/cli/commands/airdrop.ts +2 -2
  34. package/src/cli/commands/config.ts +2 -2
  35. package/src/cli/commands/mint.ts +3 -3
  36. package/src/cli/commands/program-clone.ts +9 -11
  37. package/src/cli/commands/program-load.ts +3 -3
  38. package/src/cli/commands/rpc-start.ts +7 -7
  39. package/src/cli/commands/token-adopt-authority.ts +1 -1
  40. package/src/cli/commands/token-clone.ts +5 -6
  41. package/src/cli/commands/token-create.ts +5 -5
  42. package/src/cli/main.ts +33 -36
  43. package/src/cli/run-solforge.ts +3 -3
  44. package/src/cli/setup-wizard.ts +8 -6
  45. package/src/commands/add-program.ts +1 -1
  46. package/src/commands/init.ts +2 -2
  47. package/src/commands/mint.ts +5 -6
  48. package/src/commands/start.ts +10 -9
  49. package/src/commands/status.ts +1 -1
  50. package/src/commands/stop.ts +1 -1
  51. package/src/config/index.ts +33 -17
  52. package/src/config/manager.ts +3 -3
  53. package/src/db/index.ts +2 -2
  54. package/src/db/tx-store.ts +12 -8
  55. package/src/gui/public/app.css +13 -13
  56. package/src/gui/server.ts +1 -1
  57. package/src/gui/src/api.ts +1 -1
  58. package/src/gui/src/app.tsx +49 -17
  59. package/src/gui/src/components/airdrop-mint-form.tsx +32 -8
  60. package/src/gui/src/components/clone-program-modal.tsx +25 -6
  61. package/src/gui/src/components/clone-token-modal.tsx +25 -6
  62. package/src/gui/src/components/modal.tsx +6 -1
  63. package/src/gui/src/components/status-panel.tsx +1 -1
  64. package/src/index.ts +19 -6
  65. package/src/services/api-server.ts +41 -19
  66. package/src/services/port-manager.ts +7 -10
  67. package/src/services/process-registry.ts +4 -5
  68. package/src/services/program-cloner.ts +4 -4
  69. package/src/services/token-cloner.ts +4 -4
  70. package/src/services/validator.ts +2 -4
  71. package/src/types/config.ts +2 -2
  72. package/src/utils/shell.ts +1 -1
  73. package/src/utils/token-loader.ts +2 -2
@@ -45,12 +45,13 @@ export const simulateTransaction: RpcMethodHandler = (id, params, context) => {
45
45
  : null,
46
46
  },
47
47
  });
48
- } catch (error: any) {
48
+ } catch (error: unknown) {
49
+ const message = error instanceof Error ? error.message : String(error);
49
50
  return context.createErrorResponse(
50
51
  id,
51
52
  -32003,
52
53
  "Simulation failed",
53
- error.message,
54
+ message,
54
55
  );
55
56
  }
56
57
  };
@@ -35,8 +35,8 @@ export class LiteSVMRpcServer {
35
35
  blockTime?: number;
36
36
  preBalances?: number[];
37
37
  postBalances?: number[];
38
- preTokenBalances?: any[];
39
- postTokenBalances?: any[];
38
+ preTokenBalances?: unknown[];
39
+ postTokenBalances?: unknown[];
40
40
  }
41
41
  > = new Map();
42
42
  private store: TxStore;
@@ -95,7 +95,7 @@ export class LiteSVMRpcServer {
95
95
 
96
96
  private createSuccessResponse(
97
97
  id: string | number,
98
- result: any,
98
+ result: unknown,
99
99
  ): JsonRpcResponse {
100
100
  return {
101
101
  jsonrpc: "2.0",
@@ -108,7 +108,7 @@ export class LiteSVMRpcServer {
108
108
  id: string | number,
109
109
  code: number,
110
110
  message: string,
111
- data?: any,
111
+ data?: unknown,
112
112
  ): JsonRpcResponse {
113
113
  return {
114
114
  jsonrpc: "2.0",
@@ -132,7 +132,7 @@ export class LiteSVMRpcServer {
132
132
  },
133
133
  getFaucet: () => this.faucet,
134
134
  getTxCount: () => this.txCount,
135
- registerMint: (mint: any) => {
135
+ registerMint: (mint: PublicKey | string) => {
136
136
  try {
137
137
  const pk =
138
138
  typeof mint === "string" ? mint : new PublicKey(mint).toBase58();
@@ -140,7 +140,7 @@ export class LiteSVMRpcServer {
140
140
  } catch {}
141
141
  },
142
142
  listMints: () => Array.from(this.knownMints),
143
- registerProgram: (program: any) => {
143
+ registerProgram: (program: PublicKey | string) => {
144
144
  try {
145
145
  const pk =
146
146
  typeof program === "string"
@@ -160,19 +160,30 @@ export class LiteSVMRpcServer {
160
160
  blockTime: meta?.blockTime,
161
161
  preBalances: meta?.preBalances,
162
162
  postBalances: meta?.postBalances,
163
- preTokenBalances: (meta as any)?.preTokenBalances,
164
- postTokenBalances: (meta as any)?.postTokenBalances,
163
+ preTokenBalances: (
164
+ meta as { preTokenBalances?: unknown[] } | undefined
165
+ )?.preTokenBalances,
166
+ postTokenBalances: (
167
+ meta as { postTokenBalances?: unknown[] } | undefined
168
+ )?.postTokenBalances,
165
169
  });
166
170
 
167
171
  // Persist to SQLite for durability and history queries
168
172
  try {
169
- const msg: any = tx.message as any;
170
- const rawKeys: any[] = Array.isArray(msg.staticAccountKeys)
173
+ const msg = tx.message as unknown as {
174
+ staticAccountKeys?: unknown[];
175
+ accountKeys?: unknown[];
176
+ header?: unknown;
177
+ isAccountSigner?: (i: number) => boolean;
178
+ isAccountWritable?: (i: number) => boolean;
179
+ version?: number;
180
+ };
181
+ const rawKeys: unknown[] = Array.isArray(msg.staticAccountKeys)
171
182
  ? msg.staticAccountKeys
172
183
  : Array.isArray(msg.accountKeys)
173
184
  ? msg.accountKeys
174
185
  : [];
175
- const keys: string[] = rawKeys.map((k: any) => {
186
+ const keys: string[] = rawKeys.map((k) => {
176
187
  try {
177
188
  return typeof k === "string" ? k : (k as PublicKey).toBase58();
178
189
  } catch {
@@ -226,18 +237,24 @@ export class LiteSVMRpcServer {
226
237
  err: meta?.err ?? null,
227
238
  rawBase64,
228
239
  preBalances: Array.isArray(meta?.preBalances)
229
- ? meta!.preBalances!
240
+ ? (meta?.preBalances as number[])
230
241
  : [],
231
242
  postBalances: Array.isArray(meta?.postBalances)
232
- ? meta!.postBalances!
233
- : [],
234
- logs: Array.isArray(meta?.logs) ? meta!.logs! : [],
235
- preTokenBalances: Array.isArray((meta as any)?.preTokenBalances)
236
- ? (meta as any).preTokenBalances
237
- : [],
238
- postTokenBalances: Array.isArray((meta as any)?.postTokenBalances)
239
- ? (meta as any).postTokenBalances
243
+ ? (meta?.postBalances as number[])
240
244
  : [],
245
+ logs: Array.isArray(meta?.logs) ? (meta?.logs as string[]) : [],
246
+ preTokenBalances: (() => {
247
+ const arr = (
248
+ meta as { preTokenBalances?: unknown[] } | undefined
249
+ )?.preTokenBalances;
250
+ return Array.isArray(arr) ? arr : [];
251
+ })(),
252
+ postTokenBalances: (() => {
253
+ const arr = (
254
+ meta as { postTokenBalances?: unknown[] } | undefined
255
+ )?.postTokenBalances;
256
+ return Array.isArray(arr) ? arr : [];
257
+ })(),
241
258
  accounts,
242
259
  })
243
260
  .catch(() => {});
@@ -262,7 +279,7 @@ export class LiteSVMRpcServer {
262
279
  return null;
263
280
  }
264
281
  })
265
- .filter(Boolean) as any[];
282
+ .filter(Boolean) as import("../src/db/tx-store").AccountSnapshot[];
266
283
  if (snapshots.length > 0)
267
284
  this.store.upsertAccounts(snapshots).catch(() => {});
268
285
  } catch {}
@@ -302,7 +319,7 @@ export class LiteSVMRpcServer {
302
319
 
303
320
  getSignatureStatus(
304
321
  signature: string,
305
- ): { slot: number; err: any | null } | null {
322
+ ): { slot: number; err: unknown | null } | null {
306
323
  // Prefer local record for reliability
307
324
  const rec = this.txRecords.get(signature);
308
325
  if (rec) {
@@ -312,10 +329,10 @@ export class LiteSVMRpcServer {
312
329
  const sigBytes = decodeBase58(signature);
313
330
  const tx = this.svm.getTransaction(sigBytes);
314
331
  if (!tx) return null;
315
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
316
- let errVal: any = null;
332
+ let errVal: unknown = null;
317
333
  try {
318
- errVal = "err" in tx ? (tx as any).err() : null;
334
+ const raw = (tx as { err?: unknown }).err;
335
+ errVal = typeof raw === "function" ? (raw as () => unknown)() : raw;
319
336
  } catch {
320
337
  errVal = null;
321
338
  }
@@ -350,13 +367,9 @@ export class LiteSVMRpcServer {
350
367
  }
351
368
 
352
369
  return result;
353
- } catch (error: any) {
354
- return this.createErrorResponse(
355
- id,
356
- -32603,
357
- "Internal error",
358
- error.message,
359
- );
370
+ } catch (error: unknown) {
371
+ const message = error instanceof Error ? error.message : String(error);
372
+ return this.createErrorResponse(id, -32603, "Internal error", message);
360
373
  }
361
374
  }
362
375
  }
@@ -406,7 +419,7 @@ export function createLiteSVMRpcServer(port: number = 8899, host?: string) {
406
419
  try {
407
420
  console.log(
408
421
  "RPC batch:",
409
- body.map((b: any) => b.method),
422
+ body.map((b: { method?: string }) => b.method),
410
423
  );
411
424
  } catch {}
412
425
  }
@@ -432,7 +445,7 @@ export function createLiteSVMRpcServer(port: number = 8899, host?: string) {
432
445
  headers: { "Content-Type": "application/json", ...corsHeaders },
433
446
  });
434
447
  }
435
- } catch (error) {
448
+ } catch (_error) {
436
449
  return new Response(
437
450
  JSON.stringify({
438
451
  jsonrpc: "2.0",
package/server/types.ts CHANGED
@@ -6,17 +6,17 @@ export interface JsonRpcRequest {
6
6
  jsonrpc: "2.0";
7
7
  id: string | number;
8
8
  method: string;
9
- params?: any;
9
+ params?: unknown;
10
10
  }
11
11
 
12
12
  export interface JsonRpcResponse {
13
13
  jsonrpc: "2.0";
14
14
  id: string | number;
15
- result?: any;
15
+ result?: unknown;
16
16
  error?: {
17
17
  code: number;
18
18
  message: string;
19
- data?: any;
19
+ data?: unknown;
20
20
  };
21
21
  }
22
22
 
@@ -27,12 +27,15 @@ export interface RpcMethodContext {
27
27
  store?: TxStore;
28
28
  encodeBase58: (bytes: Uint8Array) => string;
29
29
  decodeBase58: (str: string) => Uint8Array;
30
- createSuccessResponse: (id: string | number, result: any) => JsonRpcResponse;
30
+ createSuccessResponse: (
31
+ id: string | number,
32
+ result: unknown,
33
+ ) => JsonRpcResponse;
31
34
  createErrorResponse: (
32
35
  id: string | number,
33
36
  code: number,
34
37
  message: string,
35
- data?: any,
38
+ data?: unknown,
36
39
  ) => JsonRpcResponse;
37
40
  notifySignature: (signature: string) => void;
38
41
  getFaucet: () => Keypair;
@@ -69,6 +72,6 @@ export interface RpcMethodContext {
69
72
 
70
73
  export type RpcMethodHandler = (
71
74
  id: string | number,
72
- params: any,
75
+ params: unknown[] | undefined,
73
76
  context: RpcMethodContext,
74
77
  ) => JsonRpcResponse | Promise<JsonRpcResponse>;
@@ -14,7 +14,11 @@ export function createLiteSVMWebSocketServer(
14
14
  const sockets = new Set<WebSocket>();
15
15
  const pendingChecks = new Map<string, number>();
16
16
 
17
- const sendSignatureNotification = (sig: string, slot: number, err: any) => {
17
+ const sendSignatureNotification = (
18
+ sig: string,
19
+ slot: number,
20
+ err: unknown,
21
+ ) => {
18
22
  const payload = {
19
23
  jsonrpc: "2.0",
20
24
  method: "signatureNotification",
@@ -25,14 +29,14 @@ export function createLiteSVMWebSocketServer(
25
29
  for (const [id, sub] of subs.entries()) {
26
30
  if (sub.type === "signature" && sub.signature === sig) {
27
31
  try {
28
- sockets.forEach((s) =>
32
+ for (const s of sockets) {
29
33
  s.send(
30
34
  JSON.stringify({
31
35
  ...payload,
32
36
  params: { ...payload.params, subscription: id },
33
37
  }),
34
- ),
35
- );
38
+ );
39
+ }
36
40
  } catch {}
37
41
  subs.delete(id);
38
42
  }
@@ -70,7 +74,7 @@ export function createLiteSVMWebSocketServer(
70
74
  port,
71
75
  hostname: host || process.env.RPC_HOST || "127.0.0.1",
72
76
  fetch(req, srv) {
73
- if (srv.upgrade(req)) return undefined as any;
77
+ if (srv.upgrade(req)) return undefined as unknown as Response;
74
78
  return new Response("Not a websocket", { status: 400 });
75
79
  },
76
80
  websocket: {
@@ -91,7 +95,7 @@ export function createLiteSVMWebSocketServer(
91
95
  id,
92
96
  method,
93
97
  params = [],
94
- } = msg as { id: number; method: string; params?: any[] };
98
+ } = msg as { id: number; method: string; params?: unknown[] };
95
99
  if (method === "signatureSubscribe") {
96
100
  const [signature] = params;
97
101
  const subId = nextSubId++;
@@ -147,7 +151,7 @@ export function createLiteSVMWebSocketServer(
147
151
  error: { code: -32601, message: `Method not found: ${method}` },
148
152
  }),
149
153
  );
150
- } catch (e) {
154
+ } catch (_e) {
151
155
  try {
152
156
  ws.send(
153
157
  JSON.stringify({
@@ -33,13 +33,13 @@ async function main() {
33
33
  process.exit(1);
34
34
  }
35
35
 
36
- const port = parseInt(args[portIndex + 1]!);
36
+ const port = parseInt(String(args[portIndex + 1]), 10);
37
37
  const host =
38
38
  hostIndex !== -1 && args[hostIndex + 1] ? args[hostIndex + 1] : undefined;
39
- const configPath = args[configIndex + 1]!;
40
- const rpcUrl = args[rpcIndex + 1]!;
41
- const faucetUrl = args[faucetIndex + 1]!;
42
- const workDir = args[workDirIndex + 1]!;
39
+ const configPath = String(args[configIndex + 1]);
40
+ const rpcUrl = String(args[rpcIndex + 1]);
41
+ const faucetUrl = String(args[faucetIndex + 1]);
42
+ const workDir = String(args[workDirIndex + 1]);
43
43
 
44
44
  // Load configuration
45
45
  await configManager.load(configPath);
@@ -4,8 +4,8 @@ import { parseFlags } from "../utils/args";
4
4
 
5
5
  export async function airdropCommand(args: string[]) {
6
6
  const { flags } = parseFlags(args);
7
- const to = String(flags["to"] || "");
8
- const sol = Number(flags["sol"] || 0);
7
+ const to = String(flags.to || "");
8
+ const sol = Number(flags.sol || 0);
9
9
  const cfg = await readConfig();
10
10
  const url = `http://localhost:${cfg.server.rpcPort}`;
11
11
  if (!to || !sol) {
@@ -11,7 +11,7 @@ export async function configCommand(sub: string | undefined, args: string[]) {
11
11
  switch (sub) {
12
12
  case "init": {
13
13
  const { flags } = parseFlags(args);
14
- const force = !!flags["force"];
14
+ const force = !!flags.force;
15
15
  await writeDefaultConfig({ force });
16
16
  p.log.success("Wrote sf.config.json");
17
17
  return;
@@ -28,7 +28,7 @@ export async function configCommand(sub: string | undefined, args: string[]) {
28
28
  const updated = setConfigValue(cfg, key, value);
29
29
  await Bun.write(
30
30
  "sf.config.json",
31
- JSON.stringify(updated, null, 2) + "\n",
31
+ `${JSON.stringify(updated, null, 2)}\n`,
32
32
  );
33
33
  p.log.success(`Updated ${key}`);
34
34
  return;
@@ -7,9 +7,9 @@ import { parseFlags } from "../utils/args";
7
7
  // Usage: solforge mint --mint <mint> --to <owner> --amount <amount>
8
8
  export async function mintCommand(args: string[]) {
9
9
  const { flags } = parseFlags(args);
10
- let mint = flags["mint"] as string | undefined;
11
- let receiver = flags["to"] as string | undefined; // required: receiver address (ATA owner)
12
- let amountBase = flags["amount"] as string | undefined; // optional direct base-units
10
+ let mint = flags.mint as string | undefined;
11
+ let receiver = flags.to as string | undefined; // required: receiver address (ATA owner)
12
+ let amountBase = flags.amount as string | undefined; // optional direct base-units
13
13
  let uiAmount = flags["ui-amount"] as string | undefined; // preferred UI units
14
14
 
15
15
  const cfg = await readConfig();
@@ -6,12 +6,12 @@ export async function programCloneCommand(args: string[]) {
6
6
  const { flags, rest } = parseFlags(args);
7
7
  const programId = (
8
8
  (rest[0] as string) ||
9
- (flags["program"] as string) ||
9
+ (flags.program as string) ||
10
10
  ""
11
11
  ).trim();
12
- const configPath = flags["config"] as string | undefined;
12
+ const configPath = flags.config as string | undefined;
13
13
  const cfg = await readConfig(configPath);
14
- const endpoint = (flags["endpoint"] as string) || cfg.clone.endpoint;
14
+ const endpoint = (flags.endpoint as string) || cfg.clone.endpoint;
15
15
  const withAccounts = !!flags["with-accounts"];
16
16
  const accountsLimit = flags["accounts-limit"]
17
17
  ? Number(flags["accounts-limit"])
@@ -56,16 +56,14 @@ export async function programAccountsCloneCommand(args: string[]) {
56
56
  const { flags, rest } = parseFlags(args);
57
57
  const programId = (
58
58
  (rest[0] as string) ||
59
- (flags["program"] as string) ||
59
+ (flags.program as string) ||
60
60
  ""
61
61
  ).trim();
62
- const configPath = flags["config"] as string | undefined;
62
+ const configPath = flags.config as string | undefined;
63
63
  const cfg = await readConfig(configPath);
64
- const endpoint = (flags["endpoint"] as string) || cfg.clone.endpoint;
65
- const limit = flags["limit"] ? Number(flags["limit"]) : undefined;
66
- const filters = flags["filters"]
67
- ? safeJson(flags["filters"] as string)
68
- : undefined;
64
+ const endpoint = (flags.endpoint as string) || cfg.clone.endpoint;
65
+ const limit = flags.limit ? Number(flags.limit) : undefined;
66
+ const filters = flags.filters ? safeJson(flags.filters as string) : undefined;
69
67
  if (!programId) {
70
68
  p.log.error(
71
69
  "Usage: solforge program accounts clone <programId> [--endpoint URL] [--limit N] [--filters JSON]",
@@ -97,7 +95,7 @@ export async function programAccountsCloneCommand(args: string[]) {
97
95
  }
98
96
  }
99
97
 
100
- function safeJson(s: string): any {
98
+ function safeJson(s: string): unknown {
101
99
  try {
102
100
  return JSON.parse(s);
103
101
  } catch {
@@ -5,9 +5,9 @@ import { parseFlags } from "../utils/args";
5
5
 
6
6
  export async function programLoadCommand(args: string[]) {
7
7
  const { flags, rest } = parseFlags(args);
8
- const programId = (rest[0] as string) || (flags["program"] as string);
9
- const fromFile = flags["file"] as string | undefined;
10
- const endpoint = flags["endpoint"] as string | undefined;
8
+ const programId = (rest[0] as string) || (flags.program as string);
9
+ const fromFile = flags.file as string | undefined;
10
+ const endpoint = flags.endpoint as string | undefined;
11
11
  if (!programId) {
12
12
  p.log.error(
13
13
  "Usage: solforge program load <programId> [--file PATH | --endpoint URL]",
@@ -5,13 +5,11 @@ import { parseFlags } from "../utils/args";
5
5
 
6
6
  export async function rpcStartCommand(args: string[]) {
7
7
  const { flags } = parseFlags(args);
8
- const cfg = await readConfig(flags["config"] as string | undefined);
9
- const rpcPort = Number(flags["port"] ?? cfg.server.rpcPort ?? 8899);
8
+ const cfg = await readConfig(flags.config as string | undefined);
9
+ const rpcPort = Number(flags.port ?? cfg.server.rpcPort ?? 8899);
10
10
  const wsPort = Number(flags["ws-port"] ?? cfg.server.wsPort ?? rpcPort + 1);
11
11
  const host =
12
- flags["network"] === true
13
- ? "0.0.0.0"
14
- : (flags["host"] as string) || "127.0.0.1";
12
+ flags.network === true ? "0.0.0.0" : (flags.host as string) || "127.0.0.1";
15
13
  const dbMode =
16
14
  (flags["db-mode"] as string) || cfg.server.db.mode || "ephemeral";
17
15
  const dbPath =
@@ -20,7 +18,7 @@ export async function rpcStartCommand(args: string[]) {
20
18
  const guiEnabled =
21
19
  flags["no-gui"] === true
22
20
  ? false
23
- : flags["gui"] === true
21
+ : flags.gui === true
24
22
  ? true
25
23
  : cfg.gui.enabled !== false;
26
24
 
@@ -28,10 +26,12 @@ export async function rpcStartCommand(args: string[]) {
28
26
  const guiMsg = guiEnabled ? `, GUI on ${guiPort}` : "";
29
27
  s.start(`Starting RPC on ${host}:${rpcPort}, WS on ${wsPort}${guiMsg}...`);
30
28
  try {
29
+ const mode: "ephemeral" | "persistent" =
30
+ dbMode === "persistent" ? "persistent" : "ephemeral";
31
31
  const started = startRpcServers({
32
32
  rpcPort,
33
33
  wsPort,
34
- dbMode: dbMode as any,
34
+ dbMode: mode,
35
35
  dbPath,
36
36
  host,
37
37
  guiEnabled,
@@ -5,7 +5,7 @@ import { parseFlags } from "../utils/args";
5
5
  // Set the faucet as mint authority for an existing mint in LiteSVM (local-only)
6
6
  export async function tokenAdoptAuthorityCommand(args: string[]) {
7
7
  const { flags, rest } = parseFlags(args);
8
- const mint = (rest[0] as string) || (flags["mint"] as string);
8
+ const mint = (rest[0] as string) || (flags.mint as string);
9
9
  if (!mint) {
10
10
  p.log.error("Usage: solforge token adopt-authority <mint>");
11
11
  return;
@@ -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,22 +26,22 @@ 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
- // Pass through any flags provided when no explicit command was given
33
- await runSolforge(raw);
34
- return;
35
- }
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
+ }
36
35
 
37
- if (cmd === "help" || cmd === "-h" || cmd === "--help") {
38
- printHelp();
39
- return;
40
- }
36
+ if (cmd === "help" || cmd === "-h" || cmd === "--help") {
37
+ printHelp();
38
+ return;
39
+ }
41
40
 
42
- if (cmd === "version" || cmd === "-v" || cmd === "--version") {
43
- printVersion();
44
- return;
45
- }
41
+ if (cmd === "version" || cmd === "-v" || cmd === "--version") {
42
+ printVersion();
43
+ return;
44
+ }
46
45
 
47
46
  // Alias: solforge start -> solforge rpc start
48
47
  if (cmd === "start") {
@@ -117,7 +116,7 @@ async function main() {
117
116
  }
118
117
 
119
118
  function printHelp() {
120
- console.log(`
119
+ console.log(`
121
120
  solforge <command>
122
121
 
123
122
  Commands:
@@ -142,14 +141,12 @@ Options:
142
141
  }
143
142
 
144
143
  async function unknownCommand(parts: (string | undefined)[]) {
145
- p.log.error(`Unknown command: ${parts.filter(Boolean).join(" ")}`);
146
- printHelp();
144
+ p.log.error(`Unknown command: ${parts.filter(Boolean).join(" ")}`);
145
+ printHelp();
147
146
  }
148
147
 
149
148
  function printVersion() {
150
- // Prefer package.json version if available
151
- const v = (pkg as any)?.version ?? "";
152
- console.log(String(v));
149
+ console.log(String(VERSION));
153
150
  }
154
151
 
155
152
  main();
@@ -15,7 +15,7 @@ const CONFIG_PATH = "sf.config.json";
15
15
 
16
16
  export async function runSolforge(args: string[] = []) {
17
17
  const { flags } = parseFlags(args);
18
- const ci = flags["ci"] === true || flags["y"] === true;
18
+ const ci = flags.ci === true || flags.y === true;
19
19
  const config = await ensureConfig(ci);
20
20
  await startWithConfig(config, args);
21
21
  }
@@ -53,9 +53,9 @@ async function ensureConfig(ci = false): Promise<SolforgeConfig> {
53
53
  async function startWithConfig(config: SolforgeConfig, args: string[] = []) {
54
54
  const { flags } = parseFlags(args);
55
55
  const host = String(
56
- flags["network"] === true
56
+ flags.network === true
57
57
  ? "0.0.0.0"
58
- : ((flags["host"] as string) ?? process.env.RPC_HOST ?? "127.0.0.1"),
58
+ : ((flags.host as string) ?? process.env.RPC_HOST ?? "127.0.0.1"),
59
59
  );
60
60
  const rpcPort = Number(config.server.rpcPort || defaultConfig.server.rpcPort);
61
61
  const wsPort = Number(config.server.wsPort || rpcPort + 1);