solforge 0.2.12 → 0.2.14

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 (175) hide show
  1. package/package.json +1 -5
  2. package/start.cjs +19 -23
  3. package/docs/API.md +0 -379
  4. package/docs/CONFIGURATION.md +0 -407
  5. package/docs/bun-single-file-executable.md +0 -585
  6. package/docs/cli-plan.md +0 -154
  7. package/docs/data-indexing-plan.md +0 -214
  8. package/docs/gui-roadmap.md +0 -202
  9. package/scripts/decode-b58.ts +0 -10
  10. package/scripts/install.sh +0 -112
  11. package/server/index.ts +0 -5
  12. package/server/lib/base58.ts +0 -33
  13. package/server/lib/faucet.ts +0 -110
  14. package/server/lib/instruction-parser.ts +0 -328
  15. package/server/lib/parsers/spl-associated-token-account.ts +0 -50
  16. package/server/lib/parsers/spl-token.ts +0 -340
  17. package/server/lib/spl-token.ts +0 -57
  18. package/server/methods/TEMPLATE.md +0 -117
  19. package/server/methods/account/get-account-info.ts +0 -86
  20. package/server/methods/account/get-balance.ts +0 -23
  21. package/server/methods/account/get-multiple-accounts.ts +0 -84
  22. package/server/methods/account/get-parsed-account-info.ts +0 -17
  23. package/server/methods/account/index.ts +0 -12
  24. package/server/methods/account/parsers/index.ts +0 -52
  25. package/server/methods/account/parsers/loader-upgradeable.ts +0 -79
  26. package/server/methods/account/parsers/spl-token.ts +0 -256
  27. package/server/methods/account/parsers/system.ts +0 -4
  28. package/server/methods/account/request-airdrop.ts +0 -271
  29. package/server/methods/admin/adopt-mint-authority.ts +0 -94
  30. package/server/methods/admin/clone-program-accounts.ts +0 -55
  31. package/server/methods/admin/clone-program.ts +0 -152
  32. package/server/methods/admin/clone-token-accounts.ts +0 -117
  33. package/server/methods/admin/clone-token-mint.ts +0 -82
  34. package/server/methods/admin/create-mint.ts +0 -114
  35. package/server/methods/admin/create-token-account.ts +0 -137
  36. package/server/methods/admin/helpers.ts +0 -70
  37. package/server/methods/admin/index.ts +0 -10
  38. package/server/methods/admin/list-mints.ts +0 -21
  39. package/server/methods/admin/load-program.ts +0 -52
  40. package/server/methods/admin/mint-to.ts +0 -266
  41. package/server/methods/block/get-block-height.ts +0 -5
  42. package/server/methods/block/get-block.ts +0 -31
  43. package/server/methods/block/get-blocks-with-limit.ts +0 -19
  44. package/server/methods/block/get-latest-blockhash.ts +0 -12
  45. package/server/methods/block/get-slot.ts +0 -5
  46. package/server/methods/block/index.ts +0 -6
  47. package/server/methods/block/is-blockhash-valid.ts +0 -19
  48. package/server/methods/epoch/get-cluster-nodes.ts +0 -17
  49. package/server/methods/epoch/get-epoch-info.ts +0 -16
  50. package/server/methods/epoch/get-epoch-schedule.ts +0 -15
  51. package/server/methods/epoch/get-highest-snapshot-slot.ts +0 -9
  52. package/server/methods/epoch/get-leader-schedule.ts +0 -8
  53. package/server/methods/epoch/get-max-retransmit-slot.ts +0 -9
  54. package/server/methods/epoch/get-max-shred-insert-slot.ts +0 -9
  55. package/server/methods/epoch/get-slot-leader.ts +0 -6
  56. package/server/methods/epoch/get-slot-leaders.ts +0 -9
  57. package/server/methods/epoch/get-stake-activation.ts +0 -9
  58. package/server/methods/epoch/get-stake-minimum-delegation.ts +0 -9
  59. package/server/methods/epoch/get-vote-accounts.ts +0 -19
  60. package/server/methods/epoch/index.ts +0 -13
  61. package/server/methods/epoch/minimum-ledger-slot.ts +0 -5
  62. package/server/methods/fee/get-fee-calculator-for-blockhash.ts +0 -12
  63. package/server/methods/fee/get-fee-for-message.ts +0 -8
  64. package/server/methods/fee/get-fee-rate-governor.ts +0 -16
  65. package/server/methods/fee/get-fees.ts +0 -14
  66. package/server/methods/fee/get-recent-prioritization-fees.ts +0 -22
  67. package/server/methods/fee/index.ts +0 -5
  68. package/server/methods/get-address-lookup-table.ts +0 -27
  69. package/server/methods/index.ts +0 -265
  70. package/server/methods/performance/get-recent-performance-samples.ts +0 -25
  71. package/server/methods/performance/get-transaction-count.ts +0 -5
  72. package/server/methods/performance/index.ts +0 -2
  73. package/server/methods/program/get-block-commitment.ts +0 -9
  74. package/server/methods/program/get-block-production.ts +0 -14
  75. package/server/methods/program/get-block-time.ts +0 -21
  76. package/server/methods/program/get-blocks.ts +0 -11
  77. package/server/methods/program/get-first-available-block.ts +0 -9
  78. package/server/methods/program/get-genesis-hash.ts +0 -6
  79. package/server/methods/program/get-identity.ts +0 -6
  80. package/server/methods/program/get-inflation-governor.ts +0 -15
  81. package/server/methods/program/get-inflation-rate.ts +0 -10
  82. package/server/methods/program/get-inflation-reward.ts +0 -12
  83. package/server/methods/program/get-largest-accounts.ts +0 -8
  84. package/server/methods/program/get-parsed-program-accounts.ts +0 -12
  85. package/server/methods/program/get-parsed-token-accounts-by-delegate.ts +0 -12
  86. package/server/methods/program/get-parsed-token-accounts-by-owner.ts +0 -12
  87. package/server/methods/program/get-program-accounts.ts +0 -221
  88. package/server/methods/program/get-supply.ts +0 -13
  89. package/server/methods/program/get-token-account-balance.ts +0 -60
  90. package/server/methods/program/get-token-accounts-by-delegate.ts +0 -82
  91. package/server/methods/program/get-token-accounts-by-owner.ts +0 -416
  92. package/server/methods/program/get-token-largest-accounts.ts +0 -81
  93. package/server/methods/program/get-token-supply.ts +0 -39
  94. package/server/methods/program/index.ts +0 -21
  95. package/server/methods/solforge/index.ts +0 -158
  96. package/server/methods/system/get-health.ts +0 -5
  97. package/server/methods/system/get-minimum-balance-for-rent-exemption.ts +0 -13
  98. package/server/methods/system/get-version.ts +0 -9
  99. package/server/methods/system/index.ts +0 -3
  100. package/server/methods/transaction/get-confirmed-transaction.ts +0 -11
  101. package/server/methods/transaction/get-parsed-transaction.ts +0 -17
  102. package/server/methods/transaction/get-signature-statuses.ts +0 -79
  103. package/server/methods/transaction/get-signatures-for-address.ts +0 -41
  104. package/server/methods/transaction/get-transaction.ts +0 -639
  105. package/server/methods/transaction/index.ts +0 -7
  106. package/server/methods/transaction/inner-instructions.test.ts +0 -104
  107. package/server/methods/transaction/send-transaction.ts +0 -469
  108. package/server/methods/transaction/simulate-transaction.ts +0 -57
  109. package/server/rpc-server.ts +0 -521
  110. package/server/types.ts +0 -109
  111. package/server/ws-server.ts +0 -178
  112. package/src/api-server-entry.ts +0 -109
  113. package/src/cli/bootstrap.ts +0 -67
  114. package/src/cli/commands/airdrop.ts +0 -37
  115. package/src/cli/commands/config.ts +0 -39
  116. package/src/cli/commands/mint.ts +0 -187
  117. package/src/cli/commands/program-clone.ts +0 -122
  118. package/src/cli/commands/program-load.ts +0 -64
  119. package/src/cli/commands/rpc-start.ts +0 -49
  120. package/src/cli/commands/token-adopt-authority.ts +0 -37
  121. package/src/cli/commands/token-clone.ts +0 -112
  122. package/src/cli/commands/token-create.ts +0 -81
  123. package/src/cli/main.ts +0 -158
  124. package/src/cli/run-solforge.ts +0 -112
  125. package/src/cli/setup-utils.ts +0 -54
  126. package/src/cli/setup-wizard.ts +0 -258
  127. package/src/cli/utils/args.ts +0 -15
  128. package/src/commands/add-program.ts +0 -333
  129. package/src/commands/init.ts +0 -122
  130. package/src/commands/list.ts +0 -136
  131. package/src/commands/mint.ts +0 -287
  132. package/src/commands/start.ts +0 -881
  133. package/src/commands/status.ts +0 -99
  134. package/src/commands/stop.ts +0 -405
  135. package/src/config/index.ts +0 -146
  136. package/src/config/manager.ts +0 -157
  137. package/src/db/index.ts +0 -83
  138. package/src/db/schema/accounts.ts +0 -23
  139. package/src/db/schema/address-signatures.ts +0 -31
  140. package/src/db/schema/index.ts +0 -6
  141. package/src/db/schema/meta-kv.ts +0 -9
  142. package/src/db/schema/transactions.ts +0 -36
  143. package/src/db/schema/tx-account-states.ts +0 -23
  144. package/src/db/schema/tx-accounts.ts +0 -33
  145. package/src/db/tx-store.ts +0 -264
  146. package/src/gui/public/app.css +0 -1556
  147. package/src/gui/public/build/main.css +0 -1569
  148. package/src/gui/public/build/main.js +0 -303
  149. package/src/gui/public/build/main.js.txt +0 -231
  150. package/src/gui/public/index.html +0 -19
  151. package/src/gui/server.ts +0 -296
  152. package/src/gui/src/api.ts +0 -127
  153. package/src/gui/src/app.tsx +0 -441
  154. package/src/gui/src/components/airdrop-mint-form.tsx +0 -246
  155. package/src/gui/src/components/clone-program-modal.tsx +0 -202
  156. package/src/gui/src/components/clone-token-modal.tsx +0 -230
  157. package/src/gui/src/components/modal.tsx +0 -134
  158. package/src/gui/src/components/programs-panel.tsx +0 -124
  159. package/src/gui/src/components/status-panel.tsx +0 -136
  160. package/src/gui/src/components/tokens-panel.tsx +0 -122
  161. package/src/gui/src/hooks/use-interval.ts +0 -17
  162. package/src/gui/src/index.css +0 -557
  163. package/src/gui/src/main.tsx +0 -17
  164. package/src/index.ts +0 -216
  165. package/src/migrations-bundled.ts +0 -23
  166. package/src/rpc/start.ts +0 -44
  167. package/src/services/api-server.ts +0 -504
  168. package/src/services/port-manager.ts +0 -174
  169. package/src/services/process-registry.ts +0 -153
  170. package/src/services/program-cloner.ts +0 -317
  171. package/src/services/token-cloner.ts +0 -811
  172. package/src/services/validator.ts +0 -293
  173. package/src/types/config.ts +0 -110
  174. package/src/utils/shell.ts +0 -110
  175. package/src/utils/token-loader.ts +0 -115
