create-awarizon-app 1.0.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 (95) hide show
  1. package/dist/index.js +154 -0
  2. package/package.json +39 -0
  3. package/templates/expo/.env +1 -0
  4. package/templates/expo/.env.example +3 -0
  5. package/templates/expo/_gitignore +5 -0
  6. package/templates/expo/app/(tabs)/_layout.tsx +24 -0
  7. package/templates/expo/app/(tabs)/index.tsx +79 -0
  8. package/templates/expo/app/_layout.tsx +24 -0
  9. package/templates/expo/app.json +36 -0
  10. package/templates/expo/package.json +35 -0
  11. package/templates/expo/tsconfig.json +8 -0
  12. package/templates/expo-js/.env +1 -0
  13. package/templates/expo-js/.env.example +3 -0
  14. package/templates/expo-js/_gitignore +5 -0
  15. package/templates/expo-js/app/(tabs)/_layout.jsx +24 -0
  16. package/templates/expo-js/app/(tabs)/index.jsx +81 -0
  17. package/templates/expo-js/app/_layout.jsx +24 -0
  18. package/templates/expo-js/app.json +33 -0
  19. package/templates/expo-js/babel.config.js +6 -0
  20. package/templates/expo-js/jsconfig.json +12 -0
  21. package/templates/expo-js/package.json +33 -0
  22. package/templates/nextjs/.env.example +11 -0
  23. package/templates/nextjs/.env.local +4 -0
  24. package/templates/nextjs/_gitignore +6 -0
  25. package/templates/nextjs/app/globals.css +30 -0
  26. package/templates/nextjs/app/layout.tsx +29 -0
  27. package/templates/nextjs/app/page.tsx +168 -0
  28. package/templates/nextjs/components/ui/Badge.tsx +32 -0
  29. package/templates/nextjs/components/ui/Button.tsx +43 -0
  30. package/templates/nextjs/components/ui/Card.tsx +15 -0
  31. package/templates/nextjs/components/ui/Skeleton.tsx +7 -0
  32. package/templates/nextjs/components/ui/StatCard.tsx +24 -0
  33. package/templates/nextjs/lib/awarizon.ts +8 -0
  34. package/templates/nextjs/lib/utils.ts +3 -0
  35. package/templates/nextjs/next.config.ts +7 -0
  36. package/templates/nextjs/package.json +29 -0
  37. package/templates/nextjs/postcss.config.js +6 -0
  38. package/templates/nextjs/tailwind.config.ts +19 -0
  39. package/templates/nextjs/tsconfig.json +21 -0
  40. package/templates/nextjs-js/.env.example +11 -0
  41. package/templates/nextjs-js/.env.local +4 -0
  42. package/templates/nextjs-js/_gitignore +5 -0
  43. package/templates/nextjs-js/app/globals.css +30 -0
  44. package/templates/nextjs-js/app/layout.jsx +29 -0
  45. package/templates/nextjs-js/app/page.jsx +141 -0
  46. package/templates/nextjs-js/components/ui/Badge.jsx +24 -0
  47. package/templates/nextjs-js/components/ui/Button.jsx +25 -0
  48. package/templates/nextjs-js/components/ui/Card.jsx +9 -0
  49. package/templates/nextjs-js/components/ui/Skeleton.jsx +7 -0
  50. package/templates/nextjs-js/components/ui/StatCard.jsx +16 -0
  51. package/templates/nextjs-js/jsconfig.json +21 -0
  52. package/templates/nextjs-js/lib/awarizon.js +7 -0
  53. package/templates/nextjs-js/lib/utils.js +3 -0
  54. package/templates/nextjs-js/next.config.js +6 -0
  55. package/templates/nextjs-js/package.json +25 -0
  56. package/templates/nextjs-js/postcss.config.js +6 -0
  57. package/templates/nextjs-js/tailwind.config.js +16 -0
  58. package/templates/react/.env +1 -0
  59. package/templates/react/.env.example +7 -0
  60. package/templates/react/_gitignore +3 -0
  61. package/templates/react/index.html +12 -0
  62. package/templates/react/package.json +28 -0
  63. package/templates/react/postcss.config.js +6 -0
  64. package/templates/react/src/App.tsx +166 -0
  65. package/templates/react/src/components/ui/Badge.tsx +32 -0
  66. package/templates/react/src/components/ui/Button.tsx +43 -0
  67. package/templates/react/src/components/ui/Card.tsx +15 -0
  68. package/templates/react/src/components/ui/Skeleton.tsx +7 -0
  69. package/templates/react/src/components/ui/StatCard.tsx +24 -0
  70. package/templates/react/src/index.css +30 -0
  71. package/templates/react/src/lib/utils.ts +3 -0
  72. package/templates/react/src/main.tsx +22 -0
  73. package/templates/react/tailwind.config.js +15 -0
  74. package/templates/react/tsconfig.app.json +20 -0
  75. package/templates/react/tsconfig.json +7 -0
  76. package/templates/react/tsconfig.node.json +15 -0
  77. package/templates/react/vite.config.ts +6 -0
  78. package/templates/react-js/.env +1 -0
  79. package/templates/react-js/.env.example +7 -0
  80. package/templates/react-js/_gitignore +3 -0
  81. package/templates/react-js/index.html +12 -0
  82. package/templates/react-js/jsconfig.json +14 -0
  83. package/templates/react-js/package.json +25 -0
  84. package/templates/react-js/postcss.config.js +6 -0
  85. package/templates/react-js/src/App.jsx +139 -0
  86. package/templates/react-js/src/components/ui/Badge.jsx +24 -0
  87. package/templates/react-js/src/components/ui/Button.jsx +25 -0
  88. package/templates/react-js/src/components/ui/Card.jsx +9 -0
  89. package/templates/react-js/src/components/ui/Skeleton.jsx +7 -0
  90. package/templates/react-js/src/components/ui/StatCard.jsx +16 -0
  91. package/templates/react-js/src/index.css +30 -0
  92. package/templates/react-js/src/lib/utils.js +3 -0
  93. package/templates/react-js/src/main.jsx +22 -0
  94. package/templates/react-js/tailwind.config.js +15 -0
  95. package/templates/react-js/vite.config.js +6 -0
