diff options
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..c2c7d5f --- /dev/null +++ b/README.md @@ -0,0 +1,118 @@ +# coinosv3-server + +The server-side services behind [coinos v3](https://v3.coinos.io), the +bitcoin, Ark, Lightning and nostr wallet whose app lives in +[coinosv3](https://git.coinos.io/coinosv3.git). The wallet itself is +self-custodial and runs in the browser. These services hold no keys to user +funds; they give a wallet a payment address, wake it when a request arrives, +and store its encrypted sync data. + +| Directory | Service | Public at | +| ---------- | ------- | --------- | +| `names/` | **Payment-name registrar.** Gives each wallet a `[email protected]` address: BIP-353 DNS records (written through Cloudflare's API), LNURL-pay, and a BOLT 12 offer per name on the Ark server's Lightning node. Settled payments are forwarded to the name's Ark address from a small float wallet. Also serves zap receipts, point-of-sale invoices, CLINK, payment webhooks, link previews and translation. Writes are authorized with NIP-98. | `names.coinos.io` | +| `nwcpush/` | **NWC push notifier.** Watches relays for Nostr Wallet Connect requests addressed to registered wallet-service keys and wakes the device with a Web Push, so a closed wallet can answer. | (internal, behind the app) | +| `blossom/` | **Blossom server for sync envelopes.** Stores only the wallet's encrypted cross-device state blobs, which can outgrow a relay's event size. Refuses anything else. | `blossom.coinos.io` | +| `feed/` | **Public feed snapshot** (`/api/feed`) and server-rendered note and profile pages. | `v3.coinos.io` | +| `vmedia/` | **Media helper** for the feed: video posters, H.264 fallbacks and resized pictures. | `v3.coinos.io/vmedia/` | +| `bridge/` | Ark to Lightning swap bridge. **Retired**: the app uses the Ark server's Lightning. `bridge/ln.js` (a minimal CLN RPC client) is still used by `names/`. | — | + +## Shared code: the `coinosv3` submodule + +The services use the wallet's own code for Ark, BOLT 12 and nostr helpers, +so the server speaks exactly the wire format and policy the app does. That +code comes from the `coinosv3/` submodule, **pinned to a specific commit**. +Moving the pin is a deliberate, reviewable commit of its own: + +```sh +git -C coinosv3 fetch && git -C coinosv3 checkout <commit> +git add coinosv3 && git commit -m "coinosv3 → <commit>" +``` + +`names/vendor/` holds two text helpers, `lang-guess.js` and +`translate-split.js`, at the versions the server runs. They are newer than the +current pin, and both go once the pin moves past them. + +## Running + +You need [Bun](https://bun.sh) (the deployment pins `oven/bun:1.3.14`) and, +for `names/`, a Core Lightning node's RPC socket and a Cloudflare zone. + +```sh +git clone --recurse-submodules https://git.coinos.io/coinosv3-server.git +cd coinosv3-server +bun install +cp names/config.example.json names/config.json # fill it in +NAMES_CONFIG=names/config.json bun names/server.js +``` + +Each service reads a JSON config. `names` uses `NAMES_CONFIG` and `nwcpush` +uses `NWCPUSH_CONFIG`; `blossom` reads `BLOSSOM_*` environment variables +(see the header of `blossom/server.js`). Example configs: +`names/config.example.json`, `nwcpush/config.example.json`, +`bridge/config.example.json`. + +**Configs hold secrets and are never committed.** They include the DNS +provider's API key, admin tokens, the forwarder float's mnemonic, VAPID keys +and nostr secret keys. `.gitignore` excludes every `*config*.json` except the +examples, and all runtime state. + +### With Docker + +`compose.yml` runs `names`, `nwcpush` and `blossom` from the checkout, +mounted read-only. Configs and state live outside it, under a directory you +name in a `.env` file: + +```sh +# .env +STATE=/srv/coinosv3-state +CLN_RPC=/path/to/lightning-rpc +``` + +``` +$STATE/names/config.json $STATE/names/data/ (names.db) +$STATE/nwcpush/config.json $STATE/nwcpush/data/ + $STATE/blossom/data/ +``` + +```sh +docker network create net # once; the services share it with the reverse proxy +docker compose up -d +``` + +## State + +`names` keeps its state in SQLite (`names.db`, see `names/store.js`): one row +per name, offer, invoice and so on. Each change is a single transaction that +writes only the rows that changed. On its first start it imports the older +JSON state file named by `stateFile`, and a corrupt file stops startup rather +than starting empty. For a consistent backup while it runs, take a snapshot +through SQLite, not by copying the file: + +```sh +sqlite3 names.db "VACUUM INTO 'names-backup.db'" +``` + +## Deploying + +coinos deploys by pushing to a bare repository on the server. +`deploy/post-receive` is its hook. A push to `prod` checks the commit out, +installs dependencies, restarts the services whose files changed, and mirrors +the commit to [git.coinos.io](https://git.coinos.io) and gittr. Don't copy +files onto the server by hand: what runs should always be a commit. + +```sh +git push prod HEAD:prod && git push origin HEAD:master +``` + +## Tests + +```sh +bun test names/store.test.js +``` + +`tools/` holds the older end-to-end and unit scripts for the registrar, feed +and translation. They are run directly with `bun tools/<file>`. + +## License + +MIT, see [LICENSE](LICENSE). |
