The v0.3 backend answers GET /users/me/username with {"username": ...};
the legacy backend sent a bare string. The page put the object into state
and rendered it, so /settings threw for every signed-in user.
parseUsernameResponse accepts both shapes and returns only a string or
null. Legacy-only fields on /auth/me are optional. Adds node:test cases,
run with npm test.
v0.3 wallets register with the v0.3 backend, so a site built against the
legacy backend answered every v0.3 sign-in with "User not found". The
v0.3 backend resolves website sign-in by each coin's own key and adopts a
legacy identity on first proof, so it serves both generations.
The v0.3 backend has no social linking. Settings now loads linked accounts
separately and hides that section when they are unavailable, instead of
failing the whole page and taking username editing with it. The public user
count and stats may come from a separate backend via
NEXT_PUBLIC_STATS_API_URL; unset keeps today's behavior.
- Privacy: add Nostr identity + name@smirk.cash, encrypted messaging,
and IP-hashing sections; note the self-hostable backend (your data
goes to that operator, not us). Correct the BTC/LTC description:
addresses are queried against Electrum/Fulcrum servers, not
mempool.space/litecoinspace.org.
- Terms: usernames/identity, reporting unlawful content, DMCA, and
relay/messaging abuse terms for v0.3.
- smirk.d.ts: SmirkPaymentRequest.amount is a human decimal amount, not
atomic units (matches the dapp protocol after the decimal-amount fix).
The feed now reads the backend's advertised feed config — show owner / premium
members / a featured npub allowlist, across the relay + optional extra relays —
and renders an owner badge. Falls back to a sensible default (the Smirk relay,
premium + owner) when a backend doesn't advertise a feed config yet, and shows
an "off" state when an operator disables it.
The Smirk square, served from relay.smirk.cash. Because the relay is
premium-post gated, the feed is self-curating — general notes (kind 1) come
only from premium members. v1 is read-only (subscribe + render); composing
arrives with the wallet's Nostr dapp-api scope. Adds nostr-tools and a Nostr
icon beside Telegram/Discord that links to the feed.
Disclose the Trocador swap fee, PA governing law + class/jury-waiver dispute
terms, 18+/sanctions, Apple EULA rider. Replaces the old 'access is free, fees
later' clause. No MoonPay section (not integrated).
The runtime that installs window.smirk in v0.3.0+ iframe context
is now available as a published npm package, so smirk.cash can
import it directly instead of carrying a synced local copy. Same
behaviour, less maintenance burden.
- npm install @such-software/smirk-dapp-api@^0.3.0
- SmirkBridgeBootstrap imports installSmirkPageApi from the package
- Local mirror deleted (src/lib/smirk-iframe-bridge.ts)
Adds a runtime that auto-detects parent-frame context and installs
window.smirk via postMessage, so smirk.cash works inside the
v0.3.0 Smirk desktop wallet's embedded browser the same way it
already works under the v0.2.x browser extension. Extension-injected
window.smirk takes precedence, so existing dapps and the v0.2.x
flow are unchanged.
Local mirror of @smirk/dapp-api's installSmirkPageApi pending
that package being published to npm; see the file header for the
sync contract.
The extension's window.smirk injection runs as `<script type=module>`,
which browsers defer until after DOMContentLoaded. The previous
detection (sync check + once at +500ms) could race past that on
heavier Next.js pages, leaving the Connect button stuck greyed-out
even though the extension was installed and unlocked.
Three-layer fix in both `app/page.tsx` and `app/tip/[id]/TipPageClient.tsx`:
1. Immediate sync check (fast path: extension already there).
2. Listen for `smirk-ready` CustomEvent (extension v0.2.5+ dispatches it).
3. Polling fallback at 100ms intervals up to 3s, for older
extensions or any future browser quirk. Cheap; stops as soon as
window.smirk appears.
`hasExtension` stays `null` (initial) until either we resolve `true`
or hit the 3s timeout and resolve `false` — so the install prompt
doesn't flash on first paint while polling is still in flight.
Also updated `types/smirk.d.ts` to current extension API surface:
asset-scoped `connect(assets?: SmirkAsset[])`, `getAddresses`,
`requestPayment`, and the `smirk-ready` WindowEventMap entry.
Per-asset return fields are nullable now since the user can approve
a subset of assets at connect time (cross-chain deanon mitigation).
- Extract fragment key from URL
- Check confirmations before allowing claim
- Add claim button with loading/error states
- Update SmirkAPI types for claimPublicTip
- Auth flow now uses single signature from user's chosen coin
- Update SmirkSignResult types to match extension API
- Add Creepster font for branding
- Better error messages from API responses
- Update docs to reflect single-asset auth is working
- Next.js 16 with TypeScript and Tailwind CSS
- Single-asset authentication (user picks favorite coin to sign)
- Logo with glow animation
- Coin picker UI with all 5 assets
- API client for backend auth endpoints
- TypeScript types for window.smirk extension API