Warning
This is an experimental proof-of-concept: a prototype and reference implementation developed and published by Parity. This open source code is provided 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 and obtain legal advice as appropriate — DYOR.
Parity does not deploy or operate this code and does not run any service behind it; it may update the code based on community feedback. If you experience problems with an app that was built from or distributed using this code, contact the party who built and distributed it, not Parity.
Self-custodial Android superapp for Polkadot. Messaging, identity, payments, and built-in support for Polkadot applications — all-in-one, with you in full control of it.
- Identity — On-chain username with an allowance for free transactions, verified by Proof-of-Unique-Device.
- Chat — End-to-end p2p encrypted text messaging with media (images/video) and encrypted video/audio calls.
- Payments — Send and receive payments by username or QR code, and directly in chat.
- Auto-conversion — Top up your wallet and auto-convert it into the tokens you want.
- Built-in dApp support & sandboxing — Explore and use any dApp, and manage its sandbox permissions.
- dApp modalities — Supports SPA and Chat modalities for dApps.
- Deeplinks — Navigate the app and dApps through links and QR codes.
- Remote signing — Connect to Polkadot Desktop and Polkadot Web and use Mobile as a signer.
- Multi-device sync — Sync contacts and chats between Polkadot Mobile and Polkadot Desktop.
- Cloud backups — Back up your account using Google Drive.
- Manual backups — Keep your account stored only in the secure enclave storage locally.
- Customization — Fully customizable UI design system with 5 default themes.
Prerequisites
- JDK 21 (Temurin) and Android Studio
- Android SDK (compileSdk 36) and NDK r29
- Rust (stable) with the Android targets and
cargo-ndk:rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android cargo install cargo-ndk
- Node.js — the Gradle build runs
npm install/npm run buildinfeature/productsto bundle the dApp container - Python 3 — used by the Rust Android Gradle plugin's linker wrapper
Point Gradle at your SDK/NDK in local.properties:
sdk.dir=/path/to/android-sdk
ndk.dir=/path/to/android-ndk-r29Clone the repo:
git clone https://github.com/paritytech/polkadot-android-community.git
cd polkadot-android-community
# Optional: install the Detekt pre-commit hook
./developer-tools/setup.shGradle refuses to configure the project — even ./gradlew help — until every mandatory
variable below is set. Put them in the untracked local.properties (or export them as
environment variables with the same names):
sdk.dir=/path/to/android-sdk
# Build identity (public values, compiled into the APK)
APPLICATION_ID=com.example.polkadot
IOS_BUNDLE_ID=com.example.polkadot
APPLICATION_NAME=Polkadot
PRIVACY_POLICY_URL=https://example.com/privacy
TERMS_OF_USE_URL=https://example.com/terms
LOG_COLLECTION_EMAIL=logs@example.com
CONTACT_EMAIL=support@example.com
CURRENCY_SYMBOL=CASH
FIAT_SYMBOL=$
# Your Google Cloud / Firebase project (docs/DEPLOYMENT.md §4, §5.2)
GOOGLE_OAUTH_ID=<OAuth 2.0 web client id used for Google Sign-In>
GOOGLE_PROJECT_ID=<Google Cloud project number used for Play Integrity>
FIRESTORE_DATABASE_ID=(default)
# Sentry slugs are mandatory for the Gradle plugin; reporting stays off while SENTRY_DSN is unset
SENTRY_ORG=my-org
SENTRY_PROJECT=my-project
# Throwaway funding account for the testnet top-up flow of debug/nightly builds
NIGHTLY_FUNDING_MNEMONIC=<12 words>
# Dev keystore used to sign debug/nightly builds
CI_KEYSTORE_PASS=<store password>
CI_KEYSTORE_KEY_ALIAS=<alias>
CI_KEYSTORE_KEY_PASS=<key password>Then provide the three files/services the build and the app depend on:
- Dev keystore at the repo root, matching the
CI_KEYSTORE_*values:keytool -genkeypair -v -keystore develop_key.jks -alias <alias> -keyalg RSA -keysize 2048 -validity 10000
app/google-services.jsonfrom your own Firebase project. Its client list must includeAPPLICATION_IDand the.debug/.nightly/.safetynetsuffixed ids.- Firebase Remote Config values. The app ships no bundled defaults: its chain list, DotNS contract addresses, and backend endpoints all come from Remote Config, so a fresh Firebase project produces an app that cannot connect to anything. The keys and their shapes are listed in docs/DEPLOYMENT.md §4.1.
The full variable reference, including the optional overrides, is in docs/DEPLOYMENT.md §5.
Open the project in Android Studio, select the gp flavor with a debug build type and an Android 10+ device or emulator, then build and run.
The app talks to Polkadot system chains (People Chain, Asset Hub, Bulletin Chain). Which chains
and RPC nodes it uses is not hard-coded: the chains / chains_v2 Remote Config keys of your
Firebase project define the set, so a fork can point the same build at Polkadot, at the
Paseo testnet, or at its own network.
# Build a debug APK (lands in app/build/outputs/apk/gp/debug/)
./gradlew assembleGpDebug
# Run unit tests
./gradlew testGpDebugUnitTestThe project has two flavors (gp with Google Play Services, vanilla without — it
keeps Firebase Remote Config, which the app requires and which needs no Play Services
on the device) and debug / nightly / safetynet / release build types — e.g.
./gradlew assembleGpRelease for a production build (requires the release keystore
and secrets). Both flavors read the same set of mandatory variables; vanilla merely
ignores the Google values at runtime.
Polkadot Android is a self-custodial superapp: your keys are created on your phone, stay on your phone, and everything else — identity, chat, payments, apps — is built on top of them using Polkadot's public chains instead of company servers.
- Keeps your keys on your device. Your account is generated locally and encrypted with Android's hardware-backed keystore. You choose how to back it up: an encrypted backup in your own Google Drive, or no backup at all — keys stored only on the device.
- Gives you an on-chain name. You register a username on Polkadot's People Chain. Your phone proves it's a unique device, which earns you an allowance for free transactions — no tokens needed to start.
- Lets you chat without a messaging server. Messages are end-to-end encrypted and delivered through the People Chain statement store, so there is no company inbox holding your conversations. Voice and video calls are encrypted and go directly peer-to-peer over WebRTC.
- Sends money to names, not addresses. Pick a username (or scan a QR code, or pay right inside a chat) — the app resolves it to an account on-chain and sends the payment. Swaps and auto-conversion run on Asset Hub's liquidity pools.
- Runs Polkadot apps inside the app. Type a
.dotname and the app fetches the dApp's content (published on the Bulletin Chain and addressed via DotNS) and runs it in a sandbox. Each dApp gets its own permissions — network, camera, signing, storage — that you grant and revoke per app. - Works as one account across devices. Pair with Polkadot Desktop or Polkadot Web by scanning a QR code: your phone becomes the signer that approves their transactions, and contacts and chats sync between devices over the same encrypted channels.
- It does not act as a custodian of your keys or your money — the keys are stored only on your device, and nobody (including the developers) can freeze, recover, or move your funds. If you lose your device and have no cloud/written backup, the associated accounts are gone.
- It does not route your chats and calls through company messaging servers — messages travel through the public chain, calls go peer-to-peer.
- It is not a production-hardened product — treat it as a reference implementation (see the warning at the top).
A modular Kotlin / Jetpack Compose codebase: features are split into api and impl modules wired with Hilt, performance-critical crypto is compiled from Rust via the NDK (bindings/), and chain access goes through substrate-sdk-android (JSON-RPC, storage subscriptions, extrinsics).
GitHub Actions validate pull requests. The remaining workflows are the maintainers' own build and distribution flows; a fork does not need them. Build-time configuration and the steps to sign and publish the app are documented in docs/DEPLOYMENT.md.
Architecture conventions, module layout, and coding standards are documented in CLAUDE.md.
Issues and pull requests are welcome. Read CONTRIBUTING.md before you start.
If you build and distribute an app from this code, you are responsible for:
- Reviewing the code yourself — this repository is a reference, not a hardened production build.
- Checking that the dependencies are up to date and free of known vulnerabilities.
- Securing your own fork and build environment (keys, secrets, network configuration) and the services you point the app at.
- Deciding when to pick up new commits; security fixes land on
mainonly and older revisions are not backported.
Report vulnerabilities responsibly following Parity's security policy — do not open public issues for security reports. For Parity's disclosure process and Bug Bounty programme, see parity.io/bug-bounty. This proof-of-concept is maintained on a best-effort basis: reports are welcome, but there is no commitment to a fix or a timeline.
Licensed under the GNU General Public License v3.0 — see LICENSE.