Skip to content

Set banks up from Settings, with forms their plugins describe - #31

Merged
IAmJSD merged 2 commits into
bank/5-uifrom
bank/6-setup
Oct 21, 2026
Merged

IAmJSD merged 2 commits into
bank/5-uifrom
bank/6-setup

Conversation

@IAmJSD

@IAmJSD IAmJSD commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Part 6 of 7 in the bank stack, on #28.

What this adds

Banks are set up from Settings → Bank now, not the server's .env.

  • The plugins describe the UI. Each bank factory declares:

    • its settings form (fields): labels, hints, which are secret, choices (Bitcoin's network), keys the form can make, and fields that can't change while cards are open
    • what its cards are (instrument: card or wallet)
    • where to top it up (fundAt: a treasury's address)

    The web app renders whatever a server's plugins say, with no bank-specific code. That's because one web app (including app.nibblets.dev) talks to many servers, and it can't know their plugins when it's built.

  • Saving checks first. Each plugin gains check(), which asks its provider something harmless:

    • Slash: lists cards, or reads the account's balance
    • Bitcoin: reads the treasury from Esplora
    • Ethereum: checks the chain id and the treasury's balance

    Only BankError messages reach the form. Anything else is logged, since it could carry an RPC URL's key.

  • No restart. Saved settings go in the settings table (banks). The server reloads its plugins into the running Bank and publishes bank_changed. Nibblets see the card tools from their next request.

  • Keys made in the browser. "Make one" fills a treasury key with 32 random bytes from crypto.getRandomValues. It's shown once so it can be copied, and afterwards it's only ever shown masked.

  • Cards hold their bank. A bank can't be removed while it has cards that aren't closed, and its locked fields (a treasury's key and network, a chain's id and coin) can't change either. Its cards depend on them.

  • The environment is a fallback. A bank with nothing saved still loads from variables named like its fields, so existing setups keep working. Saving in Settings takes over from them.

  • API: bank.configure, bank.remove, and kinds on bank.status.

  • Fixed the mock counting closing cards for what they've spent instead of in full.

#32 lets several banks share one plugin.

Screenshots

All from the mock server (?mock=1), which fakes the providers: Slash refuses the key wrong.

No bank yet, then Add a bank

Bank section with no bank set up and an Add a bank button

Add a bank: Slash, Bitcoin and Ethereum, each with a line on what it is

Slash: a key Slash refuses, then one it takes, being checked

Set up Slash with the error Slash: Invalid API key Set up Slash with an account ID, checking

Bitcoin: the empty form, then signet with a key made here

Set up Bitcoin, empty Set up Bitcoin on signet with a generated treasury key and a Copy button

Both set up, with where to top the new treasury up

Slash with its balance, and Bitcoin (signet) at 0.00 BTC with its top-up address

While a bank has open cards, its key and network are locked, and it can't be removed

Editing Bitcoin with its network and key locked Removing Bitcoin refused: it has 2 cards that aren't closed

Phone width

Set up Ethereum at phone width, with a generated key

Review fixes

  • With no bank when the server starts, the minute-by-minute card check never started, so banks set up later in Settings were never synced. It now starts as soon as there's a bank.
  • The bank form fetches status when it opens, for the open-card counts that lock a bank's fields, since card events no longer refetch it.

Checks

pnpm format:check, pnpm -r typecheck, pnpm --filter @nibblet/web build and pnpm test pass. New tests:

  • apps/server/src/banks.test.ts: saving, masked secrets, refusals, locked fields, removal, and the environment fallback
  • each plugin's check and fundAt
  • the base's settings helpers
  • the web form's draft logic

🤖 Generated with Claude Code

IAmJSD and others added 2 commits October 21, 2026 11:15
Each bank plugin's factory now describes its own settings form (fields,
hints, secrets, choices, keys the form can make, and fields that can't
change while cards are open), what its cards are, and where to top it up.
Settings → Bank adds, edits and removes any of them from that, checking
the settings with the provider before saving them and loading the bank
without a restart. The server's environment is now only a fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rm opens

- With no bank when the server starts, the minute-by-minute card check
  never started, so a bank set up later never had its used single-use
  cards closed, killed wallets swept, or spending read. It now starts as
  soon as there's a bank.
- Card events no longer refetch the banks' status, so the form fetches it
  when it opens, for the open cards that lock a bank's fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@IAmJSD
IAmJSD merged commit 92075fc into main Oct 21, 2026
4 of 6 checks passed
@IAmJSD
IAmJSD deleted the bank/6-setup branch October 21, 2026 10:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant