Commit Graph

54 Commits

Author SHA1 Message Date
pezkuwichain 707d1baba4 Add a Pending Signatures card to the wallet home screen
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.
2026-07-17 13:03:12 -07:00
pezkuwichain 6fd7a56382 Bridge: add retry on origin failure, dedupe fee constant
Retry: OriginFailed only offered "Done" (start over from the input
screen) - the origin transfer never left the wallet in that state, so
retrying is just re-running submit() from scratch, same as Swap's own
retryClicked(). The execution screen's action button now shows "Try
again"/retries when OriginFailed, "Done" otherwise - derived from the
same state observer already driving the alert banner, not a second
LiveData to keep in sync.

FEE_PERCENT was duplicated as separate 0.001 literals in BridgeViewModel
and BridgeExecutionViewModel. Moved to BridgeMultisigConstants (already
the shared home for this feature's cross-cutting constants) so there's
one number to change if the server-side fee_basis_points ever does.

Deliberately NOT touching the deeper architecture items (LiveData vs
StateFlow, extracting submit logic to a domain interactor) - Bridge's
sealed BridgeExecutionState already gives it the single-source-of-truth
property that motivated Swap's StateFlow design, and its submit/wait
logic isn't shared with any other screen, so there's no duplication or
desync bug those changes would actually fix here. This scope is staying
USDT.p<->USDT only going forward (other bridge/swap pairs route through
the separate pezsnowbridge DApp) - the real trigger for that refactor
(a second bridge pair reusing this logic) will not happen in this
screen, so it's not deferred tech debt, it's a closed decision.
2026-07-16 15:57:12 -07:00
pezkuwichain ec0ec9153f Bridge: lock down execution navigation, predict manual review upfront
Execution screen safety fix: hardware back and the toolbar home button
could navigate away mid-submission (the transfer's own ViewModel scope
gets cancelled on leaving, same class of risk as leaving Swap's execution
screen mid-flight, which that screen has always prevented). Now matches
SwapExecutionFragment exactly - back suppressed, home button hidden, the
only way out is the Done button once the operation has actually resolved.

Bridge previously only found out "this needs manual 3-of-5 review" after
watching the destination balance for up to 90s and giving up - honest, but
slow to tell the user something the input screen's own on-chain checks
already knew before submission. The consent gate checked the automation
key's remaining on-chain allowance but not usdt-bridge's separate hard
per-tx cap (max_single_tx, 50,000 USDT) - a large single swap could read
as "fast" against a freshly-renewed 200,000 allowance while the backend
would still force it to manual review. Added that check
(BridgeMultisigConstants.MAX_SINGLE_TX), forwarded the resulting
prediction through BridgeExecutionPayload.expectManualReview, and added a
new AwaitingManualReview state so the execution screen shows the same
clear message ("needs approval from 3 of 5 signatories, ~2 hours,
t.me/pezkuwidestek") immediately instead of after a false wait -
regardless of whether manual review is needed because the amount itself
is large or because other users' swaps have temporarily used up the
automation key's approval.
2026-07-16 10:23:01 -07:00
pezkuwichain 272921dcdf Match the execution screen's visual polish to the app's own Swap flow
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.
2026-07-15 21:47:32 -07:00
pezkuwichain 3c06ae00e0 Add pre-submit consent gate for amounts exceeding auto-pay approval
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.
2026-07-15 19:46:24 -07:00
pezkuwichain cf8127c8f8 Fix missing imports (launch, getAssetIconOrFallback) from the Bridge split
Dropped while rewriting BridgeViewModel/adding BridgeExecutionViewModel -
first real CI run caught it.
2026-07-15 16:31:44 -07:00
pezkuwichain 52e5645409 Split Bridge into input and dedicated execution screens, matching Swap
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.
2026-07-15 16:12:03 -07:00
pezkuwichain 6e07348695 Bridge: clear entered amount after a successful origin-chain submit
The origin transfer already happened once submitBridgeTransfer's dispatch
result comes back success, so the amount input still holding the just-spent
value made the live balance-vs-amount check flag a false "insufficient
balance" error right next to the real success/waiting state - reading as if
the transfer failed or was retried, when it had already gone through once.
Clearing the field via the existing fillAmountEvent mechanism removes the
stale comparison instead of adding new state.
2026-07-15 09:33:53 -07:00
pezkuwichain 974296704f Fix missing viewModelScope import in BridgeViewModel
androidx.lifecycle.viewModelScope is a KTX extension property - it must be
imported in every file that uses it directly, not just inherited via
BaseViewModel (which imports it for its own use only). CI caught this on
the previous commit's real-submission wiring.
2026-07-15 08:12:22 -07:00
pezkuwichain 437dfff813 Bridge: submit deposit via real submit-and-await execution, not generic Send
swapClicked() used to hand off to the generic Send flow's confirm screen,
which only fire-and-forget submits and pops back immediately regardless of
real dispatch outcome - a real user hit exactly that: tapped confirm, the
screen closed like it succeeded, funds never arrived. Now the bridge builds
its own WeightedAssetTransfer and calls
SendUseCase.performOnChainTransferAndAwaitExecution directly, mirroring the
same real submit-and-await pattern the app's own Swap execution screen
already uses, so Success/Error reflect what actually happened on-chain.
2026-07-15 07:59:35 -07:00
pezkuwichain b51e2ecf58 Add real deposit-wait progress to Bridge screen, reusing the swap timer UX
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.
2026-07-15 06:10:41 -07:00
pezkuwichain f655ef5a33 Fix ktlint: blank line before commented declaration in BridgeMultisigConstants 2026-07-14 22:20:33 -07:00
pezkuwichain c60967e7af Fix ktlint: blank line before commented declaration in BridgeViewModel 2026-07-14 21:50:18 -07:00
pezkuwichain 6c70c91730 Fix Bridge swap destination + add confirmed Kurdish translation
BRIDGE_ADDRESS_GENERIC was still the retired legacy single-key bot's
address (5C5CW7xD...), not the real 3-of-5 multisig custody
(BridgeMultisigConstants.MULTISIG_ADDRESS). Confirmed live: a real user
swap sent there landed at the dead address and was never detected by
usdt-bridge's listener (which only watches the multisig account). Funds
were recovered separately using the still-intact legacy seed; this fixes
the actual destination so future swaps land where the listener watches.

Also added the user-confirmed Kurmancî translation for
bridge_wusdt_to_usdt_blocked (values-ku), replacing the now-stale text left
untouched in the previous commit pending native review.
2026-07-14 21:22:04 -07:00
pezkuwichain a8dc9add24 Replace dead legacy-bot status check with a real per-amount reserve check
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.
2026-07-14 18:57:59 -07:00
pezkuwichain 09b1b37b49 Sync bridge renewal threshold/topup with server-side 40K/200K config
Server-side (pezbridge_bot_config.json, usdt-bridge's bridge_config.json)
was already bumped to a 40,000/200,000 wUSDT renewal threshold/topup this
session, but this app's own BridgeMultisigConstants still had the old
3,000/10,000 values - it construct/checks the exact same on-chain call, so
the mismatch wasn't just a stale display, it meant a signer's app would
consider a 20,000-remaining allowance "fine" while PezbridgeBot was already
paging everyone to renew it.
2026-07-14 16:50:35 -07:00
pezkuwichain 7a2d330a0a Retire DOT-HEZ bridge from the Bridge screen
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.
2026-07-14 14:41:56 -07:00
pezkuwichain be2e1088e5 Merge branch 'feature/btc-native-send' into fix/multisig-first-signer-deep-link
# Conflicts:
#	feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/bridge/BridgeFragment.kt
#	feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/bridge/BridgeViewModel.kt
#	feature-assets/src/main/java/io/novafoundation/nova/feature_assets/presentation/bridge/di/BridgeModule.kt
2026-07-14 07:36:14 -07:00
pezkuwichain 3def96792a Fix Bridge multisig compile errors surfaced by CI
- module(Modules.X) needs substrate_sdk_android's module() extension
  imported explicitly, not just the Module type.
- accountIdIn is a MetaAccount member, not a top-level import.
- submitExtrinsicAndAwaitExecution(...).requireOk() resolves to the
  Result<T>-preserving overload, so wrapping it in runCatching produced
  Result<Result<T>>; unwrap with getOrThrow() first so the T-returning
  overload applies.
2026-07-14 07:29:35 -07:00
pezkuwichain 4941a95ee5 feat(dashboard): collapsible Pezkuwi card, minimal by default
Card now opens in a slim single-line pill showing only Trust Score.
Tapping it expands to the full card (citizen status, world Kurdish
count, referral actions); a chevron in the expanded header collapses
it back. Expand state persists across scroll/recycling within the
session but resets to collapsed on a fresh app launch.
2026-07-14 07:27:01 -07:00
pezkuwichain cfdeff8ab7 Add signatory-only sign button to Bridge screen
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.
2026-07-14 06:59:18 -07:00
pezkuwichain 7401783436 feat: block Bridge swap when send amount exceeds available balance
The Bridge screen let a user type any amount and enabled the Swap
button regardless of what they actually held, unlike the Swap screen
which shows a live "Max: X" and disables on overflow. The confirm-step
ValidationSystem would still catch it before signing, but only after
routing through Send - no immediate feedback on the Bridge screen
itself.

Wires WalletInteractor.assetFlow(chainId, assetId) to the currently
selected origin side (re-subscribed on every direction/pair change),
tracking Asset.transferable - the same field the real transfer
validation checks. Reuses the existing MaxAmountView/MaxAvailableView
widget the Swap screen already uses for the "Max: X" display, and adds
a matching error-bordered state to BridgeAssetInputView. The
"Insufficient balance" string (bridge_insufficient_balance) was
already translated into every locale but never wired to any code.
2026-07-13 12:10:16 -07:00
pezkuwichain e0cd1f5def fix: Bridge cards use AssetIconProvider and displayNameWithAssetStandard
The redesigned Bridge cards resolved asset icons via the chain-icon
helper (asset.icon.asIconOrFallback()), which treats the value as a
ready-to-load URL. Chain.Asset.icon is frequently a bare filename
resolved through AssetIconProvider's base-URL/color-mode logic, so
any asset relying on that path rendered a blank icon (Polkadot Asset
Hub's USDT, and the DOT/HEZ utility assets on the affected side).
Switched to assetIconProvider.getAssetIconOrFallback(asset), the same
path every other asset row in the app uses.

Also switched the card subtitle from chain.name to
chain.displayNameWithAssetStandard(), so Pezkuwi Asset Hub shows its
PEZ-20 token-standard label, matching Send/Receive/the balance list.
2026-07-13 11:43:03 -07:00
pezkuwichain 3b5e15457d fix: remove unused Chain import flagged by ktlint
The type is only used via inference (chainRegistry.getChain() return),
never referenced explicitly.
2026-07-13 09:33:29 -07:00
pezkuwichain 398f2fc996 Redesign Bridge screen UI to match Swap's modern card layout
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.
2026-07-13 09:28:30 -07:00
pezkuwichain cf02896a58 fix: apply the chain/asset-standard label to the main balance list too
The Send/Receive/etc. network picker (NetworkFlowViewModel) already showed
"Ethereum (ERC-20)"/"Tron (TRC-20)" for a multi-chain token's per-chain rows,
but the main Assets dashboard's own expandable per-token breakdown (tap a
token like USDT to see every chain it exists on) is a completely separate
code path (TokenAssetMappers/TokenAssetViewHolder) that still showed a bare
chain name - found via a real device screenshot of that specific screen.

Moved the shared display-name-with-label logic to a public extension
(Chain.displayNameWithAssetStandard(), runtime/ext/ChainExt.kt) so both
screens build the exact same string instead of duplicating (and now
diverging) the same logic twice.
2026-07-11 14:07:59 -07:00
pezkuwichain e055e1a84c feat: order and label per-chain token breakdown by ecosystem + standard
The per-chain list shown when picking an action (Send/Receive/Swap/Buy/Sell/
Gift) for a token that exists on multiple chains (e.g. USDT) now orders
Ethereum and Tron right after the existing Pezkuwi/Polkadot/Kusama priority
chains instead of falling into the alphabetical "everything else" bucket,
and appends a token-standard label - "(PEZ-20)"/"(ERC-20)"/"(TRC-20)" - to
disambiguate which issuance this is, since a bare chain name alone doesn't
convey that.

The label is intentionally chain-specific, not derived from Chain.Asset.Type,
since every Statemine-type chain (Polkadot AH, Kusama AH, Pezkuwi AH) shares
the same asset type but only Pezkuwi AH's issuance needs the PEZ-20 label.
2026-07-11 06:44:35 -07:00
pezkuwichain 7f071f4821 debug: log Tron chain arrival + gate evaluation in BalancesUpdateSystem
TRX is completely absent from the Assets list even for a brand-new
wallet on a completely fresh install - ruled out per-account backfill
(fresh wallet correctly derives tronAddress) and stale per-device chain
state (fresh install, no carried-over connectionState). Need to see
empirically whether the Tron chain even reaches currentChains at all,
and if so, which of hasAccountIn/connectionState.isDisabled gates it.
2026-07-10 17:25:31 -07:00
pezkuwichain c5174d0ccf fix: NativeAssetBalance uses typed subscribe DSL, not raw key subscription
Root cause found via 4 rounds of CI diagnostics: HEZ (native asset) on
Pezkuwi Asset Hub was correctly present+enabled in the Chain domain model,
correctly dispatched to NativeAssetBalance, and its System.Account storage
key was correctly computed - but the raw subscriptionBuilder.subscribe(key)
call never actually reached the RPC connection, with zero exceptions and
zero data, while the chain's 5 other assets (all statemine-type, all using
the same SharedRequestsBuilder) synced fine. The same NativeAssetBalance
code worked correctly for every OTHER native asset on every OTHER chain
tested, ruling out a generic bug in the class.

Switched startSyncingBalance() to the typed remoteStorage.subscribe { }
DSL (metadata.system.account.observeWithRaw) - the same mechanism this
class's own subscribeAccountBalanceUpdatePoint() and PooledBalanceUpdater/
BalanceLocksUpdater already use successfully on the same busy chain
connection, instead of the raw subscriptionBuilder.subscribe(key) call
that appears to silently drop registration in that specific configuration.

Also removes the diagnostic logging added during the investigation
(BalancesUpdateSystem's per-chain balancesSync trace, FullSyncPaymentUpdater's
per-chain asset dump) - kept the one genuinely valuable permanent addition,
the "listenForUpdates() threw synchronously" error log for a previously
silent failure mode.
2026-07-09 11:53:35 -07:00
pezkuwichain 688a23ba6b fix: log and stop swallowing synchronous listenForUpdates() failures; retry NDK download in CI
BalancesUpdateSystem.launchChainUpdaters() wrapped updater.listenForUpdates() in a
try/catch that discarded synchronous exceptions with zero logging - a silent failure
point that could explain a chain's balances never syncing with no trace in logcat.

Also add a full-architecture instrumented test that persists a real watch-only
MetaAccount and polls AssetDao through the actual BalancesUpdateSystem pipeline,
instead of bypassing it like the existing BalancesIntegrationTest does.
2026-07-09 07:52:15 -07:00
pezkuwichain 74728a8477 feat(dashboard): collapsible Pezkuwi card, minimal by default
Card now opens in a slim single-line pill showing only Trust Score.
Tapping it expands to the full card (citizen status, world Kurdish
count, referral actions); a chevron in the expanded header collapses
it back. Expand state persists across scroll/recycling within the
session but resets to collapsed on a fresh app launch.
2026-07-08 10:18:04 -07:00
pezkuwichain 85bde7e448 Redesign: dashboard card + action row (v1.1.1) (#6)
* redesign(dashboard): brand-book restyle of Pezkuwi dashboard card

Match the brand book / handoff screenshot:
- bg_pezkuwi_dashboard: blue/indigo gradient -> frosted dark-navy surface
  (#1C1F2E) with a 1px periwinkle hairline, 20dp corners.
- item_pezkuwi_dashboard: replace hardcoded non-brand colors —
  trust value amber #FFD54F -> zer #FDB813; welati count -> positive #2FC864;
  Approve/start buttons Material-green -> kesk #009639; Sign red -> sor #E2231A;
  Share button yellow #FDD835 -> frosted-navy secondary #2A2F45 (white text);
  blue-grey text -> brand white tokens. Pill-er 12dp button corners.

* redesign(actions): circular action buttons (primary green Send + dark rest)

Match the brand-book screenshot: the balance action row (Send/Receive/Swap/
Buy/Gift) becomes circular icon buttons with a label below — Send on a kesk
green circle, the rest on frosted-dark circles. IDs preserved (used only for
click + isEnabled), so AssetsTotalBalanceView keeps working.

* redesign(dashboard): pro-level Pezkuwi card layout

Rework the card to match the brand-book screenshot: header row with a small
Newroz-flame icon + title/roles on the left and the citizen count on the right;
trust score row; full-height (48dp) pill-er (14dp) action buttons — Approve
(kesk, bold), Sign (sor), Share (frosted-dark with hairline). Adds the small
ic_nevroz_flame icon.

* release: bump versionName to 1.1.1 (dashboard & action-row redesign)
2026-06-14 23:34:49 -07:00
pezkuwichain 8d150266fb fix: detect on-chain dispatch errors for citizenship and staking extrinsics
Switch from submitExtrinsic (fire-and-forget) to submitExtrinsicAndAwaitExecution
which waits for block inclusion and checks ExtrinsicFailed events. Previously the
app showed success even when pallet-level errors occurred (e.g. ReferrerNotCitizen,
AlreadyExists). Now dispatch errors are properly surfaced to the user.
2026-03-09 02:46:49 +03:00
pezkuwichain 84d0f39f8a fix: replace setFragmentResult with interface callback for citizenship dismiss
setFragmentResult API not available in this project. Use CitizenshipDismissListener
interface instead for parent-child fragment communication.
2026-03-08 19:06:21 +03:00
pezkuwichain 138c0199c9 fix: auto-refresh Pezkuwi dashboard card after actions
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.
2026-03-08 17:32:40 +03:00
pezkuwichain ba057617d3 fix: ktlint multiline-if-else braces in PezkuwiDashboardAdapter 2026-03-05 02:40:08 +03:00
pezkuwichain 91f2b5d254 feat: add Start Tracking button for StakingScore on dashboard
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.
2026-03-05 02:33:31 +03:00
pezkuwichain 81b0491691 fix: use safe call for nullable String in ifBlank 2026-03-01 22:22:41 +03:00
pezkuwichain 5705d0d578 fix: resolve citizenship bottom sheet not opening on button tap
Event(null) was swallowed by EventObserver's ?.let pattern, preventing
the CitizenshipBottomSheet from opening when tapping dashboard buttons.
Changed to Event("") with ifBlank conversion to preserve null referrer
semantics while ensuring the observer callback fires.
2026-03-01 22:08:19 +03:00
pezkuwichain d33a0a6289 fix: use https telegram link in dashboard share referral button 2026-02-28 04:22:16 +03:00
pezkuwichain 5771fbc10b fix: use https telegram link instead of custom scheme for sharing
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.
2026-02-28 02:40:06 +03:00
pezkuwichain 66be33c43e fix: disable referrer input when pre-filled from deep link
Prevent user from editing or clearing the referrer address when it
comes from a referral deep link to ensure correct on-chain submission.
2026-02-28 02:00:08 +03:00
pezkuwichain 33c6559a41 fix: connect referral link to blockchain via deep link handler
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.
2026-02-27 22:11:34 +03:00
pezkuwichain 894e5dac22 fix: prevent staking dashboard hang when exposure flag not cached
isPagedExposuresUsed() called storageCache.getEntry() which suspends
forever if the entry doesn't exist. The flag is only written by
ValidatorExposureUpdater (staking detail flow), so the dashboard
would hang indefinitely waiting for it.

Check cache first with isFullKeyInCache() and default to paged
exposures when the flag is absent. Also remove debug log statements.
2026-02-27 13:41:26 +03:00
pezkuwichain b9fadbe6da fix: remove unused imports to pass ktlint 2026-02-22 05:15:10 +03:00
pezkuwichain 771c9c8877 feat: in-app citizenship application with referral system
- 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
2026-02-22 05:04:43 +03:00
pezkuwichain 37829e30f0 style: fix ktlint no-multi-spaces violations in BridgeViewModel 2026-02-21 18:46:37 +03:00
pezkuwichain 359cfb1eb3 fix: correct Welati counter URL to telegram.pezkiwi.app 2026-02-18 07:01:20 +03:00
pezkuwichain 326aa869ed fix: update Welati counter URL to telegram.pezkuwi.app/kurds 2026-02-18 06:58:09 +03:00
pezkuwichain 533aa9e831 feat: replace dashboard image with Welati counter (Hejmara Kurd Le Cihane)
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.
2026-02-18 06:52:01 +03:00