@better-sol/cli 0.1.0-alpha.1 → 0.1.0-alpha.5
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 +12 -8
- package/dist/index.js +24 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @better-sol/cli
|
|
2
2
|
|
|
3
|
+
> **Alpha**
|
|
4
|
+
>
|
|
5
|
+
> Better Sol is in early development. APIs may change, rough edges exist, and things can break. Your feedback shapes what comes next. Thank you for being an early adopter.
|
|
6
|
+
|
|
3
7
|
The Better Sol command-line tool. Scaffold programs, compile and deploy to Solana, generate database schemas, and import external programs.
|
|
4
8
|
|
|
5
9
|
No installation needed. Run with `npx` or `bunx`.
|
|
@@ -11,7 +15,7 @@ No installation needed. Run with `npx` or `bunx`.
|
|
|
11
15
|
Set up a new project.
|
|
12
16
|
|
|
13
17
|
```bash
|
|
14
|
-
npx @better-sol/cli init
|
|
18
|
+
npx @better-sol/cli@alpha init
|
|
15
19
|
```
|
|
16
20
|
|
|
17
21
|
Creates a payer keypair at `keypair.json`, a `programs/` directory, and a `.gitignore`. Detects your existing Solana CLI keypair at `~/.config/solana/id.json` if you have one. Offers to install `better-sol` if a `package.json` exists.
|
|
@@ -26,7 +30,7 @@ Creates a payer keypair at `keypair.json`, a `programs/` directory, and a `.giti
|
|
|
26
30
|
Scaffold a new program.
|
|
27
31
|
|
|
28
32
|
```bash
|
|
29
|
-
npx @better-sol/cli create counter
|
|
33
|
+
npx @better-sol/cli@alpha create counter
|
|
30
34
|
```
|
|
31
35
|
|
|
32
36
|
Generates `programs/counter.ts` with a working counter template and `.better-sol/counter.json` with the program keypair.
|
|
@@ -41,7 +45,7 @@ Generates `programs/counter.ts` with a working counter template and `.better-sol
|
|
|
41
45
|
Compile and deploy to Solana.
|
|
42
46
|
|
|
43
47
|
```bash
|
|
44
|
-
npx @better-sol/cli deploy
|
|
48
|
+
npx @better-sol/cli@alpha deploy
|
|
45
49
|
```
|
|
46
50
|
|
|
47
51
|
Parses your TypeScript, generates Anchor Rust, compiles it via the cloud API, and deploys the binary. On devnet and testnet, automatically funds your payer if the balance is low.
|
|
@@ -62,10 +66,10 @@ Import an external program from an on-chain address or a local IDL file.
|
|
|
62
66
|
|
|
63
67
|
```bash
|
|
64
68
|
# From an on-chain program
|
|
65
|
-
npx @better-sol/cli generate idl 12b3t1cNiAUoYLiWFEnFa4w6qYxVAiqCWU7KZuzLPYtH
|
|
69
|
+
npx @better-sol/cli@alpha generate idl 12b3t1cNiAUoYLiWFEnFa4w6qYxVAiqCWU7KZuzLPYtH
|
|
66
70
|
|
|
67
71
|
# From a local IDL JSON file
|
|
68
|
-
npx @better-sol/cli generate idl ./staking-idl.json
|
|
72
|
+
npx @better-sol/cli@alpha generate idl ./staking-idl.json
|
|
69
73
|
```
|
|
70
74
|
|
|
71
75
|
Produces a typed `.ts` file in `generated/`. Detects whether the argument is an address or a file path automatically.
|
|
@@ -81,7 +85,7 @@ Produces a typed `.ts` file in `generated/`. Detects whether the argument is an
|
|
|
81
85
|
Generate a Drizzle ORM schema from your account definitions.
|
|
82
86
|
|
|
83
87
|
```bash
|
|
84
|
-
npx @better-sol/cli generate db
|
|
88
|
+
npx @better-sol/cli@alpha generate db
|
|
85
89
|
```
|
|
86
90
|
|
|
87
91
|
| Flag | Default | Description |
|
|
@@ -95,7 +99,7 @@ npx @better-sol/cli generate db
|
|
|
95
99
|
Save your compiler API key.
|
|
96
100
|
|
|
97
101
|
```bash
|
|
98
|
-
npx @better-sol/cli login
|
|
102
|
+
npx @better-sol/cli@alpha login
|
|
99
103
|
```
|
|
100
104
|
|
|
101
105
|
Saves your key to `.better-sol/auth.json`. Without a key you get 5 compiles per hour. With a key, 100 per hour.
|
|
@@ -105,7 +109,7 @@ Saves your key to `.better-sol/auth.json`. Without a key you get 5 compiles per
|
|
|
105
109
|
Submit a deployed program for OtterSec verified-builds.
|
|
106
110
|
|
|
107
111
|
```bash
|
|
108
|
-
npx @better-sol/cli verify counter --program-id <address>
|
|
112
|
+
npx @better-sol/cli@alpha verify counter --program-id <address>
|
|
109
113
|
```
|
|
110
114
|
|
|
111
115
|
| Flag | Description |
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
5
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
6
|
import path, { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
8
7
|
import { homedir } from "node:os";
|
|
9
8
|
import { execSync } from "node:child_process";
|
|
10
9
|
import { generateKeyPairSigner, getAddressDecoder } from "@solana/kit";
|
|
11
10
|
import { access, mkdir, opendir, readFile, writeFile } from "node:fs/promises";
|
|
11
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
12
12
|
import { parseSync } from "oxc-parser";
|
|
13
13
|
import { AnchorProvider, Program } from "@coral-xyz/anchor";
|
|
14
14
|
import crypto$1 from "crypto";
|
|
@@ -3036,11 +3036,18 @@ function primitiveLayout(type) {
|
|
|
3036
3036
|
//#endregion
|
|
3037
3037
|
//#region src/parser/discover.ts
|
|
3038
3038
|
function globToRegex(pattern) {
|
|
3039
|
-
const
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3039
|
+
const parts = pattern.split("/");
|
|
3040
|
+
const regexParts = [];
|
|
3041
|
+
for (let i = 0; i < parts.length; i++) {
|
|
3042
|
+
const part = parts[i];
|
|
3043
|
+
const isLast = i === parts.length - 1;
|
|
3044
|
+
if (part === "**") regexParts.push("(.*\\/)?");
|
|
3045
|
+
else {
|
|
3046
|
+
regexParts.push(part.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]"));
|
|
3047
|
+
if (!isLast) regexParts.push("/");
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
return new RegExp(`^${regexParts.join("")}$`);
|
|
3044
3051
|
}
|
|
3045
3052
|
async function findFiles(pattern) {
|
|
3046
3053
|
const regex = globToRegex(pattern);
|
|
@@ -3098,6 +3105,7 @@ async function discoverProgramsWithSpinner(src) {
|
|
|
3098
3105
|
//#region src/commands/deploy.ts
|
|
3099
3106
|
const DEFAULT_PAYER_PATH = "keypair.json";
|
|
3100
3107
|
const AIRDROP_LAMPORTS = 2000000000n;
|
|
3108
|
+
const AIRDROP_RETRIES = 3;
|
|
3101
3109
|
const MIN_DEPLOY_BALANCE = 1500000000n;
|
|
3102
3110
|
async function deploy(options) {
|
|
3103
3111
|
intro("better-sol deploy");
|
|
@@ -3208,14 +3216,19 @@ async function ensureFunded(address, cluster, rpcUrl) {
|
|
|
3208
3216
|
return;
|
|
3209
3217
|
}
|
|
3210
3218
|
s.message(`Low balance (${(Number(balance) / 1e9).toFixed(4)} SOL). Requesting airdrop on ${cluster}...`);
|
|
3211
|
-
try {
|
|
3219
|
+
for (let attempt = 1; attempt <= AIRDROP_RETRIES; attempt++) try {
|
|
3212
3220
|
await confirmSignature(await requestAirdrop(address, rpcUrl, AIRDROP_LAMPORTS), rpcUrl);
|
|
3213
3221
|
const newBalance = await getBalance(address, rpcUrl);
|
|
3214
3222
|
s.stop(`Funded. Balance: ${(Number(newBalance) / 1e9).toFixed(2)} SOL`);
|
|
3223
|
+
return;
|
|
3215
3224
|
} catch {
|
|
3216
|
-
|
|
3217
|
-
|
|
3225
|
+
if (attempt < AIRDROP_RETRIES) {
|
|
3226
|
+
s.message(`Airdrop attempt ${attempt} failed, retrying...`);
|
|
3227
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
3228
|
+
}
|
|
3218
3229
|
}
|
|
3230
|
+
s.stop("Airdrop failed");
|
|
3231
|
+
throw new Error(`Failed to airdrop SOL on ${cluster}. Fund ${address} manually or try again.`);
|
|
3219
3232
|
}
|
|
3220
3233
|
function printProgramSummary(program, cluster, out, wroteRust) {
|
|
3221
3234
|
log.info(`Program: ${program.name}`);
|
|
@@ -69246,7 +69259,7 @@ async function gitCommit() {
|
|
|
69246
69259
|
//#endregion
|
|
69247
69260
|
//#region src/index.ts
|
|
69248
69261
|
const cli = new Command();
|
|
69249
|
-
cli.name("better-sol").description("TypeScript-first Solana program tooling — run with npx @better-sol/cli").version("0.1.0-alpha.
|
|
69262
|
+
cli.name("better-sol").description("TypeScript-first Solana program tooling — run with npx @better-sol/cli").version("0.1.0-alpha.5");
|
|
69250
69263
|
cli.command("init").description("Initialize a better-sol project").option("--force", "overwrite existing files", false).option("--skip-install", "skip installing dependencies", false).action((options) => run(() => init(options)));
|
|
69251
69264
|
cli.command("create").description("Create a new better-sol program").argument("[name]", "program name").option("--dir <dir>", "program directory", "programs").option("--force", "overwrite existing files", false).action((name, options) => run(() => create(name, options)));
|
|
69252
69265
|
cli.command("login").description("Save your compiler API key").action(() => run(() => login()));
|
|
@@ -69255,7 +69268,7 @@ const generate = cli.command("generate").description("Generate derived artifacts
|
|
|
69255
69268
|
generate.command("db").description("Generate a database schema from account definitions").option("--dialect <dialect>", "postgres, mysql, or sqlite", "postgres").option("--out <path>", "output file", "src/db/better-sol.ts").option("--src <glob>", "program source glob").action((options) => run(() => generateDb(options)));
|
|
69256
69269
|
generate.command("idl").description("Generate a typed Better Sol program from an IDL file or on-chain program address").argument("<source>", "path to IDL JSON file or on-chain program address").option("--out <path>", "output TypeScript file (default: generated/<name>.ts)").option("--name <name>", "program name override (default: derived from IDL)").option("--cluster <cluster>", "cluster for on-chain IDL fetch (mainnet, devnet, testnet, localnet)", "mainnet").action((source, options) => run(() => generateIdl(source, options)));
|
|
69257
69270
|
cli.command("verify").description("Submit a deployed program for OtterSec verified-builds").argument("[program]", "program name or program ID").option("--program-id <programId>", "program ID to verify").option("--lib-name <name>", "Rust library name (defaults to program name)").option("--mount-path <path>", "subdirectory in repo where Cargo.toml lives (defaults to generated/<name>)").action((program, options) => run(() => verify(program, options)));
|
|
69258
|
-
|
|
69271
|
+
cli.parse(process.argv);
|
|
69259
69272
|
async function run(task) {
|
|
69260
69273
|
try {
|
|
69261
69274
|
await task();
|