@bwalletx/connect 0.5.4 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +76 -8
- package/dist/bwalletx-connect.global.js +92 -25
- package/dist/bwalletx-connect.global.js.map +1 -1
- package/dist/{wallets-CbzMtxrf.d.ts → choice-DCh-tgpT.d.cts} +112 -4
- package/dist/{wallets-CbzMtxrf.d.cts → choice-DCh-tgpT.d.ts} +112 -4
- package/dist/chunk-34DKBQNN.js +222 -0
- package/dist/chunk-34DKBQNN.js.map +1 -0
- package/dist/{chunk-QRXFL66W.js → chunk-A2WLGS25.js} +6 -4
- package/dist/chunk-A2WLGS25.js.map +1 -0
- package/dist/chunk-IFGOAROM.js +255 -0
- package/dist/chunk-IFGOAROM.js.map +1 -0
- package/dist/chunk-LS6AYEBO.js +1886 -0
- package/dist/chunk-LS6AYEBO.js.map +1 -0
- package/dist/element-D9Zl-x12.d.cts +46 -0
- package/dist/element-D9Zl-x12.d.ts +46 -0
- package/dist/element.cjs +1147 -61
- package/dist/element.cjs.map +1 -1
- package/dist/element.d.cts +23 -28
- package/dist/element.d.ts +23 -28
- package/dist/element.js +29 -2
- package/dist/element.js.map +1 -1
- package/dist/index.cjs +1469 -453
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +163 -14
- package/dist/index.d.ts +163 -14
- package/dist/index.js +100 -12
- package/dist/index.js.map +1 -1
- package/dist/next.cjs +5 -3
- package/dist/next.cjs.map +1 -1
- package/dist/next.js +1 -1
- package/dist/react.cjs +994 -183
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +75 -8
- package/dist/react.d.ts +75 -8
- package/dist/react.js +121 -40
- package/dist/react.js.map +1 -1
- package/dist/server.cjs +5 -3
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +8 -3
- package/dist/server.d.ts +8 -3
- package/dist/server.js +1 -1
- package/package.json +10 -9
- package/dist/chunk-EXRQJTXF.js +0 -910
- package/dist/chunk-EXRQJTXF.js.map +0 -1
- package/dist/chunk-QRXFL66W.js.map +0 -1
- package/dist/chunk-RIOHG5JH.js +0 -459
- package/dist/chunk-RIOHG5JH.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/discover.ts","../src/in-order.ts","../src/pair.ts","../src/protocol.ts","../src/signin.ts","../src/access-client.ts","../src/element.ts"],"sourcesContent":["import { WalletClient, XDM, type WalletInterface } from '@bsv/sdk';\n\n/** Ids bWalletX announces in BRC-100 wallet discovery. */\nexport const RDNS_EXTENSION = 'com.bwalletx.extension';\nexport const RDNS_MOBILE = 'space.bwallet.mobile';\nexport const BWALLETX_RDNS = [RDNS_EXTENSION, RDNS_MOBILE] as const;\n\nexport type FoundBy = 'extension' | 'in-app';\n\nexport interface FoundWallet {\n wallet: WalletInterface;\n /** 'extension' for the Chrome extension; 'in-app' inside the bWalletX app's own browser. */\n method: FoundBy;\n rdns: string | null;\n}\n\n/**\n * Default wait for a wallet that has not answered yet, ms. bWalletX for Chrome answers `brc100:requestWallet`\n * synchronously and the in-app browser sets `window.CWI` before the page runs, so a found wallet resolves at once;\n * this is only how long \"nothing here\" takes before the pairing QR shows. Was 1200 (0.5.3 and earlier).\n */\nexport const DEFAULT_DISCOVER_MS = 300;\n\n/**\n * Like findBwalletX, but also says which bWalletX answered.\n * Order: a BRC-100 announcement with a bWalletX rdns (answered at once by the extension); then `window.CWI` (set by\n * the in-app browser, and by older builds that do not announce), taken straight away; then, only when framed, the\n * parent's XDM answer (probed in parallel with the wait). Otherwise null after `ms`.\n */\nexport function discoverBwalletX(ms = DEFAULT_DISCOVER_MS): Promise<FoundWallet | null> {\n if (typeof window === 'undefined') return Promise.resolve(null);\n return new Promise((resolve) => {\n let done = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const finish = (r: FoundWallet | null) => {\n if (done) return;\n done = true;\n if (timer !== undefined) clearTimeout(timer);\n window.removeEventListener('brc100:announceWallet', onAnnounce);\n resolve(r);\n };\n const onAnnounce = (e: Event) => {\n const d = (e as CustomEvent).detail as { info?: { rdns?: string }; wallet?: WalletInterface } | undefined;\n const rdns = d?.info?.rdns ?? '';\n if (d?.wallet && (BWALLETX_RDNS as readonly string[]).includes(rdns)) {\n finish({ wallet: d.wallet, method: rdns === RDNS_EXTENSION ? 'extension' : 'in-app', rdns });\n }\n };\n const cwiNow = (): boolean => {\n const cwi = (window as unknown as { CWI?: WalletInterface }).CWI;\n if (cwi) finish({ wallet: cwi, method: 'in-app', rdns: null });\n return !!cwi;\n };\n window.addEventListener('brc100:announceWallet', onAnnounce);\n window.dispatchEvent(new Event('brc100:requestWallet'));\n if (done || cwiNow()) return;\n // Inside bWalletX's in-wallet frame nothing is injected into the page: the wallet answers BRC-100 XDM\n // (postMessage to the parent) instead. Only tried when framed, and only kept if the parent answers.\n // The parent may take a moment to answer, so it gets at least the old 1200 ms; unframed pages never wait on it.\n if (isFramed()) {\n void probeXdm(Math.max(ms, 1200)).then((w) => finish(w ? { wallet: w, method: 'in-app', rdns: null } : null));\n return;\n }\n timer = setTimeout(() => {\n timer = undefined;\n if (!cwiNow()) finish(null);\n }, ms);\n });\n}\n\n/**\n * Find bWalletX in this page: the extension on a computer, or the wallet itself when the page is\n * open in bWalletX's in-app browser. Resolves null if nothing answered within `ms`.\n */\nexport async function findBwalletX(ms = DEFAULT_DISCOVER_MS): Promise<WalletInterface | null> {\n return (await discoverBwalletX(ms))?.wallet ?? null;\n}\n\nconst isFramed = (): boolean => {\n try {\n return window.parent !== window;\n } catch {\n return true;\n }\n};\n\n/**\n * The only parents that may answer as bWalletX over XDM (security audit 25 Oct 2026). Without this, any page that\n * framed a site using this package became \"the wallet\": it saw every call (payments, sign-in challenges) and could\n * answer with a fake txid. The wallet's own frames: the web wallet, bwallet.space, the iOS/Android app shells and\n * the Chrome extension. Payments must still be checked on your server (verifyPayment), never trusted from the page.\n */\nexport const BWALLETX_PARENT_ORIGINS: readonly string[] = [\n 'https://web.bwalletx.com',\n 'https://desktop.bwalletx.com',\n 'https://bwalletx.com',\n 'https://www.bwallet.space',\n 'https://bwallet.space',\n 'capacitor://localhost', // iOS app shell\n 'https://localhost', // Android app shell\n 'tauri://localhost', // bWalletX Desktop (macOS)\n 'https://tauri.localhost', // bWalletX Desktop (Windows)\n 'chrome-extension://bombmmcjghjdlbmcclnhjodgcelnehgl', // bWalletX for Chrome (fixed id)\n];\n\n/** The parent frame's origin, as the browser reports it (ancestorOrigins, else the referrer), or null. */\nexport const parentOrigin = (): string | null => {\n try {\n const anc = (window.location as Location & { ancestorOrigins?: DOMStringList }).ancestorOrigins;\n if (anc && anc.length > 0) return anc[0] ?? null;\n if (!document.referrer) return null;\n // Not URL.origin: it is \"null\" for non-special schemes (capacitor:, chrome-extension:) in some engines.\n const u = new URL(document.referrer);\n return `${u.protocol}//${u.host}`;\n } catch {\n return null;\n }\n};\n\n/**\n * The parent frame's wallet over BRC-100 XDM, or null when the parent is not bWalletX (BWALLETX_PARENT_ORIGINS) or\n * does not answer within `ms`. Messages go to that exact origin and only its answers are taken.\n */\nexport async function probeXdm(ms = 1200, allowed: readonly string[] = BWALLETX_PARENT_ORIGINS): Promise<WalletInterface | null> {\n const origin = parentOrigin();\n if (!origin || !allowed.includes(origin)) return null;\n try {\n const w = new WalletClient(new XDM(origin) as unknown as WalletInterface);\n const ok = await Promise.race([\n w.isAuthenticated({}).then(\n () => true,\n () => false,\n ),\n new Promise<boolean>((r) => setTimeout(() => r(false), ms)),\n ]);\n return ok ? w : null;\n } catch {\n return null;\n }\n}\n\nlet warmedAt = 0;\n\n/**\n * Wake the wallet before the click (call on pointerenter / focus / touchstart of your Connect button). Chrome stops an\n * idle extension worker after ~30 s, and a cold worker needs 1-3 s to reopen the wallet; this sends a liveness call\n * (isAuthenticated: never shows a prompt, never reveals a key) so that work starts while the pointer is on its way.\n * At most once every 20 s. Does nothing when no bWalletX is in the page.\n */\nexport function prewarmBwalletX(): void {\n if (typeof window === 'undefined' || Date.now() - warmedAt < 20_000) return;\n warmedAt = Date.now();\n void discoverBwalletX(0).then((f) => {\n if (f && f.method === 'extension') void f.wallet.isAuthenticated({}).catch(() => {});\n });\n}\n\n/** Prewarm on hover, keyboard focus and touch. Returns a function that removes the listeners. */\nexport function bindPrewarm(el: EventTarget): () => void {\n const on = () => prewarmBwalletX();\n const evs = ['pointerenter', 'focus', 'touchstart'];\n for (const e of evs) el.addEventListener(e, on, { passive: true });\n return () => evs.forEach((e) => el.removeEventListener(e, on));\n}\n","/**\n * Wrap an async frame handler so frames are handled one at a time, in arrival order.\n *\n * WebSocket `onmessage` does not wait for an async handler. The phone sends its plain `hello`\n * and then, as soon as the user taps Connect, a sealed `ready`. If the handler for `hello` is\n * still deriving the session key when `ready` arrives, a naive handler sees no key yet and drops\n * `ready`, so pairing never finishes. Chaining every frame onto one promise fixes that.\n */\nexport function inOrder<T>(handle: (frame: T) => Promise<void> | void, onError?: (e: unknown) => void) {\n let queue: Promise<void> = Promise.resolve();\n return (frame: T): Promise<void> => {\n queue = queue.then(() => handle(frame)).catch((e) => onError?.(e));\n return queue;\n };\n}\n","import { PrivateKey, type WalletInterface } from '@bsv/sdk';\nimport { inOrder } from './in-order.js';\nimport {\n DEFAULT_RELAY,\n PAIR_VERSION,\n QR_LIFETIME_S,\n Sealer,\n deriveSession,\n isSealed,\n claimDigest,\n newChannel,\n newClaim,\n pairUrl,\n relaySocketUrl,\n walletClaimFor,\n type HelloFrame,\n type PairMessage,\n} from './protocol.js';\n\n/** localStorage-shaped storage. Methods may be sync or async. */\nexport interface PairStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\n/** The minimum of the browser WebSocket API this package uses (the `ws` package also fits). */\nexport interface SocketLike {\n readonly readyState: number;\n onopen: ((ev: unknown) => void) | null;\n onmessage: ((ev: { data: unknown }) => void) | null;\n onerror: ((ev: unknown) => void) | null;\n onclose: ((ev: unknown) => void) | null;\n send(data: string): void;\n close(): void;\n}\nexport type SocketFactory = (url: string) => SocketLike;\n\nexport interface PairConnectionOptions {\n /** Where the pairing is kept so it survives a reload. Default: localStorage, else memory only. */\n storage?: PairStorage | null;\n /** Storage key. Default 'bwalletx.connect.pairing.v1'. */\n storageKey?: string;\n /** Opens a socket. Default: the global WebSocket. Pass one to run in Node or to test. */\n socket?: SocketFactory;\n /** Per-call timeout in ms. Default 120000. */\n callTimeoutMs?: number;\n}\n\nexport interface PairingOptions extends PairConnectionOptions {\n /** Show this link as a QR code, and as text to copy (web.bwalletx.com takes it pasted). */\n onLink: (link: string) => void;\n /** Show this 4-digit code. The wallet shows the same one; the user checks they match. */\n onCode: (code: string) => void;\n signal?: AbortSignal;\n /** Relay host. Default relay.bwallet.space. */\n relay?: string;\n /** This page's origin, as the relay will see it. Default location.origin. */\n origin?: string;\n}\n\n/** A BRC-100 wallet whose every call goes, end-to-end encrypted, to the paired phone or web wallet. */\nexport type PairedWallet = WalletInterface & {\n /** Close the relay connection. The pairing stays stored; the next call reconnects. */\n close(): void;\n /** Tell the wallet to unpair, close, and delete the stored pairing. */\n forget(): Promise<void>;\n};\n\ninterface StoredPairing {\n v: 1;\n c: string; // channel\n r: string; // relay host\n s: string; // our pairing private key (hex). Random; not a wallet key.\n k: string; // the wallet's pairing public key\n sent: number;\n lastSeen: number;\n pairedAt: number;\n sc?: string; // our relay site claim, sent on every connect. Pairings stored before 0.5.4 get one on reconnect.\n}\n\nconst DEFAULT_KEY = 'bwalletx.connect.pairing.v1';\nconst OPEN = 1;\n\nfunction memoryStorage(): PairStorage {\n const m = new Map<string, string>();\n return { getItem: (k) => m.get(k) ?? null, setItem: (k, v) => void m.set(k, v), removeItem: (k) => void m.delete(k) };\n}\n\nfunction defaultStorage(): PairStorage {\n try {\n if (typeof localStorage !== 'undefined') return localStorage;\n } catch {\n /* blocked storage */\n }\n return memoryStorage();\n}\n\nfunction defaultSocket(): SocketFactory {\n return (url) => {\n if (typeof WebSocket === 'undefined') throw new Error('No WebSocket here. Pass options.socket.');\n return new WebSocket(url) as unknown as SocketLike;\n };\n}\n\nfunction parseStored(raw: string | null): StoredPairing | null {\n if (!raw) return null;\n try {\n const p = JSON.parse(raw) as Partial<StoredPairing>;\n const n = (x: unknown) => Number.isInteger(x) && (x as number) >= 0;\n if (p.v !== 1) return null;\n if (typeof p.c !== 'string' || !/^[A-Za-z0-9_-]{22}$/.test(p.c)) return null;\n if (typeof p.r !== 'string' || !/^[a-z0-9.-]+(:\\d+)?$/i.test(p.r)) return null;\n if (typeof p.s !== 'string' || !/^[0-9a-f]{64}$/i.test(p.s)) return null;\n if (typeof p.k !== 'string' || !/^0[23][0-9a-f]{64}$/i.test(p.k)) return null;\n if (!n(p.sent) || !n(p.lastSeen) || !n(p.pairedAt)) return null;\n if (p.sc !== undefined && (typeof p.sc !== 'string' || !/^[A-Za-z0-9_-]{22,64}$/.test(p.sc))) return null;\n return p as StoredPairing;\n } catch {\n return null;\n }\n}\n\nclass Link {\n private ws: SocketLike | null = null;\n private opening: Promise<void> | null = null;\n private waiting = new Map<string, { resolve: (v: unknown) => void; reject: (e: Error) => void; timer: ReturnType<typeof setTimeout> }>();\n private forgotten = false;\n\n constructor(\n private p: StoredPairing,\n private sealer: Sealer,\n private storage: PairStorage,\n private key: string,\n private socket: SocketFactory,\n private timeoutMs: number,\n ) {}\n\n /** Take over a socket that is already open (the one pairing used). */\n adopt(ws: SocketLike) {\n this.ws = ws;\n this.wire(ws);\n }\n\n private wire(ws: SocketLike) {\n ws.onmessage = inOrder((ev: { data: unknown }) => this.onFrame(String(ev.data)));\n ws.onerror = null;\n ws.onclose = () => {\n if (this.ws === ws) this.ws = null;\n this.failAll(new Error('The connection to bWalletX closed'));\n };\n }\n\n private persist() {\n if (this.forgotten) return;\n this.p = { ...this.p, ...this.sealer.counters };\n void Promise.resolve(this.storage.setItem(this.key, JSON.stringify(this.p))).catch(() => {});\n }\n\n private failAll(e: Error) {\n for (const w of this.waiting.values()) {\n clearTimeout(w.timer);\n w.reject(e);\n }\n this.waiting.clear();\n }\n\n private async ensure() {\n if (this.forgotten) throw new Error('This pairing was removed. Pair again.');\n if (this.ws && this.ws.readyState === OPEN) return;\n this.opening ??= this.reopen().finally(() => (this.opening = null));\n await this.opening;\n }\n\n private reopen() {\n // Pairings stored before site claims get one now; the relay binds it on this connect.\n if (!this.p.sc) {\n this.p = { ...this.p, sc: newClaim() };\n this.persist();\n }\n // A fresh expiry lets the relay recreate the channel if it was dropped; the wallet rejoins on its own.\n const e = Math.floor(Date.now() / 1000) + QR_LIFETIME_S - 10;\n const ws = this.socket(relaySocketUrl(this.p.r, this.p.c, 'site', e, this.p.sc));\n return new Promise<void>((resolve, reject) => {\n ws.onopen = () => {\n this.ws = ws;\n this.wire(ws);\n resolve();\n };\n ws.onerror = () => reject(new Error('Could not reach the bWalletX pairing service'));\n ws.onclose = () => reject(new Error('Could not reach the bWalletX pairing service'));\n });\n }\n\n private async onFrame(raw: string) {\n let f: unknown;\n try {\n f = JSON.parse(raw);\n } catch {\n return;\n }\n const t = (f as { t?: string; error?: string }).t;\n if (t === 'relay' && (f as { error?: string }).error) {\n return this.failAll(new Error(`bWalletX pairing service: ${(f as { error: string }).error}`));\n }\n if (!isSealed(f)) return;\n const msg = await this.sealer.open(f);\n if (!msg) return;\n this.persist();\n if (msg.t === 'res') {\n const w = this.waiting.get(msg.id);\n if (!w) return;\n clearTimeout(w.timer);\n this.waiting.delete(msg.id);\n if (msg.error) w.reject(Object.assign(new Error(msg.error.message), { code: msg.error.code }));\n else w.resolve(msg.result);\n } else if (msg.t === 'close') {\n this.drop();\n this.failAll(new Error('bWalletX disconnected this site. Pair again.'));\n }\n }\n\n async call(action: string, params: unknown): Promise<unknown> {\n await this.ensure();\n const ws = this.ws!;\n const id = `${action}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n const result = new Promise<unknown>((resolve, reject) => {\n const timer = setTimeout(() => {\n if (this.waiting.delete(id)) reject(new Error('No answer from bWalletX. Open it, unlocked, and approve.'));\n }, this.timeoutMs);\n this.waiting.set(id, { resolve, reject, timer });\n });\n ws.send(JSON.stringify(await this.sealer.seal({ t: 'req', id, action, params } satisfies PairMessage)));\n this.persist();\n return result;\n }\n\n close() {\n const ws = this.ws;\n this.ws = null;\n ws?.close();\n }\n\n private drop() {\n this.forgotten = true;\n void Promise.resolve(this.storage.removeItem(this.key)).catch(() => {});\n this.close();\n }\n\n async forget() {\n if (this.forgotten) return;\n try {\n if (this.ws && this.ws.readyState === OPEN) {\n this.ws.send(JSON.stringify(await this.sealer.seal({ t: 'close', reason: 'site unpaired' })));\n }\n } catch {\n /* best effort */\n }\n this.drop();\n }\n\n wallet(): PairedWallet {\n return new Proxy({} as PairedWallet, {\n get: (_t, method) => {\n if (method === 'close') return () => this.close();\n if (method === 'forget') return () => this.forget();\n if (typeof method !== 'string' || method === 'then' || method === 'toJSON') return undefined;\n return (params: unknown) => this.call(method, params ?? {});\n },\n });\n }\n}\n\n/**\n * Pair with bWalletX on a phone (scan the QR) or web.bwalletx.com (paste the link).\n * Resolves with a wallet once the user taps Connect. The pairing is stored (see `storage`) so\n * `restorePairing()` can reconnect after a reload without a new QR.\n */\nexport function pairBwalletX(opts: PairingOptions): Promise<PairedWallet> {\n const storage = opts.storage === undefined ? defaultStorage() : (opts.storage ?? memoryStorage());\n const key = opts.storageKey ?? DEFAULT_KEY;\n const socket = opts.socket ?? defaultSocket();\n const relay = opts.relay ?? DEFAULT_RELAY;\n const origin = opts.origin ?? (typeof location !== 'undefined' ? location.origin : '');\n if (!origin) return Promise.reject(new Error('pairBwalletX needs options.origin outside a browser'));\n\n const siteKey = PrivateKey.fromRandom(); // a throwaway pairing key, not a wallet key\n const channel = newChannel();\n const expiry = Math.floor(Date.now() / 1000) + QR_LIFETIME_S;\n // b-Aware 26 Oct 2026: our own role claim (N3-1), and the digest of the wallet claim only the QR can produce (N3-2).\n const siteClaim = newClaim();\n const sitePub = siteKey.toPublicKey().toString();\n\n return walletClaimFor(channel, sitePub).then(claimDigest).then((wc) => new Promise<PairedWallet>((resolve, reject) => {\n if (opts.signal?.aborted) return reject(new Error('cancelled'));\n let ws: SocketLike;\n try {\n ws = socket(relaySocketUrl(relay, channel, 'site', expiry, siteClaim, wc));\n } catch (e) {\n return reject(e);\n }\n let sealer: Sealer | null = null;\n let walletKey = '';\n let settled = false;\n const fail = (e: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n ws.close();\n reject(e);\n };\n const timer = setTimeout(() => fail(new Error('The pairing code expired. Show a new one.')), QR_LIFETIME_S * 1000);\n opts.signal?.addEventListener('abort', () => fail(new Error('cancelled')));\n ws.onerror = () => fail(new Error('Could not reach the bWalletX pairing service'));\n ws.onclose = () => fail(new Error('The connection to bWalletX closed before pairing finished'));\n ws.onmessage = inOrder(async (ev: { data: unknown }) => {\n if (settled) return;\n let f: unknown;\n try {\n f = JSON.parse(String(ev.data));\n } catch {\n return;\n }\n if ((f as HelloFrame).t === 'hello' && !sealer) {\n walletKey = (f as HelloFrame).k;\n const s = await deriveSession(siteKey, walletKey, channel);\n sealer = new Sealer(s.key, 'site');\n opts.onCode(s.code);\n return;\n }\n if (!sealer || !isSealed(f)) return;\n const msg = await sealer.open(f);\n if (!msg) return;\n if (msg.t === 'ready') {\n settled = true;\n clearTimeout(timer);\n const p: StoredPairing = { v: 1, c: channel, r: relay, s: siteKey.toHex(), k: walletKey, ...sealer.counters, pairedAt: Date.now(), sc: siteClaim };\n await Promise.resolve(storage.setItem(key, JSON.stringify(p))).catch(() => {});\n const link = new Link(p, sealer, storage, key, socket, opts.callTimeoutMs ?? 120_000);\n link.adopt(ws);\n resolve(link.wallet());\n } else if (msg.t === 'close') {\n fail(new Error('Pairing was declined in bWalletX'));\n }\n });\n opts.onLink(pairUrl({ v: PAIR_VERSION, r: relay, c: channel, k: sitePub, o: origin, e: expiry }));\n }));\n}\n\n/**\n * The wallet from a pairing stored by an earlier `pairBwalletX`, or null if there is none.\n * It connects on the first call. The wallet must still have this site paired.\n */\nexport async function restorePairing(opts: PairConnectionOptions = {}): Promise<PairedWallet | null> {\n const storage = opts.storage === undefined ? defaultStorage() : (opts.storage ?? memoryStorage());\n const key = opts.storageKey ?? DEFAULT_KEY;\n const p = parseStored(await Promise.resolve(storage.getItem(key)).catch(() => null));\n if (!p) return null;\n const { key: aes } = await deriveSession(PrivateKey.fromHex(p.s), p.k, p.c);\n const sealer = new Sealer(aes, 'site');\n sealer.restore({ sent: p.sent, lastSeen: p.lastSeen });\n return new Link(p, sealer, storage, key, opts.socket ?? defaultSocket(), opts.callTimeoutMs ?? 120_000).wallet();\n}\n\n/** Delete the stored pairing without telling the wallet. */\nexport async function clearPairing(opts: Pick<PairConnectionOptions, 'storage' | 'storageKey'> = {}) {\n const storage = opts.storage === undefined ? defaultStorage() : (opts.storage ?? memoryStorage());\n await Promise.resolve(storage.removeItem(opts.storageKey ?? DEFAULT_KEY)).catch(() => {});\n}\n","/**\n * Phone pairing protocol (tokenblaster.lol docs/wallet-connect.md §4), shared by the site side and\n * bWallet. Kept dependency-light (@bsv/sdk + WebCrypto) so the same file can be copied into sites\n * until it ships as @b0ase/wallet.\n *\n * QR: https://www.bwallet.space/pair?v=1&r=<relay host>&c=<channel>&k=<site pubkey>&o=<origin>&e=<expiry>\n * key: ECDH(secp256k1) → HKDF-SHA256(salt = channel bytes, info = \"bwallet-pair-v1\") → AES-256-GCM\n * frame: { s: seq, n: nonce b64, d: ciphertext b64 }, AAD = \"<sender role>|<s>\", s strictly increasing\n * code: first 2 bytes of SHA-256(key bits) → 4 digits, shown on both screens\n */\nimport { PrivateKey, PublicKey } from '@bsv/sdk';\n\nexport const PAIR_VERSION = '1';\nexport const PAIR_INFO = 'bwallet-pair-v1';\n// www: the bare domain redirects there, and app-link checks (Apple's AASA) don't follow redirects.\nexport const PAIR_HOST = 'www.bwallet.space';\nconst PAIR_HOSTS = new Set([PAIR_HOST, 'bwallet.space']);\nexport const DEFAULT_RELAY = 'relay.bwallet.space';\nexport const QR_LIFETIME_S = 120;\n\nexport type Role = 'site' | 'wallet';\nexport type WalletInfo = { name: string; icon?: string; rdns: string };\n\nexport type PairLink = { v: string; r: string; c: string; k: string; o: string; e: number };\n\n/** Plaintext messages inside encrypted frames. */\nexport type PairMessage =\n | { t: 'req'; id: string; action: string; params: unknown }\n | { t: 'res'; id: string; result?: unknown; error?: { code: string; message: string } }\n | { t: 'ready' }\n | { t: 'ping' }\n | { t: 'close'; reason: string };\n\n/** Unencrypted frames: from the relay, and the phone's hello (its key isn't shared yet). */\nexport type RelayFrame = { t: 'relay'; verifiedOrigin?: string; peer?: 'joined' | 'left'; role?: Role; error?: string };\nexport type HelloFrame = { t: 'hello'; k: string; info: WalletInfo };\nexport type SealedFrame = { s: number; n: string; d: string };\n\nconst enc = new TextEncoder();\nconst dec = new TextDecoder();\n\n// Chunked: String.fromCharCode(...bytes) overflows the call stack on large frames (signed transactions).\nconst binary = (bytes: Uint8Array) => {\n let s = '';\n for (let i = 0; i < bytes.length; i += 0x8000) s += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n return s;\n};\nexport const b64url = (bytes: Uint8Array) =>\n btoa(binary(bytes)).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\nexport const fromB64url = (s: string) => {\n const t = s.replace(/-/g, '+').replace(/_/g, '/');\n const bin = atob(t + '='.repeat((4 - (t.length % 4)) % 4));\n return Uint8Array.from(bin, (ch) => ch.charCodeAt(0));\n};\nconst b64 = (bytes: Uint8Array) => btoa(binary(bytes));\nconst fromB64 = (s: string) => Uint8Array.from(atob(s), (ch) => ch.charCodeAt(0));\n\nexport const newChannel = () => b64url(crypto.getRandomValues(new Uint8Array(16)));\n\nexport function pairUrl(link: PairLink): string {\n const q = new URLSearchParams({ v: link.v, r: link.r, c: link.c, k: link.k, o: link.o, e: String(link.e) });\n return `https://${PAIR_HOST}/pair?${q}`;\n}\n\n/** Parse a scanned QR (https link or bwallet:// fallback). Throws on anything else. */\nexport function parsePairUrl(text: string, nowS = Math.floor(Date.now() / 1000)): PairLink {\n const u = new URL(text.trim());\n const ok =\n (u.protocol === 'https:' && PAIR_HOSTS.has(u.host) && u.pathname === '/pair') ||\n (u.protocol === 'bwallet:' && /pair/.test(u.href));\n if (!ok) throw new Error('Not a bWallet pairing code');\n const g = (k: string) => u.searchParams.get(k) ?? '';\n const link: PairLink = { v: g('v'), r: g('r'), c: g('c'), k: g('k'), o: g('o'), e: Number(g('e')) };\n if (link.v !== PAIR_VERSION) throw new Error('This pairing code needs a newer bWallet');\n if (!/^[A-Za-z0-9_-]{22}$/.test(link.c)) throw new Error('Bad pairing code');\n if (!/^0[23][0-9a-f]{64}$/i.test(link.k)) throw new Error('Bad pairing code');\n if (!/^[a-z0-9.-]+(:\\d+)?$/i.test(link.r)) throw new Error('Bad pairing code');\n const o = new URL(link.o);\n if (o.origin !== link.o) throw new Error('Bad pairing code');\n if (!Number.isFinite(link.e) || link.e < nowS) throw new Error('This code has expired. Ask the site for a new one.');\n return link;\n}\n\n/** A fresh relay role claim (16 random bytes): the relay then admits this role only with the same claim. */\nexport const newClaim = () => b64url(crypto.getRandomValues(new Uint8Array(16)));\n\nconst WALLET_CLAIM_INFO = 'bwallet-pair-wallet-claim-v1';\nconst hex = (b: Uint8Array) => Array.from(b, (x) => x.toString(16).padStart(2, '0')).join('');\n\n/**\n * The wallet's relay claim for a fresh QR: SHA-256 of the channel and the site's pairing key, both read from the QR.\n * The site sends its digest (`wc`) when it opens the channel; the relay sees only the channel ID, so a stranger who\n * learns that can't take the wallet role before the phone scans (b-Aware 26 Oct 2026, N3-2).\n */\nexport async function walletClaimFor(channel: string, sitePub: string): Promise<string> {\n const d = await crypto.subtle.digest('SHA-256', enc.encode(`${WALLET_CLAIM_INFO}|${channel}|${sitePub}`));\n return b64url(new Uint8Array(d));\n}\n\n/** SHA-256 (hex) of a claim: what the relay stores and what a site sends as `wc`. */\nexport async function claimDigest(claim: string): Promise<string> {\n return hex(new Uint8Array(await crypto.subtle.digest('SHA-256', enc.encode(claim))));\n}\n\n/**\n * The relay socket URL. `claim` binds the role to this client (N3-1: a site always sends one, on every reconnect).\n * A site opening a new channel also passes `walletClaimHash` so only the phone that scanned the QR gets the wallet role.\n */\nexport const relaySocketUrl = (relay: string, channel: string, role: Role, expiry?: number, claim?: string, walletClaimHash?: string) => {\n const local = /^(localhost|127\\.0\\.0\\.1)(:\\d+)?$/.test(relay);\n const q = new URLSearchParams({ role });\n if (expiry) q.set('e', String(expiry));\n if (claim) q.set('claim', claim);\n if (walletClaimHash && role === 'site') q.set('wc', walletClaimHash);\n return `${local ? 'ws' : 'wss'}://${relay}/v1/c/${channel}?${q}`;\n};\n\n/** Shared AES key + 4-digit comparison code from my private key and their public key. */\nexport async function deriveSession(mine: PrivateKey, theirs: string, channel: string) {\n const point = mine.deriveSharedSecret(PublicKey.fromString(theirs));\n const ikm = new Uint8Array(point.encode(true) as number[]);\n const base = await crypto.subtle.importKey('raw', ikm, 'HKDF', false, ['deriveBits']);\n const bits = new Uint8Array(\n await crypto.subtle.deriveBits(\n { name: 'HKDF', hash: 'SHA-256', salt: fromB64url(channel), info: enc.encode(PAIR_INFO) },\n base,\n 256,\n ),\n );\n const key = await crypto.subtle.importKey('raw', bits, 'AES-GCM', false, ['encrypt', 'decrypt']);\n const h = new Uint8Array(await crypto.subtle.digest('SHA-256', bits));\n const code = String(((h[0] << 8) | h[1]) % 10000).padStart(4, '0');\n return { key, code };\n}\n\n/** One direction-aware encrypted pipe. `me` is the sender role used in the AAD. */\nexport class Sealer {\n private sent = 0;\n private lastSeen = 0;\n constructor(\n private key: CryptoKey,\n private me: Role,\n ) {}\n\n async seal(msg: PairMessage): Promise<SealedFrame> {\n const s = ++this.sent;\n const n = crypto.getRandomValues(new Uint8Array(12));\n const ct = new Uint8Array(\n await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: n, additionalData: enc.encode(`${this.me}|${s}`) },\n this.key,\n enc.encode(JSON.stringify(msg)),\n ),\n );\n return { s, n: b64(n), d: b64(ct) };\n }\n\n /** Decrypts a frame from the other side; null for replays, reflections or tampering. */\n async open(f: SealedFrame): Promise<PairMessage | null> {\n if (!Number.isInteger(f.s) || f.s <= this.lastSeen) return null;\n const from: Role = this.me === 'site' ? 'wallet' : 'site';\n try {\n const pt = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: fromB64(f.n), additionalData: enc.encode(`${from}|${f.s}`) },\n this.key,\n fromB64(f.d),\n );\n this.lastSeen = f.s;\n return JSON.parse(dec.decode(pt)) as PairMessage;\n } catch {\n return null;\n }\n }\n\n /** For resuming a session after a reload: continue counters where they were. */\n get counters() {\n return { sent: this.sent, lastSeen: this.lastSeen };\n }\n restore(c: { sent: number; lastSeen: number }) {\n this.sent = c.sent;\n this.lastSeen = c.lastSeen;\n }\n}\n\nexport const isSealed = (x: unknown): x is SealedFrame =>\n !!x && typeof x === 'object' && 'd' in x && 'n' in x && 's' in x;\n","import type { WalletInterface, WalletProtocol } from '@bsv/sdk';\nimport { discoverBwalletX, DEFAULT_DISCOVER_MS } from './discover.js';\nimport { pairBwalletX, restorePairing, type PairingOptions } from './pair.js';\n\n/** Security level 2, a protocol name used for nothing else. */\nexport const LOGIN_PROTOCOL: WalletProtocol = [2, 'bwallet sign in'];\n\n/** What your server's challenge route returns (createChallenge from '@bwalletx/connect/server'). */\nexport interface Challenge {\n nonce: string;\n message: string;\n keyID: string;\n protocolID?: WalletProtocol;\n}\n\nexport type SignInMethod = 'extension' | 'in-app' | 'pairing' | 'wallet';\n\n/**\n * Progress for the button label. 'finding': looking for a wallet (sub-second); 'opening': a wallet was found and its\n * approval is on the way (\"Opening your wallet…\"); 'pairing': no wallet in this browser, the QR is showing;\n * 'signing': the identity key arrived, the sign-in signature is being asked for.\n */\nexport type SignInStatus = 'finding' | 'opening' | 'pairing' | 'signing';\n\nexport interface SignInOptions {\n /** Ask your server for a challenge for this identity key. */\n challenge: (identityKey: string) => Promise<Challenge>;\n /** Use this wallet instead of looking for one. `method` is then 'wallet'. */\n wallet?: WalletInterface;\n /** How to show the QR and code if pairing is needed. Without it, pairing is not tried. */\n pairing?: PairingOptions;\n /** Reuse a pairing stored by an earlier sign-in before showing a new QR. Default true. */\n reusePairing?: boolean;\n /** How long to wait for a wallet that has not answered, in ms, before pairing. Default 300 (a present wallet answers at once). */\n discoverMs?: number;\n /** Called as the sign-in moves on, so the button can say \"Opening your wallet…\" straight away. */\n onStatus?: (status: SignInStatus) => void;\n}\n\nexport interface SignInResult {\n identityKey: string;\n /** DER signature as number[], ready to post to verifySignIn. */\n signature: number[];\n nonce: string;\n method: SignInMethod;\n /** The wallet that signed. Keep it to make more calls. */\n wallet: WalletInterface;\n}\n\n/** Find a wallet: extension or in-app browser first, then a stored pairing, then a new pairing. */\nexport async function connectBwalletX(\n opts: Pick<SignInOptions, 'wallet' | 'pairing' | 'reusePairing' | 'discoverMs' | 'onStatus'> = {},\n): Promise<{ wallet: WalletInterface; method: SignInMethod }> {\n const status = (s: SignInStatus) => {\n try {\n opts.onStatus?.(s);\n } catch {\n /* a UI callback must never break sign-in */\n }\n };\n if (opts.wallet) {\n status('opening');\n return { wallet: opts.wallet, method: 'wallet' };\n }\n status('finding');\n const found = await discoverBwalletX(opts.discoverMs ?? DEFAULT_DISCOVER_MS);\n if (found) {\n status('opening');\n return { wallet: found.wallet, method: found.method };\n }\n if (opts.reusePairing !== false) {\n const restored = await restorePairing(opts.pairing ?? {});\n if (restored) {\n status('opening');\n return { wallet: restored, method: 'pairing' };\n }\n }\n if (!opts.pairing) {\n throw Object.assign(new Error('bWalletX was not found in this browser'), { code: 'NOT_FOUND' });\n }\n status('pairing');\n return { wallet: await pairBwalletX(opts.pairing), method: 'pairing' };\n}\n\n/**\n * Sign the server's challenge with the user's bWalletX identity key. Post the result's\n * identityKey, nonce and signature to your verify route.\n */\nexport async function signInWithBwalletX(opts: SignInOptions): Promise<SignInResult> {\n const { wallet, method } = await connectBwalletX(opts);\n if (method !== 'pairing') await wallet.waitForAuthentication({}).catch(() => {});\n const { publicKey: identityKey } = await atStage('identity', () => wallet.getPublicKey({ identityKey: true }));\n try {\n opts.onStatus?.('signing');\n } catch {\n /* UI only */\n }\n const c = await atStage('challenge', () => opts.challenge(identityKey));\n const { signature } = await atStage('signature', () =>\n wallet.createSignature({\n protocolID: c.protocolID ?? LOGIN_PROTOCOL,\n keyID: c.keyID,\n counterparty: 'anyone',\n data: Array.from(new TextEncoder().encode(c.message)),\n }),\n );\n return { identityKey, signature: Array.from(signature), nonce: c.nonce, method, wallet };\n}\n\n/** Where a sign-in failed: the wallet's identity prompt, the site's challenge endpoint, or the wallet's signature. */\nexport type SignInStage = 'identity' | 'challenge' | 'signature' | 'verify';\n\n/** Tags a failure with its stage (err.stage), keeping the original message, so a site can say what actually failed. */\nexport async function atStage<T>(stage: SignInStage, run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n if (!(err as { stage?: string }).stage) Object.assign(err, { stage });\n throw err;\n }\n}\n","/**\n * Browser side of the access protocol: ask the wallet to sign the site's challenge and prove the\n * keys holding the required token, using standard BRC-100 calls only (so any BRC-100 wallet works).\n */\nimport { Hash, PublicKey, Utils, type WalletInterface, type WalletProtocol } from '@bsv/sdk';\nimport {\n ACCESS_PROTOCOL,\n AccessError,\n MAX_HOLDING_PROOFS,\n challengeBytes,\n parseAccessChallenge,\n type AccessErrorBody,\n type AccessResponse,\n type HoldingProof,\n} from './access.js';\nimport { connectBwalletX, type SignInOptions } from './signin.js';\n\n/** The challenge route's answer (createAccessChallenge). */\nexport interface AccessChallengeLike {\n challenge: string;\n}\n\nexport interface RequestAccessOptions {\n /** Ask your server for a challenge. Gets the wallet's identity key. */\n challenge: (identityKey: string) => Promise<AccessChallengeLike>;\n /** Post the signed response to your server. Throw AccessError (or return an error body) to refuse. */\n verify?: (response: AccessResponse) => Promise<unknown>;\n wallet?: WalletInterface;\n pairing?: SignInOptions['pairing'];\n discoverMs?: number;\n /** Basket holding BSV-21 outputs. Default 'bsv21' (bWalletX, 1Sat wallets). */\n tokenBasket?: string;\n}\n\nexport interface RequestAccessResult {\n response: AccessResponse;\n /** Whatever `verify` returned. */\n verified?: unknown;\n wallet: WalletInterface;\n}\n\nconst ONESAT: WalletProtocol = [0, 'onesat'];\nconst LEGACY_ONESAT: WalletProtocol = [0, 'p 1sat'];\n\n/** Map a wallet / fetch failure to a protocol error. */\nexport function toAccessError(e: unknown): AccessError {\n if (e instanceof AccessError) return e;\n const err = e as { code?: string; message?: string; status?: number } | null;\n const msg = String(err?.message ?? e ?? '');\n if (err?.code === 'NOT_FOUND') return new AccessError('not_installed', msg);\n if (/reject|denied|declin|cancel|user/i.test(msg) || err?.code === 'ERR_USER_REJECTED' || err?.status === 4001) {\n return new AccessError('user_rejected', msg);\n }\n return new AccessError('bad_request', msg || 'access failed');\n}\n\n/** Read an AccessErrorBody from a server answer and throw it as AccessError. */\nexport function throwIfAccessError(body: unknown): void {\n const b = body as Partial<AccessErrorBody> | null;\n if (b && typeof b.error === 'string') throw new AccessError(b.error as AccessError['code'], b.message, { have: b.have, need: b.need });\n}\n\nfunction hash160FromP2pkh(script: string): string | null {\n const m = /^76a914([0-9a-f]{40})88ac$/i.exec(script.slice(-50));\n return m ? m[1].toLowerCase() : null;\n}\n\n/**\n * Sign the challenge with every key that locks an output of `tokenId` in the wallet's token basket.\n * Outputs whose derivation can't be reproduced are skipped (the server counts only what is proven).\n */\nexport async function proveHoldings(wallet: WalletInterface, challenge: string, tokenId: string, basket = 'bsv21'): Promise<HoldingProof[]> {\n const bare = tokenId.replace(/^bsv21:/, '');\n const list = await wallet.listOutputs({ basket, include: 'locking scripts', includeCustomInstructions: true, limit: 10000 });\n const byKey = new Map<string, HoldingProof>();\n const data = challengeBytes(challenge);\n for (const out of list.outputs) {\n if (byKey.size >= MAX_HOLDING_PROOFS) break;\n let ci: { id?: string; keyID?: string; protocolID?: WalletProtocol; counterparty?: string } = {};\n try {\n ci = JSON.parse(out.customInstructions ?? '{}');\n } catch {\n continue;\n }\n if (ci.id !== bare || !ci.keyID) continue;\n const want = out.lockingScript ? hash160FromP2pkh(out.lockingScript) : null;\n const counterparty = ci.counterparty ?? 'self';\n for (const protocolID of ci.protocolID ? [ci.protocolID] : [ONESAT, LEGACY_ONESAT]) {\n const { publicKey } = await wallet.getPublicKey({ protocolID, keyID: ci.keyID, counterparty });\n const h = Utils.toHex(Hash.hash160(PublicKey.fromString(publicKey).encode(true) as number[]));\n if (want && h !== want) continue;\n const existing = byKey.get(publicKey);\n if (existing) {\n existing.outpoints!.push(out.outpoint.replace('.', '_'));\n break;\n }\n const { signature } = await wallet.createSignature({ protocolID, keyID: ci.keyID, counterparty, data });\n byKey.set(publicKey, { pubkey: publicKey, signature: Array.from(signature), outpoints: [out.outpoint.replace('.', '_')] });\n break;\n }\n }\n return [...byKey.values()];\n}\n\n/**\n * Run the whole flow: find the wallet, get a challenge, sign it, prove holdings, post to verify.\n * Throws AccessError with a protocol code on every failure.\n */\nexport async function requestAccess(o: RequestAccessOptions): Promise<RequestAccessResult> {\n let wallet: WalletInterface;\n try {\n ({ wallet } = await connectBwalletX({ wallet: o.wallet, pairing: o.pairing, discoverMs: o.discoverMs }));\n } catch (e) {\n throw (e as { code?: string })?.code === 'NOT_FOUND' ? new AccessError('not_installed') : toAccessError(e);\n }\n try {\n const { publicKey: identityKey } = await wallet.getPublicKey({ identityKey: true });\n const { challenge } = await o.challenge(identityKey);\n const c = parseAccessChallenge(challenge);\n if (c.sub && c.sub !== identityKey.toLowerCase()) throw new AccessError('wrong_account');\n if (Date.now() / 1000 >= c.exp) throw new AccessError('expired');\n const { signature } = await wallet.createSignature({\n protocolID: ACCESS_PROTOCOL,\n keyID: c.nonce,\n counterparty: 'anyone',\n data: challengeBytes(challenge),\n });\n const response: AccessResponse = { v: 1, challenge, identityKey, signature: Array.from(signature) };\n if (c.require.token) response.holdings = await proveHoldings(wallet, challenge, c.require.token.id, o.tokenBasket);\n let verified: unknown;\n if (o.verify) {\n verified = await o.verify(response);\n throwIfAccessError(verified);\n }\n return { response, verified, wallet };\n } catch (e) {\n throw toAccessError(e);\n }\n}\n","/**\n * <bwalletx-signin>: the standard \"Sign in with bWalletX\" button as a framework-free web component.\n *\n * Design reference: the gold button in bit-sign's sign-in card (src/components/BwalletSignIn.tsx):\n * amber-300 → amber-500 vertical gradient, 12px radius, 16px/20px padding, 16px bold black label,\n * 11px subtitle at 60% black, a black 28px circle holding the gold \"b\", amber shadow.\n *\n * Attributes (all optional):\n * size lg (default) | md | sm | icon\n * theme gold (default) | dark | light\n * label signin (default) | continue | connect\n * brand bWalletX (default) | bWallet (store edition text)\n * subtitle on | off | <custom text>. Default on for lg/md, off for sm/icon and for brand=\"bWallet\"\n * full-width stretch to the container\n * loading show the spinner and set aria-busy\n * disabled disable the button\n * challenge-url / verify-url run the sign-in flow on click (POST JSON, as in the README)\n * require-token / min / min-bps with challenge-url: run the $403 access flow instead; emits\n * bwalletx-access-granted or bwalletx-access-denied { code, have, need }\n * get-url where \"Get bWalletX\" points. Default https://bwalletx.com/get\n * web-url the web wallet. Default https://web.bwalletx.com\n * discover-ms how long to wait for a wallet that has not answered. Default 300\n * href plain link mode: navigate here on click\n * authorize-url (+ client-id, redirect-uri, scope) OAuth mode, for auth.bwalletx.com once it exists\n *\n * Events (bubble, composed):\n * bwalletx-signin on every click, before anything else. Cancelable: preventDefault() stops the\n * built-in behaviour so you can run your own flow.\n * bwalletx-signed-in detail { identityKey, method, nonce, signature, response }\n * bwalletx-not-found no bWalletX answered; the \"Get bWalletX\" row is shown\n * bwalletx-error detail { error }\n */\nimport { bindPrewarm, discoverBwalletX, DEFAULT_DISCOVER_MS } from './discover.js';\nimport { signInWithBwalletX, type Challenge } from './signin.js';\nimport { requestAccess, type AccessChallengeLike } from './access-client.js';\nimport { AccessError } from './access.js';\n\nexport const SIGNIN_TAG = 'bwalletx-signin';\nexport const GET_URL = 'https://bwalletx.com/get';\nexport const WEB_WALLET_URL = 'https://web.bwalletx.com';\n\nexport type SigninSize = 'lg' | 'md' | 'sm' | 'icon';\nexport type SigninTheme = 'gold' | 'dark' | 'light';\nexport type SigninLabel = 'signin' | 'continue' | 'connect';\nexport type SigninBrand = 'bWalletX' | 'bWallet';\n\nconst VERBS: Record<SigninLabel, string> = { signin: 'Sign in with', continue: 'Continue with', connect: 'Connect' };\n\n/** The visible label for a label/brand pair, e.g. \"Sign in with bWalletX\". */\nexport function signinText(label: SigninLabel = 'signin', brand: SigninBrand = 'bWalletX'): string {\n return `${VERBS[label] ?? VERBS.signin} ${brand}`;\n}\n\nlet uid = 0;\n/** The gold \"b\" (bwalletx-site/logo.svg). Ids are unique per copy so several marks can share a page. */\nexport function markSvg(px = 20): string {\n const n = ++uid;\n return `<svg viewBox=\"23 8 74 100\" width=\"${Math.round(px * 0.74)}\" height=\"${px}\" aria-hidden=\"true\" focusable=\"false\"><defs><linearGradient id=\"bwxg${n}\" gradientUnits=\"userSpaceOnUse\" x1=\"0\" y1=\"12\" x2=\"0\" y2=\"105\"><stop offset=\"0\" stop-color=\"#FFE58A\"/><stop offset=\".55\" stop-color=\"#FFD24D\"/><stop offset=\"1\" stop-color=\"#C98F00\"/></linearGradient><mask id=\"bwxh${n}\"><rect width=\"140\" height=\"140\" fill=\"#fff\"/><circle cx=\"60\" cy=\"72\" r=\"15\" fill=\"#000\"/></mask></defs><g fill=\"url(#bwxg${n})\" mask=\"url(#bwxh${n})\"><polygon points=\"45,12 45,76 27,76 27,30\"/><circle cx=\"60\" cy=\"72\" r=\"33\"/></g></svg>`;\n}\n\nexport const SIGNIN_CSS = `\n:host{display:inline-block;vertical-align:middle;font-family:Inter,ui-sans-serif,system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif}\n:host([full-width]){display:block;width:100%}\n:host([hidden]){display:none}\nbutton{all:unset;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:12px;width:100%;cursor:pointer;\n padding:16px 20px;border-radius:12px;font-size:16px;font-weight:700;line-height:1.2;text-align:left;\n background:linear-gradient(180deg,#fcd34d,#f59e0b);color:#000;\n box-shadow:0 10px 15px -3px rgba(245,158,11,.2),0 4px 6px -4px rgba(245,158,11,.2);\n transition:background .15s,transform .1s,box-shadow .15s,border-color .15s;-webkit-tap-highlight-color:transparent}\nbutton:hover{background:linear-gradient(180deg,#fde68a,#fbbf24)}\nbutton:active{transform:translateY(1px);background:linear-gradient(180deg,#fbbf24,#d97706)}\nbutton:focus-visible{outline:2px solid #b45309;outline-offset:3px}\nbutton:disabled{opacity:.6;cursor:not-allowed;transform:none}\nbutton[aria-busy=true]{cursor:wait}\n.mark{display:inline-flex;align-items:center;justify-content:center;flex:none;width:28px;height:28px;border-radius:50%;background:#000}\n.txt{display:flex;flex-direction:column;align-items:flex-start;min-width:0}\n.txt b{font-weight:700;white-space:nowrap}\n.txt small{font-size:11px;font-weight:500;color:rgba(0,0,0,.65);white-space:nowrap}\n.spin{width:16px;height:16px;border-radius:50%;border:2px solid rgba(255,210,77,.35);border-top-color:#ffd24d;animation:r .8s linear infinite}\n@keyframes r{to{transform:rotate(360deg)}}\n@media (prefers-reduced-motion:reduce){button{transition:none}button:active{transform:none}.spin{animation:none;border-color:#ffd24d;border-right-color:transparent}}\n/* sizes */\n:host([size=md]) button{padding:10px 16px;border-radius:10px;font-size:15px;gap:10px}\n:host([size=md]) .mark{width:24px;height:24px}\n:host([size=md]) .txt small{font-size:10.5px}\n:host([size=sm]) button{padding:6px 12px 6px 6px;border-radius:8px;font-size:13px;gap:8px;min-height:36px}\n:host([size=sm]) .mark{width:22px;height:22px}\n:host([size=icon]) button{width:48px;height:48px;padding:0;border-radius:50%;gap:0}\n:host([size=icon]) .mark{width:34px;height:34px}\n/* themes */\n:host([theme=dark]) button{background:#0a0a0a;color:#fafafa;border:1px solid #3f3f46;box-shadow:none}\n:host([theme=dark]) button:hover{background:#18181b;border-color:rgba(251,191,36,.6)}\n:host([theme=dark]) button:active{background:#000}\n:host([theme=dark]) button:focus-visible{outline-color:#fcd34d}\n:host([theme=dark]) .mark{box-shadow:inset 0 0 0 1px #3f3f46}\n:host([theme=dark]) .txt small{color:rgba(255,255,255,.65)}\n:host([theme=light]) button{background:#fff;color:#09090b;border:1px solid #d4d4d8;box-shadow:0 1px 2px rgba(0,0,0,.06)}\n:host([theme=light]) button:hover{background:#fafafa;border-color:#f59e0b}\n:host([theme=light]) button:active{background:#f4f4f5}\n:host([theme=light]) .txt small{color:#52525b}\n/* not found */\n.nf{margin-top:8px;font-size:12px;line-height:1.4;color:#71717a;text-align:center}\n.nf a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px}\n.nf a:focus-visible{outline:2px solid #b45309;outline-offset:2px;border-radius:2px}\n:host([theme=dark]) .nf,:host-context(.dark) .nf{color:#a1a1aa}\n.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n`;\n\n/** Optional OAuth parameters for authorize-url mode. auth.bwalletx.com is planned, not live. */\nexport interface AuthorizeParams { authorizeUrl: string; clientId?: string | null; redirectUri?: string | null; scope?: string | null }\n\nfunction b64url(bytes: Uint8Array): string {\n let s = '';\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/**\n * Build an OAuth 2.1 authorization-code + S256 PKCE redirect URL, and keep the verifier, state and\n * nonce in sessionStorage under \"bwalletx:oauth\" for your callback page. Matches the plan in\n * bit-sign docs/SIGN-IN-WITH-BWALLETX.md. The provider is not live yet.\n */\nexport async function buildAuthorizeUrl(p: AuthorizeParams): Promise<string> {\n const rnd = (n: number) => b64url(crypto.getRandomValues(new Uint8Array(n)));\n const verifier = rnd(32);\n const state = rnd(16);\n const nonce = rnd(16);\n const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier)));\n const u = new URL(p.authorizeUrl, typeof location !== 'undefined' ? location.href : undefined);\n const set = (k: string, v: string | null | undefined) => { if (v) u.searchParams.set(k, v); };\n set('response_type', 'code');\n set('client_id', p.clientId);\n set('redirect_uri', p.redirectUri);\n set('scope', p.scope || 'openid profile');\n set('state', state);\n set('nonce', nonce);\n set('code_challenge', b64url(digest));\n set('code_challenge_method', 'S256');\n try { sessionStorage.setItem('bwalletx:oauth', JSON.stringify({ verifier, state, nonce })); } catch { /* storage blocked */ }\n return u.toString();\n}\n\nasync function postJson<T>(url: string, body: unknown): Promise<T> {\n const res = await fetch(url, { method: 'POST', credentials: 'include', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) });\n const data = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error((data as { error?: string }).error ?? `HTTP ${res.status}`);\n return data as T;\n}\n\n/** POST that returns the body even on 4xx, so access error codes reach requestAccess. */\nasync function postAccess(url: string, body: unknown): Promise<unknown> {\n const res = await fetch(url, { method: 'POST', credentials: 'include', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) });\n return res.json().catch(() => ({ error: 'bad_request', message: `HTTP ${res.status}` }));\n}\n\nconst OBSERVED = ['size', 'theme', 'label', 'brand', 'subtitle', 'loading', 'disabled', 'full-width', 'aria-label', 'get-url', 'web-url'];\n\n/** The element class. Created lazily so importing this module on a server is harmless. */\nfunction createClass(): CustomElementConstructor {\n return class BwalletxSigninElement extends HTMLElement {\n static get observedAttributes() { return OBSERVED; }\n #root: ShadowRoot;\n #notFound = false;\n #busy = false;\n\n constructor() {\n super();\n this.#root = this.attachShadow({ mode: 'open' });\n }\n\n connectedCallback() { this.#render(); }\n attributeChangedCallback() { if (this.isConnected) this.#render(); }\n\n /** The inner <button>, for focus() and tests. */\n get button(): HTMLButtonElement | null { return this.#root.querySelector('button'); }\n get notFound() { return this.#notFound; }\n\n focus(opts?: FocusOptions) { this.button?.focus(opts); }\n\n #attr(name: string) { return this.getAttribute(name); }\n\n #render() {\n const size = (this.#attr('size') ?? 'lg') as SigninSize;\n const brand: SigninBrand = this.#attr('brand') === 'bWallet' ? 'bWallet' : 'bWalletX';\n const text = signinText((this.#attr('label') ?? 'signin') as SigninLabel, brand);\n const subAttr = this.#attr('subtitle');\n const subDefault = brand === 'bWalletX' && (size === 'lg' || size === 'md') ? 'also works with bWallet' : null;\n const subtitle = subAttr === null || subAttr === '' || subAttr === 'on' ? (subAttr === 'on' ? 'also works with bWallet' : subDefault)\n : subAttr === 'off' ? null : subAttr;\n const loading = this.hasAttribute('loading') || this.#busy;\n const disabled = this.hasAttribute('disabled');\n const markPx = size === 'icon' ? 24 : size === 'sm' ? 15 : size === 'md' ? 17 : 20;\n const aria = this.#attr('aria-label') ?? (subtitle && size !== 'icon' ? `${text}, ${subtitle}` : text);\n const getUrl = this.#attr('get-url') ?? GET_URL;\n const webUrl = this.#attr('web-url') ?? WEB_WALLET_URL;\n\n const esc = (s: string) => s.replace(/[&<>\"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '\"': '"' })[c]!);\n const label = size === 'icon' ? '' : `<span class=\"txt\" part=\"text\"><b part=\"label\">${esc(text)}</b>${subtitle ? `<small part=\"subtitle\">${esc(subtitle)}</small>` : ''}</span>`;\n const mark = loading ? '<span class=\"spin\" aria-hidden=\"true\"></span>' : markSvg(markPx);\n const nf = this.#notFound\n ? `<p class=\"nf\" part=\"not-found\" role=\"status\">bWalletX wasn't found in this browser. <a href=\"${esc(getUrl)}\" target=\"_blank\" rel=\"noopener\">Get ${brand}</a> or <a href=\"${esc(webUrl)}\" target=\"_blank\" rel=\"noopener\">use the web wallet</a>.</p>`\n : '';\n this.#root.innerHTML = `<style>${SIGNIN_CSS}</style><button type=\"button\" part=\"button\" aria-label=\"${esc(aria)}\" title=\"${esc(subtitle ? `${text} (${subtitle})` : text)}\"${disabled ? ' disabled' : ''}${loading ? ' aria-busy=\"true\"' : ''}><span class=\"mark\" part=\"mark\">${mark}</span>${label}</button>${loading ? '<span class=\"sr\" role=\"status\">Connecting to bWalletX…</span>' : ''}${nf}`;\n this.button!.addEventListener('click', () => void this.#click());\n bindPrewarm(this.button!);\n }\n\n #emit(type: string, detail?: unknown, cancelable = false) {\n return this.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable }));\n }\n\n #setBusy(on: boolean) { this.#busy = on; this.#render(); }\n\n async #click() {\n if (this.hasAttribute('disabled') || this.hasAttribute('loading') || this.#busy) return;\n if (!this.#emit('bwalletx-signin', { element: this }, true)) return;\n\n const href = this.#attr('href');\n const authorizeUrl = this.#attr('authorize-url');\n if (authorizeUrl) {\n location.assign(await buildAuthorizeUrl({ authorizeUrl, clientId: this.#attr('client-id'), redirectUri: this.#attr('redirect-uri'), scope: this.#attr('scope') }));\n return;\n }\n if (href) { location.assign(href); return; }\n\n const challengeUrl = this.#attr('challenge-url');\n if (!challengeUrl) return; // event-only mode: the page runs its own flow\n\n this.#notFound = false;\n this.#setBusy(true);\n try {\n const ms = Number(this.#attr('discover-ms')) || DEFAULT_DISCOVER_MS;\n const found = await discoverBwalletX(ms);\n if (!found) {\n this.#notFound = true;\n this.#emit('bwalletx-not-found');\n if (this.#attr('require-token')) this.#emit('bwalletx-access-denied', { code: 'not_installed', message: 'No wallet found' });\n return;\n }\n const requireToken = this.#attr('require-token');\n if (requireToken) {\n // $403 gate. The server's own config is authoritative; these attributes are passed along as a hint.\n const verifyUrl = this.#attr('verify-url');\n const min = this.#attr('min');\n const minBps = this.#attr('min-bps');\n const hint = { token: { id: requireToken, ...(minBps ? { minBps: Number(minBps) } : { min: min ?? '1' }) } };\n try {\n const a = await requestAccess({\n wallet: found.wallet,\n challenge: (identityKey) => postJson<AccessChallengeLike>(challengeUrl, { identityKey, require: hint }),\n verify: verifyUrl ? (response) => postAccess(verifyUrl, response) : undefined,\n });\n this.#emit('bwalletx-access-granted', { identityKey: a.response.identityKey, response: a.verified });\n } catch (e) {\n const err = e instanceof AccessError ? e : new AccessError('bad_request', String(e));\n this.#emit('bwalletx-access-denied', { code: err.code, message: err.message, have: err.have, need: err.need });\n }\n return;\n }\n const r = await signInWithBwalletX({ wallet: found.wallet, challenge: (identityKey) => postJson<Challenge>(challengeUrl, { identityKey }) });\n const verifyUrl = this.#attr('verify-url');\n const response = verifyUrl ? await postJson(verifyUrl, { identityKey: r.identityKey, nonce: r.nonce, signature: r.signature }) : null;\n this.#emit('bwalletx-signed-in', { identityKey: r.identityKey, method: found.method, nonce: r.nonce, signature: r.signature, response });\n } catch (error) {\n this.#emit('bwalletx-error', { error });\n } finally {\n this.#setBusy(false);\n }\n }\n };\n}\n\n/** Register <bwalletx-signin> (once). Safe to call on a server: it does nothing there. */\nexport function defineBwalletxSignin(tag = SIGNIN_TAG): CustomElementConstructor | undefined {\n if (typeof window === 'undefined' || typeof customElements === 'undefined') return undefined;\n const existing = customElements.get(tag);\n if (existing) return existing;\n const C = createClass();\n customElements.define(tag, C);\n return C;\n}\n"],"mappings":"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","names":["PrivateKey","PrivateKey","PublicKey","PublicKey","b64url","verifyUrl","response"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/nonce-stores.ts","../src/session.ts","../src/verify-payment.ts","../src/link.ts","../src/access-server.ts"],"sourcesContent":["import { ProtoWallet, PublicKey, type WalletProtocol } from '@bsv/sdk';\n\n/** Security level 2, a protocol name used for nothing else. Keep it constant. */\nexport const LOGIN_PROTOCOL: WalletProtocol = [2, 'bwallet sign in'];\nexport const CHALLENGE_LIFETIME_MS = 2 * 60 * 1000;\n\nexport interface PendingChallenge {\n identityKey: string;\n origin: string;\n message: string;\n expiresAt: number;\n}\n\n/**\n * Where challenges wait between the two routes. Use Redis or a database table in production.\n * `take` must read and delete in one step, so each nonce can be tried once.\n */\nexport interface NonceStore {\n put(nonce: string, c: PendingChallenge): Promise<void> | void;\n take(nonce: string): Promise<PendingChallenge | null> | PendingChallenge | null;\n}\n\nlet warned = false;\n\n/**\n * In-memory store. For development and tests only: it is lost on restart and not shared between\n * server processes or serverless instances. Expired entries are pruned on each put.\n */\nexport function memoryStore(opts: { quiet?: boolean } = {}): NonceStore {\n const prod = typeof process !== 'undefined' && process.env?.NODE_ENV === 'production';\n if ((prod || !opts.quiet) && !warned) {\n warned = true;\n console.warn(\n prod\n ? '[@bwalletx/connect] WARNING: the in-memory nonce store is running in production. It is not shared between instances and breaks on serverless. Use redisStore or pgStore.'\n : '[@bwalletx/connect] Using the in-memory nonce store. It is for development only; pass a shared store (redisStore, pgStore) in production.',\n );\n }\n const m = new Map<string, PendingChallenge>();\n return {\n put(nonce, c) {\n const now = Date.now();\n for (const [k, v] of m) if (v.expiresAt < now) m.delete(k);\n m.set(nonce, c);\n },\n take(nonce) {\n const c = m.get(nonce) ?? null;\n m.delete(nonce);\n return c;\n },\n };\n}\n\nlet defaultStore: NonceStore | null = null;\nconst storeOrDefault = (s?: NonceStore) => s ?? (defaultStore ??= memoryStore());\n\nexport function isIdentityKey(x: unknown): x is string {\n if (typeof x !== 'string' || !/^0[23][0-9a-fA-F]{64}$/.test(x)) return false;\n try {\n PublicKey.fromString(x);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction normalOrigin(origin: string): string {\n const u = new URL(origin);\n if (u.origin === 'null' || u.origin !== origin.replace(/\\/$/, '')) {\n throw new Error(`origin must be scheme://host[:port], got ${origin}`);\n }\n return u.origin;\n}\n\n/** The text the user signs. Lines joined with \\n, no trailing newline. */\nexport function loginMessage(origin: string, nonce: string, expiresAt: number): string {\n return [\n `Sign in to ${new URL(origin).host} with bWallet`,\n '',\n 'This proves you hold this wallet. It does not spend anything.',\n '',\n `Origin: ${origin}`,\n `Nonce: ${nonce}`,\n `Expires: ${new Date(expiresAt).toISOString()}`,\n ].join('\\n');\n}\n\nfunction randomNonce(): string {\n const b = new Uint8Array(16);\n globalThis.crypto.getRandomValues(b);\n let s = '';\n for (const x of b) s += String.fromCharCode(x);\n return btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nexport interface CreateChallengeOptions {\n /** YOUR site's origin from config, e.g. \"https://example.com\". Never take it from the request. */\n origin: string;\n /** The identity key the browser claims. Checked again at verify. */\n identityKey: unknown;\n /** Default: a process-wide in-memory store (dev only). */\n store?: NonceStore;\n}\n\nexport interface ChallengeResponse {\n nonce: string;\n message: string;\n protocolID: WalletProtocol;\n keyID: string;\n expiresAt: number;\n}\n\n/** Step 1. Throws if identityKey is not a valid compressed public key. Send the result to the browser. */\nexport async function createChallenge(opts: CreateChallengeOptions): Promise<ChallengeResponse> {\n if (!isIdentityKey(opts.identityKey)) throw new Error('identityKey must be a compressed public key (66 hex chars)');\n const origin = normalOrigin(opts.origin);\n const nonce = randomNonce();\n const expiresAt = Date.now() + CHALLENGE_LIFETIME_MS;\n const message = loginMessage(origin, nonce, expiresAt);\n await storeOrDefault(opts.store).put(nonce, { identityKey: opts.identityKey.toLowerCase(), origin, message, expiresAt });\n return { nonce, message, protocolID: LOGIN_PROTOCOL, keyID: nonce, expiresAt };\n}\n\nexport interface VerifySignInOptions {\n /** YOUR site's origin from config. Must equal the origin the challenge was made for. */\n origin: string;\n /** From the request body. */\n identityKey: unknown;\n nonce: unknown;\n signature: unknown;\n store?: NonceStore;\n}\n\n/**\n * Step 2. Returns the proven identity key (lowercase hex), or null.\n * The nonce is deleted before anything is checked, so each challenge can be tried once.\n */\nexport async function verifySignIn(opts: VerifySignInOptions): Promise<string | null> {\n if (typeof opts.nonce !== 'string' || opts.nonce.length > 64) return null;\n const c = await storeOrDefault(opts.store).take(opts.nonce);\n if (!c || Date.now() > c.expiresAt) return null;\n let origin: string;\n try {\n origin = normalOrigin(opts.origin);\n } catch {\n return null;\n }\n if (c.origin !== origin) return null;\n if (!isIdentityKey(opts.identityKey)) return null;\n const identityKey = opts.identityKey.toLowerCase();\n if (c.identityKey !== identityKey) return null;\n\n const sig = opts.signature;\n if (!Array.isArray(sig) || sig.length < 8 || sig.length > 80 || !sig.every((b) => Number.isInteger(b) && b >= 0 && b <= 255)) {\n return null;\n }\n try {\n const { valid } = await new ProtoWallet('anyone').verifySignature({\n protocolID: LOGIN_PROTOCOL,\n keyID: opts.nonce,\n counterparty: identityKey,\n data: Array.from(new TextEncoder().encode(c.message)),\n signature: sig as number[],\n });\n return valid ? identityKey : null;\n } catch {\n return null; // @bsv/sdk throws on a bad signature instead of returning valid: false\n }\n}\n\n/** True when a request's Origin header is exactly your configured origin. Check it on both routes. */\nexport function originAllowed(requestOrigin: string | null | undefined, origin: string): boolean {\n try {\n return !!requestOrigin && requestOrigin === normalOrigin(origin);\n } catch {\n return false;\n }\n}\n\nexport { redisStore, pgStore, pgNonceTableSql } from './nonce-stores.js';\nexport type { RedisLike, RedisStoreOptions, PgQuery, PgStoreOptions } from './nonce-stores.js';\nexport { signSession, verifySession, serializeCookie, readCookie, MIN_SECRET_LENGTH } from './session.js';\nexport type { SessionPayload, SignSessionOptions, CookieOptions } from './session.js';\nexport { verifyPayment, PaymentVerificationError } from './verify-payment.js';\nexport type { VerifyPaymentOptions, VerifyPaymentResult, ExpectedOutput, TxStatus } from './verify-payment.js';\nexport { linkIdentity, signInOrLink, IdentityLinkConflictError } from './link.js';\nexport type { LinkCallbacks, LinkResult, SignInOrLinkOptions, SignInOrLinkResult } from './link.js';\nexport * from './access.js';\nexport { createAccessChallenge, verifyAccess, verifyHoldingProof, checkTokenHolding, oneSatResolver, bitSignResolver } from './access-server.js';\nexport type { AccessResolver, IdentityStatus, OneSatResolverOptions, BitSignResolverOptions, CreateAccessChallengeOptions, AccessChallengeResponse, VerifyAccessOptions, AccessGrant } from './access-server.js';\n","/**\n * Shared NonceStore adapters. No database driver is imported: you pass your own client or query\n * function. Every adapter makes `take` read-and-delete in one step, so each nonce works once.\n */\nimport type { NonceStore, PendingChallenge } from './server.js';\n\nconst ttlSeconds = (c: PendingChallenge) => Math.max(1, Math.ceil((c.expiresAt - Date.now()) / 1000));\n\nfunction parse(v: unknown): PendingChallenge | null {\n if (v == null) return null;\n try {\n const c = (typeof v === 'string' ? JSON.parse(v) : v) as PendingChallenge;\n if (!c || typeof c.identityKey !== 'string' || typeof c.message !== 'string' || typeof c.expiresAt !== 'number') return null;\n return c.expiresAt < Date.now() ? null : c;\n } catch {\n return null;\n }\n}\n\n/**\n * The Redis commands used. Fits @upstash/redis and node-redis v4+ as they are\n * (`set(key, value, { ex | EX })`, `getdel` / `getDel`). For ioredis pass `flavor: 'ioredis'`.\n */\nexport interface RedisLike {\n set(key: string, value: string, ...args: unknown[]): Promise<unknown>;\n getdel?(key: string): Promise<unknown>;\n getDel?(key: string): Promise<unknown>;\n}\n\nexport interface RedisStoreOptions {\n client: RedisLike;\n /** Key prefix. Default 'bwalletx:nonce:'. */\n prefix?: string;\n /** 'ioredis' uses positional `set(key, value, 'EX', s)`. Default 'object' (Upstash, node-redis). */\n flavor?: 'object' | 'ioredis';\n}\n\n/** Redis / Upstash / Vercel KV. Needs Redis 6.2+ for GETDEL. */\nexport function redisStore(opts: RedisStoreOptions): NonceStore {\n const { client } = opts;\n const prefix = opts.prefix ?? 'bwalletx:nonce:';\n const getdel = client.getdel?.bind(client) ?? client.getDel?.bind(client);\n if (!getdel) throw new Error('redisStore: the client needs getdel (or getDel). Redis 6.2+.');\n return {\n async put(nonce, c) {\n const s = ttlSeconds(c);\n if (opts.flavor === 'ioredis') await client.set(prefix + nonce, JSON.stringify(c), 'EX', s);\n else await client.set(prefix + nonce, JSON.stringify(c), { ex: s, EX: s });\n },\n async take(nonce) {\n return parse(await getdel(prefix + nonce));\n },\n };\n}\n\n/** `query(sql, params)` resolving to `{ rows }` (node-postgres, @vercel/postgres, Neon) or a bare array (postgres.js `sql.unsafe`). */\nexport type PgQuery = (sql: string, params: unknown[]) => Promise<{ rows: unknown[] } | unknown[]>;\n\nexport interface PgStoreOptions {\n query: PgQuery;\n /** Table name (letters, digits, _ and one optional schema dot). Default 'bwalletx_nonces'. */\n table?: string;\n}\n\n/** Run this once (a migration) before using pgStore. */\nexport function pgNonceTableSql(table = 'bwalletx_nonces'): string {\n const t = safeTable(table);\n return `create table if not exists ${t} (\n nonce text primary key,\n challenge jsonb not null,\n expires_at timestamptz not null\n);\ncreate index if not exists ${t.replace('.', '_')}_expires_idx on ${t} (expires_at);`;\n}\n\nfunction safeTable(t: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)?$/.test(t)) throw new Error(`pgStore: bad table name ${t}`);\n return t;\n}\n\n/** Postgres (e.g. self-hosted Supabase). Single-use via DELETE ... RETURNING. */\nexport function pgStore(opts: PgStoreOptions): NonceStore {\n const t = safeTable(opts.table ?? 'bwalletx_nonces');\n const rows = (r: { rows: unknown[] } | unknown[]) => (Array.isArray(r) ? r : r.rows);\n return {\n async put(nonce, c) {\n await opts.query(`delete from ${t} where expires_at < now()`, []);\n await opts.query(`insert into ${t} (nonce, challenge, expires_at) values ($1, $2, to_timestamp($3 / 1000.0))`, [\n nonce,\n JSON.stringify(c),\n c.expiresAt,\n ]);\n },\n async take(nonce) {\n const r = rows(await opts.query(`delete from ${t} where nonce = $1 returning challenge`, [nonce]));\n const row = r[0] as { challenge?: unknown } | undefined;\n return parse(row?.challenge);\n },\n };\n}\n","/**\n * Signed session tokens: base64url(JSON payload) + \".\" + base64url(HMAC-SHA256).\n * WebCrypto only, so it runs in Node 20+, Vercel Edge and Cloudflare Workers.\n * There is no default secret: pass one (32+ chars) or every call throws.\n */\n\nexport interface SessionPayload {\n /** The proven identity key (lowercase hex). */\n sub: string;\n /** Issued at, seconds since the epoch. */\n iat: number;\n /** Expires at, seconds since the epoch. */\n exp: number;\n /** Your app's user id, if the identity key is linked to one. */\n uid?: string;\n handle?: string;\n paymail?: string;\n [claim: string]: unknown;\n}\n\nexport const MIN_SECRET_LENGTH = 32;\n\nconst enc = new TextEncoder();\nconst dec = new TextDecoder();\n\nfunction b64u(bytes: Uint8Array): string {\n let s = '';\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction unb64u(s: string): Uint8Array<ArrayBuffer> {\n if (!/^[A-Za-z0-9_-]*$/.test(s)) throw new Error('bad base64url');\n const b = atob(s.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat((4 - (s.length % 4)) % 4));\n return Uint8Array.from(b, (c) => c.charCodeAt(0));\n}\n\nexport function assertSecret(secret: unknown): asserts secret is string {\n if (typeof secret !== 'string' || secret.length < MIN_SECRET_LENGTH) {\n throw new Error(\n `[@bwalletx/connect] A session secret of at least ${MIN_SECRET_LENGTH} characters is required. ` +\n 'Set it in an environment variable (e.g. BWALLETX_SESSION_SECRET). There is no default.',\n );\n }\n}\n\nconst keys = new Map<string, Promise<CryptoKey>>();\nfunction hmacKey(secret: string): Promise<CryptoKey> {\n let k = keys.get(secret);\n if (!k) {\n k = globalThis.crypto.subtle.importKey('raw', enc.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign', 'verify']);\n keys.set(secret, k);\n }\n return k;\n}\n\nexport interface SignSessionOptions {\n secret: string;\n /** Lifetime in seconds. Default 7 days. */\n maxAge?: number;\n /** For tests. */\n now?: number;\n}\n\n/** Sign a session. `claims.sub` (identity key) is required. */\nexport async function signSession(\n claims: Omit<SessionPayload, 'iat' | 'exp'> & Partial<Pick<SessionPayload, 'iat' | 'exp'>>,\n opts: SignSessionOptions,\n): Promise<string> {\n assertSecret(opts.secret);\n if (typeof claims.sub !== 'string' || !claims.sub) throw new Error('session needs a sub (identity key)');\n const iat = Math.floor((opts.now ?? Date.now()) / 1000);\n const payload: SessionPayload = { ...claims, sub: claims.sub, iat, exp: iat + (opts.maxAge ?? 7 * 24 * 3600) };\n const body = b64u(enc.encode(JSON.stringify(payload)));\n const sig = new Uint8Array(await globalThis.crypto.subtle.sign('HMAC', await hmacKey(opts.secret), enc.encode(body)));\n return `${body}.${b64u(sig)}`;\n}\n\n/** The payload if the token is authentic and unexpired, else null. Never throws on bad input (only on a missing secret). */\nexport async function verifySession(token: unknown, opts: { secret: string; now?: number }): Promise<SessionPayload | null> {\n assertSecret(opts.secret);\n if (typeof token !== 'string' || token.length > 8192) return null;\n const dot = token.indexOf('.');\n if (dot < 1 || dot !== token.lastIndexOf('.')) return null;\n const body = token.slice(0, dot);\n try {\n const sig = unb64u(token.slice(dot + 1));\n // crypto.subtle.verify compares in constant time.\n const ok = await globalThis.crypto.subtle.verify('HMAC', await hmacKey(opts.secret), sig, enc.encode(body));\n if (!ok) return null;\n const p = JSON.parse(dec.decode(unb64u(body))) as SessionPayload;\n if (!p || typeof p.sub !== 'string' || typeof p.exp !== 'number') return null;\n if (Math.floor((opts.now ?? Date.now()) / 1000) >= p.exp) return null;\n return p;\n } catch {\n return null;\n }\n}\n\nexport interface CookieOptions {\n name: string;\n maxAge: number;\n secure?: boolean;\n sameSite?: 'Lax' | 'Strict' | 'None';\n path?: string;\n domain?: string;\n}\n\n/** A Set-Cookie header value. Always HttpOnly. */\nexport function serializeCookie(value: string, o: CookieOptions): string {\n const parts = [`${o.name}=${value}`, `Path=${o.path ?? '/'}`, `Max-Age=${o.maxAge}`, 'HttpOnly', `SameSite=${o.sameSite ?? 'Lax'}`];\n if (o.secure !== false) parts.push('Secure');\n if (o.domain) parts.push(`Domain=${o.domain}`);\n return parts.join('; ');\n}\n\n/** Read one cookie from a Cookie header. */\nexport function readCookie(header: string | null | undefined, name: string): string | null {\n if (!header) return null;\n for (const part of header.split(';')) {\n const i = part.indexOf('=');\n if (i > 0 && part.slice(0, i).trim() === name) return part.slice(i + 1).trim();\n }\n return null;\n}\n","/**\n * Server side: check that a transaction really pays what you expected before you deliver anything.\n * Read-only: it never broadcasts, signs or retries a spend.\n */\nimport { P2PKH, Transaction, Utils, type ChainTracker } from '@bsv/sdk';\n\nexport interface ExpectedOutput {\n /** Locking script hex. Give this or `address`. */\n script?: string;\n /** A P2PKH address. */\n address?: string;\n /** Minimum satoshis this output must carry. */\n satoshis: number;\n}\n\nexport type TxStatus =\n | { state: 'confirmed'; confirmations: number; source: 'woc' | 'arc' }\n | { state: 'mempool'; source: 'woc' | 'arc'; detail?: string }\n | { state: 'not-found' | 'rejected'; source: 'woc' | 'arc'; detail?: string }\n | { state: 'unchecked' };\n\nexport interface VerifyPaymentOptions {\n /** A txid (fetched from WhatsOnChain), raw tx / BEEF / Atomic BEEF as hex, or BEEF bytes. */\n tx: string | number[] | Uint8Array;\n /** Every one must be matched by a different output. */\n expected: ExpectedOutput[];\n network?: 'main' | 'test';\n /** Where to ask for status. Default 'woc'. 'none' skips the network (BEEF only). */\n status?: 'woc' | 'arc' | 'none';\n /** ARC base URL, e.g. https://arc.taal.com. Needed when status is 'arc'. */\n arcUrl?: string;\n /** Sent as Bearer. Read it from env; never hardcode. */\n arcApiKey?: string;\n /** Fail unless the network has seen the tx (mempool or confirmed). Default false. */\n requireSeen?: boolean;\n /** Minimum confirmations. Default 0. */\n minConfirmations?: number;\n /** Also run SPV (merkle proofs + scripts) on a BEEF with this chain tracker. */\n spv?: ChainTracker;\n /** Injected fetch (tests, custom agents). Default globalThis.fetch. */\n fetch?: typeof fetch;\n}\n\nexport interface VerifyPaymentResult {\n ok: true;\n txid: string;\n /** For each expected output, the index of the output that paid it. */\n matched: { vout: number; satoshis: number; script: string }[];\n status: TxStatus;\n}\n\nexport type PaymentErrorCode = 'BAD_TX' | 'TX_NOT_FOUND' | 'OUTPUT_MISSING' | 'NOT_SEEN' | 'REJECTED' | 'SPV_FAILED' | 'NETWORK' | 'BAD_EXPECTED';\n\nexport class PaymentVerificationError extends Error {\n constructor(\n readonly code: PaymentErrorCode,\n message: string,\n readonly txid?: string,\n ) {\n super(message);\n this.name = 'PaymentVerificationError';\n }\n}\n\nconst isHex = (s: string) => /^([0-9a-fA-F]{2})+$/.test(s);\nconst woc = (n: 'main' | 'test') => `https://api.whatsonchain.com/v1/bsv/${n}`;\n\nfunction parseTx(input: string | number[] | Uint8Array): Transaction {\n const bytes = typeof input === 'string' ? Utils.toArray(input, 'hex') : Array.from(input);\n const tries: (() => Transaction)[] = [\n () => Transaction.fromAtomicBEEF(bytes),\n () => Transaction.fromBEEF(bytes),\n () => Transaction.fromBinary(bytes),\n ];\n for (const t of tries) {\n try {\n return t();\n } catch {\n /* next format */\n }\n }\n throw new PaymentVerificationError('BAD_TX', 'Could not parse the transaction (expected a txid, raw tx, BEEF or Atomic BEEF).');\n}\n\nfunction expectedScript(e: ExpectedOutput): string {\n if (!Number.isSafeInteger(e.satoshis) || e.satoshis < 0) throw new PaymentVerificationError('BAD_EXPECTED', 'expected.satoshis must be a non-negative integer');\n if (e.script) {\n if (!isHex(e.script)) throw new PaymentVerificationError('BAD_EXPECTED', 'expected.script must be hex');\n return e.script.toLowerCase();\n }\n if (e.address) {\n try {\n return new P2PKH().lock(e.address).toHex();\n } catch {\n throw new PaymentVerificationError('BAD_EXPECTED', `Not a valid address: ${e.address}`);\n }\n }\n throw new PaymentVerificationError('BAD_EXPECTED', 'Each expected output needs a script or an address');\n}\n\nasync function getJson(f: typeof fetch, url: string, headers: Record<string, string> = {}): Promise<{ status: number; body: unknown }> {\n let r: Response;\n try {\n r = await f(url, { headers });\n } catch (e) {\n throw new PaymentVerificationError('NETWORK', `Could not reach ${new URL(url).host}: ${(e as Error).message}`);\n }\n const text = await r.text();\n let body: unknown = text;\n try {\n body = JSON.parse(text);\n } catch {\n /* plain text */\n }\n return { status: r.status, body };\n}\n\nasync function checkStatus(o: VerifyPaymentOptions, f: typeof fetch, txid: string): Promise<TxStatus> {\n const mode = o.status ?? 'woc';\n if (mode === 'none') return { state: 'unchecked' };\n if (mode === 'arc') {\n if (!o.arcUrl) throw new PaymentVerificationError('NETWORK', \"status 'arc' needs arcUrl\");\n const { status, body } = await getJson(f, `${o.arcUrl.replace(/\\/$/, '')}/v1/tx/${txid}`, o.arcApiKey ? { Authorization: `Bearer ${o.arcApiKey}` } : {});\n if (status === 404) return { state: 'not-found', source: 'arc' };\n if (status >= 400) throw new PaymentVerificationError('NETWORK', `ARC answered ${status}`, txid);\n const b = body as { txStatus?: string; blockHeight?: number; extraInfo?: string };\n const s = String(b.txStatus ?? '').toUpperCase();\n if (s === 'MINED' || s === 'IMMUTABLE') return { state: 'confirmed', confirmations: 1, source: 'arc' };\n if (s === 'REJECTED' || s === 'DOUBLE_SPEND_ATTEMPTED') return { state: 'rejected', source: 'arc', detail: b.extraInfo ?? s };\n if (s === 'UNKNOWN' || s === '') return { state: 'not-found', source: 'arc', detail: s };\n return { state: 'mempool', source: 'arc', detail: s };\n }\n const { status, body } = await getJson(f, `${woc(o.network ?? 'main')}/tx/hash/${txid}`);\n if (status === 404) return { state: 'not-found', source: 'woc' };\n if (status >= 400) throw new PaymentVerificationError('NETWORK', `WhatsOnChain answered ${status}`, txid);\n const c = Number((body as { confirmations?: number }).confirmations ?? 0);\n return c > 0 ? { state: 'confirmed', confirmations: c, source: 'woc' } : { state: 'mempool', source: 'woc' };\n}\n\n/**\n * Throws PaymentVerificationError (with a `code`) unless every expected output is paid by a\n * distinct output of the transaction with at least the expected satoshis.\n */\nexport async function verifyPayment(o: VerifyPaymentOptions): Promise<VerifyPaymentResult> {\n const f = o.fetch ?? globalThis.fetch;\n if (!o.expected?.length) throw new PaymentVerificationError('BAD_EXPECTED', 'Pass at least one expected output');\n const want = o.expected.map((e) => ({ script: expectedScript(e), satoshis: e.satoshis }));\n\n let tx: Transaction;\n if (typeof o.tx === 'string' && /^[0-9a-fA-F]{64}$/.test(o.tx)) {\n const txid = o.tx.toLowerCase();\n let r: Response;\n try {\n r = await f(`${woc(o.network ?? 'main')}/tx/${txid}/hex`);\n } catch (e) {\n throw new PaymentVerificationError('NETWORK', `Could not reach WhatsOnChain: ${(e as Error).message}`, txid);\n }\n if (r.status === 404) throw new PaymentVerificationError('TX_NOT_FOUND', `Transaction ${txid} was not found`, txid);\n if (!r.ok) throw new PaymentVerificationError('NETWORK', `WhatsOnChain answered ${r.status}`, txid);\n tx = parseTx((await r.text()).trim());\n if (tx.id('hex') !== txid) throw new PaymentVerificationError('BAD_TX', 'The fetched transaction does not match the txid', txid);\n } else {\n if (typeof o.tx === 'string' && !isHex(o.tx)) throw new PaymentVerificationError('BAD_TX', 'tx must be a txid or hex');\n tx = parseTx(o.tx);\n }\n const txid = tx.id('hex');\n\n if (o.spv) {\n let ok = false;\n try {\n ok = await tx.verify(o.spv);\n } catch (e) {\n throw new PaymentVerificationError('SPV_FAILED', `SPV check failed: ${(e as Error).message}`, txid);\n }\n if (!ok) throw new PaymentVerificationError('SPV_FAILED', 'SPV check failed', txid);\n }\n\n const used = new Set<number>();\n const matched: VerifyPaymentResult['matched'] = [];\n for (const w of want) {\n const vout = tx.outputs.findIndex(\n (out, i) => !used.has(i) && out.lockingScript.toHex() === w.script && (out.satoshis ?? 0) >= w.satoshis,\n );\n if (vout < 0) {\n throw new PaymentVerificationError('OUTPUT_MISSING', `No output pays ${w.satoshis} sats to script ${w.script.slice(0, 16)}…`, txid);\n }\n used.add(vout);\n matched.push({ vout, satoshis: tx.outputs[vout].satoshis ?? 0, script: w.script });\n }\n\n const status = await checkStatus(o, f, txid);\n if (status.state === 'rejected') throw new PaymentVerificationError('REJECTED', `The network rejected ${txid}: ${status.detail ?? ''}`.trim(), txid);\n if ((o.requireSeen || (o.minConfirmations ?? 0) > 0) && status.state !== 'mempool' && status.state !== 'confirmed') {\n throw new PaymentVerificationError('NOT_SEEN', `The network has not seen ${txid} yet`, txid);\n }\n const conf = status.state === 'confirmed' ? status.confirmations : 0;\n if ((o.minConfirmations ?? 0) > conf) {\n throw new PaymentVerificationError('NOT_SEEN', `${txid} has ${conf} confirmations, needs ${o.minConfirmations}`, txid);\n }\n return { ok: true, txid, matched, status };\n}\n","/**\n * Link a proven identity key to a user in YOUR auth system (Supabase, next-auth, your own table).\n * You supply the storage callbacks; this module only holds the rules.\n */\n\nexport interface LinkCallbacks {\n /** The user id this identity key is linked to, or null. */\n findUserByIdentityKey(identityKey: string): Promise<string | null> | string | null;\n /** Save the link. Make (identity_key) unique in your table so a race cannot double-link. */\n attach(userId: string, identityKey: string): Promise<void> | void;\n}\n\nexport type LinkResult = { status: 'linked' | 'already-linked'; userId: string; identityKey: string };\n\nexport class IdentityLinkConflictError extends Error {\n readonly code = 'IDENTITY_LINKED_TO_OTHER_USER';\n constructor(\n readonly identityKey: string,\n readonly otherUserId: string,\n ) {\n super('This bWalletX identity is already linked to a different account. Sign in with that account, or unlink it there first.');\n this.name = 'IdentityLinkConflictError';\n }\n}\n\nconst norm = (k: string) => {\n if (typeof k !== 'string' || !/^0[23][0-9a-fA-F]{64}$/.test(k)) throw new Error('identityKey must be a compressed public key (66 hex chars)');\n return k.toLowerCase();\n};\n\n/**\n * Link `identityKey` (already verified with verifySignIn) to the signed-in `userId`.\n * Throws IdentityLinkConflictError if it belongs to someone else. Idempotent for the same user.\n */\nexport async function linkIdentity(userId: string, identityKey: string, cb: LinkCallbacks): Promise<LinkResult> {\n if (!userId) throw new Error('linkIdentity needs the current user id');\n const key = norm(identityKey);\n const owner = await cb.findUserByIdentityKey(key);\n if (owner && owner !== userId) throw new IdentityLinkConflictError(key, owner);\n if (owner === userId) return { status: 'already-linked', userId, identityKey: key };\n await cb.attach(userId, key);\n return { status: 'linked', userId, identityKey: key };\n}\n\nexport interface SignInOrLinkOptions extends LinkCallbacks {\n /** The user already signed in some other way (e.g. HandCash, email), if any. */\n currentUserId?: string | null;\n /** Make a new user for an unknown identity key. Without it, unknown keys return status 'unknown'. */\n createUser?(identityKey: string): Promise<string> | string;\n}\n\nexport type SignInOrLinkResult =\n | { status: 'signed-in' | 'linked' | 'already-linked' | 'created'; userId: string; identityKey: string }\n | { status: 'unknown'; userId: null; identityKey: string };\n\n/**\n * The usual verify-route logic: signed in already → link; known key → that user; else create (or report unknown).\n * Throws IdentityLinkConflictError when a signed-in user tries to link a key owned by another user.\n */\nexport async function signInOrLink(identityKey: string, o: SignInOrLinkOptions): Promise<SignInOrLinkResult> {\n const key = norm(identityKey);\n if (o.currentUserId) return linkIdentity(o.currentUserId, key, o);\n const owner = await o.findUserByIdentityKey(key);\n if (owner) return { status: 'signed-in', userId: owner, identityKey: key };\n if (!o.createUser) return { status: 'unknown', userId: null, identityKey: key };\n const userId = await o.createUser(key);\n await o.attach(userId, key);\n return { status: 'created', userId, identityKey: key };\n}\n","/**\n * Server side of the access protocol (docs/ACCESS-PROTOCOL.md): issue a challenge, verify the\n * wallet's response against an indexer, and re-check a granted session later.\n *\n * Fails closed: anything that cannot be confirmed is an AccessError, never a grant.\n */\nimport { ProtoWallet, PublicKey, Signature } from '@bsv/sdk';\nimport {\n ACCESS_CHALLENGE_LIFETIME_S,\n ACCESS_PROTOCOL,\n AccessError,\n MAX_HOLDING_PROOFS,\n atLeastRaw,\n canonicalJson,\n challengeBytes,\n kindFor,\n normaliseRequirement,\n parseAccessChallenge,\n tokenNeedRaw,\n type AccessChallenge,\n type AccessKind,\n type AccessRequirement,\n type AccessResponse,\n} from './access.js';\nimport { isIdentityKey, type NonceStore } from './server.js';\n\n// ── Resolvers ─────────────────────────────────────────────────────────────────────────────\n\nexport interface IdentityStatus {\n /** bit-sign identity level: 0 none, 1 Basic … 4 Sovereign (Veriff). */\n level: number;\n /** A live KYC credential for this identity key. */\n kyc: boolean;\n}\n\n/**\n * Where verifyAccess reads the chain and identity data. Every method THROWS when it cannot answer;\n * a throw becomes `indexer_unavailable`, never \"holds nothing\".\n */\nexport interface AccessResolver {\n /** Confirmed + unspent raw balance of `tokenId` ('bsv21:…') over these P2PKH addresses. */\n tokenBalance(tokenId: string, addresses: string[]): Promise<string>;\n /** Total supply, raw. Needed only for minBps requirements. */\n tokenSupply?(tokenId: string): Promise<string>;\n /** Identity level and KYC for a key. Needed only for identityLevel / kyc requirements. */\n identity?(identityKey: string, response: AccessResponse): Promise<IdentityStatus>;\n}\n\ntype FetchLike = typeof fetch;\n\nexport interface OneSatResolverOptions {\n /** Default 'https://api.1sat.app/1sat'. */\n base?: string;\n fetch?: FetchLike;\n timeoutMs?: number;\n}\n\nconst bare = (tokenId: string) => tokenId.replace(/^bsv21:/, '');\n\n/** BSV-21 balances and supply from the 1Sat indexer (the one bit-sign's token rooms use). */\nexport function oneSatResolver(o: OneSatResolverOptions = {}): AccessResolver {\n const base = (o.base ?? 'https://api.1sat.app/1sat').replace(/\\/$/, '');\n const f = o.fetch ?? globalThis.fetch;\n const t = o.timeoutMs ?? 12_000;\n const call = async (path: string, init?: RequestInit) => {\n const res = await f(`${base}${path}`, { ...init, signal: AbortSignal.timeout(t), cache: 'no-store' });\n if (!res.ok) throw new Error(`1sat ${res.status} for ${path}`);\n return res.json() as Promise<unknown>;\n };\n return {\n async tokenBalance(tokenId, addresses) {\n const sorted = [...new Set(addresses)].sort();\n let total = 0n;\n for (let i = 0; i < sorted.length; i += 100) {\n const j = (await call(`/bsv21/${bare(tokenId)}/p2pkh/balance`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(sorted.slice(i, i + 100)),\n })) as { balance?: number | string } | null;\n const b = j?.balance ?? 0;\n const s = typeof b === 'number' ? String(Math.trunc(b)) : String(b).split('.')[0] || '0';\n if (!/^\\d+$/.test(s)) throw new Error('1sat returned a bad balance');\n total += BigInt(s);\n }\n return total.toString();\n },\n async tokenSupply(tokenId) {\n const j = (await call(`/bsv21/${bare(tokenId)}`)) as Record<string, unknown> | null;\n const tok = ((j?.token as Record<string, unknown> | undefined) ?? j) || {};\n const v = tok.amt ?? tok.max ?? tok.supply;\n const s = v === undefined || v === null ? '' : String(v).split('.')[0];\n if (!/^\\d+$/.test(s) || s === '0') throw new Error('1sat did not report a supply');\n return s;\n },\n };\n}\n\nexport interface BitSignResolverOptions {\n /** Default 'https://bit-sign.online'. */\n base?: string;\n fetch?: FetchLike;\n timeoutMs?: number;\n /** Token reads. Default: oneSatResolver(). */\n tokens?: AccessResolver;\n}\n\n/**\n * Identity level / KYC from bit-sign's POST /api/access/verify, which checks the signed response\n * itself (the user's signature is their consent to disclose those facts to this origin).\n * Token reads go to `tokens` (default the 1Sat indexer).\n */\nexport function bitSignResolver(o: BitSignResolverOptions = {}): AccessResolver {\n const base = (o.base ?? 'https://bit-sign.online').replace(/\\/$/, '');\n const f = o.fetch ?? globalThis.fetch;\n const tokens = o.tokens ?? oneSatResolver({ fetch: f });\n return {\n tokenBalance: (id, a) => tokens.tokenBalance(id, a),\n tokenSupply: tokens.tokenSupply ? (id) => tokens.tokenSupply!(id) : undefined,\n async identity(identityKey, response) {\n const res = await f(`${base}/api/access/verify`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ response, only: 'identity' }),\n signal: AbortSignal.timeout(o.timeoutMs ?? 12_000),\n cache: 'no-store',\n });\n const j = (await res.json().catch(() => null)) as { identityKey?: string; identity?: { level?: unknown; kyc?: unknown } } | null;\n if (!j?.identity || j.identityKey !== identityKey) throw new Error(`bit-sign ${res.status}`);\n return { level: Number(j.identity.level) || 0, kyc: j.identity.kyc === true };\n },\n };\n}\n\n// ── Challenge ─────────────────────────────────────────────────────────────────────────────\n\nfunction normalOrigin(origin: string): string {\n const u = new URL(origin);\n if (u.origin === 'null' || u.origin !== origin.replace(/\\/$/, '')) throw new Error(`origin must be scheme://host[:port], got ${origin}`);\n return u.origin;\n}\n\nfunction randomNonce(): string {\n const b = new Uint8Array(18);\n globalThis.crypto.getRandomValues(b);\n let s = '';\n for (const x of b) s += String.fromCharCode(x);\n return btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nexport interface CreateAccessChallengeOptions {\n /** YOUR origin from config. Never from the request. */\n origin: string;\n /** The requirement, from YOUR config. Never from the request. */\n require: AccessRequirement;\n /** A shared store (redisStore / pgStore). The same stores sign-in uses. */\n store: NonceStore;\n /** The identity key the browser says it is (optional). If given, a different signer is wrong_account. */\n identityKey?: unknown;\n /** Default: '403' when a token is required, else '401'. */\n kind?: AccessKind;\n lifetimeS?: number;\n now?: number;\n}\n\nexport interface AccessChallengeResponse {\n /** The canonical JSON the wallet signs. Pass it to the wallet unchanged. */\n challenge: string;\n nonce: string;\n kind: AccessKind;\n protocolID: typeof ACCESS_PROTOCOL;\n keyID: string;\n exp: number;\n}\n\nexport async function createAccessChallenge(o: CreateAccessChallengeOptions): Promise<AccessChallengeResponse> {\n const origin = normalOrigin(o.origin);\n const require = normaliseRequirement(o.require);\n let sub: string | undefined;\n if (o.identityKey !== undefined && o.identityKey !== null && o.identityKey !== '') {\n if (!isIdentityKey(o.identityKey)) throw new AccessError('bad_request', 'identityKey must be a compressed public key');\n sub = o.identityKey.toLowerCase();\n }\n const iat = Math.floor((o.now ?? Date.now()) / 1000);\n const exp = iat + (o.lifetimeS ?? ACCESS_CHALLENGE_LIFETIME_S);\n const nonce = randomNonce();\n const c: AccessChallenge = { v: 1, kind: o.kind ?? kindFor(require), origin, nonce, iat, exp, sub, require };\n const challenge = canonicalJson(c);\n await o.store.put(nonce, { identityKey: sub ?? '', origin, message: challenge, expiresAt: exp * 1000 });\n return { challenge, nonce, kind: c.kind, protocolID: ACCESS_PROTOCOL, keyID: nonce, exp };\n}\n\n// ── Verify ────────────────────────────────────────────────────────────────────────────────\n\nconst isByteArray = (s: unknown): s is number[] =>\n Array.isArray(s) && s.length >= 8 && s.length <= 80 && s.every((b) => Number.isInteger(b) && b >= 0 && b <= 255);\n\n/** The P2PKH address a holding proof establishes, or null if the proof does not verify. */\nexport function verifyHoldingProof(challenge: string, p: unknown): string | null {\n const proof = p as { pubkey?: unknown; signature?: unknown } | null;\n if (!proof || typeof proof.pubkey !== 'string' || !/^0[23][0-9a-fA-F]{64}$/.test(proof.pubkey) || !isByteArray(proof.signature)) return null;\n try {\n const pub = PublicKey.fromString(proof.pubkey);\n const sig = Signature.fromDER(proof.signature);\n return pub.verify(challengeBytes(challenge), sig) ? pub.toAddress() : null;\n } catch {\n return null;\n }\n}\n\nexport interface VerifyAccessOptions {\n origin: string;\n /** The body the browser posted (AccessResponse). Untrusted. */\n response: unknown;\n store: NonceStore;\n resolver: AccessResolver;\n /**\n * The requirement YOUR config says this gate needs. If given, the challenge must carry exactly it\n * (defence in depth: the challenge came from your store, but configs change).\n */\n require?: AccessRequirement;\n now?: number;\n}\n\nexport interface AccessGrant {\n ok: true;\n identityKey: string;\n kind: AccessKind;\n require: AccessRequirement;\n /** Proven addresses holding the token (store them to re-check later). */\n addresses: string[];\n have: { tokenRaw?: string; needRaw?: string; identityLevel?: number; kyc?: boolean };\n}\n\n/**\n * Verify a wallet's response. Returns the grant, or throws AccessError with a protocol code.\n * The nonce is consumed first, so each challenge can be tried once.\n */\nexport async function verifyAccess(o: VerifyAccessOptions): Promise<AccessGrant> {\n const r = o.response as Partial<AccessResponse> | null;\n if (!r || typeof r !== 'object' || r.v !== 1) throw new AccessError('bad_request', 'response must be { v: 1, challenge, identityKey, signature }');\n const c = parseAccessChallenge(r.challenge);\n const nowS = Math.floor((o.now ?? Date.now()) / 1000);\n\n const pending = await o.store.take(c.nonce);\n if (!pending) throw new AccessError(nowS >= c.exp ? 'expired' : 'replay');\n if (nowS >= c.exp || (o.now ?? Date.now()) > pending.expiresAt) throw new AccessError('expired');\n if (pending.message !== r.challenge) throw new AccessError('replay', 'challenge does not match the one issued');\n let origin: string;\n try {\n origin = normalOrigin(o.origin);\n } catch {\n throw new AccessError('bad_request', 'server origin is misconfigured');\n }\n if (c.origin !== origin || pending.origin !== origin) throw new AccessError('bad_request', 'origin mismatch');\n if (o.require && canonicalJson(normaliseRequirement(o.require)) !== canonicalJson(c.require)) {\n throw new AccessError('bad_request', 'challenge requirement does not match this gate');\n }\n\n if (!isIdentityKey(r.identityKey)) throw new AccessError('bad_request', 'identityKey must be a compressed public key');\n const identityKey = r.identityKey.toLowerCase();\n if (c.sub && c.sub !== identityKey) throw new AccessError('wrong_account');\n if (!isByteArray(r.signature)) throw new AccessError('invalid_signature');\n let valid = false;\n try {\n ({ valid } = await new ProtoWallet('anyone').verifySignature({\n protocolID: ACCESS_PROTOCOL,\n keyID: c.nonce,\n counterparty: identityKey,\n data: challengeBytes(r.challenge as string),\n signature: r.signature,\n }));\n } catch {\n valid = false; // @bsv/sdk throws on a bad signature\n }\n if (!valid) throw new AccessError('invalid_signature');\n\n const grant: AccessGrant = { ok: true, identityKey, kind: c.kind, require: c.require, addresses: [], have: {} };\n\n if (c.require.identityLevel || c.require.kyc) {\n if (!o.resolver.identity) throw new AccessError('indexer_unavailable', 'no identity resolver configured');\n let id: IdentityStatus;\n try {\n id = await o.resolver.identity(identityKey, r as AccessResponse);\n } catch (e) {\n throw new AccessError('indexer_unavailable', `identity lookup failed: ${(e as Error).message}`);\n }\n grant.have.identityLevel = id.level;\n grant.have.kyc = id.kyc;\n if (c.require.kyc && !id.kyc) throw new AccessError('kyc_required');\n if (c.require.identityLevel && id.level < c.require.identityLevel) {\n throw new AccessError('identity_level_too_low', undefined, { have: id.level, need: c.require.identityLevel });\n }\n }\n\n if (c.require.token) {\n const proofs = Array.isArray(r.holdings) ? r.holdings.slice(0, MAX_HOLDING_PROOFS) : [];\n const addresses = new Set<string>();\n for (const p of proofs) {\n const a = verifyHoldingProof(r.challenge as string, p);\n if (a) addresses.add(a);\n }\n grant.addresses = [...addresses].sort();\n const check = await checkTokenHolding(c.require, grant.addresses, o.resolver);\n grant.have.tokenRaw = check.have;\n grant.have.needRaw = check.need;\n }\n return grant;\n}\n\n/**\n * Re-check a token requirement over already-proven addresses (for periodic re-verification).\n * Returns { have, need } or throws AccessError('insufficient_tokens' | 'indexer_unavailable').\n */\nexport async function checkTokenHolding(\n require: AccessRequirement,\n addresses: string[],\n resolver: AccessResolver,\n): Promise<{ have: string; need: string }> {\n const t = require.token;\n if (!t) return { have: '0', need: '0' };\n let supply: string | undefined;\n if (t.minBps) {\n if (!resolver.tokenSupply) throw new AccessError('indexer_unavailable', 'no supply resolver configured');\n try {\n supply = await resolver.tokenSupply(t.id);\n } catch (e) {\n throw new AccessError('indexer_unavailable', `supply lookup failed: ${(e as Error).message}`);\n }\n }\n const need = tokenNeedRaw(t, supply);\n if (!addresses.length) throw new AccessError('insufficient_tokens', undefined, { have: '0', need });\n let have: string;\n try {\n have = await resolver.tokenBalance(t.id, addresses);\n } catch (e) {\n throw new AccessError('indexer_unavailable', `balance lookup failed: ${(e as Error).message}`);\n }\n if (!atLeastRaw(have, need)) throw new AccessError('insufficient_tokens', undefined, { have, need });\n return { have, need };\n}\n"],"mappings":"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","names":["ProtoWallet","PublicKey","status","body","txid","require","PublicKey","normalOrigin","randomNonce","ProtoWallet"]}
|