@bwalletx/connect 0.5.3 → 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.
Files changed (50) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +80 -8
  3. package/dist/bwalletx-connect.global.js +92 -25
  4. package/dist/bwalletx-connect.global.js.map +1 -1
  5. package/dist/{wallets-VOKIKBbO.d.ts → choice-DCh-tgpT.d.cts} +113 -5
  6. package/dist/{wallets-VOKIKBbO.d.cts → choice-DCh-tgpT.d.ts} +113 -5
  7. package/dist/chunk-34DKBQNN.js +222 -0
  8. package/dist/chunk-34DKBQNN.js.map +1 -0
  9. package/dist/{chunk-QRXFL66W.js → chunk-A2WLGS25.js} +6 -4
  10. package/dist/chunk-A2WLGS25.js.map +1 -0
  11. package/dist/chunk-IFGOAROM.js +255 -0
  12. package/dist/chunk-IFGOAROM.js.map +1 -0
  13. package/dist/chunk-LS6AYEBO.js +1886 -0
  14. package/dist/chunk-LS6AYEBO.js.map +1 -0
  15. package/dist/element-D9Zl-x12.d.cts +46 -0
  16. package/dist/element-D9Zl-x12.d.ts +46 -0
  17. package/dist/element.cjs +1221 -67
  18. package/dist/element.cjs.map +1 -1
  19. package/dist/element.d.cts +23 -28
  20. package/dist/element.d.ts +23 -28
  21. package/dist/element.js +29 -2
  22. package/dist/element.js.map +1 -1
  23. package/dist/index.cjs +1539 -449
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +185 -12
  26. package/dist/index.d.ts +185 -12
  27. package/dist/index.js +106 -12
  28. package/dist/index.js.map +1 -1
  29. package/dist/next.cjs +5 -3
  30. package/dist/next.cjs.map +1 -1
  31. package/dist/next.js +1 -1
  32. package/dist/react.cjs +1073 -194
  33. package/dist/react.cjs.map +1 -1
  34. package/dist/react.d.cts +75 -8
  35. package/dist/react.d.ts +75 -8
  36. package/dist/react.js +121 -40
  37. package/dist/react.js.map +1 -1
  38. package/dist/server.cjs +5 -3
  39. package/dist/server.cjs.map +1 -1
  40. package/dist/server.d.cts +8 -3
  41. package/dist/server.d.ts +8 -3
  42. package/dist/server.js +1 -1
  43. package/dist/shell-react.cjs.map +1 -1
  44. package/dist/shell-react.js.map +1 -1
  45. package/package.json +1 -1
  46. package/dist/chunk-IUDD7YTQ.js +0 -839
  47. package/dist/chunk-IUDD7YTQ.js.map +0 -1
  48. package/dist/chunk-PI42H3XY.js +0 -459
  49. package/dist/chunk-PI42H3XY.js.map +0 -1
  50. package/dist/chunk-QRXFL66W.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { WalletInterface, WalletProtocol } from '@bsv/sdk';
2
- import { f as PairingOptions, W as WalletOption } from './wallets-VOKIKBbO.cjs';
3
- export { g as BRC29_PROTOCOL, i as Brc29Remittance, B as BuyTokenRequest, C as ConnectedWallet, D as DiscoverWalletsOptions, H as HandCashAdapterOptions, L as LegacyPayer, j as PairConnectionOptions, k as PairStorage, l as PairedWallet, b as PayOptions, m as PayOutput, P as PayRequest, a as PayResult, n as PaySource, c as PaymentError, o as PaymentErrorCode, S as SocketFactory, q as SocketLike, T as TokenQuote, r as WalletKind, s as amountInSats, d as brc100Option, t as buyToken, u as clearPairing, e as discoverWallets, h as handcashAdapter, v as isIdentityKeyHex, w as isPaymail, x as pairBwalletX, p as pairingOption, y as pay, z as resolvePaymailP2P, A as restorePairing, E as tip } from './wallets-VOKIKBbO.cjs';
4
- export { AuthorizeParams, GET_URL, SIGNIN_CSS, SIGNIN_TAG, SigninBrand, SigninLabel, SigninSize, SigninTheme, WEB_WALLET_URL, buildAuthorizeUrl, defineBwalletxSignin, markSvg, signinText } from './element.cjs';
2
+ import { g as PairingOptions, W as WalletOption, A as AttemptHook, C as ConnectedWallet, S as Substrate, i as ChoiceReason } from './choice-DCh-tgpT.cjs';
3
+ export { j as AttemptOutcome, k as BRC29_PROTOCOL, l as BWALLETX_TYPE, m as Brc29Remittance, B as BuyTokenRequest, n as ConnectAttempt, o as ConnectOptions, D as DESKTOP_OPTION_ID, q as DecideWalletOptions, r as DiscoverWalletsOptions, H as HandCashAdapterOptions, L as LegacyPayer, s as PairConnectionOptions, t as PairStorage, u as PairedWallet, b as PayOptions, v as PayOutput, P as PayRequest, a as PayResult, w as PaySource, c as PaymentError, x as PaymentErrorCode, y as SocketFactory, z as SocketLike, T as TokenQuote, E as WalletChoice, F as WalletKind, G as amountInSats, I as attemptFor, d as autoChoice, e as brc100Option, J as buyToken, K as chooserOrder, M as clearPairing, N as cwiIsAnnounced, O as decideWallet, Q as desktopOption, f as discoverWallets, h as handcashAdapter, R as hasBwalletX, U as isIdentityKeyHex, V as isPaymail, X as isPresentBwalletX, Y as otherDetected, Z as outcomeOf, _ as pairBwalletX, p as pairingOption, $ as pay, a0 as reportAttempt, a1 as resolvePaymailP2P, a2 as restorePairing, a3 as substrateOf, a4 as tip, a5 as walletTypeOf } from './choice-DCh-tgpT.cjs';
4
+ export { A as AuthorizeParams, G as GET_URL, M as MENU_CSS, P as PENDING_LABEL, e as PENDING_LABEL_OTHER, f as PENDING_NOTE, g as SIGNIN_CSS, h as SIGNIN_TAG, i as SigninAccount, c as SigninBrand, b as SigninLabel, j as SigninMode, S as SigninSize, d as SigninState, a as SigninTheme, W as WEB_WALLET_URL, k as buildAuthorizeUrl, l as defineBwalletxSignin, m as markSvg, s as signinText } from './element-D9Zl-x12.cjs';
5
+ export { BUTTON_TAG, ButtonState, CONNECTED_KEY, defineBwalletxButton, dropLegacyConnectedKey, getUrlFor, handleLabel, stateFor } from './element.cjs';
5
6
  import { b as AccessResponse, H as HoldingProof, A as AccessError } from './access-Dp0eKIOc.cjs';
