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.
- package/dist/index.js +154 -0
- package/package.json +39 -0
- package/templates/expo/.env +1 -0
- package/templates/expo/.env.example +3 -0
- package/templates/expo/_gitignore +5 -0
- package/templates/expo/app/(tabs)/_layout.tsx +24 -0
- package/templates/expo/app/(tabs)/index.tsx +79 -0
- package/templates/expo/app/_layout.tsx +24 -0
- package/templates/expo/app.json +36 -0
- package/templates/expo/package.json +35 -0
- package/templates/expo/tsconfig.json +8 -0
- package/templates/expo-js/.env +1 -0
- package/templates/expo-js/.env.example +3 -0
- package/templates/expo-js/_gitignore +5 -0
- package/templates/expo-js/app/(tabs)/_layout.jsx +24 -0
- package/templates/expo-js/app/(tabs)/index.jsx +81 -0
- package/templates/expo-js/app/_layout.jsx +24 -0
- package/templates/expo-js/app.json +33 -0
- package/templates/expo-js/babel.config.js +6 -0
- package/templates/expo-js/jsconfig.json +12 -0
- package/templates/expo-js/package.json +33 -0
- package/templates/nextjs/.env.example +11 -0
- package/templates/nextjs/.env.local +4 -0
- package/templates/nextjs/_gitignore +6 -0
- package/templates/nextjs/app/globals.css +30 -0
- package/templates/nextjs/app/layout.tsx +29 -0
- package/templates/nextjs/app/page.tsx +168 -0
- package/templates/nextjs/components/ui/Badge.tsx +32 -0
- package/templates/nextjs/components/ui/Button.tsx +43 -0
- package/templates/nextjs/components/ui/Card.tsx +15 -0
- package/templates/nextjs/components/ui/Skeleton.tsx +7 -0
- package/templates/nextjs/components/ui/StatCard.tsx +24 -0
- package/templates/nextjs/lib/awarizon.ts +8 -0
- package/templates/nextjs/lib/utils.ts +3 -0
- package/templates/nextjs/next.config.ts +7 -0
- package/templates/nextjs/package.json +29 -0
- package/templates/nextjs/postcss.config.js +6 -0
- package/templates/nextjs/tailwind.config.ts +19 -0
- package/templates/nextjs/tsconfig.json +21 -0
- package/templates/nextjs-js/.env.example +11 -0
- package/templates/nextjs-js/.env.local +4 -0
- package/templates/nextjs-js/_gitignore +5 -0
- package/templates/nextjs-js/app/globals.css +30 -0
- package/templates/nextjs-js/app/layout.jsx +29 -0
- package/templates/nextjs-js/app/page.jsx +141 -0
- package/templates/nextjs-js/components/ui/Badge.jsx +24 -0
- package/templates/nextjs-js/components/ui/Button.jsx +25 -0
- package/templates/nextjs-js/components/ui/Card.jsx +9 -0
- package/templates/nextjs-js/components/ui/Skeleton.jsx +7 -0
- package/templates/nextjs-js/components/ui/StatCard.jsx +16 -0
- package/templates/nextjs-js/jsconfig.json +21 -0
- package/templates/nextjs-js/lib/awarizon.js +7 -0
- package/templates/nextjs-js/lib/utils.js +3 -0
- package/templates/nextjs-js/next.config.js +6 -0
- package/templates/nextjs-js/package.json +25 -0
- package/templates/nextjs-js/postcss.config.js +6 -0
- package/templates/nextjs-js/tailwind.config.js +16 -0
- package/templates/react/.env +1 -0
- package/templates/react/.env.example +7 -0
- package/templates/react/_gitignore +3 -0
- package/templates/react/index.html +12 -0
- package/templates/react/package.json +28 -0
- package/templates/react/postcss.config.js +6 -0
- package/templates/react/src/App.tsx +166 -0
- package/templates/react/src/components/ui/Badge.tsx +32 -0
- package/templates/react/src/components/ui/Button.tsx +43 -0
- package/templates/react/src/components/ui/Card.tsx +15 -0
- package/templates/react/src/components/ui/Skeleton.tsx +7 -0
- package/templates/react/src/components/ui/StatCard.tsx +24 -0
- package/templates/react/src/index.css +30 -0
- package/templates/react/src/lib/utils.ts +3 -0
- package/templates/react/src/main.tsx +22 -0
- package/templates/react/tailwind.config.js +15 -0
- package/templates/react/tsconfig.app.json +20 -0
- package/templates/react/tsconfig.json +7 -0
- package/templates/react/tsconfig.node.json +15 -0
- package/templates/react/vite.config.ts +6 -0
- package/templates/react-js/.env +1 -0
- package/templates/react-js/.env.example +7 -0
- package/templates/react-js/_gitignore +3 -0
- package/templates/react-js/index.html +12 -0
- package/templates/react-js/jsconfig.json +14 -0
- package/templates/react-js/package.json +25 -0
- package/templates/react-js/postcss.config.js +6 -0
- package/templates/react-js/src/App.jsx +139 -0
- package/templates/react-js/src/components/ui/Badge.jsx +24 -0
- package/templates/react-js/src/components/ui/Button.jsx +25 -0
- package/templates/react-js/src/components/ui/Card.jsx +9 -0
- package/templates/react-js/src/components/ui/Skeleton.jsx +7 -0
- package/templates/react-js/src/components/ui/StatCard.jsx +16 -0
- package/templates/react-js/src/index.css +30 -0
- package/templates/react-js/src/lib/utils.js +3 -0
- package/templates/react-js/src/main.jsx +22 -0
- package/templates/react-js/tailwind.config.js +15 -0
- 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,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,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,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,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,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
|
+
}
|