The v0.3.1 wallet offers THORChain swaps alongside Trocador, and the backend
adds a THORChain affiliate fee: THORName suchsoftware, 25 basis points of the
swap, withheld by THORChain and paid to that THORName. The Terms described
only the Trocador referral commission and said in-wallet swaps were executed
by Trocador, which is no longer true.
Section 7.1 now scopes the Trocador text to Trocador swaps. A new 7.2
describes THORChain swaps (the wallet deposits directly to a THORChain vault;
we hold no funds and are not the counterparty) and the affiliate fee, which
the quote shows before the user confirms. Additional providers moves to 7.3.
Section 9 notes that our own swap fees are the exception to "set by those
providers", and the summary names both fees. Effective date: October 15, 2026.
Type check, 10 unit tests and the production build pass. Lint fails at the
base commit as before: eslint.config.mjs expects a flat-config
eslint-config-next, and 15.3.6 does not export one.
Section G now names every third party the v0.3.1 wallet can contact, matching
the client's PRIVACY.md: Trocador, THORChain through Liquify's gateway, NonLogs
through our backend, Neroswap price lookups, and backend.smirk.cash for old
tips. It says what each receives and when, that opening the Swap tab contacts
no provider, and that NonLogs is the one provider that does not see the user's
IP. It also adds the NonLogs fee share beside the Trocador commission, and the
second sealing of tip claim keys sent to a Nostr identity. Effective date moves
to October 9, 2026.
The site now reads tips from the v0.3 backend, which does not hold tips
created by v0.2.x wallets, so their links said "Tip not found". A 404 from
the v0.3 backend now falls back to the legacy backend. Such tips are shown
without a claim button, with a note that claiming needs the next wallet
update, because a v0.3 wallet cannot claim them yet. Only the fields the
page renders are kept from either response.
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