Replaces the buggy useEffect that derived citizen number from wallet
address (and re-triggered whenever user cleared the field) with a clean
sync from DashboardContext's NFT-derived citizenNumber. Field is read-only
when NFT data is present, preventing the refill loop entirely.
- Use PezkuwiExchange.png logo instead of emoji for exchange app icon
- External link opens exchange.pezkuwichain.io in new tab (noopener)
- No auth required (exchange is publicly accessible)
- Added imgIcon and href fields to AppItem interface
B2B button now opens Bereketli (bereketli.pezkiwi.app) embedded in an
iframe. PWAP exchanges the user's Supabase JWT for a Bereketli JWT
via the existing /v1/auth/exchange endpoint, then passes tokens to
the iframe via postMessage. User never sees a login screen.
- New /bereketli route (ProtectedRoute)
- Token caching in localStorage (10 min TTL)
- Camera + geolocation permissions on iframe
- Desktop and mobile layouts supported
- Re-auth on token expiry via postMessage
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Section titles (FINANCE, GOVERNANCE, SOCIAL, EDUCATION) and all app
names are now translated via i18n keys instead of hard-coded English.
Added translations for all 6 languages (en, tr, kmr, ckb, ar, fa).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mobile users (<768px) now see a native app-style home page with:
- Green gradient header with avatar, greeting, language/wallet/notification
- Horizontal scrollable score cards (auth-aware: login prompt for guests)
- App grid sections (Finance, Governance, Social, Education) with 4-col layout
- Bottom tab bar (Home / Citizen / Referral)
- MobileShell wrapper for consistent mobile navigation across pages
BeCitizen page redesigned for mobile with full-viewport hero screen,
scroll-to-reveal content, and compact benefits/process cards.
New Identity page (/identity) with realistic Kurdistan Republic ID card
and passport design. Users can fill personal info, upload photo from
camera/gallery, and save to device (localStorage only).
Desktop layout completely untouched. i18n keys added for all 6 languages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mobile users only see the Mainnet detail card (WebSocket endpoint,
Chain ID, explorer button, services grid). The individual chain
cards (Staging, Testnet, Beta, etc.) and subdomains box are hidden
on mobile and visible on md+ screens.
Google blocks OAuth in WebViews (disallowed_useragent policy).
Detect WebView and hide the Google button, users in DApps browser
use email/password instead. Google sign-in still works in real
browsers (Chrome, Safari, etc).
Mobile users now see ChainSpecs (Mainnet card) right below the hero
section instead of scrolling far down. "Learn More" button hidden on
mobile since Mainnet card replaces its function.
- Call refreshInbox() immediately after setupKey/unlockKey so messages
decrypt instantly instead of waiting for 12s polling interval
- Query both current and previous era to prevent message loss at era
boundaries
- Add toJSON fallback for robust field parsing in getInbox
- Improve debug logging with era, address, and field diagnostics
messaging.inbox and messaging.sendCount are StorageDoubleMaps keyed by
(era, address). Passing [era, address] as a single array produced empty
results; split into two arguments so the API constructs the correct
storage key.
- Check isPalletAvailable() BEFORE requesting wallet signature
- All chain queries return safe defaults if pallet not in runtime
- Show orange banner when messaging pallet needs runtime upgrade
- Add floating back-to-home button on messaging page
- x25519 ECDH + XChaCha20-Poly1305 encryption via @noble libs
- Key derivation from wallet signRaw, private key held in memory only
- Messaging pallet integration (registerEncryptionKey, sendMessage, inbox)
- Inbox polling every 12s, auto-decrypt when key unlocked
- ComposeDialog with recipient key validation and 512-byte limit
- Settings moved from grid to nav bar gear icon, PEZMessage takes its slot
- i18n translations for all 6 languages (en, tr, kmr, ckb, ar, fa)
TX was not yet included in a block when verify fired immediately
after signing, causing first attempt to always fail. Block time on
Asset Hub is ~12s, so delay the verify call accordingly.
The manual "Verify Deposit" step required users to click a button after
signing. Hash was already captured automatically, making the manual step
redundant and risky (modal close = hash lost). Now verification starts
immediately after TX is signed, with spinner UI and retry on failure.
- Back to Home button: smaller padding/font on mobile, pinned to corner
- PriceChart: increase height to 280px, stack header vertically on mobile
- TokenSwap: reduce padding/gaps/fonts on mobile, fix double-colon in balance text
Supabase JS client wraps non-2xx responses as generic FunctionsHttpError
("Edge Function returned a non-2xx status code"), hiding the real error.
Now reads the response body to show the actual error message.
Also adds migration to drop auth.users FK on p2p_withdrawal_limits
(already absent in production, added for migration completeness).
Three fixes for WC signing:
1. Changed optionalNamespaces to requiredNamespaces so wallet MUST
approve all Pezkuwi chains (relay, asset hub, people) or reject.
2. Restored payload-based chainId in signPayload — wallet validates
that WC chainId matches the transaction payload's genesisHash
and rejects mismatches with "Wrong chain id passed by dApp".
3. Added session validation on restore — old sessions missing
required chains are discarded, forcing a fresh session with
all chains included.
WC SignClient validates that the request chainId is in the session's
approved namespaces. When the DApp browser creates a session, it may
only approve the relay chain. Signing requests for Asset Hub or People
Chain then fail with "Missing or invalid chainId".
Fix: always use a chainId from the session's approved chains for the
WC request. The wallet determines the actual signing chain from the
transaction payload's genesisHash, not from the WC request chainId.
WC session was missing Asset Hub and People Chain because their APIs
weren't connected yet at session creation time. Also fix catch blocks
in ExistingCitizenAuth that referenced undefined err variable.