@@ -0,0 +1,141 @@
1
+ 'use client'
2
+
3
+ import { useReadContract, ConnectButton } from '@awarizon/react'
4
+ import { ERC20_ABI } from '@awarizon/web3'
5
+ import { Badge } from '@/components/ui/Badge'
6
+ import { Button } from '@/components/ui/Button'
7
+ import { Card } from '@/components/ui/Card'
8
+ import { Skeleton } from '@/components/ui/Skeleton'
9
+ import { StatCard } from '@/components/ui/StatCard'
10
+
11
+ const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
12
+
13
+ function DataRow({ label, value, loading }) {
14
+ return (
15
+ <div className="flex items-center justify-between py-3 border-b border-zinc-800/50 last:border-0">
16
+ <code className="text-[11px] text-yellow-400/70 font-mono">{label}</code>
17
+ {loading
18
+ ? <Skeleton className="h-3.5 w-28" />
19
+ : <span className="font-mono text-xs text-zinc-300">{value ?? '—'}</span>}
20
+ </div>
21
+ )
22
+ }
23
+
24
+ export default function Home() {
25
+ const { data: name, isLoading: l1 } = useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: 'name' })
26
+ const { data: symbol, isLoading: l2 } = useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: 'symbol' })
27
+ const { data: decimals, isLoading: l3 } = useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: 'decimals' })
28
+ const { data: totalSupply, isLoading: l4 } = useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: 'totalSupply' })
29
+
30
+ const formatted =
31
+ totalSupply !== undefined && decimals !== undefined
32
+ ? (Number(totalSupply) / 10 ** Number(decimals))
33
+ .toLocaleString(undefined, { maximumFractionDigits: 2 })
34
+ : undefined
35
+
36
+ const synced = !l1 && !l2 && !l3 && !l4
37
+
38
+ return (
39
+ <div className="min-h-screen bg-zinc-950 text-zinc-100">
40
+
41
+ {/* ── Header ─────────────────────────────────────── */}
42
+ <header className="sticky top-0 z-10 border-b border-zinc-800/60 bg-zinc-950/80 backdrop-blur-sm px-6 py-4">
43
+ <div className="max-w-4xl mx-auto flex items-center justify-between">
44
+ <div className="flex items-center gap-2.5">
45
+ <div className="w-5 h-5 rounded-[4px] bg-yellow-400" />
46
+ <span className="font-mono text-[11px] tracking-[0.2em] text-zinc-400 uppercase">
47
+ {{project-name}}
48
+ </span>
49
+ </div>
50
+ <div className="flex items-center gap-3">
51
+ <Badge variant="outline">Base</Badge>
52
+ <Badge variant={synced ? 'success' : 'loading'}>
53
+ {synced ? '● Live' : '○ Loading'}
54
+ </Badge>
55
+ <ConnectButton />
56
+ </div>
57
+ </div>
58
+ </header>
59
+
60
+ <main className="max-w-4xl mx-auto px-6 py-12">
61
+
62
+ {/* ── Hero ───────────────────────────────────────── */}
63
+ <div className="mb-10">
64
+ <Badge variant="outline" className="mb-5">Awarizon Web3 SDK · Next.js</Badge>
65
+ <h1 className="text-4xl font-bold tracking-tight text-white mb-3">{{ProjectName}}</h1>
66
+ <p className="text-zinc-400 text-base max-w-lg leading-relaxed">
67
+ Live on-chain reads from Base — no backend required. Built with{' '}
68
+ <code className="font-mono text-[11px] text-yellow-400/80">@awarizon/react</code>.
69
+ </p>
70
+ </div>
71
+
72
+ {/* ── Data grid ──────────────────────────────────── */}
73
+ <div className="grid md:grid-cols-3 gap-4 mb-4">
74
+
75
+ <Card className="md:col-span-2">
76
+ <div className="flex items-start justify-between mb-4">
77
+ <div>
78
+ <p className="font-mono text-[9px] tracking-widest text-zinc-600 uppercase mb-1.5">
79
+ Contract · Live Read
80
+ </p>
81
+ <code className="font-mono text-xs text-zinc-500">0x8335…2913 · Base</code>
82
+ </div>
83
+ <Badge variant={synced ? 'success' : 'loading'}>
84
+ {synced ? 'Synced' : 'Fetching…'}
85
+ </Badge>
86
+ </div>
87
+ <DataRow label="name()" value={name} loading={l1} />
88
+ <DataRow label="symbol()" value={symbol} loading={l2} />
89
+ <DataRow label="decimals()" value={String(decimals ?? '')} loading={l3} />
90
+ <DataRow label="totalSupply()" value={formatted} loading={l4} />
91
+ </Card>
92
+
93
+ <div className="flex flex-col gap-4">
94
+ <StatCard label="Total Supply" value={formatted} loading={l4} sub="USDC · formatted" className="flex-1" />
95
+ <StatCard label="Token" value={symbol} loading={l2} sub="Base mainnet" className="flex-1" />
96
+ </div>
97
+ </div>
98
+
99
+ {/* ── Network info ─────────────────────────────────── */}
100
+ <div className="grid sm:grid-cols-3 gap-4 mb-4">
101
+ {[
102
+ { label: 'Network', value: 'Base Mainnet' },
103
+ { label: 'Chain ID', value: '8453' },
104
+ { label: 'SDK', value: '@awarizon/react' },
105
+ ].map(({ label, value }) => (
106
+ <div
107
+ key={label}
108
+ className="bg-zinc-900/50 border border-zinc-800/40 rounded-xl px-5 py-4 flex items-center justify-between"
109
+ >
110
+ <span className="font-mono text-[10px] text-zinc-600 uppercase tracking-widest">{label}</span>
111
+ <code className="font-mono text-xs text-zinc-400">{value}</code>
112
+ </div>
113
+ ))}
114
+ </div>
115
+
116
+ {/* ── Next steps ──────────────────────────────────── */}
117
+ <Card>
118
+ <p className="font-mono text-[9px] tracking-widest text-zinc-600 uppercase mb-4">Next Steps</p>
119
+ <ul className="space-y-3 mb-6">
120
+ {[
121
+ ['01', 'Replace USDC_BASE with your contract address'],
122
+ ['02', 'Swap ERC20_ABI for your contract ABI'],
123
+ ['03', 'Change chain="base" in app/layout.jsx to your target network'],
124
+ ['04', 'Use useWriteContract() for transactions'],
125
+ ['05', 'Add walletConnectProjectId to AwarizonProvider for mobile wallet support'],
126
+ ].map(([n, s]) => (
127
+ <li key={n} className="flex items-start gap-3">
128
+ <span className="font-mono text-[10px] text-yellow-400/50 mt-0.5 shrink-0 select-none">{n}</span>
129
+ <span className="text-sm text-zinc-400 leading-relaxed">{s}</span>
130
+ </li>
131
+ ))}
132
+ </ul>
133
+ <div className="flex flex-wrap gap-2">
134
+ <Button href="https://awarizon.com/docs" target="_blank" rel="noreferrer">Read the docs →</Button>
135
+ <Button href="https://awarizon.com/dashboard" target="_blank" rel="noreferrer" variant="secondary">Dashboard</Button>
136
+ </div>
137
+ </Card>
138
+ </main>
139
+ </div>
140
+ )
141
+ }
@@ -0,0 +1,24 @@
1
+ import { cn } from '@/lib/utils'
2
+
3
+ /** @type {Record<string, string>} */
4
+ const variants = {
5
+ default: 'bg-zinc-800 text-zinc-400',
6
+ success: 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20',
7
+ loading: 'bg-yellow-500/10 text-yellow-400 border border-yellow-500/20',
8
+ warning: 'bg-amber-500/10 text-amber-400 border border-amber-500/20',
9
+ outline: 'border border-zinc-700 text-zinc-400',
10
+ }
11
+
12
+ export function Badge({ children, variant = 'default', className }) {
13
+ return (
14
+ <span
15
+ className={cn(
16
+ 'inline-flex items-center font-mono text-[10px] tracking-widest px-2 py-1 rounded-md uppercase',
17
+ variants[variant],
18
+ className,
19
+ )}
20
+ >
21
+ {children}
22
+ </span>
23
+ )
24
+ }
@@ -0,0 +1,25 @@
1
+ import { cn } from '@/lib/utils'
2
+
3
+ /** @type {Record<string, string>} */
4
+ const variants = {
5
+ primary: 'bg-yellow-400 text-black hover:bg-yellow-300 active:bg-yellow-500',
6
+ secondary: 'bg-zinc-800 text-zinc-200 border border-zinc-700 hover:bg-zinc-700 hover:text-white',
7
+ ghost: 'text-zinc-400 hover:text-white',
8
+ }
9
+
10
+ const base = 'inline-flex items-center gap-1.5 font-mono text-[11px] tracking-widest px-4 py-2.5 rounded-lg transition-colors cursor-pointer'
11
+
12
+ export function Button({ variant = 'primary', className, children, href, ...props }) {
13
+ if (href !== undefined) {
14
+ return (
15
+ <a href={href} className={cn(base, variants[variant], className)} {...props}>
16
+ {children}
17
+ </a>
18
+ )
19
+ }
20
+ return (
21
+ <button type="button" className={cn(base, variants[variant], className)} {...props}>
22
+ {children}
23
+ </button>
24
+ )
25
+ }
@@ -0,0 +1,9 @@
1
+ import { cn } from '@/lib/utils'
2
+
3
+ export function Card({ children, className }) {
4
+ return (
5
+ <div className={cn('bg-zinc-900 border border-zinc-800/60 rounded-xl p-5', className)}>
6
+ {children}
7
+ </div>
8
+ )
9
+ }
@@ -0,0 +1,7 @@
1
+ import { cn } from '@/lib/utils'
2
+
3
+ export function Skeleton({ className }) {
4
+ return (
5
+ <div className={cn('animate-pulse rounded-md bg-zinc-800', className)} />
6
+ )
7
+ }
@@ -0,0 +1,16 @@
1
+ import { cn } from '@/lib/utils'
2
+ import { Skeleton } from './Skeleton'
3
+
4
+ export function StatCard({ label, value, sub, loading, className }) {
5
+ return (
6
+ <div className={cn('bg-zinc-900 border border-zinc-800/60 rounded-xl p-5 flex flex-col', className)}>
7
+ <p className="font-mono text-[9px] tracking-widest text-zinc-600 uppercase mb-3">{label}</p>
8
+ {loading
9
+ ? <Skeleton className="h-7 w-3/4" />
10
+ : <p className="font-mono text-xl font-semibold text-white truncate">{value ?? '—'}</p>}
11
+ {sub && (
12
+ <p className="font-mono text-[10px] text-zinc-600 mt-2">{sub}</p>
13
+ )}
14
+ </div>
15
+ )
16
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": false,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "preserve",
15
+ "incremental": true,
16
+ "plugins": [{ "name": "next" }],
17
+ "paths": { "@/*": ["./*"] }
18
+ },
19
+ "include": ["next-env.d.ts", "**/*.js", "**/*.jsx", ".next/types/**/*.ts"],
20
+ "exclude": ["node_modules"]
21
+ }
@@ -0,0 +1,7 @@
1
+ import { AwarizonWeb3 } from '@awarizon/web3'
2
+
3
+ // Server-side SDK instance (Server Components, API routes, server actions)
4
+ export const awz = new AwarizonWeb3({
5
+ chain: 'base',
6
+ apiKey: process.env.AWARIZON_API_KEY,
7
+ })
@@ -0,0 +1,3 @@
1
+ export function cn(...classes) {
2
+ return classes.filter(Boolean).join(' ')
3
+ }
@@ -0,0 +1,6 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: true,
4
+ }
5
+
6
+ module.exports = nextConfig
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "{{project-name}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "next lint"
10
+ },
11
+ "dependencies": {
12
+ "@awarizon/react": "latest",
13
+ "@awarizon/web3": "latest",
14
+ "next": "14.2.5",
15
+ "react": "^18",
16
+ "react-dom": "^18"
17
+ },
18
+ "devDependencies": {
19
+ "eslint": "^8",
20
+ "eslint-config-next": "14.2.5",
21
+ "autoprefixer": "^10.4.19",
22
+ "postcss": "^8.4.38",
23
+ "tailwindcss": "^3.4.4"
24
+ }
25
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
@@ -0,0 +1,16 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ content: [
4
+ './app/**/*.{js,jsx}',
5
+ './components/**/*.{js,jsx}',
6
+ './lib/**/*.{js,jsx}',
7
+ ],
8
+ theme: {
9
+ extend: {
10
+ colors: {
11
+ accent: '#FFE500',
12
+ },
13
+ },
14
+ },
15
+ plugins: [],
16
+ }
@@ -0,0 +1 @@
1
+ VITE_AWARIZON_API_KEY={{API_KEY}}
@@ -0,0 +1,7 @@
1
+ # Get your API key at https://awarizon.com/dashboard/api-keys
2
+ # Vite exposes variables prefixed with VITE_ to the browser
3
+ VITE_AWARIZON_API_KEY={{API_KEY}}
4
+
5
+ # Optional: enable WalletConnect for mobile wallet support (ConnectButton)
6
+ # Get a free project ID at https://cloud.walletconnect.com
7
+ VITE_WALLETCONNECT_PROJECT_ID=
@@ -0,0 +1,3 @@
1
+ .env
2
+ node_modules/
3
+ dist/
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{ProjectName}}</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "{{project-name}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc -b && vite build",
9
+ "preview": "vite preview",
10
+ "lint": "eslint ."
11
+ },
12
+ "dependencies": {
13
+ "@awarizon/react": "latest",
14
+ "@awarizon/web3": "latest",
15
+ "react": "^18.3.1",
16
+ "react-dom": "^18.3.1"
17
+ },
18
+ "devDependencies": {
19
+ "@types/react": "^18.3.1",
20
+ "@types/react-dom": "^18.3.1",
21
+ "@vitejs/plugin-react": "^4.3.1",
22
+ "typescript": "^5.5.3",
23
+ "vite": "^5.4.1",
24
+ "autoprefixer": "^10.4.19",
25
+ "postcss": "^8.4.38",
26
+ "tailwindcss": "^3.4.4"
27
+ }
28
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
@@ -0,0 +1,166 @@
1
+ import { useReadContract, ConnectButton } from '@awarizon/react'
2
+ import { ERC20_ABI } from '@awarizon/web3'
3
+ import { Badge } from './components/ui/Badge'
4
+ import { Button } from './components/ui/Button'
5
+ import { Card } from './components/ui/Card'
6
+ import { Skeleton } from './components/ui/Skeleton'
7
+ import { StatCard } from './components/ui/StatCard'
8
+
9
+ const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
10
+
11
+ function DataRow({ label, value, loading }: { label: string; value?: string; loading: boolean }) {
12
+ return (
13
+ <div className="flex items-center justify-between py-3 border-b border-zinc-800/50 last:border-0">
14
+ <code className="text-[11px] text-yellow-400/70 font-mono">{label}</code>
15
+ {loading
16
+ ? <Skeleton className="h-3.5 w-28" />
17
+ : <span className="font-mono text-xs text-zinc-300">{value ?? '—'}</span>}
18
+ </div>
19
+ )
20
+ }
21
+
22
+ export default function App() {
23
+ const { data: name, isLoading: l1 } = useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: 'name' })
24
+ const { data: symbol, isLoading: l2 } = useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: 'symbol' })
25
+ const { data: decimals, isLoading: l3 } = useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: 'decimals' })
26
+ const { data: totalSupply, isLoading: l4 } = useReadContract({ address: USDC_BASE, abi: ERC20_ABI, method: 'totalSupply' })
27
+
28
+ const formatted =
29
+ totalSupply !== undefined && decimals !== undefined
30
+ ? (Number(totalSupply as bigint) / 10 ** Number(decimals as bigint))
31
+ .toLocaleString(undefined, { maximumFractionDigits: 2 })
32
+ : undefined
33
+
34
+ const synced = !l1 && !l2 && !l3 && !l4
35
+
36
+ return (
37
+ <div className="min-h-screen bg-zinc-950 text-zinc-100">
38
+
39
+ {/* ── Header ─────────────────────────────────────── */}
40
+ <header className="sticky top-0 z-10 border-b border-zinc-800/60 bg-zinc-950/80 backdrop-blur-sm px-6 py-4">
41
+ <div className="max-w-4xl mx-auto flex items-center justify-between">
42
+ <div className="flex items-center gap-2.5">
43
+ <div className="w-5 h-5 rounded-[4px] bg-yellow-400" />
44
+ <span className="font-mono text-[11px] tracking-[0.2em] text-zinc-400 uppercase">
45
+ {{project-name}}
46
+ </span>
47
+ </div>
48
+ <div className="flex items-center gap-3">
49
+ <Badge variant="outline">Base</Badge>
50
+ <Badge variant={synced ? 'success' : 'loading'}>
51
+ {synced ? '● Live' : '○ Loading'}
52
+ </Badge>
53
+ <ConnectButton />
54
+ </div>
55
+ </div>
56
+ </header>
57
+
58
+ <main className="max-w-4xl mx-auto px-6 py-12">
59
+
60
+ {/* ── Hero ───────────────────────────────────────── */}
61
+ <div className="mb-10">
62
+ <Badge variant="outline" className="mb-5">Awarizon Web3 SDK · React + Vite</Badge>
63
+ <h1 className="text-4xl font-bold tracking-tight text-white mb-3">{{ProjectName}}</h1>
64
+ <p className="text-zinc-400 text-base max-w-lg leading-relaxed">
65
+ Live on-chain reads from Base — no backend required. Built with{' '}
66
+ <code className="font-mono text-[11px] text-yellow-400/80">@awarizon/react</code>.
67
+ </p>
68
+ </div>
69
+
70
+ {/* ── Data grid ──────────────────────────────────── */}
71
+ <div className="grid md:grid-cols-3 gap-4 mb-4">
72
+
73
+ {/* Contract reader — spans 2 cols */}
74
+ <Card className="md:col-span-2">
75
+ <div className="flex items-start justify-between mb-4">
76
+ <div>
77
+ <p className="font-mono text-[9px] tracking-widest text-zinc-600 uppercase mb-1.5">
78
+ Contract · Live Read
79
+ </p>
80
+ <code className="font-mono text-xs text-zinc-500">
81
+ 0x8335…2913 · Base
82
+ </code>
83
+ </div>
84
+ <Badge variant={synced ? 'success' : 'loading'}>
85
+ {synced ? 'Synced' : 'Fetching…'}
86
+ </Badge>
87
+ </div>
88
+ <DataRow label="name()" value={name as string} loading={l1} />
89
+ <DataRow label="symbol()" value={symbol as string} loading={l2} />
90
+ <DataRow label="decimals()" value={String(decimals ?? '')} loading={l3} />
91
+ <DataRow label="totalSupply()" value={formatted} loading={l4} />
92
+ </Card>
93
+
94
+ {/* Stat column */}
95
+ <div className="flex flex-col gap-4">
96
+ <StatCard
97
+ label="Total Supply"
98
+ value={formatted}
99
+ loading={l4}
100
+ sub="USDC · formatted"
101
+ className="flex-1"
102
+ />
103
+ <StatCard
104
+ label="Token"
105
+ value={symbol as string}
106
+ loading={l2}
107
+ sub="Base mainnet"
108
+ className="flex-1"
109
+ />
110
+ </div>
111
+ </div>
112
+
113
+ {/* ── Network info ────────────────────────────────── */}
114
+ <div className="grid sm:grid-cols-3 gap-4 mb-4">
115
+ {[
116
+ { label: 'Network', value: 'Base Mainnet' },
117
+ { label: 'Chain ID', value: '8453' },
118
+ { label: 'SDK', value: '@awarizon/react' },
119
+ ].map(({ label, value }) => (
120
+ <div
121
+ key={label}
122
+ className="bg-zinc-900/50 border border-zinc-800/40 rounded-xl px-5 py-4 flex items-center justify-between"
123
+ >
124
+ <span className="font-mono text-[10px] text-zinc-600 uppercase tracking-widest">{label}</span>
125
+ <code className="font-mono text-xs text-zinc-400">{value}</code>
126
+ </div>
127
+ ))}
128
+ </div>
129
+
130
+ {/* ── Next steps ──────────────────────────────────── */}
131
+ <Card>
132
+ <p className="font-mono text-[9px] tracking-widest text-zinc-600 uppercase mb-4">
133
+ Next Steps
134
+ </p>
135
+ <ul className="space-y-3 mb-6">
136
+ {[
137
+ ['01', 'Replace USDC_BASE with your contract address'],
138
+ ['02', 'Swap ERC20_ABI for your contract ABI'],
139
+ ['03', 'Change chain="base" in src/main.tsx to your target network'],
140
+ ['04', 'Use useWriteContract() for send transactions'],
141
+ ['05', 'Add walletConnectProjectId to AwarizonProvider for mobile wallet support'],
142
+ ].map(([n, s]) => (
143
+ <li key={n} className="flex items-start gap-3">
144
+ <span className="font-mono text-[10px] text-yellow-400/50 mt-0.5 shrink-0 select-none">{n}</span>
145
+ <span className="text-sm text-zinc-400 leading-relaxed">{s}</span>
146
+ </li>
147
+ ))}
148
+ </ul>
149
+ <div className="flex flex-wrap gap-2">
150
+ <Button href="https://awarizon.com/docs" target="_blank" rel="noreferrer">
151
+ Read the docs →
152
+ </Button>
153
+ <Button
154
+ href="https://awarizon.com/dashboard"
155
+ target="_blank"
156
+ rel="noreferrer"
157
+ variant="secondary"
158
+ >
159
+ Dashboard
160
+ </Button>
161
+ </div>
162
+ </Card>
163
+ </main>
164
+ </div>
165
+ )
166
+ }
@@ -0,0 +1,32 @@
1
+ import { ReactNode } from 'react'
2
+ import { cn } from '../../lib/utils'
3
+
4
+ type BadgeVariant = 'default' | 'success' | 'loading' | 'warning' | 'outline'
5
+
6
+ interface BadgeProps {
7
+ children: ReactNode
8
+ variant?: BadgeVariant
9
+ className?: string
10
+ }
11
+
12
+ const variants: Record<BadgeVariant, string> = {
13
+ default: 'bg-zinc-800 text-zinc-400',
14
+ success: 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20',
15
+ loading: 'bg-yellow-500/10 text-yellow-400 border border-yellow-500/20',
16
+ warning: 'bg-amber-500/10 text-amber-400 border border-amber-500/20',
17
+ outline: 'border border-zinc-700 text-zinc-400',
18
+ }
19
+
20
+ export function Badge({ children, variant = 'default', className }: BadgeProps) {
21
+ return (
22
+ <span
23
+ className={cn(
24
+ 'inline-flex items-center font-mono text-[10px] tracking-widest px-2 py-1 rounded-md uppercase',
25
+ variants[variant],
26
+ className,
27
+ )}
28
+ >
29
+ {children}
30
+ </span>
31
+ )
32
+ }
@@ -0,0 +1,43 @@
1
+ import { AnchorHTMLAttributes, ButtonHTMLAttributes, ReactNode } from 'react'
2
+ import { cn } from '../../lib/utils'
3
+
4
+ type ButtonVariant = 'primary' | 'secondary' | 'ghost'
5
+
6
+ const variants: Record<ButtonVariant, string> = {
7
+ primary: 'bg-yellow-400 text-black hover:bg-yellow-300 active:bg-yellow-500',
8
+ secondary: 'bg-zinc-800 text-zinc-200 border border-zinc-700 hover:bg-zinc-700 hover:text-white',
9
+ ghost: 'text-zinc-400 hover:text-white',
10
+ }
11
+
12
+ const base = 'inline-flex items-center gap-1.5 font-mono text-[11px] tracking-widest px-4 py-2.5 rounded-lg transition-colors cursor-pointer'
13
+
14
+ interface AsAnchorProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
15
+ href: string
16
+ variant?: ButtonVariant
17
+ children: ReactNode
18
+ }
19
+
20
+ interface AsButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
21
+ href?: never
22
+ variant?: ButtonVariant
23
+ children: ReactNode
24
+ }
25
+
26
+ type ButtonProps = AsAnchorProps | AsButtonProps
27
+
28
+ export function Button({ variant = 'primary', className, children, ...props }: ButtonProps) {
29
+ if ('href' in props && props.href !== undefined) {
30
+ const { href, ...rest } = props as AsAnchorProps
31
+ return (
32
+ <a href={href} className={cn(base, variants[variant], className)} {...rest}>
33
+ {children}
34
+ </a>
35
+ )
36
+ }
37
+ const { ...rest } = props as AsButtonProps
38
+ return (
39
+ <button type="button" className={cn(base, variants[variant], className)} {...rest}>
40
+ {children}
41
+ </button>
42
+ )
43
+ }
@@ -0,0 +1,15 @@
1
+ import { ReactNode } from 'react'
2
+ import { cn } from '../../lib/utils'
3
+
4
+ interface CardProps {
5
+ children: ReactNode
6
+ className?: string
7
+ }
8
+
9
+ export function Card({ children, className }: CardProps) {
10
+ return (
11
+ <div className={cn('bg-zinc-900 border border-zinc-800/60 rounded-xl p-5', className)}>
12
+ {children}
13
+ </div>
14
+ )
15
+ }