@qrlwallet/connect 5.1.1 → 5.1.2
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/README.md +5 -0
- package/dist/index.js +24 -12
- package/dist/index.mjs +24 -12
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -286,6 +286,9 @@ npm run dev
|
|
|
286
286
|
# Type-check
|
|
287
287
|
npm run typecheck
|
|
288
288
|
|
|
289
|
+
# Type-check tests
|
|
290
|
+
npm run typecheck:test
|
|
291
|
+
|
|
289
292
|
# Unit tests (vitest)
|
|
290
293
|
npm test
|
|
291
294
|
|
|
@@ -296,6 +299,8 @@ npm run lint
|
|
|
296
299
|
node test-e2e.mjs
|
|
297
300
|
```
|
|
298
301
|
|
|
302
|
+
CI runs `node scripts/audit-gate.mjs` after the SDK install and `node scripts/audit-gate.mjs --dir ui` after the UI install; both read `audit-allowlist.json` at the repository root. The gate blocks high and critical production advisories unless a matching, dated exception in `audit-allowlist.json` explains why the advisory cannot reach users.
|
|
303
|
+
|
|
299
304
|
## Running the example dApp
|
|
300
305
|
|
|
301
306
|
The `example/` directory contains a Vite test dApp with QR code generation, transaction sending, message signing, and read-only RPC calls.
|
package/dist/index.js
CHANGED
|
@@ -121,7 +121,8 @@ var import_ml_kem = require("@noble/post-quantum/ml-kem.js");
|
|
|
121
121
|
var import_sha3 = require("@noble/hashes/sha3.js");
|
|
122
122
|
var mldsa = __toESM(require("@theqrl/mldsa87"));
|
|
123
123
|
function webCrypto() {
|
|
124
|
-
const
|
|
124
|
+
const environment = globalThis;
|
|
125
|
+
const c = environment.crypto;
|
|
125
126
|
if (!c) {
|
|
126
127
|
throw new Error("crypto: WebCrypto is not available in this environment");
|
|
127
128
|
}
|
|
@@ -641,7 +642,8 @@ var KeyExchange = class extends import_eventemitter3.default {
|
|
|
641
642
|
this.lastAck = null;
|
|
642
643
|
this.isOriginator = isOriginator;
|
|
643
644
|
if (restored) {
|
|
644
|
-
|
|
645
|
+
const protocolVersion = restored.protocolVersion;
|
|
646
|
+
if (protocolVersion !== PROTOCOL_VERSION) {
|
|
645
647
|
throw new Error("KeyExchange: cannot restore a pre-v3 session");
|
|
646
648
|
}
|
|
647
649
|
this.session = snapshotSession(restored);
|
|
@@ -975,7 +977,8 @@ var KeyExchange = class extends import_eventemitter3.default {
|
|
|
975
977
|
}
|
|
976
978
|
/** Rehydrate a Session from its persisted form. */
|
|
977
979
|
static async sessionFromPersisted(p) {
|
|
978
|
-
|
|
980
|
+
const protocolVersion = p.protocolVersion;
|
|
981
|
+
if (protocolVersion !== PROTOCOL_VERSION) {
|
|
979
982
|
throw new Error("KeyExchange: cannot hydrate a pre-v3 session");
|
|
980
983
|
}
|
|
981
984
|
const kAeadRaw = fromBase64Exact(p.kAeadRaw, 32, "persisted AEAD key");
|
|
@@ -1553,7 +1556,12 @@ function startsWith(buf, prefix) {
|
|
|
1553
1556
|
}
|
|
1554
1557
|
return true;
|
|
1555
1558
|
}
|
|
1556
|
-
|
|
1559
|
+
function parseConnectionURI(uri) {
|
|
1560
|
+
return new Promise((resolve) => {
|
|
1561
|
+
resolve(parseURI(uri));
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
function parseURI(uri) {
|
|
1557
1565
|
if (typeof uri !== "string" || uri.length === 0) {
|
|
1558
1566
|
throw new Error("qrUri: empty URI");
|
|
1559
1567
|
}
|
|
@@ -1598,7 +1606,7 @@ async function parseConnectionURI(uri) {
|
|
|
1598
1606
|
blob = base45Decode(q);
|
|
1599
1607
|
} catch (err) {
|
|
1600
1608
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1601
|
-
throw new Error(`qrUri: base45 decode failed: ${msg}
|
|
1609
|
+
throw new Error(`qrUri: base45 decode failed: ${msg}`, { cause: err });
|
|
1602
1610
|
}
|
|
1603
1611
|
try {
|
|
1604
1612
|
if (blob.length !== BLOB_LEN) {
|
|
@@ -1671,7 +1679,8 @@ function getBrowserStorage() {
|
|
|
1671
1679
|
function getBrowserLockManager() {
|
|
1672
1680
|
try {
|
|
1673
1681
|
if (typeof navigator === "undefined") return null;
|
|
1674
|
-
|
|
1682
|
+
const browserNavigator = navigator;
|
|
1683
|
+
return browserNavigator.locks ?? null;
|
|
1675
1684
|
} catch {
|
|
1676
1685
|
return null;
|
|
1677
1686
|
}
|
|
@@ -2012,7 +2021,8 @@ var _ConnectionManager = class _ConnectionManager extends import_eventemitter33.
|
|
|
2012
2021
|
});
|
|
2013
2022
|
socketClient.on("participants_changed", (data) => {
|
|
2014
2023
|
if (!isCurrentSocket()) return;
|
|
2015
|
-
|
|
2024
|
+
const clientType = data.clientType;
|
|
2025
|
+
if (clientType !== "wallet") return;
|
|
2016
2026
|
if (data.event === "join" && data.clientType === "wallet") {
|
|
2017
2027
|
this.walletPresent = true;
|
|
2018
2028
|
log("ConnectionManager", "Wallet joined channel");
|
|
@@ -2179,7 +2189,8 @@ var _ConnectionManager = class _ConnectionManager extends import_eventemitter33.
|
|
|
2179
2189
|
log("ConnectionManager", `Generated v3 connection URI for channel ${context.channelId}`);
|
|
2180
2190
|
return uri;
|
|
2181
2191
|
} catch (err) {
|
|
2182
|
-
|
|
2192
|
+
const keyExchange = this.keyExchange;
|
|
2193
|
+
if (context ? this.isSessionWorkCurrent(context) : keyExchange !== null) {
|
|
2183
2194
|
this.invalidateSessionWork();
|
|
2184
2195
|
this.keyExchange = null;
|
|
2185
2196
|
this.socketClient.leaveChannel();
|
|
@@ -3001,7 +3012,7 @@ var _ConnectionManager = class _ConnectionManager extends import_eventemitter33.
|
|
|
3001
3012
|
const persistedKex = await context.keyExchange.exportPersisted();
|
|
3002
3013
|
if (!persistedKex) throw new Error("Cannot export established AEAD session");
|
|
3003
3014
|
this.assertSessionWorkCurrent(context);
|
|
3004
|
-
if (!this.sessionOwnership
|
|
3015
|
+
if (!this.sessionOwnership.isOwned()) {
|
|
3005
3016
|
throw new Error("Browser-tab ownership changed while persisting AEAD counters");
|
|
3006
3017
|
}
|
|
3007
3018
|
const session = {
|
|
@@ -3020,7 +3031,7 @@ var _ConnectionManager = class _ConnectionManager extends import_eventemitter33.
|
|
|
3020
3031
|
this.persistenceBroken = true;
|
|
3021
3032
|
this.removeStoredSession();
|
|
3022
3033
|
error("ConnectionManager", "Failed to persist AEAD counters:", err);
|
|
3023
|
-
throw new Error("Failed to persist AEAD counters");
|
|
3034
|
+
throw new Error("Failed to persist AEAD counters", { cause: err });
|
|
3024
3035
|
}
|
|
3025
3036
|
}
|
|
3026
3037
|
readStoredSession() {
|
|
@@ -3702,7 +3713,8 @@ function canonicalChainId2(value) {
|
|
|
3702
3713
|
return `0x${BigInt(value).toString(16)}`;
|
|
3703
3714
|
}
|
|
3704
3715
|
function requestedSwitchChainId(params) {
|
|
3705
|
-
|
|
3716
|
+
const parameterCount = params?.length;
|
|
3717
|
+
if (parameterCount !== 1) {
|
|
3706
3718
|
throw new Error("wallet_switchQrlChain requires one chain configuration object");
|
|
3707
3719
|
}
|
|
3708
3720
|
const request = params?.[0];
|
|
@@ -3768,7 +3780,7 @@ function snapshotRequestParams(params) {
|
|
|
3768
3780
|
return snapshot;
|
|
3769
3781
|
} catch (error2) {
|
|
3770
3782
|
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
3771
|
-
throw new Error(`Request params must be JSON-serializable: ${detail}
|
|
3783
|
+
throw new Error(`Request params must be JSON-serializable: ${detail}`, { cause: error2 });
|
|
3772
3784
|
}
|
|
3773
3785
|
}
|
|
3774
3786
|
function validateRestrictedRequest(method, params, authorizedAccounts, currentChainId) {
|
package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,8 @@ import { ml_kem768 } from "@noble/post-quantum/ml-kem.js";
|
|
|
12
12
|
import { shake256 } from "@noble/hashes/sha3.js";
|
|
13
13
|
import * as mldsa from "@theqrl/mldsa87";
|
|
14
14
|
function webCrypto() {
|
|
15
|
-
const
|
|
15
|
+
const environment = globalThis;
|
|
16
|
+
const c = environment.crypto;
|
|
16
17
|
if (!c) {
|
|
17
18
|
throw new Error("crypto: WebCrypto is not available in this environment");
|
|
18
19
|
}
|
|
@@ -532,7 +533,8 @@ var KeyExchange = class extends EventEmitter {
|
|
|
532
533
|
this.lastAck = null;
|
|
533
534
|
this.isOriginator = isOriginator;
|
|
534
535
|
if (restored) {
|
|
535
|
-
|
|
536
|
+
const protocolVersion = restored.protocolVersion;
|
|
537
|
+
if (protocolVersion !== PROTOCOL_VERSION) {
|
|
536
538
|
throw new Error("KeyExchange: cannot restore a pre-v3 session");
|
|
537
539
|
}
|
|
538
540
|
this.session = snapshotSession(restored);
|
|
@@ -866,7 +868,8 @@ var KeyExchange = class extends EventEmitter {
|
|
|
866
868
|
}
|
|
867
869
|
/** Rehydrate a Session from its persisted form. */
|
|
868
870
|
static async sessionFromPersisted(p) {
|
|
869
|
-
|
|
871
|
+
const protocolVersion = p.protocolVersion;
|
|
872
|
+
if (protocolVersion !== PROTOCOL_VERSION) {
|
|
870
873
|
throw new Error("KeyExchange: cannot hydrate a pre-v3 session");
|
|
871
874
|
}
|
|
872
875
|
const kAeadRaw = fromBase64Exact(p.kAeadRaw, 32, "persisted AEAD key");
|
|
@@ -1444,7 +1447,12 @@ function startsWith(buf, prefix) {
|
|
|
1444
1447
|
}
|
|
1445
1448
|
return true;
|
|
1446
1449
|
}
|
|
1447
|
-
|
|
1450
|
+
function parseConnectionURI(uri) {
|
|
1451
|
+
return new Promise((resolve) => {
|
|
1452
|
+
resolve(parseURI(uri));
|
|
1453
|
+
});
|
|
1454
|
+
}
|
|
1455
|
+
function parseURI(uri) {
|
|
1448
1456
|
if (typeof uri !== "string" || uri.length === 0) {
|
|
1449
1457
|
throw new Error("qrUri: empty URI");
|
|
1450
1458
|
}
|
|
@@ -1489,7 +1497,7 @@ async function parseConnectionURI(uri) {
|
|
|
1489
1497
|
blob = base45Decode(q);
|
|
1490
1498
|
} catch (err) {
|
|
1491
1499
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1492
|
-
throw new Error(`qrUri: base45 decode failed: ${msg}
|
|
1500
|
+
throw new Error(`qrUri: base45 decode failed: ${msg}`, { cause: err });
|
|
1493
1501
|
}
|
|
1494
1502
|
try {
|
|
1495
1503
|
if (blob.length !== BLOB_LEN) {
|
|
@@ -1562,7 +1570,8 @@ function getBrowserStorage() {
|
|
|
1562
1570
|
function getBrowserLockManager() {
|
|
1563
1571
|
try {
|
|
1564
1572
|
if (typeof navigator === "undefined") return null;
|
|
1565
|
-
|
|
1573
|
+
const browserNavigator = navigator;
|
|
1574
|
+
return browserNavigator.locks ?? null;
|
|
1566
1575
|
} catch {
|
|
1567
1576
|
return null;
|
|
1568
1577
|
}
|
|
@@ -1903,7 +1912,8 @@ var _ConnectionManager = class _ConnectionManager extends EventEmitter3 {
|
|
|
1903
1912
|
});
|
|
1904
1913
|
socketClient.on("participants_changed", (data) => {
|
|
1905
1914
|
if (!isCurrentSocket()) return;
|
|
1906
|
-
|
|
1915
|
+
const clientType = data.clientType;
|
|
1916
|
+
if (clientType !== "wallet") return;
|
|
1907
1917
|
if (data.event === "join" && data.clientType === "wallet") {
|
|
1908
1918
|
this.walletPresent = true;
|
|
1909
1919
|
log("ConnectionManager", "Wallet joined channel");
|
|
@@ -2070,7 +2080,8 @@ var _ConnectionManager = class _ConnectionManager extends EventEmitter3 {
|
|
|
2070
2080
|
log("ConnectionManager", `Generated v3 connection URI for channel ${context.channelId}`);
|
|
2071
2081
|
return uri;
|
|
2072
2082
|
} catch (err) {
|
|
2073
|
-
|
|
2083
|
+
const keyExchange = this.keyExchange;
|
|
2084
|
+
if (context ? this.isSessionWorkCurrent(context) : keyExchange !== null) {
|
|
2074
2085
|
this.invalidateSessionWork();
|
|
2075
2086
|
this.keyExchange = null;
|
|
2076
2087
|
this.socketClient.leaveChannel();
|
|
@@ -2892,7 +2903,7 @@ var _ConnectionManager = class _ConnectionManager extends EventEmitter3 {
|
|
|
2892
2903
|
const persistedKex = await context.keyExchange.exportPersisted();
|
|
2893
2904
|
if (!persistedKex) throw new Error("Cannot export established AEAD session");
|
|
2894
2905
|
this.assertSessionWorkCurrent(context);
|
|
2895
|
-
if (!this.sessionOwnership
|
|
2906
|
+
if (!this.sessionOwnership.isOwned()) {
|
|
2896
2907
|
throw new Error("Browser-tab ownership changed while persisting AEAD counters");
|
|
2897
2908
|
}
|
|
2898
2909
|
const session = {
|
|
@@ -2911,7 +2922,7 @@ var _ConnectionManager = class _ConnectionManager extends EventEmitter3 {
|
|
|
2911
2922
|
this.persistenceBroken = true;
|
|
2912
2923
|
this.removeStoredSession();
|
|
2913
2924
|
error("ConnectionManager", "Failed to persist AEAD counters:", err);
|
|
2914
|
-
throw new Error("Failed to persist AEAD counters");
|
|
2925
|
+
throw new Error("Failed to persist AEAD counters", { cause: err });
|
|
2915
2926
|
}
|
|
2916
2927
|
}
|
|
2917
2928
|
readStoredSession() {
|
|
@@ -3593,7 +3604,8 @@ function canonicalChainId2(value) {
|
|
|
3593
3604
|
return `0x${BigInt(value).toString(16)}`;
|
|
3594
3605
|
}
|
|
3595
3606
|
function requestedSwitchChainId(params) {
|
|
3596
|
-
|
|
3607
|
+
const parameterCount = params?.length;
|
|
3608
|
+
if (parameterCount !== 1) {
|
|
3597
3609
|
throw new Error("wallet_switchQrlChain requires one chain configuration object");
|
|
3598
3610
|
}
|
|
3599
3611
|
const request = params?.[0];
|
|
@@ -3659,7 +3671,7 @@ function snapshotRequestParams(params) {
|
|
|
3659
3671
|
return snapshot;
|
|
3660
3672
|
} catch (error2) {
|
|
3661
3673
|
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
3662
|
-
throw new Error(`Request params must be JSON-serializable: ${detail}
|
|
3674
|
+
throw new Error(`Request params must be JSON-serializable: ${detail}`, { cause: error2 });
|
|
3663
3675
|
}
|
|
3664
3676
|
}
|
|
3665
3677
|
function validateRestrictedRequest(method, params, authorizedAccounts, currentChainId) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qrlwallet/connect",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.2",
|
|
4
4
|
"packageManager": "npm@10.9.8",
|
|
5
5
|
"description": "Connect your dApp to QRL Wallet via QR code or deep link",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,16 +13,19 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
15
15
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
16
|
-
"typecheck": "tsc --noEmit",
|
|
16
|
+
"typecheck": "tsc --noEmit && npm run typecheck:test",
|
|
17
|
+
"typecheck:test": "tsc --noEmit -p tsconfig.eslint.json",
|
|
17
18
|
"test": "vitest run",
|
|
18
19
|
"test:watch": "vitest",
|
|
19
|
-
"lint": "eslint src
|
|
20
|
-
"lint:fix": "eslint src
|
|
20
|
+
"lint": "eslint --config eslint.config.mjs src test scripts \"*.mjs\" vitest.config.ts --report-unused-disable-directives --max-warnings 0",
|
|
21
|
+
"lint:fix": "eslint --config eslint.config.mjs src test scripts \"*.mjs\" vitest.config.ts --report-unused-disable-directives --max-warnings 0 --fix",
|
|
21
22
|
"format": "prettier --write src/",
|
|
22
23
|
"format:check": "prettier --check src/",
|
|
23
24
|
"size": "size-limit",
|
|
24
25
|
"size:check": "size-limit --highlight-less",
|
|
25
|
-
"prepublishOnly": "npm run lint && npm run typecheck && npm test && npm run build"
|
|
26
|
+
"prepublishOnly": "npm run lint && npm run typecheck && npm test && npm run build",
|
|
27
|
+
"lint:ratchet": "node scripts/lint-ratchet.mjs --check",
|
|
28
|
+
"lint:ratchet:update": "node scripts/lint-ratchet.mjs"
|
|
26
29
|
},
|
|
27
30
|
"keywords": [
|
|
28
31
|
"qrl",
|
|
@@ -49,13 +52,15 @@
|
|
|
49
52
|
"socket.io-client": "^4.8.1"
|
|
50
53
|
},
|
|
51
54
|
"devDependencies": {
|
|
55
|
+
"@eslint/js": "^10.0.1",
|
|
52
56
|
"@size-limit/file": "^11.0.0",
|
|
53
57
|
"@theqrl/wallet.js": "^6.3.0",
|
|
54
58
|
"@types/node": "^25.3.3",
|
|
55
59
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
56
60
|
"@typescript-eslint/parser": "^8.0.0",
|
|
57
|
-
"eslint": "^
|
|
61
|
+
"eslint": "^10.12.0",
|
|
58
62
|
"eslint-config-prettier": "^9.1.0",
|
|
63
|
+
"globals": "^17.13.0",
|
|
59
64
|
"prettier": "^3.4.0",
|
|
60
65
|
"size-limit": "^11.0.0",
|
|
61
66
|
"tsup": "^8.4.0",
|