create-sbc-app 0.3.1 → 0.4.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/README.md CHANGED
@@ -33,7 +33,7 @@ Arguments:
33
33
 
34
34
  Options:
35
35
  -V, --version output the version number
36
- -t, --template <type> Template to use: react, react-dynamic, or react-para
36
+ -t, --template <type> Template to use: react, react-dynamic, react-para, or react-turnkey
37
37
  -c, --chain <chain> Chain to use: baseSepolia, base, or radiusTestnet
38
38
  --api-key <apiKey> Your SBC API key for immediate configuration
39
39
  --wallet <wallet> Wallet integration (not yet implemented)
@@ -44,16 +44,18 @@ Examples:
44
44
  $ npx create-sbc-app my-app --template react --chain radiusTestnet
45
45
  $ npx create-sbc-app my-app --template react-dynamic --chain base
46
46
  $ npx create-sbc-app my-app --template react-para --api-key your-key
47
+ $ npx create-sbc-app my-app --template react-turnkey --chain base
47
48
 
48
49
  Available Templates:
49
50
  - react React + Vite template with SBC integration
50
51
  - react-dynamic React + Vite with Dynamic wallet integration
51
52
  - react-para React + Vite with Para wallet integration
53
+ - react-turnkey React + Vite + Express backend with Turnkey embedded wallets
52
54
 
53
55
  Available Chains:
54
56
  - baseSepolia Base Sepolia testnet (default)
55
57
  - base Base mainnet
