@caatinga/cli 0.2.3 → 2.0.0

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 (49) hide show
  1. package/README.md +6 -7
  2. package/dist/index.js +220 -157
  3. package/package.json +3 -2
  4. package/templates/marketplace-with-token/README.md +21 -0
  5. package/templates/marketplace-with-token/caatinga.artifacts.json +10 -0
  6. package/templates/marketplace-with-token/caatinga.config.ts +30 -0
  7. package/templates/marketplace-with-token/caatinga.template.json +21 -0
  8. package/templates/marketplace-with-token/contracts/marketplace/Cargo.lock +1731 -0
  9. package/templates/marketplace-with-token/contracts/marketplace/Cargo.toml +24 -0
  10. package/templates/marketplace-with-token/contracts/marketplace/src/lib.rs +43 -0
  11. package/templates/marketplace-with-token/contracts/marketplace/test_snapshots/test/stores_token_contract_id_in_constructor.1.json +86 -0
  12. package/templates/marketplace-with-token/contracts/token/Cargo.lock +1731 -0
  13. package/templates/marketplace-with-token/contracts/token/Cargo.toml +24 -0
  14. package/templates/marketplace-with-token/contracts/token/src/lib.rs +13 -0
  15. package/templates/marketplace-with-token/index.html +12 -0
  16. package/templates/marketplace-with-token/package.json +28 -0
  17. package/templates/marketplace-with-token/src/App.tsx +57 -0
  18. package/templates/marketplace-with-token/src/main.ts +12 -0
  19. package/templates/marketplace-with-token/src/main.tsx +10 -0
  20. package/templates/marketplace-with-token/src/styles.css +157 -0
  21. package/templates/marketplace-with-token/tsconfig.json +21 -0
  22. package/templates/marketplace-with-token/vite.config.ts +6 -0
  23. package/templates/react-vite-counter/.env.example +5 -0
  24. package/templates/react-vite-counter/README.md +83 -0
  25. package/templates/react-vite-counter/caatinga.artifacts.json +10 -0
  26. package/templates/react-vite-counter/caatinga.config.ts +26 -0
  27. package/templates/react-vite-counter/caatinga.template.json +21 -0
  28. package/templates/react-vite-counter/contracts/counter/Cargo.lock +1731 -0
  29. package/templates/react-vite-counter/contracts/counter/Cargo.toml +24 -0
  30. package/templates/react-vite-counter/contracts/counter/src/lib.rs +100 -0
  31. package/templates/react-vite-counter/contracts/counter/test_snapshots/test/get_returns_zero_before_increment.1.json +76 -0
  32. package/templates/react-vite-counter/contracts/counter/test_snapshots/test/increment_returns_overflow_error.1.json +91 -0
  33. package/templates/react-vite-counter/contracts/counter/test_snapshots/test/increments_counter.1.json +91 -0
  34. package/templates/react-vite-counter/contracts/counter/test_snapshots/test/repeated_increments_preserve_state.1.json +92 -0
  35. package/templates/react-vite-counter/index.html +12 -0
  36. package/templates/react-vite-counter/package.json +30 -0
  37. package/templates/react-vite-counter/pnpm-workspace.yaml +12 -0
  38. package/templates/react-vite-counter/public/.gitkeep +1 -0
  39. package/templates/react-vite-counter/src/App.tsx +18 -0
  40. package/templates/react-vite-counter/src/caatinga.ts +20 -0
  41. package/templates/react-vite-counter/src/components/CounterCard.tsx +86 -0
  42. package/templates/react-vite-counter/src/components/WalletButton.tsx +69 -0
  43. package/templates/react-vite-counter/src/contracts/generated/counter.ts +58 -0
  44. package/templates/react-vite-counter/src/hooks/useStellarWallet.ts +70 -0
  45. package/templates/react-vite-counter/src/main.tsx +10 -0
  46. package/templates/react-vite-counter/src/styles.css +206 -0
  47. package/templates/react-vite-counter/src/wallet.ts +29 -0
  48. package/templates/react-vite-counter/tsconfig.json +22 -0
  49. package/templates/react-vite-counter/vite.config.ts +18 -0
