Commit Graph

28 Commits

Author SHA1 Message Date
pezkuwichain d0db0a54f7 Update launcher icon to the latest goat badge design
Source: pwap-web/shared/images/pezWallet - white_background_last.png -
a refined round-badge design (wallet flap detail added). Same crop+resize
process as the previous icon passes, matched to the exact scale/position
already in use so only the artwork changes.
2026-07-15 22:19:02 -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 14c8b3c27c Change launcher icon badge background from black to white
Source: pwap-web/shared/images/pezWallet - white_background.png, same
goat artwork as the current icon with the badge recolored. Cropped to
its badge bounds and resized to match the exact scale/position the
black version already used (from the shrink+center fix), so only the
color changes, not the composition. Regenerated every foreground/
legacy/round slot across all densities and both build flavors, plus
the separate solid-fill adaptive background layer so it matches the
new badge color instead of showing dark corners through the mask.
2026-07-15 12:08:04 -07:00
pezkuwichain a5454b38f0 Fix icon: shrink+center the goat artwork instead of edge-to-edge fill
The horns were touching the canvas corners - looked cramped and got cropped
tightly by circular/squircle adaptive-icon masks on real devices. Now
scaled to 62% of the canvas and centered on transparent padding, matching
how other apps' icons actually look on a real home screen.
2026-07-15 05:14:22 -07:00
pezkuwichain ae2754d7a3 Update launcher icon to the cleaner goat-head logo (v2)
Source updated in pwap-web/shared/images/pezWallet.png - simpler design,
no border/text baked in this time. Regenerated the same way as the first
icon pass: padded to square, resized per density into every existing slot.
2026-07-14 21:21:44 -07:00
pezkuwichain 6d27949cbf Replace launcher icon with the new goat-head PezkuwiWallet brand logo
Source: pwap-web/shared/images/pezWallet.png. Padded to square (source is
979x1053, corners already fully transparent so the padding is seamless),
then resized per density into every existing icon slot - legacy ic_launcher/
ic_launcher_round and the adaptive foreground layer all use the same full
graphic, matching how the previous icon was already structured; the solid
dark adaptive background layer is untouched since it's still a compatible
fill color for the new logo.
2026-07-14 18:44:28 -07:00
pezkuwichain 2ac8005c10 Skip (not fail) BalancesIntegrationTest when a chain's RPC is unreachable
Aleph Zero's only configured public node (wss://ws.azero.dev) is
currently down (confirmed via direct WebSocket handshake - real,
external, isolated outage on their side, chain itself is healthy and
active). No free/working alternative public RPC was found to add as
failover. Rather than hard-fail CI on an external dependency neither
our code nor config controls, convert connectivity-class exceptions
(TimeoutCancellationException, directly or wrapped) into a JUnit
assumption-skip - this mirrors how production balance-sync code
already isolates per-chain RPC failures instead of treating them as
hard errors. A real bug (bad decoding, wrong assertion, etc.) still
fails the test exactly as before.
2026-07-14 09:52:45 -07:00
pezkuwichain 0eab8a8ea2 fix: TRC-20 balance always read 0 for never-activated holders
Trc20AssetBalance/RealTronGridApi.fetchTrc20Balance() read through
TronGrid's /v1/accounts/{address} REST endpoint - but a TRC-20 balance
lives entirely in the token contract's own storage, not the holder's
Account object. An address that has only ever received TRC-20 tokens
(never native TRX, never otherwise "activated" on-chain) has no Account
object at all, so /v1/accounts silently returns `data: []` for it
regardless of its real token balance, and the old code treated that the
same as a genuinely empty/zero account.

Found via a live test: a real wallet received 5 USDT-TRC20, the exchange
confirmed the transfer complete on-chain, but the app kept showing 0.
Independently verified live: /v1/accounts returned empty for the address,
while a direct balanceOf(address) contract call (triggerconstantcontract)
correctly returned 5000000.

