@qrlwallet/connect 3.1.1 → 3.2.0
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 +12 -3
- package/dist/index.d.mts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +37 -0
- package/dist/index.mjs +36 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,10 +18,12 @@ All communication is end-to-end encrypted with ML-KEM-768 (FIPS 203) key encapsu
|
|
|
18
18
|
npm install @qrlwallet/connect
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
Want a ready-made pairing dialog (QR code, deep link, copy-code fallback) instead of building your own? Add the framework-free [`@qrlwallet/connect-ui`](ui/) web component.
|
|
22
|
+
|
|
21
23
|
## Quick start
|
|
22
24
|
|
|
23
25
|
```typescript
|
|
24
|
-
import { QRLConnect } from '@qrlwallet/connect';
|
|
26
|
+
import { QRLConnect, attemptWalletRedirect, getAppStoreUrl } from '@qrlwallet/connect';
|
|
25
27
|
|
|
26
28
|
const qrl = new QRLConnect({
|
|
27
29
|
dappMetadata: {
|
|
@@ -34,9 +36,16 @@ const qrl = new QRLConnect({
|
|
|
34
36
|
const uri = await qrl.getConnectionURI();
|
|
35
37
|
|
|
36
38
|
// Desktop: render as QR code (use any QR library)
|
|
37
|
-
// Mobile:
|
|
39
|
+
// Mobile: try to open the wallet app, with a fallback for when it is
|
|
40
|
+
// not installed (a bare `window.location.href = uri` fails at the
|
|
41
|
+
// unknown protocol: silently on Android, blocking alert on iOS)
|
|
38
42
|
if (qrl.isMobile()) {
|
|
39
|
-
|
|
43
|
+
const opened = await attemptWalletRedirect(uri);
|
|
44
|
+
if (!opened) {
|
|
45
|
+
// Wallet app not installed (or the user dismissed the chooser):
|
|
46
|
+
// show your QR / copy-code pairing UI plus an install link.
|
|
47
|
+
console.log('Get MyQRLWallet:', getAppStoreUrl());
|
|
48
|
+
}
|
|
40
49
|
} else {
|
|
41
50
|
// render uri as QR code
|
|
42
51
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -777,6 +777,24 @@ declare function isMobileBrowser(): boolean;
|
|
|
777
777
|
* Falls back to app store URL after timeout.
|
|
778
778
|
*/
|
|
779
779
|
declare function getAppStoreUrl(): string;
|
|
780
|
+
/**
|
|
781
|
+
* Attempt to open a `qrlconnect://` URI in the wallet app and report whether
|
|
782
|
+
* anything handled it.
|
|
783
|
+
*
|
|
784
|
+
* A custom-scheme navigation on a device without the app installed fails
|
|
785
|
+
* silently on Android and with a blocking alert on iOS Safari, leaving the
|
|
786
|
+
* page visible either way. When the app IS installed, the OS backgrounds the
|
|
787
|
+
* browser, firing `visibilitychange`/`pagehide` almost immediately. So:
|
|
788
|
+
* navigate, then resolve `true` as soon as the page hides, or `false` if it
|
|
789
|
+
* is still visible after `timeoutMs`. On `false`, show fallback pairing UI
|
|
790
|
+
* (QR / copy-code) and an install link (`getAppStoreUrl()`).
|
|
791
|
+
*
|
|
792
|
+
* Detection is heuristic by nature: a slow device may hide the page late
|
|
793
|
+
* (harmless, the wallet still opens), and it cannot distinguish "app missing"
|
|
794
|
+
* from "user dismissed the OS chooser". Treat `false` as "show a fallback",
|
|
795
|
+
* never as proof the app is absent.
|
|
796
|
+
*/
|
|
797
|
+
declare function attemptWalletRedirect(uri: string, timeoutMs?: number): Promise<boolean>;
|
|
780
798
|
|
|
781
799
|
declare const DEFAULT_RELAY_URL = "https://qrlwallet.com";
|
|
782
800
|
declare const PROTOCOL_VERSION = 2;
|
|
@@ -795,4 +813,4 @@ declare const RESTRICTED_METHODS: Set<string>;
|
|
|
795
813
|
/** RPC methods that can be auto-proxied without approval */
|
|
796
814
|
declare const UNRESTRICTED_METHODS: Set<string>;
|
|
797
815
|
|
|
798
|
-
export { type AckMessage, BLOB_LEN, CID_LEN, ConnectionManager, ConnectionStatus, type DAppMetadata, type DAppSession, DEFAULT_RELAY_URL, DIGEST_LEN, type Domain, type EIP6963ProviderInfoOverride, FP_LEN, type JsonRpcRequest, type JsonRpcResponse, KeyExchange, KeyExchangeMessageType, type Message, MessageType, PROTOCOL_VERSION, type ParsedURI, type PendingRequest, type PersistedSession, type ProviderEvents, QRLConnectProvider as QRLConnect, type QRLConnectOptions, QRLConnectProvider, QRL_CONNECT_PROVIDER_INFO, type QrlSignMessageParams, type QrlSignTypedDataParams, type QrlSignedResult, type QrlSignedTypedDataResult, type QrlTypedDataPayload, RESTRICTED_METHODS, type RelayMessage, SCHEME_TAG_MSG, SCHEME_TAG_TYPED, SCHEME_VERSION_MSG, SCHEME_VERSION_TYPED, type Session, SocketClient, type StructDef, type SynAckMessage, type TypeMap, type TypedDataPayload, type TypedField, UNRESTRICTED_METHODS, type VerifyMessageParams, type VerifyTypedDataParams, bytesToHex, cidFromString, cidRandom, cidToString, computeFingerprint, computeMessageDigest, computeTypedDataDigest, concatBytes, encodeField, encodeType, fingerprintEquals, generateConnectionURI, getAppStoreUrl, hashStruct, hexToBytes, isMobileBrowser, parseConnectionURI, typeHash, verifyMessage, verifyTypedData };
|
|
816
|
+
export { type AckMessage, BLOB_LEN, CID_LEN, ConnectionManager, ConnectionStatus, type DAppMetadata, type DAppSession, DEFAULT_RELAY_URL, DIGEST_LEN, type Domain, type EIP6963ProviderInfoOverride, FP_LEN, type JsonRpcRequest, type JsonRpcResponse, KeyExchange, KeyExchangeMessageType, type Message, MessageType, PROTOCOL_VERSION, type ParsedURI, type PendingRequest, type PersistedSession, type ProviderEvents, QRLConnectProvider as QRLConnect, type QRLConnectOptions, QRLConnectProvider, QRL_CONNECT_PROVIDER_INFO, type QrlSignMessageParams, type QrlSignTypedDataParams, type QrlSignedResult, type QrlSignedTypedDataResult, type QrlTypedDataPayload, RESTRICTED_METHODS, type RelayMessage, SCHEME_TAG_MSG, SCHEME_TAG_TYPED, SCHEME_VERSION_MSG, SCHEME_VERSION_TYPED, type Session, SocketClient, type StructDef, type SynAckMessage, type TypeMap, type TypedDataPayload, type TypedField, UNRESTRICTED_METHODS, type VerifyMessageParams, type VerifyTypedDataParams, attemptWalletRedirect, bytesToHex, cidFromString, cidRandom, cidToString, computeFingerprint, computeMessageDigest, computeTypedDataDigest, concatBytes, encodeField, encodeType, fingerprintEquals, generateConnectionURI, getAppStoreUrl, hashStruct, hexToBytes, isMobileBrowser, parseConnectionURI, typeHash, verifyMessage, verifyTypedData };
|
package/dist/index.d.ts
CHANGED
|
@@ -777,6 +777,24 @@ declare function isMobileBrowser(): boolean;
|
|
|
777
777
|
* Falls back to app store URL after timeout.
|
|
778
778
|
*/
|
|
779
779
|
declare function getAppStoreUrl(): string;
|
|
780
|
+
/**
|
|
781
|
+
* Attempt to open a `qrlconnect://` URI in the wallet app and report whether
|
|
782
|
+
* anything handled it.
|
|
783
|
+
*
|
|
784
|
+
* A custom-scheme navigation on a device without the app installed fails
|
|
785
|
+
* silently on Android and with a blocking alert on iOS Safari, leaving the
|
|
786
|
+
* page visible either way. When the app IS installed, the OS backgrounds the
|
|
787
|
+
* browser, firing `visibilitychange`/`pagehide` almost immediately. So:
|
|
788
|
+
* navigate, then resolve `true` as soon as the page hides, or `false` if it
|
|
789
|
+
* is still visible after `timeoutMs`. On `false`, show fallback pairing UI
|
|
790
|
+
* (QR / copy-code) and an install link (`getAppStoreUrl()`).
|
|
791
|
+
*
|
|
792
|
+
* Detection is heuristic by nature: a slow device may hide the page late
|
|
793
|
+
* (harmless, the wallet still opens), and it cannot distinguish "app missing"
|
|
794
|
+
* from "user dismissed the OS chooser". Treat `false` as "show a fallback",
|
|
795
|
+
* never as proof the app is absent.
|
|
796
|
+
*/
|
|
797
|
+
declare function attemptWalletRedirect(uri: string, timeoutMs?: number): Promise<boolean>;
|
|
780
798
|
|
|
781
799
|
declare const DEFAULT_RELAY_URL = "https://qrlwallet.com";
|
|
782
800
|
declare const PROTOCOL_VERSION = 2;
|
|
@@ -795,4 +813,4 @@ declare const RESTRICTED_METHODS: Set<string>;
|
|
|
795
813
|
/** RPC methods that can be auto-proxied without approval */
|
|
796
814
|
declare const UNRESTRICTED_METHODS: Set<string>;
|
|
797
815
|
|
|
798
|
-
export { type AckMessage, BLOB_LEN, CID_LEN, ConnectionManager, ConnectionStatus, type DAppMetadata, type DAppSession, DEFAULT_RELAY_URL, DIGEST_LEN, type Domain, type EIP6963ProviderInfoOverride, FP_LEN, type JsonRpcRequest, type JsonRpcResponse, KeyExchange, KeyExchangeMessageType, type Message, MessageType, PROTOCOL_VERSION, type ParsedURI, type PendingRequest, type PersistedSession, type ProviderEvents, QRLConnectProvider as QRLConnect, type QRLConnectOptions, QRLConnectProvider, QRL_CONNECT_PROVIDER_INFO, type QrlSignMessageParams, type QrlSignTypedDataParams, type QrlSignedResult, type QrlSignedTypedDataResult, type QrlTypedDataPayload, RESTRICTED_METHODS, type RelayMessage, SCHEME_TAG_MSG, SCHEME_TAG_TYPED, SCHEME_VERSION_MSG, SCHEME_VERSION_TYPED, type Session, SocketClient, type StructDef, type SynAckMessage, type TypeMap, type TypedDataPayload, type TypedField, UNRESTRICTED_METHODS, type VerifyMessageParams, type VerifyTypedDataParams, bytesToHex, cidFromString, cidRandom, cidToString, computeFingerprint, computeMessageDigest, computeTypedDataDigest, concatBytes, encodeField, encodeType, fingerprintEquals, generateConnectionURI, getAppStoreUrl, hashStruct, hexToBytes, isMobileBrowser, parseConnectionURI, typeHash, verifyMessage, verifyTypedData };
|
|
816
|
+
export { type AckMessage, BLOB_LEN, CID_LEN, ConnectionManager, ConnectionStatus, type DAppMetadata, type DAppSession, DEFAULT_RELAY_URL, DIGEST_LEN, type Domain, type EIP6963ProviderInfoOverride, FP_LEN, type JsonRpcRequest, type JsonRpcResponse, KeyExchange, KeyExchangeMessageType, type Message, MessageType, PROTOCOL_VERSION, type ParsedURI, type PendingRequest, type PersistedSession, type ProviderEvents, QRLConnectProvider as QRLConnect, type QRLConnectOptions, QRLConnectProvider, QRL_CONNECT_PROVIDER_INFO, type QrlSignMessageParams, type QrlSignTypedDataParams, type QrlSignedResult, type QrlSignedTypedDataResult, type QrlTypedDataPayload, RESTRICTED_METHODS, type RelayMessage, SCHEME_TAG_MSG, SCHEME_TAG_TYPED, SCHEME_VERSION_MSG, SCHEME_VERSION_TYPED, type Session, SocketClient, type StructDef, type SynAckMessage, type TypeMap, type TypedDataPayload, type TypedField, UNRESTRICTED_METHODS, type VerifyMessageParams, type VerifyTypedDataParams, attemptWalletRedirect, bytesToHex, cidFromString, cidRandom, cidToString, computeFingerprint, computeMessageDigest, computeTypedDataDigest, concatBytes, encodeField, encodeType, fingerprintEquals, generateConnectionURI, getAppStoreUrl, hashStruct, hexToBytes, isMobileBrowser, parseConnectionURI, typeHash, verifyMessage, verifyTypedData };
|
package/dist/index.js
CHANGED
|
@@ -51,6 +51,7 @@ __export(index_exports, {
|
|
|
51
51
|
SCHEME_VERSION_TYPED: () => SCHEME_VERSION_TYPED,
|
|
52
52
|
SocketClient: () => SocketClient,
|
|
53
53
|
UNRESTRICTED_METHODS: () => UNRESTRICTED_METHODS,
|
|
54
|
+
attemptWalletRedirect: () => attemptWalletRedirect,
|
|
54
55
|
bytesToHex: () => bytesToHex,
|
|
55
56
|
cidFromString: () => cidFromString,
|
|
56
57
|
cidRandom: () => cidRandom,
|
|
@@ -1724,6 +1725,41 @@ function getAppStoreUrl() {
|
|
|
1724
1725
|
}
|
|
1725
1726
|
return "https://apps.apple.com/app/myqrlwallet/id6742219498";
|
|
1726
1727
|
}
|
|
1728
|
+
function attemptWalletRedirect(uri, timeoutMs = 1800) {
|
|
1729
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
1730
|
+
return Promise.resolve(false);
|
|
1731
|
+
}
|
|
1732
|
+
if (!uri.trim().toLowerCase().startsWith("qrlconnect:")) {
|
|
1733
|
+
return Promise.resolve(false);
|
|
1734
|
+
}
|
|
1735
|
+
return new Promise((resolve) => {
|
|
1736
|
+
let settled = false;
|
|
1737
|
+
const finish = (opened) => {
|
|
1738
|
+
if (settled) return;
|
|
1739
|
+
settled = true;
|
|
1740
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
1741
|
+
window.removeEventListener("pagehide", onHide);
|
|
1742
|
+
window.clearTimeout(timer);
|
|
1743
|
+
resolve(opened);
|
|
1744
|
+
};
|
|
1745
|
+
const onVisibility = () => {
|
|
1746
|
+
if (document.visibilityState === "hidden") finish(true);
|
|
1747
|
+
};
|
|
1748
|
+
const onHide = () => {
|
|
1749
|
+
finish(true);
|
|
1750
|
+
};
|
|
1751
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
1752
|
+
window.addEventListener("pagehide", onHide);
|
|
1753
|
+
const timer = window.setTimeout(() => {
|
|
1754
|
+
finish(false);
|
|
1755
|
+
}, timeoutMs);
|
|
1756
|
+
try {
|
|
1757
|
+
window.location.href = uri;
|
|
1758
|
+
} catch {
|
|
1759
|
+
finish(false);
|
|
1760
|
+
}
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1727
1763
|
|
|
1728
1764
|
// src/QRLConnectProvider.ts
|
|
1729
1765
|
var QRL_CONNECT_PROVIDER_INFO = {
|
|
@@ -2406,6 +2442,7 @@ function verifyTypedData({ signature, publicKey, payload }) {
|
|
|
2406
2442
|
SCHEME_VERSION_TYPED,
|
|
2407
2443
|
SocketClient,
|
|
2408
2444
|
UNRESTRICTED_METHODS,
|
|
2445
|
+
attemptWalletRedirect,
|
|
2409
2446
|
bytesToHex,
|
|
2410
2447
|
cidFromString,
|
|
2411
2448
|
cidRandom,
|
package/dist/index.mjs
CHANGED
|
@@ -1648,6 +1648,41 @@ function getAppStoreUrl() {
|
|
|
1648
1648
|
}
|
|
1649
1649
|
return "https://apps.apple.com/app/myqrlwallet/id6742219498";
|
|
1650
1650
|
}
|
|
1651
|
+
function attemptWalletRedirect(uri, timeoutMs = 1800) {
|
|
1652
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
1653
|
+
return Promise.resolve(false);
|
|
1654
|
+
}
|
|
1655
|
+
if (!uri.trim().toLowerCase().startsWith("qrlconnect:")) {
|
|
1656
|
+
return Promise.resolve(false);
|
|
1657
|
+
}
|
|
1658
|
+
return new Promise((resolve) => {
|
|
1659
|
+
let settled = false;
|
|
1660
|
+
const finish = (opened) => {
|
|
1661
|
+
if (settled) return;
|
|
1662
|
+
settled = true;
|
|
1663
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
1664
|
+
window.removeEventListener("pagehide", onHide);
|
|
1665
|
+
window.clearTimeout(timer);
|
|
1666
|
+
resolve(opened);
|
|
1667
|
+
};
|
|
1668
|
+
const onVisibility = () => {
|
|
1669
|
+
if (document.visibilityState === "hidden") finish(true);
|
|
1670
|
+
};
|
|
1671
|
+
const onHide = () => {
|
|
1672
|
+
finish(true);
|
|
1673
|
+
};
|
|
1674
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
1675
|
+
window.addEventListener("pagehide", onHide);
|
|
1676
|
+
const timer = window.setTimeout(() => {
|
|
1677
|
+
finish(false);
|
|
1678
|
+
}, timeoutMs);
|
|
1679
|
+
try {
|
|
1680
|
+
window.location.href = uri;
|
|
1681
|
+
} catch {
|
|
1682
|
+
finish(false);
|
|
1683
|
+
}
|
|
1684
|
+
});
|
|
1685
|
+
}
|
|
1651
1686
|
|
|
1652
1687
|
// src/QRLConnectProvider.ts
|
|
1653
1688
|
var QRL_CONNECT_PROVIDER_INFO = {
|
|
@@ -2329,6 +2364,7 @@ export {
|
|
|
2329
2364
|
SCHEME_VERSION_TYPED,
|
|
2330
2365
|
SocketClient,
|
|
2331
2366
|
UNRESTRICTED_METHODS,
|
|
2367
|
+
attemptWalletRedirect,
|
|
2332
2368
|
bytesToHex,
|
|
2333
2369
|
cidFromString,
|
|
2334
2370
|
cidRandom,
|