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
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.
- Shrink title/banner fonts and padding on mobile
- Move digital ID card above entrance buttons
- Auto-resize uploaded photos via canvas instead of 2MB limit
- Make entrance cards compact 2-column grid on all screens
The signRaw handler was wrapping the address in CAIP-10 format
(polkadot:<chain>:<address>) before sending to the wallet. The wallet
expects a plain SS58 address in polkadot_signMessage params, causing
InvalidChecksumException crash when trying to decode the CAIP-10 string.
P2P modules (TradeModal, p2p-fiat) use Sonner toast but the Sonner
Toaster component was not mounted in App.tsx. Only the shadcn Toaster
was rendered, causing all P2P toast.error/success calls to be invisible.
- requestWithdraw() calls process-withdraw edge function for full flow
(lock balance + blockchain TX + complete) instead of just DB lock
- Remove pending request block from withdrawal validation — backend
already enforces available_balance with FOR UPDATE row lock
- Pending requests shown as info alert instead of blocking error
- Balance card: numbers right-aligned, 2 decimal places
- requestWithdraw() now calls process-withdraw edge function instead of
just locking balance in DB. This triggers the full flow: lock balance,
send blockchain TX, complete withdrawal.
- Balance card: numbers right-aligned, 2 decimal places instead of 4
- Added public SELECT RLS policy on payment_methods table (was blocking
anon users from loading payment method dropdown)
DepositModal was building transactions via relay chain API, and all three
edge functions (verify-deposit, process-withdraw, process-withdrawal) had
RPC endpoints hardcoded or defaulting to the relay chain. This caused
deposit verification to fail with "Transaction not yet finalized" and
created a chain mismatch with the withdrawal system which operates on
Asset Hub.
- DepositModal: use assetHubApi instead of api for transfer TX
- verify-deposit: RPC_HTTP/RPC_WS default to asset-hub-rpc (env override)
- process-withdraw: RPC_ENDPOINT default to asset-hub-rpc (env override)
- process-withdrawal: RPC_ENDPOINT default to asset-hub-rpc
Replace all supabase.auth.getUser() calls with P2PIdentityContext that
resolves identity from on-chain citizen NFT or off-chain visa system.
- Add identityToUUID() in shared/lib/identity.ts (UUID v5 from citizen/visa number)
- Add P2PIdentityContext with citizen NFT detection and visa fallback
- Add p2p_visa migration for off-chain visa issuance
- Refactor p2p-fiat.ts: all functions now accept userId parameter
- Fix all P2P components to use useP2PIdentity() instead of useAuth()
- Update verify-deposit edge function: walletToUUID -> identityToUUID
- Add P2PLayout with identity gate (wallet/citizen/visa checks)
- Wrap all P2P routes with P2PLayout in App.tsx
- Drop auth.users FK constraints for wallet-based authentication
- Fix deferrable unique constraint on blockchain_tx_hash (ON CONFLICT compat)
- Rewrite block search: HTTP RPC + blake2b instead of WS-only @pezkuwi/api
- Add blockNumber hint for faster verification of older transactions
- Normalize SS58/hex addresses via base58 for reliable comparison
- DepositModal captures approximate block number after tx submission
Removed JWT auth requirement from edge function. Now uses wallet address
from request body and verifies it matches the on-chain transaction sender.
This works with wallet-based auth instead of Supabase Auth.
Replace all web3FromAddress calls with getSigner() that auto-detects
walletSource and uses WC signer or extension signer accordingly.
This fixes all signing operations when connected via WalletConnect.