56
- - radiusTestnet Radius testnet (react template only)
58
+ - radiusTestnet Radius testnet (react template only - not supported by Dynamic, Para, or Turnkey)
57
59
  ```
58
60
 
59
61
  ## ✨ Features
@@ -142,6 +144,34 @@ npx create-sbc-app my-app --template react-para
142
144
 
143
145
  **Additional Requirements:** Para API Key from [Para](https://para.xyz/)
144
146
 
147
+ ### React + Turnkey Template
148
+
149
+ **Best for:** Production applications requiring embedded wallets with biometric authentication and backend infrastructure
150
+
151
+ ```bash
152
+ npx create-sbc-app my-app --template react-turnkey
153
+ ```
154
+
155
+ **Supported Chains:** Base Sepolia, Base (Radius Testnet not supported)
156
+
157
+ **Features:**
158
+ - Turnkey embedded wallet integration with passkey authentication
159
+ - Express backend server for secure Turnkey API operations
160
+ - Two authentication methods: biometric passkeys (Face ID/Touch ID) or wallet connection (MetaMask/Coinbase)
161
+ - Account history and multi-account management
162
+ - Full-stack development with `dev:fullstack` script
163
+ - ERC-4337 smart accounts with gasless transactions
164
+ - All standard SBC features
165
+
166
+ **Additional Requirements:**
167
+ - Turnkey Organization ID and API Keys from [Turnkey Dashboard](https://app.turnkey.com)
168
+ - Backend deployment for production use (Railway, Render, Vercel, etc.)
169
+
170
+ **Architecture:**
171
+ - Frontend: React + Vite (port 5173)
172
+ - Backend: Express server (port 3001)
173
+ - Runs both services concurrently with `npm run dev:fullstack`
174
+
145
175
  ## 📝 Configuration
146
176
 
147
177
  ### Environment Variables
package/bin/cli.js CHANGED
@@ -10,9 +10,9 @@ const program = new Command();
10
10
  program
11
11
  .name('create-sbc-app')
12
12
  .description('Create a new SBC App Kit project with an opinionated template')
13
- .version('0.2.0')
13
+ .version('0.4.0')
14
14
  .argument('[project-directory]', 'Directory to create the new app in')
15
- .option('-t, --template <template>', 'Template to use: react, react-dynamic, or react-para')
15
+ .option('-t, --template <template>', 'Template to use: react, react-dynamic, react-para, or react-turnkey')
16
16
  .option('-c, --chain <chain>', 'Chain to use: baseSepolia, base, or radiusTestnet')
17
17
  .option('--api-key <apiKey>', 'Your SBC API key for immediate configuration')
18
18
  .option('--wallet <wallet>', 'Wallet integration (not yet implemented)')
@@ -26,6 +26,7 @@ Available Templates:
26
26
  - react React + Vite template with SBC integration
27
27
  - react-dynamic React + Vite with Dynamic wallet integration
28
28
  - react-para React + Vite with Para wallet integration
29
+ - react-turnkey React + Vite + Express backend with Turnkey embedded wallets
29
30
 
30
31
  Available Chains:
31
32
  - baseSepolia Base Sepolia testnet (default)
@@ -40,7 +41,8 @@ Available Chains:
40
41
  const templateChoices = [
41
42
  { title: 'React', value: 'react' },
42
43
  { title: 'React (Dynamic wallet)', value: 'react-dynamic' },
43
- { title: 'React (Para wallet)', value: 'react-para' }
44
+ { title: 'React (Para wallet)', value: 'react-para' },
45
+ { title: 'React (Turnkey embedded wallet + Backend)', value: 'react-turnkey' }
44
46
  ];
45
47
  const chainChoices = [
46
48
  { title: 'Base Sepolia (testnet)', value: 'baseSepolia' },
@@ -62,7 +64,7 @@ Available Chains:
62
64
  projectDir = res.dir.trim();
63
65
  }
64
66
  // Use provided option or prompt for template
65
- let template = options.template && ['react', 'react-dynamic', 'react-para'].includes(options.template) ? options.template : '';
67
+ let template = options.template && ['react', 'react-dynamic', 'react-para', 'react-turnkey'].includes(options.template) ? options.template : '';
66
68
  if (!template) {
67
69
  const res = await prompts({
68
70
  type: 'select',
@@ -75,7 +77,7 @@ Available Chains:
75
77
  process.exit(1);
76
78
  }
77
79
  template = res.template; // The value is already what we want from the choices
78
- if (!template || !['react', 'react-dynamic', 'react-para'].includes(template)) {
80
+ if (!template || !['react', 'react-dynamic', 'react-para', 'react-turnkey'].includes(template)) {
79
81
  console.log('Template selection is required.');
80
82
  process.exit(1);
81
83
  }
@@ -100,6 +102,12 @@ Available Chains:
100
102
  process.exit(1);
101
103
  }
102
104
  }
105
+ // Validate template + chain compatibility
106
+ if (['react-dynamic', 'react-para', 'react-turnkey'].includes(template) && chain === 'radiusTestnet') {
107
+ console.log(`\nError: The ${template} template does not support radiusTestnet.`);
108
+ console.log('Please use baseSepolia or base chain instead.\n');
109
+ process.exit(1);
110
+ }
103
111
  // Use provided option or prompt for API key
104
112
  let apiKey = options.apiKey && options.apiKey.trim() ? options.apiKey.trim() : '';
105
113
  if (!apiKey) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-sbc-app",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Scaffold a new SBC App Kit project with one command.",
5
5
  "bin": {
6
6
  "create-sbc-app": "bin/cli.js"
@@ -0,0 +1,26 @@
1
+ # SBC API Key (get from https://dashboard.stablecoin.xyz)
2
+ VITE_SBC_API_KEY={{apiKey}}
3
+
4
+ # Chain Configuration (baseSepolia or base)
5
+ VITE_CHAIN={{chain}}
6
+
7
+ # Turnkey Configuration (Frontend - Public, safe to expose)
8
+ VITE_TURNKEY_API_BASE_URL=https://api.turnkey.com
9
+ VITE_TURNKEY_RPID=localhost
10
+ VITE_BACKEND_URL=http://localhost:3001
11
+
12
+ # Turnkey Backend Configuration (Server - KEEP SECRET!)
13
+ # Get these from https://app.turnkey.com → Settings → API Keys
14
+ TURNKEY_API_BASE_URL=https://api.turnkey.com
15
+ TURNKEY_ORGANIZATION_ID=your_org_id_here
16
+ TURNKEY_API_PUBLIC_KEY=your_public_key_here
17
+ TURNKEY_API_PRIVATE_KEY=your_private_key_here
18
+
19
+ # Backend Server Port
20
+ PORT=3001
21
+
22
+ # Optional: Custom RPC URL
23
+ # VITE_RPC_URL=https://base-sepolia.g.alchemy.com/v2/YOUR_KEY
24
+
25
+ # Note: This example uses passkeyClient approach (official Turnkey pattern)
26
+ # You do NOT need Auth Proxy Config ID or authProxyConfigId
@@ -0,0 +1,206 @@
1
+ # {{projectName}}
2
+
3
+ SBC + Turnkey fullstack example with embedded wallets and gasless transactions.
4
+
5
+ ## Features
6
+
7
+ - ✅ **Backend Architecture**: Express server handling Turnkey sub-org creation
8
+ - ✅ **Passkey Authentication**: Users create wallets with biometric auth (Face ID/Touch ID)
9
+ - ✅ **Wallet Authentication**: Connect with MetaMask/Coinbase Wallet as alternative to passkeys
10
+ - ✅ **Embedded Wallets**: Non-custodial wallets managed by Turnkey
11
+ - ✅ **Smart Accounts**: ERC-4337 account abstraction with SBC paymaster
12
+ - ✅ **Gasless Transactions**: All gas fees sponsored by SBC
13
+ - ✅ **Account History**: Never lose access to accounts - all accounts saved and switchable
14
+
15
+ ## Prerequisites
16
+
17
+ Before you begin, you need:
18
+
19
+ 1. **SBC API Key**: Get from https://dashboard.stablecoin.xyz
20
+ 2. **Turnkey Organization + API Keys**: Get from https://app.turnkey.com
21
+
22
+ ### Getting Turnkey API Keys
23
+
24
+ 1. Go to https://app.turnkey.com and sign up
25
+ 2. Create a new organization (or use existing)
26
+ 3. Navigate to **Settings** → **API Keys**
27
+ 4. Click **"Create API Key"**
28
+ 5. **Save both keys securely**:
29
+ - Copy the **API Public Key**
30
+ - Copy the **API Private Key** (shown only once!)
31
+ 6. Copy your **Organization ID** from Settings
32
+
33
+ ## Quick Start
34
+
35
+ ### 1. Install Dependencies
36
+
37
+ ```bash
38
+ npm install
39
+ # or
40
+ pnpm install
41
+ ```
42
+
43
+ ### 2. Configure Environment Variables
44
+
45
+ Edit the `.env` file that was created for you:
46
+
47
+ ```bash
48
+ # SBC Configuration
49
+ VITE_SBC_API_KEY=your_sbc_api_key_here
50
+
51
+ # Turnkey Frontend (Public - safe for browser)
52
+ VITE_TURNKEY_API_BASE_URL=https://api.turnkey.com
53
+ VITE_TURNKEY_RPID=localhost
54
+
55
+ # Turnkey Backend (Secret - never expose to frontend!)
56
+ TURNKEY_API_BASE_URL=https://api.turnkey.com
57
+ TURNKEY_ORGANIZATION_ID=your_turnkey_org_id_here
58
+ TURNKEY_API_PUBLIC_KEY=your_turnkey_public_key_here
59
+ TURNKEY_API_PRIVATE_KEY=your_turnkey_private_key_here
60
+
61
+ # Backend Server
62
+ PORT=3001
63
+ VITE_BACKEND_URL=http://localhost:3001
64
+ ```
65
+
66
+ ### 3. Run the Application
67
+
68
+ **Option A: Run both frontend and backend together (recommended)**
69
+
70
+ ```bash
71
+ npm run dev:fullstack
72
+ ```
73
+
74
+ This starts:
75
+ - Backend server on `http://localhost:3001`
76
+ - Frontend on `http://localhost:5173`
77
+
78
+ **Option B: Run separately**
79
+
80
+ ```bash
81
+ # Terminal 1 - Backend
82
+ npm run dev:backend
83
+
84
+ # Terminal 2 - Frontend
85
+ npm run dev
86
+ ```
87
+
88
+ ## How It Works
89
+
90
+ ### Authentication Flows
91
+
92
+ #### Passkey Flow (Biometric)
93
+ 1. User clicks "Continue with Passkey"
94
+ 2. Browser creates passkey via WebAuthn (Face ID/Touch ID)
95
+ 3. Frontend → Backend: `POST /api/create-sub-org` with attestation
96
+ 4. Backend → Turnkey: Creates sub-org + Turnkey-managed wallet
97
+ 5. User signs transactions with biometric auth
98
+
99
+ #### Wallet Flow (MetaMask/Coinbase)
100
+ 1. User clicks "Connect Wallet"
101
+ 2. MetaMask prompts for connection + signature
102
+ 3. Frontend derives public key from signature
103
+ 4. Frontend → Backend: `POST /api/create-sub-org-with-wallet` with public key
104
+ 5. Backend → Turnkey: Creates sub-org (uses user's wallet as owner)
105
+ 6. User signs transactions with their connected wallet
106
+
107
+ ### Transaction Flow
108
+
109
+ 1. User initiates transaction (e.g., "Send 1 SBC")
110
+ 2. Frontend builds transaction via SBC App Kit
111
+ 3. User signs transaction:
112
+ - **Passkey**: Biometric prompt (Face ID/Touch ID)
113
+ - **Wallet**: MetaMask/Coinbase popup
114
+ 4. SBC paymaster sponsors all gas fees
115
+ 5. Transaction executes on-chain via ERC-4337
116
+
117
+ ## Project Structure
118
+
119
+ ```
120
+ {{projectName}}/
121
+ ├── server/ # Backend Express server
122
+ │ └── index.ts # Turnkey API endpoints
123
+ ├── src/ # Frontend React app
124
+ │ ├── App.tsx # Main app component
125
+ │ ├── main.tsx # Entry point
126
+ │ └── index.css # Styles
127
+ ├── public/ # Static assets
128
+ ├── .env # Environment variables (do not commit!)
129
+ └── package.json # Dependencies and scripts
130
+ ```
131
+
132
+ ## Available Scripts
133
+
134
+ - `npm run dev` - Start frontend development server
135
+ - `npm run dev:backend` - Start backend server with hot reload
136
+ - `npm run dev:fullstack` - Run both frontend and backend concurrently
137
+ - `npm run build` - Build for production
138
+ - `npm run preview` - Preview production build
139
+
140
+ ## Security Notes
141
+
142
+ ⚠️ **IMPORTANT**: Never expose Turnkey API keys to the frontend!
143
+
144
+ - API keys stay on the backend only
145
+ - Frontend uses passkeys for user authentication
146
+ - Each user gets their own isolated sub-organization
147
+
148
+ ## Production Deployment
149
+
150
+ ### Backend Deployment
151
+ Deploy the Express server to:
152
+ - Railway, Render, Fly.io (Node.js)
153
+ - Vercel, Netlify (Serverless functions)
154
+ - AWS Lambda, Google Cloud Functions
155
+
156
+ ### Frontend Deployment
157
+ Deploy the Vite app to:
158
+ - Vercel, Netlify, CloudFlare Pages
159
+ - Any static hosting service
160
+
161
+ ### Environment Variables
162
+
163
+ **Frontend (.env):**
164
+ ```bash
165
+ VITE_SBC_API_KEY=prod_key_here
166
+ VITE_TURNKEY_API_BASE_URL=https://api.turnkey.com
167
+ VITE_TURNKEY_RPID=yourdomain.com # Your production domain
168
+ VITE_BACKEND_URL=https://your-backend.com
169
+ ```
170
+
171
+ **Backend (.env):**
172
+ ```bash
173
+ TURNKEY_API_BASE_URL=https://api.turnkey.com
174
+ TURNKEY_ORGANIZATION_ID=prod_org_id
175
+ TURNKEY_API_PUBLIC_KEY=prod_public_key
176
+ TURNKEY_API_PRIVATE_KEY=prod_private_key
177
+ PORT=3001
178
+ ```
179
+
180
+ ## Troubleshooting
181
+
182
+ ### "Failed to create sub-org"
183
+ - Check backend logs for detailed error
184
+ - Verify `TURNKEY_API_PUBLIC_KEY` and `TURNKEY_API_PRIVATE_KEY` are correct
185
+ - Ensure `TURNKEY_ORGANIZATION_ID` matches your Turnkey org
186
+
187
+ ### "Network Error" when signing up
188
+ - Make sure backend is running (`npm run dev:backend`)
189
+ - Check `VITE_BACKEND_URL` points to correct backend URL
190
+ - Verify CORS is configured (backend allows frontend origin)
191
+
192
+ ### Passkey creation fails
193
+ - Use HTTPS in production (passkeys require secure context)
194
+ - For localhost: use `http://localhost` (not `127.0.0.1`)
195
+ - Check `VITE_TURNKEY_RPID` matches your domain
196
+
197
+ ## Resources
198
+
199
+ - [Turnkey Documentation](https://docs.turnkey.com)
200
+ - [Turnkey Dashboard](https://app.turnkey.com)
201
+ - [SBC App Kit Docs](https://docs.stablecoin.xyz)
202
+ - [Turnkey SDK GitHub](https://github.com/tkhq/sdk)
203
+
204
+ ## License
205
+
206
+ MIT
@@ -0,0 +1,32 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import tseslint from '@typescript-eslint/eslint-plugin'
6
+ import tsparser from '@typescript-eslint/parser'
7
+
8
+ export default [
9
+ { ignores: ['dist'] },
10
+ {
11
+ files: ['**/*.{ts,tsx}'],
12
+ languageOptions: {
13
+ ecmaVersion: 2020,
14
+ globals: globals.browser,
15
+ parser: tsparser,
16
+ },
17
+ plugins: {
18
+ '@typescript-eslint': tseslint,
19
+ 'react-hooks': reactHooks,
20
+ 'react-refresh': reactRefresh,
21
+ },
22
+ rules: {
23
+ ...js.configs.recommended.rules,
24
+ ...tseslint.configs.recommended.rules,
25
+ ...reactHooks.configs.recommended.rules,
26
+ 'react-refresh/only-export-components': [
27
+ 'warn',
28
+ { allowConstantExport: true },
29
+ ],
30
+ },
31
+ },
32
+ ]
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/png" href="/sbc-logo.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>{{projectName}}</title>
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ <script type="module" src="/src/main.tsx"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "private": true,
4
+ "version": "0.0.1",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "dev:backend": "tsx watch server/index.ts",
9
+ "dev:fullstack": "concurrently \"npm run dev:backend\" \"npm run dev\"",
10
+ "build": "tsc && vite build",
11
+ "preview": "vite preview",
12
+ "lint": "eslint .",
13
+ "start": "vite"
14
+ },
15
+ "dependencies": {
16
+ "@stablecoin.xyz/core": "latest",
17
+ "@stablecoin.xyz/react": "latest",
18
+ "@turnkey/sdk-react": "^5.4.10",
19
+ "@turnkey/sdk-server": "^4.12.0",
20
+ "@turnkey/viem": "^0.14.12",
21
+ "cors": "^2.8.5",
22
+ "dotenv": "^17.2.3",
23
+ "express": "^5.1.0",
24
+ "react": "^18.2.0",
25
+ "react-dom": "^18.2.0",
26
+ "viem": "^2.33.0"
27
+ },
28
+ "devDependencies": {
29
+ "@eslint/js": "^9.9.0",
30
+ "@types/cors": "^2.8.19",
31
+ "@types/express": "^5.0.5",
32
+ "@types/react": "^18.2.66",
33
+ "@types/react-dom": "^18.2.22",
34
+ "@vitejs/plugin-react": "^4.0.0",
35
+ "concurrently": "^9.2.1",
36
+ "eslint": "^9.9.0",
37
+ "eslint-plugin-react-hooks": "^5.1.0-rc.0",
38
+ "eslint-plugin-react-refresh": "^0.4.9",
39
+ "globals": "^15.9.0",
40
+ "tsx": "^4.20.6",
41
+ "typescript": "^5.0.0",
42
+ "typescript-eslint": "^8.0.1",
43
+ "vite": "^5.0.0"
44
+ }
45
+ }