Trustless

Trustless-logo-dark       AppStore     Wallet Scrutiny    X-logo

Intro

Hi! Trustless is a fully open-source, non-custodial (only you have access to your keys), privacy-focused, Bitcoin-only mobile wallet. It is very minimalist and easy to use, yet very functional.

Table of contents

Main features

Getting started

To run the project in development mode, you need node-js and a setup for ios (xcode) or android (android studio).

  1. Clone the repository:
    git clone https://github.com/trustlesswallet/trustless.git
    cd trustless
    
  2. Install dependencies:
    npm install
    
  3. Run on device / simulator:

    • ios (mac only):
        npm run ios
      

      To run on a physical device, add the -- --device flag and ensure your iphone is connected.

    • android:
        npm run android
      

      Make sure you have an android emulator running or a physical device connected.

    • Manual build (advanced): If the automated commands fail, you can generate the native directories and build manually:
        npx expo prebuild --clean
        cd ios && pod install && cd ..
      

      Then open a trustless workspace file in your ios folder to open the project in xcode. From there you can install the app manually.

Making lightning work

Trustless uses Breez SDK to handle lightning operations. SDK requires an API key to work. For obvious reasons we don’t push the .env file with the key to the GitHub repo. To make lightning work you will have to create your own .env file in the root of the directory and add your own Breez API key there like this: EXPO_PUBLIC_BREEZ_API_KEY=your_api_key . To get the API key just fill out the form on Breez’s website. You will receive a key to your email address. This is completely free.

Reproducible build instructions

Maintainer release checklist 1. Ensure the working tree is completely clean to avoid the dirty flag. 2. Create and push the new tag: `git tag -a 3.1.1 -m "release 3.1.1"` `git push origin 3.1.1` 3. Go to GitHub Actions → "Reproducible release build" → Run workflow → enter the tag. 4. Wait for the build to complete and download the unsigned APK artifact (`trustless-unsigned-apk`). 5. If the keystore is missing, generate a new one in the current directory: `keytool -genkey -v -keystore trustless-release.keystore -alias trustless-alias -keyalg RSA -keysize 2048 -validity 10000` 6. Sign the downloaded unsigned APK: `apksigner_path=$(find ~/Library/Android/sdk/build-tools -name "apksigner" | sort -r | head -n 1)` `$apksigner_path sign --ks trustless-release.keystore --ks-key-alias trustless-alias --out trustless-v3.1.1-release.apk app-release-unsigned.apk` 8. Generate the official hash: `shasum -a 256 trustless-v3.1.1-release.apk` 9. Create the GitHub release. Upload the signed package and paste the hash into the release notes. **Build environment:** Ubuntu (linux/amd64), `reactnativecommunity/react-native-android@sha256:88d93a9282e0f54f84cec7b979da6c5e3f20d87f5be246b75c231838be852fec`, Node.js 22.14.0, NDK 27.1.12297006.

To verify that the official binary was built exactly from the published source code, follow the steps below. This process compares the internal contents of the official signed package (published on GitHub) against a locally built unsigned package (your local build).

The official APK is built on Linux (amd64) inside a pinned Docker container. To get a matching result, your local build must use the same environment.

  1. Download the signed release: Download the official signed file from the GitHub releases page into a new empty directory. (Replace the version number with the one you are testing).
    curl -L -o trustless-release.apk https://github.com/trustlesswallet/trustless/releases/download/3.1.1/trustless-v3.1.1-release.apk
    
  2. Verify the hash matches the one listed on GitHub:
    shasum -a 256 trustless-release.apk
    
  3. Clone the repository and check out the release tag:
    git clone https://github.com/trustlesswallet/trustless.git
    cd trustless
    git checkout 3.1.1
    
  4. Build the local unsigned package:
    docker run --rm --platform linux/amd64 \
      -v "$(pwd):/app" -w /app \
      reactnativecommunity/react-native-android@sha256:88d93a9282e0f54f84cec7b979da6c5e3f20d87f5be246b75c231838be852fec \
      bash -c "
      curl -fsSL -o /tmp/node.tar.gz https://nodejs.org/dist/v22.14.0/node-v22.14.0-linux-x64.tar.gz && \
      tar -xzf /tmp/node.tar.gz -C /usr/local --strip-components=1 && \
      rm /tmp/node.tar.gz && \
      node --version && \
      bash reproducibility.sh
      "
    

    Note: on macOS this runs under emulation and will be slow. A native Linux machine is recommended for faster verification.

  5. Unpack both packages: Android packages are zip archives. Extract both into separate directories for comparison.
    cd ..
    mkdir unpacked-signed unpacked-unsigned
    unzip -q -o trustless-release.apk -d unpacked-signed
    unzip -q -o trustless/android/app/build/outputs/apk/release/app-release-unsigned.apk -d unpacked-unsigned
    
  6. Strip metadata and compare: Remove the META-INF directory from both folders. This directory contains the cryptographic developer signature and timestamps that will never match between a signed and unsigned package. Compare everything else.
    rm -rf unpacked-signed/META-INF unpacked-unsigned/META-INF
    diff -r unpacked-signed unpacked-unsigned
    

    If the diff command returns empty output, the contents are identical bit-for-bit. The build is reproducible.

Lightning reproducibility implications

Trustless uses Breez SDK to handle lightning operations. The SDK requires an API key, which is not committed to the repository. Therefore, proper code reproduction is only possible without an API key, meaning lightning won’t work in a locally built version. With that said, even without the .env file, all lightning-related code is still compiled into the build, guaranteeing code integrity.

Contributing

We welcome contributions to Trustless! Please follow the standard fork-and-pull request workflow.

Contribution process

  1. Fork the repository to your own github account.
  2. Clone your fork to your local machine.
  3. Create a new branch for your feature or fix.
  4. Make your changes and commit them.
  5. Push your branch to your fork.
  6. Open a pull request against the main branch.

Guidelines

License

This project is licensed under the GNU General Public License v3.0 (GPLv3). See the LICENSE file for details.