@kaleido-xlm/cli 0.1.0 → 0.1.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 (26) hide show
  1. package/package.json +4 -3
  2. package/templates/marketplace-with-token/README.md +19 -0
  3. package/templates/marketplace-with-token/contracts/marketplace/.gitkeep +0 -0
  4. package/templates/marketplace-with-token/contracts/token/.gitkeep +0 -0
  5. package/templates/marketplace-with-token/kaleido.artifacts.json +10 -0
  6. package/templates/marketplace-with-token/kaleido.config.ts +30 -0
  7. package/templates/marketplace-with-token/kaleido.template.json +21 -0
  8. package/templates/marketplace-with-token/package.json +17 -0
  9. package/templates/marketplace-with-token/src/main.ts +1 -0
  10. package/templates/marketplace-with-token/tsconfig.json +11 -0
  11. package/templates/react-vite-counter/README.md +58 -0
  12. package/templates/react-vite-counter/contracts/counter/Cargo.toml +23 -0
  13. package/templates/react-vite-counter/contracts/counter/src/lib.rs +36 -0
  14. package/templates/react-vite-counter/index.html +12 -0
  15. package/templates/react-vite-counter/kaleido.config.ts +26 -0
  16. package/templates/react-vite-counter/kaleido.template.json +21 -0
  17. package/templates/react-vite-counter/package.json +29 -0
  18. package/templates/react-vite-counter/public/.gitkeep +1 -0
  19. package/templates/react-vite-counter/src/App.tsx +18 -0
  20. package/templates/react-vite-counter/src/components/CounterCard.tsx +29 -0
  21. package/templates/react-vite-counter/src/components/WalletButton.tsx +12 -0
  22. package/templates/react-vite-counter/src/contracts/generated/.gitkeep +1 -0
  23. package/templates/react-vite-counter/src/main.tsx +10 -0
  24. package/templates/react-vite-counter/src/styles.css +155 -0
  25. package/templates/react-vite-counter/tsconfig.json +21 -0
  26. package/templates/react-vite-counter/vite.config.ts +6 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaleido-xlm/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Developer toolkit CLI for building dApps on Stellar/Soroban",
5
5
  "keywords": [
6
6
  "stellar",
@@ -38,11 +38,12 @@
38
38
  },
39
39
  "files": [
40
40
  "dist",
41
+ "templates",
41
42
  "README.md",
42
43
  "LICENSE"
43
44
  ],
44
45
  "dependencies": {
45
- "@kaleido-xlm/core": "^0.1.0",
46
+ "@kaleido-xlm/core": "^0.1.2",
46
47
  "chalk": "^5.4.1",
47
48
  "commander": "^12.1.0"
48
49
  },
@@ -53,7 +54,7 @@
53
54
  "vitest": "^2.1.8"
54
55
  },
