@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,185 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { Card } from '@/components/ui/card'
|
|
4
|
+
import { Button } from '@/components/ui/button'
|
|
5
|
+
import { Code, Copy, ExternalLink, CheckCircle } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
export default function IntegrationPage() {
|
|
8
|
+
return (
|
|
9
|
+
<div className="space-y-8">
|
|
10
|
+
{/* Header */}
|
|
11
|
+
<div>
|
|
12
|
+
<h1 className="text-4xl font-bold mb-2">Integration</h1>
|
|
13
|
+
<p className="text-foreground/60">Quick start guides for integrating Lumina into your application</p>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
{/* SDK Installation */}
|
|
17
|
+
<Card className="glassmorphism-dark p-6 border-border">
|
|
18
|
+
<h2 className="text-2xl font-semibold mb-4">Get Started with Lumina SDK</h2>
|
|
19
|
+
|
|
20
|
+
<div className="space-y-6">
|
|
21
|
+
<div>
|
|
22
|
+
<h3 className="text-lg font-semibold mb-3">1. Install SDK</h3>
|
|
23
|
+
<div className="bg-white/5 p-4 rounded-lg font-mono text-sm border border-border/50">
|
|
24
|
+
<div className="flex justify-between items-center">
|
|
25
|
+
<code>npm install @lumina/sdk</code>
|
|
26
|
+
<button className="p-2 hover:bg-white/10 rounded">
|
|
27
|
+
<Copy size={16} />
|
|
28
|
+
</button>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div>
|
|
34
|
+
<h3 className="text-lg font-semibold mb-3">2. Initialize Provider</h3>
|
|
35
|
+
<div className="bg-white/5 p-4 rounded-lg font-mono text-sm border border-border/50 overflow-x-auto">
|
|
36
|
+
<pre>{`import { LuminaProvider } from '@lumina/sdk'
|
|
37
|
+
|
|
38
|
+
export default function App() {
|
|
39
|
+
return (
|
|
40
|
+
<LuminaProvider apiKey="lumina_prod_...">
|
|
41
|
+
<YourApp />
|
|
42
|
+
</LuminaProvider>
|
|
43
|
+
)
|
|
44
|
+
}`}</pre>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div>
|
|
49
|
+
<h3 className="text-lg font-semibold mb-3">3. Create Wallet</h3>
|
|
50
|
+
<div className="bg-white/5 p-4 rounded-lg font-mono text-sm border border-border/50 overflow-x-auto">
|
|
51
|
+
<pre>{`import { useWallet } from '@lumina/sdk'
|
|
52
|
+
|
|
53
|
+
export function MyComponent() {
|
|
54
|
+
const { createWallet } = useWallet()
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<button onClick={() => createWallet()}>
|
|
58
|
+
Create Wallet
|
|
59
|
+
</button>
|
|
60
|
+
)
|
|
61
|
+
}`}</pre>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div className="mt-6 flex gap-3">
|
|
67
|
+
<Button className="bg-emerald-600 hover:bg-emerald-700 gap-2">
|
|
68
|
+
<Code size={18} />
|
|
69
|
+
View Full Docs
|
|
70
|
+
</Button>
|
|
71
|
+
<Button variant="outline" className="gap-2">
|
|
72
|
+
<ExternalLink size={18} />
|
|
73
|
+
GitHub Repository
|
|
74
|
+
</Button>
|
|
75
|
+
</div>
|
|
76
|
+
</Card>
|
|
77
|
+
|
|
78
|
+
{/* SDK Examples */}
|
|
79
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
80
|
+
{[
|
|
81
|
+
{
|
|
82
|
+
title: 'React',
|
|
83
|
+
description: 'Modern React hooks and components',
|
|
84
|
+
status: 'Recommended',
|
|
85
|
+
icon: '⚛️',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
title: 'Next.js',
|
|
89
|
+
description: 'Full-stack integration with server components',
|
|
90
|
+
status: 'Recommended',
|
|
91
|
+
icon: '▲',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
title: 'Vue.js',
|
|
95
|
+
description: 'Vue composables and components',
|
|
96
|
+
status: 'Available',
|
|
97
|
+
icon: '✓',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
title: 'Svelte',
|
|
101
|
+
description: 'Svelte stores and components',
|
|
102
|
+
status: 'Available',
|
|
103
|
+
icon: '◆',
|
|
104
|
+
},
|
|
105
|
+
].map((sdk, index) => (
|
|
106
|
+
<Card key={index} className="glassmorphism-dark p-6 border-border">
|
|
107
|
+
<div className="flex items-start justify-between mb-4">
|
|
108
|
+
<div>
|
|
109
|
+
<h3 className="text-lg font-semibold">{sdk.title}</h3>
|
|
110
|
+
<p className="text-sm text-foreground/60 mt-1">{sdk.description}</p>
|
|
111
|
+
</div>
|
|
112
|
+
<span className="text-3xl">{sdk.icon}</span>
|
|
113
|
+
</div>
|
|
114
|
+
<div className="flex gap-2">
|
|
115
|
+
<Button size="sm" className="flex-1">Learn More</Button>
|
|
116
|
+
<Button size="sm" variant="outline">View Example</Button>
|
|
117
|
+
</div>
|
|
118
|
+
</Card>
|
|
119
|
+
))}
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
{/* Network Support */}
|
|
123
|
+
<Card className="glassmorphism-dark p-6 border-border">
|
|
124
|
+
<h2 className="text-xl font-semibold mb-6">Supported Networks</h2>
|
|
125
|
+
|
|
126
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
127
|
+
{[
|
|
128
|
+
{ name: 'Ethereum', mainnet: true, testnet: true },
|
|
129
|
+
{ name: 'Polygon', mainnet: true, testnet: true },
|
|
130
|
+
{ name: 'Solana', mainnet: true, testnet: true },
|
|
131
|
+
{ name: 'Arbitrum', mainnet: true, testnet: true },
|
|
132
|
+
{ name: 'Optimism', mainnet: true, testnet: true },
|
|
133
|
+
{ name: 'Base', mainnet: true, testnet: true },
|
|
134
|
+
].map((network, index) => (
|
|
135
|
+
<div key={index} className="flex items-center justify-between p-4 bg-white/5 rounded-lg border border-border/50">
|
|
136
|
+
<span className="font-medium">{network.name}</span>
|
|
137
|
+
<div className="flex gap-3 text-sm">
|
|
138
|
+
{network.mainnet && <span className="text-emerald-500 flex items-center gap-1"><CheckCircle size={14} /> Mainnet</span>}
|
|
139
|
+
{network.testnet && <span className="text-blue-500 flex items-center gap-1"><CheckCircle size={14} /> Testnet</span>}
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
))}
|
|
143
|
+
</div>
|
|
144
|
+
</Card>
|
|
145
|
+
|
|
146
|
+
{/* Authentication Methods */}
|
|
147
|
+
<Card className="glassmorphism-dark p-6 border-border">
|
|
148
|
+
<h2 className="text-xl font-semibold mb-4">Authentication Methods</h2>
|
|
149
|
+
|
|
150
|
+
<div className="space-y-4">
|
|
151
|
+
{[
|
|
152
|
+
{
|
|
153
|
+
name: 'Passkeys',
|
|
154
|
+
description: 'Biometric and passkey authentication',
|
|
155
|
+
supported: true,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'Social Login',
|
|
159
|
+
description: 'Google, GitHub, Discord authentication',
|
|
160
|
+
supported: true,
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'Email/Password',
|
|
164
|
+
description: 'Traditional email and password auth',
|
|
165
|
+
supported: true,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'Web3 Wallet',
|
|
169
|
+
description: 'MetaMask, WalletConnect integration',
|
|
170
|
+
supported: true,
|
|
171
|
+
},
|
|
172
|
+
].map((method, index) => (
|
|
173
|
+
<div key={index} className="flex items-center justify-between p-4 bg-white/5 rounded-lg border border-border/50">
|
|
174
|
+
<div>
|
|
175
|
+
<p className="font-medium">{method.name}</p>
|
|
176
|
+
<p className="text-sm text-foreground/60">{method.description}</p>
|
|
177
|
+
</div>
|
|
178
|
+
{method.supported && <CheckCircle className="text-emerald-500" size={24} />}
|
|
179
|
+
</div>
|
|
180
|
+
))}
|
|
181
|
+
</div>
|
|
182
|
+
</Card>
|
|
183
|
+
</div>
|
|
184
|
+
)
|
|
185
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DashboardSidebar } from '@/components/dashboard-sidebar'
|
|
2
|
+
|
|
3
|
+
export default function DashboardLayout({
|
|
4
|
+
children,
|
|
5
|
+
}: {
|
|
6
|
+
children: React.ReactNode
|
|
7
|
+
}) {
|
|
8
|
+
return (
|
|
9
|
+
<div className="flex h-screen bg-background">
|
|
10
|
+
<DashboardSidebar />
|
|
11
|
+
<main className="flex-1 overflow-auto md:ml-0 pt-16 md:pt-0">
|
|
12
|
+
<div className="p-4 md:p-8">
|
|
13
|
+
{children}
|
|
14
|
+
</div>
|
|
15
|
+
</main>
|
|
16
|
+
</div>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { BarChart3, Users, Activity, Zap, Droplets, Loader2, ExternalLink } from 'lucide-react'
|
|
4
|
+
import { Card } from '@/components/ui/card'
|
|
5
|
+
import { useState, useEffect } from 'react'
|
|
6
|
+
import { apiClient } from '@/lib/api'
|
|
7
|
+
|
|
8
|
+
interface DeveloperStats {
|
|
9
|
+
total_wallets: number
|
|
10
|
+
total_accounts: number
|
|
11
|
+
total_ops: number
|
|
12
|
+
total_gas_sponsored_wei: number
|
|
13
|
+
ops_this_month: number
|
|
14
|
+
monthly_limit: number | null
|
|
15
|
+
plan: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface RecentWallet {
|
|
19
|
+
id: string
|
|
20
|
+
signer_address: string
|
|
21
|
+
oauth_provider: string
|
|
22
|
+
created_at: string
|
|
23
|
+
account_count: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default function DashboardPage() {
|
|
27
|
+
const [stats, setStats] = useState<DeveloperStats | null>(null)
|
|
28
|
+
const [recentWallets, setRecentWallets] = useState<RecentWallet[]>([])
|
|
29
|
+
const [isLoading, setIsLoading] = useState(true)
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const fetchDashboardData = async () => {
|
|
33
|
+
try {
|
|
34
|
+
setIsLoading(true)
|
|
35
|
+
const [statsData, walletsData] = await Promise.all([
|
|
36
|
+
apiClient.dashboard('/v1/developers/stats'),
|
|
37
|
+
apiClient.dashboard('/v1/wallets?limit=5&offset=0') // Just grab the 5 newest
|
|
38
|
+
])
|
|
39
|
+
|
|
40
|
+
setStats(statsData)
|
|
41
|
+
setRecentWallets(walletsData.wallets || [])
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error('Failed to load dashboard data:', error)
|
|
44
|
+
} finally {
|
|
45
|
+
setIsLoading(false)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fetchDashboardData()
|
|
50
|
+
}, [])
|
|
51
|
+
|
|
52
|
+
const formatWei = (wei: number | undefined) => {
|
|
53
|
+
if (wei === undefined) return '0.0000'
|
|
54
|
+
return (wei / 1e18).toFixed(4)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (isLoading) {
|
|
58
|
+
return (
|
|
59
|
+
<div className="min-h-[60vh] flex items-center justify-center">
|
|
60
|
+
<Loader2 className="w-8 h-8 animate-spin text-emerald-500" />
|
|
61
|
+
</div>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<div className="space-y-8">
|
|
67
|
+
{/* Header */}
|
|
68
|
+
<div>
|
|
69
|
+
<h1 className="text-4xl font-bold mb-2">Dashboard</h1>
|
|
70
|
+
<p className="text-foreground/60">Welcome back to your Lumina workspace</p>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
{/* Stats Grid */}
|
|
74
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
75
|
+
{[
|
|
76
|
+
{
|
|
77
|
+
label: 'Total Wallets',
|
|
78
|
+
value: stats?.total_wallets.toLocaleString() || '0',
|
|
79
|
+
icon: Users,
|
|
80
|
+
color: 'emerald',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
label: 'Smart Accounts',
|
|
84
|
+
value: stats?.total_accounts.toLocaleString() || '0',
|
|
85
|
+
icon: Activity,
|
|
86
|
+
color: 'blue',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
label: 'Total Operations',
|
|
90
|
+
value: stats?.total_ops.toLocaleString() || '0',
|
|
91
|
+
icon: Zap,
|
|
92
|
+
color: 'amber',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
label: 'Gas Sponsored',
|
|
96
|
+
value: `${formatWei(stats?.total_gas_sponsored_wei)} ETH`,
|
|
97
|
+
icon: Droplets,
|
|
98
|
+
color: 'emerald',
|
|
99
|
+
},
|
|
100
|
+
].map((stat, index) => {
|
|
101
|
+
const Icon = stat.icon
|
|
102
|
+
return (
|
|
103
|
+
<Card key={index} className="glassmorphism-dark p-6 border-border">
|
|
104
|
+
<div className="flex items-start justify-between">
|
|
105
|
+
<div>
|
|
106
|
+
<p className="text-sm text-foreground/60 mb-1">{stat.label}</p>
|
|
107
|
+
<p className="text-3xl font-bold">{stat.value}</p>
|
|
108
|
+
</div>
|
|
109
|
+
<div className={`p-3 rounded-lg bg-${stat.color}-600/10`}>
|
|
110
|
+
<Icon className={`text-${stat.color}-500`} size={24} />
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</Card>
|
|
114
|
+
)
|
|
115
|
+
})}
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
{/* Main Charts Area */}
|
|
119
|
+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
120
|
+
{/* Activity Chart (Requires a new time-series endpoint in backend to make dynamic) */}
|
|
121
|
+
<Card className="glassmorphism-dark p-6 border-border lg:col-span-2">
|
|
122
|
+
<div className="mb-6 flex justify-between items-start">
|
|
123
|
+
<div>
|
|
124
|
+
<h2 className="text-xl font-semibold mb-1">Monthly Activity</h2>
|
|
125
|
+
<p className="text-sm text-foreground/60">Wallet creation trends (Demo Data)</p>
|
|
126
|
+
</div>
|
|
127
|
+
<BarChart3 className="text-emerald-500" size={24} />
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<div className="space-y-4">
|
|
131
|
+
{[
|
|
132
|
+
{ month: 'Jan', wallets: 85, pct: '65%' },
|
|
133
|
+
{ month: 'Feb', wallets: 92, pct: '71%' },
|
|
134
|
+
{ month: 'Mar', wallets: 78, pct: '59%' },
|
|
135
|
+
{ month: 'Apr', wallets: 105, pct: '81%' },
|
|
136
|
+
{ month: 'May', wallets: 118, pct: '91%' },
|
|
137
|
+
{ month: 'Jun', wallets: 142, pct: '100%' },
|
|
138
|
+
].map((item, index) => (
|
|
139
|
+
<div key={index} className="flex items-center gap-4">
|
|
140
|
+
<div className="w-12 text-sm font-medium text-foreground/60">{item.month}</div>
|
|
141
|
+
<div className="flex-1">
|
|
142
|
+
<div className="h-8 bg-white/5 rounded-lg overflow-hidden">
|
|
143
|
+
<div
|
|
144
|
+
className="h-full bg-gradient-to-r from-emerald-500 to-emerald-600 transition-all duration-500"
|
|
145
|
+
style={{ width: item.pct }}
|
|
146
|
+
/>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
<div className="text-sm font-medium w-12 text-right">{item.wallets}</div>
|
|
150
|
+
</div>
|
|
151
|
+
))}
|
|
152
|
+
</div>
|
|
153
|
+
</Card>
|
|
154
|
+
|
|
155
|
+
{/* System & Plan Status */}
|
|
156
|
+
<Card className="glassmorphism-dark p-6 border-border flex flex-col">
|
|
157
|
+
<div>
|
|
158
|
+
<h2 className="text-xl font-semibold mb-4">Current Plan</h2>
|
|
159
|
+
<div className="p-4 bg-emerald-600/10 border border-emerald-600/20 rounded-lg mb-6 text-center">
|
|
160
|
+
<p className="text-sm text-foreground/60 uppercase tracking-wider mb-1">Tier</p>
|
|
161
|
+
<p className="text-2xl font-bold capitalize text-emerald-400">{stats?.plan || 'Free'}</p>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<div className="border-t border-border pt-6 mt-auto">
|
|
166
|
+
<h3 className="text-sm font-semibold mb-3 flex items-center gap-2">
|
|
167
|
+
<div className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse"></div>
|
|
168
|
+
System Health
|
|
169
|
+
</h3>
|
|
170
|
+
<div className="space-y-2">
|
|
171
|
+
<div className="flex justify-between text-sm">
|
|
172
|
+
<span className="text-foreground/60">Paymaster Status</span>
|
|
173
|
+
<span className="font-medium text-emerald-500">Operational</span>
|
|
174
|
+
</div>
|
|
175
|
+
<div className="flex justify-between text-sm">
|
|
176
|
+
<span className="text-foreground/60">Bundler Relay</span>
|
|
177
|
+
<span className="font-medium text-emerald-500">Operational</span>
|
|
178
|
+
</div>
|
|
179
|
+
<div className="flex justify-between text-sm">
|
|
180
|
+
<span className="text-foreground/60">Operations Limit</span>
|
|
181
|
+
<span className="font-medium">
|
|
182
|
+
{stats?.ops_this_month} / {stats?.monthly_limit || '∞'}
|
|
183
|
+
</span>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
</Card>
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
{/* Recent Wallets */}
|
|
191
|
+
<Card className="glassmorphism-dark p-6 border-border">
|
|
192
|
+
<div className="mb-6">
|
|
193
|
+
<h2 className="text-xl font-semibold mb-1">Recently Created Wallets</h2>
|
|
194
|
+
<p className="text-sm text-foreground/60">The newest users to join your application</p>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<div className="overflow-x-auto">
|
|
198
|
+
<table className="w-full text-sm">
|
|
199
|
+
<thead>
|
|
200
|
+
<tr className="border-b border-border bg-white/5">
|
|
201
|
+
<th className="text-left py-3 px-4 text-foreground/60 font-medium rounded-tl-lg">Signer Address</th>
|
|
202
|
+
<th className="text-left py-3 px-4 text-foreground/60 font-medium">Auth Provider</th>
|
|
203
|
+
<th className="text-left py-3 px-4 text-foreground/60 font-medium">Smart Accounts</th>
|
|
204
|
+
<th className="text-left py-3 px-4 text-foreground/60 font-medium">Joined Date</th>
|
|
205
|
+
<th className="text-right py-3 px-4 text-foreground/60 font-medium rounded-tr-lg">Action</th>
|
|
206
|
+
</tr>
|
|
207
|
+
</thead>
|
|
208
|
+
<tbody>
|
|
209
|
+
{recentWallets.length === 0 ? (
|
|
210
|
+
<tr>
|
|
211
|
+
<td colSpan={5} className="py-8 text-center text-foreground/60">
|
|
212
|
+
No wallets created yet.
|
|
213
|
+
</td>
|
|
214
|
+
</tr>
|
|
215
|
+
) : (
|
|
216
|
+
recentWallets.map((wallet) => (
|
|
217
|
+
<tr key={wallet.id} className="border-b border-border/50 hover:bg-white/5 transition">
|
|
218
|
+
<td className="py-3 px-4">
|
|
219
|
+
<code className="text-xs font-mono">{wallet.signer_address}</code>
|
|
220
|
+
</td>
|
|
221
|
+
<td className="py-3 px-4 capitalize">
|
|
222
|
+
<span className="px-2 py-1 bg-white/10 rounded-full text-xs">
|
|
223
|
+
{wallet.oauth_provider}
|
|
224
|
+
</span>
|
|
225
|
+
</td>
|
|
226
|
+
<td className="py-3 px-4 font-medium">{wallet.account_count}</td>
|
|
227
|
+
<td className="py-3 px-4 text-foreground/60">
|
|
228
|
+
{new Date(wallet.created_at).toLocaleDateString()}
|
|
229
|
+
</td>
|
|
230
|
+
<td className="py-3 px-4 text-right">
|
|
231
|
+
<button className="text-foreground/60 hover:text-emerald-400 transition" title="View Details">
|
|
232
|
+
<ExternalLink size={16} className="inline-block" />
|
|
233
|
+
</button>
|
|
234
|
+
</td>
|
|
235
|
+
</tr>
|
|
236
|
+
))
|
|
237
|
+
)}
|
|
238
|
+
</tbody>
|
|
239
|
+
</table>
|
|
240
|
+
</div>
|
|
241
|
+
</Card>
|
|
242
|
+
</div>
|
|
243
|
+
)
|
|
244
|
+
}
|