@metamask-previews/eth-qr-keyring 1.0.0-065a890

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.
@@ -0,0 +1,242 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
6
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
+ if (kind === "m") throw new TypeError("Private method is not writable");
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
+ };
12
+ var _AirgappedSigner_instances, _AirgappedSigner_source, _AirgappedSigner_initFromUR, _AirgappedSigner_decodeUR;
13
+ function $importDefault(module) {
14
+ if (module?.__esModule) {
15
+ return module.default;
16
+ }
17
+ return module;
18
+ }
19
+ import { publicToAddress } from "@ethereumjs/util";
20
+ import { CryptoAccount, CryptoHDKey, URRegistryDecoder } from "@keystonehq/bc-ur-registry-eth";
21
+ import { add0x, getChecksumAddress } from "@metamask/utils";
22
+ // eslint-disable-next-line @typescript-eslint/naming-convention
23
+ import $HdKey from "hdkey";
24
+ const HdKey = $importDefault($HdKey);
25
+ export const SUPPORTED_UR_TYPE = {
26
+ CRYPTO_HDKEY: 'crypto-hdkey',
27
+ CRYPTO_ACCOUNT: 'crypto-account',
28
+ ETH_SIGNATURE: 'eth-signature',
29
+ };
30
+ export var KeyringMode;
31
+ (function (KeyringMode) {
32
+ KeyringMode["HD"] = "hd";
33
+ KeyringMode["ACCOUNT"] = "account";
34
+ })(KeyringMode || (KeyringMode = {}));
35
+ const DEFAULT_CHILDREN_PATH = '0/*';
36
+ const MAX_INDEX = 1000;
37
+ /**
38
+ * Get the fingerprint of the source CryptoAccount or CryptoHDKey
39
+ *
40
+ * @param source - The source CryptoAccount or CryptoHDKey
41
+ * @returns The fingerprint of the source
42
+ */
43
+ function getFingerprintFromSource(source) {
44
+ return source instanceof CryptoAccount
45
+ ? source.getMasterFingerprint()?.toString('hex')
46
+ : source.getParentFingerprint()?.toString('hex');
47
+ }
48
+ /**
49
+ * Get fingerprint, account paths and names from the a CryptoAccount
50
+ *
51
+ * Note: This function emulates the behavior of the `@keystonehq/base-eth-keyring`
52
+ * library when dealing with CryptoAccount objects (for backwards compatibility
53
+ * reasons). Though, the way it retrieves `name` and `keyringAccount` is questionable,
54
+ * as `name` and `keyringAccount` are updated after each descriptor discovery, effectively
55
+ * returning the last descriptor's `name` and `keyringAccount`.
56
+ *
57
+ * @param source - The source CryptoAccount
58
+ * @returns The paths
59
+ */
60
+ function readCryptoAccountOutputDescriptors(source) {
61
+ const descriptors = source.getOutputDescriptors();
62
+ if (!descriptors || descriptors.length === 0) {
63
+ throw new Error('No output descriptors found in CryptoAccount');
64
+ }
65
+ let name = '';
66
+ let keyringAccount = '';
67
+ const paths = descriptors.reduce((descriptorsPaths, current) => {
68
+ const hdKey = current.getHDKey();
69
+ if (hdKey) {
70
+ const path = `M/${hdKey.getOrigin().getPath()}`;
71
+ const address = getChecksumAddress(add0x(Buffer.from(publicToAddress(hdKey.getKey(), true)).toString('hex')));
72
+ descriptorsPaths[address] = path;
73
+ name = hdKey.getName();
74
+ keyringAccount = hdKey.getNote();
75
+ }
76
+ return descriptorsPaths;
77
+ }, {});
78
+ return {
79
+ paths,
80
+ name,
81
+ keyringAccount,
82
+ xfp: getFingerprintFromSource(source),
83
+ };
84
+ }
85
+ export class AirgappedSigner {
86
+ constructor() {
87
+ _AirgappedSigner_instances.add(this);
88
+ _AirgappedSigner_source.set(this, void 0);
89
+ }
90
+ /**
91
+ * Initialize the AirgappedSigner with a source.
92
+ *
93
+ * @param source - The signer source, in the form of details object, or a UR string
94
+ */
95
+ init(source) {
96
+ if (typeof source === 'string') {
97
+ __classPrivateFieldGet(this, _AirgappedSigner_instances, "m", _AirgappedSigner_initFromUR).call(this, source);
98
+ }
99
+ else {
100
+ __classPrivateFieldSet(this, _AirgappedSigner_source, source, "f");
101
+ }
102
+ }
103
+ /**
104
+ * Check if the AirgappedSigner is initialized
105
+ *
106
+ * @returns True if the AirgappedSigner is initialized, false otherwise
107
+ */
108
+ isInitialized() {
109
+ return __classPrivateFieldGet(this, _AirgappedSigner_source, "f") !== undefined;
110
+ }
111
+ /**
112
+ * Derive an address from the source at a given index
113
+ *
114
+ * @param index - The index to derive the address from
115
+ * @returns The derived address in hex format
116
+ * @throws Will throw an error if the source is not initialized
117
+ */
118
+ addressFromIndex(index) {
119
+ if (!__classPrivateFieldGet(this, _AirgappedSigner_source, "f")) {
120
+ throw new Error('UR not initialized');
121
+ }
122
+ if (__classPrivateFieldGet(this, _AirgappedSigner_source, "f").keyringMode === KeyringMode.ACCOUNT) {
123
+ const address = Object.keys(__classPrivateFieldGet(this, _AirgappedSigner_source, "f").paths)[index];
124
+ if (!address) {
125
+ throw new Error(`Address not found for index ${index}`);
126
+ }
127
+ return add0x(address);
128
+ }
129
+ const childPath = `m/${__classPrivateFieldGet(this, _AirgappedSigner_source, "f").childrenPath.replace('*', index.toString())}`;
130
+ const hdKey = HdKey.fromExtendedKey(__classPrivateFieldGet(this, _AirgappedSigner_source, "f").xpub);
131
+ const childKey = hdKey.derive(childPath);
132
+ const address = Buffer.from(publicToAddress(childKey.publicKey, true)).toString('hex');
133
+ const normalizedAddress = getChecksumAddress(add0x(address));
134
+ __classPrivateFieldGet(this, _AirgappedSigner_source, "f").indexes[normalizedAddress] = index;
135
+ return normalizedAddress;
136
+ }
137
+ /**
138
+ * Retrieve the index of an address from the source
139
+ *
140
+ * @param address - The normalized address to retrieve the index for
141
+ * @returns The index of the address
142
+ */
143
+ indexFromAddress(address) {
144
+ if (!__classPrivateFieldGet(this, _AirgappedSigner_source, "f")) {
145
+ throw new Error('UR not initialized');
146
+ }
147
+ const cachedIndex = __classPrivateFieldGet(this, _AirgappedSigner_source, "f").indexes[address];
148
+ if (cachedIndex !== undefined) {
149
+ return Number(cachedIndex);
150
+ }
151
+ if (__classPrivateFieldGet(this, _AirgappedSigner_source, "f").keyringMode === KeyringMode.ACCOUNT) {
152
+ const path = __classPrivateFieldGet(this, _AirgappedSigner_source, "f").paths[address];
153
+ if (path === undefined) {
154
+ throw new Error(`Unknown address`);
155
+ }
156
+ const index = path.split('/').pop();
157
+ if (index === undefined) {
158
+ throw new Error(`Invalid path for address ${address}`);
159
+ }
160
+ return Number(index);
161
+ }
162
+ for (let i = 0; i < MAX_INDEX; i++) {
163
+ const derivedAddress = this.addressFromIndex(i);
164
+ if (derivedAddress === address) {
165
+ return i;
166
+ }
167
+ }
168
+ throw new Error(`Address ${address} not found`);
169
+ }
170
+ /**
171
+ * Get a page of addresses derived from the source.
172
+ *
173
+ * @param page - The page number to retrieve
174
+ * @param pageSize - The number of addresses per page
175
+ * @returns An array of IndexedAddress objects, each containing the address and its index
176
+ * @throws Will throw an error if the source is not initialized
177
+ */
178
+ getAddressesPage(page, pageSize = 5) {
179
+ const startIndex = page * pageSize;
180
+ const endIndex = startIndex + pageSize;
181
+ const addresses = [];
182
+ for (let i = startIndex; i < endIndex; i++) {
183
+ const address = this.addressFromIndex(i);
184
+ addresses.push({ address, index: i });
185
+ }
186
+ return addresses;
187
+ }
188
+ /**
189
+ * Gets the source details of the AirgappedSigner.
190
+ *
191
+ * @returns The source details, or undefined if not initialized
192
+ */
193
+ getSourceDetails() {
194
+ return __classPrivateFieldGet(this, _AirgappedSigner_source, "f");
195
+ }
196
+ /**
197
+ * Clear the source details.
198
+ */
199
+ clear() {
200
+ __classPrivateFieldSet(this, _AirgappedSigner_source, undefined, "f");
201
+ }
202
+ }
203
+ _AirgappedSigner_source = new WeakMap(), _AirgappedSigner_instances = new WeakSet(), _AirgappedSigner_initFromUR = function _AirgappedSigner_initFromUR(ur) {
204
+ const source = __classPrivateFieldGet(this, _AirgappedSigner_instances, "m", _AirgappedSigner_decodeUR).call(this, ur);
205
+ const fingerprint = getFingerprintFromSource(source);
206
+ if (source instanceof CryptoAccount) {
207
+ const { name, xfp, paths, keyringAccount } = readCryptoAccountOutputDescriptors(source);
208
+ __classPrivateFieldSet(this, _AirgappedSigner_source, {
209
+ keyringMode: KeyringMode.ACCOUNT,
210
+ keyringAccount,
211
+ name,
212
+ xfp,
213
+ paths,
214
+ indexes: {},
215
+ }, "f");
216
+ }
217
+ else {
218
+ const { getBip32Key, getOrigin, getChildren, getName, getNote } = source;
219
+ __classPrivateFieldSet(this, _AirgappedSigner_source, {
220
+ keyringMode: KeyringMode.HD,
221
+ keyringAccount: getNote(),
222
+ name: getName(),
223
+ xfp: fingerprint,
224
+ hdPath: `m/${getOrigin().getPath()}`,
225
+ childrenPath: getChildren()?.getPath() || DEFAULT_CHILDREN_PATH,
226
+ xpub: getBip32Key(),
227
+ indexes: {},
228
+ }, "f");
229
+ }
230
+ }, _AirgappedSigner_decodeUR = function _AirgappedSigner_decodeUR(ur) {
231
+ const decodedUR = URRegistryDecoder.decode(ur);
232
+ const { cbor } = decodedUR;
233
+ switch (decodedUR.type) {
234
+ case SUPPORTED_UR_TYPE.CRYPTO_HDKEY:
235
+ return CryptoHDKey.fromCBOR(cbor);
236
+ case SUPPORTED_UR_TYPE.CRYPTO_ACCOUNT:
237
+ return CryptoAccount.fromCBOR(cbor);
238
+ default:
239
+ throw new Error('Unsupported UR type');
240
+ }
241
+ };
242
+ //# sourceMappingURL=airgapped-signer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"airgapped-signer.mjs","sourceRoot":"","sources":["../src/airgapped-signer.ts"],"names":[],"mappings":"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","sourcesContent":["import { publicToAddress } from '@ethereumjs/util';\nimport {\n CryptoAccount,\n CryptoHDKey,\n URRegistryDecoder,\n} from '@keystonehq/bc-ur-registry-eth';\nimport { add0x, getChecksumAddress, type Hex } from '@metamask/utils';\n// eslint-disable-next-line @typescript-eslint/naming-convention\nimport HdKey from 'hdkey';\n\nexport const SUPPORTED_UR_TYPE = {\n CRYPTO_HDKEY: 'crypto-hdkey',\n CRYPTO_ACCOUNT: 'crypto-account',\n ETH_SIGNATURE: 'eth-signature',\n};\n\nexport enum KeyringMode {\n HD = 'hd',\n ACCOUNT = 'account',\n}\n\nconst DEFAULT_CHILDREN_PATH = '0/*';\n\nconst MAX_INDEX = 1_000;\n\n/**\n * Common details for the signer source, which can be either a CryptoAccount or CryptoHDKey.\n */\nexport type CommonSignerDetails = {\n /**\n * Value take out from the device note field, if available.\n */\n keyringAccount: string;\n /**\n * The name of the device\n */\n name: string;\n /**\n * The device fingerprint, hex-encoded\n */\n xfp: string;\n /**\n * Indexes of the accounts derived from the device\n * in the form of a map from address to index\n */\n indexes: Record<Hex, number>;\n};\n\n/**\n * Details for the HD mode of the AirgappedSigner. This mode derives\n * accounts from a root public key (xpub) and a derivation path.\n */\nexport type HDModeSignerDetails = {\n /**\n * The keyring mode is HD, indicating that it derives accounts from a\n * root public key (xpub) and a derivation path.\n */\n keyringMode: KeyringMode.HD;\n /**\n * The xpub of the HD key\n */\n xpub: string;\n /**\n * The derivation path of the HD key\n */\n hdPath: string;\n /**\n * The path used to derive child accounts\n */\n childrenPath: string;\n};\n\n/**\n * Details for the Account mode of the AirgappedSigner. This mode derives\n * accounts from a set of addresses and their corresponding paths.\n */\nexport type AccountModeSignerDetails = {\n /**\n * The keyring mode is ACCOUNT, indicating that it derives accounts from\n * a set of addresses and their corresponding paths.\n */\n keyringMode: KeyringMode.ACCOUNT;\n /**\n * The derivation paths for each hex-encoded address in the device\n */\n paths: Record<Hex, string>;\n};\n\n/**\n * An address with its corresponding index.\n */\nexport type IndexedAddress = {\n address: Hex;\n index: number;\n};\n\n/**\n * The details of the source CryptoAccount or CryptoHDKey\n * that the AirgappedSigner uses to derive accounts.\n */\nexport type AirgappedSignerDetails = CommonSignerDetails &\n (HDModeSignerDetails | AccountModeSignerDetails);\n\n/**\n * Get the fingerprint of the source CryptoAccount or CryptoHDKey\n *\n * @param source - The source CryptoAccount or CryptoHDKey\n * @returns The fingerprint of the source\n */\nfunction getFingerprintFromSource(source: CryptoAccount | CryptoHDKey): string {\n return source instanceof CryptoAccount\n ? source.getMasterFingerprint()?.toString('hex')\n : source.getParentFingerprint()?.toString('hex');\n}\n\n/**\n * Get fingerprint, account paths and names from the a CryptoAccount\n *\n * Note: This function emulates the behavior of the `@keystonehq/base-eth-keyring`\n * library when dealing with CryptoAccount objects (for backwards compatibility\n * reasons). Though, the way it retrieves `name` and `keyringAccount` is questionable,\n * as `name` and `keyringAccount` are updated after each descriptor discovery, effectively\n * returning the last descriptor's `name` and `keyringAccount`.\n *\n * @param source - The source CryptoAccount\n * @returns The paths\n */\nfunction readCryptoAccountOutputDescriptors(source: CryptoAccount): {\n xfp: string;\n paths: Record<Hex, string>;\n name: string;\n keyringAccount: string;\n} {\n const descriptors = source.getOutputDescriptors();\n\n if (!descriptors || descriptors.length === 0) {\n throw new Error('No output descriptors found in CryptoAccount');\n }\n\n let name = '';\n let keyringAccount = '';\n const paths = descriptors.reduce(\n (descriptorsPaths: Record<Hex, string>, current) => {\n const hdKey = current.getHDKey();\n if (hdKey) {\n const path = `M/${hdKey.getOrigin().getPath()}`;\n const address = getChecksumAddress(\n add0x(\n Buffer.from(publicToAddress(hdKey.getKey(), true)).toString('hex'),\n ),\n );\n descriptorsPaths[address] = path;\n name = hdKey.getName();\n keyringAccount = hdKey.getNote();\n }\n return descriptorsPaths;\n },\n {},\n );\n\n return {\n paths,\n name,\n keyringAccount,\n xfp: getFingerprintFromSource(source),\n };\n}\n\nexport class AirgappedSigner {\n #source?: AirgappedSignerDetails | undefined;\n\n /**\n * Initialize the AirgappedSigner with a source.\n *\n * @param source - The signer source, in the form of details object, or a UR string\n */\n init(source: AirgappedSignerDetails | string): void {\n if (typeof source === 'string') {\n this.#initFromUR(source);\n } else {\n this.#source = source;\n }\n }\n\n /**\n * Check if the AirgappedSigner is initialized\n *\n * @returns True if the AirgappedSigner is initialized, false otherwise\n */\n isInitialized(): boolean {\n return this.#source !== undefined;\n }\n\n /**\n * Derive an address from the source at a given index\n *\n * @param index - The index to derive the address from\n * @returns The derived address in hex format\n * @throws Will throw an error if the source is not initialized\n */\n addressFromIndex(index: number): Hex {\n if (!this.#source) {\n throw new Error('UR not initialized');\n }\n\n if (this.#source.keyringMode === KeyringMode.ACCOUNT) {\n const address = Object.keys(this.#source.paths)[index];\n if (!address) {\n throw new Error(`Address not found for index ${index}`);\n }\n return add0x(address);\n }\n const childPath = `m/${this.#source.childrenPath.replace(\n '*',\n index.toString(),\n )}`;\n\n const hdKey = HdKey.fromExtendedKey(this.#source.xpub);\n const childKey = hdKey.derive(childPath);\n\n const address = Buffer.from(\n publicToAddress(childKey.publicKey, true),\n ).toString('hex');\n\n const normalizedAddress = getChecksumAddress(add0x(address));\n\n this.#source.indexes[normalizedAddress] = index;\n\n return normalizedAddress;\n }\n\n /**\n * Retrieve the index of an address from the source\n *\n * @param address - The normalized address to retrieve the index for\n * @returns The index of the address\n */\n indexFromAddress(address: Hex): number {\n if (!this.#source) {\n throw new Error('UR not initialized');\n }\n\n const cachedIndex = this.#source.indexes[address];\n if (cachedIndex !== undefined) {\n return Number(cachedIndex);\n }\n\n if (this.#source.keyringMode === KeyringMode.ACCOUNT) {\n const path = this.#source.paths[address];\n if (path === undefined) {\n throw new Error(`Unknown address`);\n }\n\n const index = path.split('/').pop();\n if (index === undefined) {\n throw new Error(`Invalid path for address ${address}`);\n }\n\n return Number(index);\n }\n\n for (let i = 0; i < MAX_INDEX; i++) {\n const derivedAddress = this.addressFromIndex(i);\n if (derivedAddress === address) {\n return i;\n }\n }\n\n throw new Error(`Address ${address} not found`);\n }\n\n /**\n * Get a page of addresses derived from the source.\n *\n * @param page - The page number to retrieve\n * @param pageSize - The number of addresses per page\n * @returns An array of IndexedAddress objects, each containing the address and its index\n * @throws Will throw an error if the source is not initialized\n */\n getAddressesPage(page: number, pageSize = 5): IndexedAddress[] {\n const startIndex = page * pageSize;\n const endIndex = startIndex + pageSize;\n const addresses: IndexedAddress[] = [];\n\n for (let i = startIndex; i < endIndex; i++) {\n const address = this.addressFromIndex(i);\n addresses.push({ address, index: i });\n }\n\n return addresses;\n }\n\n /**\n * Gets the source details of the AirgappedSigner.\n *\n * @returns The source details, or undefined if not initialized\n */\n getSourceDetails(): AirgappedSignerDetails | undefined {\n return this.#source;\n }\n\n /**\n * Clear the source details.\n */\n clear(): void {\n this.#source = undefined;\n }\n\n /**\n * Set the root account from a UR string\n *\n * @param ur - The UR string to set the root account from\n */\n #initFromUR(ur: string): void {\n const source = this.#decodeUR(ur);\n const fingerprint = getFingerprintFromSource(source);\n\n if (source instanceof CryptoAccount) {\n const { name, xfp, paths, keyringAccount } =\n readCryptoAccountOutputDescriptors(source);\n this.#source = {\n keyringMode: KeyringMode.ACCOUNT,\n keyringAccount,\n name,\n xfp,\n paths,\n indexes: {},\n };\n } else {\n const { getBip32Key, getOrigin, getChildren, getName, getNote } = source;\n this.#source = {\n keyringMode: KeyringMode.HD,\n keyringAccount: getNote(),\n name: getName(),\n xfp: fingerprint,\n hdPath: `m/${getOrigin().getPath()}`,\n childrenPath: getChildren()?.getPath() || DEFAULT_CHILDREN_PATH,\n xpub: getBip32Key(),\n indexes: {},\n };\n }\n }\n\n /**\n * Decodes a UR\n *\n * @param ur - The UR to decode\n * @returns The decoded CryptoAccount or CryptoHDKey\n * @throws Will throw an error if the UR type is not supported\n */\n #decodeUR(ur: string): CryptoAccount | CryptoHDKey {\n const decodedUR = URRegistryDecoder.decode(ur);\n\n const { cbor } = decodedUR;\n\n switch (decodedUR.type) {\n case SUPPORTED_UR_TYPE.CRYPTO_HDKEY:\n return CryptoHDKey.fromCBOR(cbor);\n case SUPPORTED_UR_TYPE.CRYPTO_ACCOUNT:\n return CryptoAccount.fromCBOR(cbor);\n default:\n throw new Error('Unsupported UR type');\n }\n }\n}\n"]}
package/dist/index.cjs ADDED
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./qr-keyring-bridge.cjs"), exports);
18
+ __exportStar(require("./qr-keyring.cjs"), exports);
19
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAoC;AACpC,mDAA6B","sourcesContent":["export * from './qr-keyring-bridge';\nexport * from './qr-keyring';\n"]}
@@ -0,0 +1,3 @@
1
+ export * from "./qr-keyring-bridge.cjs";
2
+ export * from "./qr-keyring.cjs";
3
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAoC;AACpC,iCAA6B"}
@@ -0,0 +1,3 @@
1
+ export * from "./qr-keyring-bridge.mjs";
2
+ export * from "./qr-keyring.mjs";
3
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAoC;AACpC,iCAA6B"}
package/dist/index.mjs ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./qr-keyring-bridge.mjs";
2
+ export * from "./qr-keyring.mjs";
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAoC;AACpC,iCAA6B","sourcesContent":["export * from './qr-keyring-bridge';\nexport * from './qr-keyring';\n"]}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _QrKeyringScannerBridge_requestScan;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.QrKeyringScannerBridge = void 0;
16
+ /**
17
+ * A bridge that allows the QrKeyring to request a QR code scan
18
+ * while keeping the implementation defined by the QrKeyring consumer.
19
+ */
20
+ class QrKeyringScannerBridge {
21
+ constructor({ requestScan }) {
22
+ _QrKeyringScannerBridge_requestScan.set(this, void 0);
23
+ __classPrivateFieldSet(this, _QrKeyringScannerBridge_requestScan, requestScan, "f");
24
+ }
25
+ /**
26
+ * Requests a QR code scan and returns the scanned data.
27
+ *
28
+ * @returns The scanned data as a string.
29
+ */
30
+ async requestScan() {
31
+ return __classPrivateFieldGet(this, _QrKeyringScannerBridge_requestScan, "f").call(this);
32
+ }
33
+ }
34
+ exports.QrKeyringScannerBridge = QrKeyringScannerBridge;
35
+ _QrKeyringScannerBridge_requestScan = new WeakMap();
36
+ //# sourceMappingURL=qr-keyring-bridge.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr-keyring-bridge.cjs","sourceRoot":"","sources":["../src/qr-keyring-bridge.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAYA;;;GAGG;AACH,MAAa,sBAAsB;IAGjC,YAAY,EAAE,WAAW,EAAiC;QAFjD,sDAAoC;QAG3C,uBAAA,IAAI,uCAAgB,WAAW,MAAA,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW;QACf,OAAO,uBAAA,IAAI,2CAAa,MAAjB,IAAI,CAAe,CAAC;IAC7B,CAAC;CACF;AAfD,wDAeC","sourcesContent":["import type { QrKeyringBridge } from './qr-keyring';\n\n/**\n * Options for the QrKeyringScannerBridge.\n */\nexport type QrKeyringScannerBridgeOptions = {\n /**\n * An injected function that the bridge uses to request a QR code scan.\n */\n requestScan: () => Promise<string>;\n};\n\n/**\n * A bridge that allows the QrKeyring to request a QR code scan\n * while keeping the implementation defined by the QrKeyring consumer.\n */\nexport class QrKeyringScannerBridge implements QrKeyringBridge {\n readonly #requestScan: () => Promise<string>;\n\n constructor({ requestScan }: QrKeyringScannerBridgeOptions) {\n this.#requestScan = requestScan;\n }\n\n /**\n * Requests a QR code scan and returns the scanned data.\n *\n * @returns The scanned data as a string.\n */\n async requestScan(): Promise<string> {\n return this.#requestScan();\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import type { QrKeyringBridge } from "./qr-keyring.cjs";
2
+ /**
3
+ * Options for the QrKeyringScannerBridge.
4
+ */
5
+ export type QrKeyringScannerBridgeOptions = {
6
+ /**
7
+ * An injected function that the bridge uses to request a QR code scan.
8
+ */
9
+ requestScan: () => Promise<string>;
10
+ };
11
+ /**
12
+ * A bridge that allows the QrKeyring to request a QR code scan
13
+ * while keeping the implementation defined by the QrKeyring consumer.
14
+ */
15
+ export declare class QrKeyringScannerBridge implements QrKeyringBridge {
16
+ #private;
17
+ constructor({ requestScan }: QrKeyringScannerBridgeOptions);
18
+ /**
19
+ * Requests a QR code scan and returns the scanned data.
20
+ *
21
+ * @returns The scanned data as a string.
22
+ */
23
+ requestScan(): Promise<string>;
24
+ }
25
+ //# sourceMappingURL=qr-keyring-bridge.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr-keyring-bridge.d.cts","sourceRoot":"","sources":["../src/qr-keyring-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,yBAAqB;AAEpD;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C;;OAEG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACpC,CAAC;AAEF;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,eAAe;;gBAGhD,EAAE,WAAW,EAAE,EAAE,6BAA6B;IAI1D;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;CAGrC"}
@@ -0,0 +1,25 @@
1
+ import type { QrKeyringBridge } from "./qr-keyring.mjs";
2
+ /**
3
+ * Options for the QrKeyringScannerBridge.
4
+ */
5
+ export type QrKeyringScannerBridgeOptions = {
6
+ /**
7
+ * An injected function that the bridge uses to request a QR code scan.
8
+ */
9
+ requestScan: () => Promise<string>;
10
+ };
11
+ /**
12
+ * A bridge that allows the QrKeyring to request a QR code scan
13
+ * while keeping the implementation defined by the QrKeyring consumer.
14
+ */
15
+ export declare class QrKeyringScannerBridge implements QrKeyringBridge {
16
+ #private;
17
+ constructor({ requestScan }: QrKeyringScannerBridgeOptions);
18
+ /**
19
+ * Requests a QR code scan and returns the scanned data.
20
+ *
21
+ * @returns The scanned data as a string.
22
+ */
23
+ requestScan(): Promise<string>;
24
+ }
25
+ //# sourceMappingURL=qr-keyring-bridge.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr-keyring-bridge.d.mts","sourceRoot":"","sources":["../src/qr-keyring-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,yBAAqB;AAEpD;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C;;OAEG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACpC,CAAC;AAEF;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,eAAe;;gBAGhD,EAAE,WAAW,EAAE,EAAE,6BAA6B;IAI1D;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;CAGrC"}
@@ -0,0 +1,32 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _QrKeyringScannerBridge_requestScan;
13
+ /**
14
+ * A bridge that allows the QrKeyring to request a QR code scan
15
+ * while keeping the implementation defined by the QrKeyring consumer.
16
+ */
17
+ export class QrKeyringScannerBridge {
18
+ constructor({ requestScan }) {
19
+ _QrKeyringScannerBridge_requestScan.set(this, void 0);
20
+ __classPrivateFieldSet(this, _QrKeyringScannerBridge_requestScan, requestScan, "f");
21
+ }
22
+ /**
23
+ * Requests a QR code scan and returns the scanned data.
24
+ *
25
+ * @returns The scanned data as a string.
26
+ */
27
+ async requestScan() {
28
+ return __classPrivateFieldGet(this, _QrKeyringScannerBridge_requestScan, "f").call(this);
29
+ }
30
+ }
31
+ _QrKeyringScannerBridge_requestScan = new WeakMap();
32
+ //# sourceMappingURL=qr-keyring-bridge.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr-keyring-bridge.mjs","sourceRoot":"","sources":["../src/qr-keyring-bridge.ts"],"names":[],"mappings":";;;;;;;;;;;;AAYA;;;GAGG;AACH,MAAM,OAAO,sBAAsB;IAGjC,YAAY,EAAE,WAAW,EAAiC;QAFjD,sDAAoC;QAG3C,uBAAA,IAAI,uCAAgB,WAAW,MAAA,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW;QACf,OAAO,uBAAA,IAAI,2CAAa,MAAjB,IAAI,CAAe,CAAC;IAC7B,CAAC;CACF","sourcesContent":["import type { QrKeyringBridge } from './qr-keyring';\n\n/**\n * Options for the QrKeyringScannerBridge.\n */\nexport type QrKeyringScannerBridgeOptions = {\n /**\n * An injected function that the bridge uses to request a QR code scan.\n */\n requestScan: () => Promise<string>;\n};\n\n/**\n * A bridge that allows the QrKeyring to request a QR code scan\n * while keeping the implementation defined by the QrKeyring consumer.\n */\nexport class QrKeyringScannerBridge implements QrKeyringBridge {\n readonly #requestScan: () => Promise<string>;\n\n constructor({ requestScan }: QrKeyringScannerBridgeOptions) {\n this.#requestScan = requestScan;\n }\n\n /**\n * Requests a QR code scan and returns the scanned data.\n *\n * @returns The scanned data as a string.\n */\n async requestScan(): Promise<string> {\n return this.#requestScan();\n }\n}\n"]}