NPT is a privacy-preserving mobile wallet for Neptune Cash. It is built with Tauri (Rust + React) and targets Android (iOS support is planned but requires a macOS build host).
All private keys are derived and stored locally on the device. Transactions are built and signed locally; only ProofCollection-backed transactions ever leave the app. The wallet communicates with a neptune-core "supporter" node via JSON-RPC for chain state; the supporter never learns which addresses belong to the wallet.
src/— React + TypeScript frontendscreens/— page components (Wallet, Send, History, Settings, Unlock, …)store/— Zustand state (wallet, settings)api/rpc.ts— Tauri invoke wrappershooks/— React hooks (session guard)components/ui/— shared UI components (NavBar, logo, …)
src-tauri/— Rust backendsrc/lib.rs— Tauri commands, app state, session logicsrc/seed.rs— BIP39 mnemonic + AES-256-GCM + Argon2id KDFsrc/keys.rs— local key derivationsrc/sync.rs— privacy-preserving UTXO scan (flag-based + local decryption)src/rpc.rs— JSON-RPC client for supporter nodesrc/transaction.rs— STARK proof generation for sendsgen/android/— generated Android project (gradle, manifest, Kotlin shims)
leveldb-sys/,systemstat-stub/— stubs soneptune-cashcompiles on mobile
The fastest way to iterate on UI changes is to run the frontend in a browser — the Tauri backend is mocked so you see the layout but not real wallet functionality.
# Install Node.js (22.x or newer)
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
# Install system dependencies for Tauri desktop (needed even for dev)
sudo apt install -y libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev \
librsvg2-dev build-essential libglib2.0-dev
# Install Rust via rustup if not already installed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install JS dependencies
npm install
# Frontend only (fastest — for UI-only work in a browser at http://localhost:1420)
npm run dev
# Full desktop app (Rust backend + WebView, real wallet)
npm run tauri devMobile builds require the Android SDK and NDK.
# Install Android SDK + NDK (via Android Studio or sdkmanager)
# Set environment variables
export ANDROID_HOME="$HOME/android-sdk"
export NDK_HOME="$ANDROID_HOME/ndk/27.0.12077973"
export JAVA_HOME="/path/to/jdk-17"
export PATH="$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$PATH"
# Install Android Rust targets
rustup target add aarch64-linux-android x86_64-linux-android
# Initialise the Android project (first time only)
cargo tauri android init
# Start an emulator or connect a device via USB (`adb devices` should list it)
# Run the app with hot reload
cargo tauri android devGenymotion, LDPlayer, and Android Studio's emulators all work. For x86_64
emulators (LDPlayer, most Android Studio images) add --target x86_64 to
the build commands below.
# Build release APK for both aarch64 (real phones) and x86_64 (emulators)
cargo tauri android build --target aarch64 --target x86_64The unsigned APK is produced at:
src-tauri/gen/android/app/build/outputs/apk/universal/release/app-universal-release-unsigned.apk
Android requires APKs to be signed before installation. Create a keystore once:
keytool -genkey -v -keystore npt-wallet.keystore -alias npt -keyalg RSA -keysize 2048 -validity 10000Sign the built APK (uses the v2/v3 signing scheme — v1 alone is not accepted on modern devices):
APK_DIR=src-tauri/gen/android/app/build/outputs/apk/universal/release
$ANDROID_HOME/build-tools/36.0.0/zipalign -f 4 \
"$APK_DIR/app-universal-release-unsigned.apk" \
"$APK_DIR/npt-wallet-aligned.apk"
$ANDROID_HOME/build-tools/36.0.0/apksigner sign \
--ks npt-wallet.keystore --ks-key-alias npt \
--out "$APK_DIR/npt-wallet-signed.apk" \
"$APK_DIR/npt-wallet-aligned.apk"Keep the keystore safe — all future updates must be signed with the same key, otherwise users will not be able to update the app.
The wallet needs a neptune-core node with the following RPC namespaces enabled:
node, chain, wallet, archival, utxoindex. The personal namespace is
not required and the wallet never calls it — it is privacy-violating and
would require --unsafe-rpc on the node, which is never acceptable for a
third-party supporter.
To run your own supporter node:
git clone https://github.com/Neptune-Crypto/neptune-core
cd neptune-core
cargo run --release -- \
--listen-rpc=<public-ip-or-localhost>:9797 \
--rpc-modules "node,chain,wallet,archival,utxoindex" \
--utxo-indexThen set the supporter URL in the wallet's Settings screen.
No secrets are shared between the node and the wallet. A malicious supporter cannot steal funds; at worst it can refuse to serve requests or feed stale chain data. Use a TLS-terminating reverse proxy (Caddy, nginx) if you want to protect against passive eavesdroppers on the network path.
All private key material is encrypted with AES-256-GCM; the key is derived from the user's password via Argon2id (64 MB memory, 3 iterations). The seed file lives in the app's sandboxed data directory.
See the source of src-tauri/src/seed.rs for the
encryption details.