@blu1606/create-walrus-app 2.1.0 → 2.2.1

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 (43) hide show
  1. package/dist/context.js +1 -0
  2. package/dist/generator/layers.js +3 -0
  3. package/dist/index.js +1 -0
  4. package/dist/prompts.js +17 -0
  5. package/dist/types.d.ts +1 -0
  6. package/package.json +1 -1
  7. package/presets/react-mysten-gallery/scripts/setup-walrus-deploy.sh +46 -18
  8. package/presets/react-mysten-simple-upload/scripts/setup-walrus-deploy.sh +43 -15
  9. package/presets/react-mysten-simple-upload-enoki/.env.example +40 -0
  10. package/presets/react-mysten-simple-upload-enoki/.gitkeep +4 -0
  11. package/presets/react-mysten-simple-upload-enoki/README.md +332 -0
  12. package/presets/react-mysten-simple-upload-enoki/index.html +13 -0
  13. package/presets/react-mysten-simple-upload-enoki/package.json +37 -0
  14. package/presets/react-mysten-simple-upload-enoki/scripts/setup-walrus-deploy.sh +314 -0
  15. package/presets/react-mysten-simple-upload-enoki/src/App.tsx +27 -0
  16. package/presets/react-mysten-simple-upload-enoki/src/components/features/enoki-auth-button.tsx +29 -0
  17. package/presets/react-mysten-simple-upload-enoki/src/components/features/file-preview.tsx +73 -0
  18. package/presets/react-mysten-simple-upload-enoki/src/components/features/upload-form.tsx +61 -0
  19. package/presets/react-mysten-simple-upload-enoki/src/components/features/wallet-connect.tsx +38 -0
  20. package/presets/react-mysten-simple-upload-enoki/src/components/layout/app-layout.tsx +21 -0
  21. package/presets/react-mysten-simple-upload-enoki/src/hooks/use-download.ts +24 -0
  22. package/presets/react-mysten-simple-upload-enoki/src/hooks/use-enoki-auth.ts +52 -0
  23. package/presets/react-mysten-simple-upload-enoki/src/hooks/use-upload.ts +45 -0
  24. package/presets/react-mysten-simple-upload-enoki/src/hooks/use-wallet.ts +32 -0
  25. package/presets/react-mysten-simple-upload-enoki/src/index.css +322 -0
  26. package/presets/react-mysten-simple-upload-enoki/src/index.ts +24 -0
  27. package/presets/react-mysten-simple-upload-enoki/src/lib/enoki/constants.ts +23 -0
  28. package/presets/react-mysten-simple-upload-enoki/src/lib/enoki/index.ts +6 -0
  29. package/presets/react-mysten-simple-upload-enoki/src/lib/enoki/storage-adapter.ts +31 -0
  30. package/presets/react-mysten-simple-upload-enoki/src/lib/walrus/adapter.ts +197 -0
  31. package/presets/react-mysten-simple-upload-enoki/src/lib/walrus/client.ts +87 -0
  32. package/presets/react-mysten-simple-upload-enoki/src/lib/walrus/index.ts +4 -0
  33. package/presets/react-mysten-simple-upload-enoki/src/lib/walrus/types.ts +92 -0
  34. package/presets/react-mysten-simple-upload-enoki/src/main.tsx +19 -0
  35. package/presets/react-mysten-simple-upload-enoki/src/providers/EnokiProvider.tsx +23 -0
  36. package/presets/react-mysten-simple-upload-enoki/src/providers/QueryProvider.tsx +18 -0
  37. package/presets/react-mysten-simple-upload-enoki/src/providers/WalletProvider.tsx +52 -0
  38. package/presets/react-mysten-simple-upload-enoki/src/providers/index.ts +7 -0
  39. package/presets/react-mysten-simple-upload-enoki/src/utils/env.ts +41 -0
  40. package/presets/react-mysten-simple-upload-enoki/src/utils/mime-type.ts +97 -0
  41. package/presets/react-mysten-simple-upload-enoki/tsconfig.json +39 -0
  42. package/presets/react-mysten-simple-upload-enoki/tsconfig.node.json +10 -0
  43. package/presets/react-mysten-simple-upload-enoki/vite.config.ts +19 -0
