Skip to main content

Overview

The KaleidoSwap Extension injects standard wallet providers into browser pages so DApps can interact with wallet capabilities after user approval. It follows the same provider conventions as other browser wallets (e.g., Alby), so most existing WebLN, WebBTC, and Nostr apps work without any KaleidoSwap-specific integration. The extension injects:
  • window.webln — WebLN provider for Lightning (invoices, payments, message signing, keysend, LNURL).
  • window.webbtc — WebBTC provider for on-chain Bitcoin (addresses, PSBT signing, BIP-322 message signing, broadcasting).
  • window.nostr — full NIP-07 provider for Nostr event signing and encryption.
  • window.bitcoin — a Bitcoin Wallet Standard provider (Unisat/OKX/Leather-style) that some DApps probe for on-chain accounts.
  • window.rgb — a KaleidoSwap-specific provider for RGB assets: issue, receive, send and track assets, and, with a Lightning node, pay and receive them over Lightning.

How It Works

  1. The KaleidoSwap Extension’s content script is injected into web pages
  2. The content script loads an injected script that adds window.webln, window.webbtc, window.nostr, window.bitcoin, and window.rgb
  3. DApps call methods on those providers
  4. Requests are routed to the KaleidoSwap Extension background service worker
  5. Sensitive operations trigger a confirmation or permission prompt

Provider Ready Events

The injected script dispatches ready events (both with and without the colon, for SDK parity) once the providers are installed:
  • webln:ready / weblnReady
  • webbtc:ready / webbtcReady
  • nostr:ready
  • bitcoin:ready
  • rgb:ready

Error Codes

Every provider rejects with an Error that carries a code property, so a DApp can tell a user’s “no” from a wallet fault: window.rgb only uses the codes defined by the WebRGB spec, so on that provider POPUP_CLOSED and REQUEST_INTERRUPTED arrive as INTERNAL_ERROR.

WebLN Provider

window.webln follows the WebLN spec and can be used to:
  • Request node information
  • Create Lightning invoices
  • Send Lightning payments
  • Sign and verify messages
  • Send keysend payments
  • Handle LNURL requests
  • Read balance details

Supported Methods

Example Usage

WebBTC Provider

window.webbtc is an on-chain Bitcoin provider that can:
  • Return a receive address
  • Sign and finalize PSBTs
  • Sign messages (BIP-322)
  • Broadcast raw transactions
  • Send on-chain payments

Supported Methods

Some DApps probe window.bitcoin (a Bitcoin Wallet Standard provider) instead of, or alongside, window.webbtc. It exposes connect(), requestAccounts(), getAccounts(), getPublicKey(), signMessage(), signPsbt(), pushPsbt(), sendBitcoin(), and disconnect() over the same wallet keys.

PSBT Confirmations

Approving signPsbt, finalizePsbt, or pushPsbt is never blind-signing: the confirmation prompt decodes the PSBT and shows the destinations, amounts, and network fee before you approve. If the amounts cannot be decoded from the PSBT, the prompt shows an explicit warning instead. PSBT signing confirmation decoding the transaction total, each output with its destination and amount, and the network fee

RGB Provider

window.rgb exposes the wallet’s RGB runtime to DApps — the node-less RGB wallet or a connected RGB Lightning node, whichever the wallet is configured with — so an app can issue, receive, send and track RGB assets without running its own RGB backend. Every funds-touching call confirms in the extension popup, and the connect prompt lets the user restrict an origin to specific capabilities (minting is gated by its own issueAsset capability).
window.rgb ships from extension 0.3.0 on. It is not present in 0.2.0 builds; feature-detect it with the rgb:ready event rather than assuming it exists. The WebRGB 0.4 methods (witnessReceive, createUtxos, cancelReceive, getBtcBalance, refresh, getAssetMetadata, signPsbt, signMessage) ship from extension 0.4.0; check getInfo().methods before calling them.

TypeScript Support

The @kaleidorg/webrgb package ships the window.rgb declarations, provider discovery, an in-memory mock wallet and a conformance suite. SPEC.md in that repository is the interface contract this provider implements.
A rejection crosses a postMessage boundary on its way out of the wallet, so what a page catches is a plain Error carrying code — test it with isProviderError(err), never instanceof. listAssets() and listTransfers() always resolve to arrays from 0.3.0 on; toAssetArray() / toTransferArray() in the package tolerate wallets that wrap them.

Building without the extension

@kaleidorg/webrgb/mock is an in-memory provider that enforces the same rules a real one does — NOT_ENABLED before enable(), METHOD_NOT_SUPPORTED for anything absent from getInfo().methods, a confirmation step you can make refuse — so a DApp can be built and tested with no wallet installed.
The playground drives every method against the extension or against that mock, with a live log of calls, results and error codes. @kaleidorg/webrgb/conformance checks a wallet against the spec using read-only calls only, so it raises no confirmation.

Discovery

window.rgb is a single slot and only one wallet can own it, so the extension also announces itself, EIP-6963 style. It dispatches rgb:announceProvider on load and in answer to any rgb:requestProvider a page dispatches, carrying { info: { uuid, name, rdns }, provider } — its rdns is com.kaleidoswap.extension.
Discovery is additive: reading window.rgb directly still works, and requestProvider() settles on whichever arrives first.

Supported Methods

Example Usage

RGB over Lightning

When the wallet’s RGB runtime is a Lightning node, getInfo().protocol is "RGB_LN" and methods also lists makeLnInvoice and payLnInvoice. On a node-less RGB wallet both reject with METHOD_NOT_SUPPORTED.
Both calls confirm in the popup with the asset, its units and the sats the HTLC carries. Spending allowances do not apply to asset payments: every payLnInvoice prompts.

