diff --git a/src/experiments/ezwallet/EZWalletApp.svelte b/src/experiments/ezwallet/EZWalletApp.svelte
index 1329f6f9..9e0898ee 100644
--- a/src/experiments/ezwallet/EZWalletApp.svelte
+++ b/src/experiments/ezwallet/EZWalletApp.svelte
@@ -2,12 +2,12 @@
import QRCode from 'qrcode';
import { userState, ensureWalletConnected } from '../../stores/user.svelte';
import { useAuthentication } from '../../hooks/useAuthentication';
- import { TIERS, USDC, PLATFORM_PAYMENT_DESTINATION } from './config';
+ import { TIERS, USDC, KALE, PLATFORM_PAYMENT_DESTINATION } from './config';
import { buildIntent, encodeIntent } from './qrPayload';
import { generateBulk, toCsv } from './bulk';
let mode = $state<'receive_request' | 'event_drop'>('receive_request');
- let asset = $state<'XLM' | 'USDC'>('XLM');
+ let asset = $state<'XLM' | 'USDC' | 'KALE'>('XLM');
let amount = $state('');
let event = $state('');
let message = $state('');
@@ -58,10 +58,11 @@
event,
message,
destination,
- asset:
- asset === 'XLM'
- ? { type: 'native', code: 'XLM' }
- : { type: 'credit_alphanum4', code: 'USDC', issuer: USDC.issuer }
+ asset: asset === 'XLM'
+ ? { type: 'native', code: 'XLM' }
+ : asset === 'USDC'
+ ? { type: 'credit_alphanum4', code: 'USDC', issuer: USDC.issuer }
+ : { type: 'credit_alphanum4', code: 'KALE', issuer: KALE.issuer }
});
const p = encodeIntent(intent);
link = `${location.origin}/labs/ezwallet/drop?p=${p}`;
@@ -87,10 +88,11 @@
event,
message,
destination,
- asset:
- asset === 'XLM'
- ? { type: 'native', code: 'XLM' }
- : { type: 'credit_alphanum4', code: 'USDC', issuer: USDC.issuer }
+ asset: asset === 'XLM'
+ ? { type: 'native', code: 'XLM' }
+ : asset === 'USDC'
+ ? { type: 'credit_alphanum4', code: 'USDC', issuer: USDC.issuer }
+ : { type: 'credit_alphanum4', code: 'KALE', issuer: KALE.issuer }
},
count,
1,
@@ -115,8 +117,8 @@
POWERED BY SMOL • STELLAR NATIVE
EZWallet
- Scan. Claim. Receive Value.
- 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.
+ Create, Share, and Redeem in One Place.
+ Make instantly redeemable tickets for XLM, USDC, or KALE. People can scan, review, and redeem from the same simple flow.
@@ -134,23 +136,24 @@
01 · Build Your Claim Ticket
- Quick start: choose asset, add an optional amount, and generate.
+ Step 1: pick a coin, add optional details, then generate a ticket.
Asset
(asset = 'XLM')}>XLM
(asset = 'USDC')}>USDC
+ (asset = 'KALE')}>KALE
Mode
- Direct claim ticket
- Event ticket drop
+ Direct claim ticket (one person)
+ Event ticket drop (multiple people)
Amount
-
+
Destination
-
+
{#if mode === 'event_drop'}
Event
@@ -158,7 +161,7 @@
{/if}
Message
-
+
Generate QR
@@ -169,7 +172,7 @@
02 · Share & Review
- Review before signing. The QR carries claim intent metadata and never auto-sends funds.
+ Step 2: share your QR or link. Every person reviews details before redeeming. No auto-send.
{#if qrData}
@@ -211,18 +214,18 @@
{#if csv}
Export CSV manifest {/if}
Rows generated: {batchRows.length}
- Free plan creates one ticket at a time. Batch sizes above 1 require Event or Power.
+ Best for giveaways: generate many tickets at once, then print or distribute digitally.
- 04 · Ticket Integrity
+ 04 · Upgrade & Trust
Free Up to {TIERS.FREE.maxBatch}
Event Pack {TIERS.EVENT.maxBatch} • {TIERS.EVENT.priceXlm} XLM
Power Pack {TIERS.POWER.maxBatch} • {TIERS.POWER.priceXlm} XLM
Custom / Enterprise Contact for event ops scale
- One-tap checkout flow: choose your plan, open wallet checkout, and continue generating. No manual ‘I paid’ confirmation step.
+ Step 4: if needed, upgrade your batch limit. Checkout opens in wallet and you can continue right away.
{#if tier === 'EVENT'}Upgrade · {TIERS.EVENT.priceXlm} XLM{/if}
@@ -233,7 +236,7 @@
Platform destination
- Each scan opens a claim review screen first. Redemption always requires explicit signer approval.
+ Anyone can open a ticket safely, review details, and redeem from the same EZWallet flow with signer approval.
diff --git a/src/experiments/ezwallet/config.ts b/src/experiments/ezwallet/config.ts
index 1f8b64a9..a2507e04 100644
--- a/src/experiments/ezwallet/config.ts
+++ b/src/experiments/ezwallet/config.ts
@@ -2,6 +2,7 @@ export const PLATFORM_PAYMENT_DESTINATION = 'CBNORBI4DCE7LIC42FWMCIWQRULWAUGF2MH
export const PENDING_INTENT_KEY = 'smol:pendingStellarQrIntent';
export const USDC = { code: 'USDC', issuer: 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN' };
+export const KALE = { code: 'KALE', issuer: 'CB23WRDQWGSP6YPMY4UV5C4OW5CBTXKYN3XEATG7KJEZCXMJBYEHOUOV' };
export const TIERS = {
FREE: { name: 'Free', maxBatch: 1 },
diff --git a/src/experiments/ezwallet/qrPayload.ts b/src/experiments/ezwallet/qrPayload.ts
index 84b30829..47e08ea1 100644
--- a/src/experiments/ezwallet/qrPayload.ts
+++ b/src/experiments/ezwallet/qrPayload.ts
@@ -1,5 +1,5 @@
import type { StellarIntent } from './types';
-import { USDC } from './config';
+import { USDC, KALE } from './config';
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}$/ };
const clean = (v?: string, n = 80) => (v || '').trim().slice(0, n) || undefined;
@@ -12,6 +12,7 @@ export function validateIntent(i: StellarIntent): string[] {
if (i.asset.code === 'XLM' && i.asset.type !== 'native') e.push('XLM must be native');
if (i.asset.code === 'XLM' && i.asset.issuer) e.push('XLM cannot have issuer');
if (i.asset.code === 'USDC' && i.asset.issuer !== USDC.issuer) e.push('USDC issuer mismatch');
+ if (i.asset.code === 'KALE' && i.asset.issuer !== KALE.issuer) e.push('KALE issuer mismatch');
if (i.asset.code !== 'XLM' && !i.asset.issuer) e.push('Issuer required for non-native');
if (i.amount && !RE.amt.test(i.amount)) e.push('Invalid amount');
if (i.destination && !RE.g.test(i.destination) && !RE.c.test(i.destination)) e.push('Invalid destination');