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
package/cli.cjs CHANGED
@@ -9,90 +9,114 @@ const https = require("node:https");
9
9
  const { spawn } = require("node:child_process");
10
10
 
11
11
  function pkg() {
12
- // Resolve package.json next to this file regardless of install location
13
- const p = path.join(__dirname, "package.json");
14
- try { return require(p); } catch { return { version: "" }; }
12
+ // Resolve package.json next to this file regardless of install location
13
+ const p = path.join(__dirname, "package.json");
14
+ try {
15
+ return require(p);
16
+ } catch {
17
+ return { version: "" };
18
+ }
15
19
  }
16
20
 
17
21
  function assetName() {
18
- const p = process.platform;
19
- const a = process.arch;
20
- if (p === "darwin" && a === "arm64") return "solforge-darwin-arm64";
21
- if (p === "darwin" && a === "x64") return "solforge-darwin-x64";
22
- if (p === "linux" && a === "x64") return "solforge-linux-x64";
23
- if (p === "linux" && a === "arm64") return "solforge-linux-arm64";
24
- if (p === "win32" && a === "x64") return "solforge-windows-x64.exe";
25
- return null;
22
+ const p = process.platform;
23
+ const a = process.arch;
24
+ if (p === "darwin" && a === "arm64") return "solforge-darwin-arm64";
25
+ if (p === "darwin" && a === "x64") return "solforge-darwin-x64";
26
+ if (p === "linux" && a === "x64") return "solforge-linux-x64";
27
+ if (p === "linux" && a === "arm64") return "solforge-linux-arm64";
28
+ if (p === "win32" && a === "x64") return "solforge-windows-x64.exe";
29
+ return null;
26
30
  }
27
31
 
28
32
  function vendorPath() {
29
- const name = assetName();
30
- if (!name) return null;
31
- return path.join(__dirname, "vendor", name);
33
+ const name = assetName();
34
+ if (!name) return null;
35
+ return path.join(__dirname, "vendor", name);
32
36
  }
33
37
 
34
38
  function download(url, outPath) {
35
- return new Promise((resolve, reject) => {
36
- const req = https.get(url, (res) => {
37
- if ([301, 302, 307, 308].includes(res.statusCode) && res.headers.location) {
38
- return resolve(download(res.headers.location, outPath));
39
- }
40
- if (res.statusCode !== 200) {
41
- return reject(new Error(`HTTP ${res.statusCode}`));
42
- }
43
- const file = fs.createWriteStream(outPath, { mode: process.platform === "win32" ? undefined : 0o755 });
44
- res.pipe(file);
45
- file.on("finish", () => file.close(() => resolve()));
46
- file.on("error", reject);
47
- });
48
- req.on("error", reject);
49
- });
39
+ return new Promise((resolve, reject) => {
40
+ const req = https.get(url, (res) => {
41
+ if (
42
+ [301, 302, 307, 308].includes(res.statusCode) &&
43
+ res.headers.location
44
+ ) {
45
+ return resolve(download(res.headers.location, outPath));
46
+ }
47
+ if (res.statusCode !== 200) {
48
+ return reject(new Error(`HTTP ${res.statusCode}`));
49
+ }
50
+ const file = fs.createWriteStream(outPath, {
51
+ mode: process.platform === "win32" ? undefined : 0o755,
52
+ });
53
+ res.pipe(file);
54
+ file.on("finish", () => file.close(() => resolve()));
55
+ file.on("error", reject);
56
+ });
57
+ req.on("error", reject);
58
+ });
50
59
  }
51
60
 
