72 Commits

Author SHA1 Message Date
pezkuwichain 165cb47c64 security(p2p): close escrow-RPC anon-drain (release/lock behind signed edge functions)
Round 2 — fixes the CRITICAL discovered during round 1 (as severe as the withdrawal
BOLA): lock_/release_/refund_escrow_internal had default PUBLIC EXECUTE and the client
called release_escrow_internal directly with the anon key, so anyone could drain any
victim's LOCKED balance.

- release_escrow_internal now reachable only via new signed confirm-payment edge
  function: verifies seller wallet signature (raw + <Bytes>), asserts the wallet owns
  the seller identity, derived user_id == trade.seller_id, trade == payment_sent,
  single-use nonce, then release runs with the service role. confirmPaymentReceived
  now invokes confirm-payment (no more anon rpc).
- lock_escrow_internal now behind new signed lock-escrow edge function (a caller can
  only lock its own balance; stops griefing a victim's balance). Removed a zero-amount
  no-op lock call.
- Migration 20260725030000: REVOKE EXECUTE on lock_/release_/refund_escrow_internal
  from PUBLIC/anon/authenticated; GRANT to service_role only. refund has no direct
  client caller (service-role + admin_resolve_dispute only).
- DEPLOY_RUNBOOK.md consolidates the ordered migrations, edge functions and secrets
  for both security rounds. Migration 20260725030000 must ship WITH the two new edge
  functions + frontend or offer-create/payment-release break.

Remaining (non-fund, Round 2+ follow-up): read RPCs still key on a non-secret user_id
(binding to a signed session would force a sign-prompt on every passive balance read —
deferred); p2p_fiat_offers/trades/messages retain USING(true) (status labels move no
funds now that all escrow movement is service-role-gated).
2026-07-25 00:21:20 -07:00
pezkuwichain a8f41cd47f security(p2p): fix withdrawal BOLA, financial RLS exposure, admin dispute escrow
Critical/high audit remediation on the custodial P2P ledger. Auth model is
wallet-based; identity (citizen/visa) is cryptographically bound to a wallet
(People Chain tiki.citizenNft / active p2p_visa), which enables a correct fix.

- Withdrawal BOLA (CRITICAL): process-withdraw now requires a wallet-SIGNED
  challenge; server verifies signature (raw + <Bytes> forms), asserts the signer
  OWNS the identity, consumes a single-use nonce (replay), and derives user_id
  server-side — the client-supplied user_id is ignored. process-withdrawal (batch)
  now requires the service-role key (was: any bearer, incl. public anon key).
  request_withdraw is REVOKEd from anon/authenticated + service-role guarded.
- Financial RLS (HIGH): drop the blanket USING(true) SELECT on user_internal_balances,
  p2p_balance_transactions, p2p_deposit_withdraw_requests; lock p2p_user_payment_methods
  (IBAN PII) + p2p_fiat_disputes UPDATE to service_role; legitimate reads move behind
  scoped SECURITY DEFINER RPCs.
- Deposit integrity: verify-deposit now binds the on-chain sender to identity ownership
  before crediting.
- Admin dispute (CRITICAL fund-logic): DisputeResolutionPanel relabeled trades without
  moving escrow. New admin-signed resolve-dispute function + admin_resolve_dispute RPC
  moves escrow (release/refund/split) atomically with correct accounting (avoids the
  double-count in the legacy resolve_p2p_dispute). Client isAdmin documented as cosmetic.

DEPLOY RUNBOOK (gated; owner runs): 1) apply migrations 20260225/20260725* in order;
2) deploy edge functions process-withdraw, process-withdrawal, verify-deposit, resolve-dispute;
3) set edge secrets PEOPLE_RPC_ENDPOINT (+ optional ADMIN_WALLETS); 4) ship frontend.
Migrations + functions + frontend must go together or the app breaks.

KNOWN RESIDUAL (Round 2 — as severe as the withdrawal BOLA): release_/lock_/refund_
escrow_internal still have PUBLIC EXECUTE and the client calls release_escrow_internal
directly with the anon key from confirmPaymentReceived -> an anon caller can drain any
victim's LOCKED balance. Fix = a wallet-signed confirm-payment edge function (same
pattern as withdrawals) before revoking PUBLIC execute. Not yet fixed.
2026-07-25 00:09:03 -07:00
pezkuwichain 1c6ff3d578 fix(web): correct asset IDs/decimals + chain routing, string-BigInt amounts, presale signer
Fund-logic hardening (audit remediation):
- TransferModal: source asset id/decimals from the canonical MINTABLE_ASSETS
  (wUSDT=1000, wDOT=1001, wETH=1002, wBTC=1003) instead of the wrong hardcoded
  ids (BTC=3 was the deprecated "Old USDT", ETH=4, DOT=5). Route every non-native
  asset through the Asset Hub api; only native HEZ uses the relay balances pallet.
  Removes the latent wrong-asset / wrong-chain transfer.
