Deep link debug: DeepLinkModule wiring at app/root/di/deeplink/DeepLinksModule.kt
confirmed MultisigDeepLinks IS included in the assembled handler list (ruling that
out), yet the earlier MultisigOperationDetailsDeepLinkHandler-level Log.e calls never
fired at all - not even the very first one in matches(). Logging one level up, at
the true entry point, to see the raw Uri/scheme/authority/path as parsed and the
final Result, before guessing further.
Mining Simulation: adds a 'PEZ Airdrop' label above the square (user request), and
refuses to activate + shows an explicit error if trust score is 0, instead of
silently starting a permanently-zero-rate session.
Cosmetic, client-side-only preview of a trust-score-weighted PEZ emission
share, meant to incentivize referral usage (higher trust score -> visibly
faster mining). Not tied to any real distribution mechanism or backend.
- MiningSimulationFormula: pure calc. Rate per minute = (92.5M PEZ / 43200
min era) * (trustScore / 500,000 reference total) - trust score is a
direct multiplier so zero trust score always yields zero rate. Diamonds
only accrue while a 24h session is active.
- MiningSimulationRepository: local-only persistence via the existing
Preferences wrapper (same pattern as BannerVisibilityRepository), keyed
per accountId. Tapping the square freezes the live total as the new base
and starts a fresh 24h session - never resets progress on tap. A full
43200-minute era rolling over resets the total to 0 (that era's pool is
considered distributed) independently of session taps.
- UI: square button in the dashboard card's previously-empty right column,
red when inactive (needs a tap), gold (#FDB813, matching the existing
Trust Score color) while actively mining. Small Telegram icon opens
https://t.me/DKSKurdistanBot via the existing Browserable mixin.
Surfaces multisig operations awaiting the current signatory's own
approval directly on the main balance screen, instead of requiring
navigation to the separate pending-operations list. Each row shows the
formatted amount, destination, chain, and approval progress, with a
red Sign button that opens the existing operation-details/approve flow
(fee estimation, signatory balance check, and validation are all
already handled there - not reimplemented here).
Reuses the already-tested MultisigCallFormatter from
feature-multisig:operations (added as a new feature-assets dependency,
exposed via the standard FeatureApi/FeatureContainer pattern - see
AssetsFeatureHolder/AssetsFeatureComponent/AssetsFeatureDependencies)
rather than re-deriving call-preview formatting independently. The
card follows the same SingleItemAdapter + ConcatAdapter pattern as the
existing Pezkuwi Dashboard card on the same screen.
Once a pending operation is actually signed, it naturally drops off
this list on the next sync (no separate client-side "signed" state is
tracked in parallel with the real on-chain approval status).
String only added to the base (English) strings.xml for now - not yet
translated into the other ~14 locales this app otherwise maintains.
The structural separation (dedicated screen, no amount input) was already
in place, but the screen itself was much sparser than Swap's own execution
UI - just a label and a timer, no "Do not close the app!" warning and no
summary of what's actually being bridged. Added both, reusing components
already proven on Bridge's own input screen (BridgeAssetInputView in
non-editable mode, same as the main screen's fromCard/toCard) rather than
reaching into feature-swap-impl's Swap-specific components.
Also added the signatories' contact channel (t.me/pezkuwidestek) to the
existing "still processing" message, and made explicit that funds are safe
and on-chain even when auto-pay doesn't complete within the wait window -
this is the message shown when a real transfer lands in manual review, not
just the pre-submit consent gate.
Symmetric across both bridge directions, checked in priority order before
any funds move:
1. Real reserve exceeded (withdrawal only) - the multisig doesn't hold
enough real USDT on Polkadot Asset Hub. No signature can fix this, so
this stays a hard block (existing bridge_wusdt_to_usdt_blocked message),
never offered as "proceed anyway".
2. Automation-key approval exceeded (either direction) - funds exist, the
automation key just isn't currently approved to auto-pay that much.
Resolvable by 3-of-5 signing, so this is now an explicit opt-in: a
warning banner names the ~2h typical review window and the signatories'
contact channel (t.me/pezkuwidestek), gated behind a WarningCheckBox the
user must tick before Swap re-enables. Previously there was no signal at
all here - a large amount would just silently queue for manual review
after debiting the user, with no way to know that going in.
Both getWusdtRemainingAllowance/getPolkadotUsdtRemainingAllowance query the
real on-chain Assets.Approvals amount per leg - not a guess. Confirmed
on-chain (2026-07-16) the Polkadot leg has never had an approval granted at
all, so every wUSDT->USDT withdrawal currently hits the consent gate
regardless of amount, symmetric with what happens once a signatory grants
one (mirrors the existing wUSDT-side renewal flow exactly, including the
same 40,000/200,000 20%-threshold pattern) - added a second sign button so
a signatory can actually grant it from this screen.
swapClicked()'s confirmation gate now also enforces the consent requirement
server-side (well, client-domain-side) rather than only via the button's
enabled look, consistent with how it already re-checks balance/reserve.
The single-screen design (amount input + live balance validation + submit
+ destination-wait, all in one ViewModel) was structurally fragile: the
live origin-balance observer and the amount-vs-balance validation ran in
the same reactive scope as execution, so a real successful transfer could
flash a false "insufficient balance" error the instant the balance dropped
post-submission. Patching that race (clearing the field, then an isExecuting
flag) kept fixing symptoms without addressing why the class of bug existed:
the app's own Swap flow avoids it entirely by keeping amount entry and
execution as separate screens/ViewModels, so validation code for the input
screen simply doesn't exist on the execution screen.
BridgeExecutionViewModel/Fragment now own the actual submit + destination-
wait, reached by navigating with a BridgeExecutionPayload once
BridgeViewModel.swapClicked() re-validates amount against the latest known
balance/reserve - a real confirmation gate, not just a UI button-disabled
look the domain layer never itself checked. A single BridgeExecutionState
sealed class (SubmittingOrigin/OriginFailed/WaitingForDestination/
DestinationConfirmed/DestinationPendingReview) replaces what used to be six
independently-updated LiveData flags that had to be kept in sync by hand.
Also fixed two real bugs found via live device testing with real funds:
- BridgeMultisigConstants.POLKADOT_USDT_ASSET_ID was 1 (the wallet's own
chains.json ordinal for USDT on Polkadot Asset Hub) instead of 1984 (the
real on-chain Assets pallet id, confirmed directly against the chain).
getPolkadotUsdtReserve() queried asset 1, which the multisig has never
held anything at, so the wUSDT->USDT reserve check always reported 0
USDT available regardless of the multisig's real (and growing) holdings.
- The deposit-wait label's text was static XML, never updated on the
success path - a genuinely completed bridge (destination balance
confirmed, checkmark shown) still read "Waiting for confirmation..."
forever, indistinguishable from actually being stuck. The new execution
screen's label is driven by BridgeExecutionState instead.
Tapping Swap on the Bridge screen previously gave zero feedback afterward -
the same countdown/success UX already used for swap execution didn't exist
here, so a user had no way to tell whether anything was happening. Moved
ExecutionTimerView (+ its layout) from feature-swap-impl to common, since it
was already fully self-contained (no swap-specific coupling, all its
resources already lived in common) - both features now share the one
component instead of duplicating it.
Wired into BridgeViewModel: after a swap is submitted, actively observe the
destination balance (walletInteractor.assetFlow) for a real increase within
a bounded window, showing the countdown while watching and Success only on
a confirmed balance delta - never a cosmetic timer that "completes"
regardless of whether funds arrived. If the window elapses without
confirmation, it says so plainly (may need manual 3-of-5 review) rather than
showing a false success or a false error.
BridgeViewModel's wUSDT->USDT gate called http://217.77.6.126:3030/status -
the legacy single-key bridge bot's endpoint. That service was stopped this
same session (see res/validators-tiki.md), so the check always threw,
always caught, and always reported "inactive" - the red warning reflected a
dead dependency, not real reserve state.
Replaced with a direct on-chain read of the multisig's actual USDT balance
on Polkadot Asset Hub (BridgeMultisigInteractor.getPolkadotUsdtReserve, via
a new Assets.Account storage query mirroring the existing Approvals one).
The gate is now per-request: a specific withdrawal is blocked only if it
exceeds the real reserve, not on a global on/off flag requiring full 1:1
parity between total circulating supply and total reserve - matching how
the Rust listener's own reserve-shortfall check already works. Re-checked
on every amount change, not just once per screen load.
bridge_wusdt_to_usdt_blocked now takes the available reserve amount as a
parameter; updated the English and Turkish strings. Left values-ku
untouched deliberately - not fabricating Kurdish translation text without
native review.
The DOT<->HEZ bridge backend (the legacy single-key bot) is being
permanently decommissioned - it had zero multisig protection and no
liquidity gate at all on that leg (unconditionally "active" regardless
of pool state, the single least-safe path in the whole bridge). Once
USDT bridging is solid, HEZ is reachable indirectly (bridge USDT, swap
for HEZ within Pezkuwi's own ecosystem) without a dedicated native
bridge that would need its own from-scratch security work (native
currency has no Assets.approve_transfer-style delegation to reuse).
- BridgePair/BridgeDirection collapsed to USDT-only (USDT_TO_WUSDT/
WUSDT_TO_USDT) - kept the pair/pairOptions/picker structure itself
since it costs nothing and is the natural seam for a future pair,
rather than hardcoding a single value inline.
- Removed the now-dead DOT/HEZ exchange-rate fetching (CoinGecko
polling, fallback rate) and liquidity-gate logic entirely, not just
the unreachable enum branches.
- Removed the separate "Bridge DOT ↔ HEZ" entry from the asset
selector bottom sheet (BuySellSelectorMixin) - both it and "Bridge
USDT" opened the exact same screen with no preset, so keeping a
DOT-HEZ-labeled entry pointing at a USDT-only screen would have been
actively misleading, not just redundant.
- bridge_title was the generic toolbar/picker-sheet title but hardcoded
"DOT ↔ HEZ Bridge" regardless of pair - fixed to "USDT Bridge".
- Removed now-unreferenced strings (wallet_asset_bridge,
bridge_pair_dot_hez, bridge_rate_format(_reverse),
bridge_hez_to_dot_note/warning/blocked) from the base strings.xml.
Confirmed via research: feature-bridge-api/feature-bridge-impl modules
exist but are unrelated orphaned scaffolding, not depended on by :app,
zero code overlap with this screen - correctly out of scope here.
Any of the USDT bridge multisig's 5 known signatories now sees a
status button on the Bridge screen: green when the automation key's
spending allowance is healthy, red with a Sign action once it drops
below threshold. Signing submits the renewal's as_multi approval
directly from the wallet, mirroring the same on-chain action already
available via pwap-web and pezbridge-sign.pex.mom - a third
independent channel for the same operation, none of which is a
single point of failure.
Replaces the segmented pair/direction buttons and plain-text amount
sections with token-icon cards (BridgeAssetInputView), a one-tap flip
button, and a bottom-sheet pair picker (BridgePairListBottomSheet).
BridgeViewModel gains only additive presentation data (fromCard/toCard/
pairOptions, derived from the existing pair/direction state and the
same chainId/assetId mapping swapClicked() already used) - all bridge
business logic (rate, fee, minimum, liquidity warnings, submission)
is unchanged.
Branch.io was inherited from Nova Wallet fork but never configured.
Removed SDK integration, manifest intent filters, Gradle dependencies,
Dagger DI modules, and string resources. Deep linking now routes
exclusively through app.pezkuwichain.io with verified assetlinks.json.
Add dashboardRefreshSignal to trigger re-fetch on swipe-to-refresh,
onResume, citizenship bottom sheet dismiss, and score tracking.
Rename button label to "Apply & Actions (KYC)" for clarity.
Query StakingScore::StakingStartBlock from People Chain to check
tracking status. Show "Start Tracking" button for approved citizens
who haven't opted in yet. Submits start_score_tracking() extrinsic
with loading state and error handling to prevent duplicate calls.
Custom scheme pezkuwiwallet:// is not clickable in WhatsApp and
other messaging apps. Use https://t.me/pezkuwichainBot?start=ADDRESS
which is universally clickable and auto-fills the referrer field.
When Alice shares a referral link, it now generates a deep link URL
(pezkuwiwallet://pezkuwi/open/citizenship?referrer=address) that
auto-opens the citizenship form with Alice's address pre-filled as
the referrer, fixing the bug where referrer defaulted to founder.
- Add CitizenshipBottomSheet with form (name, father, grandfather, mother, tribe, region)
- Submit apply_for_citizenship extrinsic with referrer parameter to People Chain
- Query KYC status from IdentityKyc pallet and show appropriate UI state
- Referrer approval: query Referral + Applications entries, approve pending referrals
- Sign (confirm_citizenship) for applicants after referrer approval
- Share referral link for citizens to invite others
- Dashboard buttons adapt to citizenship status (hide Apply/Sign when approved)
- Balance check (1.1 HEZ) only before new applications, not for sign/approve
- i18n strings for en, tr, ku
Remove telegram_welcome image from dashboard card, add live Welati
citizen count fetched from kurds-counter API endpoint. Shows formatted
count with "Hejmara Kurd Le Cihane" label in green.
- Restore staking module to Nova upstream (fix Polkadot ACTIVE/shimmer)
- Add USDT(DOT) <-> USDT(HEZ) bridge option to Buy/Sell screen
- Dashboard card: add telegram_welcome image, info text, Non-Citizen role
- Add non-citizen info text to all 12 locale files
- Simplify ComputationalCache (remove stale scope recreation)