52
61
  async function ensureBinary() {
53
- const vp = vendorPath();
54
- if (!vp) return null;
55
- if (fs.existsSync(vp)) return vp;
62
+ const vp = vendorPath();
63
+ if (!vp) return null;
64
+ if (fs.existsSync(vp)) return vp;
56
65
 
57
- // Respect opt-out
58
- if (String(process.env.SOLFORGE_SKIP_DOWNLOAD || "").toLowerCase() === "true") {
59
- return null;
60
- }
66
+ // Respect opt-out
67
+ if (
68
+ String(process.env.SOLFORGE_SKIP_DOWNLOAD || "").toLowerCase() === "true"
69
+ ) {
70
+ return null;
71
+ }
61
72
 
62
- const { version, repository } = pkg();
63
- const repo = process.env.SOLFORGE_REPO || (repository && (typeof repository === "string" ? repository.replace(/^github:/, "") : (repository.url && (repository.url.match(/github\.com[:/](.+?)\.git$/) || [])[1]))) || "nitishxyz/solforge";
64
- if (!version) return null;
65
- const asset = path.basename(vp);
66
- const url = `https://github.com/${repo}/releases/download/v${version}/${asset}`;
73
+ const { version, repository } = pkg();
74
+ const repo =
75
+ process.env.SOLFORGE_REPO ||
76
+ (repository &&
77
+ (typeof repository === "string"
78
+ ? repository.replace(/^github:/, "")
79
+ : repository.url &&
80
+ (repository.url.match(/github\.com[:/](.+?)\.git$/) || [])[1])) ||
81
+ "nitishxyz/solforge";
82
+ if (!version) return null;
83
+ const asset = path.basename(vp);
84
+ const url = `https://github.com/${repo}/releases/download/v${version}/${asset}`;
67
85
 
68
- try {
69
- fs.mkdirSync(path.dirname(vp), { recursive: true });
70
- await download(url, vp);
71
- if (process.platform !== "win32") {
72
- try { fs.chmodSync(vp, 0o755); } catch {}
73
- }
74
- return fs.existsSync(vp) ? vp : null;
75
- } catch {
76
- return null;
77
- }
86
+ try {
87
+ fs.mkdirSync(path.dirname(vp), { recursive: true });
88
+ await download(url, vp);
89
+ if (process.platform !== "win32") {
90
+ try {
91
+ fs.chmodSync(vp, 0o755);
92
+ } catch {}
93
+ }
94
+ return fs.existsSync(vp) ? vp : null;
95
+ } catch {
96
+ return null;
97
+ }
78
98
  }
79
99
 
80
100
  function run(cmd, args) {
81
- return new Promise((resolve) => {
82
- const child = spawn(cmd, args, { stdio: "inherit" });
83
- child.on("exit", (code) => resolve(typeof code === "number" ? code : 0));
84
- });
101
+ return new Promise((resolve) => {
102
+ const child = spawn(cmd, args, { stdio: "inherit" });
103
+ child.on("exit", (code) => resolve(typeof code === "number" ? code : 0));
104
+ });
85
105
  }
86
106
 
