Warning
This is a prototype, reference implementation, and proof-of-concept. This open source code is developed and published by Parity Technologies for research, experimentation, and developer education only. It has not been audited, is actively experimental, and may contain bugs, vulnerabilities, or incomplete features. The app is a self-custodial wallet that can hold real assets — use at your own risk.
Clone paritytech/polkadot-android-community
and follow the public setup instructions in the root README.
Build-time configuration, signing, and distribution requirements are documented in
docs/DEPLOYMENT.md. Never commit keystores,
google-services.json, service-account files, or credentials.
Generate a random 12-word mnemonic for testing:
python3 scripts/generate-mnemonic.pyThis document describes all continuous integration and delivery flows for the Polkadot Android application.
Configure these values under Settings → Secrets and variables → Actions. GitHub
does not expose repository configuration to a runner automatically; the workflows
under .github/workflows explicitly map build values to the environment read by
Gradle and notification values to action inputs.
These values are public application configuration and are intentionally stored as GitHub Actions Variables rather than Secrets. They are embedded in the APK and must not contain credentials.
Most variables below are mandatory: the build reads them with readSecretOrThrow
and fails at configuration time when one is missing or empty, so a deploy can never ship
a placeholder fallback. Only signingConfigs still uses readSecretOrDefault.
SENTRY_DSN, REFERRAL_WEB_HOST and GAME_RESULTS_FALLBACK_URL are optional and keep a
fallback — the features they configure are not part of the current production build.
| Variable | Purpose |
|---|---|
APPLICATION_ID |
Base Android application ID. The build adds .debug, .nightly or .safetynet for those build types. Every resulting id must match a client in google-services.json. |
APPLICATION_NAME |
Launcher name of the application. DEBUG_APPLICATION_NAME, NIGHTLY_APPLICATION_NAME and SAFETYNET_APPLICATION_NAME optionally override it per build type; when unset they are derived from this value. |
PRIVACY_POLICY_URL |
Privacy-policy destination shown by the application. |
CURRENCY_SYMBOL |
Symbol of the in-app digital currency shown in the UI — card title, send/get actions, and every formatted amount. |
FIAT_SYMBOL |
Fiat symbol prefixed to formatted amounts. $ also puts the dollar icon on the chat pay button; any other value shows the neutral cash icon. |
TERMS_OF_USE_URL |
Terms-of-use destination shown by the application. |
LOG_COLLECTION_EMAIL |
Recipient used by the debug log-sharing flow. |
CONTACT_EMAIL |
Recipient of the Contact us action on the Legal & Support screen. |
SENTRY_DSN |
Client DSN embedded in debug/nightly manifests for runtime error reporting. Optional; an empty value disables runtime reporting. |
SENTRY_ORG |
Sentry organization slug used by the Gradle plugin. |
SENTRY_PROJECT |
Sentry project slug used by the Gradle plugin. |
REFERRAL_WEB_HOST |
Allowed web host for referral-ticket deeplinks. Supply a host only, without a scheme or path. Optional. |
GAME_RESULTS_FALLBACK_URL |
Final HTTPS fallback for the game-results webview when DotNs and Remote Config do not provide a URL. Optional. |
These values configure CI notifications and are not consumed by the Android build.
| Variable | Purpose |
|---|---|
CI_MATRIX_ROOM_IDS |
Comma-separated Matrix room IDs that receive nightly release notifications. |
NIGHTLY_DOWNLOAD_LINKS |
Multiline Markdown list of download links included in nightly release notifications. |
| Secret | Purpose |
|---|---|
NIGHTLY_FUNDING_MNEMONIC |
Funding account used by nightly and production test contours. It is provided only to Gradle build/test steps. |
NIGHTLY_FUNDING_MNEMONIC is protected while stored by GitHub and is masked in
workflow logs. The current application places it in BuildConfig, however, so it
can be extracted from a distributed APK. Use only a tightly funded test account;
never use a treasury, production, or otherwise valuable mnemonic here.
See Deployment §5 for signing, Google/Firebase, Sentry, publishing, and local-build configuration.
Trigger: Pull requests to any branch (except release branches)
Purpose: Validate code changes through automated testing
Steps:
- Check for
skip-cilabel - Setup Android development environment
- Run unit tests
- Run build
Workflows:
Trigger: Manual dispatch or PR merge to main branch
Purpose: Distribute development builds to QA team via Firebase
Steps:
- Setup Android environment
- Calculate and update build number (10100 + run_number)
- Build app with Debug configuration
- Upload to Firebase App Distribution
- Notify configured groups
Workflows:
Configuration:
- Build type: Debug
- Default groups:
android-dev-testers
Trigger: Manual workflow dispatch
Purpose: Prepare and distribute production releases to Firebase
Steps:
- Validate user permissions (optional)
- Create release branch from source ref (default:
main) - Optionally bump version (major/minor/patch/no-bump)
- Commit version changes to release branch
- Create pull request to
main - Trigger Firebase Release workflow
- Security verification (only bot-initiated PRs allowed)
- Increment build number in Release configuration
- Commit build number update
- Run tests
- Build and upload to Firebase
- Comment on PR with build information
- Extract source branch metadata from merged PR
- Validate source branch exists
- Create backport PR:
release-{version}→source_ref(e.g.,main) - Include incremented build numbers and any hotfixes from release branch
Workflows:
release_prepare.yml- Phase 1firebase_release_distribution.yml- Phase 2 & 3
Configuration:
- Build type: Release
- Branches:
release-{version}→main→ backport tosource_ref - Source branch tracking: Embedded in PR metadata
- Version: Read from
Versions.kt(not changed) - Build number:
10000 + github.run_number
- Version:
- Format:
X.Y.Z(major.minor.patch) - Updated by
release_prepare.ymlbased on bump level - Stored in
Versions.kt→DefaultVersionName
- Format:
- Build number:
- Auto-incremented by
firebase_release_distribution.yml - Stored in
Versions.kt→DefaultVersionCode
- Auto-incremented by
- App ID:
ANDROID_FIREBASE_APP_ID(from secrets) - Groups:
dev-team - APK: Debug variant with debug keystore
- App ID:
ANDROID_FIREBASE_RELEASE_APP_ID(from secrets) - Groups:
dev-team - APK: Release variant with release keystore
Each build type carries its own applicationIdSuffix, so App Distribution treats it
as a separate Firebase app and needs its own App ID secret.
| Variant | App ID | Groups |
|---|---|---|
gpNightly |
ANDROID_FIREBASE_NIGHTLY_APP_ID |
CI_FIREBASE_GROUP |
vanillaNightly |
ANDROID_FIREBASE_NIGHTLY_APP_ID (product flavors add no suffix) |
CI_FIREBASE_GROUP_VANILLA |
gpSafetynet |
ANDROID_FIREBASE_SAFETYNET_APP_ID |
CI_FIREBASE_GROUP_SAFETYNET |
Both release_prepare.yml and firebase_release_distribution.yml include security checks:
release_prepare.yml:
- Only authorized users can run (optional, can be enabled in job condition)
firebase_release_distribution.yml:
workflow_dispatch: Must be triggered bygithub-actions[bot]pull_request: PR must be created bygithub-actions[bot]
This ensures release builds can only be initiated through the official release process.
All Android builds are automatically uploaded to Scaleway Object Storage for archival and distribution.
Bucket: polkadot-app-artefacts (region: fr-par)
| Workflow | Path Pattern | Static Path | Example URL |
|---|---|---|---|
| Debug (Firebase) | /android/debug/polkadot-app-{version}-{build}.apk |
/android/debug/polkadot-app.apk |
http://polkadot-app-artefacts.s3.fr-par.scw.cloud/android/debug/polkadot-app-1.2.3-10150.apk |
| Release (Firebase via PR) | /android/releases/polkadot-app-{version}-{build}.apk |
/android/releases/polkadot-app.apk |
http://polkadot-app-artefacts.s3.fr-par.scw.cloud/android/releases/polkadot-app-1.0.0-456.apk |
| Nightly Release | /android/nightly/polkadot-app-{version}-{build}.apk |
/android/nightly/polkadot-app.apk |
http://polkadot-app-artefacts.s3.fr-par.scw.cloud/android/nightly/polkadot-app-1.0.0-1456.apk |
Static paths always point to the latest build from that workflow, while versioned paths preserve all historical builds.
Version management scripts located in .github/scripts/:
read_versions.py- Reads current version and build number fromVersions.ktupdate_marketing_version.py- Updates version (DefaultVersionName) inVersions.ktupdate_build_number.py- Updates or increments build number (DefaultVersionCode) inVersions.kt
All scripts work with build-logic/convention/src/main/kotlin/Versions.kt file.