@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.
Files changed (33) hide show
  1. package/README.md +11 -4
  2. package/dist/index.js +325 -38
  3. package/package.json +3 -3
  4. package/templates/marketplace-with-token/README.md +4 -2
  5. package/templates/marketplace-with-token/caatinga.config.ts +2 -2
  6. package/templates/marketplace-with-token/caatinga.template.json +1 -1
  7. package/templates/marketplace-with-token/contracts/marketplace/Cargo.lock +1731 -0
  8. package/templates/marketplace-with-token/contracts/marketplace/Cargo.toml +1 -0
  9. package/templates/marketplace-with-token/contracts/marketplace/src/lib.rs +31 -1
  10. package/templates/marketplace-with-token/contracts/token/Cargo.lock +1731 -0
  11. package/templates/marketplace-with-token/contracts/token/Cargo.toml +1 -0
  12. package/templates/marketplace-with-token/index.html +12 -0
  13. package/templates/marketplace-with-token/package.json +14 -3
  14. package/templates/marketplace-with-token/src/App.tsx +57 -0
  15. package/templates/marketplace-with-token/src/main.ts +3 -1
  16. package/templates/marketplace-with-token/src/main.tsx +10 -0
  17. package/templates/marketplace-with-token/src/styles.css +157 -0
  18. package/templates/marketplace-with-token/tsconfig.json +14 -4
  19. package/templates/marketplace-with-token/vite.config.ts +6 -0
  20. package/templates/react-vite-counter/README.md +1 -1
  21. package/templates/react-vite-counter/caatinga.artifacts.json +10 -0
  22. package/templates/react-vite-counter/caatinga.config.ts +1 -1
  23. package/templates/react-vite-counter/caatinga.template.json +1 -1
  24. package/templates/react-vite-counter/contracts/counter/Cargo.lock +1731 -0
  25. package/templates/react-vite-counter/contracts/counter/Cargo.toml +1 -0
  26. package/templates/react-vite-counter/package.json +3 -3
  27. package/templates/react-vite-counter/src/caatinga.ts +20 -0
  28. package/templates/react-vite-counter/src/components/CounterCard.tsx +40 -3
  29. package/templates/react-vite-counter/src/components/WalletButton.tsx +58 -5
  30. package/templates/react-vite-counter/src/contracts/generated/counter.ts +49 -0
  31. package/templates/react-vite-counter/src/styles.css +21 -0
  32. package/templates/react-vite-counter/tsconfig.json +1 -1
  33. 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) `>=22.0.0` and `<=25.2.0` on `PATH`
18
- - Rust stable and the `wasm32-unknown-unknown` target (contract builds)
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 wasm32-unknown-unknown
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 chalk from "chalk";
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(chalk.green(message));
74
+ console.log(chalk3.green(message));
20
75
  },
21
76
  warn(message) {
22
- console.warn(chalk.yellow(message));
77
+ console.warn(chalk3.yellow(message));
23
78
  },
24
79
  error(message) {
25
- console.error(chalk.red(message));
80
+ console.error(chalk3.red(message));
26
81
  },
27
82
  muted(message) {
28
- console.log(chalk.gray(message));
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(`Contract: ${contract.name}`);
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 loadConfig3 } from "@caatinga/core";
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 loadConfig3();
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 CaatingaError2, CaatingaErrorCode as CaatingaErrorCode2 } from "@caatinga/core";
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 access(candidate);
430
+ await access2(candidate);
149
431
  return candidate;
150
432
  } catch {
151
433
  }
152
434
  }
153
- throw new CaatingaError2(
435
+ throw new CaatingaError3(
154
436
  `Template "${templateName}" was not found.`,
155
- CaatingaErrorCode2.TEMPLATE_NOT_FOUND,
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
- logger.info(" npx caatinga build counter");
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 loadConfig4 } from "@caatinga/core";
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 loadConfig4();
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.1";
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.1",
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/wasm32-unknown-unknown/release/token.wasm"
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/wasm32-unknown-unknown/release/marketplace.wasm",
13
+ wasm: "./contracts/marketplace/target/wasm32v1-none/release/marketplace.wasm",
14
14
  dependsOn: ["token"],
15
15
  deployArgs: {
16
16
  tokenContractId: "${contracts.token.contractId}"
@@ -3,7 +3,7 @@
3
3
  "version": "0.1.0",
4
4
  "description": "Experimental multi-contract Soroban template with token dependency injection.",
5
5
  "caatinga": {
6
- "compatibleCore": "^0.2.1",
6
+ "compatibleCore": "^0.2.2",
7
7
  "templateVersion": 1
8
8
  },
9
9
  "frontend": {