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.
- package/package.json +1 -5
- package/start.cjs +19 -23
- package/docs/API.md +0 -379
- package/docs/CONFIGURATION.md +0 -407
- package/docs/bun-single-file-executable.md +0 -585
- package/docs/cli-plan.md +0 -154
- package/docs/data-indexing-plan.md +0 -214
- package/docs/gui-roadmap.md +0 -202
- package/scripts/decode-b58.ts +0 -10
- package/scripts/install.sh +0 -112
- package/server/index.ts +0 -5
- package/server/lib/base58.ts +0 -33
- package/server/lib/faucet.ts +0 -110
- package/server/lib/instruction-parser.ts +0 -328
- package/server/lib/parsers/spl-associated-token-account.ts +0 -50
- package/server/lib/parsers/spl-token.ts +0 -340
- package/server/lib/spl-token.ts +0 -57
- package/server/methods/TEMPLATE.md +0 -117
- package/server/methods/account/get-account-info.ts +0 -86
- package/server/methods/account/get-balance.ts +0 -23
- package/server/methods/account/get-multiple-accounts.ts +0 -84
- package/server/methods/account/get-parsed-account-info.ts +0 -17
- package/server/methods/account/index.ts +0 -12
- package/server/methods/account/parsers/index.ts +0 -52
- package/server/methods/account/parsers/loader-upgradeable.ts +0 -79
- package/server/methods/account/parsers/spl-token.ts +0 -256
- package/server/methods/account/parsers/system.ts +0 -4
- package/server/methods/account/request-airdrop.ts +0 -271
- package/server/methods/admin/adopt-mint-authority.ts +0 -94
- package/server/methods/admin/clone-program-accounts.ts +0 -55
- package/server/methods/admin/clone-program.ts +0 -152
- package/server/methods/admin/clone-token-accounts.ts +0 -117
- package/server/methods/admin/clone-token-mint.ts +0 -82
- package/server/methods/admin/create-mint.ts +0 -114
- package/server/methods/admin/create-token-account.ts +0 -137
- package/server/methods/admin/helpers.ts +0 -70
- package/server/methods/admin/index.ts +0 -10
- package/server/methods/admin/list-mints.ts +0 -21
- package/server/methods/admin/load-program.ts +0 -52
- package/server/methods/admin/mint-to.ts +0 -266
- package/server/methods/block/get-block-height.ts +0 -5
- package/server/methods/block/get-block.ts +0 -31
- package/server/methods/block/get-blocks-with-limit.ts +0 -19
- package/server/methods/block/get-latest-blockhash.ts +0 -12
- package/server/methods/block/get-slot.ts +0 -5
- package/server/methods/block/index.ts +0 -6
- package/server/methods/block/is-blockhash-valid.ts +0 -19
- package/server/methods/epoch/get-cluster-nodes.ts +0 -17
- package/server/methods/epoch/get-epoch-info.ts +0 -16
- package/server/methods/epoch/get-epoch-schedule.ts +0 -15
- package/server/methods/epoch/get-highest-snapshot-slot.ts +0 -9
- package/server/methods/epoch/get-leader-schedule.ts +0 -8
- package/server/methods/epoch/get-max-retransmit-slot.ts +0 -9
- package/server/methods/epoch/get-max-shred-insert-slot.ts +0 -9
- package/server/methods/epoch/get-slot-leader.ts +0 -6
- package/server/methods/epoch/get-slot-leaders.ts +0 -9
- package/server/methods/epoch/get-stake-activation.ts +0 -9
- package/server/methods/epoch/get-stake-minimum-delegation.ts +0 -9
- package/server/methods/epoch/get-vote-accounts.ts +0 -19
- package/server/methods/epoch/index.ts +0 -13
- package/server/methods/epoch/minimum-ledger-slot.ts +0 -5
- package/server/methods/fee/get-fee-calculator-for-blockhash.ts +0 -12
- package/server/methods/fee/get-fee-for-message.ts +0 -8
- package/server/methods/fee/get-fee-rate-governor.ts +0 -16
- package/server/methods/fee/get-fees.ts +0 -14
- package/server/methods/fee/get-recent-prioritization-fees.ts +0 -22
- package/server/methods/fee/index.ts +0 -5
- package/server/methods/get-address-lookup-table.ts +0 -27
- package/server/methods/index.ts +0 -265
- package/server/methods/performance/get-recent-performance-samples.ts +0 -25
- package/server/methods/performance/get-transaction-count.ts +0 -5
- package/server/methods/performance/index.ts +0 -2
- package/server/methods/program/get-block-commitment.ts +0 -9
- package/server/methods/program/get-block-production.ts +0 -14
- package/server/methods/program/get-block-time.ts +0 -21
- package/server/methods/program/get-blocks.ts +0 -11
- package/server/methods/program/get-first-available-block.ts +0 -9
- package/server/methods/program/get-genesis-hash.ts +0 -6
- package/server/methods/program/get-identity.ts +0 -6
- package/server/methods/program/get-inflation-governor.ts +0 -15
- package/server/methods/program/get-inflation-rate.ts +0 -10
- package/server/methods/program/get-inflation-reward.ts +0 -12
- package/server/methods/program/get-largest-accounts.ts +0 -8
- package/server/methods/program/get-parsed-program-accounts.ts +0 -12
- package/server/methods/program/get-parsed-token-accounts-by-delegate.ts +0 -12
- package/server/methods/program/get-parsed-token-accounts-by-owner.ts +0 -12
- package/server/methods/program/get-program-accounts.ts +0 -221
- package/server/methods/program/get-supply.ts +0 -13
- package/server/methods/program/get-token-account-balance.ts +0 -60
- package/server/methods/program/get-token-accounts-by-delegate.ts +0 -82
- package/server/methods/program/get-token-accounts-by-owner.ts +0 -416
- package/server/methods/program/get-token-largest-accounts.ts +0 -81
- package/server/methods/program/get-token-supply.ts +0 -39
- package/server/methods/program/index.ts +0 -21
- package/server/methods/solforge/index.ts +0 -158
- package/server/methods/system/get-health.ts +0 -5
- package/server/methods/system/get-minimum-balance-for-rent-exemption.ts +0 -13
- package/server/methods/system/get-version.ts +0 -9
- package/server/methods/system/index.ts +0 -3
- package/server/methods/transaction/get-confirmed-transaction.ts +0 -11
- package/server/methods/transaction/get-parsed-transaction.ts +0 -17
- package/server/methods/transaction/get-signature-statuses.ts +0 -79
- package/server/methods/transaction/get-signatures-for-address.ts +0 -41
- package/server/methods/transaction/get-transaction.ts +0 -639
- package/server/methods/transaction/index.ts +0 -7
- package/server/methods/transaction/inner-instructions.test.ts +0 -104
- package/server/methods/transaction/send-transaction.ts +0 -469
- package/server/methods/transaction/simulate-transaction.ts +0 -57
- package/server/rpc-server.ts +0 -521
- package/server/types.ts +0 -109
- package/server/ws-server.ts +0 -178
- package/src/api-server-entry.ts +0 -109
- package/src/cli/bootstrap.ts +0 -67
- package/src/cli/commands/airdrop.ts +0 -37
- package/src/cli/commands/config.ts +0 -39
- package/src/cli/commands/mint.ts +0 -187
- package/src/cli/commands/program-clone.ts +0 -122
- package/src/cli/commands/program-load.ts +0 -64
- package/src/cli/commands/rpc-start.ts +0 -49
- package/src/cli/commands/token-adopt-authority.ts +0 -37
- package/src/cli/commands/token-clone.ts +0 -112
- package/src/cli/commands/token-create.ts +0 -81
- package/src/cli/main.ts +0 -158
- package/src/cli/run-solforge.ts +0 -112
- package/src/cli/setup-utils.ts +0 -54
- package/src/cli/setup-wizard.ts +0 -258
- package/src/cli/utils/args.ts +0 -15
- package/src/commands/add-program.ts +0 -333
- package/src/commands/init.ts +0 -122
- package/src/commands/list.ts +0 -136
- package/src/commands/mint.ts +0 -287
- package/src/commands/start.ts +0 -881
- package/src/commands/status.ts +0 -99
- package/src/commands/stop.ts +0 -405
- package/src/config/index.ts +0 -146
- package/src/config/manager.ts +0 -157
- package/src/db/index.ts +0 -83
- package/src/db/schema/accounts.ts +0 -23
- package/src/db/schema/address-signatures.ts +0 -31
- package/src/db/schema/index.ts +0 -6
- package/src/db/schema/meta-kv.ts +0 -9
- package/src/db/schema/transactions.ts +0 -36
- package/src/db/schema/tx-account-states.ts +0 -23
- package/src/db/schema/tx-accounts.ts +0 -33
- package/src/db/tx-store.ts +0 -264
- package/src/gui/public/app.css +0 -1556
- package/src/gui/public/build/main.css +0 -1569
- package/src/gui/public/build/main.js +0 -303
- package/src/gui/public/build/main.js.txt +0 -231
- package/src/gui/public/index.html +0 -19
- package/src/gui/server.ts +0 -296
- package/src/gui/src/api.ts +0 -127
- package/src/gui/src/app.tsx +0 -441
- package/src/gui/src/components/airdrop-mint-form.tsx +0 -246
- package/src/gui/src/components/clone-program-modal.tsx +0 -202
- package/src/gui/src/components/clone-token-modal.tsx +0 -230
- package/src/gui/src/components/modal.tsx +0 -134
- package/src/gui/src/components/programs-panel.tsx +0 -124
- package/src/gui/src/components/status-panel.tsx +0 -136
- package/src/gui/src/components/tokens-panel.tsx +0 -122
- package/src/gui/src/hooks/use-interval.ts +0 -17
- package/src/gui/src/index.css +0 -557
- package/src/gui/src/main.tsx +0 -17
- package/src/index.ts +0 -216
- package/src/migrations-bundled.ts +0 -23
- package/src/rpc/start.ts +0 -44
- package/src/services/api-server.ts +0 -504
- package/src/services/port-manager.ts +0 -174
- package/src/services/process-registry.ts +0 -153
- package/src/services/program-cloner.ts +0 -317
- package/src/services/token-cloner.ts +0 -811
- package/src/services/validator.ts +0 -293
- package/src/types/config.ts +0 -110
- package/src/utils/shell.ts +0 -110
- package/src/utils/token-loader.ts +0 -115
package/src/cli/run-solforge.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
import {
|
|
3
|
-
defaultConfig,
|
|
4
|
-
readConfig,
|
|
5
|
-
type SolforgeConfig,
|
|
6
|
-
writeConfig,
|
|
7
|
-
} from "../config";
|
|
8
|
-
import { startRpcServers } from "../rpc/start";
|
|
9
|
-
import { bootstrapEnvironment } from "./bootstrap";
|
|
10
|
-
import { cancelSetup } from "./setup-utils";
|
|
11
|
-
import { runSetupWizard } from "./setup-wizard";
|
|
12
|
-
import { parseFlags } from "./utils/args";
|
|
13
|
-
|
|
14
|
-
const CONFIG_PATH = "sf.config.json";
|
|
15
|
-
|
|
16
|
-
export async function runSolforge(args: string[] = []) {
|
|
17
|
-
const { flags } = parseFlags(args);
|
|
18
|
-
const ci = flags.ci === true || flags.y === true;
|
|
19
|
-
const config = await ensureConfig(ci);
|
|
20
|
-
await startWithConfig(config, args);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function ensureConfig(ci = false): Promise<SolforgeConfig> {
|
|
24
|
-
const exists = await Bun.file(CONFIG_PATH).exists();
|
|
25
|
-
if (!exists) {
|
|
26
|
-
if (ci) {
|
|
27
|
-
// Non-interactive: write defaults and continue
|
|
28
|
-
await saveConfig(defaultConfig);
|
|
29
|
-
return defaultConfig;
|
|
30
|
-
}
|
|
31
|
-
p.intro("Solforge setup");
|
|
32
|
-
const config = await runSetupWizard();
|
|
33
|
-
await saveConfig(config);
|
|
34
|
-
p.outro("Configuration saved");
|
|
35
|
-
return config;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const current = await readConfig(CONFIG_PATH);
|
|
39
|
-
if (ci) return current; // Non-interactive: always reuse existing config
|
|
40
|
-
const reuse = await p.confirm({
|
|
41
|
-
message: `Use existing config at ${CONFIG_PATH}?`,
|
|
42
|
-
initialValue: true,
|
|
43
|
-
});
|
|
44
|
-
if (p.isCancel(reuse)) cancelSetup();
|
|
45
|
-
|
|
46
|
-
if (reuse) return current;
|
|
47
|
-
|
|
48
|
-
const updated = await runSetupWizard(current);
|
|
49
|
-
await saveConfig(updated);
|
|
50
|
-
return updated;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async function startWithConfig(config: SolforgeConfig, args: string[] = []) {
|
|
54
|
-
const { flags } = parseFlags(args);
|
|
55
|
-
const host = String(
|
|
56
|
-
flags.network === true
|
|
57
|
-
? "0.0.0.0"
|
|
58
|
-
: ((flags.host as string) ?? process.env.RPC_HOST ?? "127.0.0.1"),
|
|
59
|
-
);
|
|
60
|
-
const rpcPort = Number(config.server.rpcPort || defaultConfig.server.rpcPort);
|
|
61
|
-
const wsPort = Number(config.server.wsPort || rpcPort + 1);
|
|
62
|
-
const guiEnabled = config.gui?.enabled !== false;
|
|
63
|
-
const guiPort = Number(config.gui?.port ?? defaultConfig.gui.port);
|
|
64
|
-
|
|
65
|
-
const spinner = p.spinner();
|
|
66
|
-
const guiPart = guiEnabled ? `, GUI ${guiPort}` : "";
|
|
67
|
-
spinner.start(
|
|
68
|
-
`Starting RPC on ${host}:${rpcPort} (WS ${wsPort}${guiPart})...`,
|
|
69
|
-
);
|
|
70
|
-
try {
|
|
71
|
-
const started = startRpcServers({
|
|
72
|
-
rpcPort,
|
|
73
|
-
wsPort,
|
|
74
|
-
dbMode: config.server.db.mode,
|
|
75
|
-
dbPath: config.server.db.path,
|
|
76
|
-
host,
|
|
77
|
-
guiEnabled,
|
|
78
|
-
guiPort,
|
|
79
|
-
});
|
|
80
|
-
spinner.stop("RPC started");
|
|
81
|
-
|
|
82
|
-
await waitForRpc(`http://${host}:${started.rpcPort}`);
|
|
83
|
-
await bootstrapEnvironment(config, host, started.rpcPort);
|
|
84
|
-
|
|
85
|
-
p.log.success(
|
|
86
|
-
`Solforge ready ➜ HTTP http://${host}:${started.rpcPort} | WS ws://${host}:${started.wsPort}${
|
|
87
|
-
started.guiPort ? ` | GUI http://${host}:${started.guiPort}` : ""
|
|
88
|
-
}`,
|
|
89
|
-
);
|
|
90
|
-
} catch (error) {
|
|
91
|
-
spinner.stop("Failed to start RPC");
|
|
92
|
-
p.log.error(String(error));
|
|
93
|
-
process.exitCode = 1;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async function waitForRpc(url: string, timeoutMs = 10_000) {
|
|
98
|
-
const start = Date.now();
|
|
99
|
-
while (Date.now() - start < timeoutMs) {
|
|
100
|
-
try {
|
|
101
|
-
const res = await fetch(`${url}/health`);
|
|
102
|
-
if (res.ok) return;
|
|
103
|
-
} catch {}
|
|
104
|
-
await Bun.sleep(200);
|
|
105
|
-
}
|
|
106
|
-
throw new Error("RPC server did not become ready in time");
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async function saveConfig(config: SolforgeConfig) {
|
|
110
|
-
await writeConfig(config, CONFIG_PATH);
|
|
111
|
-
p.log.success(`Updated ${CONFIG_PATH}`);
|
|
112
|
-
}
|
package/src/cli/setup-utils.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
|
|
3
|
-
const CANCEL_MESSAGE = "Setup cancelled";
|
|
4
|
-
|
|
5
|
-
export function cancelSetup(): never {
|
|
6
|
-
p.cancel(CANCEL_MESSAGE);
|
|
7
|
-
process.exit(0);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function ensure<T>(value: T | symbol): T {
|
|
11
|
-
if (p.isCancel(value)) cancelSetup();
|
|
12
|
-
return value as T;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function validatePort(value: string | number | undefined) {
|
|
16
|
-
const num = Number(value);
|
|
17
|
-
if (!Number.isInteger(num)) return "Port must be an integer";
|
|
18
|
-
if (num < 1 || num > 65535) return "Port must be between 1 and 65535";
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function validatePositiveNumber(value: string) {
|
|
23
|
-
const num = Number(value);
|
|
24
|
-
if (!Number.isFinite(num)) return "Enter a number";
|
|
25
|
-
if (num <= 0) return "Enter a positive number";
|
|
26
|
-
return undefined;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function validatePubkey(value: string | undefined) {
|
|
30
|
-
if (!value) return "Value is required";
|
|
31
|
-
const trimmed = value.trim();
|
|
32
|
-
if (trimmed.length < 32 || trimmed.length > 44)
|
|
33
|
-
return "Expected base58 address";
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export async function collectCustomEntries(label: string) {
|
|
38
|
-
const results: string[] = [];
|
|
39
|
-
while (true) {
|
|
40
|
-
const value = await p.text({
|
|
41
|
-
message: `Enter ${label} (leave blank to finish)`,
|
|
42
|
-
});
|
|
43
|
-
if (p.isCancel(value)) cancelSetup();
|
|
44
|
-
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
45
|
-
if (!trimmed) break;
|
|
46
|
-
const error = validatePubkey(trimmed);
|
|
47
|
-
if (error) {
|
|
48
|
-
p.log.error(error);
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
results.push(trimmed);
|
|
52
|
-
}
|
|
53
|
-
return results;
|
|
54
|
-
}
|
package/src/cli/setup-wizard.ts
DELETED
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
import { defaultConfig, type SolforgeConfig } from "../config";
|
|
3
|
-
import {
|
|
4
|
-
cancelSetup,
|
|
5
|
-
collectCustomEntries,
|
|
6
|
-
ensure,
|
|
7
|
-
validatePort,
|
|
8
|
-
validatePositiveNumber,
|
|
9
|
-
validatePubkey,
|
|
10
|
-
} from "./setup-utils";
|
|
11
|
-
|
|
12
|
-
const TOKEN_PRESETS = [
|
|
13
|
-
{
|
|
14
|
-
value: "usdc",
|
|
15
|
-
label: "USDC",
|
|
16
|
-
mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
value: "usdt",
|
|
20
|
-
label: "USDT",
|
|
21
|
-
mint: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
|
22
|
-
},
|
|
23
|
-
];
|
|
24
|
-
const PROGRAM_PRESETS = [
|
|
25
|
-
{
|
|
26
|
-
value: "jupiter",
|
|
27
|
-
label: "Jupiter",
|
|
28
|
-
programId: "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
value: "pump",
|
|
32
|
-
label: "Pump core",
|
|
33
|
-
programId: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
value: "pump-amm",
|
|
37
|
-
label: "Pump AMM",
|
|
38
|
-
programId: "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA",
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
value: "pump-fees",
|
|
42
|
-
label: "Pump fees",
|
|
43
|
-
programId: "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ",
|
|
44
|
-
},
|
|
45
|
-
];
|
|
46
|
-
export async function runSetupWizard(existing: SolforgeConfig = defaultConfig) {
|
|
47
|
-
const base: SolforgeConfig = JSON.parse(JSON.stringify(existing));
|
|
48
|
-
|
|
49
|
-
const rpcPort = Number(
|
|
50
|
-
ensure(
|
|
51
|
-
await p.text({
|
|
52
|
-
message: "RPC port",
|
|
53
|
-
initialValue: String(
|
|
54
|
-
base.server.rpcPort ?? defaultConfig.server.rpcPort,
|
|
55
|
-
),
|
|
56
|
-
validate: validatePort,
|
|
57
|
-
}),
|
|
58
|
-
),
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
const wsPort = Number(
|
|
62
|
-
ensure(
|
|
63
|
-
await p.text({
|
|
64
|
-
message: "WebSocket port",
|
|
65
|
-
initialValue: String(base.server.wsPort ?? rpcPort + 1),
|
|
66
|
-
validate: validatePort,
|
|
67
|
-
}),
|
|
68
|
-
),
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const guiEnabledResp = await p.confirm({
|
|
72
|
-
message: "Enable GUI server?",
|
|
73
|
-
initialValue: base.gui?.enabled ?? defaultConfig.gui.enabled,
|
|
74
|
-
});
|
|
75
|
-
if (p.isCancel(guiEnabledResp)) cancelSetup();
|
|
76
|
-
const guiEnabled = guiEnabledResp !== false;
|
|
77
|
-
|
|
78
|
-
let guiPort = base.gui?.port ?? defaultConfig.gui.port;
|
|
79
|
-
if (guiEnabled) {
|
|
80
|
-
guiPort = Number(
|
|
81
|
-
ensure(
|
|
82
|
-
await p.text({
|
|
83
|
-
message: "GUI port",
|
|
84
|
-
initialValue: String(guiPort ?? defaultConfig.gui.port),
|
|
85
|
-
validate: validatePort,
|
|
86
|
-
}),
|
|
87
|
-
),
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const endpoint = ensure(
|
|
92
|
-
await p.text({
|
|
93
|
-
message: "Source RPC endpoint for cloning",
|
|
94
|
-
initialValue: base.clone.endpoint || defaultConfig.clone.endpoint,
|
|
95
|
-
placeholder: defaultConfig.clone.endpoint,
|
|
96
|
-
validate: (value) => (value ? undefined : "Endpoint is required"),
|
|
97
|
-
}),
|
|
98
|
-
).trim();
|
|
99
|
-
|
|
100
|
-
const tokenSelection = ensure(
|
|
101
|
-
await p.multiselect({
|
|
102
|
-
message: "Which tokens should be cloned into LiteSVM?",
|
|
103
|
-
options: [
|
|
104
|
-
...TOKEN_PRESETS.map((token) => ({
|
|
105
|
-
value: token.value,
|
|
106
|
-
label: `${token.label} (${token.mint})`,
|
|
107
|
-
})),
|
|
108
|
-
{ value: "__custom__", label: "Add custom token mint" },
|
|
109
|
-
],
|
|
110
|
-
initialValues: TOKEN_PRESETS.filter((preset) =>
|
|
111
|
-
base.clone.tokens?.includes(preset.mint),
|
|
112
|
-
).map((preset) => preset.value),
|
|
113
|
-
required: false,
|
|
114
|
-
}),
|
|
115
|
-
) as string[];
|
|
116
|
-
let tokenSeed: string[] = [];
|
|
117
|
-
if ((base.clone.tokens?.length ?? 0) > 0) {
|
|
118
|
-
const keep = await p.confirm({
|
|
119
|
-
message: `Keep existing token list (${base.clone.tokens.length})?`,
|
|
120
|
-
initialValue: true,
|
|
121
|
-
});
|
|
122
|
-
if (p.isCancel(keep)) cancelSetup();
|
|
123
|
-
if (keep) tokenSeed = [...base.clone.tokens];
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const tokens = await resolveTokens(tokenSelection, tokenSeed);
|
|
127
|
-
|
|
128
|
-
const programSelection = ensure(
|
|
129
|
-
await p.multiselect({
|
|
130
|
-
message: "Clone any on-chain programs?",
|
|
131
|
-
options: [
|
|
132
|
-
...PROGRAM_PRESETS.map((program) => ({
|
|
133
|
-
value: program.value,
|
|
134
|
-
label: `${program.label} (${program.programId})`,
|
|
135
|
-
})),
|
|
136
|
-
{ value: "__custom__", label: "Add custom program" },
|
|
137
|
-
],
|
|
138
|
-
initialValues: PROGRAM_PRESETS.filter((preset) =>
|
|
139
|
-
base.clone.programs?.includes(preset.programId),
|
|
140
|
-
).map((preset) => preset.value),
|
|
141
|
-
required: false,
|
|
142
|
-
}),
|
|
143
|
-
) as string[];
|
|
144
|
-
let programSeed: string[] = [];
|
|
145
|
-
if ((base.clone.programs?.length ?? 0) > 0) {
|
|
146
|
-
const keepPrograms = await p.confirm({
|
|
147
|
-
message: `Keep existing program list (${base.clone.programs.length})?`,
|
|
148
|
-
initialValue: true,
|
|
149
|
-
});
|
|
150
|
-
if (p.isCancel(keepPrograms)) cancelSetup();
|
|
151
|
-
if (keepPrograms) programSeed = [...base.clone.programs];
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const programs = await resolvePrograms(programSelection, programSeed);
|
|
155
|
-
|
|
156
|
-
const airdrops = await collectAirdrops(base.bootstrap?.airdrops ?? []);
|
|
157
|
-
|
|
158
|
-
base.server.rpcPort = rpcPort;
|
|
159
|
-
base.server.wsPort = wsPort;
|
|
160
|
-
base.gui = { enabled: guiEnabled, port: guiPort ?? defaultConfig.gui.port };
|
|
161
|
-
base.clone.endpoint = endpoint;
|
|
162
|
-
base.clone.tokens = tokens;
|
|
163
|
-
base.clone.programs = programs;
|
|
164
|
-
base.bootstrap = { airdrops };
|
|
165
|
-
|
|
166
|
-
return base;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async function resolveTokens(selections: string[], existing: string[] = []) {
|
|
170
|
-
const set = new Set(existing);
|
|
171
|
-
for (const selection of selections) {
|
|
172
|
-
if (selection === "__custom__") {
|
|
173
|
-
{
|
|
174
|
-
const values = await collectCustomEntries("token mint address");
|
|
175
|
-
for (const value of values) set.add(value);
|
|
176
|
-
}
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
const preset = TOKEN_PRESETS.find((token) => token.value === selection);
|
|
180
|
-
if (!preset) continue;
|
|
181
|
-
const mint = ensure(
|
|
182
|
-
await p.text({
|
|
183
|
-
message: `Mint address for ${preset.label}`,
|
|
184
|
-
initialValue: preset.mint,
|
|
185
|
-
validate: validatePubkey,
|
|
186
|
-
}),
|
|
187
|
-
).trim();
|
|
188
|
-
set.add(mint);
|
|
189
|
-
}
|
|
190
|
-
return Array.from(set);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async function resolvePrograms(selections: string[], existing: string[] = []) {
|
|
194
|
-
const set = new Set(existing);
|
|
195
|
-
for (const selection of selections) {
|
|
196
|
-
if (selection === "__custom__") {
|
|
197
|
-
{
|
|
198
|
-
const values = await collectCustomEntries("program id");
|
|
199
|
-
for (const value of values) set.add(value);
|
|
200
|
-
}
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
const preset = PROGRAM_PRESETS.find(
|
|
204
|
-
(program) => program.value === selection,
|
|
205
|
-
);
|
|
206
|
-
if (!preset) continue;
|
|
207
|
-
const programId = ensure(
|
|
208
|
-
await p.text({
|
|
209
|
-
message: `Program ID for ${preset.label}`,
|
|
210
|
-
initialValue: preset.programId,
|
|
211
|
-
validate: validatePubkey,
|
|
212
|
-
}),
|
|
213
|
-
).trim();
|
|
214
|
-
set.add(programId);
|
|
215
|
-
}
|
|
216
|
-
return Array.from(set);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
async function collectAirdrops(
|
|
220
|
-
existing: Array<{ address: string; amountSol: number }>,
|
|
221
|
-
) {
|
|
222
|
-
const entries: Array<{ address: string; amountSol: number }> = [];
|
|
223
|
-
if (existing.length > 0) {
|
|
224
|
-
const keep = await p.confirm({
|
|
225
|
-
message: `Keep existing airdrop recipients (${existing.length})?`,
|
|
226
|
-
initialValue: true,
|
|
227
|
-
});
|
|
228
|
-
if (p.isCancel(keep)) cancelSetup();
|
|
229
|
-
if (keep) entries.push(...existing);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
while (true) {
|
|
233
|
-
const address = await p.text({
|
|
234
|
-
message:
|
|
235
|
-
entries.length === 0
|
|
236
|
-
? "Airdrop recipient address (leave blank to skip)"
|
|
237
|
-
: "Add another airdrop recipient (leave blank to finish)",
|
|
238
|
-
});
|
|
239
|
-
if (p.isCancel(address)) cancelSetup();
|
|
240
|
-
const trimmed = typeof address === "string" ? address.trim() : "";
|
|
241
|
-
if (!trimmed) break;
|
|
242
|
-
const error = validatePubkey(trimmed);
|
|
243
|
-
if (error) {
|
|
244
|
-
p.log.error(error);
|
|
245
|
-
continue;
|
|
246
|
-
}
|
|
247
|
-
const amount = ensure(
|
|
248
|
-
await p.text({
|
|
249
|
-
message: `Amount of SOL to airdrop to ${trimmed}`,
|
|
250
|
-
initialValue: "100",
|
|
251
|
-
validate: validatePositiveNumber,
|
|
252
|
-
}),
|
|
253
|
-
);
|
|
254
|
-
entries.push({ address: trimmed, amountSol: Number(amount) });
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
return entries;
|
|
258
|
-
}
|
package/src/cli/utils/args.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export function parseFlags(args: string[]) {
|
|
2
|
-
const flags: Record<string, string | boolean> = {};
|
|
3
|
-
const rest: string[] = [];
|
|
4
|
-
for (let i = 0; i < args.length; i++) {
|
|
5
|
-
const a = args[i];
|
|
6
|
-
if (a.startsWith("--")) {
|
|
7
|
-
const [k, v] = a.slice(2).split("=");
|
|
8
|
-
if (typeof v === "string" && v.length > 0) flags[k] = v;
|
|
9
|
-
else if (i + 1 < args.length && !args[i + 1].startsWith("-"))
|
|
10
|
-
flags[k] = args[++i];
|
|
11
|
-
else flags[k] = true;
|
|
12
|
-
} else rest.push(a);
|
|
13
|
-
}
|
|
14
|
-
return { flags, rest };
|
|
15
|
-
}
|