- Replace BigInt(parseFloat(x)*10**dec) with string-based parseTokenInput in
  TransferModal + 3 DEX init modals; BigInt(float) threw RangeError on common
  fractional amounts (e.g. 100.3 HEZ), breaking sends and pool/bridge init.
- Presale.contribute now resolves a signer via getSigner and passes { signer }
  to signAndSend (was signer-less -> broken for all users).
- presale.ts contribute/refund/claimVested now reject on dropped/invalid/usurped/
  retracted tx states instead of hanging the UI forever.
2026-07-24 22:55:54 -07:00
pezkuwichain 0651b80eb7 fix: sync renewal topup with the live bridge config (10K -> 200K wUSDT)
STANDARD_RENEWAL_TOPUP still had the bot's old built-in default (10,000).
The live pezbridge_bot_config.json and the Android wallet's
BridgeMultisigConstants both renew to 200,000 (threshold 40,000) - and all
three signing channels must build the same call, or the hash differs and
real pending renewals stop auto-matching in the /multisig/pending UI.
2026-07-19 01:48:13 -07:00
pezkuwichain dd58fe9164 Add multisig pending-operations UI, fix broken multisig address calc, new signing portal
- calculateMultisigAddress was completely broken (hex-decoded an SS58 string
  and never hashed the preimage) - fixed via @pezkuwi/util-crypto's real
  encodeMultiAddress/createKeyMulti, verified against the actual known
  multisig address on-chain.
- ReservesDashboardPage had stale Noter/Berdevk addresses that don't match
  the real signers - centralized as BRIDGE_MULTISIG_SPECIFIC_ADDRESSES.
- USDTBridge withdrawal called assets.burn directly as a single-signer
  extrinsic (always fails - only the multisig is Admin) while only
  checking status.isFinalized (a failed dispatch is still finalized, so it
  silently did nothing) - replaced with the correct transfer-to-custody
  flow the relayer actually watches for.
- New MultisigOperationsPage (/multisig/pending) lists pending calls from
  real Multisig.Multisigs storage and lets any of the 5 signers
  approve/reject with their own wallet extension.
- New standalone sign/ app (deployed separately at
  pezbridge-sign.pex.mom) - a dedicated, gated signing portal for the same
  operations, so signing isn't dependent on this app alone.
2026-07-14 07:19:34 -07:00
pezkuwichain e3beba7538 fix: correct KycLevel enum map and restrict founder bypass
1. Fixed enum map missing NotStarted at index 0, causing all status
   indices to be off by one (ReferrerApproved decoded as PendingReferral)
2. Restricted founder bypass to only show applications with no referrer,
   not all applications regardless of referrer
