|
2 | 2 | import QRCode from 'qrcode'; |
3 | 3 | import { userState, ensureWalletConnected } from '../../stores/user.svelte'; |
4 | 4 | import { useAuthentication } from '../../hooks/useAuthentication'; |
5 | | - import { TIERS, USDC, PLATFORM_PAYMENT_DESTINATION } from './config'; |
| 5 | + import { TIERS, USDC, KALE, PLATFORM_PAYMENT_DESTINATION } from './config'; |
6 | 6 | import { buildIntent, encodeIntent } from './qrPayload'; |
7 | 7 | import { generateBulk, toCsv } from './bulk'; |
8 | 8 |
|
9 | 9 | let mode = $state<'receive_request' | 'event_drop'>('receive_request'); |
10 | | - let asset = $state<'XLM' | 'USDC'>('XLM'); |
| 10 | + let asset = $state<'XLM' | 'USDC' | 'KALE'>('XLM'); |
11 | 11 | let amount = $state(''); |
12 | 12 | let event = $state(''); |
13 | 13 | let message = $state(''); |
|
58 | 58 | event, |
59 | 59 | message, |
60 | 60 | destination, |
61 | | - asset: |
62 | | - asset === 'XLM' |
63 | | - ? { type: 'native', code: 'XLM' } |
64 | | - : { type: 'credit_alphanum4', code: 'USDC', issuer: USDC.issuer } |
| 61 | + asset: asset === 'XLM' |
| 62 | + ? { type: 'native', code: 'XLM' } |
| 63 | + : asset === 'USDC' |
| 64 | + ? { type: 'credit_alphanum4', code: 'USDC', issuer: USDC.issuer } |
| 65 | + : { type: 'credit_alphanum4', code: 'KALE', issuer: KALE.issuer } |
65 | 66 | }); |
66 | 67 | const p = encodeIntent(intent); |
67 | 68 | link = `${location.origin}/labs/ezwallet/drop?p=${p}`; |
|
87 | 88 | event, |
88 | 89 | message, |
89 | 90 | destination, |
90 | | - asset: |
91 | | - asset === 'XLM' |
92 | | - ? { type: 'native', code: 'XLM' } |
93 | | - : { type: 'credit_alphanum4', code: 'USDC', issuer: USDC.issuer } |
| 91 | + asset: asset === 'XLM' |
| 92 | + ? { type: 'native', code: 'XLM' } |
| 93 | + : asset === 'USDC' |
| 94 | + ? { type: 'credit_alphanum4', code: 'USDC', issuer: USDC.issuer } |
| 95 | + : { type: 'credit_alphanum4', code: 'KALE', issuer: KALE.issuer } |
94 | 96 | }, |
95 | 97 | count, |
96 | 98 | 1, |
|
115 | 117 | <header class="glass-panel hero-panel"> |
116 | 118 | <p class="kicker">POWERED BY SMOL • STELLAR NATIVE</p> |
117 | 119 | <h1 class="holo-text">EZWallet</h1> |
118 | | - <p class="hero-tag">Scan. Claim. Receive Value.</p> |
119 | | - <p class="hero-sub">Create claim tickets where the QR payload carries transfer intent metadata (XLM/USDC), so recipients review and redeem value flows instead of being prompted for immediate payment.</p> |
| 120 | + <p class="hero-tag">Create, Share, and Redeem in One Place.</p> |
| 121 | + <p class="hero-sub">Make instantly redeemable tickets for XLM, USDC, or KALE. People can scan, review, and redeem from the same simple flow.</p> |
120 | 122 | </header> |
121 | 123 | <div class="wip-banner" role="status" aria-live="polite"> |
122 | 124 | <span class="wip-dot" aria-hidden="true"></span> |
|
134 | 136 | <section class="dashboard-grid"> |
135 | 137 | <article class="glass-panel"> |
136 | 138 | <h2 class="section-title">01 · Build Your Claim Ticket</h2> |
137 | | - <p class="muted">Quick start: choose asset, add an optional amount, and generate.</p> |
| 139 | + <p class="muted">Step 1: pick a coin, add optional details, then generate a ticket.</p> |
138 | 140 | <div class="label">Asset</div> |
139 | 141 | <div class="pill-row"> |
140 | 142 | <button class="asset-pill" class:active={asset === 'XLM'} onclick={() => (asset = 'XLM')}>XLM</button> |
141 | 143 | <button class="asset-pill" class:active={asset === 'USDC'} onclick={() => (asset = 'USDC')}>USDC</button> |
| 144 | + <button class="asset-pill" class:active={asset === 'KALE'} onclick={() => (asset = 'KALE')}>KALE</button> |
142 | 145 | </div> |
143 | 146 | <label>Mode |
144 | 147 | <select bind:value={mode}> |
145 | | - <option value="receive_request">Direct claim ticket</option> |
146 | | - <option value="event_drop">Event ticket drop</option> |
| 148 | + <option value="receive_request">Direct claim ticket (one person)</option> |
| 149 | + <option value="event_drop">Event ticket drop (multiple people)</option> |
147 | 150 | </select> |
148 | 151 | </label> |
149 | 152 | <label>Amount |
150 | | - <input bind:value={amount} placeholder="Optional" /> |
| 153 | + <input bind:value={amount} placeholder="Optional (example: 10 or 10.5)" /> |
151 | 154 | </label> |
152 | 155 | <label>Destination |
153 | | - <input bind:value={destination} placeholder="Optional (G.../C...)" /> |
| 156 | + <input bind:value={destination} placeholder="Optional wallet (G... or C...)" /> |
154 | 157 | </label> |
155 | 158 | {#if mode === 'event_drop'} |
156 | 159 | <label>Event |
157 | 160 | <input bind:value={event} placeholder="Event name" /> |
158 | 161 | </label> |
159 | 162 | {/if} |
160 | 163 | <label>Message |
161 | | - <input bind:value={message} placeholder="Optional note for recipient" /> |
| 164 | + <input bind:value={message} placeholder="Optional note (what this giveaway is for)" /> |
162 | 165 | </label> |
163 | 166 | <div class="action-row"> |
164 | 167 | <button class="holo-button" onclick={makeOne}>Generate QR</button> |
|
169 | 172 |
|
170 | 173 | <article class="glass-panel"> |
171 | 174 | <h2 class="section-title">02 · Share & Review</h2> |
172 | | - <p class="safety">Review before signing. The QR carries claim intent metadata and never auto-sends funds.</p> |
| 175 | + <p class="safety">Step 2: share your QR or link. Every person reviews details before redeeming. No auto-send.</p> |
173 | 176 | <div class="qr-frame"> |
174 | 177 | {#if qrData} |
175 | 178 | <img src={qrData} alt="Generated Stellar QR intent" class="qr-image" /> |
|
211 | 214 | {#if csv}<button class="soft-button" onclick={downloadCsv}>Export CSV manifest</button>{/if} |
212 | 215 | </div> |
213 | 216 | <p class="muted">Rows generated: {batchRows.length}</p> |
214 | | - <p class="muted">Free plan creates one ticket at a time. Batch sizes above 1 require Event or Power.</p> |
| 217 | + <p class="muted">Best for giveaways: generate many tickets at once, then print or distribute digitally.</p> |
215 | 218 | </article> |
216 | 219 |
|
217 | 220 | <article class="glass-panel pricing-panel"> |
218 | | - <h2 class="section-title">04 · Ticket Integrity</h2> |
| 221 | + <h2 class="section-title">04 · Upgrade & Trust</h2> |
219 | 222 | <div class="plan-grid"> |
220 | 223 | <div class="plan-card"><strong>Free</strong><span>Up to {TIERS.FREE.maxBatch}</span></div> |
221 | 224 | <div class="plan-card popular"><strong>Event Pack</strong><span>{TIERS.EVENT.maxBatch} • {TIERS.EVENT.priceXlm} XLM</span></div> |
222 | 225 | <div class="plan-card"><strong>Power Pack</strong><span>{TIERS.POWER.maxBatch} • {TIERS.POWER.priceXlm} XLM</span></div> |
223 | 226 | <div class="plan-card"><strong>Custom / Enterprise</strong><span>Contact for event ops scale</span></div> |
224 | 227 | </div> |
225 | | - <p class="review">One-tap checkout flow: choose your plan, open wallet checkout, and continue generating. No manual ‘I paid’ confirmation step.</p> |
| 228 | + <p class="review">Step 4: if needed, upgrade your batch limit. Checkout opens in wallet and you can continue right away.</p> |
226 | 229 | <div class="action-row"> |
227 | 230 | <button class="holo-button" onclick={checkoutSelectedTier} disabled={tier === 'FREE'}> |
228 | 231 | {#if tier === 'EVENT'}Upgrade · {TIERS.EVENT.priceXlm} XLM{/if} |
|
233 | 236 | <label>Platform destination |
234 | 237 | <input value={PLATFORM_PAYMENT_DESTINATION} readonly /> |
235 | 238 | </label> |
236 | | - <p class="muted">Each scan opens a claim review screen first. Redemption always requires explicit signer approval.</p> |
| 239 | + <p class="muted">Anyone can open a ticket safely, review details, and redeem from the same EZWallet flow with signer approval.</p> |
237 | 240 | </article> |
238 | 241 | </section> |
239 | 242 |
|
|
0 commit comments