@jerydam/lumina-sdk 0.1.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/BUTTON_FIXES.md +59 -0
- package/DOCS_INDEX.md +332 -0
- package/DOCUMENTATION.md +252 -0
- package/DOCUMENTATION_BUILD_SUMMARY.md +376 -0
- package/DOCUMENTATION_COMPLETE.md +311 -0
- package/FEATURES.md +333 -0
- package/Lumina-sdk/src/components/lumina-provider.tsx +46 -0
- package/Lumina-sdk/src/components/transaction-confirm.tsx +242 -0
- package/Lumina-sdk/src/components/wallet-display.tsx +157 -0
- package/Lumina-sdk/src/components/wallet-login.tsx +163 -0
- package/Lumina-sdk/src/hooks/use-mobile.ts +19 -0
- package/Lumina-sdk/src/hooks/use-toast.ts +191 -0
- package/Lumina-sdk/src/index.ts +0 -0
- package/Lumina-sdk/src/lib/api.ts +66 -0
- package/Lumina-sdk/src/lib/utils.ts +6 -0
- package/Lumina-sdk/src/package.json +42 -0
- package/Lumina-sdk/src/tsconfig.json +19 -0
- package/NEW_FILES_MANIFEST.txt +146 -0
- package/README.md +298 -0
- package/app/dashboard/analytics/page.tsx +218 -0
- package/app/dashboard/api-keys/page.tsx +260 -0
- package/app/dashboard/billing/page.tsx +412 -0
- package/app/dashboard/integration/page.tsx +185 -0
- package/app/dashboard/layout.tsx +18 -0
- package/app/dashboard/page.tsx +244 -0
- package/app/dashboard/settings/page.tsx +285 -0
- package/app/dashboard/users/page.tsx +148 -0
- package/app/docs/api/authentication/page.tsx +246 -0
- package/app/docs/api/endpoints/page.tsx +397 -0
- package/app/docs/api/errors/page.tsx +305 -0
- package/app/docs/api/overview/page.tsx +306 -0
- package/app/docs/examples/basic-setup/page.tsx +256 -0
- package/app/docs/examples/multi-chain/page.tsx +331 -0
- package/app/docs/examples/nextjs-full-stack/page.tsx +332 -0
- package/app/docs/getting-started/environment-setup/page.tsx +243 -0
- package/app/docs/getting-started/installation/page.tsx +187 -0
- package/app/docs/getting-started/introduction/page.tsx +178 -0
- package/app/docs/getting-started/quick-start/page.tsx +199 -0
- package/app/docs/guides/nextjs/page.tsx +358 -0
- package/app/docs/guides/react/page.tsx +230 -0
- package/app/docs/guides/security/page.tsx +284 -0
- package/app/docs/layout.tsx +32 -0
- package/app/docs/page.tsx +180 -0
- package/app/docs/sdk/lumina-provider/page.tsx +186 -0
- package/app/docs/sdk/transaction-confirm/page.tsx +331 -0
- package/app/docs/sdk/wallet-display/page.tsx +224 -0
- package/app/docs/sdk/wallet-login/page.tsx +207 -0
- package/app/docs/troubleshooting/common-issues/page.tsx +301 -0
- package/app/docs/troubleshooting/faq/page.tsx +105 -0
- package/app/globals.css +125 -0
- package/app/invite/[token]/page.tsx +78 -0
- package/app/layout.tsx +36 -0
- package/app/login/page.tsx +175 -0
- package/app/page.tsx +336 -0
- package/app/sdk-demo/page.tsx +239 -0
- package/components/dashboard-sidebar.tsx +113 -0
- package/components/docs/breadcrumb.tsx +51 -0
- package/components/docs/callout.tsx +53 -0
- package/components/docs/code-block.tsx +77 -0
- package/components/docs/docs-sidebar.tsx +214 -0
- package/components/docs/table-of-contents.tsx +83 -0
- package/components/sdk/lumina-provider.tsx +46 -0
- package/components/sdk/transaction-confirm.tsx +242 -0
- package/components/sdk/wallet-display.tsx +157 -0
- package/components/sdk/wallet-login.tsx +163 -0
- package/components/theme-provider.tsx +11 -0
- package/components/ui/accordion.tsx +66 -0
- package/components/ui/alert-dialog.tsx +157 -0
- package/components/ui/alert.tsx +66 -0
- package/components/ui/aspect-ratio.tsx +11 -0
- package/components/ui/avatar.tsx +53 -0
- package/components/ui/badge.tsx +46 -0
- package/components/ui/breadcrumb.tsx +109 -0
- package/components/ui/button-group.tsx +83 -0
- package/components/ui/button.tsx +60 -0
- package/components/ui/calendar.tsx +213 -0
- package/components/ui/card.tsx +92 -0
- package/components/ui/carousel.tsx +241 -0
- package/components/ui/chart.tsx +351 -0
- package/components/ui/checkbox.tsx +32 -0
- package/components/ui/collapsible.tsx +33 -0
- package/components/ui/command.tsx +184 -0
- package/components/ui/context-menu.tsx +252 -0
- package/components/ui/dialog.tsx +143 -0
- package/components/ui/drawer.tsx +135 -0
- package/components/ui/dropdown-menu.tsx +257 -0
- package/components/ui/empty.tsx +104 -0
- package/components/ui/field.tsx +244 -0
- package/components/ui/form.tsx +167 -0
- package/components/ui/hover-card.tsx +44 -0
- package/components/ui/input-group.tsx +169 -0
- package/components/ui/input-otp.tsx +77 -0
- package/components/ui/input.tsx +21 -0
- package/components/ui/item.tsx +193 -0
- package/components/ui/kbd.tsx +28 -0
- package/components/ui/label.tsx +24 -0
- package/components/ui/menubar.tsx +276 -0
- package/components/ui/navigation-menu.tsx +166 -0
- package/components/ui/pagination.tsx +127 -0
- package/components/ui/popover.tsx +48 -0
- package/components/ui/progress.tsx +31 -0
- package/components/ui/radio-group.tsx +45 -0
- package/components/ui/resizable.tsx +56 -0
- package/components/ui/scroll-area.tsx +58 -0
- package/components/ui/select.tsx +185 -0
- package/components/ui/separator.tsx +28 -0
- package/components/ui/sheet.tsx +139 -0
- package/components/ui/sidebar.tsx +726 -0
- package/components/ui/skeleton.tsx +13 -0
- package/components/ui/slider.tsx +59 -0
- package/components/ui/sonner.tsx +25 -0
- package/components/ui/spinner.tsx +16 -0
- package/components/ui/switch.tsx +29 -0
- package/components/ui/table.tsx +116 -0
- package/components/ui/tabs.tsx +66 -0
- package/components/ui/textarea.tsx +18 -0
- package/components/ui/toast.tsx +129 -0
- package/components/ui/toaster.tsx +35 -0
- package/components/ui/toggle-group.tsx +73 -0
- package/components/ui/toggle.tsx +47 -0
- package/components/ui/tooltip.tsx +61 -0
- package/components/ui/use-mobile.tsx +19 -0
- package/components/ui/use-toast.ts +191 -0
- package/components.json +21 -0
- package/hooks/use-mobile.ts +19 -0
- package/hooks/use-toast.ts +191 -0
- package/lib/api.ts +66 -0
- package/lib/utils.ts +6 -0
- package/next-env.d.ts +6 -0
- package/next.config.mjs +11 -0
- package/package.json +73 -0
- package/pnpm-workspace.yaml +5 -0
- package/postcss.config.mjs +8 -0
- package/public/apple-icon.png +0 -0
- package/public/fav.jpeg +0 -0
- package/public/fav.png +0 -0
- package/public/icon-dark-32x32.png +0 -0
- package/public/icon-light-32x32.png +0 -0
- package/public/icon.png +0 -0
- package/public/icon.svg +26 -0
- package/public/logo.jpeg +0 -0
- package/public/logo.png +0 -0
- package/public/logo2.jpeg +0 -0
- package/public/logo2.png +0 -0
- package/public/placeholder-logo.png +0 -0
- package/public/placeholder-logo.svg +1 -0
- package/public/placeholder-user.jpg +0 -0
- package/public/placeholder.jpg +0 -0
- package/public/placeholder.svg +1 -0
- package/styles/globals.css +209 -0
- package/tailwind.config.ts +15 -0
- package/tsconfig.json +41 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { Breadcrumb } from '@/components/docs/breadcrumb'
|
|
4
|
+
import { TableOfContents } from '@/components/docs/table-of-contents'
|
|
5
|
+
import { CodeBlock } from '@/components/docs/code-block'
|
|
6
|
+
import { Callout } from '@/components/docs/callout'
|
|
7
|
+
|
|
8
|
+
export default function APIOverviewPage() {
|
|
9
|
+
const headings = [
|
|
10
|
+
{ id: 'introduction', level: 2, text: 'Introduction' },
|
|
11
|
+
{ id: 'base-url', level: 2, text: 'Base URL' },
|
|
12
|
+
{ id: 'authentication', level: 2, text: 'Authentication' },
|
|
13
|
+
{ id: 'requests', level: 2, text: 'Making Requests' },
|
|
14
|
+
{ id: 'response-format', level: 2, text: 'Response Format' },
|
|
15
|
+
{ id: 'headers', level: 2, text: 'Headers' },
|
|
16
|
+
{ id: 'rate-limits', level: 2, text: 'Rate Limits' },
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div className="flex gap-8 max-w-7xl mx-auto px-4 py-8">
|
|
21
|
+
<main className="flex-1 min-w-0">
|
|
22
|
+
<Breadcrumb
|
|
23
|
+
items={[
|
|
24
|
+
{ label: 'Docs', href: '/docs' },
|
|
25
|
+
{ label: 'API', href: '/docs/api/overview' },
|
|
26
|
+
{ label: 'Overview' },
|
|
27
|
+
]}
|
|
28
|
+
/>
|
|
29
|
+
|
|
30
|
+
<div className="mt-8 prose prose-invert max-w-none">
|
|
31
|
+
<h1>REST API Overview</h1>
|
|
32
|
+
|
|
33
|
+
<p className="text-lg text-foreground/80">
|
|
34
|
+
The Lumina REST API provides programmatic access to wallet management, transactions, and account operations.
|
|
35
|
+
</p>
|
|
36
|
+
|
|
37
|
+
<h2 id="introduction">Introduction</h2>
|
|
38
|
+
<p>
|
|
39
|
+
The Lumina API is built on REST principles and uses standard HTTP methods. All responses are JSON-encoded. The API uses API keys for authentication and enforces rate limits to ensure fair usage.
|
|
40
|
+
</p>
|
|
41
|
+
|
|
42
|
+
<Callout type="info">
|
|
43
|
+
All API requests must use HTTPS. Unencrypted HTTP requests will be rejected.
|
|
44
|
+
</Callout>
|
|
45
|
+
|
|
46
|
+
<h2 id="base-url">Base URL</h2>
|
|
47
|
+
<CodeBlock
|
|
48
|
+
code={`# Production
|
|
49
|
+
https://api.lumina.dev/v1
|
|
50
|
+
|
|
51
|
+
# Testnet
|
|
52
|
+
https://testnet-api.lumina.dev/v1`}
|
|
53
|
+
language="bash"
|
|
54
|
+
title="Base URLs"
|
|
55
|
+
/>
|
|
56
|
+
|
|
57
|
+
<h2 id="authentication">Authentication</h2>
|
|
58
|
+
<p>
|
|
59
|
+
Lumina uses API key-based authentication. Include your API key in the Authorization header:
|
|
60
|
+
</p>
|
|
61
|
+
|
|
62
|
+
<CodeBlock
|
|
63
|
+
code={`Authorization: Bearer YOUR_SECRET_KEY`}
|
|
64
|
+
language="bash"
|
|
65
|
+
title="Authorization Header"
|
|
66
|
+
/>
|
|
67
|
+
|
|
68
|
+
<h3>Example Request</h3>
|
|
69
|
+
<CodeBlock
|
|
70
|
+
code={`curl -X GET https://api.lumina.dev/v1/wallets \\
|
|
71
|
+
-H "Authorization: Bearer sk_live_abc123def456..." \\
|
|
72
|
+
-H "Content-Type: application/json"`}
|
|
73
|
+
language="bash"
|
|
74
|
+
title="cURL Example"
|
|
75
|
+
/>
|
|
76
|
+
|
|
77
|
+
<h3>API Key Types</h3>
|
|
78
|
+
<CodeBlock
|
|
79
|
+
code={`// Public Key (pk_*)
|
|
80
|
+
// - Use on client-side
|
|
81
|
+
// - Limited permissions
|
|
82
|
+
// - Safe to expose in frontend code
|
|
83
|
+
|
|
84
|
+
// Secret Key (sk_*)
|
|
85
|
+
// - Use on server-side only
|
|
86
|
+
// - Full permissions
|
|
87
|
+
// - Never expose in frontend code`}
|
|
88
|
+
language="text"
|
|
89
|
+
title="Key Types"
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
<h2 id="requests">Making Requests</h2>
|
|
93
|
+
|
|
94
|
+
<h3>JavaScript/TypeScript</h3>
|
|
95
|
+
<CodeBlock
|
|
96
|
+
code={`const response = await fetch('https://api.lumina.dev/v1/wallets', {
|
|
97
|
+
method: 'GET',
|
|
98
|
+
headers: {
|
|
99
|
+
'Authorization': \`Bearer \${process.env.LUMINA_SECRET_KEY}\`,
|
|
100
|
+
'Content-Type': 'application/json',
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const data = await response.json()`}
|
|
105
|
+
language="typescript"
|
|
106
|
+
title="Fetch API"
|
|
107
|
+
/>
|
|
108
|
+
|
|
109
|
+
<h3>Python</h3>
|
|
110
|
+
<CodeBlock
|
|
111
|
+
code={`import requests
|
|
112
|
+
|
|
113
|
+
headers = {
|
|
114
|
+
'Authorization': f'Bearer {secret_key}',
|
|
115
|
+
'Content-Type': 'application/json',
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
response = requests.get(
|
|
119
|
+
'https://api.lumina.dev/v1/wallets',
|
|
120
|
+
headers=headers
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
data = response.json()`}
|
|
124
|
+
language="python"
|
|
125
|
+
title="Python Example"
|
|
126
|
+
/>
|
|
127
|
+
|
|
128
|
+
<h3>cURL</h3>
|
|
129
|
+
<CodeBlock
|
|
130
|
+
code={`curl -X GET https://api.lumina.dev/v1/wallets \\
|
|
131
|
+
-H "Authorization: Bearer sk_live_abc123..." \\
|
|
132
|
+
-H "Content-Type: application/json"`}
|
|
133
|
+
language="bash"
|
|
134
|
+
title="cURL Example"
|
|
135
|
+
/>
|
|
136
|
+
|
|
137
|
+
<h2 id="response-format">Response Format</h2>
|
|
138
|
+
<p>
|
|
139
|
+
All API responses follow a consistent JSON format:
|
|
140
|
+
</p>
|
|
141
|
+
|
|
142
|
+
<CodeBlock
|
|
143
|
+
code={`{
|
|
144
|
+
"success": true,
|
|
145
|
+
"data": {
|
|
146
|
+
"id": "wallet_abc123",
|
|
147
|
+
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f42e0d",
|
|
148
|
+
"balance": "2.5",
|
|
149
|
+
"network": "ethereum"
|
|
150
|
+
},
|
|
151
|
+
"timestamp": "2024-01-15T10:30:00Z"
|
|
152
|
+
}`}
|
|
153
|
+
language="json"
|
|
154
|
+
title="Success Response"
|
|
155
|
+
/>
|
|
156
|
+
|
|
157
|
+
<h3>Error Responses</h3>
|
|
158
|
+
<CodeBlock
|
|
159
|
+
code={`{
|
|
160
|
+
"success": false,
|
|
161
|
+
"error": {
|
|
162
|
+
"code": "AUTHENTICATION_FAILED",
|
|
163
|
+
"message": "Invalid API key",
|
|
164
|
+
"details": {
|
|
165
|
+
"provided_key": "sk_test_invalid..."
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"timestamp": "2024-01-15T10:30:00Z"
|
|
169
|
+
}`}
|
|
170
|
+
language="json"
|
|
171
|
+
title="Error Response"
|
|
172
|
+
/>
|
|
173
|
+
|
|
174
|
+
<h2 id="headers">Headers</h2>
|
|
175
|
+
|
|
176
|
+
<p>
|
|
177
|
+
Required and optional headers for API requests:
|
|
178
|
+
</p>
|
|
179
|
+
|
|
180
|
+
<CodeBlock
|
|
181
|
+
code={`// Required
|
|
182
|
+
Authorization: Bearer YOUR_SECRET_KEY
|
|
183
|
+
Content-Type: application/json
|
|
184
|
+
|
|
185
|
+
// Optional
|
|
186
|
+
X-Idempotency-Key: unique-request-id
|
|
187
|
+
X-Request-Timeout: 30000
|
|
188
|
+
X-Webhook-Secret: your-webhook-secret`}
|
|
189
|
+
language="text"
|
|
190
|
+
title="Request Headers"
|
|
191
|
+
/>
|
|
192
|
+
|
|
193
|
+
<h3>Idempotency</h3>
|
|
194
|
+
<p>
|
|
195
|
+
For critical operations (transfers, swaps), use an idempotency key to ensure the request is only processed once:
|
|
196
|
+
</p>
|
|
197
|
+
|
|
198
|
+
<CodeBlock
|
|
199
|
+
code={`curl -X POST https://api.lumina.dev/v1/transactions \\
|
|
200
|
+
-H "Authorization: Bearer sk_live_abc123..." \\
|
|
201
|
+
-H "Content-Type: application/json" \\
|
|
202
|
+
-H "X-Idempotency-Key: txn_12345_attempt_1" \\
|
|
203
|
+
-d '{
|
|
204
|
+
"to": "0x...",
|
|
205
|
+
"amount": "1.0",
|
|
206
|
+
"token": "ETH"
|
|
207
|
+
}'`}
|
|
208
|
+
language="bash"
|
|
209
|
+
title="Idempotency Example"
|
|
210
|
+
/>
|
|
211
|
+
|
|
212
|
+
<h2 id="rate-limits">Rate Limits</h2>
|
|
213
|
+
|
|
214
|
+
<p>
|
|
215
|
+
API rate limits are enforced per API key and vary by plan:
|
|
216
|
+
</p>
|
|
217
|
+
|
|
218
|
+
<CodeBlock
|
|
219
|
+
code={`Free Plan:
|
|
220
|
+
- 100 requests per minute
|
|
221
|
+
- 10,000 requests per day
|
|
222
|
+
|
|
223
|
+
Pro Plan:
|
|
224
|
+
- 500 requests per minute
|
|
225
|
+
- 100,000 requests per day
|
|
226
|
+
|
|
227
|
+
Enterprise:
|
|
228
|
+
- Custom limits
|
|
229
|
+
- Contact support`}
|
|
230
|
+
language="text"
|
|
231
|
+
title="Rate Limits by Plan"
|
|
232
|
+
/>
|
|
233
|
+
|
|
234
|
+
<h3>Rate Limit Headers</h3>
|
|
235
|
+
<CodeBlock
|
|
236
|
+
code={`// Response headers include:
|
|
237
|
+
X-RateLimit-Limit: 100 // Maximum requests per minute
|
|
238
|
+
X-RateLimit-Remaining: 95 // Remaining requests
|
|
239
|
+
X-RateLimit-Reset: 1705318200 // Unix timestamp when limit resets
|
|
240
|
+
|
|
241
|
+
// Example
|
|
242
|
+
curl -i https://api.lumina.dev/v1/wallets \\
|
|
243
|
+
-H "Authorization: Bearer sk_live_abc123..."
|
|
244
|
+
|
|
245
|
+
// Response headers:
|
|
246
|
+
// X-RateLimit-Limit: 100
|
|
247
|
+
// X-RateLimit-Remaining: 99
|
|
248
|
+
// X-RateLimit-Reset: 1705318200`}
|
|
249
|
+
language="bash"
|
|
250
|
+
title="Rate Limit Headers"
|
|
251
|
+
/>
|
|
252
|
+
|
|
253
|
+
<Callout type="warning">
|
|
254
|
+
When you hit the rate limit (429 Too Many Requests), wait until the X-RateLimit-Reset timestamp before making additional requests.
|
|
255
|
+
</Callout>
|
|
256
|
+
|
|
257
|
+
<h3>Rate Limit Best Practices</h3>
|
|
258
|
+
<CodeBlock
|
|
259
|
+
code={`// Implement exponential backoff
|
|
260
|
+
async function apiCall(url, options, attempt = 1) {
|
|
261
|
+
try {
|
|
262
|
+
const response = await fetch(url, options)
|
|
263
|
+
|
|
264
|
+
if (response.status === 429) {
|
|
265
|
+
const resetTime = parseInt(
|
|
266
|
+
response.headers.get('X-RateLimit-Reset')
|
|
267
|
+
) * 1000
|
|
268
|
+
const waitTime = resetTime - Date.now()
|
|
269
|
+
|
|
270
|
+
console.log(\`Rate limited. Waiting \${waitTime}ms\`)
|
|
271
|
+
await new Promise(resolve => setTimeout(resolve, waitTime))
|
|
272
|
+
|
|
273
|
+
return apiCall(url, options, attempt + 1)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return response.json()
|
|
277
|
+
} catch (error) {
|
|
278
|
+
if (attempt < 3) {
|
|
279
|
+
const delay = Math.pow(2, attempt) * 1000
|
|
280
|
+
await new Promise(resolve => setTimeout(resolve, delay))
|
|
281
|
+
return apiCall(url, options, attempt + 1)
|
|
282
|
+
}
|
|
283
|
+
throw error
|
|
284
|
+
}
|
|
285
|
+
}`}
|
|
286
|
+
language="typescript"
|
|
287
|
+
title="Exponential Backoff"
|
|
288
|
+
/>
|
|
289
|
+
</div>
|
|
290
|
+
|
|
291
|
+
<div className="flex justify-between mt-12 pt-8 border-t border-white/10">
|
|
292
|
+
<a href="/docs/sdk/transaction-confirm" className="text-emerald-400 hover:text-emerald-300">
|
|
293
|
+
← Transaction Confirm
|
|
294
|
+
</a>
|
|
295
|
+
<a href="/docs/api/endpoints" className="text-emerald-400 hover:text-emerald-300">
|
|
296
|
+
Endpoints →
|
|
297
|
+
</a>
|
|
298
|
+
</div>
|
|
299
|
+
</main>
|
|
300
|
+
|
|
301
|
+
<aside className="hidden lg:block w-64 flex-shrink-0">
|
|
302
|
+
<TableOfContents headings={headings} />
|
|
303
|
+
</aside>
|
|
304
|
+
</div>
|
|
305
|
+
)
|
|
306
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { Breadcrumb } from '@/components/docs/breadcrumb'
|
|
2
|
+
import { CodeBlock } from '@/components/docs/code-block'
|
|
3
|
+
import { Callout } from '@/components/docs/callout'
|
|
4
|
+
|
|
5
|
+
export const metadata = {
|
|
6
|
+
title: 'Basic Setup Example - Lumina Examples',
|
|
7
|
+
description: 'Complete example of setting up Lumina in a Next.js app.',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function BasicSetupPage() {
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
<Breadcrumb />
|
|
14
|
+
|
|
15
|
+
<div className="space-y-8">
|
|
16
|
+
<div className="space-y-4">
|
|
17
|
+
<h1 className="text-4xl font-bold text-white">Basic Setup Example</h1>
|
|
18
|
+
<p className="text-lg text-foreground/80">
|
|
19
|
+
A complete, minimal Next.js application with Lumina authentication and wallet display.
|
|
20
|
+
</p>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div className="space-y-4">
|
|
24
|
+
<h2 className="text-2xl font-bold">Project Structure</h2>
|
|
25
|
+
<CodeBlock
|
|
26
|
+
code={`my-app/
|
|
27
|
+
├── app/
|
|
28
|
+
│ ├── layout.tsx
|
|
29
|
+
│ ├── page.tsx
|
|
30
|
+
│ ├── login/
|
|
31
|
+
│ │ └── page.tsx
|
|
32
|
+
│ └── dashboard/
|
|
33
|
+
│ └── page.tsx
|
|
34
|
+
├── .env.local
|
|
35
|
+
├── package.json
|
|
36
|
+
└── tsconfig.json`}
|
|
37
|
+
language="bash"
|
|
38
|
+
/>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div className="space-y-4">
|
|
42
|
+
<h2 className="text-2xl font-bold">1. Root Layout</h2>
|
|
43
|
+
<CodeBlock
|
|
44
|
+
code={`import { LuminaProvider } from '@lumina/sdk'
|
|
45
|
+
import './globals.css'
|
|
46
|
+
|
|
47
|
+
export default function RootLayout({
|
|
48
|
+
children,
|
|
49
|
+
}: {
|
|
50
|
+
children: React.ReactNode
|
|
51
|
+
}) {
|
|
52
|
+
return (
|
|
53
|
+
<html>
|
|
54
|
+
<body>
|
|
55
|
+
<LuminaProvider
|
|
56
|
+
apiKey={process.env.NEXT_PUBLIC_LUMINA_API_KEY!}
|
|
57
|
+
network={
|
|
58
|
+
process.env.NODE_ENV === 'production'
|
|
59
|
+
? 'mainnet'
|
|
60
|
+
: 'testnet'
|
|
61
|
+
}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
</LuminaProvider>
|
|
65
|
+
</body>
|
|
66
|
+
</html>
|
|
67
|
+
)
|
|
68
|
+
}`}
|
|
69
|
+
language="tsx"
|
|
70
|
+
title="app/layout.tsx"
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div className="space-y-4">
|
|
75
|
+
<h2 className="text-2xl font-bold">2. Home Page</h2>
|
|
76
|
+
<CodeBlock
|
|
77
|
+
code={`'use client'
|
|
78
|
+
|
|
79
|
+
import Link from 'next/link'
|
|
80
|
+
import { useLumina } from '@lumina/sdk'
|
|
81
|
+
|
|
82
|
+
export default function Home() {
|
|
83
|
+
const { isConnected } = useLumina()
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<main className="flex items-center justify-center min-h-screen">
|
|
87
|
+
<div className="text-center space-y-4">
|
|
88
|
+
<h1 className="text-4xl font-bold">Welcome to Lumina</h1>
|
|
89
|
+
<p className="text-lg text-gray-600">
|
|
90
|
+
Secure Web3 Wallet Infrastructure
|
|
91
|
+
</p>
|
|
92
|
+
|
|
93
|
+
{!isConnected ? (
|
|
94
|
+
<Link
|
|
95
|
+
href="/login"
|
|
96
|
+
className="px-6 py-3 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700"
|
|
97
|
+
>
|
|
98
|
+
Get Started
|
|
99
|
+
</Link>
|
|
100
|
+
) : (
|
|
101
|
+
<Link
|
|
102
|
+
href="/dashboard"
|
|
103
|
+
className="px-6 py-3 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700"
|
|
104
|
+
>
|
|
105
|
+
Go to Dashboard
|
|
106
|
+
</Link>
|
|
107
|
+
)}
|
|
108
|
+
</div>
|
|
109
|
+
</main>
|
|
110
|
+
)
|
|
111
|
+
}`}
|
|
112
|
+
language="tsx"
|
|
113
|
+
title="app/page.tsx"
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div className="space-y-4">
|
|
118
|
+
<h2 className="text-2xl font-bold">3. Login Page</h2>
|
|
119
|
+
<CodeBlock
|
|
120
|
+
code={`'use client'
|
|
121
|
+
|
|
122
|
+
import { useRouter } from 'next/navigation'
|
|
123
|
+
import { WalletLogin } from '@lumina/sdk'
|
|
124
|
+
|
|
125
|
+
export default function LoginPage() {
|
|
126
|
+
const router = useRouter()
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<main className="flex items-center justify-center min-h-screen bg-gray-100">
|
|
130
|
+
<div className="w-full max-w-md">
|
|
131
|
+
<WalletLogin
|
|
132
|
+
onSuccess={() => {
|
|
133
|
+
router.push('/dashboard')
|
|
134
|
+
}}
|
|
135
|
+
authMethods={['email', 'passkey']}
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
138
|
+
</main>
|
|
139
|
+
)
|
|
140
|
+
}`}
|
|
141
|
+
language="tsx"
|
|
142
|
+
title="app/login/page.tsx"
|
|
143
|
+
/>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<div className="space-y-4">
|
|
147
|
+
<h2 className="text-2xl font-bold">4. Dashboard Page</h2>
|
|
148
|
+
<CodeBlock
|
|
149
|
+
code={`'use client'
|
|
150
|
+
|
|
151
|
+
import { useRouter } from 'next/navigation'
|
|
152
|
+
import { useLumina, WalletDisplay } from '@lumina/sdk'
|
|
153
|
+
|
|
154
|
+
export default function DashboardPage() {
|
|
155
|
+
const router = useRouter()
|
|
156
|
+
const { user, isConnected, logout } = useLumina()
|
|
157
|
+
|
|
158
|
+
if (!isConnected) {
|
|
159
|
+
router.push('/login')
|
|
160
|
+
return null
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const handleLogout = () => {
|
|
164
|
+
logout()
|
|
165
|
+
router.push('/')
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
<main className="min-h-screen bg-gray-50 p-8">
|
|
170
|
+
<div className="max-w-4xl mx-auto">
|
|
171
|
+
<div className="flex justify-between items-center mb-8">
|
|
172
|
+
<h1 className="text-3xl font-bold">Dashboard</h1>
|
|
173
|
+
<button
|
|
174
|
+
onClick={handleLogout}
|
|
175
|
+
className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700"
|
|
176
|
+
>
|
|
177
|
+
Logout
|
|
178
|
+
</button>
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
|
+
<div className="bg-white rounded-lg shadow p-6">
|
|
182
|
+
<h2 className="text-xl font-semibold mb-4">Account Info</h2>
|
|
183
|
+
<p className="text-gray-600 mb-4">Email: {user?.email}</p>
|
|
184
|
+
|
|
185
|
+
<WalletDisplay
|
|
186
|
+
address={user?.walletAddress!}
|
|
187
|
+
balance={user?.balance!}
|
|
188
|
+
network="ethereum"
|
|
189
|
+
/>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
</main>
|
|
193
|
+
)
|
|
194
|
+
}`}
|
|
195
|
+
language="tsx"
|
|
196
|
+
title="app/dashboard/page.tsx"
|
|
197
|
+
/>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
<div className="space-y-4">
|
|
201
|
+
<h2 className="text-2xl font-bold">5. Environment Variables</h2>
|
|
202
|
+
<CodeBlock
|
|
203
|
+
code={`NEXT_PUBLIC_LUMINA_API_KEY=pk_test_xxxxx
|
|
204
|
+
LUMINA_SECRET_KEY=sk_test_xxxxx
|
|
205
|
+
NEXT_PUBLIC_LUMINA_NETWORK=testnet`}
|
|
206
|
+
language="env"
|
|
207
|
+
title=".env.local"
|
|
208
|
+
/>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<div className="space-y-4">
|
|
212
|
+
<h2 className="text-2xl font-bold">6. Package Dependencies</h2>
|
|
213
|
+
<CodeBlock
|
|
214
|
+
code={`{
|
|
215
|
+
"dependencies": {
|
|
216
|
+
"next": "^14.0.0",
|
|
217
|
+
"react": "^18.0.0",
|
|
218
|
+
"react-dom": "^18.0.0",
|
|
219
|
+
"@lumina/sdk": "^1.0.0"
|
|
220
|
+
},
|
|
221
|
+
"devDependencies": {
|
|
222
|
+
"@types/node": "^20.0.0",
|
|
223
|
+
"@types/react": "^18.0.0",
|
|
224
|
+
"typescript": "^5.0.0"
|
|
225
|
+
}
|
|
226
|
+
}`}
|
|
227
|
+
language="json"
|
|
228
|
+
title="package.json (dependencies)"
|
|
229
|
+
/>
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
<Callout type="success" title="Ready to Run">
|
|
233
|
+
This is a complete, working example. Just update the API key and run <code className="bg-black/40 px-2 py-1 rounded text-xs">npm run dev</code> to start!
|
|
234
|
+
</Callout>
|
|
235
|
+
|
|
236
|
+
<div className="space-y-4">
|
|
237
|
+
<h2 className="text-2xl font-bold">Next Steps</h2>
|
|
238
|
+
<ul className="space-y-2 text-foreground/80 text-sm">
|
|
239
|
+
<li className="flex gap-3">
|
|
240
|
+
<span className="text-emerald-400">▸</span>
|
|
241
|
+
<a href="/docs/guides/security" className="text-emerald-400 hover:underline">Add security features</a> - Implement best practices
|
|
242
|
+
</li>
|
|
243
|
+
<li className="flex gap-3">
|
|
244
|
+
<span className="text-emerald-400">▸</span>
|
|
245
|
+
<a href="/docs/examples/send-transaction" className="text-emerald-400 hover:underline">Add transactions</a> - Enable sending funds
|
|
246
|
+
</li>
|
|
247
|
+
<li className="flex gap-3">
|
|
248
|
+
<span className="text-emerald-400">▸</span>
|
|
249
|
+
<a href="/docs/guides/nextjs" className="text-emerald-400 hover:underline">Advanced setup</a> - Learn more features
|
|
250
|
+
</li>
|
|
251
|
+
</ul>
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
</>
|
|
255
|
+
)
|
|
256
|
+
}
|