4 Commits

Author SHA1 Message Date
pezkuwichain c4fe2df923 fix(build): declare resource-task deps for google-services bind task
bindDevelopGithubGoogleServicesToRelease writes into src/develop, which
generate/mergeDevelopResources read — Gradle 8.9 fails on the implicit
dependency. Add generate/mergeResources to the bind task's dependents
(null-safe via findByName).
2026-06-13 09:12:46 -07:00
pezkuwichain 4361230c47 fix(build): bind production google-services to develop variant
develop now uses the base io.pezkuwichain.wallet applicationId, whose
google-services client is in the production google-services.json (the DEV
google-services.json only has a .debug client). Extend the release-binding
task to copy src/release/google-services.json into src/develop so
processDevelopGoogleServices finds a matching client.
2026-06-13 08:13:22 -07:00
pezkuwichain 84978e147e fix(build): develop variant uses base applicationId io.pezkuwichain.wallet
The develop build type appended a '.dev' applicationIdSuffix, producing
io.pezkuwichain.wallet.dev, which has no matching client in the
google-services.json and broke every PR/develop build at
processDevelopGoogleServices. Drop the suffix so develop uses the base
io.pezkuwichain.wallet identity (keeps the -develop versionName suffix).
2026-06-13 07:29:57 -07:00
pezkuwichain 959bfa6b0d feat(assets): PEZ-20 badge on PEZ & USDT in token list
Show a small PEZ-20 pill next to PEZ and USDT (wUSDT) token rows in the
main balance list. These are fungible assets on Pezkuwi Asset Hub — the
PEZ-20 token standard.

- item_token_asset.xml: add itemTokenAssetPez20 chip (gone by default).
- TokenAssetViewHolder: show it when chainId == Pezkuwi Asset Hub and the
  symbol is PEZ/USDT/wUSDT.