@@ -1,178 +0,0 @@
1
- import type { Server } from "bun";
2
- import type { LiteSVMRpcServer } from "./rpc-server";
3
-
4
- type Sub = { id: number; type: "signature"; signature: string };
5
-
6
- export function createLiteSVMWebSocketServer(
7
- rpcServer: LiteSVMRpcServer,
8
- port: number = 8900,
9
- host?: string,
10
- ) {
11
- let nextSubId = 1;
12
- const subs = new Map<number, Sub>();
13
-
14
- const sockets = new Set<WebSocket>();
15
- const pendingChecks = new Map<string, number>();
16
-
17
- const sendSignatureNotification = (
18
- sig: string,
19
- slot: number,
20
- err: unknown,
21
- ) => {
22
- const payload = {
23
- jsonrpc: "2.0",
24
- method: "signatureNotification",
25
- params: {
26
- result: { context: { slot }, value: { err } },
27
- },
28
- } as const;
29
- for (const [id, sub] of subs.entries()) {
30
- if (sub.type === "signature" && sub.signature === sig) {
31
- try {
32
- for (const s of sockets) {
33
- s.send(
34
- JSON.stringify({
35
- ...payload,
36
- params: { ...payload.params, subscription: id },
37
- }),
38
- );
39
- }
40
- } catch {}
41
- subs.delete(id);
42
- }
43
- }
44
- };
45
-
46
- const scheduleSignatureCheck = (sig: string) => {
47
- if (pendingChecks.has(sig)) return;
48
- pendingChecks.set(sig, 0);
49
- const tick = () => {
50
- const tries = (pendingChecks.get(sig) ?? 0) + 1;
51
- pendingChecks.set(sig, tries);
52
- const status = rpcServer.getSignatureStatus(sig);
53
- if (status) {
54
- pendingChecks.delete(sig);
55
- sendSignatureNotification(sig, status.slot, status.err);
56
- return;
57
- }
58
- if (tries < 60) {
59
- setTimeout(tick, 25);
60
- } else {
61
- pendingChecks.delete(sig);
62
- }
63
- };
64
- setTimeout(tick, 10);
65
- };
66
-
67
- const notifySignature = (sig: string) => {
68
- scheduleSignatureCheck(sig);
69
- };
70
-
71
- const unsubscribe = rpcServer.onSignatureRecorded(notifySignature);
72
-
73
- const server: Server = Bun.serve({
74
- port,
75
- hostname: host || process.env.RPC_HOST || "127.0.0.1",
76
- fetch(req, srv) {
77
- if (srv.upgrade(req)) return undefined as unknown as Response;
78
- return new Response("Not a websocket", { status: 400 });
79
- },
80
- websocket: {
81
- open(ws) {
82
- sockets.add(ws);
83
- },
84
- close(ws) {
85
- sockets.delete(ws);
86
- },
87
- message(ws, data) {
88
- try {
89
- const msg = JSON.parse(
90
- typeof data === "string"
91
- ? data
92
- : Buffer.from(data as ArrayBuffer).toString("utf8"),
93
- );
94
- const {
95
- id,
96
- method,
97
- params = [],
98
- } = msg as { id: number; method: string; params?: unknown[] };
99
- if (method === "signatureSubscribe") {
100
- const [signature] = params;
101
- const subId = nextSubId++;
102
- subs.set(subId, { id: subId, type: "signature", signature });
103
- // Respond with subscription id
104
- ws.send(JSON.stringify({ jsonrpc: "2.0", id, result: subId }));
105
- // If already have a status, notify immediately
106
- const status = rpcServer.getSignatureStatus(signature);
107
- if (status) {
108
- ws.send(
109
- JSON.stringify({
110
- jsonrpc: "2.0",
111
- method: "signatureNotification",
112
- params: {
113
- result: {
114
- context: { slot: status.slot },
115
- value: { err: status.err },
116
- },
117
- subscription: subId,
118
- },
119
- }),
120
- );
121
- subs.delete(subId);
122
- }
123
- return;
124
- }
125
- if (method === "signatureUnsubscribe") {
126
- const [subId] = params;
127
- subs.delete(subId);
128
- ws.send(JSON.stringify({ jsonrpc: "2.0", id, result: true }));
129
- return;
130
- }
131
- // Stub other subs to succeed without notifications
132
- if (
133
- method === "logsSubscribe" ||
134
- method === "slotSubscribe" ||
135
- method === "programSubscribe" ||
136
- method === "blockSubscribe"
137
- ) {
138
- const subId = nextSubId++;
139
- ws.send(JSON.stringify({ jsonrpc: "2.0", id, result: subId }));
140
- return;
141
- }
142
- if (method === "ping") {
143
- ws.send(JSON.stringify({ jsonrpc: "2.0", id, result: null }));
144
- return;
145
- }
146
- // Method not found (ws)
147
- ws.send(
148
- JSON.stringify({
149
- jsonrpc: "2.0",
150
- id,
151
- error: { code: -32601, message: `Method not found: ${method}` },
152
- }),
153
- );
154
- } catch (_e) {
155
- try {
156
- ws.send(
157
- JSON.stringify({
158
- jsonrpc: "2.0",
159
- id: null,
160
- error: { code: -32700, message: "Parse error" },
161
- }),
162
- );
163
- } catch {}
164
- }
165
- },
166
- },
167
- });
168
-
169
- const hostname = (host || process.env.RPC_HOST || "127.0.0.1").toString();
170
- console.log(`📣 LiteSVM RPC PubSub running on ws://${hostname}:${port}`);
171
- return {
172
- wsServer: server,
173
- stop: () => {
174
- unsubscribe();
175
- server.stop(true);
176
- },
177
- };
178
- }
@@ -1,109 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import chalk from "chalk";
4
- import { configManager } from "./config/manager.js";
5
- import { APIServer } from "./services/api-server.js";
6
-
7
- async function main() {
8
- try {
9
- // Parse command line arguments
10
- const args = process.argv.slice(2);
11
- const portIndex = args.indexOf("--port");
12
- const hostIndex = args.indexOf("--host");
13
- const configIndex = args.indexOf("--config");
14
- const rpcIndex = args.indexOf("--rpc-url");
15
- const faucetIndex = args.indexOf("--faucet-url");
16
- const workDirIndex = args.indexOf("--work-dir");
17
-
18
- if (
19
- portIndex === -1 ||
20
- configIndex === -1 ||
21
- rpcIndex === -1 ||
22
- faucetIndex === -1 ||
23
- workDirIndex === -1 ||
24
- !args[portIndex + 1] ||
25
- !args[configIndex + 1] ||
26
- !args[rpcIndex + 1] ||
27
- !args[faucetIndex + 1] ||
28
- !args[workDirIndex + 1]
29
- ) {
30
- console.error(
31
- "Usage: api-server-entry --port <port> --config <config-path> --rpc-url <url> --faucet-url <url> --work-dir <dir> [--host <host>]",
32
- );
33
- process.exit(1);
34
- }
35
-
36
- const port = parseInt(String(args[portIndex + 1]), 10);
37
- const host =
38
- hostIndex !== -1 && args[hostIndex + 1] ? args[hostIndex + 1] : undefined;
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
-
44
- // Load configuration
45
- await configManager.load(configPath);
46
- const config = configManager.getConfig();
47
-
48
- // Create and start API server
49
- const apiServer = new APIServer({
50
- port,
51
- host,
52
- validatorRpcUrl: rpcUrl,
53
- validatorFaucetUrl: faucetUrl,
54
- config,
55
- workDir,
56
- });
57
-
58
- const result = await apiServer.start();
59
-
60
- if (result.success) {
61
- console.log(chalk.green(`🚀 API Server started on port ${port}`));
62
-
63
- // Keep the process alive
64
- process.on("SIGTERM", async () => {
65
- console.log(
66
- chalk.yellow("📡 API Server received SIGTERM, shutting down..."),
67
- );
68
- await apiServer.stop();
69
- process.exit(0);
70
- });
71
-
72
- process.on("SIGINT", async () => {
73
- console.log(
74
- chalk.yellow("📡 API Server received SIGINT, shutting down..."),
75
- );
76
- await apiServer.stop();
77
- process.exit(0);
78
- });
79
-
80
- // Keep process alive
81
- setInterval(() => {}, 1000);
82
- } else {
83
- console.error(
84
- chalk.red(`❌ Failed to start API server: ${result.error}`),
85
- );
86
- process.exit(1);
87
- }
88
- } catch (error) {
89
- console.error(
90
- chalk.red(
91
- `❌ API Server error: ${
92
- error instanceof Error ? error.message : String(error)
93
- }`,
94
- ),
95
- );
96
- process.exit(1);
97
- }
98
- }
99
-
100
- main().catch((error) => {
101
- console.error(
102
- chalk.red(
103
- `❌ Fatal error: ${
104
- error instanceof Error ? error.message : String(error)
105
- }`,
106
- ),
107
- );
108
- process.exit(1);
109
- });
@@ -1,67 +0,0 @@
1
- import * as p from "@clack/prompts";
2
- import { defaultConfig, type SolforgeConfig } from "../config";
3
-
4
- export async function bootstrapEnvironment(
5
- config: SolforgeConfig,
6
- host: string,
7
- rpcPort: number,
8
- ) {
9
- const url = `http://${host}:${rpcPort}`;
10
- const endpoint = config.clone.endpoint || defaultConfig.clone.endpoint;
11
-
12
- for (const mint of config.clone.tokens || []) {
13
- await withSpinner(`Cloning token ${mint}`, async () => {
14
- await callRpc(url, "solforgeAdminCloneTokenMint", [mint, { endpoint }]);
15
- await callRpc(url, "solforgeAdoptMintAuthority", [mint]);
16
- });
17
- }
18
-
19
- for (const programId of config.clone.programs || []) {
20
- await withSpinner(`Cloning program ${programId}`, async () => {
21
- await callRpc(url, "solforgeAdminCloneProgram", [
22
- programId,
23
- { endpoint },
24
- ]);
25
- });
26
- }
27
-
28
- for (const { address, amountSol } of config.bootstrap?.airdrops || []) {
29
- await withSpinner(
30
- `Airdropping ${amountSol} SOL to ${address}`,
31
- async () => {
32
- const lamports = Math.round(amountSol * 1_000_000_000);
33
- await callRpc(url, "requestAirdrop", [address, lamports]);
34
- },
35
- );
36
- }
37
- }
38
-
39
- async function withSpinner(task: string, action: () => Promise<void>) {
40
- const spin = p.spinner();
41
- spin.start(`${task}...`);
42
- try {
43
- await action();
44
- spin.stop(`${task} done`);
45
- } catch (error) {
46
- spin.stop(`${task} failed`);
47
- p.log.error(String(error));
48
- }
49
- }
50
-
51
- async function callRpc(url: string, method: string, params: unknown[]) {
52
- const res = await fetch(url, {
53
- method: "POST",
54
- headers: { "content-type": "application/json" },
55
- body: JSON.stringify({ jsonrpc: "2.0", id: Date.now(), method, params }),
56
- });
57
- if (!res.ok) throw new Error(`${method} HTTP ${res.status}`);
58
- const json = await res.json();
59
- if (json?.error) {
60
- const message = json.error?.message || `${method} failed`;
61
- const detail = json.error?.data
62
- ? `: ${JSON.stringify(json.error.data)}`
63
- : "";
64
- throw new Error(message + detail);
65
- }
66
- return json.result;
67
- }
@@ -1,37 +0,0 @@
1
- import * as p from "@clack/prompts";
2
- import { readConfig } from "../../config";
3
- import { parseFlags } from "../utils/args";
4
-
5
- export async function airdropCommand(args: string[]) {
6
- const { flags } = parseFlags(args);
7
- const to = String(flags.to || "");
8
- const sol = Number(flags.sol || 0);
9
- const cfg = await readConfig();
10
- const url = `http://localhost:${cfg.server.rpcPort}`;
11
- if (!to || !sol) {
12
- p.log.error("Usage: solforge airdrop --to <pubkey> --sol <amount>");
13
- return;
14
- }
15
- const lamports = BigInt(Math.floor(sol * 1_000_000_000));
16
- const body = {
17
- jsonrpc: "2.0",
18
- id: 1,
19
- method: "requestAirdrop",
20
- params: [to, Number(lamports)],
21
- };
22
- const s = p.spinner();
23
- s.start("Requesting airdrop...");
24
- try {
25
- const res = await fetch(url, {
26
- method: "POST",
27
- headers: { "content-type": "application/json" },
28
- body: JSON.stringify(body),
29
- });
30
- const json = await res.json();
31
- s.stop("Airdrop requested");
32
- console.log(JSON.stringify(json, null, 2));
33
- } catch (e) {
34
- s.stop("Airdrop failed");
35
- p.log.error(String(e));
36
- }
37
- }
@@ -1,39 +0,0 @@
1
- import * as p from "@clack/prompts";
2
- import {
3
- getConfigValue,
4
- readConfig,
5
- setConfigValue,
6
- writeDefaultConfig,
7
- } from "../../config";
8
- import { parseFlags } from "../utils/args";
9
-
10
- export async function configCommand(sub: string | undefined, args: string[]) {
11
- switch (sub) {
12
- case "init": {
13
- const { flags } = parseFlags(args);
14
- const force = !!flags.force;
15
- await writeDefaultConfig({ force });
16
- p.log.success("Wrote sf.config.json");
17
- return;
18
- }
19
- case "get": {
20
- const key = args[0];
21
- const cfg = await readConfig();
22
- console.log(getConfigValue(cfg, key));
23
- return;
24
- }
25
- case "set": {
26
- const [key, value] = args;
27
- const cfg = await readConfig();
28
- const updated = setConfigValue(cfg, key, value);
29
- await Bun.write(
30
- "sf.config.json",
31
- `${JSON.stringify(updated, null, 2)}\n`,
32
- );
33
- p.log.success(`Updated ${key}`);
34
- return;
35
- }
36
- default:
37
- p.log.error("Usage: solforge config <init|get|set>");
38
- }
39
- }
@@ -1,187 +0,0 @@
1
- import * as p from "@clack/prompts";
2
- import { readConfig } from "../../config";
3
- import { parseFlags } from "../utils/args";
4
- // No network fetch; decimals are read from LiteSVM via RPC getTokenSupply
5
-
6
- // Create/overwrite a token account (ATA) with a specified amount (base units)
7
- // Usage: solforge mint --mint <mint> --to <owner> --amount <amount>
8
- export async function mintCommand(args: string[]) {
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
13
- let uiAmount = flags["ui-amount"] as string | undefined; // preferred UI units
14
-
15
- const cfg = await readConfig();
16
- const url = `http://localhost:${cfg.server.rpcPort}`;
17
-
18
- // Get known mints from server for selection
19
- let knownMints: string[] = [];
20
- try {
21
- const resList = await fetch(url, {
22
- method: "POST",
23
- headers: { "content-type": "application/json" },
24
- body: JSON.stringify({
25
- jsonrpc: "2.0",
26
- id: 1,
27
- method: "solforgeListMints",
28
- params: [],
29
- }),
30
- });
31
- const j = await resList.json();
32
- if (!j.error && Array.isArray(j.result)) knownMints = j.result;
33
- } catch {}
34
-
35
- if (!mint) {
36
- if (knownMints.length > 0) {
37
- const choice = (await p.select({
38
- message: "Select mint",
39
- options: knownMints.map((m) => ({ value: m, label: m })),
40
- })) as string | symbol | null;
41
- if (!choice || typeof choice !== "string") return;
42
- mint = choice;
43
- } else {
44
- p.log.error("No known mints. Clone or create a token first.");
45
- return;
46
- }
47
- }
48
-
49
- // Receiver (ATA owner) is required
50
- if (!receiver) {
51
- receiver = (await p.text({
52
- message: "Receiver public key (ATA owner)",
53
- placeholder: "<receiver public key>",
54
- validate: (v) =>
55
- v && v.length >= 32 ? undefined : "Enter a valid public key",
56
- })) as string;
57
- if (!receiver) return;
58
- }
59
-
60
- // Amount selection (prefer UI units)
61
- if (!amountBase && !uiAmount) {
62
- uiAmount = (await p.text({
63
- message: "Amount (UI units)",
64
- placeholder: "1000",
65
- validate: (v) =>
66
- v && !Number.isNaN(Number(v)) ? undefined : "Enter a number",
67
- })) as string;
68
- if (!uiAmount) return;
69
- }
70
-
71
- // If UI amount provided, get decimals from LiteSVM via getTokenSupply
72
- if (!amountBase && uiAmount) {
73
- let decimals = 0;
74
- try {
75
- const res = await fetch(url, {
76
- method: "POST",
77
- headers: { "content-type": "application/json" },
78
- body: JSON.stringify({
79
- jsonrpc: "2.0",
80
- id: 2,
81
- method: "getTokenSupply",
82
- params: [mint],
83
- }),
84
- });
85
- const j = await res.json();
86
- const d = j?.result?.value?.decimals ?? j?.result?.decimals;
87
- if (typeof d === "number") decimals = d;
88
- } catch {}
89
- amountBase = toBaseUnits(uiAmount, decimals);
90
- }
91
-
92
- const s = p.spinner();
93
- s.start("Minting via real transaction...");
94
- try {
95
- const res = await fetch(url, {
96
- method: "POST",
97
- headers: { "content-type": "application/json" },
98
- body: JSON.stringify({
99
- jsonrpc: "2.0",
100
- id: 1,
101
- method: "solforgeMintTo",
102
- params: [mint, receiver, amountBase],
103
- }),
104
- });
105
- const json = await res.json();
106
- if (json.error) {
107
- const msg = String(json.error.message || "mint failed");
108
- // Offer admin fallback when faucet is not mint authority
109
- if (/no faucet authority|authority/i.test(msg)) {
110
- const choice = (await p.select({
111
- message: "Mint authority is not faucet. Choose action:",
112
- options: [
113
- {
114
- value: "adopt",
115
- label: "Adopt faucet as authority (local) and mint (real tx)",
116
- },
117
- { value: "admin", label: "Admin set-balance (no real tx)" },
118
- { value: "cancel", label: "Cancel" },
119
- ],
120
- })) as "adopt" | "admin" | "cancel" | symbol | null;
121
- if (!choice || choice === "cancel") throw new Error(msg);
122
- if (choice === "adopt") {
123
- s.message("Adopting faucet as authority...");
124
- const resAdopt = await fetch(url, {
125
- method: "POST",
126
- headers: { "content-type": "application/json" },
127
- body: JSON.stringify({
128
- jsonrpc: "2.0",
129
- id: 2,
130
- method: "solforgeAdoptMintAuthority",
131
- params: [mint],
132
- }),
133
- });
134
- const jA = await resAdopt.json();
135
- if (jA.error)
136
- throw new Error(jA.error.message || "adopt authority failed");
137
- s.message("Minting via real transaction...");
138
- const resRetry = await fetch(url, {
139
- method: "POST",
140
- headers: { "content-type": "application/json" },
141
- body: JSON.stringify({
142
- jsonrpc: "2.0",
143
- id: 3,
144
- method: "solforgeMintTo",
145
- params: [mint, receiver, amountBase],
146
- }),
147
- });
148
- const jR = await resRetry.json();
149
- if (jR.error) throw new Error(jR.error.message || "mint failed");
150
- s.stop("Minted");
151
- console.log(JSON.stringify(jR.result, null, 2));
152
- return;
153
- }
154
- if (choice === "admin") {
155
- const res2 = await fetch(url, {
156
- method: "POST",
157
- headers: { "content-type": "application/json" },
158
- body: JSON.stringify({
159
- jsonrpc: "2.0",
160
- id: 4,
161
- method: "solforgeCreateTokenAccount",
162
- params: [mint, receiver, amountBase],
163
- }),
164
- });
165
- const json2 = await res2.json();
166
- if (json2.error)
167
- throw new Error(json2.error.message || "admin mint failed");
168
- s.stop("Minted (admin)");
169
- console.log(JSON.stringify(json2.result, null, 2));
170
- return;
171
- }
172
- }
173
- throw new Error(msg);
174
- }
175
- s.stop("Minted");
176
- console.log(JSON.stringify(json.result, null, 2));
177
- } catch (e) {
178
- s.stop("Mint failed");
179
- p.log.error(String(e));
180
- }
181
- }
182
-
183
- function toBaseUnits(ui: string, decimals: number): string {
184
- const [i, f = ""] = String(ui).split(".");
185
- const frac = (f + "0".repeat(decimals)).slice(0, decimals);
186
- return BigInt(i + (decimals ? frac : "")).toString();
187
- }