@caatinga/cli 2.1.0 → 2.2.1
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 -6
- package/dist/index.js +195 -13
- package/package.json +3 -3
- package/templates/marketplace-with-token/caatinga.template.json +1 -1
- package/templates/marketplace-with-token/package.json +3 -3
- package/templates/react-vite-counter/caatinga.template.json +1 -1
- package/templates/react-vite-counter/package.json +22 -7
- package/templates/react-vite-counter/pnpm-workspace.yaml +16 -9
- package/templates/react-vite-counter/src/App.tsx +17 -3
- package/templates/react-vite-counter/src/components/ContractNotDeployed.tsx +27 -0
- package/templates/react-vite-counter/src/components/CounterCard.tsx +1 -1
- package/templates/react-vite-counter/src/components/WalletButton.tsx +8 -7
- package/templates/react-vite-counter/src/components/WalletModal.tsx +248 -0
- package/templates/react-vite-counter/src/stubs/empty-wallet-dep/index.cjs +3 -0
- package/templates/react-vite-counter/src/stubs/empty-wallet-dep/package.json +6 -0
- package/templates/react-vite-counter/src/stubs/hot-wallet-sdk/index.cjs +7 -0
- package/templates/react-vite-counter/src/stubs/hot-wallet-sdk/package.json +6 -0
- package/templates/react-vite-counter/src/styles.css +261 -0
- package/templates/react-vite-counter/src/wallet-modal-controller.ts +73 -0
- package/templates/react-vite-counter/src/wallet.ts +9 -1
- package/templates/react-vite-counter/vite.config.ts +17 -1
- package/templates/react-vite-counter/src/context/WalletContext.tsx +0 -64
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @caatinga/cli
|
|
2
2
|
|
|
3
|
-
Developer toolkit for Stellar / Soroban dApps — `init`, `build`, `deploy`, `generate`, and `invoke`.
|
|
3
|
+
Developer toolkit for Stellar / Soroban dApps — `init`, `build`, `deploy`, `generate`, `status`, and `invoke`.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -35,11 +35,11 @@ npm install
|
|
|
35
35
|
|
|
36
36
|
npx caatinga build counter
|
|
37
37
|
npx caatinga deploy counter --network testnet --source alice
|
|
38
|
-
npx caatinga
|
|
38
|
+
npx caatinga status --network testnet
|
|
39
39
|
npx caatinga invoke counter.increment --network testnet --source alice
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
`build` only compiles the WASM file. `deploy` writes contract IDs to `caatinga.artifacts.json
|
|
42
|
+
`build` only compiles the WASM file. `deploy` writes contract IDs to `caatinga.artifacts.json` and then generates TypeScript bindings automatically under the path configured in `caatinga.config.ts` (templates default to `contracts/generated/`); pass `--no-generate` to skip. `status` shows what's deployed per network and whether bindings are fresh.
|
|
43
43
|
|
|
44
44
|
## Commands
|
|
45
45
|
|
|
@@ -49,10 +49,11 @@ npx caatinga invoke counter.increment --network testnet --source alice
|
|
|
49
49
|
| `caatinga doctor [--network <network>] [--source <identity>]` | Check local Node, Stellar CLI, Rust, config, artifacts, network, and source identity setup |
|
|
50
50
|
| `caatinga build [contract]` | Compile contract WASM through Stellar CLI (default contract: `counter`) |
|
|
51
51
|
| `caatinga deploy [contract]` | Deploy one contract or the full configured graph; record IDs in artifacts |
|
|
52
|
-
| `caatinga generate [contract]` |
|
|
52
|
+
| `caatinga generate [contract]` | (Re)generate TypeScript bindings; omit the name to generate for all deployed contracts |
|
|
53
|
+
| `caatinga status [--network <name>] [--json]` | Show deployed contracts and binding freshness per network |
|
|
53
54
|
| `caatinga invoke <contract.method>` | Invoke a deployed contract method; extra args forward to Stellar CLI |
|
|
54
55
|
|
|
55
|
-
The supported CLI flow is `init -> build -> deploy
|
|
56
|
+
The supported CLI flow is `init -> build -> deploy (bindings auto-generate) -> invoke`.
|
|
56
57
|
|
|
57
58
|
### `init`
|
|
58
59
|
|
|
@@ -78,12 +79,17 @@ The supported CLI flow is `init -> build -> deploy -> generate -> invoke`.
|
|
|
78
79
|
- `-s, --source <identity>` is required; must be a Stellar CLI identity alias that can sign (for example `alice`)
|
|
79
80
|
- `--force` redeploys even when artifacts already store a contract ID
|
|
80
81
|
- `--no-deps` skips dependency deployment for a single named contract (`--no-deps` requires `[contract]`)
|
|
82
|
+
- `--no-generate` skips the automatic bindings generation after deploy
|
|
81
83
|
|
|
82
84
|
Dependencies listed in `dependsOn` deploy first unless `--no-deps` is set. Deploy args may reference `${contracts.<name>.contractId}` placeholders resolved from artifacts.
|
|
83
85
|
|
|
84
|
-
|
|
86
|
+
After a successful deploy, bindings generate automatically for the deployed contracts. A generation failure never fails the deploy — the CLI prints a warning plus the recovery command (`npx caatinga generate --network <network>`).
|
|
87
|
+
|
|
88
|
+
### `generate`, `status`, and `invoke`
|
|
85
89
|
|
|
86
90
|
- `-n, --network <network>` selects the network used to resolve deployed contract IDs
|
|
91
|
+
- `generate` prints binding freshness per contract before regenerating in all-contracts mode
|
|
92
|
+
- `status` prints a per-network table (contract ID, WASM hash, deployed, binding freshness, dependencies); `--json` emits the machine-readable structure
|
|
87
93
|
- `invoke` expects `<contract.method>` (for example `counter.increment`) and forwards `[args...]` to the underlying Stellar invocation
|
|
88
94
|
|
|
89
95
|
`caatinga dev` is reserved, hidden in pre-v1 builds, and not part of the stability promise. Use your frontend dev server (for example Vite) alongside the commands above.
|
package/dist/index.js
CHANGED
|
@@ -161,9 +161,16 @@ async function warnIfDefaultNetworkNeedsDeploy(config) {
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
// src/commands/deploy.command.ts
|
|
164
|
-
import {
|
|
164
|
+
import {
|
|
165
|
+
deployContractGraph,
|
|
166
|
+
generateBindingsGraph,
|
|
167
|
+
toCaatingaError as toCaatingaError2,
|
|
168
|
+
CaatingaError as CaatingaError2,
|
|
169
|
+
CaatingaErrorCode as CaatingaErrorCode2,
|
|
170
|
+
loadConfig as loadConfig3
|
|
171
|
+
} from "@caatinga/core";
|
|
165
172
|
function registerDeployCommand(program2) {
|
|
166
|
-
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("--verify-deps", "Verify dependency contract IDs exist on-chain before deploy").action((contractName, options) => runCliAction(async () => {
|
|
173
|
+
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("--verify-deps", "Verify dependency contract IDs exist on-chain before deploy").option("--no-generate", "Skip TypeScript bindings generation after deploy").action((contractName, options) => runCliAction(async () => {
|
|
167
174
|
if (options.deps === false && !contractName) {
|
|
168
175
|
throw new CaatingaError2(
|
|
169
176
|
"`--no-deps` requires a contract name.",
|
|
@@ -197,15 +204,44 @@ function registerDeployCommand(program2) {
|
|
|
197
204
|
logger.info(` Contract ID: ${contract.contractId}`);
|
|
198
205
|
}
|
|
199
206
|
logger.info("Artifacts updated: caatinga.artifacts.json");
|
|
200
|
-
if (result.deployedContracts.length
|
|
207
|
+
if (result.deployedContracts.length === 0) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (options.generate === false) {
|
|
201
211
|
logger.info("");
|
|
212
|
+
logger.info("Bindings generation skipped (--no-generate).");
|
|
202
213
|
logger.info("Next:");
|
|
203
214
|
for (const contract of result.deployedContracts) {
|
|
204
215
|
logger.info(` npx caatinga generate ${contract.name} --network ${result.network.name}`);
|
|
205
216
|
}
|
|
206
217
|
logger.info(" npm run dev");
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
const generated = await generateBindingsGraph({
|
|
222
|
+
config,
|
|
223
|
+
contractNames: result.deployedContracts.map((contract) => contract.name),
|
|
224
|
+
networkName: result.network.name
|
|
225
|
+
});
|
|
226
|
+
logger.info("");
|
|
227
|
+
logger.success("Bindings generated");
|
|
228
|
+
for (const binding of generated.results) {
|
|
229
|
+
logger.info(` ${binding.contractName} \u2192 ${binding.importPath}`);
|
|
230
|
+
}
|
|
231
|
+
logger.info("");
|
|
232
|
+
logger.info("Next:");
|
|
233
|
+
logger.info(" npm run dev");
|
|
234
|
+
} catch (error) {
|
|
235
|
+
const caatingaError = toCaatingaError2(error);
|
|
207
236
|
logger.info("");
|
|
208
|
-
logger.
|
|
237
|
+
logger.warn("Deploy succeeded, but bindings generation failed.");
|
|
238
|
+
logger.warn(` ${caatingaError.message} (${caatingaError.code})`);
|
|
239
|
+
if (caatingaError.hint) {
|
|
240
|
+
logger.warn(` Hint: ${caatingaError.hint}`);
|
|
241
|
+
}
|
|
242
|
+
logger.info("");
|
|
243
|
+
logger.info("Recover with:");
|
|
244
|
+
logger.info(` npx caatinga generate --network ${result.network.name}`);
|
|
209
245
|
}
|
|
210
246
|
}));
|
|
211
247
|
}
|
|
@@ -398,6 +434,33 @@ function printFixes(diagnostics) {
|
|
|
398
434
|
}
|
|
399
435
|
}
|
|
400
436
|
|
|
437
|
+
// src/commands/doctor-bindings.ts
|
|
438
|
+
import {
|
|
439
|
+
evaluateBindingsFreshness,
|
|
440
|
+
loadConfig as loadConfig5,
|
|
441
|
+
readArtifacts as readArtifacts3,
|
|
442
|
+
resolveNetwork as resolveNetwork3
|
|
443
|
+
} from "@caatinga/core";
|
|
444
|
+
async function evaluateBindingCoverage(options) {
|
|
445
|
+
const cwd = options.cwd;
|
|
446
|
+
const config = await loadConfig5({ cwd });
|
|
447
|
+
const network = resolveNetwork3(config, options.networkName);
|
|
448
|
+
const artifacts = await readArtifacts3(cwd);
|
|
449
|
+
const freshness = await evaluateBindingsFreshness({
|
|
450
|
+
config,
|
|
451
|
+
artifacts,
|
|
452
|
+
networkName: network.name,
|
|
453
|
+
cwd
|
|
454
|
+
});
|
|
455
|
+
const lines = freshness.map((entry) => ({
|
|
456
|
+
name: entry.contractName,
|
|
457
|
+
status: entry.status,
|
|
458
|
+
reason: entry.reason,
|
|
459
|
+
...entry.status === "fresh" ? {} : { fix: `Run: caatinga generate ${entry.contractName} --network ${network.name}` }
|
|
460
|
+
}));
|
|
461
|
+
return { lines, allFresh: lines.every((line) => line.status === "fresh") };
|
|
462
|
+
}
|
|
463
|
+
|
|
401
464
|
// src/commands/doctor.command.ts
|
|
402
465
|
function printDeployCoverageLine(line) {
|
|
403
466
|
if (line.ok) {
|
|
@@ -424,6 +487,25 @@ async function reportDeployCoverage(networkName) {
|
|
|
424
487
|
}
|
|
425
488
|
return true;
|
|
426
489
|
}
|
|
490
|
+
function printBindingCoverageLine(line) {
|
|
491
|
+
if (line.status === "fresh") {
|
|
492
|
+
logger.info(`\u2713 ${line.name} \u2014 bindings fresh`);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
logger.info(`\u2717 ${line.name} \u2014 bindings ${line.status}${line.reason ? ` (${line.reason})` : ""}`);
|
|
496
|
+
if (line.fix) logger.info(` ${line.fix}`);
|
|
497
|
+
}
|
|
498
|
+
async function reportBindingCoverage(networkName) {
|
|
499
|
+
const coverage = await evaluateBindingCoverage({ networkName });
|
|
500
|
+
if (coverage.lines.length === 0) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
logger.info("");
|
|
504
|
+
logger.info(`Bindings (${networkName}):`);
|
|
505
|
+
for (const line of coverage.lines) {
|
|
506
|
+
printBindingCoverageLine(line);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
427
509
|
function registerDoctorCommand(program2) {
|
|
428
510
|
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").action((options) => runCliAction(async () => {
|
|
429
511
|
logger.info("Caatinga Doctor");
|
|
@@ -441,6 +523,7 @@ function registerDoctorCommand(program2) {
|
|
|
441
523
|
ready = false;
|
|
442
524
|
throw error;
|
|
443
525
|
}
|
|
526
|
+
await reportBindingCoverage(options.network);
|
|
444
527
|
}
|
|
445
528
|
logger.info("");
|
|
446
529
|
logger.info(`Status: ${ready ? "ready" : "blocked"}`);
|
|
@@ -451,11 +534,41 @@ function registerDoctorCommand(program2) {
|
|
|
451
534
|
}
|
|
452
535
|
|
|
453
536
|
// src/commands/generate.command.ts
|
|
454
|
-
import {
|
|
537
|
+
import {
|
|
538
|
+
evaluateBindingsFreshness as evaluateBindingsFreshness2,
|
|
539
|
+
generateBindingsGraph as generateBindingsGraph2,
|
|
540
|
+
loadConfig as loadConfig6,
|
|
541
|
+
readArtifacts as readArtifacts4,
|
|
542
|
+
resolveNetwork as resolveNetwork4
|
|
543
|
+
} from "@caatinga/core";
|
|
544
|
+
async function printFreshnessPreState(config, networkName) {
|
|
545
|
+
try {
|
|
546
|
+
const network = resolveNetwork4(config, networkName);
|
|
547
|
+
const artifacts = await readArtifacts4();
|
|
548
|
+
const freshness = await evaluateBindingsFreshness2({
|
|
549
|
+
config,
|
|
550
|
+
artifacts,
|
|
551
|
+
networkName: network.name
|
|
552
|
+
});
|
|
553
|
+
if (freshness.length === 0) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
logger.info("Current bindings:");
|
|
557
|
+
for (const entry of freshness) {
|
|
558
|
+
const reason = entry.reason ? ` \u2014 ${entry.reason}` : "";
|
|
559
|
+
logger.info(` [${entry.status}] ${entry.contractName}${reason}`);
|
|
560
|
+
}
|
|
561
|
+
logger.info("");
|
|
562
|
+
} catch {
|
|
563
|
+
}
|
|
564
|
+
}
|
|
455
565
|
function registerGenerateCommand(program2) {
|
|
456
566
|
program2.command("generate").description("Generate TypeScript bindings for deployed contracts").argument("[contract]", "Contract name (defaults to all deployed contracts)").option("-n, --network <network>", "Configured network name").action((contractName, options) => runCliAction(async () => {
|
|
457
|
-
const config = await
|
|
458
|
-
|
|
567
|
+
const config = await loadConfig6();
|
|
568
|
+
if (!contractName) {
|
|
569
|
+
await printFreshnessPreState(config, options.network);
|
|
570
|
+
}
|
|
571
|
+
const { network, results } = await generateBindingsGraph2({
|
|
459
572
|
config,
|
|
460
573
|
contractName,
|
|
461
574
|
networkName: options.network
|
|
@@ -562,26 +675,25 @@ function registerInitCommand(program2) {
|
|
|
562
675
|
logger.info(
|
|
563
676
|
` npx caatinga deploy ${defaultContract} --network testnet --source <identity>`
|
|
564
677
|
);
|
|
565
|
-
logger.info(` npx caatinga generate ${defaultContract} --network testnet`);
|
|
566
678
|
} else {
|
|
567
679
|
logger.info(" npx caatinga build");
|
|
568
680
|
logger.info(" npx caatinga deploy --network testnet --source <identity>");
|
|
569
|
-
logger.info(" npx caatinga generate --network testnet");
|
|
570
681
|
}
|
|
571
682
|
logger.info(" npm run dev");
|
|
572
683
|
logger.info("");
|
|
573
684
|
logger.info(
|
|
574
|
-
"Note: deploy
|
|
685
|
+
"Note: deploy generates TypeScript bindings automatically (--no-generate to skip) \u2014"
|
|
575
686
|
);
|
|
576
687
|
logger.info("the dApp reads the contract ID from caatinga.artifacts.json.");
|
|
688
|
+
logger.info("If generation fails, recover with: npx caatinga generate --network testnet");
|
|
577
689
|
}));
|
|
578
690
|
}
|
|
579
691
|
|
|
580
692
|
// src/commands/invoke.command.ts
|
|
581
|
-
import { invokeContract, loadConfig as
|
|
693
|
+
import { invokeContract, loadConfig as loadConfig7 } from "@caatinga/core";
|
|
582
694
|
function registerInvokeCommand(program2) {
|
|
583
695
|
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)").allowUnknownOption(true).allowExcessArguments(true).action((target, args, options) => runCliAction(async () => {
|
|
584
|
-
const config = await
|
|
696
|
+
const config = await loadConfig7();
|
|
585
697
|
const result = await invokeContract({
|
|
586
698
|
config,
|
|
587
699
|
target,
|
|
@@ -601,8 +713,77 @@ function registerInvokeCommand(program2) {
|
|
|
601
713
|
}));
|
|
602
714
|
}
|
|
603
715
|
|
|
716
|
+
// src/commands/status.command.ts
|
|
717
|
+
import { collectProjectStatus, loadConfig as loadConfig8 } from "@caatinga/core";
|
|
718
|
+
|
|
719
|
+
// src/utils/table.ts
|
|
720
|
+
function renderTable(headers, rows) {
|
|
721
|
+
const widths = headers.map(
|
|
722
|
+
(header, column) => Math.max(header.length, ...rows.map((row) => (row[column] ?? "").length))
|
|
723
|
+
);
|
|
724
|
+
const renderRow = (cells) => cells.map((cell, column) => (cell ?? "").padEnd(widths[column])).join(" ").trimEnd();
|
|
725
|
+
return [
|
|
726
|
+
renderRow(headers),
|
|
727
|
+
widths.map((width) => "\u2500".repeat(width)).join(" "),
|
|
728
|
+
...rows.map((row) => renderRow(row))
|
|
729
|
+
];
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// src/commands/status.command.ts
|
|
733
|
+
function shortId(value) {
|
|
734
|
+
if (!value) return "\u2014";
|
|
735
|
+
return value.length > 12 ? `${value.slice(0, 5)}\u2026${value.slice(-4)}` : value;
|
|
736
|
+
}
|
|
737
|
+
function shortHash(value) {
|
|
738
|
+
if (!value) return "\u2014";
|
|
739
|
+
return value.slice(0, 8);
|
|
740
|
+
}
|
|
741
|
+
function toRow(entry) {
|
|
742
|
+
return [
|
|
743
|
+
entry.name,
|
|
744
|
+
shortId(entry.contractId),
|
|
745
|
+
shortHash(entry.wasmHash),
|
|
746
|
+
entry.deployed ? "\u2713" : "\u2717",
|
|
747
|
+
entry.bindings.status,
|
|
748
|
+
entry.dependencies.length > 0 ? entry.dependencies.join(", ") : "\u2014"
|
|
749
|
+
];
|
|
750
|
+
}
|
|
751
|
+
function registerStatusCommand(program2) {
|
|
752
|
+
program2.command("status").description("Show deployed contracts and binding freshness per network").option("-n, --network <network>", "Configured network name").option("--json", "Print machine-readable JSON instead of the table").action((options) => runCliAction(async () => {
|
|
753
|
+
const config = await loadConfig8();
|
|
754
|
+
const status = await collectProjectStatus({
|
|
755
|
+
config,
|
|
756
|
+
networkName: options.network
|
|
757
|
+
});
|
|
758
|
+
if (options.json) {
|
|
759
|
+
console.log(JSON.stringify(status, null, 2));
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
logger.success(`Project: ${status.project}`);
|
|
763
|
+
for (const network of status.networks) {
|
|
764
|
+
logger.info("");
|
|
765
|
+
logger.info(`Network: ${network.network}`);
|
|
766
|
+
const lines = renderTable(
|
|
767
|
+
["CONTRACT", "CONTRACT ID", "WASM HASH", "DEPLOYED", "BINDINGS", "DEPS"],
|
|
768
|
+
network.contracts.map(toRow)
|
|
769
|
+
);
|
|
770
|
+
for (const line of lines) {
|
|
771
|
+
logger.info(line);
|
|
772
|
+
}
|
|
773
|
+
const needsAttention = network.contracts.filter(
|
|
774
|
+
(entry) => entry.deployed && entry.bindings.status !== "fresh"
|
|
775
|
+
);
|
|
776
|
+
for (const entry of needsAttention) {
|
|
777
|
+
logger.warn(
|
|
778
|
+
`Bindings ${entry.bindings.status} for ${entry.name}${entry.bindings.reason ? ` (${entry.bindings.reason})` : ""} \u2014 run: npx caatinga generate ${entry.name} --network ${network.network}`
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}));
|
|
783
|
+
}
|
|
784
|
+
|
|
604
785
|
// src/version.ts
|
|
605
|
-
var CAATINGA_CLI_VERSION = "2.1
|
|
786
|
+
var CAATINGA_CLI_VERSION = "2.2.1";
|
|
606
787
|
|
|
607
788
|
// src/program.ts
|
|
608
789
|
function createProgram() {
|
|
@@ -615,6 +796,7 @@ function createProgram() {
|
|
|
615
796
|
registerDeployCommand(program2);
|
|
616
797
|
registerGenerateCommand(program2);
|
|
617
798
|
registerInvokeCommand(program2);
|
|
799
|
+
registerStatusCommand(program2);
|
|
618
800
|
return program2;
|
|
619
801
|
}
|
|
620
802
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caatinga/cli",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Caatinga CLI for building dApps on Stellar/Soroban",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"stellar",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"LICENSE"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@caatinga/core": "^2.1
|
|
46
|
+
"@caatinga/core": "^2.2.1",
|
|
47
47
|
"chalk": "^5.4.1",
|
|
48
48
|
"commander": "^12.1.0"
|
|
49
49
|
},
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"vitest": "^2.1.8"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
|
-
"build": "tsup src/index.ts --format esm --dts --clean && rm -rf ./templates &&
|
|
57
|
+
"build": "tsup src/index.ts --format esm --dts --clean && rm -rf ./templates && mkdir ./templates && (cd ../templates && tar --exclude=node_modules --exclude=dist -cf - .) | (cd ./templates && tar -xf -)",
|
|
58
58
|
"predev": "pnpm --filter @caatinga/core build",
|
|
59
59
|
"dev": "tsx src/index.ts",
|
|
60
60
|
"test": "vitest run --pool=threads",
|
|
@@ -12,15 +12,15 @@
|
|
|
12
12
|
"caatinga:generate": "caatinga generate token && caatinga generate marketplace"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@caatinga/client": "^2.1
|
|
16
|
-
"@caatinga/core": "^2.1
|
|
15
|
+
"@caatinga/client": "^2.2.1",
|
|
16
|
+
"@caatinga/core": "^2.2.1",
|
|
17
17
|
"@vitejs/plugin-react": "^4.3.4",
|
|
18
18
|
"react": "^18.3.1",
|
|
19
19
|
"react-dom": "^18.3.1",
|
|
20
20
|
"vite": "^6.0.6"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@caatinga/cli": "^2.1
|
|
23
|
+
"@caatinga/cli": "^2.2.1",
|
|
24
24
|
"@types/react": "^18.3.18",
|
|
25
25
|
"@types/react-dom": "^18.3.5",
|
|
26
26
|
"typescript": "^5.7.2"
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
"dev": "vite",
|
|
8
8
|
"build": "tsc && vite build",
|
|
9
9
|
"preview": "vite preview",
|
|
10
|
-
"caatinga:build": "caatinga build counter",
|
|
11
|
-
"caatinga:deploy": "caatinga deploy counter",
|
|
12
|
-
"caatinga:generate": "caatinga generate counter"
|
|
10
|
+
"caatinga:build": "npx caatinga build counter",
|
|
11
|
+
"caatinga:deploy": "npx caatinga deploy counter --network testnet --source ${CAATINGA_SOURCE:-alice}",
|
|
12
|
+
"caatinga:generate": "npx caatinga generate counter --network testnet"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@caatinga/client": "^2.1
|
|
16
|
-
"@caatinga/core": "^2.1
|
|
17
|
-
"@creit.tech/stellar-wallets-kit": "^
|
|
15
|
+
"@caatinga/client": "^2.2.1",
|
|
16
|
+
"@caatinga/core": "^2.2.1",
|
|
17
|
+
"@creit.tech/stellar-wallets-kit": "^2.3.0",
|
|
18
18
|
"@stellar/stellar-sdk": "^14.5.0",
|
|
19
19
|
"buffer": "^6.0.3",
|
|
20
20
|
"@vitejs/plugin-react": "^4.3.4",
|
|
@@ -23,9 +23,24 @@
|
|
|
23
23
|
"vite": "^6.0.6"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@caatinga/cli": "^2.1
|
|
26
|
+
"@caatinga/cli": "^2.2.1",
|
|
27
27
|
"@types/react": "^18.3.18",
|
|
28
28
|
"@types/react-dom": "^18.3.5",
|
|
29
29
|
"typescript": "^5.7.2"
|
|
30
|
+
},
|
|
31
|
+
"overrides": {
|
|
32
|
+
"uuid": "^14.0.0",
|
|
33
|
+
"@creit.tech/stellar-wallets-kit": {
|
|
34
|
+
"@trezor/connect-web": "file:./src/stubs/empty-wallet-dep",
|
|
35
|
+
"@trezor/connect-plugin-stellar": "file:./src/stubs/empty-wallet-dep",
|
|
36
|
+
"@hot-wallet/sdk": "file:./src/stubs/hot-wallet-sdk"
|
|
37
|
+
},
|
|
38
|
+
"@reown/appkit-utils": {
|
|
39
|
+
"@safe-global/safe-apps-sdk": "-",
|
|
40
|
+
"@safe-global/safe-apps-provider": "-"
|
|
41
|
+
},
|
|
42
|
+
"@safe-global/safe-apps-sdk": {
|
|
43
|
+
"@safe-global/safe-gateway-typescript-sdk": "-"
|
|
44
|
+
}
|
|
30
45
|
}
|
|
31
46
|
}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
# pnpm
|
|
1
|
+
# pnpm-only file (npm / yarn / bun ignore it). pnpm 10.26+/11.x block lifecycle
|
|
2
|
+
# scripts by default; vite depends on esbuild's, so allow it.
|
|
3
|
+
# Install-time overrides block unused wallet SDK branches; vite.config.ts aliases
|
|
4
|
+
# provide a second layer so yarn/bun bundles stay clean too.
|
|
2
5
|
allowBuilds:
|
|
3
6
|
esbuild: true
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
ignoredOptionalDependencies:
|
|
9
|
+
- "@safe-global/safe-apps-provider"
|
|
10
|
+
- "@safe-global/safe-apps-sdk"
|
|
11
|
+
|
|
12
|
+
overrides:
|
|
13
|
+
uuid: "^14.0.0"
|
|
14
|
+
"@creit.tech/stellar-wallets-kit>@trezor/connect-web": "-"
|
|
15
|
+
"@creit.tech/stellar-wallets-kit>@trezor/connect-plugin-stellar": "-"
|
|
16
|
+
"@creit.tech/stellar-wallets-kit>@hot-wallet/sdk": "-"
|
|
17
|
+
"@reown/appkit-utils>@safe-global/safe-apps-sdk": "-"
|
|
18
|
+
"@reown/appkit-utils>@safe-global/safe-apps-provider": "-"
|
|
19
|
+
"@safe-global/safe-apps-sdk>@safe-global/safe-gateway-typescript-sdk": "-"
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import { WalletProvider, useWallet } from "@caatinga/client/react";
|
|
2
|
+
import type { CaatingaArtifacts } from "@caatinga/core/browser";
|
|
3
|
+
import artifactsJson from "../caatinga.artifacts.json";
|
|
4
|
+
import { ContractNotDeployed } from "./components/ContractNotDeployed";
|
|
1
5
|
import { CounterCard } from "./components/CounterCard";
|
|
2
6
|
import { WalletButton } from "./components/WalletButton";
|
|
3
|
-
import {
|
|
7
|
+
import { WalletModal } from "./components/WalletModal";
|
|
8
|
+
import { stellarWalletAdapter } from "./wallet.js";
|
|
9
|
+
|
|
10
|
+
const artifacts = artifactsJson as CaatingaArtifacts;
|
|
11
|
+
const counterContractId = artifacts.networks?.testnet?.contracts?.counter?.contractId;
|
|
12
|
+
const isDeployed = Boolean(counterContractId);
|
|
4
13
|
|
|
5
14
|
function AppBody() {
|
|
6
15
|
const { publicKey } = useWallet();
|
|
@@ -15,7 +24,9 @@ function AppBody() {
|
|
|
15
24
|
<WalletButton />
|
|
16
25
|
</header>
|
|
17
26
|
|
|
18
|
-
{
|
|
27
|
+
{!isDeployed ? (
|
|
28
|
+
<ContractNotDeployed />
|
|
29
|
+
) : publicKey ? (
|
|
19
30
|
<CounterCard />
|
|
20
31
|
) : (
|
|
21
32
|
<section className="counter-panel" aria-labelledby="connect-title">
|
|
@@ -35,8 +46,11 @@ function AppBody() {
|
|
|
35
46
|
|
|
36
47
|
export default function App() {
|
|
37
48
|
return (
|
|
38
|
-
|
|
49
|
+
// persist keeps the session across reloads; the provider silently
|
|
50
|
+
// reconnects on mount (autoConnect defaults to true when persisting).
|
|
51
|
+
<WalletProvider adapter={stellarWalletAdapter} options={{ persist: true }}>
|
|
39
52
|
<AppBody />
|
|
53
|
+
<WalletModal />
|
|
40
54
|
</WalletProvider>
|
|
41
55
|
);
|
|
42
56
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function ContractNotDeployed() {
|
|
2
|
+
return (
|
|
3
|
+
<section className="counter-panel" aria-labelledby="not-deployed-title">
|
|
4
|
+
<div className="counter-panel__header">
|
|
5
|
+
<div>
|
|
6
|
+
<p className="eyebrow">Get started</p>
|
|
7
|
+
<h2 id="not-deployed-title">Contract not deployed</h2>
|
|
8
|
+
</div>
|
|
9
|
+
<span className="network-pill">testnet</span>
|
|
10
|
+
</div>
|
|
11
|
+
<p>
|
|
12
|
+
The counter contract has no on-chain ID yet, so the frontend can't read or update it.
|
|
13
|
+
Build and deploy first — the dApp reads the contract ID from{" "}
|
|
14
|
+
<code>caatinga.artifacts.json</code>. Deploy also generates TypeScript bindings
|
|
15
|
+
automatically.
|
|
16
|
+
</p>
|
|
17
|
+
<pre className="counter-error" role="note">
|
|
18
|
+
{`npx caatinga build counter
|
|
19
|
+
npx caatinga deploy counter --network testnet --source <identity>
|
|
20
|
+
npm run dev
|
|
21
|
+
|
|
22
|
+
# If bindings generation failed after deploy:
|
|
23
|
+
npx caatinga generate counter --network testnet`}
|
|
24
|
+
</pre>
|
|
25
|
+
</section>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
2
|
import { caatingaClient } from "../caatinga.js";
|
|
3
3
|
import { formatCaatingaError } from "@caatinga/core/browser";
|
|
4
|
-
import { useWallet } from "
|
|
4
|
+
import { useWallet } from "@caatinga/client/react";
|
|
5
5
|
import { LoadingModal } from "./LoadingModal.js";
|
|
6
6
|
|
|
7
7
|
export function CounterCard() {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { useWallet } from "
|
|
1
|
+
import { useWallet } from "@caatinga/client/react";
|
|
2
|
+
import { WALLET_SELECTION_CLOSED_ERROR } from "../wallet-modal-controller.js";
|
|
2
3
|
|
|
3
4
|
function shortenAddress(address: string): string {
|
|
4
5
|
if (address.length <= 12) {
|
|
@@ -9,23 +10,23 @@ function shortenAddress(address: string): string {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export function WalletButton() {
|
|
12
|
-
const { publicKey,
|
|
13
|
+
const { publicKey, connecting, error, connect, disconnect } = useWallet();
|
|
13
14
|
|
|
14
15
|
return (
|
|
15
16
|
<div className="wallet-shell">
|
|
16
17
|
<button
|
|
17
18
|
className="wallet-button"
|
|
18
19
|
type="button"
|
|
19
|
-
onClick={publicKey ? () => void disconnect() : () => void connect()}
|
|
20
|
-
disabled={
|
|
20
|
+
onClick={publicKey ? () => void disconnect() : () => void connect().catch(() => {})}
|
|
21
|
+
disabled={connecting}
|
|
21
22
|
aria-live="polite"
|
|
22
23
|
>
|
|
23
24
|
<span className={publicKey ? "status-dot status-dot--on" : "status-dot"} />
|
|
24
|
-
{
|
|
25
|
+
{connecting ? "Connecting..." : publicKey ? shortenAddress(publicKey) : "Connect"}
|
|
25
26
|
</button>
|
|
26
|
-
{error ? (
|
|
27
|
+
{error && error.name !== WALLET_SELECTION_CLOSED_ERROR ? (
|
|
27
28
|
<p className="wallet-error" role="alert">
|
|
28
|
-
{error}
|
|
29
|
+
{error.message}
|
|
29
30
|
</p>
|
|
30
31
|
) : null}
|
|
31
32
|
</div>
|