create-stellar-devkit-app 1.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.
package/dist/index.js ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+
4
+ // src/index.ts
5
+ import { program } from "commander";
6
+ import chalk from "chalk";
7
+ import fs from "fs-extra";
8
+ import path from "path";
9
+ import { execSync } from "child_process";
10
+ import prompts from "prompts";
11
+ var pkg = await fs.readJSON(path.join(path.dirname(new URL(import.meta.url).pathname), "../package.json"));
12
+ function getTemplatesDir() {
13
+ const candidates = [
14
+ path.join(process.cwd(), "node_modules/create-stellar-devkit-app/templates"),
15
+ path.join(path.dirname(new URL(import.meta.url).pathname), "../templates")
16
+ ];
17
+ for (const d of candidates) {
18
+ if (fs.existsSync(d)) return d;
19
+ }
20
+ throw new Error("Templates directory not found");
21
+ }
22
+ function getTemplateName(projectType) {
23
+ return projectType === "agent-kit" ? "agent-kit" : "x402-api";
24
+ }
25
+ async function main() {
26
+ console.log();
27
+ console.log(chalk.bold.cyan(" Stellar DevKit"));
28
+ console.log(chalk.gray(" Agent Kit DeFi \u2022 x402 Pay-per-Request APIs"));
29
+ console.log(chalk.gray(` v${pkg.version}`));
30
+ console.log();
31
+ program.name("create-stellar-devkit-app").description("Create a new Stellar DevKit project").version(pkg.version).argument("[project-name]", "Project name").option("--agent-kit", "Use Agent Kit template (swap UI + StellarAgentKit)").option("--x402-api", "Use x402 API template (payment-gated endpoints)").option("--skip-install", "Skip installing dependencies").parse();
32
+ const args = program.opts();
33
+ let projectName = program.args[0];
34
+ let projectType = args.agentKit ? "agent-kit" : args.x402Api ? "x402-api" : void 0;
35
+ const skipInstall = !!args.skipInstall;
36
+ if (!projectName) {
37
+ const { name } = await prompts({
38
+ type: "text",
39
+ name: "name",
40
+ message: "Project name?",
41
+ initial: "my-stellar-app",
42
+ validate: (v) => /^[a-z0-9-_]+$/i.test(v) ? true : "Use only letters, numbers, hyphens, underscores"
43
+ });
44
+ projectName = name;
45
+ }
46
+ if (!projectType) {
47
+ const { type } = await prompts({
48
+ type: "select",
49
+ name: "type",
50
+ message: "Which template?",
51
+ choices: [
52
+ { title: chalk.green("Agent Kit"), value: "agent-kit", description: "Swap UI + StellarAgentKit" },
53
+ { title: chalk.cyan("x402 API"), value: "x402-api", description: "Payment-gated API with Stellar" }
54
+ ],
55
+ initial: 0
56
+ });
57
+ projectType = type;
58
+ }
59
+ const projectPath = path.resolve(process.cwd(), projectName);
60
+ if (fs.existsSync(projectPath)) {
61
+ console.log(chalk.red(`Directory ${projectName} already exists.`));
62
+ process.exit(1);
63
+ }
64
+ const templatesDir = getTemplatesDir();
65
+ const templateName = getTemplateName(projectType);
66
+ const templatePath = path.join(templatesDir, templateName);
67
+ if (!fs.existsSync(templatePath)) {
68
+ console.log(chalk.yellow(`Template "${templateName}" not found. Available: ${fs.readdirSync(templatesDir).join(", ")}`));
69
+ process.exit(1);
70
+ }
71
+ fs.copySync(templatePath, projectPath);
72
+ const pkgPath = path.join(projectPath, "package.json");
73
+ if (fs.existsSync(pkgPath)) {
74
+ const pkgJson = await fs.readJSON(pkgPath);
75
+ pkgJson.name = projectName;
76
+ await fs.writeJSON(pkgPath, pkgJson, { spaces: 2 });
77
+ }
78
+ if (!skipInstall) {
79
+ try {
80
+ execSync("npm install", { cwd: projectPath, stdio: "inherit" });
81
+ } catch {
82
+ console.log(chalk.yellow("Install failed. Run manually: cd " + projectName + " && npm install"));
83
+ }
84
+ }
85
+ console.log();
86
+ console.log(chalk.green.bold("\u2714 Success!"), "Created", chalk.cyan(projectName));
87
+ console.log(chalk.gray(" cd " + projectName));
88
+ if (skipInstall) console.log(chalk.gray(" npm install"));
89
+ console.log(chalk.gray(" cp .env.example .env # then add SECRET_KEY / SOROSWAP_API_KEY"));
90
+ console.log(chalk.gray(" npm run dev"));
91
+ console.log();
92
+ }
93
+ main().catch((e) => {
94
+ console.error(e);
95
+ process.exit(1);
96
+ });
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "create-stellar-devkit-app",
3
+ "version": "1.0.0",
4
+ "description": "Scaffold Stellar DevKit apps – Agent Kit or x402 API",
5
+ "type": "module",
6
+ "bin": "./dist/index.js",
7
+ "main": "./dist/index.js",
8
+ "files": [
9
+ "dist",
10
+ "templates"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsup",
14
+ "typecheck": "tsc --noEmit",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "dependencies": {
18
+ "chalk": "^5.3.0",
19
+ "commander": "^12.0.0",
20
+ "fs-extra": "^11.2.0",
21
+ "prompts": "^2.4.2"
22
+ },
23
+ "devDependencies": {
24
+ "@types/fs-extra": "^11.0.4",
25
+ "tsup": "^8.5.0",
26
+ "typescript": "^5.3.0"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/codewmilan/stellar-agent-kit.git"
31
+ },
32
+ "license": "MIT",
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "engines": {
37
+ "node": ">=18"
38
+ }
39
+ }
@@ -0,0 +1,4 @@
1
+ # Stellar Agent Kit – testnet by default
2
+ SECRET_KEY=S...
3
+ SOROSWAP_API_KEY=sk_...
4
+ NETWORK=testnet
@@ -0,0 +1,27 @@
1
+ # Stellar Agent Kit starter
2
+
3
+ Minimal Next.js app using `stellar-agent-kit` for a DEX quote.
4
+
5
+ ## Setup
6
+
7
+ 1. Copy env and set your keys:
8
+ ```bash
9
+ cp .env.example .env
10
+ ```
11
+ Edit `.env`:
12
+ - `SECRET_KEY` — Stellar secret key (S...) for the quote API (server-only).
13
+ - `SOROSWAP_API_KEY` — Optional for quote; required if you add swap execution.
14
+ - `NETWORK` — `testnet` or `mainnet` (default: testnet).
15
+
16
+ 2. Install and run:
17
+ ```bash
18
+ npm install
19
+ npm run dev
20
+ ```
21
+
22
+ 3. Open http://localhost:3000 and click **Get XLM → USDC quote**.
23
+
24
+ ## Next steps
25
+
26
+ - Add a swap flow: call `agent.dexSwap(quote)` from an API route (keep `SECRET_KEY` server-side) or use Freighter to sign in the browser and submit via your API.
27
+ - Use the full [Warly UI](../../../ui) in this repo as reference for swap UI, wallet connect, and API routes.
@@ -0,0 +1,35 @@
1
+ import { NextResponse } from "next/server";
2
+ import { StellarAgentKit, MAINNET_ASSETS, TESTNET_ASSETS } from "stellar-agent-kit";
3
+
4
+ export async function GET() {
5
+ const secretKey = process.env.SECRET_KEY;
6
+ const network = (process.env.NETWORK === "mainnet" ? "mainnet" : "testnet") as "mainnet" | "testnet";
7
+ const assets = network === "mainnet" ? MAINNET_ASSETS : TESTNET_ASSETS;
8
+
9
+ if (!secretKey) {
10
+ return NextResponse.json(
11
+ { error: "Set SECRET_KEY in .env" },
12
+ { status: 500 }
13
+ );
14
+ }
15
+
16
+ try {
17
+ const agent = new StellarAgentKit(secretKey, network);
18
+ await agent.initialize();
19
+
20
+ const quote = await agent.dexGetQuote(
21
+ { contractId: assets.XLM.contractId },
22
+ { contractId: assets.USDC.contractId },
23
+ "10000000" // 1 XLM (7 decimals)
24
+ );
25
+
26
+ return NextResponse.json({
27
+ amountIn: quote.expectedIn,
28
+ amountOut: quote.expectedOut,
29
+ minOut: quote.minOut,
30
+ });
31
+ } catch (e) {
32
+ const message = e instanceof Error ? e.message : "Quote failed";
33
+ return NextResponse.json({ error: message }, { status: 500 });
34
+ }
35
+ }
@@ -0,0 +1,13 @@
1
+ export default function RootLayout({
2
+ children,
3
+ }: {
4
+ children: React.ReactNode;
5
+ }) {
6
+ return (
7
+ <html lang="en">
8
+ <body style={{ fontFamily: "system-ui", margin: 0, padding: 24 }}>
9
+ {children}
10
+ </body>
11
+ </html>
12
+ );
13
+ }
@@ -0,0 +1,53 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+
5
+ export default function Home() {
6
+ const [quote, setQuote] = useState<{ in: string; out: string } | null>(null);
7
+ const [loading, setLoading] = useState(false);
8
+ const [error, setError] = useState<string | null>(null);
9
+
10
+ const getQuote = async () => {
11
+ setLoading(true);
12
+ setError(null);
13
+ setQuote(null);
14
+ try {
15
+ const res = await fetch("/api/quote");
16
+ if (!res.ok) throw new Error(await res.text());
17
+ const data = await res.json();
18
+ setQuote({ in: data.amountIn ?? "", out: data.amountOut ?? "" });
19
+ } catch (e) {
20
+ setError(e instanceof Error ? e.message : "Request failed");
21
+ } finally {
22
+ setLoading(false);
23
+ }
24
+ };
25
+
26
+ return (
27
+ <div style={{ maxWidth: 560 }}>
28
+ <h1 style={{ fontSize: 24, marginBottom: 8 }}>Stellar Agent Kit</h1>
29
+ <p style={{ color: "#666", marginBottom: 24 }}>
30
+ Starter app. Set <code>SECRET_KEY</code> and <code>SOROSWAP_API_KEY</code> in{" "}
31
+ <code>.env</code>, then run <code>npm run dev</code>.
32
+ </p>
33
+ <button
34
+ type="button"
35
+ onClick={getQuote}
36
+ disabled={loading}
37
+ style={{
38
+ padding: "8px 16px",
39
+ fontSize: 14,
40
+ cursor: loading ? "not-allowed" : "pointer",
41
+ }}
42
+ >
43
+ {loading ? "Loading…" : "Get XLM → USDC quote (1 XLM)"}
44
+ </button>
45
+ {error && <p style={{ color: "crimson", marginTop: 16 }}>{error}</p>}
46
+ {quote && (
47
+ <pre style={{ marginTop: 16, padding: 16, background: "#f5f5f5", borderRadius: 8 }}>
48
+ {JSON.stringify(quote, null, 2)}
49
+ </pre>
50
+ )}
51
+ </div>
52
+ );
53
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "my-stellar-app",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start"
9
+ },
10
+ "dependencies": {
11
+ "next": "^14.0.0",
12
+ "react": "^18.2.0",
13
+ "react-dom": "^18.2.0",
14
+ "stellar-agent-kit": "^1.0.0"
15
+ },
16
+ "devDependencies": {
17
+ "typescript": "^5.0.0"
18
+ }
19
+ }
@@ -0,0 +1,3 @@
1
+ # x402 Stellar API – payment receiver account (G...)
2
+ X402_DESTINATION=G...
3
+ NETWORK=testnet
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "my-x402-api",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx src/index.ts",
8
+ "build": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "express": "^4.18.0",
13
+ "x402-stellar-sdk": "^1.0.0"
14
+ },
15
+ "devDependencies": {
16
+ "tsx": "^4.0.0",
17
+ "typescript": "^5.0.0"
18
+ }
19
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Minimal x402 API – premium route gated by Stellar payment.
3
+ */
4
+ import express from "express";
5
+ import { x402 } from "x402-stellar-sdk/server";
6
+
7
+ const app = express();
8
+ app.use(express.json());
9
+
10
+ const destination = process.env.X402_DESTINATION || "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2X";
11
+ const network = (process.env.NETWORK === "mainnet" ? "mainnet" : "testnet") as "mainnet" | "testnet";
12
+
13
+ app.use(
14
+ "/api/premium",
15
+ x402({
16
+ price: "1",
17
+ assetCode: "XLM",
18
+ network,
19
+ destination,
20
+ memo: "premium-api",
21
+ })
22
+ );
23
+
24
+ app.get("/api/premium", (_req, res) => {
25
+ res.json({ data: "Premium content – payment verified." });
26
+ });
27
+
28
+ const port = process.env.PORT || 3000;
29
+ app.listen(port, () => console.log(`x402 API at http://localhost:${port}`));