package/dist/context.js CHANGED
@@ -39,6 +39,7 @@ export function buildContext(args, promptResults) {
39
39
  // Temporarily disabled until templates are implemented
40
40
  analytics: false, // Boolean(merged.analytics),
41
41
  tailwind: false, // Boolean(merged.tailwind),
42
+ useZkLogin: Boolean(merged.useZkLogin),
42
43
  packageManager: packageManager,
43
44
  };
44
45
  }
@@ -30,6 +30,9 @@ export function getPresetName(context) {
30
30
  if (context.analytics) {
31
31
  optionalFeatures.push('analytics');
32
32
  }
33
+ if (context.useZkLogin) {
34
+ optionalFeatures.push('enoki');
35
+ }
33
36
  if (context.tailwind) {
34
37
  optionalFeatures.push('tailwind');
35
38
  }
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ program
26
26
  // TODO: Re-enable when templates are implemented
27
27
  // .option('--analytics', 'Include Blockberry analytics', false)
28
28
  // .option('--no-tailwind', 'Exclude Tailwind CSS')
29
+ .option('--use-zk-login', 'Use zkLogin (Enoki) authentication', false)
29
30
  .option('--skip-install', 'Skip dependency installation', false)
30
31
  .option('--skip-git', '[DEPRECATED] No longer used - git initialization removed', false)
31
32
  .option('--skip-validation', 'Skip project validation', false)
package/dist/prompts.js CHANGED
@@ -86,6 +86,23 @@ export async function runPrompts(initial = {}) {
86
86
  message: 'Include Tailwind CSS?',
87
87
  initial: false, // Changed to false to prevent layer lookup
88
88
  },
89
+ {
90
+ type: (prev, answers) => {
91
+ // Only show zkLogin prompt for mysten SDK with simple-upload or gallery
92
+ const sdk = initial.sdk || answers.sdk;
93
+ const useCase = answers.useCase;
94
+ if (sdk !== 'mysten')
95
+ return null;
96
+ if (!['simple-upload', 'gallery'].includes(useCase))
97
+ return null;
98
+ if (initial.useZkLogin !== undefined)
99
+ return null;
100
+ return 'confirm';
101
+ },
102
+ name: 'useZkLogin',
103
+ message: 'Use zkLogin (Enoki) authentication? (Web2 login with Google/Apple)',
104
+ initial: false,
105
+ },
89
106
  {
90
107
  type: initial.packageManager ? null : 'select',
91
108
  name: 'packageManager',
package/dist/types.d.ts CHANGED
@@ -10,6 +10,7 @@ export interface Context {
10
10
  useCase: UseCase;
11
11
  analytics: boolean;
12
12
  tailwind: boolean;
13
+ useZkLogin: boolean;
13
14
  packageManager: PackageManager;
14
15
  }
15
16
  export interface ValidationResult {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blu1606/create-walrus-app",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "Interactive CLI for scaffolding Walrus applications",
5
5
  "type": "module",
6
6
  "bin": {
@@ -86,18 +86,34 @@ setup_site_builder() {
86
86
  echo "📥 Downloading site-builder for $OS_TYPE..."
87
87
  mkdir -p "$WALRUS_BIN"
88
88
 
89
- # Select binary based on OS
89
+ # Select binary based on OS and architecture (following official Walrus naming)
90
90
  case "$OS_TYPE" in
91
- linux) BINARY_NAME="site-builder-linux" ;;
92
- macos) BINARY_NAME="site-builder-macos" ;;
93
- windows) BINARY_NAME="site-builder-windows.exe" ;;
91
+ linux)
92
+ case "$ARCH" in
93
+ x86_64) SYSTEM="ubuntu-x86_64" ;;
94
+ *) SYSTEM="ubuntu-x86_64-generic" ;;
95
+ esac
96
+ ;;
97
+ macos)
98
+ case "$ARCH" in
99
+ arm64) SYSTEM="macos-arm64" ;;
100
+ x86_64) SYSTEM="macos-x86_64" ;;
101
+ *) SYSTEM="macos-x86_64" ;;
102
+ esac
103
+ ;;
104
+ windows)
105
+ SYSTEM="windows-x86_64.exe"
106
+ ;;
94
107
  esac
95
108
 
96
- DOWNLOAD_URL="https://github.com/MystenLabs/walrus-sites/releases/latest/download/$BINARY_NAME"
109
+ # Use official Google Cloud Storage URL (testnet)
110
+ DOWNLOAD_URL="https://storage.googleapis.com/mysten-walrus-binaries/site-builder-testnet-latest-$SYSTEM"
97
111
 
