Skip to content

Commit 9467801

Browse files
authored
Merge pull request #141 from tacticalnoot/codex/update-ezwallet-for-clarity-and-user-friendliness
2 parents 7fa522e + f7e4d00 commit 9467801

3 files changed

Lines changed: 29 additions & 24 deletions

File tree

src/experiments/ezwallet/EZWalletApp.svelte

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
import QRCode from 'qrcode';
33
import { userState, ensureWalletConnected } from '../../stores/user.svelte';
44
import { useAuthentication } from '../../hooks/useAuthentication';
5-
import { TIERS, USDC, PLATFORM_PAYMENT_DESTINATION } from './config';
5+
import { TIERS, USDC, KALE, PLATFORM_PAYMENT_DESTINATION } from './config';
66
import { buildIntent, encodeIntent } from './qrPayload';
77
import { generateBulk, toCsv } from './bulk';
88
99
let mode = $state<'receive_request' | 'event_drop'>('receive_request');
10-
let asset = $state<'XLM' | 'USDC'>('XLM');
10+
let asset = $state<'XLM' | 'USDC' | 'KALE'>('XLM');
1111
let amount = $state('');
1212
let event = $state('');
1313
let message = $state('');
@@ -58,10 +58,11 @@
5858
event,
5959
message,
6060
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 }
6566
});
6667
const p = encodeIntent(intent);
6768
link = `${location.origin}/labs/ezwallet/drop?p=${p}`;
@@ -87,10 +88,11 @@
8788
event,
8889
message,
8990
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 }
9496
},
9597
count,
9698
1,
@@ -115,8 +117,8 @@
115117
<header class="glass-panel hero-panel">
116118
<p class="kicker">POWERED BY SMOL • STELLAR NATIVE</p>
117119
<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>
120122
</header>
121123
<div class="wip-banner" role="status" aria-live="polite">
122124
<span class="wip-dot" aria-hidden="true"></span>
@@ -134,31 +136,32 @@
134136
<section class="dashboard-grid">
135137
<article class="glass-panel">
136138
<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>
138140
<div class="label">Asset</div>
139141
<div class="pill-row">
140142
<button class="asset-pill" class:active={asset === 'XLM'} onclick={() => (asset = 'XLM')}>XLM</button>
141143
<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>
142145
</div>
143146
<label>Mode
144147
<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>
147150
</select>
148151
</label>
149152
<label>Amount
150-
<input bind:value={amount} placeholder="Optional" />
153+
<input bind:value={amount} placeholder="Optional (example: 10 or 10.5)" />
151154
</label>
152155
<label>Destination
153-
<input bind:value={destination} placeholder="Optional (G.../C...)" />
156+
<input bind:value={destination} placeholder="Optional wallet (G... or C...)" />
154157
</label>
155158
{#if mode === 'event_drop'}
156159
<label>Event
157160
<input bind:value={event} placeholder="Event name" />
158161
</label>
159162
{/if}
160163
<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)" />
162165
</label>
163166
<div class="action-row">
164167
<button class="holo-button" onclick={makeOne}>Generate QR</button>
@@ -169,7 +172,7 @@
169172

170173
<article class="glass-panel">
171174
<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>
173176
<div class="qr-frame">
174177
{#if qrData}
175178
<img src={qrData} alt="Generated Stellar QR intent" class="qr-image" />
@@ -211,18 +214,18 @@
211214
{#if csv}<button class="soft-button" onclick={downloadCsv}>Export CSV manifest</button>{/if}
212215
</div>
213216
<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>
215218
</article>
216219

217220
<article class="glass-panel pricing-panel">
218-
<h2 class="section-title">04 · Ticket Integrity</h2>
221+
<h2 class="section-title">04 · Upgrade & Trust</h2>
219222
<div class="plan-grid">
220223
<div class="plan-card"><strong>Free</strong><span>Up to {TIERS.FREE.maxBatch}</span></div>
221224
<div class="plan-card popular"><strong>Event Pack</strong><span>{TIERS.EVENT.maxBatch} • {TIERS.EVENT.priceXlm} XLM</span></div>
222225
<div class="plan-card"><strong>Power Pack</strong><span>{TIERS.POWER.maxBatch} • {TIERS.POWER.priceXlm} XLM</span></div>
223226
<div class="plan-card"><strong>Custom / Enterprise</strong><span>Contact for event ops scale</span></div>
224227
</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>
226229
<div class="action-row">
227230
<button class="holo-button" onclick={checkoutSelectedTier} disabled={tier === 'FREE'}>
228231
{#if tier === 'EVENT'}Upgrade · {TIERS.EVENT.priceXlm} XLM{/if}
@@ -233,7 +236,7 @@
233236
<label>Platform destination
234237
<input value={PLATFORM_PAYMENT_DESTINATION} readonly />
235238
</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>
237240
</article>
238241
</section>
239242

src/experiments/ezwallet/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export const PLATFORM_PAYMENT_DESTINATION = 'CBNORBI4DCE7LIC42FWMCIWQRULWAUGF2MH
22
export const PENDING_INTENT_KEY = 'smol:pendingStellarQrIntent';
33

44
export const USDC = { code: 'USDC', issuer: 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN' };
5+
export const KALE = { code: 'KALE', issuer: 'CB23WRDQWGSP6YPMY4UV5C4OW5CBTXKYN3XEATG7KJEZCXMJBYEHOUOV' };
56

67
export const TIERS = {
78
FREE: { name: 'Free', maxBatch: 1 },

src/experiments/ezwallet/qrPayload.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { StellarIntent } from './types';
2-
import { USDC } from './config';
2+
import { USDC, KALE } from './config';
33

44
const RE = { amt: /^\d+(\.\d{1,7})?$/, code: /^[A-Z0-9]{1,12}$/, g: /^G[A-Z2-7]{55}$/, c: /^C[A-Z2-7]{55}$/ };
55
const clean = (v?: string, n = 80) => (v || '').trim().slice(0, n) || undefined;
@@ -12,6 +12,7 @@ export function validateIntent(i: StellarIntent): string[] {
1212
if (i.asset.code === 'XLM' && i.asset.type !== 'native') e.push('XLM must be native');
1313
if (i.asset.code === 'XLM' && i.asset.issuer) e.push('XLM cannot have issuer');
1414
if (i.asset.code === 'USDC' && i.asset.issuer !== USDC.issuer) e.push('USDC issuer mismatch');
15+
if (i.asset.code === 'KALE' && i.asset.issuer !== KALE.issuer) e.push('KALE issuer mismatch');
1516
if (i.asset.code !== 'XLM' && !i.asset.issuer) e.push('Issuer required for non-native');
1617
if (i.amount && !RE.amt.test(i.amount)) e.push('Invalid amount');
1718
if (i.destination && !RE.g.test(i.destination) && !RE.c.test(i.destination)) e.push('Invalid destination');

0 commit comments

Comments
 (0)