Rewrote fetchTrc20Balance() to read via balanceOf(address) instead -
reuses the existing triggerConstantContract() call already used for TRC-20
transfer fee estimation, plus a new encodeBalanceOfParameters() ABI helper
alongside the existing transfer() one. Added a regression test pinned to
this exact real address/balance so this can't silently regress again.
2026-07-11 15:21:24 -07:00
pezkuwichain 9105560a36 test: verify Ethereum USDT sync too, closing the third originally-reported gap
Adds a real EVM address for the Founder account - derived via standard
BIP44 (m/44'/60'/0'/0/0) from the same already-verified mnemonic used
for the substrate address, since no dedicated founder EVM wallet record
exists anywhere. Ethereum's USDT-ERC20 assetId isn't a fixed integer
like Substrate assets (EvmAssetsSyncService hashes the contract address
at sync time), so it's resolved dynamically via ChainAssetDao instead
of hardcoded in the JSON fixture.

This closes the loop on all 3 originally-reported symptoms from this
investigation: Tron disabled (fixed, unaffected by any revert), Pezkuwi
tokens missing (fixed - ordering bug), USDT on Polkadot AH/Ethereum
missing (Polkadot AH already covered, Ethereum added here). Ethereum
ERC20 sync uses an entirely separate mechanism (EthereumRequestsAggregator,
not Substrate's StorageSubscriptionMultiplexer) so it was likely never
actually broken by anything this session touched - this verifies that
directly instead of assuming it from code reading.
2026-07-09 19:53:32 -07:00
pezkuwichain 01effc26c9 fix: retry TronGrid 429s instead of just tolerating the flake
Public TronGrid rate-limits aggressively, and this test now runs on
every PR (plus its own 8h schedule) - a bare 429 was failing runs for
a transient, infrastructure reason unrelated to code correctness. Add
exponential backoff retry instead of treating it as an accepted flake.

Also required-status-check balances_test.yml's run-tests job on main
now that both this and the wallet-utils phantom-asset fix are confirmed
clean - it was deliberately left optional until proven, per "don't
promise gates you haven't verified."
2026-07-09 17:29:55 -07:00
pezkuwichain 593fedcdd4 fix: avoid suspend call inside non-inline removeAll(predicate)
removeAll { assetDao.getAsset(...) } failed to compile ("Suspension
functions can only be called within coroutine body"). filter{} is
unambiguously inline and safe for a suspend call inside a suspend
function; pair it with the plain Collection-based removeAll(elements)
overload instead, which takes no lambda at all.
2026-07-09 12:34:02 -07:00
pezkuwichain 72a881c059 test: expand full-architecture test to cover the whole Pezkuwi ecosystem
Was HEZ-on-Asset-Hub-only. Now data-driven from wallet-utils' new
pezkuwi_assets_for_testBalance.json (TEST_ASSETS_URL), asserting every
asset - HEZ/PEZ/USDT/DOT/ETH/BTC across Pezkuwi's 3 chains - gets an
assets DB row written via a single shared BalancesUpdateSystem run, not
just one asset on one chain. Failure message lists exactly which assets
never synced, by name and chain.
2026-07-09 12:08:27 -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 2bb8a4e3d0 fix: actually start BalancesUpdateSystem in the full-architecture test
First run of this test produced zero BalancesDiag output at all - not even a
single balancesSync() call for any chain. Root cause: BalancesUpdateSystem.start()
is a cold flow only ever collected by RootInteractor, which is wired to the root
Activity/ViewModel lifecycle. This bare instrumented test never launches that
Activity, so the pipeline was never started - the test's own timeout, not the
production bug, explained the failure. Now collect the same AssetsFeatureApi.
updateSystem instance directly instead of relying on app UI lifecycle.
2026-07-09 09:15:28 -07:00
pezkuwichain 4cf6cef68d fix: add missing scalars converter dependency for androidTest
TronBalancesIntegrationTest.kt uses ScalarsConverterFactory but nothing in
app/build.gradle declared it, so the app module's androidTest compilation
failed with "Unresolved reference 'scalars'" - this was never caught before
now because the emulator balances_test.yml workflow only runs on a schedule/
manual dispatch, not on every push.
2026-07-09 08:16:32 -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 57dbe77db3 test: add Tron balance integration test
Tron is a REST API (TronGrid), not a Substrate runtime, so it never goes
through BalancesIntegrationTest's chainRegistry-based mechanism at all -
it had zero CI coverage. This exercises the exact TronGridApi the
production app uses for balance reads, via a standalone Retrofit client
(TronGridApi isn't exposed through a public feature API for tests to
reach through the DI graph).

Test account is the mainnet Founder's Tron address, verified live via
TronGrid's public API on 2026-07-09: 3,925.23 TRX native + 625,213.92
USDT-TRC20 - substantial real balances, not a guessed or empty account.
2026-07-09 04:01:00 -07:00
pezkuwichain 7dea79dbee fix: use arm64-v8a emulator image on macos-14 runners (#11)
* fix: use arm64-v8a emulator image on macos-14 runners

The "Run balances tests" job has been failing on every scheduled run
for weeks: the emulator requested an x86 system image while
macos-14 GitHub-hosted runners are Apple Silicon (aarch64) - QEMU2
refuses to boot a mismatched-architecture image ("Avd's CPU
Architecture 'x86' is not supported by the QEMU2 emulator on
aarch64 host"), so every adb command against the never-booted
emulator failed with "device not found" for the full 10-minute
boot timeout on every run.

* fix(ci): run balances-test emulator on ubuntu-latest with KVM instead of macos-14

macos-14 (Apple Silicon) GitHub-hosted runners don't expose nested
virtualization to guests, so the Android emulator's HVF backend fails
with HV_UNSUPPORTED and the job times out waiting for boot - this
affects both x86 and arm64-v8a system images, so the arch: arm64-v8a
change alone wasn't sufficient. macos-13 (which previously supported
this via HAXM) was retired by GitHub.

Linux hosted runners support KVM-accelerated emulators once the kvm
device's udev permissions are relaxed, which is the documented setup
for reactivecircus/android-emulator-runner and also faster/cheaper
than macOS runners.

* fix(ci): build instrumentialTest androidTest APK to match AllureAndroidJUnitRunner

run_balances_test.sh has always targeted
io.novafoundation.nova.debug.test/io.qameta.allure.android.runners.AllureAndroidJUnitRunner,
but android_build.yml's "Build debug tests" step built the plain
debug variant's androidTest APK, whose manifest declares the module
default runner (androidx.test.runner.AndroidJUnitRunner, from
allmodules.gradle) - AllureAndroidJUnitRunner is only wired via
testInstrumentationRunner on the dedicated instrumentialTest build
type (app/build.gradle), which was apparently created for exactly
this purpose but never actually wired into CI. Result:
INSTRUMENTATION_FAILED as soon as the emulator boot issue was fixed
and this step was reached for the first time.

instrumentialTest initWith buildTypes.debug (same applicationIdSuffix
'.debug', same default debug signing), so it installs under the same
package next to the already-built debug app APK - only the
androidTest APK's build type needs to change, not the main app build.

Only balances_test.yml sets build-debug-tests: true, so this doesn't
affect any other android_build.yml caller (pull_request.yml has it
explicitly disabled with its own separate pre-existing TODO).

* test: temporarily point android_build.yml ref at this branch for verification

TEMPORARY - reusable workflow calls (uses: ...@ref) pin to that ref's
copy regardless of the caller's branch, so android_build.yml's fix
never actually ran in the previous verification attempts even though
it was committed to this branch. Must revert to @main before merging
this PR, once android_build.yml's changes are on main.

* fix(ci): declare AllureAndroidJUnitRunner on debug build type, not instrumentialTest

AGP only ever compiles one androidTest APK per module, tied to
android.testBuildType (default "debug", never overridden in this
project) - so a testInstrumentationRunner override on any other build
type, including instrumentialTest, is unreachable regardless of which
gradle task or main-app variant is used. That's why the previous
attempt (assembleInstrumentialTestAndroidTest) failed outright: no
such task exists, since androidTest is only ever generated for
testBuildType.

Reverts the previous commit's task/path changes back to
assembleDebugAndroidTest / app/androidTest/debug/..., and instead
moves the testInstrumentationRunner override onto the debug build
type itself, which is what androidTest actually compiles against and
what run_balances_test.sh has always targeted. Also drops the dead
override from instrumentialTest now that it's confirmed non-functional
there.

* debug(ci): dump pm list instrumentation before running balances test

Diagnostic only - the previous fix (testInstrumentationRunner moved
to the debug build type's defaultConfig) still hit the identical
INSTRUMENTATION_FAILED for AllureAndroidJUnitRunner even though both
APKs now install successfully with the corrected paths. Need to see
what PackageManager actually registered for the installed test APK
rather than keep guessing from Gradle DSL evaluation-order theory -
allmodules.gradle's subprojects{} block also sets
testInstrumentationRunner on every module including app, and it's not
yet confirmed which assignment wins.

* fix(ci): use current io.pezkuwichain.wallet package instead of stale upstream name

Diagnostic (pm list instrumentation) confirmed the real, final root
cause: AllureAndroidJUnitRunner IS correctly registered on-device
after the previous fix, but under the app's real applicationId
(io.pezkuwichain.wallet, set in build.gradle since the Pezkuwi rebrand)
- not the pre-rebrand upstream Nova Wallet package
(io.novafoundation.nova) these scripts still hardcoded. Every previous
INSTRUMENTATION_FAILED was simply am instrument targeting a package
that was never installed.

Also fixes the identical stale reference in run_instrumental_tests.sh
(currently unused by any workflow, but has the same bug).

The BalancesIntegrationTest class's own Kotlin package
(io.novafoundation.nova.balances) is untouched - that's the test
class's real source package on disk, unrelated to the app's
applicationId, and was never part of the bug.

* fix(ci): bound run-tests to 25min and unbuffer python output

Latest verification run hung for 1h15m+ inside am instrument with
zero visible progress - had to be cancelled manually. Post-mortem:
Python's stdout is fully buffered (not line-buffered) when piped
under GitHub Actions' `run:`, so the script's own 5s heartbeat prints
(explicitly there to avoid CI's inactivity-based cancellation) never
actually reached the log until the buffer filled near the very end,
making the run look identical to a genuine hang for its entire
duration with no way to tell what BalancesIntegrationTest was doing.

- timeout-minutes: 25 on run-tests bounds any future hang to a fixed,
  reasonable ceiling instead of requiring a manual cancel after an
  hour+.
- python -u unbuffers stdout so the next run's logs show real-time
  heartbeat/output, giving actual visibility into where a hang (or
  slow chain RPC) occurs instead of a silent multi-hour gap.

Root cause of the hang itself is still open - this only makes it
diagnosable and bounds its cost.

* fix: skip WSS ChainConnection setup for Tron-based chains

Real root cause of the 1h15m+ hang in the previous verification run
(had to be cancelled manually): ChainRegistry registers all chains
sequentially (diff.newOrUpdated.forEach { registerChain(it) }), and
registerConnection() unconditionally called
connectionPool.setupConnection(chain), which creates a ChainConnection
backed by a WSS-only SocketService - for every chain, with no check
for chain type. Tron's node (https://api.trongrid.io) is a plain REST
API with no WebSocket support, so this connection attempt just hangs
forever with no timeout, and since registration is sequential and
Pezkuwi chains (including Tron) are ordered first in the merged chain
list, every chain after it in the list never finishes registering
either - including all the third-party chains BalancesIntegrationTest
actually exercises.

This isn't just a test problem: any real user with the Tron chain
enabled would hit the same registry-wide freeze during chain sync.

Tron balance/transfer operations already go through their own
TronGridApi REST client (built in the Phase 1/2 Tron work),
independent of ConnectionPool/ChainConnection - confirmed nothing else
reads chainRegistry.getConnection() for a Tron chain id - so skipping
ChainConnection setup entirely for isTronBased chains is safe.

* debug(ci): stream live logcat during test run

Diagnostic only. Previous fix (skip WSS ChainConnection for
isTronBased chains) did NOT resolve the hang - identical symptom
(silent for the full 25min timeout, just heartbeats, nothing from the
actual test process). Need real device-side visibility into what's
actually happening (network calls, coroutine timeouts, ANRs) instead
of guessing blind from am instrument's own stdout/stderr, which stays
completely silent until the process exits.

* debug(ci): SIGQUIT thread dump 3min into a hung run, bump logcat to debug level

Previous diagnostic (live logcat at info level) showed the app staying
genuinely alive (GC cycles, system chatter) but produced zero signal
from the test itself after the initial successful chains.json fetch -
no WSS/DB/coroutine activity visible, likely because relevant logging
is below info level. Static code reading (ChainConnection.setup(),
ChainSyncService.syncUp(), ChainFetcher) hasn't turned up an obvious
blocking call, and this exact hang predates this session by at least
a month (zero successes in the last 100 scheduled runs going back to
2026-06-09) - so it's a real, previously-latent bug in the app/test
itself, never previously reached because every earlier run failed at
an earlier CI-infra stage.

kill -3 on the app process forces ART to dump every thread's Java
stack trace to logcat (the standard ANR-diagnosis technique) - this
should show exactly which coroutine/thread is parked and where,
instead of continuing to guess from log filtering.

* fix(ci): bump run-tests timeout to 90min, drop now-unneeded SIGQUIT diagnostic

With the chain blacklist fixed, the previous run genuinely started
executing the 160-case parameterized test suite (visible TestRunner
started/finished events for real chains) instead of hanging silently
- first time this has happened in this entire investigation.

It still hit the 25min ceiling: each test case has an explicit
withTimeout(80.seconds), and several chains that aren't fully dead
(so not blacklisted) but are slow/unresponsive burn the full 80s
before failing. With 160 total test cases, the worst-case aggregate
easily exceeds 25 minutes even with zero actual hangs - so the
timeout needs to be realistic for the test's own design, not just
long enough to catch a true infinite hang. 90min matches
android_build.yml's existing precedent for this project's CI jobs.

The SIGQUIT-after-3-minutes diagnostic added earlier is now
counterproductive noise: any healthy run legitimately takes far
longer than 3 minutes to get through 160 cases, so it would fire on
every run rather than only genuine hangs. Removed now that its actual
purpose (finding the real hang) is done - the blacklist was the
answer, not something a thread dump would have caught anyway (dead
sockets, not deadlocked application code).

* chore: revert temporary android_build.yml ref pin back to @main

Was pointed at this branch only to verify android_build.yml's own
fixes actually took effect during iteration (reusable workflow calls
resolve against the ref they're pinned to, not the caller's branch).
android_build.yml is now byte-identical to main (the wrong task-name
attempt was fully reverted in an earlier commit), so this is a no-op
functionally - just restoring the correct long-term reference before
merge.
2026-07-08 06:36:31 -07:00
pezkuwichain 22422c85da Redesign: brand-book alignment + forbidden-color purge (v1.1.0) (#3)
* redesign(colors): purge forbidden magenta/purple from palette

Brand book permits only the Kurdistan palette (kesk/sor/zer/fire) + navy.
Replace the four Nova-legacy violations in common colors.xml (names preserved,
so no references break):
- crowdloan_banner_gradient_start  #BD387F -> #009639 (kesk)
- networks_banner_gradient_end     #661D78 -> #017A2F (kesk-700)
- chip_on_card_background           #443679 -> #3D999EC7 (frosted periwinkle)
- button_wallet_connect_background  #353D67 -> #1F2A4D (neutral navy)

Repo-wide grep confirmed no other hardcoded magenta/purple literals or
purple/pink-named resources remain.

* redesign(type): adopt brand fonts (Space Grotesk / Plus Jakarta Sans / JetBrains Mono)

Brand book typography. Add OFL static fonts under common/res/font and repoint
the theme font attrs (consumed app-wide via ?attr/font* in styles.xml):
- fontRegular     -> Plus Jakarta Sans Regular (body/UI)
- fontSemiBold    -> Plus Jakarta Sans SemiBold
- fontBold/ExtraBold -> Space Grotesk Bold (display: balances, titles)
- fontExtraLight  -> Plus Jakarta Sans Light
- Monospace text appearance (addresses/hashes) -> JetBrains Mono

Static TTFs chosen (minSdk 24 < variable-font API 26). All five verified to
cover Turkish + Kurdish Kurmancî glyphs (ş ğ ı İ ê î û ç …).

* redesign(splash): replace map+wordmark logo with Newroz flame brand mark

The first-launch splash logo (ic_loading_screen_logo) showed a Kurdistan map
with a baked-in wordmark. Per the brand book the mark is the Newroz flame.
Rasterized assets/nevroz-fire-flame.svg into the existing 6 density slots
(same pixel dimensions = drop-in, no bg_splash.xml change, transparent WebP so
it composites cleanly over the splash background).

* redesign(onboarding): welcome hero -> Global United States of Pezkuwi

Replace the legacy onboarding hero (ic_create_wallet_background, whose six
density PNGs had inconsistent broken dimensions) with the brand 'Global United
States of Pezkuwi' infographic. Consolidate to a single high-res WebP in
drawable-nodpi (1408x768, 204K vs 1.75MB PNG) and switch the welcome ImageView
scaleType centerCrop -> fitCenter so it shows full and uncropped above the
CTA buttons, per the brand book.

* redesign(assets): purge magenta/purple from raster illustrations

colors.xml only covers named colors; these raster drawables still carried
forbidden magenta/purple/pink pixels. Selectively rotate the 255-350 deg hue
band (purple-magenta-pink) toward kesk green/teal across all densities,
preserving gradients, shapes and the on-brand blues:
- ic_pink_siri, ic_networks_banner_image, ic_no_added_networks,
  ic_import_option_hardware, tinder_gov (6 densities each).
Third-party ic_powered_by_oak (OAK Network trademark) left untouched.
crowdloan_banner_image is being handled separately.

* redesign(assets): de-pink crowdloan banner across all densities

The crowdloan banner's magenta sphere was recolored to brand sor red (xxxhdpi).
Propagate that fix to the other five densities by downscaling the corrected
xxxhdpi master (LANCZOS), so every device shows the same brand-clean banner.
Pink-pixel scan now 0% on all six variants.

* chore: remove pre-production debug code (release-blocker)

CHANGELOG_PEZKUWI listed debug code to strip before production; two items were
still live:
- FeeLoaderV2Provider: the fee-retry dialog showed a raw "DEBUG: <err> | Runtime:
  <diagnostics>" string to users -> reverted to the localized resource string and
  dropped the diagnostics lookup.
- RuntimeFactory: removed the companion lastDiagnostics field and its assignment
  (plus the now-dangling diagnostic vars), and the matching log line in the
  PezkuwiLiveTransferTest androidTest.
Items #3-#6 were already clean. Repo now has no 'DEBUG:' literals or
lastDiagnostics references. CHANGELOG marked cleaned.

* docs: add BRAND.md — enforceable wallet brand rules

Kurdistan-only palette (no pink/magenta/purple), brand fonts, Newroz flame mark,
a PR brand checklist with a raster pink-scan snippet, the third-party-logo
exception, and the Apache-2.0 attribution rule (keep LICENSE/NOTICE). Points to
the canonical brand book at wiki.pezkuwichain.io/brand.

* release: bump versionName to 1.1.0 (brand-book UI redesign)

Live Play version is 1.0.4; minor bump for the UI redesign. versionCode stays
CI-managed (CI_BUILD_ID). Add the v1.1.0 entry to CHANGELOG_PEZKUWI.
2026-06-14 22:20:33 -07:00
pezkuwichain 817ce246b4 fix: remove trailing blank lines before closing braces (ktlint) 2026-04-20 16:57:22 +03:00
pezkuwichain f5b38eed8c chore: remove Branch.io SDK and route deep links through own domain
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.
2026-03-23 22:59:05 +03:00
pezkuwichain 28d0391d72 fix: store native libs uncompressed with 16KB zip alignment
Set jniLibs.useLegacyPackaging = false to ensure .so files are stored
uncompressed and 16KB-aligned within the AAB, as required by Google Play
for Android 15+ compatibility.
2026-03-14 19:50:06 +03:00
pezkuwichain 64d727dd21 fix: 16KB page alignment for all native libraries
- Rebuild renderscript-toolkit.aar from source with NDK 27 and 16KB alignment
- Rebuild libsr25519java.so from substrate-sdk source with 16KB alignment
- Realign libsqlcipher.so ELF segments to 16KB (preserves JNI API compatibility)
- Add jniLibs overrides for sr25519java and sqlcipher to replace AAR versions
- All native .so files now have 0x4000 (16KB) LOAD segment alignment
2026-03-14 18:35:15 +03:00
pezkuwichain c30cdf2411 build: add native debug symbols for releaseMarket 2026-02-24 18:20:18 +03:00
pezkuwichain 9c7bb7c6e9 Prepare for Play Store release: simplify dashboard, clean debug logs
- Simplify dashboard card: remove referral/staking/perwerde fields (not yet on-chain), keep roles + trust score + action button
- Remove all debug Log.d/e/w calls added during development (PEZ_STAKE, RuntimeFactory, ExtrinsicBuilder, etc.)
- Change Play Store track from beta to production
- Add release notes (whatsnew-en-US)
2026-02-17 06:13:59 +03:00
pezkuwichain 921e6de224 prepare release: staking config, proguard fixes, icons and build cleanup
- Add subquery endpoints for staking-rewards, history, staking APIs
- Add identityChain, stakingWiki, pushSupport to chain config
- Remove versionNameSuffix/applicationIdSuffix from releaseMarket build
- Fix privacy/terms URLs to use .html extension
- Strengthen proguard rules for Retrofit, SR25519, Substrate SDK,
  WalletConnect, Google Drive, Navigation and crypto classes
- Update launcher icons for debug and release variants
2026-02-13 06:45:30 +03:00
pezkuwichain ec250adb07 fix: revert incompatible dependency updates, keep security improvements
- Reverted Navigation to 2.3.1 (2.7.7 has breaking API changes)
- Reverted Lifecycle to 2.2.0 (2.7.0 has breaking API changes)
- Reverted BouncyCastle to 1.70/jdk15on (1.77/jdk18on causes conflicts)
- Kept: OkHttp 4.12.0, Gson 2.10.1, ConstraintLayout 2.1.4
- Kept: minifyEnabled=true, ProGuard rules, Branch.io security
2026-02-12 05:30:22 +03:00
pezkuwichain a294aa1a6b Initial commit: Pezkuwi Wallet Android
Security hardened release:
- Code obfuscation enabled (minifyEnabled=true, shrinkResources=true)
- Sensitive files excluded (google-services.json, keystores)
- Branch.io key moved to BuildConfig placeholder
- Updated dependencies: OkHttp 4.12.0, Gson 2.10.1, BouncyCastle 1.77
- Comprehensive ProGuard rules for crypto wallet
- Navigation 2.7.7, Lifecycle 2.7.0, ConstraintLayout 2.1.4
2026-02-12 05:19:41 +03:00