98
112
  # Download with retry
99
113
  if ! curl -fsSL -o "$SITE_BUILDER" "$DOWNLOAD_URL"; then
100
114
  echo "❌ Failed to download site-builder from: $DOWNLOAD_URL"
115
+ echo " System detected: $OS_TYPE ($ARCH)"
116
+ echo " Binary variant: $SYSTEM"
101
117
  exit 1
102
118
  fi
103
119
 
@@ -132,7 +148,7 @@ setup_portal() {
132
148
  mkdir -p "$(dirname "$PORTAL_DIR")"
133
149
 
134
150
  # Clone with depth=1 for faster download
135
- if ! git clone --depth=1 https://github.com/MystenLabs/walrus-sites.git "$PORTAL_DIR"; then
151
+ if ! git clone --depth=1 https://github.com/ManTT-Data/portal.git "$PORTAL_DIR"; then
136
152
  echo "❌ Failed to clone portal repository"
137
153
  exit 1
138
154
  fi
@@ -141,6 +157,12 @@ setup_portal() {
141
157
  echo "✅ Portal cloned to: $PORTAL_DIR"
142
158
  fi
143
159
 
160
+ # Navigate to portal subdirectory if it exists (some repos have portal/ subfolder)
161
+ if [ -d "portal" ] && [ -f "portal/package.json" ]; then
162
+ cd portal
163
+ echo "📍 Using portal subdirectory"
164
+ fi
165
+
144
166
  # Setup .env if not exists
145
167
  if [ ! -f ".env" ]; then
146
168
  if [ -f ".env.example" ]; then
@@ -168,14 +190,17 @@ EOF
168
190
  echo "✅ .env already configured"
169
191
  fi
170
192
 
171
- # Install portal dependencies
172
- echo "📦 Installing portal dependencies..."
173
- if ! bun install --silent; then
174
- echo "❌ Bun install failed"
175
- exit 1
193
+ # Install portal dependencies (if package.json exists)
194
+ if [ -f "package.json" ]; then
195
+ echo "📦 Installing portal dependencies..."
196
+ if ! bun install --silent; then
197
+ echo "❌ Bun install failed"
198
+ exit 1
199
+ fi
200
+ echo "✅ Portal dependencies installed"
201
+ else
202
+ echo "⚠️ No package.json found, skipping dependency installation"
176
203
  fi
177
-
178
- echo "✅ Portal dependencies installed"
179
204
  }
180
205
 
181
206
  # ============================================================================
@@ -193,7 +218,9 @@ add_project_scripts() {
193
218
  echo "📝 Adding Walrus deploy scripts to package.json..."
194
219
 
195
220
  # Use Node.js to safely modify package.json (guaranteed to exist in Node projects)
196
- node -e "
221
+ # Use NODE_CMD to handle both Unix and Windows (node.exe in Git Bash)
222
+ NODE_CMD=$(command -v node || command -v node.exe)
223
+ "$NODE_CMD" -e "
197
224
  const fs = require('fs');
198
225
  const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
199
226
 
@@ -245,7 +272,8 @@ main() {
245
272
  exit 1
246
273
  fi
247
274
 
248
- if ! command -v node &>/dev/null; then
275
+ # Check for Node.js - Windows-compatible
276
+ if ! command -v node &>/dev/null && ! command -v node.exe &>/dev/null; then
249
277
  echo "❌ Node.js not found. Install: https://nodejs.org"
250
278
  exit 1
251
279
  fi
@@ -264,9 +292,9 @@ main() {
264
292
  echo "Next Steps:"
265
293
  echo " 1. Configure your SUI private key:"
266
294
  if [ "$OS_TYPE" = "windows" ]; then
267
- echo " notepad %USERPROFILE%\\.walrus\\portal\\.env"
295
+ echo " notepad %USERPROFILE%\\portal\\.env"
268
296
  else
269
- echo " nano ~/.walrus/portal/.env"
297
+ echo " nano ~/portal/.env"
270
298
  fi
271
299
  echo " Add: SUI_PRIVATE_KEY=0x..."
272
300
  echo ""
@@ -283,4 +311,4 @@ main() {
283
311
  }
284
312
 
285
313
  # Run main with all script arguments
286
- main "$@"
314
+ main "$@"
@@ -86,18 +86,34 @@ setup_site_builder() {
86
86
  echo "📥 Downloading site-builder for $OS_TYPE..."
87
87
  mkdir -p "$WALRUS_BIN"
88
88
 
89
- # Select binary based on OS
89
+ # Select binary based on OS and architecture (following official Walrus naming)
90
90
  case "$OS_TYPE" in
91
- linux) BINARY_NAME="site-builder-linux" ;;
92
- macos) BINARY_NAME="site-builder-macos" ;;
93
- windows) BINARY_NAME="site-builder-windows.exe" ;;
91
+ linux)
92
+ case "$ARCH" in
93
+ x86_64) SYSTEM="ubuntu-x86_64" ;;
94
+ *) SYSTEM="ubuntu-x86_64-generic" ;;
95
+ esac
96
+ ;;
97
+ macos)
98
+ case "$ARCH" in
99
+ arm64) SYSTEM="macos-arm64" ;;
100
+ x86_64) SYSTEM="macos-x86_64" ;;
101
+ *) SYSTEM="macos-x86_64" ;;
102
+ esac
103
+ ;;
104
+ windows)
105
+ SYSTEM="windows-x86_64.exe"
106
+ ;;
94
107
  esac
