aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md4
1 files changed, 3 insertions, 1 deletions
diff --git a/README.md b/README.md
index c181376a..35704685 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,8 @@ To get started, clone or download the repo, then:
- run `pnpm run dev` every time you want to start up the UI
- run `pnpm format` to format the code before committing any changes
+This is a frontend for [`coinos-server`](https://github.com/coinos/coinos-server), so you will need to have that running in order for this UI to be useful.
+
## Libraries
This UI uses the following libraries:
@@ -27,4 +29,4 @@ This UI uses the following libraries:
### Internationalization
-CoinOS has a system for translation using [`svelte-i18n`](https://www.npmjs.com/package/svelte-i18n). For more information and instructions on how to translate CoinOS, click [here](./doc/i18n.md). For technical details, click [here](./doc/i18n-technical.md).
+CoinOS has a system for translation using [`sveltekit-i18n`](https://www.npmjs.com/package/sveltekit-i18n). For more information and instructions on how to translate CoinOS, click [here](./doc/i18n.md). For technical details, click [here](./doc/i18n-technical.md).
/a> 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
# coinos v3

A self-custodial Bitcoin wallet and Nostr client that runs entirely in the
browser. Your keys are made and kept on your device; there is no account,
email or password. One app holds an on-chain **Savings** balance, an
off-chain **Spending** balance on [Ark](https://ark-protocol.org) with
Lightning built in, a `[email protected]` payment address, and a full Nostr
social client: feeds, zaps, private messages and group chats.

- Live at **https://v3.coinos.io** (installable as a PWA)
- Android: [Zapstore](https://zapstore.dev), a direct APK at
  `v3.coinos.io/coinos.apk`, and an F-Droid build (`io.coinos.fdroid`, in review)
- Offline: `standalone.html` is the whole wallet in one file you can save and
  open from disk


## Features

### Wallet core (always included)

- **BIP84 / native SegWit** HD wallet from a 12-word BIP39 seed (any valid
  phrase imports; optional passphrase).
- **Watch-only wallets** from an account xpub/zpub: receive and view history
  without the seed; load the seed later to spend.
- **Offline / air-gapped signing**: export a keyless snapshot on an online
  device, sign on an offline one, and carry the signed transaction back by QR
  to broadcast.
- **Per-wallet networks**: mainnet, testnet, signet, mutinynet or regtest,
  stamped on each wallet, so wallets on different networks coexist.
- **Choose your data source**: Electrum-over-WebSocket servers
  (`electrum.coinos.io` by default) or Esplora REST explorers, with failover,
  or your own node.
- **Real-time receives** over WebSocket where the source supports it, polling
  as the fallback; replaced (RBF) transactions are pruned automatically.
- **Sending** with coin selection, fee estimation, a fee-rate picker,
  send-max, multiple recipients and a camera QR scanner (addresses, BIP21,
  invoices, signed transactions).
- **One fresh address at a time**, so scans stay small (no gap-limit probing).
- **Fiat** balances and history values in your currency, with the rate at the
  time of each payment.
- 20 languages.

### Spending on Ark (feature: `ark`)

A native-JS client for [bark/captaind](https://gitlab.com/ark-bitcoin/bark)
Ark servers: gRPC-web and MuSig2 spoken directly, no WASM. coinos runs
`ark.coinos.io`; other captaind servers can be chosen.

- **Instant off-chain payments** between Ark users, with fees shown before
  anything moves (free between coinos wallets).
- **Lightning in and out of the Ark balance** through the Ark server's own
  Lightning node (HTLC-locked VTXOs), with no swap service. Routing fees are
  quoted before you pay.
- **Board** on-chain coins into Spending and **offboard** back to Savings or
  any on-chain address in one cooperative transaction.
- **Automatic renewal** before coins expire, plus a server-side scheduled
  backstop that renews them even while the app is closed.
- **Unilateral exit**: publish the coins' pre-signed transaction chain
  (CPFP-bumped, TRUC-aware) and claim after the timelock with your key alone,
  even if the server is gone. Progress is shown live.
- **Full receive-side validation** of every VTXO's transaction chain, and
  crash-safe ceremonies that checkpoint around every server round-trip.
- Ark state lives in IndexedDB, fronted by memory, and is reconciled against
  the server before money moves.

### Payment addresses (feature: `names`)

- **`[email protected]`**: a name claimed on first run that works as a
  Lightning address (LNURL-pay) and as a **BIP-353** DNS payment address
  (`₿[email protected]`, a DNSSEC-signed TXT record).
- Paying a BIP-353 name validates its **DNSSEC chain in the browser**.
- **BOLT12 offers**: pay `lno1…` offers (invoice signatures checked
  client-side) and publish your own offer in your DNS record.
- **CLINK** offer codes (`noffer1…`): request invoices over Nostr.
- **Moving from coinos.io**: existing coinos.io users can bring their
  username over; payments to the legacy account are forwarded to the new
  wallet.

### Zaps and Nostr Wallet Connect (features: `zaps`, `nwc`)

- **NIP-57 zaps** to any npub, Lightning address or LNURL, with one-tap zaps
  in the feed and a custom-amount screen on long press.
- **coinos as an NWC wallet service (NIP-47)**: connect Damus, Amethyst,
  Primal and others, with per-connection keys and budgets.
- **Background answering**: a Web Push from `nwcpush` wakes the service
  worker, which pays and replies from the browser even with the app closed
  (keys never leave the device). Multi-device safe: one device answers each
  request.

### Gifts (feature: `gifts`)

- **Gift links**: bitcoin you send as a link, claimable straight into a
  brand-new wallet or an existing one. On-chain gifts use a one-time key so
  they can't be front-run; Ark gifts are claimed instantly and free.
- Reclaim or revoke unclaimed gifts; optionally lock a gift to a Nostr
  account (the claim code is DM'd to them).

### Point of sale (feature: `pos`)

- Enter an amount, the customer picks a tip, and one Lightning invoice
  settles it; bills and tips are kept apart in history.

### Sign-in (feature: `nostrlogin`)

- **Seed phrase**, created or imported.
- **Passkeys**: the WebAuthn PRF extension derives the wallet's secret.
- **Google**, via pomegranate: the Nostr key is FROST-sharded 2-of-3 across
  independent operators.
- **Nostr signers**: browser extensions (NIP-07), remote signers
  (`bunker://` and `nostrconnect://`, NIP-46) and Amber on Android (NIP-55).
  A pasted or signer key becomes a recovery key for the wallet.
- Several identities side by side, each with its own wallet; switch or sign
  out per identity.

### Cross-device sync (feature: `sync`)

- Wallet state, read receipts and custom feeds are **NIP-44 encrypted to
  yourself** and published as replaceable Nostr events, one per domain (core
  wallet, Ark, NWC, …), so only what changed republishes.
- Domains too big for a relay event go to **Blossom** as an encrypted blob
  (`blossom.coinos.io` by default, or any Blossom server); the event carries
  its hash.
- A durable outbox holds signed snapshots until a relay accepts them.

### Social: a Nostr client (feature: `messages`)

**Feeds**
- **Following**, a curated **Popular** feed (prose in your language that
  several people engaged with), and **custom feeds** from people, hashtags,
  relays, follow packs or NIP-51 lists. Custom feeds sync across devices;
  people feeds publish as NIP-51 follow sets.
- Shareable feed links (`/feed/<npub>`, `/feed/t/<tag>`, packs and lists).
- **Views**: All, an **Images** grid, **Videos** (full-screen vertical clips
  with autoplay), and long-form **Articles** (NIP-23).
- Cached posts paint first and new ones arrive without moving what you're
  reading; long feeds are windowed.

**Posts**
- Replies, reposts, quotes, reactions, polls (NIP-88) and zaps on one
  action bar, with who-reacted panels.
- Link previews, YouTube embeds, audio players for podcast links, article
  cards for `naddr` references, and inline quoted notes.
- Compose with pictures and video (compressed on device, uploaded to
  Blossom media hosts).
- Linkable notes and profiles (`/nevent1…`, `/npub1…`), with server-rendered
  pages for link previews elsewhere.

**Moderation**
- Your NIP-51 mute list (people, words, hashtags, threads, including its
  private half) applied everywhere; reports (NIP-56) from people you follow
  fold posts; duplicate and hashtag-spam filtering.

**Messages**
- **Private DMs** (NIP-17 gift-wrapped), with replies, reactions and
  encrypted attachments.
- **Communities** on Concord: end-to-end encrypted channels compatible with
  Vector, including Vector's custom emoji packs (NIP-30) and community icons.
  Every user joins the coinos community; anyone can create or join others.
- **Group chats** on White Noise (Marmot) and on **Cordn** (the MLS group
  chats in Amethyst 1.17 and the Cordn app, delivered through a coordinator
  that only ever sees sealed bytes), both on a native-JS MLS (RFC 9420)
  implementation.
- **Notifications** for mentions, replies, reactions and zaps, with push
  delivery to your devices.

### Extras

- **Hats** (feature: `hats`): supporter hats worn above your avatar.


## Modular builds

Every optional feature above is a **plugin behind a build seam**.
`COINOS_FEATURES` selects what ships; excluded features never enter the
bundle (their code, their network endpoints, their crypto):

```bash
bun run build                                 # everything
COINOS_FEATURES=ark,gifts bun run build       # core + ark + gifts
bun run build:minimal                         # core on-chain wallet only
```

Feature names: `gifts`, `ark`, `nostrlogin`, `names`, `zaps`, `nwc`, `hats`,
`sync`, `messages`, `pos`. `tools/minimal-smoke.js` checks the minimal
profile is a working on-chain wallet with no feature code in the bundle.

Other build switches:

| Variable | Effect |
| --- | --- |
| `COINOS_TARGET=staging` | mutinynet-first defaults and a visible staging stamp |
| `COINOS_NO_SW=1` | no service worker (the bundled Android/F-Droid build) |


## Develop

Requires [Bun](https://bun.sh).

```bash
bun install
bun run dev      # http://localhost:5173 (rebuilds on each refresh)
```

The dev server proxies local regtest backends (Electrum, Esplora) so the app
works unchanged from a phone on the LAN. The end-to-end suites in `tools/`
drive headless Chrome through real flows (boarding, Ark sends, Lightning,
offboard, exit, gifts, feeds, chat) against a regtest stack or live relays.


## Build

```bash
bun run build    # → dist/
```

- `dist/index.html` is a small shell; the app loads as `app-<hash>.js` plus
  lazily loaded `chunk-<hash>.js` features.
- `sw.js`, `manifest.webmanifest` and icons make it an installable PWA that
  works offline.
- `dist/standalone.html` inlines everything (code, libraries, CSS, fonts):
  save it and open it from disk with no server.


## Services in this repo

The app is static; these small services run beside it (Bun):

| Directory | Service |
| --- | --- |
| `names/` | Payment-name registrar (`names.coinos.io`): BIP-353 TXT records via the DNS provider's API, LNURL-pay for `@coinos.io` names, NIP-98 auth, link previews |
| `feed/` | Public feed snapshot (`/api/feed`) and server-rendered note pages |
| `nwcpush/` | Watches relays for NWC requests and push notifications, and wakes devices with Web Push |
| `blossom/` | `blossom.coinos.io`: a Blossom server that only stores encrypted sync envelopes |
| `bridge/` | Ark→Lightning swap bridge (retired; the app uses the Ark server's Lightning) |


## How state is kept

1. **sessionStorage** keeps the wallet open across a refresh (cleared on
   lock or tab close).
2. **localStorage** caches scanned state, feeds and profiles per wallet and
   network, so a reload paints instantly.
3. **IndexedDB** holds Ark coins, the feed media index and White Noise MLS
   state.
4. **Nostr** (and Blossom for large domains) holds the encrypted
   cross-device copy.


## Layout

| Path | Purpose |
| --- | --- |
| `src/wallet.js` | BIP84 core: derivation, scanning, coin selection, signing, realtime, cache, and the feature seams |
| `src/api.js` / `src/electrum.js` | Data sources: Esplora REST and Electrum-over-WebSocket, presets and failover |
| `src/ark/` | Native-JS Ark: gRPC-web codec, arkoor sends, board, refresh rounds, offboard, Lightning, exit, validation, crash-safe manager, IndexedDB store |
| `src/features/` | Feature plugins (see Modular builds); `index.js` is rewritten at build time by `COINOS_FEATURES` |
| `src/nostr.js` / `src/sync-*.js` | Encrypted state sync, relay pool, Blossom envelopes, the sync outbox |
| `src/nostr-login.js` / `src/passkey.js` / `src/pomegranate.js` | Nostr signers, passkey PRF sign-in, Google via FROST |
| `src/dm.js` / `src/concord.js` / `src/mls.js` / `src/marmot*.js` / `src/cordn*.js` / `src/contextvm.js` | NIP-17 DMs, Concord communities, MLS, the White Noise layer, and Cordn over ContextVM |
| `src/bip353.js` / `src/dnssec.js` / `src/bolt12.js` / `src/noffer.js` / `src/clink.js` / `src/lnurl.js` | Payment-name resolution with DNSSEC validation, BOLT12, CLINK, LNURL and zaps |
| `src/sw-nwc.js` / `src/nwc-*.js` | Background NWC answering in the service worker |
| `src/app.js` | UI controller (vanilla DOM, no framework) and feature registry |
| `build.js` / `dev.js` | Bun bundler (split build, PWA, standalone file); dev server with regtest proxies |
| `android/` | Android wrapper: a Trusted Web Activity build and a bundled F-Droid flavor |


## Security notes

- Self-custody software handling real keys: a hot wallet whose keys live in
  the browser. Review the code before trusting it with funds; for large
  amounts use the offline-signing flow or don't keep them in a hot wallet.
- **Ark trust model**: the Ark server co-signs off-chain spends and decides
  off-chain spent/unspent state, but it can never spend your coins, and the
  pre-signed exit path returns them on-chain without its cooperation. Ark
  coins expire if never renewed; the wallet renews them automatically.
- **Lightning via the Ark server**: payments are HTLC-locked, so the server
  can fail a payment but not take the funds.
- **NWC background answering** means `nwcpush` learns your wallet-service
  pubkeys and when requests arrive (not their contents).
- Your data source sees your addresses and IP; point it at your own node
  for privacy. Synced state is end-to-end encrypted; relays see only
  ciphertext and timing.


## License

MIT, see [LICENSE](LICENSE).