2026-03-01 22:08:40 +03:00
pezkuwichain a8505a4d50 fix: use dynamic SS58 prefix in referral/KYC address encoding
Replace hardcoded SS58 prefix 42 with api.registry.chainSS58 ?? 42
for robustness in getPendingApprovalsForReferrer, getReferralInfo,
and getMyReferrals functions.
2026-02-28 01:59:04 +03:00
pezkuwichain fd57a75fd9 fix: handle all kycStatus formats in pending approvals check
toJSON() for Substrate enums can return string, object ({"approved":null}),
or number (enum index). Previous code assumed string only, causing already
approved applications to appear as pending.
2026-02-27 04:14:35 +03:00
pezkuwichain abdb67f6ca fix: convert hex AccountId to SS58 in referral/KYC queries
toJSON() returns hex format for AccountId fields but comparison was
against SS58 addresses, causing referrer matching to always fail.
- citizenship-workflow: encodeAddress for referrer in getPendingApprovals
- citizenship-workflow: handle both PascalCase and camelCase KycStatus
- referral: encodeAddress for referrer in getMyReferrals and getReferralInfo
2026-02-27 03:57:36 +03:00
pezkuwichain 8232cdb0e1 fix: extract actual error from process-withdraw edge function response
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).
2026-02-24 23:01:50 +03:00
pezkuwichain 607ef72948 fix: payment proof lifecycle, repeating toast, and escrow migrations
- Replace IPFS/Pinata upload with Supabase Storage for payment proofs
- Add 1-day auto-expiry for proof images (retained if disputed)
- Fix repeating "payment deadline expired" toast (fire once, clear interval)
- Fix cancel_reason → cancellation_reason column reference
- Add payment proof lifecycle migration (proof_expires_at, cleanup functions)
- Add atomic escrow migration (accept_p2p_offer, complete/cancel trade)
- Add cleanup-proofs edge function for daily expired proof deletion
2026-02-24 06:15:22 +03:00
pezkuwichain d380e6a3cd fix: correct cancel_reason column name to cancellation_reason
Also add migration to drop remaining auth.users FK constraints
on p2p_messages, notifications, ratings, audit_log tables.
2026-02-24 05:34:42 +03:00
pezkuwichain 0a9349f2b3 fix: show actual Supabase error details in P2P toast messages
PostgrestError is not instanceof Error, so catch blocks were falling
through to generic messages. Now extracts .message and .details from
Supabase errors for better debugging.
2026-02-24 05:00:45 +03:00
pezkuwichain 56adb45b07 fix: remove price_per_unit from offer insert (generated column) 2026-02-23 22:36:15 +03:00
pezkuwichain b839a1834d fix: withdrawal calls process-withdraw edge function, balance card UI improvements
- 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)
2026-02-23 22:19:06 +03:00
pezkuwichain a80a2cfb07 feat: replace supabase auth with citizen/visa identity system for P2P
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
2026-02-23 19:54:57 +03:00
pezkuwichain 80d8bbbcb1 fix: universal getSigner helper for WalletConnect + extension signing
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.
2026-02-23 07:01:18 +03:00
pezkuwichain bcee7c2a7d fix: mobile UI improvements and web3Enable for WalletConnect signing
- Compact stat cards on mobile (Dashboard, Referral, P2P)
- Hide unnecessary sections on mobile (Recent Activity, NFTs, Score Calculation, Liquidity Pools, Recent Swaps)
- Fix back arrow overlapping title on all pages
- Swap Settings and Governance nav positions for better mobile dropdown
- Add back arrow to Presale page
- Add web3Enable before all web3FromAddress calls for WalletConnect compatibility
- Fix citizenship authentication signing with WalletConnect
2026-02-23 06:22:12 +03:00
pezkuwichain e4abee939f feat: migrate staking from Relay Chain to Asset Hub
- shared/staking.ts: update for AH (remove babe dep, remove validatorPool, bonding 2 eras)
- StakingDashboard: switch all staking operations from api (RC) to assetHubApi (AH)
2026-02-21 02:55:27 +03:00
pezkuwichain 6ac55ecf88 fix: citizenship pending approvals not showing for founder
Application struct has no status field - was filtering by
appData.status === 'PendingReferral' which always returned false.
Now checks kycStatuses storage instead, and allows founder to see
all pending applications.
2026-02-20 00:44:05 +03:00
pezkuwichain 64caf56612 fix: compute staking score from CachedStakingDetails instead of hardcoded 0 2026-02-17 02:38:46 +03:00
pezkuwichain b7d7d008dc feat: staking score 3-state model and noter integration 2026-02-17 01:32:54 +03:00
pezkuwichain 86dc8c1fcd fix: rewrite citizenship workflow to referral-based model
- Replace governance-based KYC with trustless referral workflow
- New 3-step flow: applyForCitizenship -> approveReferral -> confirmCitizenship
- Fix FOUNDER_ADDRESS (was Alice test address)
- Use applications storage instead of legacy pendingKycApplications
- Add approveReferral, cancelApplication, confirmCitizenship functions
- Rewrite KycApprovalTab as referrer approval panel (no governance)
- Fix InviteUserModal to use peopleApi for referral pallet
- Add pending approvals section to ReferralDashboard
2026-02-16 02:56:27 +03:00
pezkuwichain 82ba29c1b0 fix(scores): use correct PezRewards storage query names from live chain metadata
Storage names were wrong (from integration test dev node, not live chain):
- getCurrentEpochInfo → epochInfo
- getUserTrustScoreForEpoch → userEpochScores
- getClaimedReward → claimedRewards
- getEpochRewardPool → epochRewardPools
2026-02-13 20:44:40 +03:00
pezkuwichain f3450d1207 feat: align frontend scoring with People Chain pallet queries
- Update staking score/tracking calls from relayApi to peopleApi
- Fix referral score to use on-chain tiered scoring with penalties
- Fix perwerde score to query studentCourses + enrollments storage
- Update Dashboard and StakingDashboard for People Chain API
2026-02-13 20:13:55 +03:00
pezkuwichain 6fe061cef2 feat(pez-rewards): align frontend with blockchain pallet storage queries
- Fix storage query names: getCurrentEpochInfo, epochStatus, getUserTrustScoreForEpoch, getClaimedReward, getEpochRewardPool
- Add recordTrustScore() and claimPezReward() extrinsic functions
- Add EpochStatus type and epoch status display (Open/ClaimPeriod/Closed)
- Move PezRewardInfo and getPezRewards from staking.ts to scores.ts
- Add PEZ Rewards error/success messages to error-handler.ts
- Add PEZ Rewards card with Record/Claim to Dashboard, Wallet, and Staking pages
- Add recordTrustScore to TransactionHistory tracking
2026-02-13 17:37:10 +03:00
pezkuwichain b378aeb171 refactor(scores): remove frontend fallback, read all scores from blockchain
Remove all frontend staking/trust score calculation and localStorage
fallback code. All scores now read directly from People Chain pallets
(pezpallet-trust, pezpallet-referral, pezpallet-tiki). Trust pallet
computes composite score on-chain.
2026-02-13 03:14:57 +03:00
pezkuwichain fc0907f8ac fix(tiki): fetch roleNFTs from blockchain instead of returning empty array
- getAllTikiNFTDetails now calls fetchUserTikiNFTs to query UserTikis storage
- This enables proper authorization check for government roles like Serok
2026-02-10 22:56:22 +03:00
pezkuwichain e787eaac15 debug: add console logs for trust score calculation 2026-02-07 01:39:11 +03:00
pezkuwichain 598c9f2fec fix: use frontend fallback for trust score calculation
On-chain trust pallet exists but StakingInfoProvider returns None,
causing trust score to be 0 even when user has stake. Use frontend
calculation until runtime upgrade is deployed.
2026-02-07 01:25:05 +03:00
pezkuwichain 90b8204c25 feat: add frontend fallback for staking and trust scores
Until runtime upgrade is deployed, calculate scores on frontend:

