@bwalletx/connect 0.5.3 → 0.5.4
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 +7 -0
- package/README.md +4 -0
- package/dist/bwalletx-connect.global.js +8 -8
- package/dist/bwalletx-connect.global.js.map +1 -1
- package/dist/{chunk-IUDD7YTQ.js → chunk-EXRQJTXF.js} +91 -20
- package/dist/chunk-EXRQJTXF.js.map +1 -0
- package/dist/{chunk-PI42H3XY.js → chunk-RIOHG5JH.js} +4 -4
- package/dist/chunk-RIOHG5JH.js.map +1 -0
- package/dist/element.cjs +86 -18
- package/dist/element.cjs.map +1 -1
- package/dist/element.js +1 -1
- package/dist/index.cjs +97 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -7
- package/dist/index.d.ts +31 -7
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +90 -22
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/shell-react.cjs.map +1 -1
- package/dist/shell-react.js.map +1 -1
- package/dist/{wallets-VOKIKBbO.d.cts → wallets-CbzMtxrf.d.cts} +1 -1
- package/dist/{wallets-VOKIKBbO.d.ts → wallets-CbzMtxrf.d.ts} +1 -1
- package/package.json +9 -10
- package/dist/chunk-IUDD7YTQ.js.map +0 -1
- package/dist/chunk-PI42H3XY.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ __export(src_exports, {
|
|
|
36
36
|
AccessError: () => AccessError,
|
|
37
37
|
BRC29_PROTOCOL: () => BRC29_PROTOCOL,
|
|
38
38
|
BWALLETX_RDNS: () => BWALLETX_RDNS,
|
|
39
|
+
DEFAULT_DISCOVER_MS: () => DEFAULT_DISCOVER_MS,
|
|
39
40
|
GET_URL: () => GET_URL,
|
|
40
41
|
LOGIN_PROTOCOL: () => LOGIN_PROTOCOL,
|
|
41
42
|
LOGO_URL: () => LOGO_URL,
|
|
@@ -49,6 +50,7 @@ __export(src_exports, {
|
|
|
49
50
|
WEB_WALLET_URL: () => WEB_WALLET_URL,
|
|
50
51
|
accessErrorMessage: () => accessErrorMessage,
|
|
51
52
|
amountInSats: () => amountInSats,
|
|
53
|
+
bindPrewarm: () => bindPrewarm,
|
|
52
54
|
brc100Option: () => brc100Option,
|
|
53
55
|
buildAuthorizeUrl: () => buildAuthorizeUrl,
|
|
54
56
|
buyToken: () => buyToken,
|
|
@@ -71,6 +73,7 @@ __export(src_exports, {
|
|
|
71
73
|
pairingOption: () => pairingOption,
|
|
72
74
|
pay: () => pay,
|
|
73
75
|
pickWallet: () => pickWallet,
|
|
76
|
+
prewarmBwalletX: () => prewarmBwalletX,
|
|
74
77
|
protocolMediaUrl: () => protocolMediaUrl,
|
|
75
78
|
proveHoldings: () => proveHoldings,
|
|
76
79
|
qrSvg: () => qrSvg,
|
|
@@ -91,13 +94,16 @@ var import_sdk = require("@bsv/sdk");
|
|
|
91
94
|
var RDNS_EXTENSION = "com.bwalletx.extension";
|
|
92
95
|
var RDNS_MOBILE = "space.bwallet.mobile";
|
|
93
96
|
var BWALLETX_RDNS = [RDNS_EXTENSION, RDNS_MOBILE];
|
|
94
|
-
|
|
97
|
+
var DEFAULT_DISCOVER_MS = 300;
|
|
98
|
+
function discoverBwalletX(ms = DEFAULT_DISCOVER_MS) {
|
|
95
99
|
if (typeof window === "undefined") return Promise.resolve(null);
|
|
96
100
|
return new Promise((resolve) => {
|
|
97
101
|
let done = false;
|
|
102
|
+
let timer;
|
|
98
103
|
const finish = (r) => {
|
|
99
104
|
if (done) return;
|
|
100
105
|
done = true;
|
|
106
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
101
107
|
window.removeEventListener("brc100:announceWallet", onAnnounce);
|
|
102
108
|
resolve(r);
|
|
103
109
|
};
|
|
@@ -108,17 +114,25 @@ function discoverBwalletX(ms = 1200) {
|
|
|
108
114
|
finish({ wallet: d.wallet, method: rdns === RDNS_EXTENSION ? "extension" : "in-app", rdns });
|
|
109
115
|
}
|
|
110
116
|
};
|
|
117
|
+
const cwiNow = () => {
|
|
118
|
+
const cwi = window.CWI;
|
|
119
|
+
if (cwi) finish({ wallet: cwi, method: "in-app", rdns: null });
|
|
120
|
+
return !!cwi;
|
|
121
|
+
};
|
|
111
122
|
window.addEventListener("brc100:announceWallet", onAnnounce);
|
|
112
123
|
window.dispatchEvent(new Event("brc100:requestWallet"));
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
124
|
+
if (done || cwiNow()) return;
|
|
125
|
+
if (isFramed()) {
|
|
126
|
+
void probeXdm(Math.max(ms, 1200)).then((w) => finish(w ? { wallet: w, method: "in-app", rdns: null } : null));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
timer = setTimeout(() => {
|
|
130
|
+
timer = void 0;
|
|
131
|
+
if (!cwiNow()) finish(null);
|
|
118
132
|
}, ms);
|
|
119
133
|
});
|
|
120
134
|
}
|
|
121
|
-
async function findBwalletX(ms =
|
|
135
|
+
async function findBwalletX(ms = DEFAULT_DISCOVER_MS) {
|
|
122
136
|
return (await discoverBwalletX(ms))?.wallet ?? null;
|
|
123
137
|
}
|
|
124
138
|
var isFramed = () => {
|
|
@@ -173,6 +187,21 @@ async function probeXdm(ms = 1200, allowed = BWALLETX_PARENT_ORIGINS) {
|
|
|
173
187
|
return null;
|
|
174
188
|
}
|
|
175
189
|
}
|
|
190
|
+
var warmedAt = 0;
|
|
191
|
+
function prewarmBwalletX() {
|
|
192
|
+
if (typeof window === "undefined" || Date.now() - warmedAt < 2e4) return;
|
|
193
|
+
warmedAt = Date.now();
|
|
194
|
+
void discoverBwalletX(0).then((f) => {
|
|
195
|
+
if (f && f.method === "extension") void f.wallet.isAuthenticated({}).catch(() => {
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function bindPrewarm(el2) {
|
|
200
|
+
const on = () => prewarmBwalletX();
|
|
201
|
+
const evs = ["pointerenter", "focus", "touchstart"];
|
|
202
|
+
for (const e of evs) el2.addEventListener(e, on, { passive: true });
|
|
203
|
+
return () => evs.forEach((e) => el2.removeEventListener(e, on));
|
|
204
|
+
}
|
|
176
205
|
|
|
177
206
|
// src/pair.ts
|
|
178
207
|
var import_sdk3 = require("@bsv/sdk");
|
|
@@ -213,10 +242,22 @@ function pairUrl(link) {
|
|
|
213
242
|
const q = new URLSearchParams({ v: link.v, r: link.r, c: link.c, k: link.k, o: link.o, e: String(link.e) });
|
|
214
243
|
return `https://${PAIR_HOST}/pair?${q}`;
|
|
215
244
|
}
|
|
216
|
-
var
|
|
245
|
+
var newClaim = () => b64url(crypto.getRandomValues(new Uint8Array(16)));
|
|
246
|
+
var WALLET_CLAIM_INFO = "bwallet-pair-wallet-claim-v1";
|
|
247
|
+
var hex = (b) => Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
248
|
+
async function walletClaimFor(channel, sitePub) {
|
|
249
|
+
const d = await crypto.subtle.digest("SHA-256", enc.encode(`${WALLET_CLAIM_INFO}|${channel}|${sitePub}`));
|
|
250
|
+
return b64url(new Uint8Array(d));
|
|
251
|
+
}
|
|
252
|
+
async function claimDigest(claim) {
|
|
253
|
+
return hex(new Uint8Array(await crypto.subtle.digest("SHA-256", enc.encode(claim))));
|
|
254
|
+
}
|
|
255
|
+
var relaySocketUrl = (relay, channel, role, expiry, claim, walletClaimHash) => {
|
|
217
256
|
const local = /^(localhost|127\.0\.0\.1)(:\d+)?$/.test(relay);
|
|
218
257
|
const q = new URLSearchParams({ role });
|
|
219
258
|
if (expiry) q.set("e", String(expiry));
|
|
259
|
+
if (claim) q.set("claim", claim);
|
|
260
|
+
if (walletClaimHash && role === "site") q.set("wc", walletClaimHash);
|
|
220
261
|
return `${local ? "ws" : "wss"}://${relay}/v1/c/${channel}?${q}`;
|
|
221
262
|
};
|
|
222
263
|
async function deriveSession(mine, theirs, channel) {
|
|
@@ -314,6 +355,7 @@ function parseStored(raw) {
|
|
|
314
355
|
if (typeof p.s !== "string" || !/^[0-9a-f]{64}$/i.test(p.s)) return null;
|
|
315
356
|
if (typeof p.k !== "string" || !/^0[23][0-9a-f]{64}$/i.test(p.k)) return null;
|
|
316
357
|
if (!n(p.sent) || !n(p.lastSeen) || !n(p.pairedAt)) return null;
|
|
358
|
+
if (p.sc !== void 0 && (typeof p.sc !== "string" || !/^[A-Za-z0-9_-]{22,64}$/.test(p.sc))) return null;
|
|
317
359
|
return p;
|
|
318
360
|
} catch {
|
|
319
361
|
return null;
|
|
@@ -371,7 +413,12 @@ var Link = class {
|
|
|
371
413
|
await this.opening;
|
|
372
414
|
}
|
|
373
415
|
reopen() {
|
|
374
|
-
|
|
416
|
+
if (!this.p.sc) {
|
|
417
|
+
this.p = { ...this.p, sc: newClaim() };
|
|
418
|
+
this.persist();
|
|
419
|
+
}
|
|
420
|
+
const e = Math.floor(Date.now() / 1e3) + QR_LIFETIME_S - 10;
|
|
421
|
+
const ws = this.socket(relaySocketUrl(this.p.r, this.p.c, "site", e, this.p.sc));
|
|
375
422
|
return new Promise((resolve, reject) => {
|
|
376
423
|
ws.onopen = () => {
|
|
377
424
|
this.ws = ws;
|
|
@@ -465,11 +512,13 @@ function pairBwalletX(opts) {
|
|
|
465
512
|
const siteKey = import_sdk3.PrivateKey.fromRandom();
|
|
466
513
|
const channel = newChannel();
|
|
467
514
|
const expiry = Math.floor(Date.now() / 1e3) + QR_LIFETIME_S;
|
|
468
|
-
|
|
515
|
+
const siteClaim = newClaim();
|
|
516
|
+
const sitePub = siteKey.toPublicKey().toString();
|
|
517
|
+
return walletClaimFor(channel, sitePub).then(claimDigest).then((wc) => new Promise((resolve, reject) => {
|
|
469
518
|
if (opts.signal?.aborted) return reject(new Error("cancelled"));
|
|
470
519
|
let ws;
|
|
471
520
|
try {
|
|
472
|
-
ws = socket(relaySocketUrl(relay, channel, "site", expiry));
|
|
521
|
+
ws = socket(relaySocketUrl(relay, channel, "site", expiry, siteClaim, wc));
|
|
473
522
|
} catch (e) {
|
|
474
523
|
return reject(e);
|
|
475
524
|
}
|
|
@@ -508,7 +557,7 @@ function pairBwalletX(opts) {
|
|
|
508
557
|
if (msg.t === "ready") {
|
|
509
558
|
settled = true;
|
|
510
559
|
clearTimeout(timer);
|
|
511
|
-
const p = { v: 1, c: channel, r: relay, s: siteKey.toHex(), k: walletKey, ...sealer.counters, pairedAt: Date.now() };
|
|
560
|
+
const p = { v: 1, c: channel, r: relay, s: siteKey.toHex(), k: walletKey, ...sealer.counters, pairedAt: Date.now(), sc: siteClaim };
|
|
512
561
|
await Promise.resolve(storage.setItem(key, JSON.stringify(p))).catch(() => {
|
|
513
562
|
});
|
|
514
563
|
const link = new Link(p, sealer, storage, key, socket, opts.callTimeoutMs ?? 12e4);
|
|
@@ -518,8 +567,8 @@ function pairBwalletX(opts) {
|
|
|
518
567
|
fail(new Error("Pairing was declined in bWalletX"));
|
|
519
568
|
}
|
|
520
569
|
});
|
|
521
|
-
opts.onLink(pairUrl({ v: PAIR_VERSION, r: relay, c: channel, k:
|
|
522
|
-
});
|
|
570
|
+
opts.onLink(pairUrl({ v: PAIR_VERSION, r: relay, c: channel, k: sitePub, o: origin, e: expiry }));
|
|
571
|
+
}));
|
|
523
572
|
}
|
|
524
573
|
async function restorePairing(opts = {}) {
|
|
525
574
|
const storage = opts.storage === void 0 ? defaultStorage() : opts.storage ?? memoryStorage();
|
|
@@ -540,16 +589,33 @@ async function clearPairing(opts = {}) {
|
|
|
540
589
|
// src/signin.ts
|
|
541
590
|
var LOGIN_PROTOCOL = [2, "bwallet sign in"];
|
|
542
591
|
async function connectBwalletX(opts = {}) {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
592
|
+
const status = (s) => {
|
|
593
|
+
try {
|
|
594
|
+
opts.onStatus?.(s);
|
|
595
|
+
} catch {
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
if (opts.wallet) {
|
|
599
|
+
status("opening");
|
|
600
|
+
return { wallet: opts.wallet, method: "wallet" };
|
|
601
|
+
}
|
|
602
|
+
status("finding");
|
|
603
|
+
const found = await discoverBwalletX(opts.discoverMs ?? DEFAULT_DISCOVER_MS);
|
|
604
|
+
if (found) {
|
|
605
|
+
status("opening");
|
|
606
|
+
return { wallet: found.wallet, method: found.method };
|
|
607
|
+
}
|
|
546
608
|
if (opts.reusePairing !== false) {
|
|
547
609
|
const restored = await restorePairing(opts.pairing ?? {});
|
|
548
|
-
if (restored)
|
|
610
|
+
if (restored) {
|
|
611
|
+
status("opening");
|
|
612
|
+
return { wallet: restored, method: "pairing" };
|
|
613
|
+
}
|
|
549
614
|
}
|
|
550
615
|
if (!opts.pairing) {
|
|
551
616
|
throw Object.assign(new Error("bWalletX was not found in this browser"), { code: "NOT_FOUND" });
|
|
552
617
|
}
|
|
618
|
+
status("pairing");
|
|
553
619
|
return { wallet: await pairBwalletX(opts.pairing), method: "pairing" };
|
|
554
620
|
}
|
|
555
621
|
async function signInWithBwalletX(opts) {
|
|
@@ -557,6 +623,10 @@ async function signInWithBwalletX(opts) {
|
|
|
557
623
|
if (method !== "pairing") await wallet.waitForAuthentication({}).catch(() => {
|
|
558
624
|
});
|
|
559
625
|
const { publicKey: identityKey } = await atStage("identity", () => wallet.getPublicKey({ identityKey: true }));
|
|
626
|
+
try {
|
|
627
|
+
opts.onStatus?.("signing");
|
|
628
|
+
} catch {
|
|
629
|
+
}
|
|
560
630
|
const c = await atStage("challenge", () => opts.challenge(identityKey));
|
|
561
631
|
const { signature } = await atStage(
|
|
562
632
|
"signature",
|
|
@@ -1006,6 +1076,7 @@ function createClass() {
|
|
|
1006
1076
|
const nf = this.#notFound ? `<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>` : "";
|
|
1007
1077
|
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\u2026</span>' : ""}${nf}`;
|
|
1008
1078
|
this.button.addEventListener("click", () => void this.#click());
|
|
1079
|
+
bindPrewarm(this.button);
|
|
1009
1080
|
}
|
|
1010
1081
|
#emit(type, detail, cancelable = false) {
|
|
1011
1082
|
return this.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable }));
|
|
@@ -1032,7 +1103,7 @@ function createClass() {
|
|
|
1032
1103
|
this.#notFound = false;
|
|
1033
1104
|
this.#setBusy(true);
|
|
1034
1105
|
try {
|
|
1035
|
-
const ms = Number(this.#attr("discover-ms")) ||
|
|
1106
|
+
const ms = Number(this.#attr("discover-ms")) || DEFAULT_DISCOVER_MS;
|
|
1036
1107
|
const found = await discoverBwalletX(ms);
|
|
1037
1108
|
if (!found) {
|
|
1038
1109
|
this.#notFound = true;
|
|
@@ -1160,11 +1231,11 @@ async function resolvePaymailP2P(paymail, sats, f = fetch) {
|
|
|
1160
1231
|
return {
|
|
1161
1232
|
outputs: body.outputs.map((o) => ({ script: o.script, satoshis: o.satoshis })),
|
|
1162
1233
|
reference: body.reference,
|
|
1163
|
-
submit: receive ? async (
|
|
1234
|
+
submit: receive ? async (hex2) => {
|
|
1164
1235
|
await f(fill(receive), {
|
|
1165
1236
|
method: "POST",
|
|
1166
1237
|
headers: { "content-type": "application/json" },
|
|
1167
|
-
body: JSON.stringify({ hex, reference: body.reference, metadata: {} })
|
|
1238
|
+
body: JSON.stringify({ hex: hex2, reference: body.reference, metadata: {} })
|
|
1168
1239
|
});
|
|
1169
1240
|
} : void 0
|
|
1170
1241
|
};
|
|
@@ -1310,7 +1381,7 @@ async function probe(substrate, ms) {
|
|
|
1310
1381
|
}
|
|
1311
1382
|
async function discoverWallets(o = {}) {
|
|
1312
1383
|
const out = [];
|
|
1313
|
-
const ms = o.ms ??
|
|
1384
|
+
const ms = o.ms ?? 300;
|
|
1314
1385
|
if (typeof window !== "undefined") {
|
|
1315
1386
|
const seen = /* @__PURE__ */ new Map();
|
|
1316
1387
|
const onAnnounce = (e) => {
|
|
@@ -1324,7 +1395,7 @@ async function discoverWallets(o = {}) {
|
|
|
1324
1395
|
window.addEventListener("brc100:announceWallet", onAnnounce);
|
|
1325
1396
|
window.dispatchEvent(new Event("brc100:requestWallet"));
|
|
1326
1397
|
const local = o.probeLocal ? Promise.all([probe("json-api", ms), probe("Cicada", ms)]) : Promise.resolve([null, null]);
|
|
1327
|
-
await new Promise((r) => setTimeout(r, ms));
|
|
1398
|
+
await new Promise((r) => setTimeout(r, seen.size > 0 || window.CWI ? Math.min(ms, 50) : ms));
|
|
1328
1399
|
window.removeEventListener("brc100:announceWallet", onAnnounce);
|
|
1329
1400
|
out.push(...seen.values());
|
|
1330
1401
|
const cwi = window.CWI;
|
|
@@ -1516,6 +1587,7 @@ function declareWalletTheme(theme) {
|
|
|
1516
1587
|
AccessError,
|
|
1517
1588
|
BRC29_PROTOCOL,
|
|
1518
1589
|
BWALLETX_RDNS,
|
|
1590
|
+
DEFAULT_DISCOVER_MS,
|
|
1519
1591
|
GET_URL,
|
|
1520
1592
|
LOGIN_PROTOCOL,
|
|
1521
1593
|
LOGO_URL,
|
|
@@ -1529,6 +1601,7 @@ function declareWalletTheme(theme) {
|
|
|
1529
1601
|
WEB_WALLET_URL,
|
|
1530
1602
|
accessErrorMessage,
|
|
1531
1603
|
amountInSats,
|
|
1604
|
+
bindPrewarm,
|
|
1532
1605
|
brc100Option,
|
|
1533
1606
|
buildAuthorizeUrl,
|
|
1534
1607
|
buyToken,
|
|
@@ -1551,6 +1624,7 @@ function declareWalletTheme(theme) {
|
|
|
1551
1624
|
pairingOption,
|
|
1552
1625
|
pay,
|
|
1553
1626
|
pickWallet,
|
|
1627
|
+
prewarmBwalletX,
|
|
1554
1628
|
protocolMediaUrl,
|
|
1555
1629
|
proveHoldings,
|
|
1556
1630
|
qrSvg,
|