mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-11-02 08:51:14 +00:00
* feat(network): fetch config from jsDelivr when raw.githubusercontent.com fails Every config file the app reads -- chains, assets, DApps, XCM, banners, token icons -- comes from raw.githubusercontent.com with no other source, so when that host cannot be reached a fresh install has no chains at all. ConfigMirrorInterceptor retries the same file on cdn.jsdelivr.net and then fastly.jsdelivr.net when the primary fails to connect or answers 403, 429, 451 or 5xx. A 404 is an answer and is returned as is. A host that failed is skipped for ten minutes so later requests do not each wait for its timeout. Mirror requests revalidate, so a mirror's long max-age cannot pin a copy in the HTTP cache after the primary is back. The shared OkHttp client and Coil's image client both carry it. * feat(runtime): start a first install from the chain list the APK was built with A first install has no chains until chains.json is fetched, and the fetch retries forever: with GitHub and its mirrors unreachable the wallet stays empty. The runtime module now bundles the live chains.json at build time (bundleChainsConfig, run before preBuild, falling back to jsDelivr and refusing anything that is not a non-empty JSON array). When the local database is empty, ChainSyncService tries the network once and, if that fails, applies the bundled list so the wallet opens; the fetched list then replaces it through the usual diff as soon as it arrives. * feat(dapps): show the bundled DApps catalog until one can be fetched The DApps catalog lived only in memory and every read waited on first(), so with the catalog URL unreachable the DApps screen waited forever. feature-dapp-impl now bundles dapps_full.json at build time. On the first sync the repository tries the network once and, if that fails, publishes the bundled catalog so every read returns; the fetched catalog replaces it as soon as it arrives. The download task moves to scripts/bundled-config.gradle and serves both the chain list and the DApps catalog. runtime and feature-dapp-impl unit tests return defaults for android.util.Log, which the fallback calls. * feat(network): resolve names over DNS-over-HTTPS first, system DNS as fallback A network that answers plain DNS with a wrong address decides where the app connects. The shared OkHttp client and Coil's client now resolve through EncryptedFirstDns: Google, Cloudflare and Quad9 over HTTPS, each reached by IP, then the system resolver if all of them fail, so no network is worse off. - A resolver whose request failed is skipped for ten minutes, so a network that blocks DoH pays the four-second timeout once. NXDOMAIN and SERVFAIL do not count as failures. - IPv4 addresses are returned first: DoH answers IPv6 whether or not the network has it, and OkHttp tries addresses in order. - IP literals and localhost never leave the device. WebSocket RPC (nv-websocket) still resolves through the system. * feat(config): verify signed config metadata, TUF style The rules the app will apply to config it fetches, not wired yet: - A root, signed by a threshold of root keys, names the keys that may sign the targets list and how many must. The APK carries the first root. - A new root is accepted one version at a time, signed by a threshold of the old root's keys and of its own, so keys can be replaced without a release and a lost targets key can be revoked. - The targets list gives the sha256 of each config file; it cannot go back a version, cannot jump more than 10,000 at once, and is refused once it or its root has expired. - Ed25519 over the payload bytes exactly as published (BouncyCastle, already a dependency); a key signing twice counts once; a key must match its id. * fix(config): parse metadata with the Gson API the app resolves JsonParser.parseString is not in the Gson version on the app's classpath; the instance parse method is, and behaves the same here. * test(runtime): add the Log.e overload with a throwable to the test shim The first-install fallback logs the failed fetch with its exception, and the shim only had the two-argument form, so the test hit NoSuchMethodError. * feat(config): refuse config files the signed list does not give SignedConfigInterceptor checks every JSON file from pezkuwi-wallet-utils against signed/targets.json, whichever host the mirrors got it from. A file the list does not give, or one without a verified list behind it, comes back as a 502, so callers keep the stored chains and bundled lists as they do when the source is unreachable. Newer roots are followed from signed/root.N.json; the targets version and the latest time seen are stored, so an older list cannot be replayed. Root keys may now be sr25519 wallet accounts: they sign through the wallet's message signing, which wraps the bytes in <Bytes>, and the SDK's schnorrkel verifies them. The APK carries root 1 as an asset, trusted as the APK is.
158 lines
6.3 KiB
Groovy
158 lines
6.3 KiB
Groovy
apply plugin: 'kotlin-parcelize'
|
|
|
|
android {
|
|
|
|
defaultConfig {
|
|
|
|
buildConfigField "String", "WEBSITE_URL", "\"https://pezkuwichain.io\""
|
|
buildConfigField "String", "PRIVACY_URL", "\"https://pezkuwichain.io/privacy.html\""
|
|
buildConfigField "String", "TERMS_URL", "\"https://pezkuwichain.io/terms.html\""
|
|
buildConfigField "String", "GITHUB_URL", "\"https://github.com/pezkuwichain\""
|
|
buildConfigField "String", "TELEGRAM_URL", "\"https://t.me/pezkuwichainBot\""
|
|
buildConfigField "String", "TWITTER_URL", "\"https://x.com/bizinikiwi\""
|
|
buildConfigField "String", "RATE_URL", "\"market://details?id=${rootProject.applicationId}.${releaseApplicationSuffix}\""
|
|
buildConfigField "String", "EMAIL", "\"support@pezkuwichain.io\""
|
|
buildConfigField "String", "YOUTUBE_URL", "\"https://www.youtube.com/@SatoshiQazi\""
|
|
|
|
buildConfigField "String", "TWITTER_ACCOUNT_TEMPLATE", "\"https://twitter.com/%s\""
|
|
buildConfigField "String", "RECOMMENDED_VALIDATORS_LEARN_MORE", "\"https://docs.pezkuwichain.io/wallet-wiki/staking/staking-faq#q-how-does-pezkuwi-wallet-select-validators-collators\""
|
|
|
|
buildConfigField "String", "PAYOUTS_LEARN_MORE", "\"https://docs.pezkuwichain.io/wallet-wiki/staking/staking-faq#q-what-is-the-difference-between-restake-rewards-and-transferable-rewards\""
|
|
|
|
buildConfigField "String", "SET_CONTROLLER_LEARN_MORE", "\"https://docs.pezkuwichain.io/wallet-wiki/staking/staking-faq#q-what-are-stash-and-controller-accounts\""
|
|
|
|
buildConfigField "String", "SET_CONTROLLER_DEPRECATED_LEARN_MORE", "\"https://docs.pezkuwichain.io/wallet-wiki/staking/controller-account-deprecation\""
|
|
|
|
buildConfigField "String", "PARITY_SIGNER_TROUBLESHOOTING", "\"https://docs.pezkuwichain.io/wallet-wiki/hardware-wallets/parity-signer/troubleshooting\""
|
|
buildConfigField "String", "POLKADOT_VAULT_TROUBLESHOOTING", "\"https://docs.pezkuwichain.io/wallet-wiki/hardware-wallets/polkadot-vault/troubleshooting\""
|
|
buildConfigField "String", "PEZKUWI_WALLET_WIKI_BASE", "\"https://docs.pezkuwichain.io/wallet-wiki/about-pezkuwi-wallet\""
|
|
buildConfigField "String", "PEZKUWI_WALLET_WIKI_PROXY", "\"https://docs.pezkuwichain.io/wallet-wiki/wallet-management/delegated-authorities-proxies\""
|
|
buildConfigField "String", "PEZKUWI_WALLET_WIKI_INTEGRATE_NETWORK", "\"https://docs.pezkuwichain.io/wallet-wiki/misc/developer-documentation/integrate-network\""
|
|
|
|
buildConfigField "String", "LEDGER_MIGRATION_ARTICLE", "\"https://docs.pezkuwichain.io/wallet-wiki/wallet-management/hardware-wallets/ledger-nano-x/ledger-app-migration\""
|
|
|
|
buildConfigField "String", "LEDGER_CONNECTION_GUIDE", "\"https://docs.pezkuwichain.io/wallet-wiki/wallet-management/hardware-wallets/ledger-devices\""
|
|
|
|
buildConfigField "String", "APP_UPDATE_SOURCE_LINK", "\"https://wallet.pezkuwichain.io\""
|
|
|
|
buildConfigField "String", "PEZKUWI_CARD_WIDGET_URL", "\"https://exchange.mercuryo.io\""
|
|
|
|
buildConfigField "String", "ASSET_COLORED_ICON_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/main/icons/tokens/colored\""
|
|
buildConfigField "String", "ASSET_WHITE_ICON_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/main/icons/tokens/white\""
|
|
|
|
buildConfigField "String", "UNIFIED_ADDRESS_ARTICLE", "\"https://docs.pezkuwichain.io/wallet-wiki/asset-management/how-to-receive-tokens#unified-and-legacy-addresses\""
|
|
|
|
buildConfigField "String", "MULTISIGS_WIKI_URL", "\"https://docs.pezkuwichain.io/wallet-wiki/wallet-management/multisig-wallets\""
|
|
|
|
buildConfigField "String", "GIFTS_WIKI_URL", "\"https://docs.pezkuwichain.io/wallet-wiki/asset-management/gifting-tokens\""
|
|
|
|
buildConfigField "long", "CLOUD_PROJECT_NUMBER", "171267697857L"
|
|
|
|
buildConfigField "String", "GLOBAL_CONFIG_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/staking/global_config_dev.json\""
|
|
}
|
|
|
|
buildTypes {
|
|
debug {
|
|
|
|
}
|
|
release {
|
|
minifyEnabled false
|
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
|
|
buildConfigField "long", "CLOUD_PROJECT_NUMBER", "802342409053L"
|
|
|
|
buildConfigField "String", "GLOBAL_CONFIG_URL", "\"https://raw.githubusercontent.com/pezkuwichain/pezkuwi-wallet-utils/master/staking/global_config.json\""
|
|
}
|
|
|
|
releaseGithub {
|
|
initWith buildTypes.release
|
|
matchingFallbacks = ['release']
|
|
buildConfigField "String", "APP_UPDATE_SOURCE_LINK", "\"https://github.com/pezkuwichain/pezWallet/releases\""
|
|
}
|
|
}
|
|
|
|
namespace 'io.novafoundation.nova.common'
|
|
|
|
buildFeatures {
|
|
viewBinding true
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
|
|
implementation(name: 'renderscript-toolkit', ext: 'aar')
|
|
|
|
api project(":core-api")
|
|
|
|
implementation kotlinDep
|
|
|
|
implementation androidDep
|
|
implementation cardViewDep
|
|
implementation recyclerViewDep
|
|
implementation materialDep
|
|
implementation constraintDep
|
|
|
|
implementation biometricDep
|
|
|
|
implementation bouncyCastleDep
|
|
|
|
api substrateSdkDep
|
|
|
|
implementation coroutinesDep
|
|
api liveDataKtxDep
|
|
implementation lifeCycleKtxDep
|
|
|
|
implementation viewModelKtxDep
|
|
|
|
implementation daggerDep
|
|
ksp daggerCompiler
|
|
|
|
implementation lifecycleDep
|
|
ksp lifecycleCompiler
|
|
|
|
implementation retrofitDep
|
|
api gsonConvertedDep
|
|
implementation scalarsConverterDep
|
|
implementation interceptorVersion
|
|
implementation okhttpDnsOverHttpsDep
|
|
|
|
implementation zXingCoreDep
|
|
implementation zXingEmbeddedDep
|
|
|
|
implementation progressButtonDep
|
|
|
|
implementation wsDep
|
|
|
|
api insetterDep
|
|
|
|
api coilDep
|
|
api coilSvg
|
|
|
|
api web3jDep
|
|
api coroutinesFutureDep
|
|
api coroutinesRxDep
|
|
|
|
implementation shimmerDep
|
|
|
|
implementation playIntegrity
|
|
|
|
testImplementation jUnitDep
|
|
testImplementation mockitoDep
|
|
testImplementation project(':test-shared')
|
|
|
|
implementation permissionsDep
|
|
|
|
implementation flexBoxDep
|
|
|
|
implementation markwonDep
|
|
implementation markwonImage
|
|
implementation markwonTables
|
|
implementation markwonLinkify
|
|
implementation markwonStrikethrough
|
|
implementation markwonHtml
|
|
implementation kotlinReflect
|
|
|
|
implementation playServicesAuthDep
|
|
|
|
} |