@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.
Files changed (152) hide show
  1. package/BUTTON_FIXES.md +59 -0
  2. package/DOCS_INDEX.md +332 -0
  3. package/DOCUMENTATION.md +252 -0
  4. package/DOCUMENTATION_BUILD_SUMMARY.md +376 -0
  5. package/DOCUMENTATION_COMPLETE.md +311 -0
  6. package/FEATURES.md +333 -0
  7. package/Lumina-sdk/src/components/lumina-provider.tsx +46 -0
  8. package/Lumina-sdk/src/components/transaction-confirm.tsx +242 -0
  9. package/Lumina-sdk/src/components/wallet-display.tsx +157 -0
  10. package/Lumina-sdk/src/components/wallet-login.tsx +163 -0
  11. package/Lumina-sdk/src/hooks/use-mobile.ts +19 -0
  12. package/Lumina-sdk/src/hooks/use-toast.ts +191 -0
  13. package/Lumina-sdk/src/index.ts +0 -0
  14. package/Lumina-sdk/src/lib/api.ts +66 -0
  15. package/Lumina-sdk/src/lib/utils.ts +6 -0
  16. package/Lumina-sdk/src/package.json +42 -0
  17. package/Lumina-sdk/src/tsconfig.json +19 -0
  18. package/NEW_FILES_MANIFEST.txt +146 -0
  19. package/README.md +298 -0
  20. package/app/dashboard/analytics/page.tsx +218 -0
  21. package/app/dashboard/api-keys/page.tsx +260 -0
  22. package/app/dashboard/billing/page.tsx +412 -0
  23. package/app/dashboard/integration/page.tsx +185 -0
  24. package/app/dashboard/layout.tsx +18 -0
  25. package/app/dashboard/page.tsx +244 -0
  26. package/app/dashboard/settings/page.tsx +285 -0
  27. package/app/dashboard/users/page.tsx +148 -0
  28. package/app/docs/api/authentication/page.tsx +246 -0
  29. package/app/docs/api/endpoints/page.tsx +397 -0
  30. package/app/docs/api/errors/page.tsx +305 -0
  31. package/app/docs/api/overview/page.tsx +306 -0
  32. package/app/docs/examples/basic-setup/page.tsx +256 -0
  33. package/app/docs/examples/multi-chain/page.tsx +331 -0
  34. package/app/docs/examples/nextjs-full-stack/page.tsx +332 -0
  35. package/app/docs/getting-started/environment-setup/page.tsx +243 -0
  36. package/app/docs/getting-started/installation/page.tsx +187 -0
  37. package/app/docs/getting-started/introduction/page.tsx +178 -0
  38. package/app/docs/getting-started/quick-start/page.tsx +199 -0
  39. package/app/docs/guides/nextjs/page.tsx +358 -0
  40. package/app/docs/guides/react/page.tsx +230 -0
  41. package/app/docs/guides/security/page.tsx +284 -0
  42. package/app/docs/layout.tsx +32 -0
  43. package/app/docs/page.tsx +180 -0
  44. package/app/docs/sdk/lumina-provider/page.tsx +186 -0
  45. package/app/docs/sdk/transaction-confirm/page.tsx +331 -0
  46. package/app/docs/sdk/wallet-display/page.tsx +224 -0
  47. package/app/docs/sdk/wallet-login/page.tsx +207 -0
  48. package/app/docs/troubleshooting/common-issues/page.tsx +301 -0
  49. package/app/docs/troubleshooting/faq/page.tsx +105 -0
  50. package/app/globals.css +125 -0
  51. package/app/invite/[token]/page.tsx +78 -0
  52. package/app/layout.tsx +36 -0
  53. package/app/login/page.tsx +175 -0
  54. package/app/page.tsx +336 -0
  55. package/app/sdk-demo/page.tsx +239 -0
  56. package/components/dashboard-sidebar.tsx +113 -0
  57. package/components/docs/breadcrumb.tsx +51 -0
  58. package/components/docs/callout.tsx +53 -0
  59. package/components/docs/code-block.tsx +77 -0
  60. package/components/docs/docs-sidebar.tsx +214 -0
  61. package/components/docs/table-of-contents.tsx +83 -0
  62. package/components/sdk/lumina-provider.tsx +46 -0
  63. package/components/sdk/transaction-confirm.tsx +242 -0
  64. package/components/sdk/wallet-display.tsx +157 -0
  65. package/components/sdk/wallet-login.tsx +163 -0
  66. package/components/theme-provider.tsx +11 -0
  67. package/components/ui/accordion.tsx +66 -0
  68. package/components/ui/alert-dialog.tsx +157 -0
  69. package/components/ui/alert.tsx +66 -0
  70. package/components/ui/aspect-ratio.tsx +11 -0
  71. package/components/ui/avatar.tsx +53 -0
  72. package/components/ui/badge.tsx +46 -0
  73. package/components/ui/breadcrumb.tsx +109 -0
  74. package/components/ui/button-group.tsx +83 -0
  75. package/components/ui/button.tsx +60 -0
  76. package/components/ui/calendar.tsx +213 -0
  77. package/components/ui/card.tsx +92 -0
  78. package/components/ui/carousel.tsx +241 -0
  79. package/components/ui/chart.tsx +351 -0
  80. package/components/ui/checkbox.tsx +32 -0
  81. package/components/ui/collapsible.tsx +33 -0
  82. package/components/ui/command.tsx +184 -0
  83. package/components/ui/context-menu.tsx +252 -0
  84. package/components/ui/dialog.tsx +143 -0
  85. package/components/ui/drawer.tsx +135 -0
  86. package/components/ui/dropdown-menu.tsx +257 -0
  87. package/components/ui/empty.tsx +104 -0
  88. package/components/ui/field.tsx +244 -0
  89. package/components/ui/form.tsx +167 -0
  90. package/components/ui/hover-card.tsx +44 -0
  91. package/components/ui/input-group.tsx +169 -0
  92. package/components/ui/input-otp.tsx +77 -0
  93. package/components/ui/input.tsx +21 -0
  94. package/components/ui/item.tsx +193 -0
  95. package/components/ui/kbd.tsx +28 -0
  96. package/components/ui/label.tsx +24 -0
  97. package/components/ui/menubar.tsx +276 -0
  98. package/components/ui/navigation-menu.tsx +166 -0
  99. package/components/ui/pagination.tsx +127 -0
  100. package/components/ui/popover.tsx +48 -0
  101. package/components/ui/progress.tsx +31 -0
  102. package/components/ui/radio-group.tsx +45 -0
  103. package/components/ui/resizable.tsx +56 -0
  104. package/components/ui/scroll-area.tsx +58 -0
  105. package/components/ui/select.tsx +185 -0
  106. package/components/ui/separator.tsx +28 -0
  107. package/components/ui/sheet.tsx +139 -0
  108. package/components/ui/sidebar.tsx +726 -0
  109. package/components/ui/skeleton.tsx +13 -0
  110. package/components/ui/slider.tsx +59 -0
  111. package/components/ui/sonner.tsx +25 -0
  112. package/components/ui/spinner.tsx +16 -0
  113. package/components/ui/switch.tsx +29 -0
  114. package/components/ui/table.tsx +116 -0
  115. package/components/ui/tabs.tsx +66 -0
  116. package/components/ui/textarea.tsx +18 -0
  117. package/components/ui/toast.tsx +129 -0
  118. package/components/ui/toaster.tsx +35 -0
  119. package/components/ui/toggle-group.tsx +73 -0
  120. package/components/ui/toggle.tsx +47 -0
  121. package/components/ui/tooltip.tsx +61 -0
  122. package/components/ui/use-mobile.tsx +19 -0
  123. package/components/ui/use-toast.ts +191 -0
  124. package/components.json +21 -0
  125. package/hooks/use-mobile.ts +19 -0
  126. package/hooks/use-toast.ts +191 -0
  127. package/lib/api.ts +66 -0
  128. package/lib/utils.ts +6 -0
  129. package/next-env.d.ts +6 -0
  130. package/next.config.mjs +11 -0
  131. package/package.json +73 -0
  132. package/pnpm-workspace.yaml +5 -0
  133. package/postcss.config.mjs +8 -0
  134. package/public/apple-icon.png +0 -0
  135. package/public/fav.jpeg +0 -0
  136. package/public/fav.png +0 -0
  137. package/public/icon-dark-32x32.png +0 -0
  138. package/public/icon-light-32x32.png +0 -0
  139. package/public/icon.png +0 -0
  140. package/public/icon.svg +26 -0
  141. package/public/logo.jpeg +0 -0
  142. package/public/logo.png +0 -0
  143. package/public/logo2.jpeg +0 -0
  144. package/public/logo2.png +0 -0
  145. package/public/placeholder-logo.png +0 -0
  146. package/public/placeholder-logo.svg +1 -0
  147. package/public/placeholder-user.jpg +0 -0
  148. package/public/placeholder.jpg +0 -0
  149. package/public/placeholder.svg +1 -0
  150. package/styles/globals.css +209 -0
  151. package/tailwind.config.ts +15 -0
  152. package/tsconfig.json +41 -0
