@caatinga/cli 0.2.1 → 0.2.2
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 +11 -4
- package/dist/index.js +325 -38
- package/package.json +3 -3
- package/templates/marketplace-with-token/README.md +4 -2
- package/templates/marketplace-with-token/caatinga.config.ts +2 -2
- package/templates/marketplace-with-token/caatinga.template.json +1 -1
- package/templates/marketplace-with-token/contracts/marketplace/Cargo.lock +1731 -0
- package/templates/marketplace-with-token/contracts/marketplace/Cargo.toml +1 -0
- package/templates/marketplace-with-token/contracts/marketplace/src/lib.rs +31 -1
- package/templates/marketplace-with-token/contracts/token/Cargo.lock +1731 -0
- package/templates/marketplace-with-token/contracts/token/Cargo.toml +1 -0
- package/templates/marketplace-with-token/index.html +12 -0
- package/templates/marketplace-with-token/package.json +14 -3
- package/templates/marketplace-with-token/src/App.tsx +57 -0
- package/templates/marketplace-with-token/src/main.ts +3 -1
- package/templates/marketplace-with-token/src/main.tsx +10 -0
- package/templates/marketplace-with-token/src/styles.css +157 -0
- package/templates/marketplace-with-token/tsconfig.json +14 -4
- package/templates/marketplace-with-token/vite.config.ts +6 -0
- package/templates/react-vite-counter/README.md +1 -1
- package/templates/react-vite-counter/caatinga.artifacts.json +10 -0
- package/templates/react-vite-counter/caatinga.config.ts +1 -1
- package/templates/react-vite-counter/caatinga.template.json +1 -1
- package/templates/react-vite-counter/contracts/counter/Cargo.lock +1731 -0
- package/templates/react-vite-counter/contracts/counter/Cargo.toml +1 -0
- package/templates/react-vite-counter/package.json +3 -3
- package/templates/react-vite-counter/src/caatinga.ts +20 -0
- package/templates/react-vite-counter/src/components/CounterCard.tsx +40 -3
- package/templates/react-vite-counter/src/components/WalletButton.tsx +58 -5
- package/templates/react-vite-counter/src/contracts/generated/counter.ts +49 -0
- package/templates/react-vite-counter/src/styles.css +21 -0
- package/templates/react-vite-counter/tsconfig.json +1 -1
- package/templates/react-vite-counter/src/contracts/generated/.gitkeep +0 -1
package/README.md
CHANGED
|
@@ -14,12 +14,12 @@ Inside a generated project, prefer `npx caatinga` so the project-local workflow
|
|
|
14
14
|
## Requirements
|
|
15
15
|
|
|
16
16
|
- Node.js `>=20`
|
|
17
|
-
- [Stellar CLI](https://developers.stellar.org/docs/tools/developer-tools/cli/stellar-cli) `>=
|
|
18
|
-
- Rust
|
|
17
|
+
- [Stellar CLI](https://developers.stellar.org/docs/tools/developer-tools/cli/stellar-cli) `>=23.0.0` and `<=25.2.0` on `PATH` (22.x breaks `caatinga invoke` signing)
|
|
18
|
+
- Rust 1.84.0 or newer with the `wasm32v1-none` target (contract builds)
|
|
19
19
|
- A funded Stellar CLI identity for `deploy` and `invoke` (for example `alice`)
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
rustup target add
|
|
22
|
+
rustup target add wasm32v1-none
|
|
23
23
|
stellar keys generate alice --fund --network testnet
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -45,6 +45,7 @@ npx caatinga invoke counter.increment --network testnet --source alice
|
|
|
45
45
|
| Command | What it does |
|
|
46
46
|
| --- | --- |
|
|
47
47
|
| `caatinga init <projectName>` | Create a project from a bundled template and write `caatinga.artifacts.json` |
|
|
48
|
+
| `caatinga doctor [--network <network>] [--source <identity>]` | Check local Node, Stellar CLI, Rust, config, artifacts, network, and source identity setup |
|
|
48
49
|
| `caatinga build [contract]` | Compile contract WASM through Stellar CLI (default contract: `counter`) |
|
|
49
50
|
| `caatinga deploy [contract]` | Deploy one contract or the full configured graph; record IDs in artifacts |
|
|
50
51
|
| `caatinga generate <contract>` | Generate TypeScript bindings from a deployed contract ID |
|
|
@@ -63,6 +64,12 @@ The supported CLI flow is `init -> build -> deploy -> generate -> invoke`.
|
|
|
63
64
|
- `[contract]` defaults to `counter` when omitted
|
|
64
65
|
- `--allow-untested-stellar-cli` allows a Stellar CLI newer than Caatinga's tested maximum (local only)
|
|
65
66
|
|
|
67
|
+
### `doctor`
|
|
68
|
+
|
|
69
|
+
- `-n, --network <network>` validates that the network exists in `caatinga.config.ts`
|
|
70
|
+
- `-s, --source <identity>` validates that the local Stellar CLI identity exists
|
|
71
|
+
- exits `0` when all diagnostics pass and non-zero when a blocking diagnostic fails
|
|
72
|
+
|
|
66
73
|
### `deploy`
|
|
67
74
|
|
|
68
75
|
- Omit `[contract]` to deploy the full configured dependency graph
|
|
@@ -84,7 +91,7 @@ Dependencies listed in `dependsOn` deploy first unless `--no-deps` is set. Deplo
|
|
|
84
91
|
|
|
85
92
|
## Supported inputs
|
|
86
93
|
|
|
87
|
-
- `--source` accepts a Stellar CLI identity alias that can sign transactions; public `G...` addresses and secret keys are rejected
|
|
94
|
+
- `--source` accepts a local Stellar CLI identity alias that can sign transactions; public `G...` addresses and secret keys are rejected
|
|
88
95
|
- `--network` must match a network defined in `caatinga.config.ts`
|
|
89
96
|
- Project commands require `caatinga.config.ts` in the working directory
|
|
90
97
|
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// src/utils/preflight.ts
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
var NODE_MIN_MAJOR = 20;
|
|
6
|
+
function checkNodeVersion() {
|
|
7
|
+
const major = parseInt(process.versions.node.split(".")[0] ?? "0", 10);
|
|
8
|
+
if (major < NODE_MIN_MAJOR) {
|
|
9
|
+
return `Node.js ${process.versions.node} is below the required minimum v${NODE_MIN_MAJOR}.
|
|
10
|
+
Install Node.js ${NODE_MIN_MAJOR} or newer: https://nodejs.org/`;
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
function runPreflight() {
|
|
15
|
+
const failures = [];
|
|
16
|
+
const nodeFailure = checkNodeVersion();
|
|
17
|
+
if (nodeFailure) failures.push(nodeFailure);
|
|
18
|
+
if (failures.length > 0) return { ok: false, failures };
|
|
19
|
+
return { ok: true };
|
|
20
|
+
}
|
|
21
|
+
function assertPreflight() {
|
|
22
|
+
const result = runPreflight();
|
|
23
|
+
if (result.ok) return;
|
|
24
|
+
console.error(chalk.red.bold("\n\u2716 Caatinga preflight check failed\n"));
|
|
25
|
+
for (const failure of result.failures) {
|
|
26
|
+
console.error(chalk.red(` \u2022 ${failure}
|
|
27
|
+
`));
|
|
28
|
+
}
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
3
32
|
// src/program.ts
|
|
4
33
|
import { Command } from "commander";
|
|
5
34
|
|
|
@@ -7,47 +36,54 @@ import { Command } from "commander";
|
|
|
7
36
|
import { buildContract, loadConfig } from "@caatinga/core";
|
|
8
37
|
|
|
9
38
|
// src/utils/errors.ts
|
|
39
|
+
import chalk2 from "chalk";
|
|
10
40
|
import { toCaatingaError } from "@caatinga/core";
|
|
41
|
+
var SEPARATOR = chalk2.gray("\u2500".repeat(50));
|
|
42
|
+
function printError(error) {
|
|
43
|
+
const caatingaError = toCaatingaError(error);
|
|
44
|
+
console.error("");
|
|
45
|
+
console.error(SEPARATOR);
|
|
46
|
+
console.error(chalk2.red.bold(" \u2716 Error"));
|
|
47
|
+
console.error(SEPARATOR);
|
|
48
|
+
console.error(chalk2.red(` ${caatingaError.message}`));
|
|
49
|
+
console.error("");
|
|
50
|
+
console.error(chalk2.gray(` Code: ${caatingaError.code}`));
|
|
51
|
+
if (caatingaError.hint) {
|
|
52
|
+
console.error("");
|
|
53
|
+
console.error(chalk2.yellow(` Hint: ${caatingaError.hint}`));
|
|
54
|
+
}
|
|
55
|
+
console.error(SEPARATOR);
|
|
56
|
+
console.error("");
|
|
57
|
+
}
|
|
58
|
+
async function runCliAction(action) {
|
|
59
|
+
try {
|
|
60
|
+
await action();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
printError(error);
|
|
63
|
+
process.exitCode = 1;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
11
66
|
|
|
12
67
|
// src/utils/logger.ts
|
|
13
|
-
import
|
|
68
|
+
import chalk3 from "chalk";
|
|
14
69
|
var logger = {
|
|
15
70
|
info(message) {
|
|
16
71
|
console.log(message);
|
|
17
72
|
},
|
|
18
73
|
success(message) {
|
|
19
|
-
console.log(
|
|
74
|
+
console.log(chalk3.green(message));
|
|
20
75
|
},
|
|
21
76
|
warn(message) {
|
|
22
|
-
console.warn(
|
|
77
|
+
console.warn(chalk3.yellow(message));
|
|
23
78
|
},
|
|
24
79
|
error(message) {
|
|
25
|
-
console.error(
|
|
80
|
+
console.error(chalk3.red(message));
|
|
26
81
|
},
|
|
27
82
|
muted(message) {
|
|
28
|
-
console.log(
|
|
83
|
+
console.log(chalk3.gray(message));
|
|
29
84
|
}
|
|
30
85
|
};
|
|
31
86
|
|
|
32
|
-
// src/utils/errors.ts
|
|
33
|
-
function printError(error) {
|
|
34
|
-
const caatingaError = toCaatingaError(error);
|
|
35
|
-
logger.error(`Error: ${caatingaError.message}`);
|
|
36
|
-
logger.info("");
|
|
37
|
-
logger.info(`Code: ${caatingaError.code}`);
|
|
38
|
-
if (caatingaError.hint) {
|
|
39
|
-
logger.info(`Hint: ${caatingaError.hint}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
async function runCliAction(action) {
|
|
43
|
-
try {
|
|
44
|
-
await action();
|
|
45
|
-
} catch (error) {
|
|
46
|
-
printError(error);
|
|
47
|
-
process.exitCode = 1;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
87
|
// src/commands/build.command.ts
|
|
52
88
|
function registerBuildCommand(program2) {
|
|
53
89
|
program2.command("build").description("Build a configured Soroban contract").argument("[contract]", "Contract name", "counter").option("--allow-untested-stellar-cli", "Allow local use of a Stellar CLI version newer than Caatinga's tested maximum").action((contractName, options) => runCliAction(async () => {
|
|
@@ -67,7 +103,7 @@ function registerBuildCommand(program2) {
|
|
|
67
103
|
// src/commands/deploy.command.ts
|
|
68
104
|
import { deployContractGraph, CaatingaError, CaatingaErrorCode, loadConfig as loadConfig2 } from "@caatinga/core";
|
|
69
105
|
function registerDeployCommand(program2) {
|
|
70
|
-
program2.command("deploy").description("Deploy one or all configured Soroban contracts").argument("[contract]", "Contract name").option("-n, --network <network>", "Configured network name").requiredOption("-s, --source <source>", "Stellar CLI identity alias that can sign (for example alice)").option("--force", "Redeploy contracts even if artifacts already contain contract IDs").option("--no-deps", "Do not deploy missing dependencies for a selected contract").option("--allow-untested-stellar-cli", "Allow local use of a Stellar CLI version newer than Caatinga's tested maximum").action((contractName, options) => runCliAction(async () => {
|
|
106
|
+
program2.command("deploy").description("Deploy one or all configured Soroban contracts").argument("[contract]", "Contract name").option("-n, --network <network>", "Configured network name").requiredOption("-s, --source <source>", "Stellar CLI identity alias that can sign (for example alice)").option("--force", "Redeploy contracts even if artifacts already contain contract IDs").option("--no-deps", "Do not deploy missing dependencies for a selected contract").option("--no-stale-check", "Do not warn when WASM may be older than contract sources").option("--allow-untested-stellar-cli", "Allow local use of a Stellar CLI version newer than Caatinga's tested maximum").option("--verify-deps", "Verify dependency contract IDs exist on-chain before deploy").action((contractName, options) => runCliAction(async () => {
|
|
71
107
|
if (options.deps === false && !contractName) {
|
|
72
108
|
throw new CaatingaError(
|
|
73
109
|
"`--no-deps` requires a contract name.",
|
|
@@ -83,14 +119,23 @@ function registerDeployCommand(program2) {
|
|
|
83
119
|
source: options.source,
|
|
84
120
|
includeDependencies: options.deps !== false,
|
|
85
121
|
force: options.force === true,
|
|
122
|
+
checkStaleWasm: options.staleCheck !== false,
|
|
123
|
+
verifyDeps: options.verifyDeps === true,
|
|
86
124
|
allowUntestedStellarCli: options.allowUntestedStellarCli === true
|
|
87
125
|
});
|
|
126
|
+
for (const warning of result.staleWasmWarnings) {
|
|
127
|
+
logger.warn(warning.message);
|
|
128
|
+
}
|
|
88
129
|
logger.success("Deploy complete");
|
|
89
130
|
logger.info("");
|
|
90
131
|
logger.info(`Network: ${result.network.name}`);
|
|
132
|
+
for (const skipped of result.skippedContracts) {
|
|
133
|
+
logger.info(`[skipped] ${skipped.name} \u2014 already deployed on ${result.network.name}`);
|
|
134
|
+
logger.info(` Contract ID: ${skipped.contractId}`);
|
|
135
|
+
}
|
|
91
136
|
for (const contract of result.deployedContracts) {
|
|
92
|
-
logger.info(`
|
|
93
|
-
logger.info(`Contract ID: ${contract.contractId}`);
|
|
137
|
+
logger.info(`[deployed] ${contract.name}`);
|
|
138
|
+
logger.info(` Contract ID: ${contract.contractId}`);
|
|
94
139
|
}
|
|
95
140
|
logger.info("Artifacts updated: caatinga.artifacts.json");
|
|
96
141
|
}));
|
|
@@ -108,11 +153,248 @@ function registerDevCommand(program2) {
|
|
|
108
153
|
dev.configureHelp({ visibleOptions: () => [] });
|
|
109
154
|
}
|
|
110
155
|
|
|
156
|
+
// src/commands/doctor.command.ts
|
|
157
|
+
import { access } from "fs/promises";
|
|
158
|
+
import {
|
|
159
|
+
assertSupportedStellarCliVersion,
|
|
160
|
+
CaatingaError as CaatingaError2,
|
|
161
|
+
CaatingaErrorCode as CaatingaErrorCode2,
|
|
162
|
+
loadConfig as loadConfig4,
|
|
163
|
+
parseStellarCliVersion,
|
|
164
|
+
readArtifacts as readArtifacts2,
|
|
165
|
+
resolveNetwork as resolveNetwork2,
|
|
166
|
+
runCommand,
|
|
167
|
+
validateSourceShape
|
|
168
|
+
} from "@caatinga/core";
|
|
169
|
+
|
|
170
|
+
// src/commands/doctor-deploy-coverage.ts
|
|
171
|
+
import { loadConfig as loadConfig3, readArtifacts, resolveNetwork } from "@caatinga/core";
|
|
172
|
+
async function evaluateDeployCoverage(options) {
|
|
173
|
+
const cwd = options.cwd;
|
|
174
|
+
const config = await loadConfig3({ cwd });
|
|
175
|
+
const network = resolveNetwork(config, options.networkName);
|
|
176
|
+
const artifacts = await readArtifacts(cwd);
|
|
177
|
+
const lines = [];
|
|
178
|
+
for (const name of Object.keys(config.contracts)) {
|
|
179
|
+
const contractId = artifacts.networks[network.name]?.contracts[name]?.contractId;
|
|
180
|
+
if (contractId) {
|
|
181
|
+
lines.push({ name, ok: true, contractId });
|
|
182
|
+
} else {
|
|
183
|
+
lines.push({
|
|
184
|
+
name,
|
|
185
|
+
ok: false,
|
|
186
|
+
fix: `Run: caatinga deploy ${name} --network ${network.name}`
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return { lines, complete: lines.every((line) => line.ok) };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// src/commands/doctor.command.ts
|
|
194
|
+
var NODE_MIN_MAJOR2 = 20;
|
|
195
|
+
var WASM_TARGET = "wasm32v1-none";
|
|
196
|
+
function nodeDiagnostic() {
|
|
197
|
+
const version = process.versions.node;
|
|
198
|
+
const major = Number.parseInt(version.split(".")[0] ?? "0", 10);
|
|
199
|
+
if (major < NODE_MIN_MAJOR2) {
|
|
200
|
+
return {
|
|
201
|
+
ok: false,
|
|
202
|
+
label: `Node.js ${version} is below the required minimum ${NODE_MIN_MAJOR2}.0.0`,
|
|
203
|
+
fix: `Install Node.js ${NODE_MIN_MAJOR2} or newer.`
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return { ok: true, label: `Node.js ${version}` };
|
|
207
|
+
}
|
|
208
|
+
async function stellarDiagnostic(allowUntested) {
|
|
209
|
+
try {
|
|
210
|
+
const result = await runCommand("stellar", ["--version"], {
|
|
211
|
+
skipStellarVersionCheck: true
|
|
212
|
+
});
|
|
213
|
+
const version = assertSupportedStellarCliVersion({
|
|
214
|
+
version: parseStellarCliVersion(result.all || result.stdout || result.stderr),
|
|
215
|
+
allowUntested
|
|
216
|
+
});
|
|
217
|
+
return { ok: true, label: `Stellar CLI ${version}` };
|
|
218
|
+
} catch (error) {
|
|
219
|
+
const hint = error instanceof CaatingaError2 ? error.hint : void 0;
|
|
220
|
+
return {
|
|
221
|
+
ok: false,
|
|
222
|
+
label: "Stellar CLI not ready",
|
|
223
|
+
fix: hint ?? "Install Stellar CLI: cargo install --locked stellar-cli --version 25.2.0"
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async function rustDiagnostic() {
|
|
228
|
+
try {
|
|
229
|
+
const result = await runCommand("rustc", ["--version"]);
|
|
230
|
+
return { ok: true, label: result.stdout || result.all || "Rust installed" };
|
|
231
|
+
} catch {
|
|
232
|
+
return {
|
|
233
|
+
ok: false,
|
|
234
|
+
label: "Rust not found",
|
|
235
|
+
fix: "Install Rust, then run: rustup target add wasm32v1-none"
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async function wasmTargetDiagnostic() {
|
|
240
|
+
try {
|
|
241
|
+
const result = await runCommand("rustup", ["target", "list", "--installed"]);
|
|
242
|
+
const installedTargets = result.stdout || result.all;
|
|
243
|
+
if (installedTargets.split(/\r?\n/).includes(WASM_TARGET)) {
|
|
244
|
+
return { ok: true, label: `${WASM_TARGET} target installed` };
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
ok: false,
|
|
248
|
+
label: `${WASM_TARGET} target not installed`,
|
|
249
|
+
fix: `Run: rustup target add ${WASM_TARGET}`
|
|
250
|
+
};
|
|
251
|
+
} catch {
|
|
252
|
+
return {
|
|
253
|
+
ok: false,
|
|
254
|
+
label: "rustup not found",
|
|
255
|
+
fix: "Install rustup, then run: rustup target add wasm32v1-none"
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async function configDiagnostic() {
|
|
260
|
+
try {
|
|
261
|
+
await loadConfig4();
|
|
262
|
+
return { ok: true, label: "caatinga.config.ts found" };
|
|
263
|
+
} catch (error) {
|
|
264
|
+
const hint = error instanceof CaatingaError2 ? error.hint : void 0;
|
|
265
|
+
return {
|
|
266
|
+
ok: false,
|
|
267
|
+
label: "caatinga.config.ts not ready",
|
|
268
|
+
fix: hint ?? "Run this command from a Caatinga project root."
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function artifactsDiagnostic() {
|
|
273
|
+
try {
|
|
274
|
+
await access("caatinga.artifacts.json");
|
|
275
|
+
await readArtifacts2();
|
|
276
|
+
return { ok: true, label: "caatinga.artifacts.json found" };
|
|
277
|
+
} catch {
|
|
278
|
+
return {
|
|
279
|
+
ok: false,
|
|
280
|
+
label: "caatinga.artifacts.json not found or invalid",
|
|
281
|
+
fix: "Run caatinga init, or restore a valid caatinga.artifacts.json file."
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async function networkDiagnostic(networkName) {
|
|
286
|
+
if (!networkName) return void 0;
|
|
287
|
+
try {
|
|
288
|
+
const config = await loadConfig4();
|
|
289
|
+
const network = resolveNetwork2(config, networkName);
|
|
290
|
+
return { ok: true, label: `network ${network.name} found` };
|
|
291
|
+
} catch (error) {
|
|
292
|
+
const hint = error instanceof CaatingaError2 ? error.hint : void 0;
|
|
293
|
+
return {
|
|
294
|
+
ok: false,
|
|
295
|
+
label: `network ${networkName} not found`,
|
|
296
|
+
fix: hint ?? `Add "${networkName}" to caatinga.config.ts networks.`
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async function sourceDiagnostic(source) {
|
|
301
|
+
if (!source) return void 0;
|
|
302
|
+
const unsafeSource = validateSourceShape(source);
|
|
303
|
+
if (unsafeSource) {
|
|
304
|
+
return {
|
|
305
|
+
ok: false,
|
|
306
|
+
label: `source identity ${source} rejected (${unsafeSource.code})`,
|
|
307
|
+
fix: unsafeSource.hint
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
await runCommand("stellar", ["keys", "public-key", source]);
|
|
312
|
+
return { ok: true, label: `source identity ${source} found` };
|
|
313
|
+
} catch {
|
|
314
|
+
return {
|
|
315
|
+
ok: false,
|
|
316
|
+
label: `source identity ${source} not found`,
|
|
317
|
+
fix: `Create and fund it: stellar keys generate ${source} --fund --network testnet`
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function printDiagnostic(diagnostic) {
|
|
322
|
+
logger.info(`${diagnostic.ok ? "\u2713" : "\u2717"} ${diagnostic.label}`);
|
|
323
|
+
}
|
|
324
|
+
function printFixes(diagnostics) {
|
|
325
|
+
const failures = diagnostics.filter((diagnostic) => !diagnostic.ok);
|
|
326
|
+
if (failures.length === 0) return;
|
|
327
|
+
logger.info("");
|
|
328
|
+
logger.info("Fix:");
|
|
329
|
+
for (const failure of failures) {
|
|
330
|
+
if (failure.fix) logger.info(failure.fix);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function printDeployCoverageLine(line) {
|
|
334
|
+
if (line.ok) {
|
|
335
|
+
logger.info(`\u2713 ${line.name} \u2014 ${line.contractId}`);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
logger.info(`\u2717 ${line.name}`);
|
|
339
|
+
if (line.fix) logger.info(` ${line.fix}`);
|
|
340
|
+
}
|
|
341
|
+
async function reportDeployCoverage(networkName) {
|
|
342
|
+
const coverage = await evaluateDeployCoverage({ networkName });
|
|
343
|
+
logger.info("");
|
|
344
|
+
logger.info(`Deploy coverage (${networkName}):`);
|
|
345
|
+
for (const line of coverage.lines) {
|
|
346
|
+
printDeployCoverageLine(line);
|
|
347
|
+
}
|
|
348
|
+
if (!coverage.complete) {
|
|
349
|
+
const missing = coverage.lines.filter((line) => !line.ok).map((line) => line.name);
|
|
350
|
+
throw new CaatingaError2(
|
|
351
|
+
`Not all configured contracts are deployed on ${networkName}.`,
|
|
352
|
+
CaatingaErrorCode2.DOCTOR_PARTIAL_DEPLOY,
|
|
353
|
+
`Deploy missing contracts: ${missing.join(", ")}. See the commands above.`
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
function registerDoctorCommand(program2) {
|
|
359
|
+
program2.command("doctor").description("Check local Caatinga, Stellar CLI, Rust, config, and source identity setup").option("-n, --network <network>", "Configured network name to validate").option("-s, --source <source>", "Stellar CLI identity alias to validate").option("--allow-untested-stellar-cli", "Allow local use of a Stellar CLI version newer than Caatinga's tested maximum").action((options) => runCliAction(async () => {
|
|
360
|
+
logger.info("Caatinga Doctor");
|
|
361
|
+
logger.info("");
|
|
362
|
+
const diagnostics = [
|
|
363
|
+
nodeDiagnostic(),
|
|
364
|
+
await stellarDiagnostic(options.allowUntestedStellarCli === true),
|
|
365
|
+
await rustDiagnostic(),
|
|
366
|
+
await wasmTargetDiagnostic(),
|
|
367
|
+
await configDiagnostic(),
|
|
368
|
+
await artifactsDiagnostic(),
|
|
369
|
+
await networkDiagnostic(options.network),
|
|
370
|
+
await sourceDiagnostic(options.source)
|
|
371
|
+
].filter((diagnostic) => diagnostic !== void 0);
|
|
372
|
+
for (const diagnostic of diagnostics) {
|
|
373
|
+
printDiagnostic(diagnostic);
|
|
374
|
+
}
|
|
375
|
+
printFixes(diagnostics);
|
|
376
|
+
let ready = diagnostics.every((diagnostic) => diagnostic.ok);
|
|
377
|
+
if (options.network && ready) {
|
|
378
|
+
try {
|
|
379
|
+
await reportDeployCoverage(options.network);
|
|
380
|
+
} catch (error) {
|
|
381
|
+
ready = false;
|
|
382
|
+
throw error;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
logger.info("");
|
|
386
|
+
logger.info(`Status: ${ready ? "ready" : "blocked"}`);
|
|
387
|
+
if (!ready) {
|
|
388
|
+
process.exitCode = 1;
|
|
389
|
+
}
|
|
390
|
+
}));
|
|
391
|
+
}
|
|
392
|
+
|
|
111
393
|
// src/commands/generate.command.ts
|
|
112
|
-
import { generateBindings, loadConfig as
|
|
394
|
+
import { generateBindings, loadConfig as loadConfig5 } from "@caatinga/core";
|
|
113
395
|
function registerGenerateCommand(program2) {
|
|
114
396
|
program2.command("generate").description("Generate TypeScript bindings for a deployed contract").argument("<contract>", "Contract name").option("-n, --network <network>", "Configured network name").option("--allow-untested-stellar-cli", "Allow local use of a Stellar CLI version newer than Caatinga's tested maximum").action((contractName, options) => runCliAction(async () => {
|
|
115
|
-
const config = await
|
|
397
|
+
const config = await loadConfig5();
|
|
116
398
|
const result = await generateBindings({
|
|
117
399
|
config,
|
|
118
400
|
contractName,
|
|
@@ -132,10 +414,10 @@ import path2 from "path";
|
|
|
132
414
|
import { createProjectFromTemplate } from "@caatinga/core";
|
|
133
415
|
|
|
134
416
|
// src/utils/template-path.ts
|
|
135
|
-
import { access } from "fs/promises";
|
|
417
|
+
import { access as access2 } from "fs/promises";
|
|
136
418
|
import path from "path";
|
|
137
419
|
import { fileURLToPath } from "url";
|
|
138
|
-
import { CaatingaError as
|
|
420
|
+
import { CaatingaError as CaatingaError3, CaatingaErrorCode as CaatingaErrorCode3 } from "@caatinga/core";
|
|
139
421
|
async function resolveTemplateDir(templateName) {
|
|
140
422
|
const envTemplatesDir = process.env.CAATINGA_TEMPLATES_DIR;
|
|
141
423
|
const candidates = [
|
|
@@ -145,14 +427,14 @@ async function resolveTemplateDir(templateName) {
|
|
|
145
427
|
].filter((candidate) => Boolean(candidate));
|
|
146
428
|
for (const candidate of candidates) {
|
|
147
429
|
try {
|
|
148
|
-
await
|
|
430
|
+
await access2(candidate);
|
|
149
431
|
return candidate;
|
|
150
432
|
} catch {
|
|
151
433
|
}
|
|
152
434
|
}
|
|
153
|
-
throw new
|
|
435
|
+
throw new CaatingaError3(
|
|
154
436
|
`Template "${templateName}" was not found.`,
|
|
155
|
-
|
|
437
|
+
CaatingaErrorCode3.TEMPLATE_NOT_FOUND,
|
|
156
438
|
"Set CAATINGA_TEMPLATES_DIR or run from a Caatinga checkout that includes packages/templates."
|
|
157
439
|
);
|
|
158
440
|
}
|
|
@@ -191,15 +473,18 @@ function registerInitCommand(program2) {
|
|
|
191
473
|
logger.info("Next steps:");
|
|
192
474
|
logger.info(` cd ${projectDirectory}`);
|
|
193
475
|
logger.info(" npm install");
|
|
194
|
-
|
|
476
|
+
const defaultContract = result.template.contracts.default;
|
|
477
|
+
logger.info(
|
|
478
|
+
defaultContract ? ` npx caatinga build ${defaultContract}` : " npx caatinga build"
|
|
479
|
+
);
|
|
195
480
|
}));
|
|
196
481
|
}
|
|
197
482
|
|
|
198
483
|
// src/commands/invoke.command.ts
|
|
199
|
-
import { invokeContract, loadConfig as
|
|
484
|
+
import { invokeContract, loadConfig as loadConfig6 } from "@caatinga/core";
|
|
200
485
|
function registerInvokeCommand(program2) {
|
|
201
486
|
program2.command("invoke").description("Invoke a deployed contract function").argument("<target>", "Invoke target in contract.method format").argument("[args...]", "Arguments forwarded to Stellar CLI after the method name").option("-n, --network <network>", "Configured network name").requiredOption("-s, --source <source>", "Stellar CLI identity alias that can sign (for example alice)").option("--allow-untested-stellar-cli", "Allow local use of a Stellar CLI version newer than Caatinga's tested maximum").allowUnknownOption(true).allowExcessArguments(true).action((target, args, options) => runCliAction(async () => {
|
|
202
|
-
const config = await
|
|
487
|
+
const config = await loadConfig6();
|
|
203
488
|
const result = await invokeContract({
|
|
204
489
|
config,
|
|
205
490
|
target,
|
|
@@ -221,7 +506,7 @@ function registerInvokeCommand(program2) {
|
|
|
221
506
|
}
|
|
222
507
|
|
|
223
508
|
// src/version.ts
|
|
224
|
-
var CAATINGA_CLI_VERSION = "0.2.
|
|
509
|
+
var CAATINGA_CLI_VERSION = "0.2.2";
|
|
225
510
|
|
|
226
511
|
// src/program.ts
|
|
227
512
|
function createProgram() {
|
|
@@ -229,6 +514,7 @@ function createProgram() {
|
|
|
229
514
|
program2.name("caatinga").description("Developer toolkit for Stellar/Soroban dApps").version(CAATINGA_CLI_VERSION);
|
|
230
515
|
registerInitCommand(program2);
|
|
231
516
|
registerDevCommand(program2);
|
|
517
|
+
registerDoctorCommand(program2);
|
|
232
518
|
registerBuildCommand(program2);
|
|
233
519
|
registerDeployCommand(program2);
|
|
234
520
|
registerGenerateCommand(program2);
|
|
@@ -237,6 +523,7 @@ function createProgram() {
|
|
|
237
523
|
}
|
|
238
524
|
|
|
239
525
|
// src/index.ts
|
|
526
|
+
assertPreflight();
|
|
240
527
|
var program = createProgram();
|
|
241
528
|
void program.parseAsync(process.argv).catch((error) => {
|
|
242
529
|
console.error(error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caatinga/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Caatinga CLI for building dApps on Stellar/Soroban",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"stellar",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"LICENSE"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
+
"@caatinga/core": "^0.2.2",
|
|
46
47
|
"chalk": "^5.4.1",
|
|
47
|
-
"commander": "^12.1.0"
|
|
48
|
-
"@caatinga/core": "^0.2.1"
|
|
48
|
+
"commander": "^12.1.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"tsup": "^8.3.5",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# __PROJECT_NAME__
|
|
2
2
|
|
|
3
|
-
Experimental Caatinga multi-contract template.
|
|
3
|
+
Experimental Caatinga multi-contract template with a real constructor dependency.
|
|
4
4
|
|
|
5
5
|
## Deploy
|
|
6
6
|
|
|
@@ -9,6 +9,8 @@ npm install
|
|
|
9
9
|
npx caatinga build token
|
|
10
10
|
npx caatinga build marketplace
|
|
11
11
|
npx caatinga deploy --network testnet --source alice
|
|
12
|
+
npx caatinga generate token
|
|
13
|
+
npx caatinga generate marketplace
|
|
12
14
|
```
|
|
13
15
|
|
|
14
16
|
Deploy order:
|
|
@@ -16,4 +18,4 @@ Deploy order:
|
|
|
16
18
|
1. `token`
|
|
17
19
|
2. `marketplace`
|
|
18
20
|
|
|
19
|
-
`marketplace.deployArgs.tokenContractId` resolves from `${contracts.token.contractId}` after the token deploy writes `caatinga.artifacts.json`.
|
|
21
|
+
`marketplace.deployArgs.tokenContractId` resolves from `${contracts.token.contractId}` after the token deploy writes `caatinga.artifacts.json`. Caatinga passes that value to the contract `__constructor` as `--token_contract_id`.
|
|
@@ -6,11 +6,11 @@ export default defineConfig({
|
|
|
6
6
|
contracts: {
|
|
7
7
|
token: {
|
|
8
8
|
path: "./contracts/token",
|
|
9
|
-
wasm: "./contracts/token/target/
|
|
9
|
+
wasm: "./contracts/token/target/wasm32v1-none/release/token.wasm"
|
|
10
10
|
},
|
|
11
11
|
marketplace: {
|
|
12
12
|
path: "./contracts/marketplace",
|
|
13
|
-
wasm: "./contracts/marketplace/target/
|
|
13
|
+
wasm: "./contracts/marketplace/target/wasm32v1-none/release/marketplace.wasm",
|
|
14
14
|
dependsOn: ["token"],
|
|
15
15
|
deployArgs: {
|
|
16
16
|
tokenContractId: "${contracts.token.contractId}"
|