@caatinga/cli 0.2.0 → 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 (34) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +101 -34
  3. package/dist/index.js +326 -39
  4. package/package.json +2 -2
  5. package/templates/marketplace-with-token/README.md +4 -2
  6. package/templates/marketplace-with-token/caatinga.config.ts +2 -2
  7. package/templates/marketplace-with-token/caatinga.template.json +1 -1
  8. package/templates/marketplace-with-token/contracts/marketplace/Cargo.lock +1731 -0
  9. package/templates/marketplace-with-token/contracts/marketplace/Cargo.toml +1 -0
  10. package/templates/marketplace-with-token/contracts/marketplace/src/lib.rs +31 -1
  11. package/templates/marketplace-with-token/contracts/token/Cargo.lock +1731 -0
  12. package/templates/marketplace-with-token/contracts/token/Cargo.toml +1 -0
  13. package/templates/marketplace-with-token/index.html +12 -0
  14. package/templates/marketplace-with-token/package.json +14 -3
  15. package/templates/marketplace-with-token/src/App.tsx +57 -0
  16. package/templates/marketplace-with-token/src/main.ts +3 -1
  17. package/templates/marketplace-with-token/src/main.tsx +10 -0
  18. package/templates/marketplace-with-token/src/styles.css +157 -0
  19. package/templates/marketplace-with-token/tsconfig.json +14 -4
  20. package/templates/marketplace-with-token/vite.config.ts +6 -0
  21. package/templates/react-vite-counter/README.md +1 -1
  22. package/templates/react-vite-counter/caatinga.artifacts.json +10 -0
  23. package/templates/react-vite-counter/caatinga.config.ts +1 -1
  24. package/templates/react-vite-counter/caatinga.template.json +1 -1
  25. package/templates/react-vite-counter/contracts/counter/Cargo.lock +1731 -0
  26. package/templates/react-vite-counter/contracts/counter/Cargo.toml +1 -0
  27. package/templates/react-vite-counter/package.json +3 -3
  28. package/templates/react-vite-counter/src/caatinga.ts +20 -0
  29. package/templates/react-vite-counter/src/components/CounterCard.tsx +40 -3
  30. package/templates/react-vite-counter/src/components/WalletButton.tsx +58 -5
  31. package/templates/react-vite-counter/src/contracts/generated/counter.ts +49 -0
  32. package/templates/react-vite-counter/src/styles.css +21 -0
  33. package/templates/react-vite-counter/tsconfig.json +1 -1
  34. package/templates/react-vite-counter/src/contracts/generated/.gitkeep +0 -1
@@ -1,6 +1,7 @@
1
1
  [package]
2
2
  name = "counter"
3
3
  version = "0.1.0"
4
+ rust-version = "1.84.0"
4
5
  edition = "2021"
5
6
 
6
7
  [lib]
@@ -12,8 +12,8 @@
12
12
  "caatinga:generate": "caatinga generate counter"
13
13
  },
14
14
  "dependencies": {
15
- "@caatinga/client": "^0.2.0",
16
- "@caatinga/core": "^0.2.0",
15
+ "@caatinga/client": "^0.2.2",
16
+ "@caatinga/core": "^0.2.2",
17
17
  "@stellar/freighter-api": "^4.0.0",
18
18
  "@vitejs/plugin-react": "^4.3.4",
19
19
  "vite": "^6.0.6",
@@ -21,7 +21,7 @@
21
21
  "react-dom": "^18.3.1"
22
22
  },