@@ -0,0 +1,331 @@
1
+ 'use client'
2
+
3
+ import { Breadcrumb } from '@/components/docs/breadcrumb'
4
+ import { CodeBlock } from '@/components/docs/code-block'
5
+ import { Callout } from '@/components/docs/callout'
6
+
7
+ export default function MultiChainExamplePage() {
8
+ return (
9
+ <div className="flex gap-8 max-w-7xl mx-auto px-4 py-8">
10
+ <main className="flex-1 min-w-0">
11
+ <Breadcrumb
12
+ items={[
13
+ { label: 'Docs', href: '/docs' },
14
+ { label: 'Examples', href: '/docs/examples/basic-setup' },
15
+ { label: 'Multi-Chain' },
16
+ ]}
17
+ />
18
+
19
+ <div className="mt-8 prose prose-invert max-w-none">
20
+ <h1>Multi-Chain Wallet Example</h1>
21
+
22
+ <p className="text-lg text-foreground/80">
23
+ Build a wallet application that supports multiple blockchain networks with Lumina.
24
+ </p>
25
+
26
+ <h2>Supported Networks</h2>
27
+ <CodeBlock
28
+ code={`const networks = {
29
+ ethereum: {
30
+ id: 1,
31
+ name: 'Ethereum',
32
+ rpc: 'https://eth-mainnet.g.alchemy.com/v2/...',
33
+ explorer: 'https://etherscan.io',
34
+ },
35
+ polygon: {
36
+ id: 137,
37
+ name: 'Polygon',
38
+ rpc: 'https://polygon-mainnet.g.alchemy.com/v2/...',
39
+ explorer: 'https://polygonscan.com',
40
+ },
41
+ arbitrum: {
42
+ id: 42161,
43
+ name: 'Arbitrum',
44
+ rpc: 'https://arbitrum-mainnet.g.alchemy.com/v2/...',
45
+ explorer: 'https://arbiscan.io',
46
+ },
47
+ optimism: {
48
+ id: 10,
49
+ name: 'Optimism',
50
+ rpc: 'https://opt-mainnet.g.alchemy.com/v2/...',
51
+ explorer: 'https://optimistic.etherscan.io',
52
+ },
53
+ }`}
54
+ language="typescript"
55
+ title="Supported Networks"
56
+ />
57
+
58
+ <h2>Multi-Chain Provider Setup</h2>
59
+ <CodeBlock
60
+ code={`// app/providers.tsx
61
+ 'use client'
62
+
63
+ import { ReactNode, useState } from 'react'
64
+ import { LuminaProvider } from '@lumina/react'
65
+
66
+ export function Providers({ children }: { children: ReactNode }) {
67
+ const [network, setNetwork] = useState('ethereum')
68
+
69
+ return (
70
+ <LuminaProvider
71
+ publicKey={process.env.NEXT_PUBLIC_LUMINA_PUBLIC_KEY!}
72
+ network={network as any}
73
+ onNetworkChange={setNetwork}
74
+ >
75
+ {children}
76
+ </LuminaProvider>
77
+ )
78
+ }`}
79
+ language="typescript"
80
+ title="Multi-Chain Provider"
81
+ />
82
+
83
+ <h2>Network Selector Component</h2>
84
+ <CodeBlock
85
+ code={`'use client'
86
+
87
+ import { useState } from 'react'
88
+ import { useLumina } from '@lumina/react'
89
+
90
+ const networks = [
91
+ { id: 'ethereum', name: 'Ethereum', icon: '⟠' },
92
+ { id: 'polygon', name: 'Polygon', icon: '🟣' },
93
+ { id: 'arbitrum', name: 'Arbitrum', icon: '🟦' },
94
+ { id: 'optimism', name: 'Optimism', icon: '🔴' },
95
+ ]
96
+
97
+ export function NetworkSelector() {
98
+ const { network, setNetwork } = useLumina()
99
+
100
+ return (
101
+ <div className="flex gap-2">
102
+ {networks.map((net) => (
103
+ <button
104
+ key={net.id}
105
+ onClick={() => setNetwork(net.id)}
106
+ className={
107
+ network === net.id
108
+ ? 'bg-emerald-600 text-white'
109
+ : 'bg-white/10 text-white hover:bg-white/20'
110
+ }
111
+ >
112
+ {net.icon} {net.name}
113
+ </button>
114
+ ))}
115
+ </div>
116
+ )
117
+ }`}
118
+ language="typescript"
119
+ title="Network Selector"
120
+ />
121
+
122
+ <h2>Multi-Wallet Management</h2>
123
+ <CodeBlock
124
+ code={`// app/wallets/page.tsx
125
+ 'use client'
126
+
127
+ import { useState, useEffect } from 'react'
128
+ import { useLumina } from '@lumina/react'
129
+
130
+ interface Wallet {
131
+ id: string
132
+ network: string
133
+ address: string
134
+ balance: string
135
+ }
136
+
137
+ export default function WalletsPage() {
138
+ const { network, user } = useLumina()
139
+ const [wallets, setWallets] = useState<Wallet[]>([])
140
+ const [loading, setLoading] = useState(true)
141
+
142
+ useEffect(() => {
143
+ loadWallets()
144
+ }, [user])
145
+
146
+ async function loadWallets() {
147
+ try {
148
+ const response = await fetch(\`/api/wallets?user_id=\${user.id}\`)
149
+ const data = await response.json()
150
+ setWallets(data.data.wallets)
151
+ } finally {
152
+ setLoading(false)
153
+ }
154
+ }
155
+
156
+ async function createWalletForNetwork(networkId: string) {
157
+ try {
158
+ const response = await fetch('/api/wallets', {
159
+ method: 'POST',
160
+ headers: { 'Content-Type': 'application/json' },
161
+ body: JSON.stringify({
162
+ user_id: user.id,
163
+ network: networkId,
164
+ name: \`\${networkId} Wallet\`,
165
+ }),
166
+ })
167
+ const wallet = await response.json()
168
+ setWallets([...wallets, wallet.data])
169
+ } catch (error) {
170
+ console.error('Failed to create wallet:', error)
171
+ }
172
+ }
173
+
174
+ return (
175
+ <div>
176
+ <h1>My Multi-Chain Wallets</h1>
177
+
178
+ {loading ? (
179
+ <p>Loading wallets...</p>
180
+ ) : (
181
+ <div>
182
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
183
+ {wallets.map((wallet) => (
184
+ <div
185
+ key={wallet.id}
186
+ className="p-4 border border-emerald-600/20 rounded-lg"
187
+ >
188
+ <h3>{wallet.network.toUpperCase()}</h3>
189
+ <p className="font-mono text-sm">{wallet.address}</p>
190
+ <p className="text-lg">Balance: {wallet.balance} ETH</p>
191
+ </div>
192
+ ))}
193
+ </div>
194
+
195
+ <button
196
+ onClick={() => createWalletForNetwork('polygon')}
197
+ className="mt-4 px-4 py-2 bg-emerald-600 text-white rounded"
198
+ >
199
+ Add Polygon Wallet
200
+ </button>
201
+ </div>
202
+ )}
203
+ </div>
204
+ )
205
+ }`}
206
+ language="typescript"
207
+ title="Multi-Wallet Component"
208
+ />
209
+
210
+ <h2>Cross-Chain Transaction</h2>
211
+ <CodeBlock
212
+ code={`// lib/multi-chain.ts
213
+ export async function sendCrossChainTransaction({
214
+ sourceNetwork,
215
+ destinationNetwork,
216
+ walletId,
217
+ recipient,
218
+ amount,
219
+ }: {
220
+ sourceNetwork: string
221
+ destinationNetwork: string
222
+ walletId: string
223
+ recipient: string
224
+ amount: string
225
+ }) {
226
+ // Create transaction on source network
227
+ const txResponse = await fetch('/api/transactions', {
228
+ method: 'POST',
229
+ headers: { 'Content-Type': 'application/json' },
230
+ body: JSON.stringify({
231
+ wallet_id: walletId,
232
+ to: recipient,
233
+ amount,
234
+ token: 'ETH',
235
+ chain_id: sourceNetwork,
236
+ type: 'cross-chain-transfer',
237
+ destination_chain: destinationNetwork,
238
+ }),
239
+ })
240
+
241
+ const transaction = await txResponse.json()
242
+
243
+ return transaction.data
244
+ }
245
+
246
+ // Track cross-chain status
247
+ export async function getCrossChainStatus(transactionId: string) {
248
+ const response = await fetch(\`/api/transactions/\${transactionId}/status\`)
249
+ const data = await response.json()
250
+
251
+ return {
252
+ sourceChainStatus: data.data.source_status, // pending, confirmed
253
+ destinationChainStatus: data.data.dest_status, // pending, completed
254
+ estimatedTime: data.data.estimated_time,
255
+ }
256
+ }`}
257
+ language="typescript"
258
+ title="Cross-Chain Helper"
259
+ />
260
+
261
+ <h2>Gas Price Comparison</h2>
262
+ <CodeBlock
263
+ code={`'use client'
264
+
265
+ import { useEffect, useState } from 'react'
266
+
267
+ export function GasComparison() {
268
+ const [gasPrices, setGasPrices] = useState({})
269
+
270
+ useEffect(() => {
271
+ fetchGasPrices()
272
+ }, [])
273
+
274
+ async function fetchGasPrices() {
275
+ const networks = ['ethereum', 'polygon', 'arbitrum', 'optimism']
276
+ const prices: any = {}
277
+
278
+ for (const network of networks) {
279
+ try {
280
+ const response = await fetch(
281
+ \`/api/networks/\${network}/gas-price\`
282
+ )
283
+ const data = await response.json()
284
+ prices[network] = data.data.gas_price
285
+ } catch (error) {
286
+ console.error(\`Failed to fetch gas price for \${network}\`, error)
287
+ }
288
+ }
289
+
290
+ setGasPrices(prices)
291
+ }
292
+
293
+ return (
294
+ <div className="p-4 bg-white/5 rounded-lg">
295
+ <h3>Gas Prices Comparison</h3>
296
+ <div className="grid grid-cols-2 gap-2">
297
+ {Object.entries(gasPrices).map(([network, price]: any) => (
298
+ <div key={network}>
299
+ <p className="text-sm text-gray-400">{network}</p>
300
+ <p className="text-lg font-bold">{price} Gwei</p>
301
+ </div>
302
+ ))}
303
+ </div>
304
+ </div>
305
+ )
306
+ }`}
307
+ language="typescript"
308
+ title="Gas Price Comparison"
309
+ />
310
+
311
+ <Callout type="info">
312
+ Use bridging services like Across or Stargate for efficient cross-chain transfers. Lumina supports integration with major bridge protocols.
313
+ </Callout>
314
+
315
+ <Callout type="warning">
316
+ Always verify gas prices and estimated transaction times before executing cross-chain transactions. Rates vary significantly between networks.
317
+ </Callout>
318
+ </div>
319
+
320
+ <div className="flex justify-between mt-12 pt-8 border-t border-white/10">
321
+ <a href="/docs/examples/nextjs-full-stack" className="text-emerald-400 hover:text-emerald-300">
322
+ ← Full Stack Example
323
+ </a>
324
+ <a href="/docs/troubleshooting/faq" className="text-emerald-400 hover:text-emerald-300">
325
+ FAQ →
326
+ </a>
327
+ </div>
328
+ </main>
329
+ </div>
330
+ )
331
+ }
@@ -0,0 +1,332 @@
1
+ 'use client'
2
+
3
+ import { Breadcrumb } from '@/components/docs/breadcrumb'
4
+ import { CodeBlock } from '@/components/docs/code-block'
5
+ import { Callout } from '@/components/docs/callout'
6
+
7
+ export default function FullStackExamplePage() {
8
+ return (
9
+ <div className="flex gap-8 max-w-7xl mx-auto px-4 py-8">
10
+ <main className="flex-1 min-w-0">
11
+ <Breadcrumb
12
+ items={[
13
+ { label: 'Docs', href: '/docs' },
14
+ { label: 'Examples', href: '/docs/examples/basic-setup' },
15
+ { label: 'Next.js Full Stack' },
16
+ ]}
17
+ />
18
+
19
+ <div className="mt-8 prose prose-invert max-w-none">
20
+ <h1>Next.js Full Stack Example</h1>
21
+
22
+ <p className="text-lg text-foreground/80">
23
+ Complete full-stack example of a wallet application built with Next.js, including server-side and client-side components.
24
+ </p>
25
+
26
+ <h2>Project Structure</h2>
27
+ <CodeBlock
28
+ code={`my-wallet-app/
29
+ ├── app/
30
+ │ ├── api/
31
+ │ │ └── wallets/
32
+ │ │ ├── route.ts # Create wallet
33
+ │ │ └── [id]/
34
+ │ │ └── route.ts # Get wallet
35
+ │ ├── wallet/
36
+ │ │ └── page.tsx # Wallet page
37
+ │ ├── layout.tsx
38
+ │ └── providers.tsx
39
+ ├── lib/
40
+ │ └── lumina.ts # Lumina API helpers
41
+ ├── .env.local
42
+ └── package.json`}
43
+ language="text"
44
+ title="File Structure"
45
+ />
46
+
47
+ <h2>Environment Setup</h2>
48
+ <CodeBlock
49
+ code={`# .env.local
50
+ NEXT_PUBLIC_LUMINA_PUBLIC_KEY=pk_live_abc123def456...
51
+ LUMINA_SECRET_KEY=sk_live_xyz789uvw012...
52
+ NEXT_PUBLIC_LUMINA_API_URL=https://api.lumina.dev
53
+ NEXT_PUBLIC_LUMINA_NETWORK=ethereum`}
54
+ language="bash"
55
+ title=".env.local"
56
+ />
57
+
58
+ <h2>API Helpers</h2>
59
+ <CodeBlock
60
+ code={`// lib/lumina.ts
61
+ export interface LuminaConfig {
62
+ baseUrl: string
63
+ secretKey: string
64
+ publicKey: string
65
+ }
66
+
67
+ const config: LuminaConfig = {
68
+ baseUrl: process.env.NEXT_PUBLIC_LUMINA_API_URL || '',
69
+ secretKey: process.env.LUMINA_SECRET_KEY || '',
70
+ publicKey: process.env.NEXT_PUBLIC_LUMINA_PUBLIC_KEY || '',
71
+ }
72
+
73
+ export async function createWallet(userId: string) {
74
+ const response = await fetch(\`\${config.baseUrl}/v1/wallets\`, {
75
+ method: 'POST',
76
+ headers: {
77
+ 'Authorization': \`Bearer \${config.secretKey}\`,
78
+ 'Content-Type': 'application/json',
79
+ },
80
+ body: JSON.stringify({ user_id: userId, network: 'ethereum' }),
81
+ })
82
+
83
+ if (!response.ok) {
84
+ const error = await response.json()
85
+ throw new Error(error.error.message)
86
+ }
87
+
88
+ return response.json()
89
+ }
90
+
91
+ export async function getWallet(walletId: string) {
92
+ const response = await fetch(
93
+ \`\${config.baseUrl}/v1/wallets/\${walletId}\`,
94
+ {
95
+ headers: {
96
+ 'Authorization': \`Bearer \${config.secretKey}\`,
97
+ },
98
+ }
99
+ )
100
+
101
+ if (!response.ok) {
102
+ throw new Error('Failed to fetch wallet')
103
+ }
104
+
105
+ return response.json()
106
+ }
107
+
108
+ export async function createTransaction(
109
+ walletId: string,
110
+ to: string,
111
+ amount: string
112
+ ) {
113
+ const response = await fetch(\`\${config.baseUrl}/v1/transactions\`, {
114
+ method: 'POST',
115
+ headers: {
116
+ 'Authorization': \`Bearer \${config.secretKey}\`,
117
+ 'Content-Type': 'application/json',
118
+ },
119
+ body: JSON.stringify({
120
+ wallet_id: walletId,
121
+ to,
122
+ amount,
123
+ token: 'ETH',
124
+ }),
125
+ })
126
+
127
+ if (!response.ok) {
128
+ const error = await response.json()
129
+ throw new Error(error.error.message)
130
+ }
131
+
132
+ return response.json()
133
+ }`}
134
+ language="typescript"
135
+ title="Helper Functions"
136
+ />
137
+
138
+ <h2>Server Components</h2>
139
+
140
+ <h3>Providers Setup</h3>
141
+ <CodeBlock
142
+ code={`// app/providers.tsx
143
+ 'use client'
144
+
145
+ import { ReactNode } from 'react'
146
+ import { LuminaProvider } from '@lumina/react'
147
+
148
+ export function Providers({ children }: { children: ReactNode }) {
149
+ return (
150
+ <LuminaProvider
151
+ publicKey={process.env.NEXT_PUBLIC_LUMINA_PUBLIC_KEY!}
152
+ network={process.env.NEXT_PUBLIC_LUMINA_NETWORK as any}
153
+ >
154
+ {children}
155
+ </LuminaProvider>
156
+ )
157
+ }`}
158
+ language="typescript"
159
+ title="Providers"
160
+ />
161
+
162
+ <h3>Root Layout</h3>
163
+ <CodeBlock
164
+ code={`// app/layout.tsx
165
+ import { Providers } from './providers'
166
+ import './globals.css'
167
+
168
+ export const metadata = {
169
+ title: 'My Wallet',
170
+ description: 'Web3 wallet application',
171
+ }
172
+
173
+ export default function RootLayout({
174
+ children,
175
+ }: {
176
+ children: React.ReactNode
177
+ }) {
178
+ return (
179
+ <html lang="en">
180
+ <body>
181
+ <Providers>{children}</Providers>
182
+ </body>
183
+ </html>
184
+ )
185
+ }`}
186
+ language="typescript"
187
+ title="Layout"
188
+ />
189
+
190
+ <h2>API Routes</h2>
191
+
192
+ <h3>Create Wallet Endpoint</h3>
193
+ <CodeBlock
194
+ code={`// app/api/wallets/route.ts
195
+ import { NextRequest, NextResponse } from 'next/server'
196
+ import { createWallet } from '@/lib/lumina'
197
+
198
+ export async function POST(request: NextRequest) {
199
+ try {
200
+ const { userId } = await request.json()
201
+
202
+ if (!userId) {
203
+ return NextResponse.json(
204
+ { error: 'userId is required' },
205
+ { status: 400 }
206
+ )
207
+ }
208
+
209
+ const wallet = await createWallet(userId)
210
+ return NextResponse.json(wallet)
211
+ } catch (error: any) {
212
+ console.error('Create wallet error:', error)
213
+ return NextResponse.json(
214
+ { error: error.message },
215
+ { status: 500 }
216
+ )
217
+ }
218
+ }`}
219
+ language="typescript"
220
+ title="POST /api/wallets"
221
+ />
222
+
223
+ <h3>Get Wallet Endpoint</h3>
224
+ <CodeBlock
225
+ code={`// app/api/wallets/[id]/route.ts
226
+ import { NextRequest, NextResponse } from 'next/server'
227
+ import { getWallet } from '@/lib/lumina'
228
+
229
+ export async function GET(
230
+ request: NextRequest,
231
+ { params }: { params: { id: string } }
232
+ ) {
233
+ try {
234
+ const wallet = await getWallet(params.id)
235
+ return NextResponse.json(wallet)
236
+ } catch (error: any) {
237
+ return NextResponse.json(
238
+ { error: error.message },
239
+ { status: 500 }
240
+ )
241
+ }
242
+ }`}
243
+ language="typescript"
244
+ title="GET /api/wallets/[id]"
245
+ />
246
+
247
+ <h2>Client Components</h2>
248
+
249
+ <h3>Wallet Page</h3>
250
+ <CodeBlock
251
+ code={`// app/wallet/page.tsx
252
+ 'use client'
253
+
254
+ import { useState, useEffect } from 'react'
255
+ import { WalletDisplay, WalletLogin, TransactionConfirm } from '@lumina/react'
256
+
257
+ export default function WalletPage() {
258
+ const [user, setUser] = useState(null)
259
+ const [wallet, setWallet] = useState(null)
260
+ const [loading, setLoading] = useState(false)
261
+ const [showTransaction, setShowTransaction] = useState(false)
262
+
263
+ const handleLogin = async (userData: any) => {
264
+ setUser(userData)
265
+ setLoading(true)
266
+ try {
267
+ // Create wallet for user
268
+ const response = await fetch('/api/wallets', {
269
+ method: 'POST',
270
+ headers: { 'Content-Type': 'application/json' },
271
+ body: JSON.stringify({ userId: userData.id }),
272
+ })
273
+ const data = await response.json()
274
+ setWallet(data.data)
275
+ } catch (error) {
276
+ console.error('Failed to create wallet:', error)
277
+ } finally {
278
+ setLoading(false)
279
+ }
280
+ }
281
+
282
+ return (
283
+ <main className="max-w-4xl mx-auto p-8">
284
+ {!user ? (
285
+ <WalletLogin onSuccess={handleLogin} />
286
+ ) : (
287
+ <div>
288
+ <h1>Welcome, {user.name}!</h1>
289
+ {wallet && (
290
+ <>
291
+ <WalletDisplay
292
+ address={wallet.address}
293
+ balance={wallet.balance}
294
+ onSend={() => setShowTransaction(true)}
295
+ />
296
+ {showTransaction && (
297
+ <TransactionConfirm
298
+ transactionId="txn_123"
299
+ amount="1.0"
300
+ recipient="0x..."
301
+ onConfirm={() => setShowTransaction(false)}
302
+ onCancel={() => setShowTransaction(false)}
303
+ />
304
+ )}
305
+ </>
306
+ )}
307
+ </div>
308
+ )}
309
+ </main>
310
+ )
311
+ }`}
312
+ language="typescript"
313
+ title="Wallet Page"
314
+ />
315
+
316
+ <Callout type="success">
317
+ This example provides a complete foundation for building a Web3 wallet application with Lumina. Customize it further based on your specific needs.
318
+ </Callout>
319
+ </div>
320
+
321
+ <div className="flex justify-between mt-12 pt-8 border-t border-white/10">
322
+ <a href="/docs/guides/nextjs" className="text-emerald-400 hover:text-emerald-300">
323
+ ← Next.js Guide
324
+ </a>
325
+ <a href="/docs/examples/multi-chain" className="text-emerald-400 hover:text-emerald-300">
326
+ Multi-Chain Example →
327
+ </a>
328
+ </div>
329
+ </main>
330
+ </div>
331
+ )
332
+ }