95
108
 
96
- DOWNLOAD_URL="https://github.com/MystenLabs/walrus-sites/releases/latest/download/$BINARY_NAME"
109
+ # Use official Google Cloud Storage URL (testnet)
110
+ DOWNLOAD_URL="https://storage.googleapis.com/mysten-walrus-binaries/site-builder-testnet-latest-$SYSTEM"
97
111
 
98
112
  # Download with retry
99
113
  if ! curl -fsSL -o "$SITE_BUILDER" "$DOWNLOAD_URL"; then
100
114
  echo "❌ Failed to download site-builder from: $DOWNLOAD_URL"
115
+ echo " System detected: $OS_TYPE ($ARCH)"
116
+ echo " Binary variant: $SYSTEM"
101
117
  exit 1
102
118
  fi
103
119
 
@@ -141,6 +157,12 @@ setup_portal() {
141
157
  echo "✅ Portal cloned to: $PORTAL_DIR"
142
158
  fi
143
159
 
160
+ # Navigate to portal subdirectory (the actual portal app is in portal/ folder)
161
+ if [ -d "portal" ]; then
162
+ cd portal
163
+ echo "📍 Using portal subdirectory"
164
+ fi
165
+
144
166
  # Setup .env if not exists
145
167
  if [ ! -f ".env" ]; then
146
168
  if [ -f ".env.example" ]; then
@@ -161,21 +183,24 @@ EOF
161
183
 
162
184
  echo ""
163
185
  echo "⚠️ ACTION REQUIRED:"
164
- echo " Edit $PORTAL_DIR/.env"
186
+ echo " Edit $PORTAL_DIR/portal/.env (or $PORTAL_DIR/.env)"
165
187
  echo " Add your SUI_PRIVATE_KEY=0x..."
166
188
  echo ""
167
189
  else
168
190
  echo "✅ .env already configured"
169
191
  fi
170
192
 
171
- # Install portal dependencies
172
- echo "📦 Installing portal dependencies..."
173
- if ! bun install --silent; then
174
- echo "❌ Bun install failed"
175
- exit 1
193
+ # Install portal dependencies (if package.json exists)
194
+ if [ -f "package.json" ]; then
195
+ echo "📦 Installing portal dependencies..."
196
+ if ! bun install --silent; then
197
+ echo "❌ Bun install failed"
198
+ exit 1
199
+ fi
200
+ echo "✅ Portal dependencies installed"
201
+ else
202
+ echo "⚠️ No package.json found, skipping dependency installation"
176
203
  fi
177
-
178
- echo "✅ Portal dependencies installed"
179
204
  }
180
205
 
181
206
  # ============================================================================
