@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
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"caatinga:generate": "caatinga generate counter"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@caatinga/client": "^0.2.
|
|
16
|
-
"@caatinga/core": "^0.2.
|
|
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.
|
|
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={
|
|
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={
|
|
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 [
|
|
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
|
-
<
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
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;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|