
# OS Vault
**Self-custody, multi-chain crypto wallet for macOS.**
One recovery phrase. Six chain families. Zero API keys. Nothing ever leaves your Mac.
by **Simon-Pierre Boucher** ยท [contact@spboucher.ai](mailto:contact@spboucher.ai)
[](#requirements)
[](#build)
[](#architecture)
[](#tests)
[](../../releases)
[](#release-pipeline)
[](#infrastructure--no-api-keys)
[](#security-model)
[](#chains)
[](#chains)
[](#chains)
[](#chains)
[](#chains)
[](#chains)
---
## Why OS Vault
Most wallets make you choose: convenience (custodial, tracked, keyed APIs) or
sovereignty (CLI tools, manual everything). OS Vault refuses the trade:
- ๐ **Your keys, your Mac, your encryption.** The BIP-39 mnemonic is sealed
with OS Vault's **own vault format** โ PBKDF2-HMAC-SHA512 (600k rounds) โ
AES-256-GCM โ in a local file. No macOS Keychain, no iCloud, no telemetry.
- ๐ **One phrase, every chain.** The same 12 words derive Bitcoin (BIP-84),
11 EVM chains, Solana, Tron, XRPL and TON โ cross-validated against
independent crypto stacks in the test suite.
- ๐๏ธ **Zero mandatory API keys.** Every endpoint is public and keyless, with
automatic failover. The only egress is blockchain RPC (+ optional CoinGecko
prices, one toggle to kill).
- โ๏ธ **Sign-and-forget.** The private key exists only for the milliseconds a
transaction is being signed โ every send re-derives it from your password
and discards it.
## Chains
| Family | Assets | Fees handled | Testnet default |
|---|---|---|---|
| **EVM ร 11** โ Ethereum, Base, Arbitrum, OP, Polygon, BNB, Avalanche, Gnosis, Linea, Scroll (+ Base Sepolia) | USDC, USDC.e, USDT, DAI, USDS, EURC + native coin | EIP-1559, BSC zero-base-fee, **OP-stack/Scroll L1 data fee via oracle**, Arbitrum inclusive estimates, Linea pinned base | Base Sepolia |
| **Bitcoin** | BTC (native SegWit `bc1qโฆ`) | sat/vB presets live from mempool.space, RBF on | Signet |
| **Solana** | SOL + USDC (SPL) | ATA rent surfaced when the recipient has no token account | Devnet |
| **Tron** | TRX + USDT (TRC-20) | **Energy burn estimated pre-send** (~13โ27 TRX), fee_limit capped | Nile |
| **XRP Ledger** | XRP + RLUSD | Reserves shown as locked; **one-tap RLUSD trustline**; recipient trustline checked | Testnet |
| **TON** | TON + USDT (jetton) | Jetton-wallet indirection handled; ~0.07 TON attached, excess refunded | Testnet |
Every stablecoin contract address and decimal count was **verified live
on-chain** before registration โ including the traps: BNB-peg USDT/USDC are
18 decimals, bridged USDC.e is indistinguishable from native USDC by
`symbol()` alone, DAI is 18 while USDC is 6. See
[`docs/STABLECOINS.md`](docs/STABLECOINS.md).
## Security model
```
password โโโถ PBKDF2-HMAC-SHA512 (600k) โโโถ AES-256-GCM โโโถ vault.json (0600)
โฒ
wrong password / tampering โโ indistinguishable (GCM auth)
unlock โโโถ public addresses only stay in memory
send โโโถ password โ derive key โ sign โ discard (every single time)
```
- Forced written-backup verification (3 random words) before the wallet exists
- Confirm screen with recipient, amount, network, worst-case fees โ always
- EIP-55 checksums; per-chain address validation; TESTNET badges everywhere
- App Sandbox + Hardened Runtime; signed, **notarized and stapled** by Apple
- The watch-only Bitcoin wallet holds public descriptors only; a throwaway
in-memory signer signs PSBTs
## Infrastructure โ no API keys
| Concern | Source (keyless) | Fallback |
|---|---|---|
| EVM RPC | PublicNode (11/11 verified) | official chain RPCs, health-scored failover |
| Bitcoin | mempool.space Esplora | blockstream.info |
| Solana | PublicNode | api.mainnet-beta.solana.com |
| Tron | TronGrid (anonymous, backoff) | โ |
| XRPL | xrplcluster.com | s1.ripple.com |
| TON | toncenter v2/v3 (1 req/s, throttled client-side) | โ |
| Prices | CoinGecko batched (USD/CAD/EUR), stale-while-revalidate, **off switch** | DefiLlama |
## Build
Pure SwiftPM โ no `.xcodeproj`, no CocoaPods, no manual steps:
```sh
scripts/vendor-walletcore.sh # one-time: vendors Trust wallet-core for macOS (~270 MB, not in git)
swift build # compile
swift test # 32 tests: BIP-39/BIP-84 vectors, vault crypto, decimals, validators
make dev # debug bundle, ad-hoc signed, launched
make release # Developer ID + notarize + staple + DMG with volume icon
```
The wallet-core vendoring is this repo's party trick: upstream ships no macOS
SwiftPM support, so the script repackages the official CocoaPods tarball as a
local `binaryTarget` โ including a surgical `ld -r` pass that demotes the
duplicate Rust runtime symbol it shares with the Bitcoin Dev Kit. Details in
[`docs/RESEARCH-MULTICHAIN.md`](docs/RESEARCH-MULTICHAIN.md).
## Architecture
```
Sources/OSVaultKit
โโโ Services
โ โโโ VaultCrypto โ the encryption mechanism (no Keychain)
โ โโโ KeyManager โ BIP-39, HD derivation, vault lifecycle
โ โโโ RPCService โ EVM JSON-RPC with endpoint failover
โ โโโ TransactionService โ EIP-1559 + 5 other real fee models
โ โโโ BitcoinService โ bdk-swift, watch-only + transient signer
โ โโโ SolanaService โ solana-swift (vendored), SPL + ATA
โ โโโ TronService โ wallet-core signing + TronGrid REST
โ โโโ XRPLService โ wallet-core signing + xrplcluster JSON-RPC
โ โโโ TONService โ wallet-core signing + toncenter v2/v3
โ โโโ PriceService โ CoinGecko keyless, cached, optional
โโโ Models โ Network (chain registry), Token (verified matrix)โฆ
โโโ Views โ SwiftUI: onboarding, home, per-chain panels
```
## Requirements
- macOS 15.5+ (Apple silicon or Intel)
- That's it. No accounts, no keys, no configuration.
## Testnet quickstart
1. Create a wallet (write the 12 words down โ the app makes you prove it).
2. Fund: [Circle faucet](https://faucet.circle.com) (USDC on Base Sepolia +
Solana devnet), a Base Sepolia ETH faucet, [mempool.space signet
faucet](https://signetfaucet.com), [nileex.io](https://nileex.io) (TRX +
test USDT), [XRPL faucet](https://xrpl.org/resources/dev-tools/xrp-faucets),
[@testgiver_ton_bot](https://t.me/testgiver_ton_bot).
3. Send. Watch it confirm on the linked explorer.
---
**Built with Swift, paranoia, and a refusal to type API keys.**
ยฉ 2026 Simon-Pierre Boucher ยท [contact@spboucher.ai](mailto:contact@spboucher.ai)