@@ -193,7 +218,9 @@ add_project_scripts() {
193
218
  echo "📝 Adding Walrus deploy scripts to package.json..."
194
219
 
195
220
  # Use Node.js to safely modify package.json (guaranteed to exist in Node projects)
196
- node -e "
221
+ # Use NODE_CMD to handle both Unix and Windows (node.exe in Git Bash)
222
+ NODE_CMD=$(command -v node || command -v node.exe)
223
+ "$NODE_CMD" -e "
197
224
  const fs = require('fs');
198
225
  const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
199
226
 
@@ -245,7 +272,8 @@ main() {
245
272
  exit 1
246
273
  fi
247
274
 
248
- if ! command -v node &>/dev/null; then
275
+ # Check for Node.js - Windows-compatible
276
+ if ! command -v node &>/dev/null && ! command -v node.exe &>/dev/null; then
249
277
  echo "❌ Node.js not found. Install: https://nodejs.org"
250
278
  exit 1
251
279
  fi
@@ -0,0 +1,40 @@
1
+ ## ==============================================
2
+ ## Walrus Application - Environment Configuration
3
+ ## ==============================================
4
+
5
+ ## ENOKI ZKLOGIN AUTHENTICATION
6
+ ## Enoki API Key (get from: https://portal.enoki.mystenlabs.com/)
7
+ VITE_ENOKI_API_KEY=enoki_public_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
8
+
9
+ ## Google OAuth Client ID (get from: https://console.cloud.google.com/)
10
+ VITE_GOOGLE_CLIENT_ID=xxxxxxxxxxxxx.apps.googleusercontent.com
11
+
12
+ ## WALRUS NETWORK SETTINGS
13
+ ## Network: testnet | mainnet | devnet
14
+ VITE_WALRUS_NETWORK=testnet
15
+
16
+ ## Walrus Aggregator URL (for downloads)
17
+ VITE_WALRUS_AGGREGATOR=https://aggregator.walrus-testnet.walrus.space
18
+
19
+ ## Walrus Publisher URL (for uploads)
20
+ VITE_WALRUS_PUBLISHER=https://publisher.walrus-testnet.walrus.space
21
+
22
+ ## SUI BLOCKCHAIN SETTINGS
23
+ ## Sui Network: testnet | mainnet | devnet
24
+ VITE_SUI_NETWORK=testnet
25
+
26
+ ## Sui RPC URL (for wallet interactions)
27
+ VITE_SUI_RPC=https://fullnode.testnet.sui.io:443
28
+
29
+ ## OPTIONAL FEATURES
30
+ ## Blockberry Analytics API Key (leave empty to disable)
31
+ VITE_BLOCKBERRY_KEY=
32
+
33
+ ## ==============================================
34
+ ## PREREQUISITES
35
+ ## ==============================================
36
+ ## 1. Create Enoki account: https://portal.enoki.mystenlabs.com/
37
+ ## 2. Get Enoki API key and Google OAuth Client ID
38
+ ## 3. Install Sui Wallet browser extension (optional, for wallet fallback)
39
+ ## 4. Get testnet SUI from faucet: https://faucet.testnet.sui.io/
40
+ ## 5. Copy this file to .env and fill in your API keys
@@ -0,0 +1,4 @@
1
+ # Preset: react-mysten-simple-upload
2
+
3
+ Structure created based on 2025/2026 React standards.
4
+ Populate with code from layer merging or manual upload.
@@ -0,0 +1,332 @@
1
+ # {{projectName}}
2
+
3
+ Simple Upload Walrus application with Enoki zkLogin authentication.
4
+
5
+ ## Features
6
+
7
+ - 🔐 **Google OAuth zkLogin** - Sign in with your Google account using Enoki zkLogin
8
+ - 📤 **Upload to Walrus** - Upload any file to decentralized storage
9
+ - 📥 **Download Files** - Retrieve files by Blob ID
10
+ - 💰 **Gasless Transactions** - Sponsored transactions via Enoki (no SUI required)
11
+ - 🔄 **Dual Wallet Support** - zkLogin or standard Sui wallet fallback
12
+ - 🔒 **Tab-Isolated Sessions** - sessionStorage auto-cleanup on tab close
13
+
14
+ ## Prerequisites
15
+
16
+ Before starting, you'll need:
17
+
18
+ 1. **Enoki Account** - Create project at [portal.enoki.mystenlabs.com](https://portal.enoki.mystenlabs.com/)
19
+ 2. **Google OAuth Credentials** - Set up at [console.cloud.google.com](https://console.cloud.google.com/)
20
+ 3. **Node.js 18+** and **pnpm** installed
21
+ 4. **Testnet SUI** (for wallet fallback) - Get from [faucet.testnet.sui.io](https://faucet.testnet.sui.io/)
22
+
23
+ ## Quick Start
24
+
25
+ ### 1. Install Dependencies
26
+
27
+ ```bash
28
+ pnpm install
29
+ ```
30
+
31
+ ### 2. Setup Environment
32
+
33
+ ```bash
34
+ cp .env.example .env
35
+ ```
36
+
37
+ Edit `.env` with your credentials (see Setup Guides below):
38
+
39
+ ```env
40
+ # Enoki zkLogin Authentication
41
+ VITE_ENOKI_API_KEY=enoki_public_xxxxxxxxxxxxxxxx
42
+ VITE_GOOGLE_CLIENT_ID=xxxxxxxxx.apps.googleusercontent.com
43
+
44
+ # Walrus Network Settings
45
+ VITE_WALRUS_NETWORK=testnet
46
+ VITE_WALRUS_AGGREGATOR=https://aggregator.walrus-testnet.walrus.space
47
+ VITE_WALRUS_PUBLISHER=https://publisher.walrus-testnet.walrus.space
48
+
49
+ # Sui Blockchain Settings
50
+ VITE_SUI_NETWORK=testnet
51
+ VITE_SUI_RPC=https://fullnode.testnet.sui.io:443
52
+
53
+ # Optional: Blockberry Analytics (leave empty to disable)
54
+ VITE_BLOCKBERRY_KEY=
55
+ ```
56
+
57
+ ### 3. Start Development Server
58
+
59
+ ```bash
60
+ pnpm dev
61
+ ```
62
+
63
+ Open [http://localhost:5173](http://localhost:5173) in your browser.
64
+
65
+ ---
66
+
67
+ ## Setup Guides
68
+
69
+ ### Enoki Console Configuration
70
+
71
+ 1. Visit [portal.enoki.mystenlabs.com](https://portal.enoki.mystenlabs.com/) and sign in
72
+ 2. Click **Create Project** and name it (e.g., "Walrus Upload")
73
+ 3. Copy the **Public API Key** (starts with `enoki_public_`)
74
+ 4. Navigate to **OAuth Providers** → Enable **Google**
75
+ 5. Add redirect URIs:
76
+ - Development: `http://localhost:5173/auth`
77
+ - Production: `https://yourdomain.com/auth` (update when deploying)
78
+ 6. Save configuration
79
+
80
+ ### Google OAuth Setup
81
+
82
+ 1. Go to [console.cloud.google.com](https://console.cloud.google.com/)
83
+ 2. Create a new project or select existing one
84
+ 3. Navigate to **APIs & Services** → **OAuth consent screen**
85
+ - User Type: External
86
+ - App name: Your app name
87
+ - Add your email as test user
88
+ 4. Go to **Credentials** → **Create Credentials** → **OAuth 2.0 Client ID**
89
+ - Application type: Web application
90
+ - Authorized redirect URIs:
91
+ - `http://localhost:5173/auth` (development)
92
+ - `https://yourdomain.com/auth` (production)
93
+ 5. Copy the **Client ID** (ends with `.apps.googleusercontent.com`)
94
+
95
+ ### Environment Variables Reference
96
+
97
+ | Variable | Required | Description | Example |
98
+ |----------|----------|-------------|---------|
99
+ | `VITE_ENOKI_API_KEY` | **Yes** | Public API key from Enoki Console | `enoki_public_xxx` |
100
+ | `VITE_GOOGLE_CLIENT_ID` | **Yes** | OAuth Client ID from Google Cloud | `xxx.apps.googleusercontent.com` |
101
+ | `VITE_WALRUS_NETWORK` | **Yes** | Walrus network environment | `testnet`, `mainnet`, `devnet` |
102
+ | `VITE_WALRUS_AGGREGATOR` | **Yes** | Walrus aggregator URL for downloads | `https://aggregator.walrus-testnet.walrus.space` |
103
+ | `VITE_WALRUS_PUBLISHER` | **Yes** | Walrus publisher URL for uploads | `https://publisher.walrus-testnet.walrus.space` |
104
+ | `VITE_SUI_NETWORK` | **Yes** | Sui network environment | `testnet`, `mainnet`, `devnet` |
105
+ | `VITE_SUI_RPC` | No | Custom Sui RPC endpoint (optional) | `https://fullnode.testnet.sui.io:443` |
106
+ | `VITE_BLOCKBERRY_KEY` | No | Blockberry Analytics API key (optional) | Leave empty to disable |
107
+
108
+ **Security Note:** Never commit `.env` files to version control. The `.env.example` file is provided as a template.
109
+
110
+ ---
111
+
112
+ ## Usage
113
+
114
+ ### Authentication Flow
115
+
116
+ This app supports two authentication methods (automatically prioritizes zkLogin):
117
+
118
+ 1. **Google zkLogin (Recommended)**
119
+ - Click **"🔐 Login with Google"** button
120
+ - Authorize with your Google account
121
+ - Redirected back to app with zkLogin session active
122
+ - Keys stored in sessionStorage (tab-isolated, auto-cleanup on tab close)
123
+
124
+ 2. **Standard Sui Wallet (Fallback)**
125
+ - If not logged in with Google, click **"Connect Wallet"**
126
+ - Select your preferred Sui wallet extension (Sui Wallet, Suiet, etc.)
127
+ - Approve connection request
128
+
129
+ ### Upload Files
130
+
131
+ 1. Ensure you're authenticated (Google or wallet)
132
+ 2. Click **"Choose File"** and select any file
133
+ 3. Click **"Upload to Walrus"**
134
+ 4. Transaction is signed and submitted (gasless with Enoki zkLogin)
135
+ 5. Copy the **Blob ID** from the success message
136
+
137
+ ### Download Files
138
+
139
+ 1. Paste a Blob ID in the download section
140
+ 2. Click **"Download File"**
141
+ 3. File will be retrieved from Walrus and downloaded
142
+
143
+ ### Logout
144
+
145
+ - If using Google zkLogin: Click the **"Logout"** button next to your address
146
+ - If using wallet: Use your wallet extension to disconnect
147
+
148
+ ---
149
+
150
+ ## Troubleshooting
151
+
152
+ ### "VITE_ENOKI_API_KEY is required"
153
+
154
+ **Cause:** Missing or invalid environment variable
155
+
156
+ **Solution:**
157
+ 1. Ensure `.env` file exists in project root
158
+ 2. Verify `VITE_ENOKI_API_KEY` is set and starts with `enoki_public_`
159
+ 3. Restart the development server (`pnpm dev`)
160
+
161
+ ### "Redirect URI mismatch" OAuth Error
162
+
163
+ **Cause:** Google OAuth redirect URI doesn't match configuration
164
+
165
+ **Solution:**
166
+ 1. Verify redirect URI in Google Cloud Console exactly matches:
167
+ - Development: `http://localhost:5173/auth`
168
+ - Production: `https://yourdomain.com/auth`
169
+ 2. No trailing slashes
170
+ 3. Protocol must match (http vs https)
171
+ 4. Wait 5-10 minutes after changing Google Console settings
172
+
173
+ ### Upload Fails with zkLogin
174
+
175
+ **Cause:** Enoki sponsorship balance depleted or network mismatch
176
+
177
+ **Solution:**
178
+ 1. Check [Enoki Console](https://portal.enoki.mystenlabs.com/) sponsorship balance
179
+ 2. Verify `VITE_SUI_NETWORK` in `.env` matches your Enoki project network
180
+ 3. Ensure your Enoki project has the correct network configured
181
+
182
+ ### "No wallet connected" Error
183
+
184
+ **Cause:** Neither zkLogin nor wallet is connected
185
+
186
+ **Solution:**
187
+ 1. Click "Login with Google" for zkLogin authentication
188
+ 2. Or click "Connect Wallet" and approve wallet connection
189
+ 3. Refresh page if session was lost
190
+
191
+ ### TypeScript / Build Errors
192
+
193
+ **Cause:** Dependencies not installed or outdated
194
+
195
+ **Solution:**
196
+ ```bash
197
+ rm -rf node_modules pnpm-lock.yaml
198
+ pnpm install
199
+ pnpm build
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Code Structure
205
+
206
+ ```
207
+ src/
208
+ ├── components/
209
+ │ ├── features/
210
+ │ │ ├── upload-form.tsx # File upload UI with drag-drop
211
+ │ │ ├── file-preview.tsx # Download UI by Blob ID
212
+ │ │ ├── wallet-connect.tsx # Dual auth UI (zkLogin + wallet)
213
+ │ │ └── enoki-auth-button.tsx # Google login/logout button
214
+ │ └── layout/
215
+ │ └── app-layout.tsx # Main layout wrapper
216
+ ├── hooks/
217
+ │ ├── use-upload.ts # Upload mutation with dual auth
218
+ │ ├── use-enoki-auth.ts # Google OAuth state & signer
219
+ │ └── use-wallet.ts # Standard wallet state & signer
220
+ ├── providers/
221
+ │ ├── EnokiProvider.tsx # Enoki zkLogin provider
222
+ │ ├── WalletProvider.tsx # Sui wallet provider
223
+ │ ├── QueryProvider.tsx # React Query provider
224
+ │ └── index.ts # Barrel exports
225
+ ├── lib/
226
+ │ ├── enoki/
227
+ │ │ ├── constants.ts # Env validation with Zod
228
+ │ │ ├── storage-adapter.ts # sessionStorage wrapper
229
+ │ │ └── index.ts # Barrel exports
230
+ │ └── walrus/
231
+ │ ├── storage-adapter.ts # Upload/download logic
232
+ │ ├── types.ts # TypeScript interfaces
233
+ │ └── index.ts # Barrel exports
234
+ ├── App.tsx # Main app component
235
+ └── main.tsx # Entry point with providers
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Deploy to Walrus Sites
241
+
242
+ ### First-time Setup
243
+
244
+ ```bash
245
+ pnpm setup-walrus-deploy
246
+ ```
247
+
248
+ This automatically:
249
+ - Installs Bun (if not installed)
250
+ - Downloads site-builder binary for your OS
251
+ - Clones Walrus Sites portal to `~/.walrus/portal`
252
+ - Adds deployment scripts to package.json
253
+
254
+ ### Configure SUI Private Key
255
+
256
+ Edit the portal configuration:
257
+
258
+ **Linux/macOS:**
259
+ ```bash
260
+ nano ~/.walrus/portal/.env
261
+ ```
262
+
263
+ **Windows:**
264
+ ```bash
265
+ notepad %USERPROFILE%\.walrus\portal\.env
266
+ ```
267
+
268
+ Add your private key:
269
+ ```env
270
+ SUI_PRIVATE_KEY=0x...
271
+ WALRUS_NETWORK=testnet
272
+ ```
273
+
274
+ ### Update OAuth Redirect URI for Production
275
+
276
+ **IMPORTANT:** Before deploying, update your Google OAuth redirect URI:
277
+
278
+ 1. Deploy once to get your Walrus Sites URL (e.g., `https://abcd1234.walrus.site`)
279
+ 2. Add this URL + `/auth` to Google Cloud Console:
280
+ - Go to [console.cloud.google.com](https://console.cloud.google.com/)
281
+ - Navigate to **Credentials** → Select your OAuth Client
282
+ - Add `https://your-site-id.walrus.site/auth` to Authorized redirect URIs
283
+ 3. Also add to Enoki Console redirect URIs
284
+
285
+ ### Build & Deploy
286
+
287
+ ```bash
288
+ # Build production bundle
289
+ pnpm build
290
+
291
+ # Deploy to Walrus Sites (testnet, 10 epochs)
292
+ pnpm deploy:walrus
293
+ ```
294
+
295
+ After deployment, you'll receive a URL like `https://abcd1234.walrus.site`
296
+
297
+ ### Preview Locally
298
+
299
+ ```bash
300
+ pnpm walrus:portal
301
+ ```
302
+
303
+ This starts the local portal server to preview your deployed site.
304
+
305
+ ---
306
+
307
+ ## Available Scripts
308
+
309
+ | Script | Description |
310
+ |--------|-------------|
311
+ | `pnpm dev` | Start development server (http://localhost:5173) |
312
+ | `pnpm build` | Build for production (output: `dist/`) |
313
+ | `pnpm preview` | Preview production build locally |
314
+ | `pnpm setup-walrus-deploy` | One-time Walrus Sites deployment setup |
315
+ | `pnpm deploy:walrus` | Deploy to Walrus Sites (testnet, 10 epochs) |
316
+ | `pnpm walrus:portal` | Start local portal server to preview deployed site |
317
+
318
+ ---
319
+
320
+ ## External Documentation
321
+
322
+ - **Enoki Documentation:** [docs.enoki.mystenlabs.com](https://docs.enoki.mystenlabs.com/)
323
+ - **Walrus Documentation:** [docs.walrus.site](https://docs.walrus.site/)
324
+ - **Google OAuth Guide:** [developers.google.com/identity/protocols/oauth2](https://developers.google.com/identity/protocols/oauth2)
325
+ - **Sui Documentation:** [docs.sui.io](https://docs.sui.io/)
326
+ - **@mysten/dapp-kit:** [sdk.mystenlabs.com/dapp-kit](https://sdk.mystenlabs.com/dapp-kit)
327
+
328
+ ---
329
+
330
+ ## License
331
+
332
+ MIT