6
7
  export { f as ACCESS_ERROR_STATUS, d as ACCESS_PROTOCOL, g as ACCESS_VERSION, h as AccessChallenge, i as AccessErrorBody, j as AccessErrorCode, c as AccessKind, a as AccessRequirement, P as PROTOCOL_MEDIA, T as TokenRequirement, k as accessErrorMessage, m as canonicalJson, r as protocolMediaUrl } from './access-Dp0eKIOc.cjs';
7
8
 
@@ -16,10 +17,22 @@ interface FoundWallet {
16
17
  method: FoundBy;
17
18
  rdns: string | null;
18
19
  }
20
+ /**
21
+ * Default wait for a wallet that has not answered yet, ms. bWalletX for Chrome and the in-app browser both answer
22
+ * `brc100:requestWallet` synchronously, so a found wallet resolves at once;
23
+ * this is only how long "nothing here" takes before the pairing QR shows. Was 1200 (0.5.3 and earlier).
24
+ */
25
+ declare const DEFAULT_DISCOVER_MS = 300;
19
26
  /**
20
27
  * Like findBwalletX, but also says which bWalletX answered.
21
- * Order: a BRC-100 announcement with a bWalletX rdns; then `window.CWI` (set by the in-app
22
- * browser, and by older builds that do not announce); otherwise null.
28
+ *
29
+ * bWalletX is recognised ONLY by its own markers: a BRC-100 announcement carrying a bWalletX rdns
30
+ * (`com.bwalletx.extension` from the Chrome extension, `space.bwallet.mobile` from the in-app browser; both answer
31
+ * `brc100:requestWallet` at once), or, only when framed, the XDM answer of a parent on BWALLETX_PARENT_ORIGINS.
32
+ *
33
+ * Never by `window.CWI` (0.5.6): another wallet (Metanet / BSV Desktop, Yours) can set or overwrite it, and treating
34
+ * whoever holds it as bWalletX handed our sign-in to that wallet. Every bWalletX build since 3 Oct 2026 announces.
35
+ * Resolves null after `ms` when no bWalletX announced (other wallets: discoverWallets).
23
36
  */
24
37
  declare function discoverBwalletX(ms?: number): Promise<FoundWallet | null>;
25
38
  /**
@@ -27,6 +40,17 @@ declare function discoverBwalletX(ms?: number): Promise<FoundWallet | null>;
27
40
  * open in bWalletX's in-app browser. Resolves null if nothing answered within `ms`.
28
41
  */
29
42
  declare function findBwalletX(ms?: number): Promise<WalletInterface | null>;
43
+ /** True inside a frame (or when the parent can't be read). */
44
+ declare const isFramed: () => boolean;
45
+ /**
46
+ * Wake the wallet before the click (call on pointerenter / focus / touchstart of your Connect button). Chrome stops an
47
+ * idle extension worker after ~30 s, and a cold worker needs 1-3 s to reopen the wallet; this sends a liveness call
48
+ * (isAuthenticated: never shows a prompt, never reveals a key) so that work starts while the pointer is on its way.
49
+ * At most once every 20 s. Does nothing when no bWalletX is in the page.
50
+ */
51
+ declare function prewarmBwalletX(): void;
52
+ /** Prewarm on hover, keyboard focus and touch. Returns a function that removes the listeners. */
53
+ declare function bindPrewarm(el: EventTarget): () => void;
30
54
 
31
55
  /** Security level 2, a protocol name used for nothing else. */
32
56
  declare const LOGIN_PROTOCOL: WalletProtocol;
@@ -38,17 +62,45 @@ interface Challenge {
38
62
  protocolID?: WalletProtocol;
39
63
  }
40
64
  type SignInMethod = 'extension' | 'in-app' | 'pairing' | 'wallet';
65
+ /**
66
+ * Progress for the button label. 'finding': looking for a wallet (sub-second); 'opening': a wallet was found and its
67
+ * approval is on the way ("Opening your wallet…"); 'pairing': no wallet in this browser, the QR is showing;
68
+ * 'signing': the challenge arrived, the wallet's sign-in approval is being asked for.
69
+ */
70
+ type SignInStatus = 'finding' | 'opening' | 'pairing' | 'signing';
41
71
  interface SignInOptions {
42
- /** Ask your server for a challenge for this identity key. */
43
- challenge: (identityKey: string) => Promise<Challenge>;
72
+ /**
73
+ * Ask your server for a challenge. Since 0.5.5 it is called BEFORE the wallet is asked anything, and gets an identity
74
+ * key only when you pass `identityKey` (an identity you already connected) or set `challengeNeedsIdentityKey`;
75
+ * otherwise undefined. The 0.5.5 server helpers (createChallenge) accept no key, and verifySignIn binds the key the
76
+ * browser then claims to the signature. A pre-0.5.5 server that refuses a keyless challenge is detected and retried
77
+ * in the old order automatically.
78
+ */
79
+ challenge(identityKey?: string): Promise<Challenge>;
80
+ /**
81
+ * The identity key you already have from an earlier connect (reuse the connected identity): the wallet is then asked
82
+ * for the signature only. Without it, getPublicKey({ identityKey: true }) and createSignature go to the wallet
83
+ * together (Promise.all), so the wallet shows ONE sheet, not three.
84
+ */
85
+ identityKey?: string;
86
+ /**
87
+ * Servers older than 0.5.5 refuse a challenge without an identity key. Set true to use the old order straight away
88
+ * (identity key, then the challenge, then the signature: two wallet calls). Without it, the old order is used only
89
+ * after such a server has refused a keyless challenge.
90
+ */
91
+ challengeNeedsIdentityKey?: boolean;
92
+ /** Skip waitForAuthentication before signing (the provider already waited). Default false. */
93
+ skipWaitForAuthentication?: boolean;
44
94
  /** Use this wallet instead of looking for one. `method` is then 'wallet'. */
45
95
  wallet?: WalletInterface;
46
96
  /** How to show the QR and code if pairing is needed. Without it, pairing is not tried. */
47
97
  pairing?: PairingOptions;
48
98
  /** Reuse a pairing stored by an earlier sign-in before showing a new QR. Default true. */
49
99
  reusePairing?: boolean;
50
- /** How long to wait for the extension or in-app browser to answer, in ms. Default 1200. */
100
+ /** How long to wait for a wallet that has not answered, in ms, before pairing. Default 300 (a present wallet answers at once). */
51
101
  discoverMs?: number;
102
+ /** Called as the sign-in moves on, so the button can say "Opening your wallet…" straight away. */
103
+ onStatus?: (status: SignInStatus) => void;
52
104
  }