23
23
  "devDependencies": {
24
- "@caatinga/cli": "^0.2.0",
24
+ "@caatinga/cli": "^0.2.2",
25
25
  "@types/react": "^18.3.18",
26
26
  "@types/react-dom": "^18.3.5",
27
27
  "typescript": "^5.7.2"
@@ -0,0 +1,20 @@
1
+ import { createCaatingaClient } from "@caatinga/client";
2
+ import { freighterWalletAdapter } from "@caatinga/client/freighter";
3
+ import type { CaatingaArtifacts } from "@caatinga/core/browser";
4
+ import artifactsJson from "../caatinga.artifacts.json";
5
+ import * as Counter from "./contracts/generated/counter.js";
6
+
7
+ const artifacts = artifactsJson as CaatingaArtifacts;
8
+
9
+ export const caatingaClient = createCaatingaClient({
10
+ network: {
11
+ name: "testnet",
12
+ rpcUrl: "https://soroban-testnet.stellar.org",
13
+ networkPassphrase: "Test SDF Network ; September 2015"
14
+ },
15
+ artifacts,
16
+ wallet: freighterWalletAdapter,
17
+ contracts: {
18
+ counter: { binding: Counter }
19
+ }
20
+ });
@@ -1,9 +1,40 @@
1
1
  import { useMemo, useState } from "react";
2
+ import { caatingaClient } from "../caatinga.js";
3
+ import { CaatingaError } from "@caatinga/core/browser";
4
+
5
+ function formatCaatingaError(error: unknown): string {
6
+ if (error instanceof CaatingaError) {
7
+ return `[${error.code}] ${error.message}\n\n${error.hint}`;
8
+ }
9
+
10
+ return error instanceof Error ? error.message : String(error);
11
+ }
2
12
 
3
13
  export function CounterCard() {
4
14
  const [count, setCount] = useState(0);
15
+ const [loading, setLoading] = useState(false);
16
+ const [error, setError] = useState<string | null>(null);
5
17
  const formattedCount = useMemo(() => new Intl.NumberFormat().format(count), [count]);
6
18
 
19
+ async function increment() {
20
+ setLoading(true);
21
+ setError(null);
22
+
23
+ try {
24
+ await caatingaClient.contract("counter").invoke("increment");
25
+ setCount((value) => value + 1);
26
+ } catch (caught) {
27
+ setError(formatCaatingaError(caught));
28
+ } finally {
29
+ setLoading(false);
30
+ }
31
+ }
32
+
33
+ function reset() {
34
+ setCount(0);
35
+ setError(null);
36
+ }
37
+
7
38
  return (
8
39
  <section className="counter-panel" aria-labelledby="counter-title">
9
40
  <div className="counter-panel__header">
@@ -17,13 +48,19 @@ export function CounterCard() {
17
48
  <div className="counter-value">{formattedCount}</div>
18
49
 
19
50
  <div className="counter-actions">
20
- <button type="button" onClick={() => setCount((value) => value + 1)}>
21
- Increment
51
+ <button type="button" onClick={increment} disabled={loading}>
52
+ {loading ? "Incrementing…" : "Increment"}
22
53
  </button>
23
- <button className="secondary-button" type="button" onClick={() => setCount(0)}>
54
+ <button className="secondary-button" type="button" onClick={reset} disabled={loading}>
24
55
  Reset
25
56
  </button>
26
57
  </div>
58
+
59
+ {error ? (
60
+ <pre className="counter-error" role="alert">
61
+ {error}
62
+ </pre>
63
+ ) : null}
27
64
  </section>
28
65
  );
29
66
  }
@@ -1,12 +1,65 @@
1
+ import { freighterWalletAdapter } from "@caatinga/client/freighter";
1
2
  import { useState } from "react";
3
+ import { CaatingaError } from "@caatinga/core/browser";
4
+
5
+ function formatWalletError(error: unknown): string {
6
+ if (error instanceof CaatingaError) {
7
+ return `[${error.code}] ${error.message}`;
8
+ }
9
+
10
+ return error instanceof Error ? error.message : String(error);
11
+ }
12
+
13
+ function shortenAddress(address: string): string {
14
+ if (address.length <= 12) {
15
+ return address;
16
+ }
17
+
18
+ return `${address.slice(0, 4)}…${address.slice(-4)}`;
19
+ }
2
20
 
3
21
  export function WalletButton() {
4
- const [connected, setConnected] = useState(false);
22
+ const [publicKey, setPublicKey] = useState<string | null>(null);
23
+ const [error, setError] = useState<string | null>(null);
24
+ const [loading, setLoading] = useState(false);
25
+
26
+ async function connect() {
27
+ setLoading(true);
28
+ setError(null);
29
+
30
+ try {
31
+ const key = await freighterWalletAdapter.getPublicKey();
32
+ setPublicKey(key);
33
+ } catch (caught) {
34
+ setPublicKey(null);
35
+ setError(formatWalletError(caught));
36
+ } finally {
37
+ setLoading(false);
38
+ }
39
+ }
40
+
41
+ function disconnect() {
42
+ setPublicKey(null);
43
+ setError(null);
44
+ }
5
45
 
6
46
  return (
7
- <button className="wallet-button" type="button" onClick={() => setConnected((value) => !value)}>
8
- <span className={connected ? "status-dot status-dot--on" : "status-dot"} />
9
- {connected ? "Connected" : "Connect"}
10
- </button>
47
+ <div className="wallet-shell">
48
+ <button
49
+ className="wallet-button"
50
+ type="button"
51
+ onClick={publicKey ? disconnect : connect}
52
+ disabled={loading}
53
+ aria-live="polite"
54
+ >
55
+ <span className={publicKey ? "status-dot status-dot--on" : "status-dot"} />
56
+ {loading ? "Connecting…" : publicKey ? shortenAddress(publicKey) : "Connect"}
57
+ </button>
58
+ {error ? (
59
+ <p className="wallet-error" role="alert">
60
+ {error}
61
+ </p>
62
+ ) : null}
63
+ </div>
11
64
  );
12
65
  }
@@ -0,0 +1,49 @@
1
+ type TransactionResult = {
2
+ txHash: string;
3
+ result?: unknown;
4
+ };
5
+
6
+ class ExampleTransaction {
7
+ constructor(
8
+ private readonly method: string,
9
+ private readonly result?: unknown
10
+ ) {}
11
+
12
+ toXDR(): string {
13
+ return `example-${this.method}-xdr`;
14
+ }
15
+
16
+ async prepare(): Promise<ExampleTransaction> {
17
+ return this;
18
+ }
19
+
20
+ async signAndSend(): Promise<TransactionResult> {
21
+ return {
22
+ txHash: "example-transaction-hash",
23
+ result: this.result
24
+ };
25
+ }
26
+ }
27
+
28
+ export class Client {
29
+ constructor(
30
+ private readonly input: {
31
+ contractId: string;
32
+ publicKey: string;
33
+ rpcUrl: string;
34
+ networkPassphrase: string;
35
+ }
36
+ ) {}
37
+
38
+ increment(): ExampleTransaction {
39
+ return new ExampleTransaction("increment");
40
+ }
41
+
42
+ get(): ExampleTransaction {
43
+ return new ExampleTransaction("get", 1);
44
+ }
45
+
46
+ describe(): string {
47
+ return `${this.input.contractId}:${this.input.publicKey}`;
48
+ }
49
+ }
@@ -72,6 +72,27 @@ button:hover {
72
72
  text-transform: uppercase;
73
73
  }
74
74
 
75
+ .wallet-shell {
76
+ display: flex;
77
+ flex-direction: column;
78
+ align-items: flex-end;
79
+ gap: 8px;
80
+ }
81
+
82
+ .wallet-error,
83
+ .counter-error {
84
+ margin: 0;
85
+ max-width: min(360px, 100%);
86
+ color: #8b1e1e;
87
+ font-size: 0.82rem;
88
+ line-height: 1.4;
89
+ white-space: pre-wrap;
90
+ }
91
+
92
+ .counter-error {
93
+ margin-top: 16px;
94
+ }
95
+
75
96
  .wallet-button,
76
97
  .network-pill {
77
98
  display: inline-flex;
@@ -10,7 +10,7 @@
10
10
  "strict": true,
11
11
  "forceConsistentCasingInFileNames": true,
12
12
  "module": "ESNext",
13
- "moduleResolution": "Node",
13
+ "moduleResolution": "bundler",
14
14
  "resolveJsonModule": true,
15
15
  "isolatedModules": true,
16
16
  "noEmit": true,