Skip to content

Repository files navigation

Interledger Android App

Android wallet application built with Jetpack Compose and modern Android architecture for fast, secure payment experiences using the Interledger Protocol.

Architecture

This project follows Clean Architecture principles with:

  • MVVM pattern with ViewModels and StateFlow-based UI state
  • Jetpack Compose for declarative UI
  • Jetpack Navigation 3 for type-safe navigation with typed route objects
  • Use Cases for business logic
  • Repository pattern for data access
  • Dependency Injection with Koin
  • Retrofit for HTTP networking with Kotlinx Serialization
  • Wire (gRPC) for Protobuf-based API communication

Features

Authentication & Registration (backed by Ory Kratos)

  • Login with email/password
  • Registration flow with multi-step onboarding
  • Email verification via deep-link
  • TOTP (two-factor authentication) setup and verification
  • Forgot password / email recovery
  • Session management with bearer token refresh

Onboarding

  • Phone number verification
  • TOTP setup screen (via AuthGraph)
  • Wallet address creation
  • KYC (Know Your Customer) flow supporting multiple providers:
    • Persona — embedded SDK
    • PTI — local HTML asset via WebView (fiant_pti_wrapper_mobile.html)
    • GateHub — WebView-based flow

Home

  • Multi-account wallet overview
  • Real-time transaction updates via Pusher
  • Account details screen
  • Add account flow

Money Flows

  • Send Money — ILP-based peer payment
  • Withdraw Money — withdraw funds from wallet
  • Deposit Money — top up wallet balance
    • Connect Bank Account flow
  • 3DS Payment Confirmation — in-app dialog to confirm card payments requiring 3-D Secure

Cards

  • Virtual card ordering
  • Physical card ordering with delivery address selection
  • Card activation screen

Transactions

  • Transaction list with status display
  • Per-transaction detail state

Settings

  • Profile screen
  • Account info
  • Documents viewer (PDF/HTML via WebView)

Networking

Retrofit (HTTP)

  • Kotlinx Serialization converter for JSON parsing
  • OkHttp client with logging interceptor
  • Bearer token interceptor and authenticator for automatic token refresh
  • Suspend functions for coroutine-based async operations
  • Type-safe API interfaces with annotations
  • Support for both main API and self-service (Ory Kratos) endpoints

Wire / gRPC (Protobuf)

  • Protobuf schema generated at build time via the Wire Gradle plugin
  • Used for wallet and transaction operations

Pusher (Real-time)

  • PusherDataSource for subscribing to live events
  • PusherLifecycleManager tied to HomeViewModel for automatic connect/disconnect
  • Events consumed as a Flow in HomeViewModel

Data Layer

Component Purpose
AuthRepository Login, registration, session
MainRepository Wallet, transactions, wallet address
OnboardingRepository KYC, phone/email verification steps
CardsRepository Card ordering and management
SessionRepository Persistent session token storage
TotpRepository TOTP setup and verification
FeatureFlagsRepository Feature flag evaluation
HtmlAssetsRepository Serving local HTML files into WebView
DocumentsUrlRepository Legal/document URL resolution
PusherDataSource Real-time event streaming

Navigation

The app uses Jetpack Navigation 3 with typed route objects:

  • AuthGraph — login, register, create password, TOTP setup
  • OnboardingGraph — email verification, phone verification, wallet address, KYC
  • HomeGraph — home, account details, add account, send/deposit/withdraw money, connect bank
  • CardsGraph — cards list, order virtual/physical card, delivery address, activation
  • TransactionsGraph — transaction list
  • SettingsGraph — settings, profile, account info, documents

Deep-link support is configured in AndroidManifest.xml and routed through RegisterViewModel for email verification.

Design System

A custom design system lives under presentation/designsystem/ and includes:

  • IlpTheme with light/dark variants
  • Color tokens, typography, and shape definitions
  • Reusable composable components

Code Quality

Static Analysis

  • ktlint — Kotlin code formatting
  • Detekt — Static code analysis
  • Test email guard — blocks hardcoded test email addresses (e.g. @breakpointit.eu) from entering non-test Kotlin source

Testing

  • JUnit — Unit tests
  • Espresso — UI tests
  • Konsist — Architecture compliance tests

Development

First-Time Setup

After cloning, install the project's git hooks (one command, per machine):

bash .github/scripts/install_hooks.sh

This points git at the tracked .githooks/ directory so the pre-commit checks run automatically before every commit.

Building & Running the App

Prerequisites: JDK 17, Android SDK (compileSdk 36, minSdk 24), and Android Studio (or just the Gradle wrapper from the command line).

Android Studio generates local.properties with sdk.dir on first sync. Add the Pusher config alongside it (values come from PUSHER_APP_KEY / PUSHER_CLUSTER env vars if omitted):

sdk.dir=/path/to/Android/sdk
PUSHER_APP_KEY=<pusher-app-key>
PUSHER_CLUSTER=eu

The app defines several build variants, each pointing at a different backend domain:

Variant Backend domain Purpose
debug sandbox.interledger.app Default local development build
local interledger.test Points at a locally-run backend
development development.interledger.app Shared development environment
beta sandbox.interledger.app Signed pre-release build
release interledger.app Production build

Build and install a variant on a connected device/emulator:

./gradlew installDebug

From Android Studio: open the project, pick a build variant in the Build Variants panel, select a device, and click Run.

To just assemble an APK without installing:

./gradlew assembleDebug   # or assembleLocal / assembleDevelopment / assembleBeta / assembleRelease

Running Tests

# Run all tests
./gradlew test

# Run architecture tests
./gradlew --tests "*ArchitectureTest*"

# Run UI tests
./gradlew connectedAndroidTest

Code Quality Checks

# Format code
./gradlew ktlintFormat

# Check formatting
./gradlew ktlintCheck

# Static analysis
./gradlew detekt

# All quality checks
./gradlew ktlintCheck detekt test

CI/CD

The project uses GitHub Actions for continuous integration:

  • CI Pipeline — Runs on push/PR to main/develop branches
  • Release Pipeline — Builds and signs an APK + App Bundle on version tags, then publishes a GitHub Release

Cutting a release

Push a v* tag to trigger a build. The channel is inferred from the tag itself:

Tag Channel Build type Example
vX.Y.Z Production release v1.0.0
vX.Y.Z-<label> Beta beta v1.0.0-beta1, v1.0.0-beta2, v1.0.0-rc1

Any tag with a suffix after the version core (-beta1, -rc1, etc.) is treated as a beta build — push as many betas as needed for the same base version, each with an incrementing label. A bare vX.Y.Z tag (no suffix) builds and releases production.

# Beta
git tag v1.0.0-beta1 && git push origin v1.0.0-beta1

# Production
git tag v1.0.0 && git push origin v1.0.0

Beta releases are published as a GitHub prerelease; production releases are published as the latest release. versionName matches the tag suffix (e.g. 1.0.0-beta1), and versionCode is the commit count on the tagged ref.

Quality gates include:

  • Unit tests
  • Architecture tests
  • Code formatting (ktlint)
  • Static analysis (Detekt)
  • Lint checks
  • Test email guard (.github/scripts/check_test_emails.sh)

The same check runs as a pre-commit hook locally (requires first-time setup above) and as a CI step on every PR. To add a new forbidden email pattern, extend the FORBIDDEN variable in .github/scripts/check_test_emails.sh:

FORBIDDEN="@breakpointit\\.eu|staging@example\\.com"

License

Copyright 2026 Interledger Foundation. Licensed under the Apache License 2.0.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages