-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpage.tsx
More file actions
233 lines (220 loc) · 11.6 KB
/
page.tsx
File metadata and controls
233 lines (220 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
'use client';
import Link from 'next/link';
import { useThemeClasses } from '@/hooks/useThemeClasses';
export default function Recipe03OverviewPage() {
const theme = useThemeClasses();
return (
<div className={`min-h-screen ${theme.bgPage} overflow-x-hidden`}>
<div className="container mx-auto px-4 py-8 max-w-7xl">
{/* Header */}
<div className="mb-8">
<Link href="/" className={`${theme.textAccent} hover:opacity-80 mb-4 inline-block`}>
← Back to Home
</Link>
<div className="flex items-start gap-3 mb-2">
<span className="text-4xl">💰</span>
<div className="flex-1 min-w-0">
<h1 className={`text-3xl md:text-4xl font-bold ${theme.textPrimary} break-words`}>
Recipe 03: Subscription Service
</h1>
</div>
</div>
<p className={`${theme.textMuted} text-sm md:text-base`}>
Automated recurring payments demonstrating blockchain-native subscriptions with LazorKit
</p>
</div>
{/* The Magic: Sign Once */}
<div className="mb-8">
<div className={`${theme.bgCta} rounded-2xl p-6 md:p-8`}>
<div className="flex items-start gap-4 mb-4">
<span className="text-5xl">✨</span>
<div className="flex-1">
<h2 className={`text-2xl md:text-3xl font-bold ${theme.textPrimary} mb-3`}>
The Magic: Sign Once with Face ID, Never Again
</h2>
<p className={`text-lg ${theme.textSecondary} mb-4`}>
This is what makes blockchain subscriptions incredible:
</p>
<div className={`space-y-3 ${theme.textSecondary}`}>
{[
{ num: '1️⃣', title: 'User subscribes with Face ID (gasless via LazorKit)', desc: 'One Face ID authentication to delegate token spending permission' },
{ num: '2️⃣', title: 'Automatic charges every billing cycle', desc: 'Backend service charges the user automatically - no signatures needed!' },
{ num: '3️⃣', title: 'Cancel anytime (also gasless)', desc: 'One click to cancel, rent gets refunded automatically' }
].map((item, i) => (
<div key={i} className="flex items-start gap-3">
<span className="text-2xl">{item.num}</span>
<div>
<p className={`font-semibold ${theme.textPrimary}`}>{item.title}</p>
<p className={`text-sm ${theme.textMuted}`}>{item.desc}</p>
</div>
</div>
))}
</div>
<div className={`mt-4 p-4 ${theme.statusSuccess} rounded-lg`}>
<p className="font-semibold flex items-center gap-2">
<span>🎯</span>
<span>Just like Netflix or Spotify - but decentralized, transparent, and user-controlled!</span>
</p>
</div>
</div>
</div>
</div>
</div>
<div className="grid lg:grid-cols-2 gap-6 lg:gap-8 mb-8">
{/* What You're Building */}
<div className={`${theme.bgCard} rounded-2xl p-6`}>
<h2 className={`text-2xl font-bold ${theme.textPrimary} mb-4`}>What We're Building</h2>
<p className={`${theme.textSecondary} mb-4 text-sm`}>
An automated subscription billing system demonstrating how blockchain-native recurring payments work with LazorKit integration:
</p>
<ul className={`space-y-3 text-sm md:text-base ${theme.textSecondary}`}>
{[
'Subscribe with minimal friction (gasless flow via LazorKit)',
'Get charged automatically every billing cycle (no user signature needed!)',
'Cancel anytime with rent refunds',
'View subscription history and payment details'
].map((item, i) => (
<li key={i} className="flex items-start gap-3">
<span className="text-purple-500 mt-1 flex-shrink-0">✓</span>
<span>{item}</span>
</li>
))}
</ul>
<div className={`mt-4 p-3 ${theme.bgCardAlt} rounded-lg`}>
<p className="text-xs">
<strong>This is a working proof-of-concept</strong> showcasing a novel integration pattern with LazorKit.
</p>
</div>
</div>
{/* The Core Innovation */}
<div className={`${theme.bgCard} rounded-2xl p-6`}>
<h2 className={`text-2xl font-bold ${theme.textPrimary} mb-4`}>The Core Innovation: Token Delegation</h2>
<p className={`text-sm ${theme.textSecondary} mb-4`}>
The key mechanism enabling automatic recurring payments is Solana's token delegation:
</p>
<div className={`${theme.codeBlock} rounded-lg p-4 mb-4 overflow-x-auto`}>
<pre className="text-xs">
{`// During subscription, user delegates once
const delegateIx = createApproveInstruction(
userTokenAccount,
merchantDelegate,
userWallet,
amountToDelegate
);
// Now merchant can charge automatically
// without requiring signatures! 🎉`}
</pre>
</div>
<p className={`text-xs ${theme.textMuted}`}>
After this one-time approval with Face ID, the merchant can charge the user automatically without requiring signatures for each payment.
</p>
</div>
</div>
{/* LazorKit Integration Benefits */}
<div className="mb-8">
<div className={`${theme.statusSuccess} rounded-2xl p-6`}>
<h2 className={`text-2xl font-bold ${theme.textPrimary} mb-4 flex items-center gap-2`}>
<span>🚀</span> LazorKit Integration Benefits
</h2>
<div className="grid md:grid-cols-2 gap-6">
{[
{ title: '1. Simplified Onboarding', desc: 'User subscribes with Face ID - LazorKit handles the complexity', code: `await signAndSendTransaction({\n instructions: [\n initSubscriptionIx,\n delegateTokensIx\n ],\n});` },
{ title: '2. Gasless User Actions', desc: "LazorKit's paymaster covers gas fees for canceling, updating preferences, and viewing status." },
{ title: '3. Smart Wallet Persistence', desc: "LazorKit's smart wallets maintain consistent addresses across sessions." },
{ title: '4. Developer Experience', desc: 'Simple hooks instead of complex wallet adapter setup.' }
].map((item, i) => (
<div key={i}>
<h3 className={`text-lg font-semibold ${theme.textPrimary} mb-2`}>{item.title}</h3>
<p className={`text-sm ${theme.textSecondary}`}>{item.desc}</p>
</div>
))}
</div>
</div>
</div>
{/* Current Limitations */}
<div className="mb-8">
<div className={`${theme.statusWarning} rounded-2xl p-6`}>
<h2 className={`text-2xl font-bold ${theme.textPrimary} mb-4 flex items-center gap-2`}>
<span>⚠️</span> Current Limitations & Production Roadmap
</h2>
<p className={`text-sm ${theme.textSecondary} mb-4`}>
This is a <strong>proof-of-concept</strong> demonstrating feasibility. For production deployment, several enhancements would be needed.
</p>
<div className="space-y-4">
<div className={`${theme.bgCard} rounded-lg p-4`}>
<h3 className={`text-base font-semibold ${theme.textPrimary} mb-2`}>1. PDA Rent Costs (~0.002 SOL)</h3>
<p className={`text-sm ${theme.textSecondary}`}>Currently required to create subscription accounts. Gets refunded on cancellation.</p>
</div>
<div className={`${theme.bgCard} rounded-lg p-4`}>
<h3 className={`text-base font-semibold ${theme.textPrimary} mb-2`}>2. Backend Charging Fees</h3>
<p className={`text-sm ${theme.textSecondary}`}>The automated charging service pays transaction fees. In production, these could be absorbed as business costs.</p>
</div>
</div>
</div>
</div>
{/* Architecture Overview */}
<div className="mb-8">
<div className={`${theme.bgCard} rounded-2xl p-6`}>
<h2 className={`text-2xl font-bold ${theme.textPrimary} mb-4`}>Architecture Overview</h2>
<div className="grid md:grid-cols-3 gap-4 text-sm">
{[
{ title: 'Frontend (Next.js + LazorKit)', items: ['Users connect via Face ID', 'Subscribe with gasless flow', 'Manage subscriptions easily'], color: 'purple' },
{ title: 'Backend Service', items: ['Scans for due subscriptions', 'Charges using delegated tokens', 'Handles business logic'], color: 'blue' },
{ title: 'Smart Contract (Anchor)', items: ['Validates delegations', 'Processes charges', 'Manages cancellations'], color: 'green' }
].map((section, i) => (
<div key={i} className={`${theme.isLazorkit ? `bg-${section.color}-50 border-${section.color}-200` : `bg-${section.color}-500/10 border-${section.color}-500/30`} border rounded-lg p-4`}>
<h3 className={`font-semibold ${theme.textPrimary} mb-2`}>{section.title}</h3>
<ul className={`${theme.textSecondary} space-y-1 text-xs`}>
{section.items.map((item, j) => <li key={j}>• {item}</li>)}
</ul>
</div>
))}
</div>
</div>
</div>
{/* CTA Buttons */}
<div className="grid md:grid-cols-2 gap-6">
<Link
href="/examples/03-subscription-service/subscribe"
className={`block p-8 ${theme.bgCta} ${theme.bgCardHover} rounded-2xl transition-all group`}
>
<div className="text-4xl mb-4">🚀</div>
<h3 className={`text-2xl font-bold ${theme.textPrimary} mb-2 group-hover:opacity-80 transition-colors`}>
Try the Demo
</h3>
<p className={`${theme.textSecondary} mb-4 text-sm`}>
Subscribe to a plan and experience the full flow. Sign once with Face ID!
</p>
<div className={`${theme.textAccent} font-semibold`}>
Start Subscribing →
</div>
</Link>
<Link
href="/examples/03-subscription-service/dashboard"
className={`block p-8 ${theme.bgCard} ${theme.bgCardHover} rounded-2xl transition-all group`}
>
<div className="text-4xl mb-4">📊</div>
<h3 className={`text-2xl font-bold ${theme.textPrimary} mb-2 group-hover:opacity-80 transition-colors`}>
View Dashboard
</h3>
<p className={`${theme.textSecondary} mb-4 text-sm`}>
Manage your active subscription, view payment history, and see admin controls.
</p>
<div className={`${theme.textAccent} font-semibold`}>
Open Dashboard →
</div>
</Link>
</div>
{/* Navigation */}
<div className="mt-8 flex justify-between items-center">
<Link href="/examples/02-gasless-transfer" className={`${theme.textAccent} hover:opacity-80`}>
← Previous: Recipe 02
</Link>
<Link href="/examples/03-subscription-service/subscribe" className={theme.btnPrimary}>
Try the Demo →
</Link>
</div>
</div>
</div>
);
}