Additive only; native HEZ and other chains are unbadged. Consistent with
the pex and Telegram mini app badges.
2026-06-12 23:36:15 -07:00
76 changed files with 199 additions and 400 deletions
-9
View File
@@ -119,7 +119,6 @@ env:
CI_MARKET_KEYSTORE_KEY_ALIAS: ${{ secrets.CI_MARKET_KEYSTORE_KEY_ALIAS }}
CI_MARKET_KEYSTORE_KEY_PASS: ${{ secrets.CI_MARKET_KEYSTORE_KEY_PASS }}
CI_MARKET_KEY_FILE: ${{ secrets.RELEASE_MARKET_KEY_FILE }}
CI_DEV_KEY_FILE: ${{ secrets.BASE64_DEV_KEYSTORE_FILE }}
CI_KEYSTORE_PASS: ${{ secrets.CI_KEYSTORE_PASS }}
CI_KEYSTORE_KEY_ALIAS: ${{ secrets.CI_KEYSTORE_KEY_ALIAS }}
@@ -216,14 +215,6 @@ jobs:
fileDir: './app/'
encodedString: ${{ env.CI_MARKET_KEY_FILE }}
- name: 🔐 Getting develop sign key
if: ${{ startsWith(inputs.keystore-file-name, 'develop_key.jks') }}
uses: timheuer/base64-to-file@v1.1
with:
fileName: ${{ inputs.keystore-file-name }}
fileDir: './app/'
encodedString: ${{ env.CI_DEV_KEY_FILE }}
- name: 🏗 Build app
if: ${{ !startsWith(inputs.gradlew-command, 'false') }}
run: ./gradlew ${{ inputs.gradlew-command }}
@@ -21,19 +21,13 @@ on:
- beta
- production
status:
description: 'Release status (draft, completed, inProgress=staged)'
description: 'Release status (draft, completed)'
required: true
default: draft
type: choice
options:
- draft
- completed
- inProgress
user_fraction:
description: 'Staged rollout fraction for inProgress (e.g. 0.2 = 20%). Ignored unless status=inProgress.'
required: false
default: '0.2'
type: string
jobs:
build:
@@ -89,8 +83,6 @@ jobs:
releaseFiles: app/bundle/releaseMarket/pezkuwi-wallet-android-${{ github.event.inputs.app_version }}.aab
track: ${{ github.event.inputs.track }}
status: ${{ github.event.inputs.status }}
# userFraction only applies to staged rollout (status=inProgress); empty otherwise
userFraction: ${{ github.event.inputs.status == 'inProgress' && github.event.inputs.user_fraction || '' }}
inAppUpdatePriority: 2
whatsNewDirectory: distribution/whatsnew
mappingFile: app/mapping/releaseMarket/mapping.txt
-1
View File
@@ -10,6 +10,5 @@ jobs:
with:
branch: ${{github.head_ref}}
gradlew-command: assembleDevelop
keystore-file-name: develop_key.jks # develop variant is signed with signingConfigs.dev (develop_key.jks)
build-debug-tests: false # TODO: Enable this, when debug build will be fixed for tests
secrets: inherit
-89
View File
@@ -1,89 +0,0 @@
# Pezkuwi Wallet — Brand Rules
This wallet must stay aligned with the **Pezkuwi brand book**. The canonical,
ecosystem-wide source of truth lives on the wiki:
**https://wiki.pezkuwichain.io/brand/**. This file is the wallet-specific,
enforceable summary — read it before changing any colors, fonts, or imagery.
## The one hard rule
> **Only the Kurdistan palette (kesk green, sor red, zer gold, fire orange) plus
> navy/neutral are allowed. Pink, magenta and purple are FORBIDDEN — anywhere.**
This applies to XML colors, Compose `Color(0x…)` literals, vector drawables,
gradients, **and raster images** (PNG/WebP banners and illustrations).
## Palette (source of truth)
| Token | Hex | | Token | Hex |
|-------|-----|-|-------|-----|
| kesk (primary) | `#009639` | | base bg | `#05081C` |
| kesk-700 | `#017A2F` | | screen bg | `#08090E` |
| positive | `#2FC864` | | elevated | `#181920` |
| sor (red) | `#E2231A` | | nav | `#0F111A` |
| negative | `#E53450` | | text primary | `#E0FFFFFF` |
| zer (gold) | `#FDB813` | | text secondary | `#7AFFFFFF` |
| warning | `#EBC50A` | | text tertiary | `#52FFFFFF` |
| fire (orange) | `#FF7A00` | | periwinkle tint | `#999EC7` @ 10/16/24% |
| info | `#2AB0F2` | | | |
## Typography
- **Space Grotesk** — display: balances, screen titles, large numbers
- **Plus Jakarta Sans** — body / UI text
- **JetBrains Mono** — addresses, hashes, block numbers
All three are OFL-licensed and cover Latin-ext / Turkish / Kurdish Kurmancî
glyphs. Fonts live in `common/src/main/res/font/`; the theme maps them via
`fontRegular/SemiBold/Bold/ExtraBold/ExtraLight` in `common/.../values/themes.xml`.
## Brand mark & imagery
- The brand mark is the **Newroz flame** (`nevroz-fire-*`). Do **not** use the
retired Roj-rosette mark or a Kurdistan-map logo anywhere.
- First-launch splash uses the Newroz flame (`ic_loading_screen_logo`).
- Onboarding hero uses the **Global United States of Pezkuwi** infographic.
- Pull chain/token/dapp icons from `pezkuwichain/pezkuwi-wallet-utils`, don't
invent art. Keep one outline icon set (2px stroke, round caps).
## Where colors are defined
- Named colors: `common/src/main/res/values/colors.xml`
- Theme/type: `common/src/main/res/values/themes.xml`, `styles.xml`
## PR checklist (brand)
- [ ] No magenta/purple/pink in `colors.xml` (`#BD387F`, `#661D78`, `#443679`, `#FF48A5`, …).
- [ ] No `purple`/`magenta`/`pink`-named drawables or Compose color literals.
- [ ] Raster assets scanned for pink/magenta pixels (see snippet below); none above noise.
- [ ] New text uses the brand font roles; addresses use JetBrains Mono.
- [ ] Any new mark is the Newroz flame, not a map/rosette.
Raster pink scan (run from repo root):
```python
# python3 with Pillow
from PIL import Image; import glob
def pink(r,g,b): return r>150 and g<110 and b>120 and (r-g)>70
for f in glob.glob('**/res/drawable*/*.png',recursive=True)+glob.glob('**/res/drawable*/*.webp',recursive=True):
if '/build/' in f: continue
im=Image.open(f).convert('RGBA'); im.thumbnail((96,96)); px=im.load(); w,h=im.size; c=t=0
for y in range(h):
for x in range(w):
r,g,b,a=px[x,y]
if a<30: continue
t+=1; c+=pink(r,g,b)
if t and c/t>0.02: print(round(c/t*100,1),'%',f)
```
> Exception: third-party trademark logos (e.g. `ic_powered_by_oak`, OAK Network)
> must **not** be recolored — leave them as the owner ships them.
## Licensing note (important)
This app is a fork of **Nova Wallet**, licensed under **Apache-2.0**. Apache-2.0
lets us fork, rebrand and ship — **but you must KEEP `LICENSE` and `NOTICE`** and
their attributions, and state changes. Do **not** delete the attribution (that
would breach the license). Removing Nova's *trademark* (name/logo) from the UI is
required; preserving the *copyright notice* is also required. The package name
`io.novafoundation.nova.app` stays (Play Store identity; not a trademark issue).
+1 -33
View File
@@ -5,39 +5,7 @@ Context sıfırlanması durumunda referans olarak kullanılmalıdır.
---
## v1.1.1 — Dashboard & action-row screen redesign (2026-06-15)
Screen-level brand-book alignment (foundation landed in v1.1.0):
- **Pezkuwi dashboard card:** blue/indigo gradient → frosted dark-navy surface with
a small Newroz-flame icon; brand buttons (Approve = kesk, Sign = sor, Share =
frosted-dark — the old yellow Share button removed); zer/positive accents.
- **Balance action row:** flat icon+label → circular buttons (Send on a kesk-green
circle, Receive/Swap/Buy/Gift on frosted-dark circles with labels below).
## v1.1.0 — Brand-book UI redesign (2026-06-15)
Görsel kimlik Pezkuwi marka kitabına hizalandı; iş mantığına dokunulmadı.
- **Renkler:** colors.xml'deki yasak magenta/mor değerleri marka renkleriyle değiştirildi
(isimler korundu). Raster illustration'lardaki pembe/mor pikseller (siri, networks
banner, no-added-networks, hardware import, tinder-gov, crowdloan) kesk/teal'e retint
edildi. Üçüncü-taraf OAK logosuna dokunulmadı.
- **Tipografi:** Public Sans → Space Grotesk (display) + Plus Jakarta Sans (gövde) +
JetBrains Mono (adres/hash). TR + Kurmancî glifleri doğrulandı.
- **Splash:** Kurdistan-haritalı logo → Newroz alevi marka işareti.
- **Onboarding:** welcome hero → "Global United States of Pezkuwi" infografiği (tam/kırpılmadan).
- **Hijyen:** production-öncesi debug kodları kaldırıldı (FeeLoader user-facing DEBUG mesajı,
RuntimeFactory diagnostics). Brand kuralları için `BRAND.md` eklendi.
---
## DEBUG KODLARI — ✅ TEMİZLENDİ (2026-06-15, v1.1.0 öncesi)
> Aşağıdaki tüm debug kodları production'a çıkmadan kaldırıldı:
> #1 FeeLoaderV2Provider (kullanıcıya görünen DEBUG hata mesajı) ve #2 RuntimeFactory
> (`lastDiagnostics` + test referansı) bu sürümde temizlendi; #3#6 zaten kaldırılmıştı.
> Doğrulama: repoda `"DEBUG:` literali / `lastDiagnostics` referansı kalmadı.
> (Aşağıdaki kayıtlar tarihsel referans içindir.)
## DEBUG KODLARI (Production öncesi KALDIRILMALI)
### 1. FeeLoaderV2Provider.kt - Hata mesajı gösterimi
**Dosya:** `feature-wallet-api/src/main/java/io/novafoundation/nova/feature_wallet_api/presentation/mixin/fee/v2/FeeLoaderV2Provider.kt`
+13 -4
View File
@@ -80,7 +80,8 @@ android {
signingConfig signingConfigs.dev
matchingFallbacks = ['debug']
versionNameSuffix '-develop'
applicationIdSuffix '.dev'
// Use the base applicationId (io.pezkuwichain.wallet) — no ".dev" suffix —
// so it matches the registered google-services client.
//Init firebase
def localReleaseNotes = releaseNotes()
def localFirebaseGroup = firebaseGroup()
@@ -120,7 +121,10 @@ android {
applicationVariants.all { variant ->
String name = variant.buildType.name
if (name != "release" && name.startsWith("release")) {
// 'develop' now shares the base io.pezkuwichain.wallet applicationId, whose
// google-services client lives in the production google-services.json — so bind
// it for develop too (the DEV google-services.json has no matching client).
if ((name != "release" && name.startsWith("release")) || name == "develop") {
createBindReleaseFileTask(variant.buildType.name)
}
}
@@ -158,11 +162,16 @@ void createBindReleaseFileTask(String destination) {
"merge${capitalizedDestination}JniLibFolders".toString(),
"merge${capitalizedDestination}StartupProfile".toString(),
"merge${capitalizedDestination}Shaders".toString(),
"merge${capitalizedDestination}ArtProfile".toString()
"merge${capitalizedDestination}ArtProfile".toString(),
// The bind task writes into src/<dest>, which resource tasks read —
// declare the dependency so Gradle 8.9 doesn't fail on implicit ordering.
"generate${capitalizedDestination}Resources".toString(),
"merge${capitalizedDestination}Resources".toString()
]
dependentTasks.forEach {
tasks.getByName(it).dependsOn(task)
def t = tasks.findByName(it)
if (t != null) t.dependsOn(task)
}
}
}
@@ -229,6 +229,9 @@ class PezkuwiLiveTransferTest : BaseIntegrationTest() {
// Just log the extension names - type access might be restricted
Log.d("LiveTransferTest", "Signed extensions count: ${extrinsicMeta.signedExtensions.size}")
// Log the extrinsic address type if available
Log.d("LiveTransferTest", "RuntimeFactory diagnostics: ${io.novafoundation.nova.runtime.multiNetwork.runtime.RuntimeFactory.lastDiagnostics}")
println("Type resolution results:\n${results.joinToString("\n")}")
}
+1 -1
View File
@@ -1,7 +1,7 @@
buildscript {
ext {
// App version
versionName = '1.1.1'
versionName = '1.0.4'
versionCode = 1
applicationId = "io.pezkuwichain.wallet"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
+6 -26
View File
@@ -1,21 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Pezkuwi Wallet — common/src/main/res/values/colors.xml
REDESIGN per Pezkuwi Wallet Design System (brand book).
This is a DROP-IN replacement for the current file: every color NAME is
preserved (so no Kotlin/XML references break), only VALUES change.
What changed vs. the shipped file — and why:
• Purged forbidden Nova-legacy PINK / MAGENTA / PURPLE. The brand permits ONLY
the Kurdistan palette (kesk green / sor red / zer gold / fire) + navy/neutral.
- crowdloan_banner_gradient_start #BD387F (magenta) -> #009639 (kesk)
- networks_banner_gradient_end #661D78 (purple) -> #017A2F (kesk-700)
- chip_on_card_background #443679 (purple) -> #3D999EC7 (frosted)
• Everything else is unchanged from the already-Kurdistan-themed file.
Search the file for "REDESIGN:" to see each changed line.
-->
<resources>
<!-- Colors not included in the design system -->
<color name="address_icon_background">#eeeeee</color>
@@ -61,13 +44,11 @@
<color name="staking_type_banner_text_inactive">#52FFFFFF</color>
<color name="tinder_gov_banner_secondary_text">#A3FFFFFF</color>
<!-- REDESIGN: crowdloan banner is now the Newroz-flame gradient (kesk -> fire), not magenta -> orange -->
<color name="crowdloan_banner_gradient_start">#009639</color>
<color name="crowdloan_banner_gradient_start">#BD387F</color>
<color name="crowdloan_banner_gradient_end">#FF7A00</color>
<!-- REDESIGN: networks banner is now navy -> kesk green, not navy -> purple -->
<color name="networks_banner_gradient_start">#00072E</color>
<color name="networks_banner_gradient_end">#017A2F</color>
<color name="networks_banner_gradient_end">#661D78</color>
<!-- Icon Colors -->
<color name="icon_primary">#E0FFFFFF</color>
@@ -89,12 +70,12 @@
<color name="bottom_sheet_background">#181920</color>
<color name="block_background">#1A999EC7</color>
<color name="hided_networks_block_background">#3D999EC7</color>
<!-- TODO update name once in design system-->
<color name="block_background_dark">#5205081C</color>
<color name="cell_background_pressed">#291F78FF</color>
<color name="input_background">#1A999EC7</color>
<color name="chips_background">#29999EC7</color>
<!-- REDESIGN: was #443679 (purple). Now frosted periwinkle, on-brand. -->
<color name="chip_on_card_background">#3D999EC7</color>
<color name="chip_on_card_background">#443679</color>
<color name="container_background">#1A999EC7</color>
<color name="token_container_background">#3D08090E</color>
<color name="segmented_background">#5208090E</color>
@@ -128,8 +109,7 @@
<color name="button_background_inactive_on_gradient">#1A999EC7</color>
<color name="button_background_inactive">#181920</color>
<!-- REDESIGN: WalletConnect button retinted off the indigo #353D67 to a neutral navy. -->
<color name="button_wallet_connect_background">#1F2A4D</color>
<color name="button_wallet_connect_background">#353D67</color>
<color name="wallet_connections_background">#101636</color>
<!-- Border Colors - Kurdistan Green -->
@@ -182,4 +162,4 @@
<color name="neutral_price_chart_line">#454968</color>
<color name="positive_price_chart_line">#2FC864</color>
<color name="negative_price_chart_line">#E53450</color>
</resources>
</resources>
+1 -1
View File
@@ -245,7 +245,7 @@
<style name="TextAppearance.NovaFoundation.Regular.Monospace">
<item name="android:textSize">12sp</item>
<item name="android:fontFamily">@font/jetbrains_mono_regular</item>
<item name="android:fontFamily">monospace</item>
</style>
<!-- Buttons -->
+6 -6
View File
@@ -30,12 +30,12 @@
<item name="textSizeSubHeadline">@dimen/text_size_subheadline</item>
<!--text sizes-->
<!--fonts: brand book — Plus Jakarta Sans (body) + Space Grotesk (display/bold)-->
<item name="fontSemiBold">@font/plus_jakarta_sans_semi_bold</item>
<item name="fontBold">@font/space_grotesk_bold</item>
<item name="fontExtraBold">@font/space_grotesk_bold</item>
<item name="fontRegular">@font/plus_jakarta_sans_regular</item>
<item name="fontExtraLight">@font/plus_jakarta_sans_light</item>
<!--fonts-->
<item name="fontSemiBold">@font/public_sans_semi_bold</item>
<item name="fontBold">@font/public_sans_bold</item>
<item name="fontExtraBold">@font/public_sans_extra_bold</item>
<item name="fontRegular">@font/public_sans_regular</item>
<item name="fontExtraLight">@font/public_sans_extra_light</item>
<!--fonts-->
<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
@@ -1,5 +1,6 @@
package io.novafoundation.nova.feature_assets.presentation.balance.common.holders
import androidx.core.view.isVisible
import coil.ImageLoader
import io.novafoundation.nova.common.list.GroupedListHolder
import io.novafoundation.nova.common.presentation.masking.setMaskableText
@@ -13,6 +14,11 @@ import io.novafoundation.nova.feature_assets.presentation.balance.list.model.ite
import io.novafoundation.nova.feature_assets.presentation.model.AssetModel
import io.novafoundation.nova.feature_wallet_api.presentation.model.maskableFiat
import io.novafoundation.nova.feature_wallet_api.presentation.model.maskableToken
import io.novafoundation.nova.runtime.ext.Geneses
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
// Fungible assets on Pezkuwi Asset Hub follow the PEZ-20 token standard.
private val PEZ20_SYMBOLS = setOf("PEZ", "USDT", "wUSDT")
class TokenAssetViewHolder(
private val binder: ItemTokenAssetBinding,
@@ -31,7 +37,12 @@ class TokenAssetViewHolder(
bindTotal(asset)
binder.itemTokenAssetToken.text = asset.token.configuration.symbol.value
val config = asset.token.configuration
binder.itemTokenAssetToken.text = config.symbol.value
val isPez20 = config.chainId == Chain.Geneses.PEZKUWI_ASSET_HUB && config.symbol.value in PEZ20_SYMBOLS
binder.itemTokenAssetPez20.isVisible = isPez20
if (isPez20) binder.itemTokenAssetPez20.text = "PEZ-20"
setOnClickListener { itemHandler.assetClicked(asset.token.configuration) }
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Brand: primary action circle — kesk green -->
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#009639" />
</shape>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Brand: secondary action circle — frosted dark -->
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#242838" />
<stroke android:width="1dp" android:color="#29999EC7" />
</shape>
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Brand book: frosted dark-navy surface + 1px periwinkle hairline (no blue/indigo gradient) -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1C1F2E" />
<gradient
android:angle="135"
android:startColor="#FF1A237E"
android:centerColor="#FF283593"
android:endColor="#FF3949AB"
android:type="linear" />
<stroke
android:width="1dp"
android:color="#33999EC7" />
<corners android:radius="20dp" />
<corners android:radius="16dp" />
</shape>
@@ -4,8 +4,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
app:cardBackgroundColor="@android:color/transparent"
app:cardCornerRadius="20dp"
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
app:strokeWidth="0dp">
@@ -14,20 +13,14 @@
android:layout_height="wrap_content"
android:background="@drawable/bg_pezkuwi_dashboard"
android:orientation="vertical"
android:padding="18dp">
android:padding="16dp">
<!-- Header: flame badge + title/roles (left), citizen count (right) -->
<!-- Top row: Title + Logo -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="12dp"
android:src="@drawable/ic_nevroz_flame" />
android:orientation="horizontal"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="0dp"
@@ -40,7 +33,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pezkuwi_dashboard_title"
android:textColor="#E0FFFFFF"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold" />
@@ -48,113 +41,109 @@
android:id="@+id/pezkuwiDashboardRoles"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
app:alignItems="center"
android:layout_marginTop="4dp"
app:flexWrap="wrap"
app:alignItems="center"
app:justifyContent="flex_start" />
<!-- Trust Score -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pezkuwi_dashboard_trust_score"
android:textColor="#B0BEC5"
android:textSize="12sp" />
<TextView
android:id="@+id/pezkuwiDashboardTrustValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textColor="#FFD54F"
android:textSize="16sp"
android:textStyle="bold" />
<com.google.android.material.button.MaterialButton
android:id="@+id/pezkuwiDashboardStartTrackingButton"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:layout_marginStart="8dp"
android:minWidth="0dp"
android:paddingHorizontal="10dp"
android:text="@string/pezkuwi_dashboard_start_tracking"
android:textAllCaps="false"
android:textColor="@android:color/white"
android:textSize="11sp"
android:visibility="gone"
app:backgroundTint="#FF9800"
app:cornerRadius="8dp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="vertical">
android:orientation="vertical"
android:gravity="center"
android:layout_marginEnd="12dp">
<TextView
android:id="@+id/pezkuwiDashboardWelatiCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:textColor="#2FC864"
android:textSize="24sp"
android:textColor="#4CAF50"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="@string/pezkuwi_dashboard_kurds_title"
android:textColor="#7AFFFFFF"
android:textColor="#CFD8DC"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>
<!-- Trust score -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="14dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pezkuwi_dashboard_trust_score"
android:textColor="#7AFFFFFF"
android:textSize="12sp" />
<TextView
android:id="@+id/pezkuwiDashboardTrustValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textColor="#FDB813"
android:textSize="16sp"
android:textStyle="bold" />
<com.google.android.material.button.MaterialButton
android:id="@+id/pezkuwiDashboardStartTrackingButton"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:layout_marginStart="8dp"
android:minWidth="0dp"
android:paddingHorizontal="10dp"
android:text="@string/pezkuwi_dashboard_start_tracking"
android:textAllCaps="false"
android:textColor="@android:color/white"
android:textSize="11sp"
android:visibility="gone"
app:backgroundTint="#009639"
app:cornerRadius="8dp" />
</LinearLayout>
<!-- Action buttons -->
<!-- Action buttons: Kesk (green), Sor (red), Zer (yellow) -->
<com.google.android.material.button.MaterialButton
android:id="@+id/pezkuwiDashboardBasvuruButton"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="16dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/pezkuwi_dashboard_basvuru"
android:textAllCaps="false"
android:textColor="@android:color/white"
android:textStyle="bold"
app:backgroundTint="#009639"
app:cornerRadius="14dp" />
app:backgroundTint="#4CAF50"
app:cornerRadius="8dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/pezkuwiDashboardSignButton"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="8dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/citizenship_sign"
android:textAllCaps="false"
android:textColor="@android:color/white"
app:backgroundTint="#E2231A"
app:cornerRadius="14dp" />
app:backgroundTint="#E53935"
app:cornerRadius="8dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/pezkuwiDashboardShareButton"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="8dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/citizenship_share_button"
android:textAllCaps="false"
android:textColor="#E0FFFFFF"
app:backgroundTint="#2A2F45"
app:cornerRadius="14dp"
app:strokeColor="#33999EC7"
app:strokeWidth="1dp" />
android:textColor="#212121"
app:backgroundTint="#FDD835"
app:cornerRadius="8dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
@@ -32,6 +32,24 @@
app:layout_constraintVertical_chainStyle="packed"
tools:text="DOT" />
<TextView
android:id="@+id/itemTokenAssetPez20"
style="@style/TextAppearance.NovaFoundation.Regular.Caption1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:background="@drawable/bg_chip_6"
android:paddingHorizontal="6dp"
android:paddingVertical="1dp"
android:textColor="@color/chip_text"
android:textSize="9sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/itemTokenAssetToken"
app:layout_constraintStart_toEndOf="@+id/itemTokenAssetToken"
app:layout_constraintTop_toTopOf="@+id/itemTokenAssetToken"
tools:text="PEZ-20"
tools:visibility="visible" />
<LinearLayout
android:id="@+id/itemTokenAssetRateContainer"
android:layout_width="wrap_content"
@@ -124,145 +124,71 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/viewAssetsTotalBalanceContainer">
<LinearLayout
<TextView
android:id="@+id/viewAssetsTotalBalanceSend"
style="@style/Widget.Nova.ActionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:paddingVertical="6dp">
android:breakStrategy="high_quality"
android:hyphenationFrequency="full"
android:paddingBottom="8dp"
android:text="@string/wallet_asset_send"
app:drawableTopCompat="@drawable/ic_send_tokens"
tools:drawableTop="@drawable/ic_send_tokens" />
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@drawable/bg_action_circle_primary"
android:padding="13dp"
android:src="@drawable/ic_send_tokens"
app:tint="@android:color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/wallet_asset_send"
android:textColor="@color/text_secondary"
android:textSize="11sp" />
</LinearLayout>
<LinearLayout
<TextView
android:id="@+id/viewAssetsTotalBalanceReceive"
style="@style/Widget.Nova.ActionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:paddingVertical="6dp">
android:breakStrategy="high_quality"
android:hyphenationFrequency="full"
android:paddingBottom="8dp"
android:text="@string/wallet_asset_receive"
app:drawableTopCompat="@drawable/ic_receive_tokens"
tools:drawableTop="@drawable/ic_receive_tokens"
tools:text="Получить" />
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@drawable/bg_action_circle_secondary"
android:padding="13dp"
android:src="@drawable/ic_receive_tokens"
app:tint="@color/icon_primary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/wallet_asset_receive"
android:textColor="@color/text_secondary"
android:textSize="11sp" />
</LinearLayout>
<LinearLayout
<TextView
android:id="@+id/viewAssetsTotalBalanceSwap"
style="@style/Widget.Nova.ActionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:paddingVertical="6dp">
android:breakStrategy="high_quality"
android:hyphenationFrequency="full"
android:paddingBottom="8dp"
android:text="@string/wallet_asset_swap"
app:drawableTopCompat="@drawable/ic_swap"
tools:drawableTop="@drawable/ic_swap" />
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@drawable/bg_action_circle_secondary"
android:padding="13dp"
android:src="@drawable/ic_swap"
app:tint="@color/icon_primary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/wallet_asset_swap"
android:textColor="@color/text_secondary"
android:textSize="11sp" />
</LinearLayout>
<LinearLayout
<TextView
android:id="@+id/viewAssetsTotalBalanceBuy"
style="@style/Widget.Nova.ActionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:paddingVertical="6dp">
android:breakStrategy="high_quality"
android:hyphenationFrequency="full"
android:paddingBottom="8dp"
android:text="@string/wallet_asset_buy_sell"
app:drawableTopCompat="@drawable/ic_buy_tokens"
tools:drawableTop="@drawable/ic_buy" />
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@drawable/bg_action_circle_secondary"
android:padding="13dp"
android:src="@drawable/ic_buy_tokens"
app:tint="@color/icon_primary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/wallet_asset_buy_sell"
android:textColor="@color/text_secondary"
android:textSize="11sp" />
</LinearLayout>
<LinearLayout
<TextView
android:id="@+id/viewAssetsTotalBalanceGift"
style="@style/Widget.Nova.ActionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:paddingVertical="6dp">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@drawable/bg_action_circle_secondary"
android:padding="13dp"
android:src="@drawable/ic_gift_card"
app:tint="@color/icon_primary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/common_gift"
android:textColor="@color/text_secondary"
android:textSize="11sp" />
</LinearLayout>
android:breakStrategy="high_quality"
android:hyphenationFrequency="full"
android:paddingBottom="8dp"
android:text="@string/common_gift"
app:drawableTopCompat="@drawable/ic_gift_card"
tools:drawableTop="@drawable/ic_gift_card" />
</LinearLayout>
@@ -15,7 +15,7 @@
android:id="@+id/logoImg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:scaleType="centerCrop"
android:src="@drawable/ic_create_wallet_background"
app:layout_constraintBottom_toTopOf="@+id/welcomeCreateWalletButton"
app:layout_constraintEnd_toEndOf="parent"
@@ -160,11 +160,15 @@ internal class FeeLoaderV2Provider<F, D>(
fee.emit(FeeStatus.Error)
// Show detailed error in retry dialog with runtime diagnostics
val diagnostics = try {
io.novafoundation.nova.runtime.multiNetwork.runtime.RuntimeFactory.lastDiagnostics
} catch (e: Exception) { "N/A" }
retryEvent.postValue(
Event(
RetryPayload(
title = resourceManager.getString(R.string.choose_amount_network_error),
message = resourceManager.getString(R.string.choose_amount_error_fee),
message = "DEBUG: $errorMsg | Runtime: $diagnostics",
onRetry = { loadFee(feeConstructor) },
onCancel = { }
)
@@ -47,6 +47,10 @@ class RuntimeFactory(
private val gson: Gson,
private val concurrencyLimit: Int = 1
) {
companion object {
@Volatile
var lastDiagnostics: String = "not yet initialized"
}
private val dispatcher = newLimitedThreadPoolExecutor(concurrencyLimit).asCoroutineDispatcher()
private val semaphore = Semaphore(concurrencyLimit)
@@ -106,6 +110,11 @@ class RuntimeFactory(
val typeRegistry = TypeRegistry(finalTypes, DynamicTypeResolver(DynamicTypeResolver.DEFAULT_COMPOUND_EXTENSIONS + GenericsExtension))
// Store diagnostic info for error messages
val hasExtrinsicSignature = typeRegistry["ExtrinsicSignature"] != null
val hasAddress = typeRegistry["Address"] != null
lastDiagnostics = "typesUsage=$typesUsage, ExtrinsicSig=$hasExtrinsicSignature, Address=$hasAddress, typeCount=${finalTypes.size}"
val runtimeMetadata = VersionedRuntimeBuilder.buildMetadata(metadataReader, typeRegistry)
ConstructedRuntime(