Events

The payload is { assetId, transferId, status, kind, amount, recipientId, txid }. Events are pushed by a background poll that runs about once a minute while a subscribed origin has an open tab, so there is no need to poll listTransfers() in a loop — but do not expect sub-minute latency.

Nostr Provider (NIP-07)

The KaleidoSwap Extension injects a full NIP-07 provider at window.nostr, so Nostr web apps can request the wallet’s public key, sign events, and encrypt or decrypt direct messages. The Nostr identity is derived from the wallet recovery phrase (or an imported identity, when set).

Supported Methods

Example Usage

Connecting a site for Nostr asks how much to approve up front. Ask every time (the default) confirms each request; Sign-in only auto-approves relay sign-in (NIP-42, kind 22242) and still asks for posts, deletions and everything else. A site connected only for WebLN or WebBTC must ask again before it can use your Nostr identity, and reading your public key or relays needs the site’s Nostr permission. If you deny a site’s connection, window.nostr stops prompting for the rest of that page, and the wallet remembers the denial for that site for 10 minutes. A prompt that is closed or left unanswered only backs off briefly; it is not recorded as a denial.

Nostr Connect (NIP-46)

Beyond in-page NIP-07 signing, the extension can act as a remote signer for Nostr apps that support NIP-46 (nsecBunker). From Settings > Nostr > Nostr Connect, generate a bunker:// connection string and paste it into the client app; signing requests then travel over Nostr relays and are approved in the extension. Active NIP-46 sessions appear in Connected Apps, where they can be reviewed and revoked. Nostr Connect remote signing screen with a listening status, the generated bunker connection string, and a revoke action

Nostr Wallet Connect (NWC)

The extension can also expose the wallet to external apps over Nostr Wallet Connect: pair an app by scanning the pairing QR code, then control what it can do with amount-aware budgets. Zap payments (NIP-57) made through NWC are validated and correlated with wallet activity.

For Developers

NWC is the integration path for anything that is not a web page in the same browser — mobile apps, desktop clients, bots and backends. The extension acts as the NIP-47 wallet service; any NIP-47 client library works against it, so nothing KaleidoSwap-specific is required. The pairing string generated in Settings > Nostr > Wallet Connect has the standard shape:
The service announces NIP-47 version 1.0 with nip04 and nip44_v2 encryption and supports these methods: Each paired client gets its own spending budget, visible and revocable under Settings > Connected Apps. A payment within budget settles without a prompt; anything over it opens the same confirmation window the in-page providers use.

Permission Prompts and Connected Apps

When a connected site makes a sensitive request, the KaleidoSwap Extension asks the user to approve or deny the action. The connect prompt lists the capabilities the site asks for (create invoices, send Lightning payments, sign messages, sign PSBTs, send Bitcoin, issue RGB assets, Nostr), and the site gets exactly the ones the user leaves on; an approval without a capability list grants nothing. Every prompt names the site that asks.
  • More requests need approval: LNURL-auth, LNURL-withdraw and LNURL-channel go through the site’s permissions and the unlock gate like any other request, and reading node info or addresses needs approval. A site cannot switch the wallet’s active account.
  • Site payments are checked first: Lightning invoices are fully decoded (checksum, network, expiry) and validated before any spending allowance is reserved, and refused when they are for another network than the paying wallet. The allowance is refunded only when the payment certainly did not go out.
  • Arkade: sites cannot start a Lightning payment (WebLN, LNURL, WebBTC) from an Arkade account, because Arkade pays Lightning through an Intents swap whose solver fee and delayed proof of payment a site confirmation does not show. Pay from the wallet’s Send screen instead.
  • Prompts are robust: an approval window survives the wallet restarting in the background, a window closed without an answer is reported as POPUP_CLOSED rather than a refusal, and a locked wallet can be unlocked from the prompt with a passkey.
  • Other wallets keep working: the injected providers are read-only but configurable, so the extension never replaces another wallet’s window.webln, webbtc, bitcoin, rgb or nostr.
Connection approval prompt showing the requesting site origin, the access it asks for, and the Nostr choice between Ask every time (default) and Sign-in only, with Deny and Allow actions Settings > Connected Apps lists every site and app connected to the wallet, including NIP-46 (bunker) clients, showing which capabilities each one has been granted. You can revoke individual capabilities or disconnect a site entirely at any time. Connected Apps screen listing connected apps, Nostr Wallet Connect sessions, and a field to block a site
Always review what a DApp is requesting before approving. Only approve payments, invoices, asset sends, and signing requests from sites you trust.

Nostr Identity

The KaleidoSwap Extension derives a Nostr identity from the wallet recovery phrase (or an imported identity) and exposes it both to web pages through window.nostr and in the extension settings.

Nostr Key Management

Your Nostr keypair is managed in Settings > Nostr > Nostr Identity:
  • View your public key (npub)
  • View/copy the session private key when the wallet is unlocked
  • Import a key, or revert an imported key to the identity derived from your recovery phrase
By default the identity is derived from the recovery phrase (NIP-06). If you already have a Nostr identity, you can import your own key (nsec1… or 64-character hex) during onboarding or later from Settings > Nostr > Nostr Identity; it is stored encrypted and used everywhere the derived identity would be.

Browser Approval Flow

The KaleidoSwap Extension keeps DApp approvals user-driven:
  1. A trusted site requests a connection, payment, invoice, asset, or signing action
  2. The KaleidoSwap Extension routes the request through the content script and background service worker
  3. The user reviews the details and approves or rejects the action
This keeps wallet-side actions explicit while still allowing DApps to use the KaleidoSwap Extension as a browser provider.

Security Considerations


Access the Beta

Request access to the KaleidoSwap Extension closed beta.