mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
docs: add Bitcoin Connect (NWC connect UX) integration plan + TODO #61
Requested: integrate getAlby/bitcoin-connect as a smooth NWC "connect wallet" front-end, keeping manual URI entry as backup. Plan (docs/bitcoin-connect-plan.md) grounds it in bitvid's existing NWC stack: BC's NWC connector exposes the raw pairing URI (provider.client.nostrWalletConnectUrl) which feeds the existing validateWalletUri → per-npub store → zap-split/pay_invoice pipeline unchanged. BC is a connect adapter, not a payment layer. Covers delivery (vendor+lazy import vs esm.sh; CSP already allows esm.sh), persistence ownership, NWC-only connector scope, least-privilege requestMethods, UI placement, FEATURE_BITCOIN_CONNECT flag, and the security constraints (bearer spending secret, Alpha lib pin/vendor). Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
793d609d6a
commit
6dd40ce330
2 files changed
+185
No files matched your search
@@ -0,0 +1,167 @@
|
||||
# Bitcoin Connect — NWC wallet connect UX — Dev Plan
|
||||
|
||||
Status: **DECISIONS NEEDED (D1–D6)** — no code yet. Adds Alby's
|
||||
[Bitcoin Connect](https://bitcoin-connect.com/) as a smooth "connect your wallet"
|
||||
front-end for NWC, feeding bitvid's **existing** NWC pipeline. Manual URI entry
|
||||
stays as the backup/advanced path. Feature-flagged (off = no trace).
|
||||
|
||||
## Executive summary
|
||||
|
||||
bitvid already has a full NWC stack: manual URI entry (`#walletUri` in the Wallet
|
||||
Connect pane → `ProfileWalletController`), validation
|
||||
(`nwcSettingsService.validateWalletUri` — requires `nostr+walletconnect://`),
|
||||
per-npub storage (`nwcSettings.js`, IndexedDB + localStorage), opt-in encrypted
|
||||
cross-login sync, and the zap-split/pay_invoice payment pipeline
|
||||
(`js/payments/*`). The friction is purely the *connect* step — pasting a URI.
|
||||
|
||||
Bitcoin Connect solves exactly that: a polished modal that walks the user through
|
||||
connecting a wallet (CoinOS, Alby Hub, mutiny, etc.) and, for the NWC connector,
|
||||
**exposes the raw NWC pairing URI**. So we bolt it on as an alternate connect
|
||||
button that extracts the URI and hands it to bitvid's existing validate→store
|
||||
pipeline. **No change to how bitvid pays or stores** — one new way to obtain the
|
||||
same string. Manual entry stays for power users / unsupported wallets.
|
||||
|
||||
## How Bitcoin Connect works (verified against the v3 README)
|
||||
|
||||
- Package `@getalby/bitcoin-connect` (ESM; Lit web components + functions; bundles
|
||||
`@getalby/js-sdk` internally — no separate peer dep). Also loadable from
|
||||
`https://esm.sh/@getalby/bitcoin-connect@<pin>` (our CSP already allows esm.sh).
|
||||
- `init({ appName, filters: ["nwc"], persistConnection, providerConfig: { nwc: {
|
||||
authorizationUrlOptions: { requestMethods } } } })` — `filters:["nwc"]` restricts
|
||||
the modal to NWC; `requestMethods` requests least-privilege scopes.
|
||||
- `launchModal()` / `await requestProvider()` opens the connect flow.
|
||||
- `onConnected((provider) => …)` → a WebLN provider. **NWC extraction:**
|
||||
```js
|
||||
import { onConnected } from "@getalby/bitcoin-connect";
|
||||
import { WebLNProviders } from "@getalby/sdk"; // or the re-export
|
||||
onConnected((provider) => {
|
||||
if (provider instanceof WebLNProviders.NostrWebLNProvider) {
|
||||
const uri = provider.client.nostrWalletConnectUrl; // ← the NWC secret
|
||||
}
|
||||
});
|
||||
```
|
||||
- `disconnect()` clears its connection; `getConnectorConfig()` returns the saved
|
||||
connector config. Persistence to localStorage is automatic when
|
||||
`persistConnection: true`.
|
||||
- ⚠️ README says the lib is **Alpha** — pin an exact version.
|
||||
|
||||
## Decisions needed
|
||||
|
||||
> **DECISION 1 — Delivery. 🔵 NEEDED.**
|
||||
> - **A — Vendor + lazy `import()`:** esbuild-bundle a pinned `@getalby/bitcoin-connect`
|
||||
> into `vendor/bitcoin-connect.bundle.min.js` (same pattern as floating-ui in
|
||||
> `scripts/build-beacon.mjs`), dynamically imported only when the user opens the
|
||||
> Wallet pane / clicks Connect. Offline-safe, supply-chain-pinned, no main-bundle bloat.
|
||||
> - **B — Lazy-load from esm.sh** (CSP already allows it) at a pinned version.
|
||||
> Zero vendoring work, but a runtime CDN dependency + supply-chain trust.
|
||||
> _Recommendation: **A** — bitvid vendors its other heavy deps; Bitcoin Connect is
|
||||
> a Lit bundle (~hundreds of KB) so lazy-import is important either way._
|
||||
|
||||
> **DECISION 2 — Persistence ownership. 🔵 NEEDED.**
|
||||
> - **A — `persistConnection: false`:** Bitcoin Connect is purely the connect UI;
|
||||
> bitvid extracts the URI and is the ONLY store (its existing encrypted-sync /
|
||||
> per-npub model). No duplicate plaintext copy in `bc:*` localStorage.
|
||||
> - **B — let it persist** and rely on `disconnect()` on bitvid logout.
|
||||
> _Recommendation: **A** — one owner of the spending secret; call `disconnect()`
|
||||
> right after extracting to be safe._
|
||||
|
||||
> **DECISION 3 — Connector scope. 🔵 NEEDED.**
|
||||
> - **A — NWC only** (`filters:["nwc"]`). Yields a URI that flows straight into the
|
||||
> existing pipeline; zap-split/pay_invoice unchanged.
|
||||
> - **B — also allow WebLN / Alby-extension / Alby Hub** connectors. Smoother for
|
||||
> Alby users, but those give a WebLN *provider*, not an NWC URI — bitvid's raw-NWC
|
||||
> payment pipeline can't consume them without a second WebLN payment path.
|
||||
> _Recommendation: **A for v1** (matches the pipeline); a WebLN path is a separate
|
||||
> later effort if there's demand._
|
||||
|
||||
> **DECISION 4 — Requested scopes. 🔵 NEEDED.**
|
||||
> `requestMethods` to request from the wallet. bitvid needs **`pay_invoice`** (zaps);
|
||||
> `get_balance` (balance display), `make_invoice` / `lookup_invoice` (receipts/tally).
|
||||
> _Recommendation: `["pay_invoice","get_balance","make_invoice","lookup_invoice"]` —
|
||||
> least privilege for what bitvid actually calls. (The wallet ultimately decides.)_
|
||||
|
||||
> **DECISION 5 — UI placement vs manual mode. 🔵 NEEDED.**
|
||||
> _Recommendation: In the Wallet Connect pane, make **"Connect wallet"** (Bitcoin
|
||||
> Connect) the primary CTA, and move the raw-URI field under a collapsible
|
||||
> **"Advanced / paste a connection manually"** — manual stays a first-class backup,
|
||||
> just de-emphasized. On success, populate the same status/disconnect UI._
|
||||
|
||||
> **DECISION 6 — Feature flag. 🔵 NEEDED.**
|
||||
> _Recommendation: `FEATURE_BITCOIN_CONNECT` in `config/instance-config.js` (default
|
||||
> off = no trace), wired exactly like `FEATURE_AUDIO_INGEST`. With it off, only the
|
||||
> manual URI field shows — zero new code path or bundle load._
|
||||
|
||||
## Config flag (off = no trace)
|
||||
|
||||
- `FEATURE_BITCOIN_CONNECT` (default **false**) — gates the "Connect wallet" button
|
||||
+ the lazy Bitcoin Connect import. Off ⇒ manual URI entry only (today's behavior).
|
||||
|
||||
## Integration points (small, contained)
|
||||
|
||||
- `components/profile-modal.html` — Wallet Connect pane: add the "Connect wallet"
|
||||
button; wrap the existing `#walletUri` field as "Advanced/manual."
|
||||
- `js/ui/profileModal/ProfileWalletController.js` — a `handleBitcoinConnect()` that
|
||||
lazy-imports the lib, `init()`s once (NWC-only, least-privilege, no-persist),
|
||||
`launchModal()`, and on `onConnected` extracts `nostrWalletConnectUrl` →
|
||||
runs the SAME `validateWalletUri` + save path as manual "Save wallet" → then
|
||||
`disconnect()`. Reuses all existing status/disconnect/sync UI.
|
||||
- `config/instance-config.js` / `js/config.js` / `js/constants.js` — the flag.
|
||||
- `scripts/` + `vendor/` — the esbuild vendor bundle (D1-A).
|
||||
|
||||
## Architecture
|
||||
|
||||
Bitcoin Connect is a **connect adapter**, not a payment layer:
|
||||
```
|
||||
[Connect wallet] → BC modal (NWC) → onConnected(provider)
|
||||
→ provider.client.nostrWalletConnectUrl
|
||||
→ validateWalletUri() (existing, scheme check)
|
||||
→ nwcSettingsService save (existing: per-npub store + optional encrypted sync)
|
||||
→ BC disconnect() (bitvid now owns the secret)
|
||||
[zaps] → js/payments/nwcClient pay_invoice + zap-split (UNCHANGED)
|
||||
```
|
||||
The manual field writes to the exact same validate→store path, so the two entry
|
||||
points converge immediately and everything downstream is untouched.
|
||||
|
||||
## Security (NWC URI = bearer SPENDING secret)
|
||||
|
||||
- **Never log** `nostrWalletConnectUrl` (or the provider) — extract → validate →
|
||||
store via the existing (never-logged) pipeline; treat like the manual field.
|
||||
- **`persistConnection: false` + `disconnect()`** after extract so the secret isn't
|
||||
duplicated in Bitcoin Connect's own plaintext `bc:*` localStorage (D2).
|
||||
- **Pin the version + vendor it** (Alpha lib) — no unpinned CDN `@latest`.
|
||||
- **Least-privilege `requestMethods`** (D4) — request only what bitvid calls.
|
||||
- Re-run bitvid's `validateWalletUri` on the extracted string; don't trust the lib
|
||||
blindly. Keep the explicit "a wallet-connect URI can SPEND" warning on the
|
||||
encrypted-sync toggle.
|
||||
- Payment invariants unchanged: `PLATFORM_FEE_PERCENT=30` split, preimage
|
||||
verification, and the "a pay_invoice timeout must NEVER auto-resend" rule all live
|
||||
in `js/payments/*` and are not touched.
|
||||
|
||||
## Phases (flag-gated from day one)
|
||||
|
||||
- **Phase 0 — Flag + vendor bundle.** Add `FEATURE_BITCOIN_CONNECT` (off) and the
|
||||
esbuild vendor step. No UX.
|
||||
- **Phase 1 — Connect button (headline).** Wallet pane "Connect wallet" → BC NWC
|
||||
modal → extract → existing save path → disconnect. Manual field → "Advanced."
|
||||
- **Phase 2 — Polish.** Balance display (BC `showBalance` / get_balance), reconnect
|
||||
affordance, and a "test connection" ping. Optional.
|
||||
- **Phase 3 (only if wanted) — WebLN path** (D3-B): accept Alby-extension/Hub
|
||||
connectors via a WebLN payment adapter alongside raw NWC. Separate effort.
|
||||
|
||||
## Risks / watch-items
|
||||
|
||||
- **Alpha library / breaking changes** — pin + vendor; wrap behind our own thin
|
||||
adapter so an API change is a one-file fix.
|
||||
- **Bundle weight** — lazy-import only on Wallet-pane open / button click.
|
||||
- **Wallet grants fewer scopes than requested** — if `pay_invoice` isn't granted,
|
||||
zaps fail; surface a clear error and fall back to manual.
|
||||
- **Not all wallets support NWC** — manual mode + non-NWC connectors (D3-B) cover the gap.
|
||||
- **esm.sh path (D1-B)** would add a runtime third-party origin to the trust surface.
|
||||
|
||||
## Sources
|
||||
|
||||
- getAlby/bitcoin-connect README (v3) — install, `init` filters/providerConfig,
|
||||
`onConnected`, `NostrWebLNProvider.client.nostrWalletConnectUrl`, `disconnect`.
|
||||
- bitcoin-connect.com. Related bitvid: `js/services/nwcSettingsService.js`,
|
||||
`js/nwcSettings.js`, `js/ui/profileModal/ProfileWalletController.js`,
|
||||
`js/payments/*`, `docs/audio-integration-plan.md` (flag-wiring pattern).
|
||||
@@ -2085,3 +2085,21 @@ example: event `95053d75…` "Nostr Compass Podcast #20" (pubkey `b7ed68b0…`).
|
||||
media grid — plan the category resolver + per-tab loaders together so video /
|
||||
audio / live / shorts don't each grow a bespoke fetch, and so the channel-profile
|
||||
tabs and sidebar tabs share one source of truth.
|
||||
|
||||
### 61. Bitcoin Connect — smooth NWC wallet connect UX — full plan in docs/bitcoin-connect-plan.md
|
||||
Requested 2026-07-09. Add Alby's Bitcoin Connect (getalby/bitcoin-connect,
|
||||
bitcoin-connect.com) as a polished "connect your wallet" modal for NWC, feeding
|
||||
bitvid's EXISTING NWC pipeline; keep manual URI entry as the backup/advanced path.
|
||||
- [ ] Verified feasible: BC's NWC connector exposes the raw pairing URI via
|
||||
`provider.client.nostrWalletConnectUrl` (on `onConnected`), which flows straight
|
||||
into `nwcSettingsService.validateWalletUri` → the existing per-npub store. No
|
||||
change to how bitvid pays or stores — one new way to obtain the same string.
|
||||
- [ ] Decisions D1–D6 in the plan (recommendations: vendor + lazy import;
|
||||
`persistConnection:false` + `disconnect()` after extract; NWC-only connector;
|
||||
least-privilege `requestMethods` incl. `pay_invoice`; Connect = primary CTA with
|
||||
manual under "Advanced"; `FEATURE_BITCOIN_CONNECT` flag, off = no trace).
|
||||
- [ ] Security: NWC URI is a bearer SPENDING secret — never log it; pin+vendor the
|
||||
(Alpha) lib; re-validate the extracted string; payment invariants
|
||||
(PLATFORM_FEE_PERCENT=30, preimage verify, no pay_invoice auto-resend) untouched.
|
||||
- [ ] Phased + flag-gated: Phase 0 flag+vendor, Phase 1 connect button, Phase 2
|
||||
polish (balance/reconnect), Phase 3 optional WebLN path for Alby-extension/Hub.
|
||||
Reference in new issue
Block a user