@@ -0,0 +1,69 @@
1
+ import { WalletNetwork, WalletType } from "../wallet.js";
2
+ import { useStellarWallet } from "../hooks/useStellarWallet.js";
3
+
4
+ function shortenAddress(address: string): string {
5
+ if (address.length <= 12) {
6
+ return address;
7
+ }
8
+
9
+ return `${address.slice(0, 4)}…${address.slice(-4)}`;
10
+ }
11
+
12
+ export function WalletButton() {
13
+ const {
14
+ publicKey,
15
+ selectedWallet,
16
+ network,
17
+ loading,
18
+ error,
19
+ selectWallet,
20
+ selectNetwork,
21
+ connect,
22
+ disconnect
23
+ } = useStellarWallet();
24
+
25
+ return (
26
+ <div className="wallet-shell">
27
+ <div className="wallet-controls">
28
+ <label>
29
+ <span>Wallet</span>
30
+ <select
31
+ value={selectedWallet}
32
+ onChange={(event) => void selectWallet(event.target.value as WalletType)}
33
+ >
34
+ <option value={WalletType.XBULL}>xBull</option>
35
+ <option value={WalletType.FREIGHTER}>Freighter</option>
36
+ <option value={WalletType.ALBEDO}>Albedo</option>
37
+ <option value={WalletType.RABET}>Rabet</option>
38
+ <option value={WalletType.WALLET_CONNECT}>WalletConnect</option>
39
+ </select>
40
+ </label>
41
+ <label>
42
+ <span>Network</span>
43
+ <select
44
+ value={network}
45
+ onChange={(event) => void selectNetwork(event.target.value as WalletNetwork)}
46
+ >
47
+ <option value={WalletNetwork.TESTNET}>Testnet</option>
48
+ <option value={WalletNetwork.PUBLIC}>Public</option>
49
+ </select>
50
+ </label>
51
+ </div>
52
+ <button
53
+ className="wallet-button"
54
+ type="button"
55
+ onClick={publicKey ? disconnect : () => void connect()}
56
+ disabled={loading}
57
+ aria-live="polite"
58
+ >
59
+ <span className={publicKey ? "status-dot status-dot--on" : "status-dot"} />
60
+ {loading ? "Connecting..." : publicKey ? shortenAddress(publicKey) : "Connect"}
61
+ </button>
62
+ {error ? (
63
+ <p className="wallet-error" role="alert">
64
+ {error}
65
+ </p>
66
+ ) : null}
67
+ </div>
68
+ );
69
+ }
@@ -0,0 +1,58 @@
1
+ type TransactionResult = {
2
+ txHash: string;
3
+ result?: unknown;
4
+ };
5
+
6
+ type SignTransaction = (
7
+ xdr: string,
8
+ opts?: { networkPassphrase?: string; address?: string }
9
+ ) => Promise<{ signedTxXdr: string }> | { signedTxXdr: string };
10
+
11
+ class ExampleTransaction {
12
+ constructor(
13
+ private readonly method: string,
14
+ private readonly result?: unknown
15
+ ) {}
16
+
17
+ toXDR(): string {
18
+ return `example-${this.method}-xdr`;
19
+ }
20
+
21
+ async prepare(): Promise<ExampleTransaction> {
22
+ return this;
23
+ }
24
+
25
+ async signAndSend(input?: { signTransaction?: SignTransaction }): Promise<TransactionResult> {
26
+ const signed = input?.signTransaction
27
+ ? await input.signTransaction(this.toXDR())
28
+ : { signedTxXdr: this.toXDR() };
29
+
30
+ return {
31
+ txHash: `example-transaction-hash:${signed.signedTxXdr}`,
32
+ result: this.result
33
+ };
34
+ }
35
+ }
36
+
37
+ export class Client {
38
+ constructor(
39
+ private readonly input: {
40
+ contractId: string;
41
+ publicKey: string;
42
+ rpcUrl: string;
43
+ networkPassphrase: string;
44
+ }
45
+ ) {}
46
+
47
+ increment(): ExampleTransaction {
48
+ return new ExampleTransaction("increment", 1);
49
+ }
50
+
51
+ get(): ExampleTransaction {
52
+ return new ExampleTransaction("get", 1);
53
+ }
54
+
55
+ describe(): string {
56
+ return `${this.input.contractId}:${this.input.publicKey}`;
57
+ }
58
+ }
@@ -0,0 +1,70 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { stellarWalletAdapter, WalletNetwork, WalletType } from "../wallet.js";
3
+
4
+ export function useStellarWallet() {
5
+ const [publicKey, setPublicKey] = useState<string | null>(null);
6
+ const [selectedWallet, setSelectedWallet] = useState<WalletType>(WalletType.XBULL);
7
+ const [network, setNetwork] = useState<WalletNetwork>(WalletNetwork.TESTNET);
8
+ const [loading, setLoading] = useState(false);
9
+ const [error, setError] = useState<string | null>(null);
10
+
11
+ const selectWallet = useCallback(async (wallet: WalletType) => {
12
+ setError(null);
13
+ await stellarWalletAdapter.setWallet(wallet);
14
+ setSelectedWallet(wallet);
15
+ setPublicKey(null);
16
+ }, []);
17
+
18
+ const selectNetwork = useCallback(async (nextNetwork: WalletNetwork) => {
19
+ setError(null);
20
+ await stellarWalletAdapter.setNetwork(nextNetwork);
21
+ setNetwork(nextNetwork);
22
+ setPublicKey(null);
23
+ }, []);
24
+
25
+ const connect = useCallback(async () => {
26
+ setLoading(true);
27
+ setError(null);
28
+
29
+ try {
30
+ if (selectedWallet === WalletType.WALLET_CONNECT) {
31
+ await stellarWalletAdapter.startWalletConnect();
32
+ await stellarWalletAdapter.connectWalletConnect();
33
+ }
34
+
35
+ const key = await stellarWalletAdapter.getPublicKey();
36
+ setPublicKey(key);
37
+ return key;
38
+ } catch (caught) {
39
+ const message = caught instanceof Error ? caught.message : String(caught);
40
+ setPublicKey(null);
41
+ setError(message);
42
+ throw caught;
43
+ } finally {
44
+ setLoading(false);
45
+ }
46
+ }, [selectedWallet]);
47
+
48
+ const disconnect = useCallback(() => {
49
+ setPublicKey(null);
50
+ setError(null);
51
+ }, []);
52
+
53
+ useEffect(() => {
54
+ stellarWalletAdapter.onWalletConnectSessionDeleted(() => {
55
+ setPublicKey(null);
56
+ });
57
+ }, []);
58
+
59
+ return {
60
+ publicKey,
61
+ selectedWallet,
62
+ network,
63
+ loading,
64
+ error,
65
+ selectWallet,
66
+ selectNetwork,
67
+ connect,
68
+ disconnect
69
+ };
70
+ }
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App";
4
+ import "./styles.css";
5
+
6
+ ReactDOM.createRoot(document.getElementById("root")!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+ );
@@ -0,0 +1,206 @@
1
+ :root {
2
+ color: #20232a;
3
+ background: #f4f2ec;
4
+ font-family:
5
+ Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
6
+ font-synthesis: none;
7
+ text-rendering: optimizeLegibility;
8
+ }
9
+
10
+ * {
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ min-width: 320px;
16
+ min-height: 100vh;
17
+ margin: 0;
18
+ }
19
+
20
+ button {
21
+ min-height: 44px;
22
+ border: 0;
23
+ border-radius: 8px;
24
+ padding: 0 16px;
25
+ background: #1d6154;
26
+ color: #ffffff;
27
+ font: inherit;
28
+ font-weight: 700;
29
+ cursor: pointer;
30
+ }
31
+
32
+ button:hover {
33
+ background: #174d44;
34
+ }
35
+
36
+ .app-shell {
37
+ width: min(960px, calc(100vw - 32px));
38
+ margin: 0 auto;
39
+ padding: 24px 0;
40
+ }
41
+
42
+ .topbar {
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: space-between;
46
+ gap: 16px;
47
+ margin-bottom: 32px;
48
+ }
49
+
50
+ .topbar h1,
51
+ .counter-panel h2 {
52
+ margin: 0;
53
+ color: #16181d;
54
+ letter-spacing: 0;
55
+ }
56
+
57
+ .topbar h1 {
58
+ font-size: clamp(2rem, 8vw, 4rem);
59
+ line-height: 1;
60
+ }
61
+
62
+ .counter-panel h2 {
63
+ font-size: 1.35rem;
64
+ }
65
+
66
+ .eyebrow {
67
+ margin: 0 0 8px;
68
+ color: #697076;
69
+ font-size: 0.78rem;
70
+ font-weight: 800;
71
+ letter-spacing: 0.08em;
72
+ text-transform: uppercase;
73
+ }
74
+
75
+ .wallet-shell {
76
+ display: flex;
77
+ flex-direction: column;
78
+ align-items: flex-end;
79
+ gap: 8px;
80
+ }
81
+
82
+ .wallet-controls {
83
+ display: flex;
84
+ flex-wrap: wrap;
85
+ justify-content: flex-end;
86
+ gap: 8px;
87
+ }
88
+
89
+ .wallet-controls label {
90
+ display: grid;
91
+ gap: 4px;
92
+ color: #45515a;
93
+ font-size: 0.72rem;
94
+ font-weight: 800;
95
+ text-transform: uppercase;
96
+ }
97
+
98
+ .wallet-controls select {
99
+ min-height: 36px;
100
+ border: 1px solid #d9d5ca;
101
+ border-radius: 8px;
102
+ background: #ffffff;
103
+ color: #20232a;
104
+ font: inherit;
105
+ font-size: 0.86rem;
106
+ text-transform: none;
107
+ }
108
+
109
+ .wallet-error,
110
+ .counter-error {
111
+ margin: 0;
112
+ max-width: min(360px, 100%);
113
+ color: #8b1e1e;
114
+ font-size: 0.82rem;
115
+ line-height: 1.4;
116
+ white-space: pre-wrap;
117
+ }
118
+
119
+ .counter-error {
120
+ margin-top: 16px;
121
+ }
122
+
123
+ .wallet-button,
124
+ .network-pill {
125
+ display: inline-flex;
126
+ align-items: center;
127
+ gap: 8px;
128
+ white-space: nowrap;
129
+ }
130
+
131
+ .status-dot {
132
+ width: 8px;
133
+ height: 8px;
134
+ border-radius: 999px;
135
+ background: #a9afb4;
136
+ }
137
+
138
+ .status-dot--on {
139
+ background: #66c887;
140
+ }
141
+
142
+ .counter-panel {
143
+ border: 1px solid #d9d5ca;
144
+ border-radius: 8px;
145
+ padding: clamp(20px, 5vw, 40px);
146
+ background: #fffdf7;
147
+ box-shadow: 0 18px 60px rgba(32, 35, 42, 0.08);
148
+ }
149
+
150
+ .counter-panel__header {
151
+ display: flex;
152
+ align-items: flex-start;
153
+ justify-content: space-between;
154
+ gap: 16px;
155
+ }
156
+
157
+ .network-pill {
158
+ min-height: 32px;
159
+ border: 1px solid #d9d5ca;
160
+ border-radius: 999px;
161
+ padding: 0 12px;
162
+ color: #45515a;
163
+ font-weight: 700;
164
+ }
165
+
166
+ .counter-value {
167
+ margin: 48px 0;
168
+ color: #111318;
169
+ font-size: clamp(5rem, 24vw, 12rem);
170
+ font-weight: 900;
171
+ line-height: 0.9;
172
+ letter-spacing: 0;
173
+ }
174
+
175
+ .counter-actions {
176
+ display: flex;
177
+ flex-wrap: wrap;
178
+ gap: 12px;
179
+ }
180
+
181
+ .secondary-button {
182
+ border: 1px solid #d9d5ca;
183
+ background: #ffffff;
184
+ color: #20232a;
185
+ }
186
+
187
+ .secondary-button:hover {
188
+ background: #f4f2ec;
189
+ }
190
+
191
+ @media (max-width: 560px) {
192
+ .topbar,
193
+ .counter-panel__header {
194
+ align-items: stretch;
195
+ flex-direction: column;
196
+ }
197
+
198
+ .wallet-button,
199
+ .wallet-controls,
200
+ .wallet-controls label,
201
+ .wallet-controls select,
202
+ .counter-actions button {
203
+ width: 100%;
204
+ justify-content: center;
205
+ }
206
+ }
@@ -0,0 +1,29 @@
1
+ // Keep in sync with examples/counter-web/src/wallet.ts (WalletConnect defaults differ per project).
2
+ import {
3
+ createStellarWalletsKitAdapter,
4
+ type StellarWalletsKitMetadata
5
+ } from "@caatinga/client/stellar-wallets-kit";
6
+ import { WalletNetwork, WalletType } from "stellar-wallets-kit";
7
+
8
+ export const stellarWalletAdapter = createStellarWalletsKitAdapter({
9
+ network: WalletNetwork.TESTNET,
10
+ selectedWallet: WalletType.XBULL,
11
+ walletConnectMetadata: getWalletConnectMetadata()
12
+ });
13
+
14
+ export { WalletNetwork, WalletType };
15
+
16
+ function getWalletConnectMetadata(): StellarWalletsKitMetadata | undefined {
17
+ const projectId = import.meta.env.VITE_WALLETCONNECT_PROJECT_ID as string | undefined;
18
+ if (!projectId) {
19
+ return undefined;
20
+ }
21
+
22
+ return {
23
+ projectId,
24
+ name: import.meta.env.VITE_APP_NAME ?? "__PROJECT_NAME__",
25
+ description: import.meta.env.VITE_APP_DESCRIPTION ?? "Caatinga counter dApp",
26
+ url: import.meta.env.VITE_APP_URL ?? window.location.origin,
27
+ icons: [import.meta.env.VITE_APP_ICON_URL ?? `${window.location.origin}/icon.png`]
28
+ };
29
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["DOM", "DOM.Iterable", "ES2020"],
6
+ "allowJs": false,
7
+ "skipLibCheck": true,
8
+ "esModuleInterop": true,
9
+ "allowSyntheticDefaultImports": true,
10
+ "strict": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "module": "ESNext",
13
+ "moduleResolution": "bundler",
14
+ "resolveJsonModule": true,
15
+ "isolatedModules": true,
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+ "types": ["vite/client"]
19
+ },
20
+ "include": ["src"],
21
+ "references": []
22
+ }
@@ -0,0 +1,18 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+ import { createRequire } from "node:module";
4
+ import { dirname, join } from "node:path";
5
+
6
+ const require = createRequire(import.meta.url);
7
+ const xbullWalletConnectRoot = dirname(
8
+ require.resolve("@creit-tech/xbull-wallet-connect/package.json")
9
+ );
10
+
11
+ export default defineConfig({
12
+ plugins: [react()],
13
+ resolve: {
14
+ alias: {
15
+ "@creit-tech/xbull-wallet-connect": join(xbullWalletConnectRoot, "src/index.ts")
16
+ }
17
+ }
18
+ });