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.
- package/README.md +471 -79
- package/cli.cjs +106 -78
- package/package.json +1 -1
- package/scripts/install.sh +1 -1
- package/scripts/postinstall.cjs +69 -61
- package/server/lib/base58.ts +1 -1
- package/server/methods/account/get-account-info.ts +3 -7
- package/server/methods/account/get-balance.ts +3 -7
- package/server/methods/account/get-multiple-accounts.ts +2 -1
- package/server/methods/account/get-parsed-account-info.ts +3 -7
- package/server/methods/account/parsers/index.ts +2 -2
- package/server/methods/account/parsers/loader-upgradeable.ts +14 -1
- package/server/methods/account/parsers/spl-token.ts +29 -10
- package/server/methods/account/request-airdrop.ts +44 -31
- package/server/methods/block/get-block.ts +3 -7
- package/server/methods/block/get-blocks-with-limit.ts +3 -7
- package/server/methods/block/is-blockhash-valid.ts +3 -7
- package/server/methods/get-address-lookup-table.ts +3 -7
- package/server/methods/program/get-program-accounts.ts +9 -9
- package/server/methods/program/get-token-account-balance.ts +3 -7
- package/server/methods/program/get-token-accounts-by-delegate.ts +4 -3
- package/server/methods/program/get-token-accounts-by-owner.ts +61 -35
- package/server/methods/program/get-token-largest-accounts.ts +3 -2
- package/server/methods/program/get-token-supply.ts +3 -2
- package/server/methods/solforge/index.ts +9 -6
- package/server/methods/transaction/get-parsed-transaction.ts +3 -7
- package/server/methods/transaction/get-signature-statuses.ts +14 -7
- package/server/methods/transaction/get-signatures-for-address.ts +3 -7
- package/server/methods/transaction/get-transaction.ts +167 -81
- package/server/methods/transaction/send-transaction.ts +29 -16
- package/server/methods/transaction/simulate-transaction.ts +3 -2
- package/server/rpc-server.ts +47 -34
- package/server/types.ts +9 -6
- package/server/ws-server.ts +15 -8
- package/src/api-server-entry.ts +91 -91
- package/src/cli/commands/airdrop.ts +2 -2
- package/src/cli/commands/config.ts +2 -2
- package/src/cli/commands/mint.ts +3 -3
- package/src/cli/commands/program-clone.ts +9 -11
- package/src/cli/commands/program-load.ts +3 -3
- package/src/cli/commands/rpc-start.ts +8 -5
- package/src/cli/commands/token-adopt-authority.ts +1 -1
- package/src/cli/commands/token-clone.ts +5 -6
- package/src/cli/commands/token-create.ts +5 -5
- package/src/cli/main.ts +38 -37
- package/src/cli/run-solforge.ts +20 -6
- package/src/cli/setup-wizard.ts +8 -6
- package/src/commands/add-program.ts +324 -328
- package/src/commands/init.ts +106 -106
- package/src/commands/list.ts +125 -125
- package/src/commands/mint.ts +247 -248
- package/src/commands/start.ts +837 -833
- package/src/commands/status.ts +80 -80
- package/src/commands/stop.ts +381 -382
- package/src/config/index.ts +33 -17
- package/src/config/manager.ts +150 -150
- package/src/db/index.ts +2 -2
- package/src/db/tx-store.ts +12 -8
- package/src/gui/public/app.css +1556 -1
- package/src/gui/public/build/main.css +1569 -1
- package/src/gui/server.ts +21 -22
- package/src/gui/src/api.ts +1 -1
- package/src/gui/src/app.tsx +96 -45
- package/src/gui/src/components/airdrop-mint-form.tsx +49 -19
- package/src/gui/src/components/clone-program-modal.tsx +31 -12
- package/src/gui/src/components/clone-token-modal.tsx +32 -13
- package/src/gui/src/components/modal.tsx +18 -11
- package/src/gui/src/components/programs-panel.tsx +27 -15
- package/src/gui/src/components/status-panel.tsx +32 -18
- package/src/gui/src/components/tokens-panel.tsx +25 -19
- package/src/gui/src/index.css +491 -463
- package/src/index.ts +177 -149
- package/src/rpc/start.ts +1 -1
- package/src/services/api-server.ts +494 -475
- package/src/services/port-manager.ts +164 -167
- package/src/services/process-registry.ts +144 -145
- package/src/services/program-cloner.ts +312 -312
- package/src/services/token-cloner.ts +799 -797
- package/src/services/validator.ts +288 -290
- package/src/types/config.ts +72 -72
- package/src/utils/shell.ts +75 -75
- 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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
const vp = vendorPath();
|
|
63
|
+
if (!vp) return null;
|
|
64
|
+
if (fs.existsSync(vp)) return vp;
|
|
56
65
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
// Respect opt-out
|
|
67
|
+
if (
|
|
68
|
+
String(process.env.SOLFORGE_SKIP_DOWNLOAD || "").toLowerCase() === "true"
|
|
69
|
+
) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
61
72
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
116
|
-
|
|
141
|
+
process.exit(0);
|
|
142
|
+
}
|
|
117
143
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
package/scripts/install.sh
CHANGED
|
@@ -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.
|
|
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"
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -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
|
-
|
|
12
|
+
console.log(`[solforge] ${msg}`);
|
|
13
13
|
}
|
|
14
14
|
function warn(msg) {
|
|
15
|
-
|
|
15
|
+
console.warn(`[solforge] ${msg}`);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
if (String(process.env.SOLFORGE_SKIP_DOWNLOAD || "").toLowerCase() === "true") {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
log("Skipping binary download due to SOLFORGE_SKIP_DOWNLOAD=true");
|
|
20
|
+
process.exit(0);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
function assetName() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
60
|
-
|
|
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
|
-
|
|
66
|
-
|
|
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
|
-
|
|
77
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
package/server/lib/base58.ts
CHANGED
|
@@ -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 =
|
|
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:
|
|
83
|
-
|
|
84
|
-
|
|
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:
|
|
20
|
-
|
|
21
|
-
|
|
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:
|
|
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:
|
|
14
|
-
|
|
15
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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,
|
|
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,
|
|
190
|
+
const out: Array<Record<string, unknown>> = [];
|
|
184
191
|
for (const ext of types) {
|
|
185
|
-
const entry: Record<string,
|
|
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
|
|
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(
|
|
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
|
|
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,
|