53
105
  interface SignInResult {
54
106
  identityKey: string;
@@ -60,15 +112,46 @@ interface SignInResult {
60
112
  wallet: WalletInterface;
61
113
  }
62
114
  /** Find a wallet: extension or in-app browser first, then a stored pairing, then a new pairing. */
63
- declare function connectBwalletX(opts?: Pick<SignInOptions, 'wallet' | 'pairing' | 'reusePairing' | 'discoverMs'>): Promise<{
115
+ declare function connectBwalletX(opts?: Pick<SignInOptions, 'wallet' | 'pairing' | 'reusePairing' | 'discoverMs' | 'onStatus'>): Promise<{
64
116
  wallet: WalletInterface;
65
117
  method: SignInMethod;
66
118
  }>;
67
119
  /**
68
- * Sign the server's challenge with the user's bWalletX identity key. Post the result's
69
- * identityKey, nonce and signature to your verify route.
120
+ * Wait for the user to unlock only when the wallet says it is locked. isAuthenticated never shows anything; an
121
+ * unconditional waitForAuthentication is not free: bWalletX answers it by fetching the site's manifest.json and, when
122
+ * that asks for permissions, shows a separate sheet, once per call.
123
+ */
124
+ declare function waitIfLocked(wallet: WalletInterface): Promise<void>;
125
+ /**
126
+ * True when a server refused a challenge because it wanted an identity key (createChallenge before 0.5.5 answers 400
127
+ * "identityKey must be a compressed public key (66 hex chars)").
128
+ */
129
+ declare function challengeWantsIdentityKey(e: unknown): boolean;
130
+ /**
131
+ * Sign the server's challenge with the user's bWalletX identity key. Post the result's identityKey, nonce and
132
+ * signature to your verify route.
133
+ *
134
+ * Wallet calls, in order:
135
+ * 1. the challenge comes from your server first (no wallet call);
136
+ * 2. getPublicKey({ identityKey: true }) and createSignature go to the wallet TOGETHER, so the wallet merges them
137
+ * into one approval. With `identityKey` (already connected) only createSignature is asked for.
70
138
  */
71
139
  declare function signInWithBwalletX(opts: SignInOptions): Promise<SignInResult>;
140
+ interface SignInAndVerifyOptions extends SignInOptions {
141
+ /** POST the result to your verify route; resolve with its JSON. A 401 (status on the error) means "sign-in failed". */
142
+ verify: (r: SignInResult) => Promise<Record<string, unknown>>;
143
+ /**
144
+ * A remembered identity key (rememberedIdentity()). Used like `identityKey` (one wallet call: the signature only),
145
+ * but if the server rejects the signature (another account is active now), it is dropped and the sign-in is retried
146
+ * with the key asked for.
147
+ */
148
+ identityKeyHint?: string;
149
+ }
150
+ /** signInWithBwalletX + your verify route, with the identity-hint fallback. */
151
+ declare function signInAndVerify(opts: SignInAndVerifyOptions): Promise<{
152
+ result: SignInResult;
153
+ verified: Record<string, unknown>;
154
+ }>;
72
155
  /** Where a sign-in failed: the wallet's identity prompt, the site's challenge endpoint, or the wallet's signature. */
73
156
  type SignInStage = 'identity' | 'challenge' | 'signature' | 'verify';
74
157
 
@@ -91,6 +174,38 @@ declare function renderButton(el: HTMLElement | string, opts?: ButtonOptions): H
91
174
  */
92
175
  declare function inOrder<T>(handle: (frame: T) => Promise<void> | void, onError?: (e: unknown) => void): (frame: T) => Promise<void>;
93
176
 
177
+ /**
178
+ * The signed-in account as the badge shows it: paymail (best-effort lookup by identity key), a $handle label, a short
179
+ * key when there is no paymail, and the bAvatar picture (gold by default, generated for any key).
180
+ */
181
+ declare const PAYMAIL_LOOKUP_URL = "https://pay.bwallet.space/api/paymail/lookup?key=";
182
+ declare const BAVATAR_URL = "https://chat.bwalletx.com/api/bavatar/";
183
+ /** 0266c1…7c83 */
184
+ declare function shortKey(key: string): string;
185
+ /** $alice for alice@bwalletx.com, a site handle as given, other paymails in full, else a short key. */
186
+ declare function accountLabel(a: {
187
+ identityKey?: string | null;
188
+ paymail?: string | null;
189
+ handle?: string | null;
190
+ }): string;
191
+ /** The bAvatar for an identity key (a generated gold avatar when the user has not set one). */
192
+ declare function avatarUrlFor(identityKey: string | null | undefined): string | null;
193
+ /** The paymail for an identity key, or null. Best effort: never throws, one request per key per page. */
194
+ declare function lookupPaymail(identityKey: string, url?: string): Promise<string | null>;
195
+ /** True when the user said no in the wallet (BRC-100 denial, or a picker / sheet closed). */
196
+ declare function isUserRejection(e: unknown): boolean;
197
+ /** One plain line for an error: "Sign-in cancelled" for a no in the wallet, otherwise the gist. */
198
+ declare function signInErrorText(e: unknown): string;
199
+ /** localStorage key for the identity key that last signed in on this site (public data; a hint, never trusted). */
200
+ declare const IDENTITY_HINT_KEY = "bwx:identityKey";
201
+ /**
202
+ * The identity key that last signed in on this site, if any. Passing it to signInWithBwalletX makes a repeat sign-in
203
+ * ONE wallet call (createSignature only). It is only a hint: the server still checks the signature against it, and a
204
+ * wrong hint (another account) fails verification and is retried with the key asked for.
205
+ */
206
+ declare function rememberedIdentity(): string | undefined;
207
+ declare function rememberIdentity(key: string | null): void;
208
+
94
209
  /** An SVG QR code for `text` (error correction M). */
95
210
  declare function qrSvg(text: string): string;
96
211
  /**
@@ -125,6 +240,24 @@ declare function pairingModal(o?: PairingModalOptions): PairingOptions & {
125
240
  declare function pickWallet(options: WalletOption[], o?: {
126
241
  title?: string;
127
242
  }): Promise<WalletOption | null>;
243
+ interface ChooseWalletOptions {
244
+ /** Default "Choose a wallet". */
245
+ title?: string;
246
+ /** Where "Get bWalletX" points. Default https://bwalletx.com/get */
247
+ getUrl?: string;
248
+ /**
249
+ * Offer "Desktop wallet" (Metanet / BSV Desktop on localhost). Default true. It probes localhost only when tapped
250
+ * (desktopOption), never while the chooser opens.
251
+ */
252
+ desktop?: boolean;
253
+ }
254
+ /**
255
+ * The wallet chooser (0.5.6). Without bWalletX in this browser, "Get bWalletX" comes first; then bWalletX on the
256
+ * phone, the other wallets that were detected, "Desktop wallet" (probes localhost only when tapped) and app-supplied
257
+ * options. Opened from "Other wallets" while bWalletX is here, bWalletX is the first, gold row.
258
+ * Resolves with the chosen option, or null when closed. "Get bWalletX" is a link and leaves the chooser open.
259
+ */
260
+ declare function chooseWallet(options: readonly WalletOption[], o?: ChooseWalletOptions): Promise<WalletOption | null>;
128
261
 
129
262
  /**
130
263
  * Browser side of the access protocol: ask the wallet to sign the site's challenge and prove the
@@ -177,4 +310,44 @@ declare const WALLET_THEME_META = "bwalletx-theme";
177
310
  /** Declare (or with null, withdraw) the theme the wallet should wear for this page. No-op outside a browser. */
178
311
  declare function declareWalletTheme(theme: string | null | undefined): void;
179
312
 
180
- export { type AccessChallengeLike, AccessError, AccessResponse, BWALLETX_RDNS, type ButtonOptions, type Challenge, type FoundBy, type FoundWallet, HoldingProof, LOGIN_PROTOCOL, LOGO_URL, type PairingModalOptions, PairingOptions, RDNS_EXTENSION, RDNS_MOBILE, type RequestAccessOptions, type RequestAccessResult, type SignInMethod, type SignInOptions, type SignInResult, type SignInStage, WALLET_THEME_META, WalletOption, connectBwalletX, declareWalletTheme, discoverBwalletX, findBwalletX, inOrder, isTouchDevice, pairingModal, pickWallet, proveHoldings, qrSvg, renderButton, requestAccess, signInWithBwalletX, throwIfAccessError, toAccessError };
313
+ interface ConnectFlowOptions {
314
+ /** The wallets found (discoverWallets). */
315
+ list: WalletOption[];
316
+ /** Connect this option without asking. */
317
+ walletId?: string;
318
+ /** false: never show the chooser (bWalletX, else the phone; never another wallet unasked). Default true. */
319
+ picker?: boolean;
320
+ /** "Other wallets": show the chooser even when bWalletX is here. */
321
+ chooser?: boolean;
322
+ /**
323
+ * bWalletX first (0.5.6, default true): bWalletX in this browser is connected with no chooser; without it the
324
+ * chooser opens ("Get bWalletX" first) and no other wallet is connected unless picked. false: the 0.5.5 rule.
325
+ */
326
+ fastPath?: boolean;
327
+ /** Show the chooser; resolves null when closed. chooseWallet (modal.ts) or your own UI. */
328
+ pick: (list: WalletOption[]) => Promise<WalletOption | null>;
329
+ /** With verifyUrl: sign in after connecting. */
330
+ challengeUrl?: string;
331
+ verifyUrl?: string;
332
+ challengeNeedsIdentityKey?: boolean;
333
+ /** POST JSON; throws with `status` on a non-2xx answer. */
334
+ post: (url: string, body: unknown) => Promise<Record<string, unknown>>;
335
+ /** Called once per attempt with { walletType, substrate, outcome, ms }. No keys, addresses or identity data. */
336
+ onAttempt?: AttemptHook;
337
+ }
338
+ interface ConnectFlowResult {
339
+ connected: ConnectedWallet;
340
+ identityKey: string | null;
341
+ handle: string | null;
342
+ paymail: string | null;
343
+ signedIn: boolean;
344
+ /** 'bwalletx' for bWalletX, else the wallet's rdns / option id. */
345
+ walletType: string;
346
+ substrate: Substrate;
347
+ /** Why this wallet: 'bwalletx' (fast path), 'chooser' (picked), 'requested' (walletId), … */
348
+ reason: ChoiceReason;
349
+ }
350
+ /** Resolves null when the user closed the chooser. Throws NOT_FOUND when there is nothing to connect. */
351
+ declare function runConnect(o: ConnectFlowOptions): Promise<ConnectFlowResult | null>;
352
+
353
+ export { type AccessChallengeLike, AccessError, AccessResponse, AttemptHook, BAVATAR_URL, BWALLETX_RDNS, type ButtonOptions, type Challenge, ChoiceReason, type ChooseWalletOptions, type ConnectFlowOptions, type ConnectFlowResult, ConnectedWallet, DEFAULT_DISCOVER_MS, type FoundBy, type FoundWallet, HoldingProof, IDENTITY_HINT_KEY, LOGIN_PROTOCOL, LOGO_URL, PAYMAIL_LOOKUP_URL, type PairingModalOptions, PairingOptions, RDNS_EXTENSION, RDNS_MOBILE, type RequestAccessOptions, type RequestAccessResult, type SignInAndVerifyOptions, type SignInMethod, type SignInOptions, type SignInResult, type SignInStage, type SignInStatus, Substrate, WALLET_THEME_META, WalletOption, accountLabel, avatarUrlFor, bindPrewarm, challengeWantsIdentityKey, chooseWallet, connectBwalletX, declareWalletTheme, discoverBwalletX, findBwalletX, inOrder, isFramed, isTouchDevice, isUserRejection, lookupPaymail, pairingModal, pickWallet, prewarmBwalletX, proveHoldings, qrSvg, rememberIdentity, rememberedIdentity, renderButton, requestAccess, runConnect, shortKey, signInAndVerify, signInErrorText, signInWithBwalletX, throwIfAccessError, toAccessError, waitIfLocked };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { WalletInterface, WalletProtocol } from '@bsv/sdk';
2
- import { f as PairingOptions, W as WalletOption } from './wallets-VOKIKBbO.js';
3
- export { g as BRC29_PROTOCOL, i as Brc29Remittance, B as BuyTokenRequest, C as ConnectedWallet, D as DiscoverWalletsOptions, H as HandCashAdapterOptions, L as LegacyPayer, j as PairConnectionOptions, k as PairStorage, l as PairedWallet, b as PayOptions, m as PayOutput, P as PayRequest, a as PayResult, n as PaySource, c as PaymentError, o as PaymentErrorCode, S as SocketFactory, q as SocketLike, T as TokenQuote, r as WalletKind, s as amountInSats, d as brc100Option, t as buyToken, u as clearPairing, e as discoverWallets, h as handcashAdapter, v as isIdentityKeyHex, w as isPaymail, x as pairBwalletX, p as pairingOption, y as pay, z as resolvePaymailP2P, A as restorePairing, E as tip } from './wallets-VOKIKBbO.js';
4
- export { AuthorizeParams, GET_URL, SIGNIN_CSS, SIGNIN_TAG, SigninBrand, SigninLabel, SigninSize, SigninTheme, WEB_WALLET_URL, buildAuthorizeUrl, defineBwalletxSignin, markSvg, signinText } from './element.js';
2
+ import { g as PairingOptions, W as WalletOption, A as AttemptHook, C as ConnectedWallet, S as Substrate, i as ChoiceReason } from './choice-DCh-tgpT.js';
3
+ export { j as AttemptOutcome, k as BRC29_PROTOCOL, l as BWALLETX_TYPE, m as Brc29Remittance, B as BuyTokenRequest, n as ConnectAttempt, o as ConnectOptions, D as DESKTOP_OPTION_ID, q as DecideWalletOptions, r as DiscoverWalletsOptions, H as HandCashAdapterOptions, L as LegacyPayer, s as PairConnectionOptions, t as PairStorage, u as PairedWallet, b as PayOptions, v as PayOutput, P as PayRequest, a as PayResult, w as PaySource, c as PaymentError, x as PaymentErrorCode, y as SocketFactory, z as SocketLike, T as TokenQuote, E as WalletChoice, F as WalletKind, G as amountInSats, I as attemptFor, d as autoChoice, e as brc100Option, J as buyToken, K as chooserOrder, M as clearPairing, N as cwiIsAnnounced, O as decideWallet, Q as desktopOption, f as discoverWallets, h as handcashAdapter, R as hasBwalletX, U as isIdentityKeyHex, V as isPaymail, X as isPresentBwalletX, Y as otherDetected, Z as outcomeOf, _ as pairBwalletX, p as pairingOption, $ as pay, a0 as reportAttempt, a1 as resolvePaymailP2P, a2 as restorePairing, a3 as substrateOf, a4 as tip, a5 as walletTypeOf } from './choice-DCh-tgpT.js';
4
+ export { A as AuthorizeParams, G as GET_URL, M as MENU_CSS, P as PENDING_LABEL, e as PENDING_LABEL_OTHER, f as PENDING_NOTE, g as SIGNIN_CSS, h as SIGNIN_TAG, i as SigninAccount, c as SigninBrand, b as SigninLabel, j as SigninMode, S as SigninSize, d as SigninState, a as SigninTheme, W as WEB_WALLET_URL, k as buildAuthorizeUrl, l as defineBwalletxSignin, m as markSvg, s as signinText } from './element-D9Zl-x12.js';
5
+ export { BUTTON_TAG, ButtonState, CONNECTED_KEY, defineBwalletxButton, dropLegacyConnectedKey, getUrlFor, handleLabel, stateFor } from './element.js';
5
6
  import { b as AccessResponse, H as HoldingProof, A as AccessError } from './access-Dp0eKIOc.js';
6
7
  export { f as ACCESS_ERROR_STATUS, d as ACCESS_PROTOCOL, g as ACCESS_VERSION, h as AccessChallenge, i as AccessErrorBody, j as AccessErrorCode, c as AccessKind, a as AccessRequirement, P as PROTOCOL_MEDIA, T as TokenRequirement, k as accessErrorMessage, m as canonicalJson, r as protocolMediaUrl } from './access-Dp0eKIOc.js';
7
8
 
@@ -16,10 +17,22 @@ interface FoundWallet {
16
17
  method: FoundBy;
17
18
  rdns: string | null;
18
19
  }
20
+ /**
21
+ * Default wait for a wallet that has not answered yet, ms. bWalletX for Chrome and the in-app browser both answer
22
+ * `brc100:requestWallet` synchronously, so a found wallet resolves at once;
23
+ * this is only how long "nothing here" takes before the pairing QR shows. Was 1200 (0.5.3 and earlier).
24
+ */
25
+ declare const DEFAULT_DISCOVER_MS = 300;
19
26
  /**
20
27
  * Like findBwalletX, but also says which bWalletX answered.
21
- * Order: a BRC-100 announcement with a bWalletX rdns; then `window.CWI` (set by the in-app
22
- * browser, and by older builds that do not announce); otherwise null.
28
+ *
29
+ * bWalletX is recognised ONLY by its own markers: a BRC-100 announcement carrying a bWalletX rdns
30
+ * (`com.bwalletx.extension` from the Chrome extension, `space.bwallet.mobile` from the in-app browser; both answer
31
+ * `brc100:requestWallet` at once), or, only when framed, the XDM answer of a parent on BWALLETX_PARENT_ORIGINS.
32
+ *
33
+ * Never by `window.CWI` (0.5.6): another wallet (Metanet / BSV Desktop, Yours) can set or overwrite it, and treating
34
+ * whoever holds it as bWalletX handed our sign-in to that wallet. Every bWalletX build since 3 Oct 2026 announces.
35
+ * Resolves null after `ms` when no bWalletX announced (other wallets: discoverWallets).
23
36
  */
24
37
  declare function discoverBwalletX(ms?: number): Promise<FoundWallet | null>;
25
38
  /**
@@ -27,6 +40,17 @@ declare function discoverBwalletX(ms?: number): Promise<FoundWallet | null>;
27
40
  * open in bWalletX's in-app browser. Resolves null if nothing answered within `ms`.
28
41
  */
29
42
  declare function findBwalletX(ms?: number): Promise<WalletInterface | null>;
43
+ /** True inside a frame (or when the parent can't be read). */
44
+ declare const isFramed: () => boolean;
45
+ /**
46
+ * Wake the wallet before the click (call on pointerenter / focus / touchstart of your Connect button). Chrome stops an
47
+ * idle extension worker after ~30 s, and a cold worker needs 1-3 s to reopen the wallet; this sends a liveness call
48
+ * (isAuthenticated: never shows a prompt, never reveals a key) so that work starts while the pointer is on its way.
49
+ * At most once every 20 s. Does nothing when no bWalletX is in the page.
50
+ */
51
+ declare function prewarmBwalletX(): void;
52
+ /** Prewarm on hover, keyboard focus and touch. Returns a function that removes the listeners. */
53
+ declare function bindPrewarm(el: EventTarget): () => void;
30
54
 
31
55
  /** Security level 2, a protocol name used for nothing else. */
32
56
  declare const LOGIN_PROTOCOL: WalletProtocol;
@@ -38,17 +62,45 @@ interface Challenge {
38
62
  protocolID?: WalletProtocol;
39
63
  }
40
64
  type SignInMethod = 'extension' | 'in-app' | 'pairing' | 'wallet';
65
+ /**
66
+ * Progress for the button label. 'finding': looking for a wallet (sub-second); 'opening': a wallet was found and its
67
+ * approval is on the way ("Opening your wallet…"); 'pairing': no wallet in this browser, the QR is showing;
68
+ * 'signing': the challenge arrived, the wallet's sign-in approval is being asked for.
69
+ */
70
+ type SignInStatus = 'finding' | 'opening' | 'pairing' | 'signing';
41
71
  interface SignInOptions {
42
- /** Ask your server for a challenge for this identity key. */
43
- challenge: (identityKey: string) => Promise<Challenge>;
72
+ /**
73
+ * Ask your server for a challenge. Since 0.5.5 it is called BEFORE the wallet is asked anything, and gets an identity
74
+ * key only when you pass `identityKey` (an identity you already connected) or set `challengeNeedsIdentityKey`;
75
+ * otherwise undefined. The 0.5.5 server helpers (createChallenge) accept no key, and verifySignIn binds the key the
76
+ * browser then claims to the signature. A pre-0.5.5 server that refuses a keyless challenge is detected and retried
77
+ * in the old order automatically.
78
+ */
79
+ challenge(identityKey?: string): Promise<Challenge>;
80
+ /**
81
+ * The identity key you already have from an earlier connect (reuse the connected identity): the wallet is then asked
82
+ * for the signature only. Without it, getPublicKey({ identityKey: true }) and createSignature go to the wallet
83
+ * together (Promise.all), so the wallet shows ONE sheet, not three.
84
+ */
85
+ identityKey?: string;
86
+ /**
87
+ * Servers older than 0.5.5 refuse a challenge without an identity key. Set true to use the old order straight away
88
+ * (identity key, then the challenge, then the signature: two wallet calls). Without it, the old order is used only
89
+ * after such a server has refused a keyless challenge.
90
+ */
91
+ challengeNeedsIdentityKey?: boolean;
92
+ /** Skip waitForAuthentication before signing (the provider already waited). Default false. */
93
+ skipWaitForAuthentication?: boolean;
44
94
  /** Use this wallet instead of looking for one. `method` is then 'wallet'. */
45
95
  wallet?: WalletInterface;
46
96
  /** How to show the QR and code if pairing is needed. Without it, pairing is not tried. */
47
97
  pairing?: PairingOptions;
48
98
  /** Reuse a pairing stored by an earlier sign-in before showing a new QR. Default true. */
49
99
  reusePairing?: boolean;
50
- /** How long to wait for the extension or in-app browser to answer, in ms. Default 1200. */
100
+ /** How long to wait for a wallet that has not answered, in ms, before pairing. Default 300 (a present wallet answers at once). */
51
101
  discoverMs?: number;
102
+ /** Called as the sign-in moves on, so the button can say "Opening your wallet…" straight away. */
103
+ onStatus?: (status: SignInStatus) => void;
52
104
  }
53
105
  interface SignInResult {
54
106
  identityKey: string;
@@ -60,15 +112,46 @@ interface SignInResult {
60
112
  wallet: WalletInterface;
61
113
  }
62
114
  /** Find a wallet: extension or in-app browser first, then a stored pairing, then a new pairing. */
63
- declare function connectBwalletX(opts?: Pick<SignInOptions, 'wallet' | 'pairing' | 'reusePairing' | 'discoverMs'>): Promise<{
115
+ declare function connectBwalletX(opts?: Pick<SignInOptions, 'wallet' | 'pairing' | 'reusePairing' | 'discoverMs' | 'onStatus'>): Promise<{
64
116
  wallet: WalletInterface;
65
117
  method: SignInMethod;
66
118
  }>;
67
119
  /**
68
- * Sign the server's challenge with the user's bWalletX identity key. Post the result's
69
- * identityKey, nonce and signature to your verify route.
120
+ * Wait for the user to unlock only when the wallet says it is locked. isAuthenticated never shows anything; an
121
+ * unconditional waitForAuthentication is not free: bWalletX answers it by fetching the site's manifest.json and, when
122
+ * that asks for permissions, shows a separate sheet, once per call.
123
+ */
124
+ declare function waitIfLocked(wallet: WalletInterface): Promise<void>;
125
+ /**
126
+ * True when a server refused a challenge because it wanted an identity key (createChallenge before 0.5.5 answers 400
127
+ * "identityKey must be a compressed public key (66 hex chars)").
128
+ */
129
+ declare function challengeWantsIdentityKey(e: unknown): boolean;
130
+ /**
131
+ * Sign the server's challenge with the user's bWalletX identity key. Post the result's identityKey, nonce and
132
+ * signature to your verify route.
133
+ *
134
+ * Wallet calls, in order:
135
+ * 1. the challenge comes from your server first (no wallet call);
136
+ * 2. getPublicKey({ identityKey: true }) and createSignature go to the wallet TOGETHER, so the wallet merges them
137
+ * into one approval. With `identityKey` (already connected) only createSignature is asked for.
70
138
  */
71
139
  declare function signInWithBwalletX(opts: SignInOptions): Promise<SignInResult>;
140
+ interface SignInAndVerifyOptions extends SignInOptions {
141
+ /** POST the result to your verify route; resolve with its JSON. A 401 (status on the error) means "sign-in failed". */
142
+ verify: (r: SignInResult) => Promise<Record<string, unknown>>;
143
+ /**
144
+ * A remembered identity key (rememberedIdentity()). Used like `identityKey` (one wallet call: the signature only),
145
+ * but if the server rejects the signature (another account is active now), it is dropped and the sign-in is retried
146
+ * with the key asked for.
147
+ */
148
+ identityKeyHint?: string;
149
+ }
150
+ /** signInWithBwalletX + your verify route, with the identity-hint fallback. */
151
+ declare function signInAndVerify(opts: SignInAndVerifyOptions): Promise<{
152
+ result: SignInResult;
153
+ verified: Record<string, unknown>;
154
+ }>;
72
155
  /** Where a sign-in failed: the wallet's identity prompt, the site's challenge endpoint, or the wallet's signature. */
73
156
  type SignInStage = 'identity' | 'challenge' | 'signature' | 'verify';
74
157
 
@@ -91,6 +174,38 @@ declare function renderButton(el: HTMLElement | string, opts?: ButtonOptions): H
91
174
  */
92
175
  declare function inOrder<T>(handle: (frame: T) => Promise<void> | void, onError?: (e: unknown) => void): (frame: T) => Promise<void>;
93
176
 
177
+ /**
178
+ * The signed-in account as the badge shows it: paymail (best-effort lookup by identity key), a $handle label, a short
179
+ * key when there is no paymail, and the bAvatar picture (gold by default, generated for any key).
180
+ */
181
+ declare const PAYMAIL_LOOKUP_URL = "https://pay.bwallet.space/api/paymail/lookup?key=";
182
+ declare const BAVATAR_URL = "https://chat.bwalletx.com/api/bavatar/";
183
+ /** 0266c1…7c83 */
184
+ declare function shortKey(key: string): string;
185
+ /** $alice for alice@bwalletx.com, a site handle as given, other paymails in full, else a short key. */
186
+ declare function accountLabel(a: {
187
+ identityKey?: string | null;
188
+ paymail?: string | null;
189
+ handle?: string | null;
190
+ }): string;
191
+ /** The bAvatar for an identity key (a generated gold avatar when the user has not set one). */
192
+ declare function avatarUrlFor(identityKey: string | null | undefined): string | null;
193
+ /** The paymail for an identity key, or null. Best effort: never throws, one request per key per page. */
194
+ declare function lookupPaymail(identityKey: string, url?: string): Promise<string | null>;
195
+ /** True when the user said no in the wallet (BRC-100 denial, or a picker / sheet closed). */
196
+ declare function isUserRejection(e: unknown): boolean;
197
+ /** One plain line for an error: "Sign-in cancelled" for a no in the wallet, otherwise the gist. */
198
+ declare function signInErrorText(e: unknown): string;
199
+ /** localStorage key for the identity key that last signed in on this site (public data; a hint, never trusted). */
200
+ declare const IDENTITY_HINT_KEY = "bwx:identityKey";
201
+ /**
202
+ * The identity key that last signed in on this site, if any. Passing it to signInWithBwalletX makes a repeat sign-in
203
+ * ONE wallet call (createSignature only). It is only a hint: the server still checks the signature against it, and a
204
+ * wrong hint (another account) fails verification and is retried with the key asked for.
205
+ */
206
+ declare function rememberedIdentity(): string | undefined;
207
+ declare function rememberIdentity(key: string | null): void;
208
+
94
209
  /** An SVG QR code for `text` (error correction M). */
95
210
  declare function qrSvg(text: string): string;
96
211
  /**
@@ -125,6 +240,24 @@ declare function pairingModal(o?: PairingModalOptions): PairingOptions & {
125
240
  declare function pickWallet(options: WalletOption[], o?: {
126
241
  title?: string;
127
242
  }): Promise<WalletOption | null>;
243
+ interface ChooseWalletOptions {
244
+ /** Default "Choose a wallet". */
245
+ title?: string;
246
+ /** Where "Get bWalletX" points. Default https://bwalletx.com/get */
247
+ getUrl?: string;
248
+ /**
249
+ * Offer "Desktop wallet" (Metanet / BSV Desktop on localhost). Default true. It probes localhost only when tapped
250
+ * (desktopOption), never while the chooser opens.
251
+ */
252
+ desktop?: boolean;
253
+ }
254
+ /**
255
+ * The wallet chooser (0.5.6). Without bWalletX in this browser, "Get bWalletX" comes first; then bWalletX on the
256
+ * phone, the other wallets that were detected, "Desktop wallet" (probes localhost only when tapped) and app-supplied
257
+ * options. Opened from "Other wallets" while bWalletX is here, bWalletX is the first, gold row.
258
+ * Resolves with the chosen option, or null when closed. "Get bWalletX" is a link and leaves the chooser open.
259
+ */
260
+ declare function chooseWallet(options: readonly WalletOption[], o?: ChooseWalletOptions): Promise<WalletOption | null>;
128
261
 
129
262
  /**
130
263
  * Browser side of the access protocol: ask the wallet to sign the site's challenge and prove the
@@ -177,4 +310,44 @@ declare const WALLET_THEME_META = "bwalletx-theme";
177
310
  /** Declare (or with null, withdraw) the theme the wallet should wear for this page. No-op outside a browser. */
178
311
  declare function declareWalletTheme(theme: string | null | undefined): void;
179
312
 
180
- export { type AccessChallengeLike, AccessError, AccessResponse, BWALLETX_RDNS, type ButtonOptions, type Challenge, type FoundBy, type FoundWallet, HoldingProof, LOGIN_PROTOCOL, LOGO_URL, type PairingModalOptions, PairingOptions, RDNS_EXTENSION, RDNS_MOBILE, type RequestAccessOptions, type RequestAccessResult, type SignInMethod, type SignInOptions, type SignInResult, type SignInStage, WALLET_THEME_META, WalletOption, connectBwalletX, declareWalletTheme, discoverBwalletX, findBwalletX, inOrder, isTouchDevice, pairingModal, pickWallet, proveHoldings, qrSvg, renderButton, requestAccess, signInWithBwalletX, throwIfAccessError, toAccessError };
313
+ interface ConnectFlowOptions {
314
+ /** The wallets found (discoverWallets). */
315
+ list: WalletOption[];
316
+ /** Connect this option without asking. */
317
+ walletId?: string;
318
+ /** false: never show the chooser (bWalletX, else the phone; never another wallet unasked). Default true. */
319
+ picker?: boolean;
320
+ /** "Other wallets": show the chooser even when bWalletX is here. */
321
+ chooser?: boolean;
322
+ /**
323
+ * bWalletX first (0.5.6, default true): bWalletX in this browser is connected with no chooser; without it the
324
+ * chooser opens ("Get bWalletX" first) and no other wallet is connected unless picked. false: the 0.5.5 rule.
325
+ */
326
+ fastPath?: boolean;
327
+ /** Show the chooser; resolves null when closed. chooseWallet (modal.ts) or your own UI. */
328
+ pick: (list: WalletOption[]) => Promise<WalletOption | null>;
329
+ /** With verifyUrl: sign in after connecting. */
330
+ challengeUrl?: string;
331
+ verifyUrl?: string;
332
+ challengeNeedsIdentityKey?: boolean;
333
+ /** POST JSON; throws with `status` on a non-2xx answer. */
334
+ post: (url: string, body: unknown) => Promise<Record<string, unknown>>;
335
+ /** Called once per attempt with { walletType, substrate, outcome, ms }. No keys, addresses or identity data. */
336
+ onAttempt?: AttemptHook;
337
+ }
338
+ interface ConnectFlowResult {
339
+ connected: ConnectedWallet;
340
+ identityKey: string | null;
341
+ handle: string | null;
342
+ paymail: string | null;
343
+ signedIn: boolean;
344
+ /** 'bwalletx' for bWalletX, else the wallet's rdns / option id. */
345
+ walletType: string;
346
+ substrate: Substrate;
347
+ /** Why this wallet: 'bwalletx' (fast path), 'chooser' (picked), 'requested' (walletId), … */
348
+ reason: ChoiceReason;
349
+ }
350
+ /** Resolves null when the user closed the chooser. Throws NOT_FOUND when there is nothing to connect. */
351
+ declare function runConnect(o: ConnectFlowOptions): Promise<ConnectFlowResult | null>;
352
+
353
+ export { type AccessChallengeLike, AccessError, AccessResponse, AttemptHook, BAVATAR_URL, BWALLETX_RDNS, type ButtonOptions, type Challenge, ChoiceReason, type ChooseWalletOptions, type ConnectFlowOptions, type ConnectFlowResult, ConnectedWallet, DEFAULT_DISCOVER_MS, type FoundBy, type FoundWallet, HoldingProof, IDENTITY_HINT_KEY, LOGIN_PROTOCOL, LOGO_URL, PAYMAIL_LOOKUP_URL, type PairingModalOptions, PairingOptions, RDNS_EXTENSION, RDNS_MOBILE, type RequestAccessOptions, type RequestAccessResult, type SignInAndVerifyOptions, type SignInMethod, type SignInOptions, type SignInResult, type SignInStage, type SignInStatus, Substrate, WALLET_THEME_META, WalletOption, accountLabel, avatarUrlFor, bindPrewarm, challengeWantsIdentityKey, chooseWallet, connectBwalletX, declareWalletTheme, discoverBwalletX, findBwalletX, inOrder, isFramed, isTouchDevice, isUserRejection, lookupPaymail, pairingModal, pickWallet, prewarmBwalletX, proveHoldings, qrSvg, rememberIdentity, rememberedIdentity, renderButton, requestAccess, runConnect, shortKey, signInAndVerify, signInErrorText, signInWithBwalletX, throwIfAccessError, toAccessError, waitIfLocked };