Files
koins/apps/ios

Koins iOS

Native SwiftUI wallet for Monero and XRP. iOS only, no JavaScript runtime.

Layout

Koins/
  KoinsApp.swift            App entry point
  AppModel.swift            Observable state, orchestrates both chains
  Models.swift              Chain / wallet / transaction models
  SelfTest.swift            Launch-time verification (see below)
  Bridge/
    Koins-Bridging-Header.h
    KoinsMoneroWallet.h/.mm ObjC++ bridge to the monero-cpp wallet
    KoinsSecp256k1.h/.mm    secp256k1 via the OpenSSL bundled in the monero lib
  Monero/
    libs/                   prebuilt monero archives (simulator + device)
    include/                monero-cpp headers
    toolchain/              how those archives are built, plus the depends patches
  Support/                  Base58, RIPEMD-160, hashing, Keychain, wallet store
  Wallet/                   XRP keys, binary codec, RPC client, services
  Views/                    SwiftUI screens

How the chains are implemented

  • Monero: the wallet runs on device through libkoins_monero_merged.a (monero-project wallet2 + monero-cpp, built for aarch64-apple-ios and the arm64 simulator). KoinsMoneroWallet serialises all C++ work on a private queue and exchanges JSON with Swift. Wallet files live in the app's Documents directory; the recovery seed is stored in the Keychain.
  • XRP: implemented directly in Swift, no third-party package.
    • Recovery phrase: a 12 word BIP-39 mnemonic, derived to the standard XRP account path m/44'/144'/0'/0/0 (BIP-32, secp256k1), so the same words restore the same account in hardware and other mobile wallets.
    • Imports also accept legacy XRP family seeds (sEd… / s…), including the Ed25519 and secp256k1 variants.
    • Key derivation and signing: Ed25519 via CryptoKit and secp256k1 via the OpenSSL build embedded in the monero static library.
    • Transaction serialization: canonical XRP binary encoding plus the STX/TXN hash prefixes, matching ripple-binary-codec.
    • Network: JSON-RPC against public XRP Ledger endpoints with failover.

Build

cd apps/ios
xcodegen generate
xcodebuild -project Koins.xcodeproj -scheme Koins -configuration Debug \
  -sdk iphonesimulator -destination 'generic/platform=iOS Simulator' \
  ARCHS=arm64 ONLY_ACTIVE_ARCH=NO -derivedDataPath /tmp/koins-dd build

Install and run on a booted simulator:

xcrun simctl install <udid> /tmp/koins-dd/Build/Products/Debug-iphonesimulator/Koins.app
xcrun simctl launch <udid> com.koins.app

Re-run xcodegen generate after adding or removing source files. No CocoaPods and no Swift packages are used. The same commands work for a device: pass -sdk iphoneos -destination 'generic/platform=iOS' and Xcode links the device Monero archive automatically.

Verification

The XRP implementation is checked against vectors produced by the reference JavaScript stack (xrpl, ripple-keypairs, ripple-binary-codec).

Cryptography and serialization (no network):

xcrun simctl launch <udid> com.koins.app -koinsSelfTest
xcrun simctl spawn <udid> log show --last 1m --predicate 'subsystem == "com.koins.app"' --style compact

Live network check (creates and then removes a temporary wallet on both chains, talks to a Monero daemon and the XRP Ledger):

xcrun simctl launch <udid> com.koins.app -koinsSelfTestNetwork

Notes

  • The Monero daemon default is xmr-node.cakewallet.com:18081 with two fallbacks; MoneroService reconnects on demand.
  • Ed25519 and OpenSSL ECDSA both use randomised nonces, so signatures are valid but not byte-identical to deterministic implementations such as ripple-keypairs. Signatures are verified rather than compared.
  • Refresh the simulator build when /tmp is cleared: the intermediate build products live in /tmp/koins-dd.