shared/lib/scores.ts:
- getFrontendStakingScore: Read stake from Relay Chain, track in localStorage
- getFrontendTrustScore: Calculate using pallet formula
- getAllScoresWithFallback: Combined score fetching with fallback

Formula (matching pezpallet-trust):
- weighted_sum = staking*100 + referral*300 + perwerde*300 + tiki*300
- trust_score = (staking * weighted_sum) / 100

Components updated:
- AccountBalance.tsx: Use getAllScoresWithFallback
- HeroSection.tsx: Use getTrustScoreWithFallback
2026-02-07 00:44:04 +03:00
pezkuwichain f93681ed96 fix: formatBalance now correctly parses hex values from blockchain 2026-02-06 22:14:56 +03:00
pezkuwichain 13646d6e8c fix: support both sonner and shadcn toast APIs in error handler 2026-02-06 21:42:27 +03:00
pezkuwichain 6b26f434dd fix: query pezRewards and stakingScore from People Chain
- pezRewards pallet is on People Chain, not Relay Chain
- stakingScore pallet is also on People Chain
- Update getStakingInfo to accept optional peopleApi parameter
- Update StakingDashboard to pass peopleApi
2026-02-06 21:28:56 +03:00
pezkuwichain 61eb5cff20 fix: update score system to use correct People Chain APIs
- Remove LP staking score (not available in blockchain)
- All scores now fetched from People Chain
- Add Start Score Tracking button to Dashboard
- Add staking status display showing tracking duration
2026-02-06 20:48:27 +03:00
pezkuwichain b0c3626e7a feat: add LP staking score and DOT/ETH/BTC tokens 2026-02-06 20:01:12 +03:00
pezkuwichain 1f14cd475f fix: restore web3FromAddress for browser extension signing 2026-02-06 19:38:59 +03:00
pezkuwichain 9fd0805a97 fix: fetch scores from correct chains (People + Relay) 2026-02-06 19:33:42 +03:00
pezkuwichain 842dc9d8c2 feat: add HEZ/DOT pool support and fix user-facing token names
- Add HEZ/DOT pool to PoolDashboard
- Display DOT, ETH, BTC instead of wDOT, wETH, wBTC to users
- Update priceOracle with correct symbol mappings
- Fix lint errors in check_all_pools.mjs
- Extract MINTABLE_ASSETS to separate file for fast refresh
2026-02-06 11:06:28 +03:00
pezkuwichain 884d68714b feat: implement hybrid oracle AMM with CoinGecko prices
- Add priceOracle service for fetching CoinGecko prices
- Update SwapInterface to use oracle prices instead of pool reserves
- All swaps route through USDT as base currency
- Multi-hop routing for non-USDT pairs (X → USDT → Y)
- Display real-time USD prices from CoinGecko
- Auto-refresh prices every 30 seconds
2026-02-06 10:41:52 +03:00
pezkuwichain 3445eea8dd fix: add null checks for welati pallet in all governance functions 2026-02-06 06:17:26 +03:00
pezkuwichain f061120112 fix: correct wHEZ asset ID from 0 to 2
tokenWrapper pallet on Asset Hub creates wHEZ as Asset ID 2, not 0.