87
107
  (async () => {
88
- // Fast path for --version/--help without booting the app
89
- const args = process.argv.slice(2);
90
- if (args.includes("-v") || args.includes("--version") || args[0] === "version") {
91
- console.log(pkg().version || "");
92
- process.exit(0);
93
- }
94
- if (args.includes("-h") || args.includes("--help") || args[0] === "help") {
95
- console.log(`
108
+ // Fast path for --version/--help without booting the app
109
+ const args = process.argv.slice(2);
110
+ if (
111
+ args.includes("-v") ||
112
+ args.includes("--version") ||
113
+ args[0] === "version"
114
+ ) {
115
+ console.log(pkg().version || "");
116
+ process.exit(0);
117
+ }
118
+ if (args.includes("-h") || args.includes("--help") || args[0] === "help") {
119
+ console.log(`
96
120
  solforge <command>
97
121
 
98
122
  Commands:
@@ -111,21 +135,25 @@ Commands:
111
135
  Options:
112
136
  -h, --help Show help
113
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)
114
140
  `);
115
- process.exit(0);
116
- }
141
+ process.exit(0);
142
+ }
117
143
 
118
- const vp = await ensureBinary();
119
- if (vp) {
120
- const code = await run(vp, process.argv.slice(2));
121
- process.exit(code);
122
- }
123
- // Fallback: try to run TS entry via Bun
124
- const bun = process.env.SOLFORGE_BUN || "bun";
125
- const entry = path.join(__dirname, "src", "cli", "main.ts");
126
- const code = await run(bun, [entry, ...process.argv.slice(2)]);
127
- if (code !== 0) {
128
- console.error("solforge: failed to run binary and Bun fallback. Install Bun or ensure a release asset exists.");
129
- }
130
- process.exit(code);
144
+ const vp = await ensureBinary();
145
+ if (vp) {
146
+ const code = await run(vp, process.argv.slice(2));
147
+ process.exit(code);
148
+ }
149
+ // Fallback: try to run TS entry via Bun
150
+ const bun = process.env.SOLFORGE_BUN || "bun";
151
+ const entry = path.join(__dirname, "src", "cli", "main.ts");
152
+ const code = await run(bun, [entry, ...process.argv.slice(2)]);
153
+ if (code !== 0) {
154
+ console.error(
155
+ "solforge: failed to run binary and Bun fallback. Install Bun or ensure a release asset exists.",
156
+ );
157
+ }
158
+ process.exit(code);
131
159
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solforge",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "private": false,
@@ -3,7 +3,7 @@ set -e
3
3
 
4
4
  # SolForge installer (downloads GitHub release binary)
5
5
  # Usage: curl -fsSL https://sh.solforge.sh | sh
6
- # Optional: SOLFORGE_VERSION=v0.2.3 curl -fsSL https://sh.solforge.sh | sh
6
+ # Optional: SOLFORGE_VERSION=v0.2.5 curl -fsSL https://sh.solforge.sh | sh
7
7
 
8
8
  REPO="nitishxyz/solforge"
9
9
  BIN_NAME="solforge"
@@ -4,66 +4,67 @@
4
4
  - Skips if SOLFORGE_SKIP_DOWNLOAD=true
5
5
  - Falls back silently on errors (CLI will still work via Bun if installed)
6
6
  */
7
- const fs = require("fs");
8
- const path = require("path");
9
- const https = require("https");
7
+ const fs = require("node:fs");
8
+ const path = require("node:path");
9
+ const https = require("node:https");
10
10
 
11
11
  function log(msg) {
12
- console.log(`[solforge] ${msg}`);
12
+ console.log(`[solforge] ${msg}`);
13
13
  }
14
14
  function warn(msg) {
15
- console.warn(`[solforge] ${msg}`);
15
+ console.warn(`[solforge] ${msg}`);
16
16
  }
17
17
 
18
18
  if (String(process.env.SOLFORGE_SKIP_DOWNLOAD || "").toLowerCase() === "true") {
19
- log("Skipping binary download due to SOLFORGE_SKIP_DOWNLOAD=true");
20
- process.exit(0);
19
+ log("Skipping binary download due to SOLFORGE_SKIP_DOWNLOAD=true");
20
+ process.exit(0);
21
21
  }
22
22
 
23
23
  function assetName() {
24
- const p = process.platform;
25
- const a = process.arch;
26
- if (p === "darwin" && a === "arm64") return "solforge-darwin-arm64";
27
- if (p === "darwin" && a === "x64") return "solforge-darwin-x64";
28
- if (p === "linux" && a === "x64") return "solforge-linux-x64";
29
- if (p === "linux" && a === "arm64") return "solforge-linux-arm64";
30
- if (p === "win32" && a === "x64") return "solforge-windows-x64.exe";
31
- return null;
24
+ const p = process.platform;
25
+ const a = process.arch;
26
+ if (p === "darwin" && a === "arm64") return "solforge-darwin-arm64";
27
+ if (p === "darwin" && a === "x64") return "solforge-darwin-x64";
28
+ if (p === "linux" && a === "x64") return "solforge-linux-x64";
29
+ if (p === "linux" && a === "arm64") return "solforge-linux-arm64";
30
+ if (p === "win32" && a === "x64") return "solforge-windows-x64.exe";
31
+ return null;
32
32
  }
33
33
 
34
34
  function getRepo() {
35
- try {
36
- const pkg = require(path.join(__dirname, "..", "package.json"));
37
- if (pkg.repository) {
38
- if (typeof pkg.repository === "string") return pkg.repository.replace(/^github:/, "");
39
- if (pkg.repository.url) {
40
- const m = pkg.repository.url.match(/github\.com[:/](.+?)\.git$/);
41
- if (m) return m[1];
42
- }
43
- }
44
- } catch {}
45
- return process.env.SOLFORGE_REPO || "nitishxyz/solforge";
35
+ try {
36
+ const pkg = require(path.join(__dirname, "..", "package.json"));
37
+ if (pkg.repository) {
38
+ if (typeof pkg.repository === "string")
39
+ return pkg.repository.replace(/^github:/, "");
40
+ if (pkg.repository.url) {
41
+ const m = pkg.repository.url.match(/github\.com[:/](.+?)\.git$/);
42
+ if (m) return m[1];
43
+ }
44
+ }
45
+ } catch {}
46
+ return process.env.SOLFORGE_REPO || "nitishxyz/solforge";
46
47
  }
47
48
 
48
49
  function getVersion() {
49
- try {
50
- const pkg = require(path.join(__dirname, "..", "package.json"));
51
- return pkg.version;
52
- } catch {
53
- return process.env.npm_package_version || "";
54
- }
50
+ try {
51
+ const pkg = require(path.join(__dirname, "..", "package.json"));
52
+ return pkg.version;
53
+ } catch {
54
+ return process.env.npm_package_version || "";
55
+ }
55
56
  }
56
57
 
57
58
  const name = assetName();
58
59
  if (!name) {
59
- warn(`No prebuilt binary for ${process.platform}/${process.arch}; skipping`);
60
- process.exit(0);
60
+ warn(`No prebuilt binary for ${process.platform}/${process.arch}; skipping`);
61
+ process.exit(0);
61
62
  }
62
63
 
63
64
  const version = getVersion();
64
65
  if (!version) {
65
- warn("Unable to determine package version; skipping binary download");
66
- process.exit(0);
66
+ warn("Unable to determine package version; skipping binary download");
67
+ process.exit(0);
67
68
  }
68
69
 
69
70
  const repo = getRepo();
@@ -73,38 +74,45 @@ const vendorDir = path.join(__dirname, "..", "vendor");
73
74
  const outPath = path.join(vendorDir, name);
74
75
 
75
76
  if (fs.existsSync(outPath)) {
76
- log(`Binary already present at vendor/${name}`);
77
- process.exit(0);
77
+ log(`Binary already present at vendor/${name}`);
78
+ process.exit(0);
78
79
  }
79
80
 
80
81
  fs.mkdirSync(vendorDir, { recursive: true });
81
82
 
82
83
  function download(to, from, cb, redirects = 0) {
83
- const req = https.get(from, (res) => {
84
- if ([301, 302, 307, 308].includes(res.statusCode) && res.headers.location && redirects < 5) {
85
- return download(to, res.headers.location, cb, redirects + 1);
86
- }
87
- if (res.statusCode !== 200) {
88
- return cb(new Error(`HTTP ${res.statusCode} for ${from}`));
89
- }
90
- const file = fs.createWriteStream(to, { mode: 0o755 });
91
- res.pipe(file);
92
- file.on("finish", () => file.close(cb));
93
- });
94
- req.on("error", (err) => cb(err));
84
+ const req = https.get(from, (res) => {
85
+ if (
86
+ [301, 302, 307, 308].includes(res.statusCode) &&
87
+ res.headers.location &&
88
+ redirects < 5
89
+ ) {
90
+ return download(to, res.headers.location, cb, redirects + 1);
91
+ }
92
+ if (res.statusCode !== 200) {
93
+ return cb(new Error(`HTTP ${res.statusCode} for ${from}`));
94
+ }
95
+ const file = fs.createWriteStream(to, { mode: 0o755 });
96
+ res.pipe(file);
97
+ file.on("finish", () => file.close(cb));
98
+ });
99
+ req.on("error", (err) => cb(err));
95
100
  }
96
101
 
97
102
  log(`Fetching ${name} for v${version}...`);
98
103
  download(outPath, url, (err) => {
99
- if (err) {
100
- warn(`Could not download prebuilt binary: ${err.message}`);
101
- warn("CLI will fall back to running via Bun if available.");
102
- try { fs.unlinkSync(outPath); } catch {}
103
- process.exit(0);
104
- }
105
- if (process.platform !== "win32") {
106
- try { fs.chmodSync(outPath, 0o755); } catch {}
107
- }
108
- log(`Installed vendor/${name}`);
104
+ if (err) {
105
+ warn(`Could not download prebuilt binary: ${err.message}`);
106
+ warn("CLI will fall back to running via Bun if available.");
107
+ try {
108
+ fs.unlinkSync(outPath);
109
+ } catch {}
110
+ process.exit(0);
111
+ }
112
+ if (process.platform !== "win32") {
113
+ try {
114
+ fs.chmodSync(outPath, 0o755);
115
+ } catch {}
116
+ }
117
+ log(`Installed vendor/${name}`);
109
118
  });
110
-
@@ -12,7 +12,7 @@ export function encodeBase58(bytes: Uint8Array): string {
12
12
  encoded = ALPHABET[Number(remainder)] + encoded;
13
13
  }
14
14
  for (let i = 0; i < bytes.length && bytes[i] === 0; i++)
15
- encoded = "1" + encoded;
15
+ encoded = `1${encoded}`;
16
16
  return encoded || "1";
17
17
  }
18
18
 
@@ -79,12 +79,8 @@ export const getAccountInfo: RpcMethodHandler = async (id, params, context) => {
79
79
  context: { slot: Number(context.slot) },
80
80
  value: accountInfo,
81
81
  });
82
- } catch (error: any) {
83
- return context.createErrorResponse(
84
- id,
85
- -32602,
86
- "Invalid params",
87
- error.message,
88
- );
82
+ } catch (error: unknown) {
83
+ const message = error instanceof Error ? error.message : String(error);
84
+ return context.createErrorResponse(id, -32602, "Invalid params", message);
89
85
  }
90
86
  };
@@ -16,12 +16,8 @@ export const getBalance: RpcMethodHandler = (id, params, context) => {
16
16
  context: { slot: Number(context.slot) },
17
17
  value: Number(balance || 0n),
18
18
  });
19
- } catch (error: any) {
20
- return context.createErrorResponse(
21
- id,
22
- -32602,
23
- "Invalid params",
24
- error.message,
25
- );
19
+ } catch (error: unknown) {
20
+ const message = error instanceof Error ? error.message : String(error);
21
+ return context.createErrorResponse(id, -32602, "Invalid params", message);
26
22
  }
27
23
  };
@@ -1,5 +1,6 @@
1
1
  import { PublicKey } from "@solana/web3.js";
2
2
  import type { RpcMethodHandler } from "../../types";
3
+ import type { AccountSnapshot } from "../../../src/db/tx-store";
3
4
 
4
5
  /**
5
6
  * Implements the getMultipleAccounts RPC method
@@ -54,7 +55,7 @@ export const getMultipleAccounts: RpcMethodHandler = async (
54
55
 
55
56
  // Opportunistic index update
56
57
  try {
57
- const snaps: any[] = [];
58
+ const snaps: AccountSnapshot[] = [];
58
59
  for (const pubkeyStr of pubkeys) {
59
60
  try {
60
61
  const pubkey = new PublicKey(pubkeyStr);
@@ -10,12 +10,8 @@ export const getParsedAccountInfo: RpcMethodHandler = async (
10
10
  const cfg = { ...(config || {}), encoding: "jsonParsed" };
11
11
  try {
12
12
  return await getAccountInfo(id, [pubkey, cfg], context);
13
- } catch (error: any) {
14
- return context.createErrorResponse(
15
- id,
16
- -32603,
17
- "Internal error",
18
- error.message,
19
- );
13
+ } catch (error: unknown) {
14
+ const message = error instanceof Error ? error.message : String(error);
15
+ return context.createErrorResponse(id, -32603, "Internal error", message);
20
16
  }
21
17
  };
@@ -6,7 +6,7 @@ import { parseSystemAccount } from "./system";
6
6
 
7
7
  export type ParsedAccountData = {
8
8
  program: string;
9
- parsed: any; // match Solana RPC jsonParsed payloads
9
+ parsed: unknown; // match Solana RPC jsonParsed payloads
10
10
  space: number;
11
11
  } | null;
12
12
 
@@ -32,7 +32,7 @@ export function parseAccountJson(
32
32
  const dataBytes =
33
33
  account.data instanceof Uint8Array
34
34
  ? account.data
35
- : Buffer.from(account.data as any);
35
+ : Buffer.from(account.data as ReadonlyArray<number>);
36
36
  const space = dataBytes.length;
37
37
 
38
38
  // 1) System program
@@ -12,7 +12,20 @@ export function parseUpgradeableLoader(
12
12
  const bytes = data;
13
13
  const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
14
14
  const space = bytes.length;
15
- let parsed: any = null;
15
+ type UpgradeableParsed =
16
+ | { type: "program"; info: { programData: string } }
17
+ | {
18
+ type: "programData";
19
+ info: {
20
+ slot: number;
21
+ upgradeAuthority: string | null;
22
+ authority: string | null;
23
+ data: [string, "base64"];
24
+ };
25
+ }
26
+ | { type: "buffer"; info: { authority: string | null } }
27
+ | null;
28
+ let parsed: UpgradeableParsed = null;
16
29
  try {
17
30
  if (bytes.length >= 4) {
18
31
  const tag = dv.getUint32(0, true);
@@ -51,10 +51,17 @@ export function parseSplTokenAccountOrMint(
51
51
  try {
52
52
  const mintAcc = context.svm.getAccount(dec.mint);
53
53
  if (mintAcc) {
54
- const mintOwner =
55
- typeof (mintAcc as any).owner?.toBase58 === "function"
56
- ? ((mintAcc as any).owner as PublicKey)
57
- : new PublicKey(mintAcc.owner);
54
+ const rawOwner = (mintAcc as { owner?: unknown }).owner;
55
+ const mintOwner = ((): PublicKey => {
56
+ if (
57
+ rawOwner &&
58
+ typeof (rawOwner as { toBase58?: unknown }).toBase58 ===
59
+ "function"
60
+ ) {
61
+ return rawOwner as PublicKey;
62
+ }
63
+ return new PublicKey(String(rawOwner));
64
+ })();
58
65
  const mintProg = mintOwner.equals(TOKEN_2022_PROGRAM_ID)
59
66
  ? TOKEN_2022_PROGRAM_ID
60
67
  : TOKEN_PROGRAM_ID;
@@ -176,18 +183,18 @@ function buildAccountExtensions(account: {
176
183
 
177
184
  function buildMintExtensions(mint: {
178
185
  tlvData: Buffer;
179
- }): Array<Record<string, any>> | undefined {
186
+ }): Array<Record<string, unknown>> | undefined {
180
187
  if (!mint.tlvData || mint.tlvData.length === 0) return undefined;
181
188
  const types = getExtensionTypes(mint.tlvData);
182
189
  if (!types.length) return undefined;
183
- const out: Array<Record<string, any>> = [];
190
+ const out: Array<Record<string, unknown>> = [];
184
191
  for (const ext of types) {
185
- const entry: Record<string, any> = {
192
+ const entry: Record<string, unknown> = {
186
193
  type: ExtensionType[ext] ?? String(ext),
187
194
  };
188
195
  try {
189
196
  if (ext === ExtensionType.MetadataPointer) {
190
- const state = getMetadataPointerState(mint as any);
197
+ const state = getMetadataPointerState(mint as { tlvData: Buffer });
191
198
  if (state) {
192
199
  entry.info = {
193
200
  authority: state.authority ? state.authority.toBase58() : null,
@@ -222,9 +229,21 @@ function buildMintExtensions(mint: {
222
229
  return out.length ? out : undefined;
223
230
  }
224
231
 
225
- function toAccountInfo(raw: any, owner: PublicKey): AccountInfo<Buffer> {
232
+ function toAccountInfo(
233
+ raw: {
234
+ data?: Buffer | Uint8Array | number[];
235
+ lamports?: number | bigint;
236
+ executable?: boolean;
237
+ rentEpoch?: number | bigint;
238
+ },
239
+ owner: PublicKey,
240
+ ): AccountInfo<Buffer> {
226
241
  const data =
227
- raw.data instanceof Buffer ? raw.data : Buffer.from(raw.data ?? []);
242
+ raw.data instanceof Buffer
243
+ ? raw.data
244
+ : raw.data instanceof Uint8Array
245
+ ? Buffer.from(raw.data)
246
+ : Buffer.from((raw.data ?? []) as number[]);
228
247
  return {
229
248
  data,
230
249
  executable: !!raw.executable,