55
56
  "scripts": {
56
- "build": "tsup src/index.ts --format esm --dts --clean",
57
+ "build": "tsup src/index.ts --format esm --dts --clean && rm -rf ./templates && cp -r ../templates ./templates",
57
58
  "dev": "tsx src/index.ts",
58
59
  "test": "vitest run --pool=threads",
59
60
  "typecheck": "tsc --noEmit"
@@ -0,0 +1,19 @@
1
+ # __PROJECT_NAME__
2
+
3
+ Experimental Kaleido multi-contract template.
4
+
5
+ ## Deploy
6
+
7
+ ```bash
8
+ npm install
9
+ npx kaleido build token
10
+ npx kaleido build marketplace
11
+ npx kaleido deploy --network testnet --source alice
12
+ ```
13
+
14
+ Deploy order:
15
+
16
+ 1. `token`
17
+ 2. `marketplace`
18
+
19
+ `marketplace.deployArgs.tokenContractId` resolves from `${contracts.token.contractId}` after the token deploy writes `kaleido.artifacts.json`.
@@ -0,0 +1,10 @@
1
+ {
2
+ "project": "__PROJECT_NAME__",
3
+ "version": 1,
4
+ "networks": {
5
+ "testnet": {
6
+ "contracts": {},
7
+ "dependencyGraph": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,30 @@
1
+ import { defineConfig } from "@kaleido-xlm/core";
2
+
3
+ export default defineConfig({
4
+ project: "__PROJECT_NAME__",
5
+ defaultNetwork: "testnet",
6
+ contracts: {
7
+ token: {
8
+ path: "./contracts/token",
9
+ wasm: "./contracts/token/target/wasm32v1-none/release/token.wasm"
10
+ },
11
+ marketplace: {
12
+ path: "./contracts/marketplace",
13
+ wasm: "./contracts/marketplace/target/wasm32v1-none/release/marketplace.wasm",
14
+ dependsOn: ["token"],
15
+ deployArgs: {
16
+ tokenContractId: "${contracts.token.contractId}"
17
+ }
18
+ }
19
+ },
20
+ networks: {
21
+ testnet: {
22
+ rpcUrl: "https://soroban-testnet.stellar.org",
23
+ networkPassphrase: "Test SDF Network ; September 2015"
24
+ }
25
+ },
26
+ frontend: {
27
+ framework: "vite-react",
28
+ bindingsOutput: "./src/contracts/generated"
29
+ }
30
+ });
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "marketplace-with-token",
3
+ "version": "0.1.0",
4
+ "description": "Experimental multi-contract Soroban template with token dependency injection.",
5
+ "kaleido": {
6
+ "compatibleCore": "^0.1.0",
7
+ "templateVersion": 1
8
+ },
9
+ "frontend": {
10
+ "framework": "vite-react",
11
+ "packageManager": "npm"
12
+ },
13
+ "contracts": {
14
+ "path": "contracts",
15
+ "default": "marketplace"
16
+ },
17
+ "files": {
18
+ "config": "kaleido.config.ts",
19
+ "artifacts": "kaleido.artifacts.json"
20
+ }
21
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "__PROJECT_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "kaleido:build": "kaleido build token && kaleido build marketplace",
8
+ "kaleido:deploy": "kaleido deploy --network testnet"
9
+ },
10
+ "dependencies": {
11
+ "@kaleido-xlm/core": "^0.1.0"
12
+ },
13
+ "devDependencies": {
14
+ "@kaleido-xlm/cli": "^0.1.0",
15
+ "typescript": "^5.7.2"
16
+ }
17
+ }
@@ -0,0 +1 @@
1
+ export const placeholder = "marketplace-with-token template bootstrap";
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "skipLibCheck": true,
8
+ "noEmit": true
9
+ },
10
+ "include": ["src", "kaleido.config.ts"]
11
+ }
@@ -0,0 +1,58 @@
1
+ # __PROJECT_NAME__
2
+
3
+ Kaleido counter dApp for Stellar/Soroban.
4
+
5
+ ## CLI Flow
6
+
7
+ ```bash
8
+ npm install
9
+ npx kaleido build counter
10
+ npx kaleido deploy counter --network testnet --source alice
11
+ npx kaleido generate counter --network testnet
12
+ npx kaleido invoke counter.increment --network testnet --source alice
13
+ npm run dev
14
+ ```
15
+
16
+ Use a Stellar CLI identity alias or public account address for `--source`; do not pass seed phrases or secret keys.
17
+
18
+ ## Client Smoke Path
19
+
20
+ After `kaleido generate`, wire generated bindings to the client:
21
+
22
+ ```ts
23
+ import { createKaleidoClient } from "@kaleido-xlm/client";
24
+ import { freighterWalletAdapter } from "@kaleido-xlm/client/freighter";
25
+ import * as Counter from "./contracts/generated/counter";
26
+ import artifacts from "../kaleido.artifacts.json";
27
+
28
+ export const kaleidoClient = createKaleidoClient({
29
+ network: {
30
+ name: "testnet",
31
+ rpcUrl: "https://soroban-testnet.stellar.org",
32
+ networkPassphrase: "Test SDF Network ; September 2015"
33
+ },
34
+ artifacts,
35
+ wallet: freighterWalletAdapter,
36
+ contracts: {
37
+ counter: {
38
+ binding: Counter
39
+ }
40
+ }
41
+ });
42
+ ```
43
+
44
+ Build XDR without wallet signing:
45
+
46
+ ```ts
47
+ const tx = await kaleidoClient.contract("counter").buildXdr("increment");
48
+ console.log(tx.preparedXdr);
49
+ ```
50
+
51
+ Invoke through Freighter:
52
+
53
+ ```ts
54
+ const result = await kaleidoClient.contract("counter").invoke("increment", {
55
+ debugXdr: true
56
+ });
57
+ console.log(result.transactionHash);
58
+ ```
@@ -0,0 +1,23 @@
1
+ [package]
2
+ name = "counter"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ [lib]
7
+ crate-type = ["cdylib"]
8
+
9
+ [dependencies]
10
+ soroban-sdk = "26.0.0"
11
+
12
+ [dev-dependencies]
13
+ soroban-sdk = { version = "26.0.0", features = ["testutils"] }
14
+
15
+ [profile.release]
16
+ opt-level = "z"
17
+ overflow-checks = true
18
+ debug = 0
19
+ strip = "symbols"
20
+ debug-assertions = false
21
+ panic = "abort"
22
+ codegen-units = 1
23
+ lto = true
@@ -0,0 +1,36 @@
1
+ #![no_std]
2
+
3
+ use soroban_sdk::{contract, contractimpl, Env};
4
+
5
+ #[contract]
6
+ pub struct CounterContract;
7
+
8
+ #[contractimpl]
9
+ impl CounterContract {
10
+ pub fn get(env: Env) -> u32 {
11
+ env.storage().instance().get(&"count").unwrap_or(0)
12
+ }
13
+
14
+ pub fn increment(env: Env) -> u32 {
15
+ let count = Self::get(env.clone()) + 1;
16
+ env.storage().instance().set(&"count", &count);
17
+ count
18
+ }
19
+ }
20
+
21
+ #[cfg(test)]
22
+ mod test {
23
+ use super::*;
24
+ use soroban_sdk::Env;
25
+
26
+ #[test]
27
+ fn increments_counter() {
28
+ let env = Env::default();
29
+ let contract_id = env.register(CounterContract, ());
30
+ let client = CounterContractClient::new(&env, &contract_id);
31
+
32
+ assert_eq!(client.get(), 0);
33
+ assert_eq!(client.increment(), 1);
34
+ assert_eq!(client.get(), 1);
35
+ }
36
+ }
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>__PROJECT_NAME__</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,26 @@
1
+ import { defineConfig } from "@kaleido-xlm/core";
2
+
3
+ export default defineConfig({
4
+ project: "__PROJECT_NAME__",
5
+ defaultNetwork: "testnet",
6
+ contracts: {
7
+ counter: {
8
+ path: "./contracts/counter",
9
+ wasm: "./contracts/counter/target/wasm32v1-none/release/counter.wasm"
10
+ }
11
+ },
12
+ networks: {
13
+ testnet: {
14
+ rpcUrl: "https://soroban-testnet.stellar.org",
15
+ networkPassphrase: "Test SDF Network ; September 2015"
16
+ },
17
+ mainnet: {
18
+ rpcUrl: "https://mainnet.sorobanrpc.com",
19
+ networkPassphrase: "Public Global Stellar Network ; September 2015"
20
+ }
21
+ },
22
+ frontend: {
23
+ framework: "vite-react",
24
+ bindingsOutput: "./src/contracts/generated"
25
+ }
26
+ });
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "react-vite-counter",
3
+ "version": "0.1.0",
4
+ "description": "Minimal Vite + React + Soroban counter dApp.",
5
+ "kaleido": {
6
+ "compatibleCore": "^0.1.0",
7
+ "templateVersion": 1
8
+ },
9
+ "frontend": {
10
+ "framework": "vite-react",
11
+ "packageManager": "npm"
12
+ },
13
+ "contracts": {
14
+ "path": "contracts",
15
+ "default": "counter"
16
+ },
17
+ "files": {
18
+ "config": "kaleido.config.ts",
19
+ "artifacts": "kaleido.artifacts.json"
20
+ }
21
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "__PROJECT_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc && vite build",
9
+ "preview": "vite preview",
10
+ "kaleido:build": "kaleido build counter",
11
+ "kaleido:deploy": "kaleido deploy counter",
12
+ "kaleido:generate": "kaleido generate counter"
13
+ },
14
+ "dependencies": {
15
+ "@kaleido-xlm/client": "^0.1.0",
16
+ "@kaleido-xlm/core": "^0.1.0",
17
+ "@stellar/freighter-api": "^4.0.0",
18
+ "@vitejs/plugin-react": "^4.3.4",
19
+ "vite": "^6.0.6",
20
+ "react": "^18.3.1",
21
+ "react-dom": "^18.3.1"
22
+ },
23
+ "devDependencies": {
24
+ "@kaleido-xlm/cli": "^0.1.0",
25
+ "@types/react": "^18.3.18",
26
+ "@types/react-dom": "^18.3.5",
27
+ "typescript": "^5.7.2"
28
+ }
29
+ }
@@ -0,0 +1,18 @@
1
+ import { CounterCard } from "./components/CounterCard";
2
+ import { WalletButton } from "./components/WalletButton";
3
+
4
+ export default function App() {
5
+ return (
6
+ <main className="app-shell">
7
+ <header className="topbar">
8
+ <div>
9
+ <p className="eyebrow">Kaleido</p>
10
+ <h1>__PROJECT_NAME__</h1>
11
+ </div>
12
+ <WalletButton />
13
+ </header>
14
+
15
+ <CounterCard />
16
+ </main>
17
+ );
18
+ }
@@ -0,0 +1,29 @@
1
+ import { useMemo, useState } from "react";
2
+
3
+ export function CounterCard() {
4
+ const [count, setCount] = useState(0);
5
+ const formattedCount = useMemo(() => new Intl.NumberFormat().format(count), [count]);
6
+
7
+ return (
8
+ <section className="counter-panel" aria-labelledby="counter-title">
9
+ <div className="counter-panel__header">
10
+ <div>
11
+ <p className="eyebrow">Counter Contract</p>
12
+ <h2 id="counter-title">Counter</h2>
13
+ </div>
14
+ <span className="network-pill">testnet</span>
15
+ </div>
16
+
17
+ <div className="counter-value">{formattedCount}</div>
18
+
19
+ <div className="counter-actions">
20
+ <button type="button" onClick={() => setCount((value) => value + 1)}>
21
+ Increment
22
+ </button>
23
+ <button className="secondary-button" type="button" onClick={() => setCount(0)}>
24
+ Reset
25
+ </button>
26
+ </div>
27
+ </section>
28
+ );
29
+ }
@@ -0,0 +1,12 @@
1
+ import { useState } from "react";
2
+
3
+ export function WalletButton() {
4
+ const [connected, setConnected] = useState(false);
5
+
6
+ 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>
11
+ );
12
+ }
@@ -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,155 @@
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-button,
76
+ .network-pill {
77
+ display: inline-flex;
78
+ align-items: center;
79
+ gap: 8px;
80
+ white-space: nowrap;
81
+ }
82
+
83
+ .status-dot {
84
+ width: 8px;
85
+ height: 8px;
86
+ border-radius: 999px;
87
+ background: #a9afb4;
88
+ }
89
+
90
+ .status-dot--on {
91
+ background: #66c887;
92
+ }
93
+
94
+ .counter-panel {
95
+ border: 1px solid #d9d5ca;
96
+ border-radius: 8px;
97
+ padding: clamp(20px, 5vw, 40px);
98
+ background: #fffdf7;
99
+ box-shadow: 0 18px 60px rgba(32, 35, 42, 0.08);
100
+ }
101
+
102
+ .counter-panel__header {
103
+ display: flex;
104
+ align-items: flex-start;
105
+ justify-content: space-between;
106
+ gap: 16px;
107
+ }
108
+
109
+ .network-pill {
110
+ min-height: 32px;
111
+ border: 1px solid #d9d5ca;
112
+ border-radius: 999px;
113
+ padding: 0 12px;
114
+ color: #45515a;
115
+ font-weight: 700;
116
+ }
117
+
118
+ .counter-value {
119
+ margin: 48px 0;
120
+ color: #111318;
121
+ font-size: clamp(5rem, 24vw, 12rem);
122
+ font-weight: 900;
123
+ line-height: 0.9;
124
+ letter-spacing: 0;
125
+ }
126
+
127
+ .counter-actions {
128
+ display: flex;
129
+ flex-wrap: wrap;
130
+ gap: 12px;
131
+ }
132
+
133
+ .secondary-button {
134
+ border: 1px solid #d9d5ca;
135
+ background: #ffffff;
136
+ color: #20232a;
137
+ }
138
+
139
+ .secondary-button:hover {
140
+ background: #f4f2ec;
141
+ }
142
+
143
+ @media (max-width: 560px) {
144
+ .topbar,
145
+ .counter-panel__header {
146
+ align-items: stretch;
147
+ flex-direction: column;
148
+ }
149
+
150
+ .wallet-button,
151
+ .counter-actions button {
152
+ width: 100%;
153
+ justify-content: center;
154
+ }
155
+ }
@@ -0,0 +1,21 @@
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": "Node",
14
+ "resolveJsonModule": true,
15
+ "isolatedModules": true,
16
+ "noEmit": true,
17
+ "jsx": "react-jsx"
18
+ },
19
+ "include": ["src"],
20
+ "references": []
21
+ }
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+
4
+ export default defineConfig({
5
+ plugins: [react()]
6
+ });