Asset IDs on Asset Hub:
- Asset 1: PEZ
- Asset 2: wHEZ (via tokenWrapper)
- Asset 1000: wUSDT

Updated:
- shared/constants/index.ts: KNOWN_TOKENS
- shared/lib/wallet.ts: ASSET_IDS.WHEZ default
- AccountBalance.tsx: pool queries
- InitializeHezPoolModal.tsx: balance query
2026-02-04 13:52:47 +03:00
pezkuwichain 02094a3635 feat: add XCM teleport and CI/CD deployment workflow
Features:
- Add XCMTeleportModal for cross-chain HEZ transfers
- Support Asset Hub and People Chain teleports
- Add "Fund Fees" button with user-friendly tooltips
- Use correct XCM V3 format with teyrchain junction

Fixes:
- Fix PEZ transfer to use Asset Hub API
- Silence unnecessary pallet availability warnings
- Fix transaction loading performance (10 blocks limit)
- Remove Supabase admin_roles dependency

CI/CD:
- Add auto-deploy to VPS on main branch push
- Add version bumping on deploy
- Upload build artifacts for deployment
2026-02-04 11:35:25 +03:00
pezkuwichain 9bb71c436b fix: update escrow address to Treasury_3
- Update PLATFORM_ESCROW_ADDRESS in p2p-fiat.ts
- Update PLATFORM_WALLET in verify-deposit edge function
- Use controlled wallet for P2P deposits/withdrawals
2026-02-03 16:50:56 +03:00
pezkuwichain 7636d46c7d feat(p2p): OKX-level security upgrade with Edge Functions
- Add process-withdraw Edge Function for blockchain withdrawals
- Update verify-deposit Edge Function with @pezkuwi/api
- Add withdrawal limits (daily/monthly) and fee system
- Add hot wallet configuration with production address
- Add admin roles for dispute resolution
- Add COMBINED SQL migration with full P2P system
- Encrypt payment details with AES-256-GCM
- Prevent TX hash reuse with UNIQUE constraint
2026-01-29 03:12:02 +03:00
pezkuwichain 7e2c2840d3 chore: Fix linting errors and update shared libs for mobile build 2026-01-19 03:35:33 +03:00
pezkuwichain 2855c0b106 Add presale lib and backup file, ignore credentials 2026-01-18 01:08:42 +03:00
pezkuwichain 1f8da810e0 fix: TypeScript errors, shadow deprecations, and build configuration
- Fix shadow style deprecation warnings across components (boxShadow)
- Add type declaration files (codec.d.ts, modules.d.ts)
- Update metro.config.cjs for proper asset extensions
- Update tsconfig.json with module resolution settings
- Fix TypeScript errors in shared/lib files
- Update app icons (optimized PNG files)
2026-01-15 09:37:37 +03:00
pezkuwichain 8d30519efc Fix all shadow deprecation warnings across entire mobile app
- Replaced shadowColor/shadowOffset/shadowOpacity/shadowRadius with boxShadow
- Fixed 28 files (21 screens + 7 components)
- Preserved elevation for Android compatibility
- All React Native Web deprecation warnings resolved

Files fixed:
- All screen components
- All reusable components
- Navigation components
- Modal components
2026-01-14 15:05:10 +03:00
pezkuwichain 1295c36241 Rebrand: polkadot → pezkuwi build fixes
- Fixed TypeScript type assertion issues
- Updated imports from api-augment/substrate to api-augment/bizinikiwi
- Fixed imgConvert.mjs header and imports
- Added @ts-expect-error for runtime-converted types
- Fixed all @polkadot copyright headers to @pezkuwi
2026-01-07 02:32:54 +03:00