@metamask-previews/eth-qr-keyring 1.0.0-e4f6caa → 1.1.0-9fbf2ff

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 (48) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/dist/device.cjs +345 -0
  3. package/dist/device.cjs.map +1 -0
  4. package/dist/device.d.cts +175 -0
  5. package/dist/device.d.cts.map +1 -0
  6. package/dist/device.d.mts +175 -0
  7. package/dist/device.d.mts.map +1 -0
  8. package/dist/device.mjs +345 -0
  9. package/dist/device.mjs.map +1 -0
  10. package/dist/index.cjs +9 -16
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +3 -2
  13. package/dist/index.d.cts.map +1 -1
  14. package/dist/index.d.mts +3 -2
  15. package/dist/index.d.mts.map +1 -1
  16. package/dist/index.mjs +3 -2
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/qr-keyring-deferred-promise-bridge.cjs +76 -0
  19. package/dist/qr-keyring-deferred-promise-bridge.cjs.map +1 -0
  20. package/dist/qr-keyring-deferred-promise-bridge.d.cts +46 -0
  21. package/dist/qr-keyring-deferred-promise-bridge.d.cts.map +1 -0
  22. package/dist/qr-keyring-deferred-promise-bridge.d.mts +46 -0
  23. package/dist/qr-keyring-deferred-promise-bridge.d.mts.map +1 -0
  24. package/dist/qr-keyring-deferred-promise-bridge.mjs +72 -0
  25. package/dist/qr-keyring-deferred-promise-bridge.mjs.map +1 -0
  26. package/dist/qr-keyring-scanner-bridge.cjs +2 -2
  27. package/dist/qr-keyring-scanner-bridge.cjs.map +1 -1
  28. package/dist/qr-keyring-scanner-bridge.d.cts +3 -3
  29. package/dist/qr-keyring-scanner-bridge.d.mts +3 -3
  30. package/dist/qr-keyring-scanner-bridge.mjs +2 -2
  31. package/dist/qr-keyring-scanner-bridge.mjs.map +1 -1
  32. package/dist/qr-keyring.cjs +65 -137
  33. package/dist/qr-keyring.cjs.map +1 -1
  34. package/dist/qr-keyring.d.cts +17 -4
  35. package/dist/qr-keyring.d.cts.map +1 -1
  36. package/dist/qr-keyring.d.mts +17 -4
  37. package/dist/qr-keyring.d.mts.map +1 -1
  38. package/dist/qr-keyring.mjs +66 -138
  39. package/dist/qr-keyring.mjs.map +1 -1
  40. package/package.json +6 -5
  41. package/dist/airgapped-signer.cjs +0 -270
  42. package/dist/airgapped-signer.cjs.map +0 -1
  43. package/dist/airgapped-signer.d.cts +0 -140
  44. package/dist/airgapped-signer.d.cts.map +0 -1
  45. package/dist/airgapped-signer.d.mts +0 -140
  46. package/dist/airgapped-signer.d.mts.map +0 -1
  47. package/dist/airgapped-signer.mjs +0 -270
  48. package/dist/airgapped-signer.mjs.map +0 -1
@@ -10,18 +10,12 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
10
10
  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");
11
11
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
12
  };
13
- var _QrKeyring_instances, _QrKeyring_signer, _QrKeyring_accounts, _QrKeyring_accountToUnlock, _QrKeyring_currentPage, _QrKeyring_scanAndInitialize, _QrKeyring_requestSignature;
13
+ var _QrKeyring_instances, _QrKeyring_device, _QrKeyring_accounts, _QrKeyring_accountToUnlock, _QrKeyring_currentPage, _QrKeyring_scanAndInitialize;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.QrKeyring = exports.getDefaultSerializedQrKeyringState = exports.QrScanRequestType = exports.QR_KEYRING_TYPE = void 0;
16
- const rlp_1 = require("@ethereumjs/rlp");
17
- const tx_1 = require("@ethereumjs/tx");
18
- const bc_ur_registry_eth_1 = require("@keystonehq/bc-ur-registry-eth");
19
16
  const utils_1 = require("@metamask/utils");
20
- const uuid_1 = require("uuid");
21
- const airgapped_signer_1 = require("./airgapped-signer.cjs");
17
+ const device_1 = require("./device.cjs");
22
18
  exports.QR_KEYRING_TYPE = 'QR Hardware Wallet Device';
23
- const DEFAULT_SCAN_REQUEST_TITLE = 'Scan with your hardware wallet';
24
- const DEFAULT_SCAN_REQUEST_DESCRIPTION = 'After your device has scanned this QR code, click on "Scan" to receive the information.';
25
19
  var QrScanRequestType;
26
20
  (function (QrScanRequestType) {
27
21
  /**
@@ -58,13 +52,13 @@ class QrKeyring {
58
52
  constructor(options) {
59
53
  _QrKeyring_instances.add(this);
60
54
  this.type = exports.QR_KEYRING_TYPE;
61
- _QrKeyring_signer.set(this, new airgapped_signer_1.AirgappedSigner());
55
+ _QrKeyring_device.set(this, void 0);
62
56
  _QrKeyring_accounts.set(this, []);
63
57
  _QrKeyring_accountToUnlock.set(this, void 0);
64
58
  _QrKeyring_currentPage.set(this, 0);
65
59
  this.bridge = options.bridge;
66
60
  if (options?.ur) {
67
- this.submitUR(options.ur);
61
+ this.pairDevice(options.ur);
68
62
  }
69
63
  }
70
64
  /**
@@ -73,38 +67,18 @@ class QrKeyring {
73
67
  * @returns The serialized state
74
68
  */
75
69
  async serialize() {
76
- const source = __classPrivateFieldGet(this, _QrKeyring_signer, "f").getSourceDetails();
77
- if (!source ||
78
- ![airgapped_signer_1.KeyringMode.HD, airgapped_signer_1.KeyringMode.ACCOUNT].includes(source.keyringMode)) {
79
- // the keyring has not initialized with a device source yet
70
+ const deviceDetails = __classPrivateFieldGet(this, _QrKeyring_device, "f")
71
+ ? __classPrivateFieldGet(this, _QrKeyring_device, "f").getDeviceDetails()
72
+ : undefined;
73
+ if (!deviceDetails ||
74
+ ![device_1.DeviceMode.HD, device_1.DeviceMode.ACCOUNT].includes(deviceDetails.keyringMode)) {
75
+ // the keyring has not initialized with a deviceDetails device yet
80
76
  return (0, exports.getDefaultSerializedQrKeyringState)();
81
77
  }
82
- const accounts = __classPrivateFieldGet(this, _QrKeyring_accounts, "f").slice();
83
- if (source.keyringMode === airgapped_signer_1.KeyringMode.HD) {
84
- // These properties are only relevant for HD Keys
85
- return {
86
- initialized: true,
87
- name: source.name,
88
- keyringMode: airgapped_signer_1.KeyringMode.HD,
89
- keyringAccount: source.keyringAccount,
90
- xfp: source.xfp,
91
- xpub: source.xpub,
92
- hdPath: source.hdPath,
93
- childrenPath: source.childrenPath,
94
- accounts,
95
- indexes: source.indexes,
96
- };
97
- }
98
- // These properties are only relevant for Account Keys
99
78
  return {
79
+ ...deviceDetails,
100
80
  initialized: true,
101
- name: source.name,
102
- keyringMode: airgapped_signer_1.KeyringMode.ACCOUNT,
103
- keyringAccount: source.keyringAccount,
104
- xfp: source.xfp,
105
- paths: source.paths,
106
- accounts,
107
- indexes: source.indexes,
81
+ accounts: __classPrivateFieldGet(this, _QrKeyring_accounts, "f").slice(),
108
82
  };
109
83
  }
110
84
  /**
@@ -115,10 +89,13 @@ class QrKeyring {
115
89
  async deserialize(state) {
116
90
  if (!state.initialized) {
117
91
  __classPrivateFieldSet(this, _QrKeyring_accounts, [], "f");
118
- __classPrivateFieldGet(this, _QrKeyring_signer, "f").clear();
92
+ __classPrivateFieldSet(this, _QrKeyring_device, undefined, "f");
119
93
  return;
120
94
  }
121
- __classPrivateFieldGet(this, _QrKeyring_signer, "f").init(state);
95
+ __classPrivateFieldSet(this, _QrKeyring_device, new device_1.Device({
96
+ requestScan: this.bridge.requestScan.bind(this.bridge),
97
+ source: state,
98
+ }), "f");
122
99
  __classPrivateFieldSet(this, _QrKeyring_accounts, (state.accounts ?? []).map(normalizeAddress), "f");
123
100
  }
124
101
  /**
@@ -128,20 +105,20 @@ class QrKeyring {
128
105
  * @returns The accounts added
129
106
  */
130
107
  async addAccounts(accountsToAdd) {
131
- const lastAccount = __classPrivateFieldGet(this, _QrKeyring_accounts, "f")[__classPrivateFieldGet(this, _QrKeyring_accounts, "f").length - 1];
132
- const startIndex = __classPrivateFieldGet(this, _QrKeyring_accountToUnlock, "f") ??
133
- (lastAccount ? __classPrivateFieldGet(this, _QrKeyring_signer, "f").indexFromAddress(lastAccount) : 0);
108
+ if (!__classPrivateFieldGet(this, _QrKeyring_device, "f")) {
109
+ throw new Error('No device paired.');
110
+ }
134
111
  const newAccounts = [];
135
112
  for (let i = 0; i < accountsToAdd; i++) {
136
- const index = startIndex + i;
137
- const address = __classPrivateFieldGet(this, _QrKeyring_signer, "f").addressFromIndex(index);
113
+ const index = __classPrivateFieldGet(this, _QrKeyring_accountToUnlock, "f") ?? __classPrivateFieldGet(this, _QrKeyring_accounts, "f").length + i;
114
+ const address = __classPrivateFieldGet(this, _QrKeyring_device, "f").addressFromIndex(index);
115
+ this.setAccountToUnlock(index + 1);
138
116
  if (__classPrivateFieldGet(this, _QrKeyring_accounts, "f").includes(address)) {
139
117
  continue;
140
118
  }
141
119
  __classPrivateFieldGet(this, _QrKeyring_accounts, "f").push(address);
142
120
  newAccounts.push(address);
143
121
  }
144
- __classPrivateFieldSet(this, _QrKeyring_accountToUnlock, startIndex + accountsToAdd, "f");
145
122
  return newAccounts;
146
123
  }
147
124
  /**
@@ -150,7 +127,7 @@ class QrKeyring {
150
127
  * @returns The accounts in the QrKeyring
151
128
  */
152
129
  async getAccounts() {
153
- return Array.from(__classPrivateFieldGet(this, _QrKeyring_accounts, "f").values());
130
+ return __classPrivateFieldGet(this, _QrKeyring_accounts, "f").slice();
154
131
  }
155
132
  /**
156
133
  * Remove an account from the keyring
@@ -162,12 +139,15 @@ class QrKeyring {
162
139
  __classPrivateFieldSet(this, _QrKeyring_accounts, __classPrivateFieldGet(this, _QrKeyring_accounts, "f").filter((account) => account !== normalizedAddress), "f");
163
140
  }
164
141
  /**
165
- * Submits a CBOR encoded UR to the QrKeyring
142
+ * Pair a QR-based Hardware Device from a CBOR encoded UR to the QrKeyring
166
143
  *
167
144
  * @param ur - The CBOR encoded UR
168
145
  */
169
- submitUR(ur) {
170
- __classPrivateFieldGet(this, _QrKeyring_signer, "f").init(ur);
146
+ pairDevice(ur) {
147
+ __classPrivateFieldSet(this, _QrKeyring_device, new device_1.Device({
148
+ requestScan: this.bridge.requestScan.bind(this.bridge),
149
+ source: ur,
150
+ }), "f");
171
151
  }
172
152
  /**
173
153
  * Sets the next account index to unlock
@@ -184,8 +164,11 @@ class QrKeyring {
184
164
  * @returns The name of the paired device or the keyring type.
185
165
  */
186
166
  getName() {
187
- const source = __classPrivateFieldGet(this, _QrKeyring_signer, "f").getSourceDetails();
188
- return source?.name ?? exports.QR_KEYRING_TYPE;
167
+ if (!__classPrivateFieldGet(this, _QrKeyring_device, "f")) {
168
+ return exports.QR_KEYRING_TYPE;
169
+ }
170
+ const source = __classPrivateFieldGet(this, _QrKeyring_device, "f").getDeviceDetails();
171
+ return source.name;
189
172
  }
190
173
  /**
191
174
  * Fetch the first page of accounts. If the keyring is not currently initialized,
@@ -229,16 +212,17 @@ class QrKeyring {
229
212
  * @returns The current page of accounts as an array of IndexedAddress objects.
230
213
  */
231
214
  async getCurrentPage() {
232
- if (!__classPrivateFieldGet(this, _QrKeyring_signer, "f").isInitialized()) {
215
+ if (!__classPrivateFieldGet(this, _QrKeyring_device, "f")) {
233
216
  await __classPrivateFieldGet(this, _QrKeyring_instances, "m", _QrKeyring_scanAndInitialize).call(this);
234
217
  }
235
- return __classPrivateFieldGet(this, _QrKeyring_signer, "f").getAddressesPage(__classPrivateFieldGet(this, _QrKeyring_currentPage, "f"));
218
+ (0, utils_1.assert)(__classPrivateFieldGet(this, _QrKeyring_device, "f"), 'A device is expected to be paired before fetching accounts.');
219
+ return __classPrivateFieldGet(this, _QrKeyring_device, "f").getAddressesPage(__classPrivateFieldGet(this, _QrKeyring_currentPage, "f"));
236
220
  }
237
221
  /**
238
222
  * Clear the keyring state and forget any paired device or accounts.
239
223
  */
240
224
  async forgetDevice() {
241
- __classPrivateFieldGet(this, _QrKeyring_signer, "f").clear();
225
+ __classPrivateFieldSet(this, _QrKeyring_device, undefined, "f");
242
226
  __classPrivateFieldSet(this, _QrKeyring_accounts, [], "f");
243
227
  __classPrivateFieldSet(this, _QrKeyring_accountToUnlock, undefined, "f");
244
228
  __classPrivateFieldSet(this, _QrKeyring_currentPage, 0, "f");
@@ -253,41 +237,10 @@ class QrKeyring {
253
237
  * @returns The signed transaction.
254
238
  */
255
239
  async signTransaction(address, transaction) {
256
- const signer = __classPrivateFieldGet(this, _QrKeyring_signer, "f").getSourceDetails();
257
- if (!signer?.xfp) {
258
- throw new Error('Keyring is not initialized. Please scan a QR code.');
259
- }
260
- const dataType = transaction.type === tx_1.TransactionType.Legacy
261
- ? bc_ur_registry_eth_1.DataType.transaction
262
- : bc_ur_registry_eth_1.DataType.typedTransaction;
263
- let messageToSign;
264
- if (transaction.type === tx_1.TransactionType.Legacy) {
265
- messageToSign = Buffer.from(rlp_1.RLP.encode(transaction.getMessageToSign()));
266
- }
267
- else {
268
- messageToSign = Buffer.from(transaction.getMessageToSign());
240
+ if (!__classPrivateFieldGet(this, _QrKeyring_device, "f")) {
241
+ throw new Error('No device paired.');
269
242
  }
270
- const hdPath = __classPrivateFieldGet(this, _QrKeyring_signer, "f").pathFromAddress(address);
271
- const chainId = Number(transaction.common.chainId());
272
- const requestId = (0, uuid_1.v4)();
273
- const ethSignRequestUR = bc_ur_registry_eth_1.EthSignRequest.constructETHRequest(messageToSign, dataType, hdPath, signer.xfp, requestId, chainId).toUR();
274
- const { r, s, v } = await __classPrivateFieldGet(this, _QrKeyring_instances, "m", _QrKeyring_requestSignature).call(this, {
275
- requestId,
276
- payload: {
277
- type: ethSignRequestUR.type,
278
- cbor: ethSignRequestUR.cbor.toString('hex'),
279
- },
280
- requestTitle: 'Scan with your hardware wallet',
281
- requestDescription: 'After your device has signed this message, click on "Scan" to receive the signature',
282
- });
283
- return tx_1.TransactionFactory.fromTxData({
284
- ...transaction,
285
- r,
286
- s,
287
- v,
288
- }, {
289
- common: transaction.common,
290
- });
243
+ return __classPrivateFieldGet(this, _QrKeyring_device, "f").signTransaction(address, transaction);
291
244
  }
292
245
  /**
293
246
  * Sign a message. This is equivalent to the `eth_signTypedData` v4 Ethereum
@@ -298,63 +251,38 @@ class QrKeyring {
298
251
  * @returns The signed message.
299
252
  */
300
253
  async signTypedData(address, data) {
301
- const signer = __classPrivateFieldGet(this, _QrKeyring_signer, "f").getSourceDetails();
302
- if (!signer?.xfp) {
303
- throw new Error('Keyring is not initialized. Please scan a QR code.');
254
+ if (!__classPrivateFieldGet(this, _QrKeyring_device, "f")) {
255
+ throw new Error('No device paired.');
304
256
  }
305
- const hdPath = __classPrivateFieldGet(this, _QrKeyring_signer, "f").pathFromAddress(address);
306
- const requestId = (0, uuid_1.v4)();
307
- const ethSignRequestUR = bc_ur_registry_eth_1.EthSignRequest.constructETHRequest(Buffer.from(JSON.stringify(data), 'utf8'), bc_ur_registry_eth_1.DataType.typedData, hdPath, signer.xfp, requestId, undefined, address).toUR();
308
- const { r, s, v } = await __classPrivateFieldGet(this, _QrKeyring_instances, "m", _QrKeyring_requestSignature).call(this, {
309
- requestId,
310
- payload: {
311
- type: ethSignRequestUR.type,
312
- cbor: ethSignRequestUR.cbor.toString('hex'),
313
- },
314
- requestTitle: DEFAULT_SCAN_REQUEST_TITLE,
315
- requestDescription: DEFAULT_SCAN_REQUEST_DESCRIPTION,
316
- });
317
- return (0, utils_1.add0x)(Buffer.concat([
318
- Uint8Array.from(r),
319
- Uint8Array.from(s),
320
- Uint8Array.from(v),
321
- ]).toString('hex'));
257
+ return __classPrivateFieldGet(this, _QrKeyring_device, "f").signTypedData(address, data);
258
+ }
259
+ /**
260
+ * Sign a message. This is equivalent to the `eth_sign` Ethereum JSON-RPC
261
+ * method, which is exposed by MetaMask as the method `personal_sign`. See
262
+ * the Ethereum JSON-RPC API documentation for more details.
263
+ *
264
+ * For more information about this method and why we call it `personal_sign`,
265
+ * see the {@link https://docs.metamask.io/guide/signing-data.html|MetaMask Docs}.
266
+ *
267
+ * @param address - The address of the account to use for signing.
268
+ * @param message - The message to sign.
269
+ * @returns The signed message.
270
+ */
271
+ async signPersonalMessage(address, message) {
272
+ if (!__classPrivateFieldGet(this, _QrKeyring_device, "f")) {
273
+ throw new Error('No device paired.');
274
+ }
275
+ return __classPrivateFieldGet(this, _QrKeyring_device, "f").signPersonalMessage(address, message);
322
276
  }
323
277
  }
324
278
  exports.QrKeyring = QrKeyring;
325
- _QrKeyring_signer = new WeakMap(), _QrKeyring_accounts = new WeakMap(), _QrKeyring_accountToUnlock = new WeakMap(), _QrKeyring_currentPage = new WeakMap(), _QrKeyring_instances = new WeakSet(), _QrKeyring_scanAndInitialize =
279
+ _QrKeyring_device = new WeakMap(), _QrKeyring_accounts = new WeakMap(), _QrKeyring_accountToUnlock = new WeakMap(), _QrKeyring_currentPage = new WeakMap(), _QrKeyring_instances = new WeakSet(), _QrKeyring_scanAndInitialize =
326
280
  /**
327
281
  * Scan for a QR code and initialize the keyring with the
328
282
  * scanned UR.
329
283
  */
330
284
  async function _QrKeyring_scanAndInitialize() {
331
- this.submitUR(await this.bridge.requestScan({ type: QrScanRequestType.PAIR }));
332
- }, _QrKeyring_requestSignature =
333
- /**
334
- * Request a signature for a transaction or message.
335
- *
336
- * @param request - The signature request containing the data to sign.
337
- * @returns The signature as an object containing r, s, and v values.
338
- */
339
- async function _QrKeyring_requestSignature(request) {
340
- const response = await this.bridge.requestScan({
341
- type: QrScanRequestType.SIGN,
342
- request,
343
- });
344
- const signatureEnvelope = bc_ur_registry_eth_1.ETHSignature.fromCBOR(Buffer.from(response.cbor, 'hex'));
345
- const signature = signatureEnvelope.getSignature();
346
- const requestId = signatureEnvelope.getRequestId();
347
- if (!requestId) {
348
- throw new Error('Signature request ID is missing.');
349
- }
350
- if (request.requestId !== (0, uuid_1.stringify)(requestId)) {
351
- throw new Error(`Signature request ID mismatch. Expected: ${request.requestId}, received: ${requestId.toString('hex')}`);
352
- }
353
- return {
354
- r: signature.subarray(0, 32),
355
- s: signature.subarray(32, 64),
356
- v: signature.subarray(64),
357
- };
285
+ this.pairDevice(await this.bridge.requestScan({ type: QrScanRequestType.PAIR }));
358
286
  };
359
287
  QrKeyring.type = exports.QR_KEYRING_TYPE;
360
288
  //# sourceMappingURL=qr-keyring.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"qr-keyring.cjs","sourceRoot":"","sources":["../src/qr-keyring.ts"],"names":[],"mappings":"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","sourcesContent":["import { RLP } from '@ethereumjs/rlp';\nimport {\n type FeeMarketEIP1559Transaction,\n TransactionFactory,\n TransactionType,\n type TypedTransaction,\n type TypedTxData,\n} from '@ethereumjs/tx';\nimport {\n DataType,\n ETHSignature,\n EthSignRequest,\n} from '@keystonehq/bc-ur-registry-eth';\nimport type { TypedMessage, MessageTypes } from '@metamask/eth-sig-util';\nimport type { Keyring } from '@metamask/keyring-utils';\nimport { type Hex, add0x, getChecksumAddress } from '@metamask/utils';\nimport { stringify, v4 as uuidv4 } from 'uuid';\n\nimport {\n type AirgappedSignerDetails,\n type IndexedAddress,\n AirgappedSigner,\n KeyringMode,\n} from './airgapped-signer';\n\nexport const QR_KEYRING_TYPE = 'QR Hardware Wallet Device';\n\nconst DEFAULT_SCAN_REQUEST_TITLE = 'Scan with your hardware wallet';\n\nconst DEFAULT_SCAN_REQUEST_DESCRIPTION =\n 'After your device has scanned this QR code, click on \"Scan\" to receive the information.';\n\nexport enum QrScanRequestType {\n /**\n * Request a scan for a QR code containing a UR\n * with information related to a hardware wallet.\n */\n PAIR = 'pair',\n /**\n * Request a scan for a QR code containing a\n * UR-encoded transaction signature.\n */\n SIGN = 'sign',\n}\n\nexport type QrSignatureRequest = {\n requestId: string;\n payload: SerializedUR;\n requestTitle?: string;\n requestDescription?: string;\n};\n\nexport type QrScanRequest = {\n type: QrScanRequestType;\n request?: QrSignatureRequest;\n};\n\nexport type SerializedUR = {\n type: string;\n cbor: string;\n};\n\nexport type QrKeyringBridge = {\n requestScan: (request: QrScanRequest) => Promise<SerializedUR>;\n};\n\nexport type QrKeyringOptions = {\n ur?: string;\n bridge: QrKeyringBridge;\n};\n\n/**\n * The state of the QrKeyring\n *\n * @property accounts - The accounts in the QrKeyring\n */\nexport type SerializedQrKeyringState = {\n version?: number;\n accounts?: string[];\n currentAccount?: number;\n} & (\n | {\n initialized?: false;\n }\n | ({\n initialized: true;\n } & AirgappedSignerDetails)\n);\n\n/**\n * Returns the default serialized state of the QrKeyring.\n *\n * @returns The default serialized state.\n */\nexport const getDefaultSerializedQrKeyringState =\n (): SerializedQrKeyringState => ({\n initialized: false,\n accounts: [],\n });\n\n/**\n * Normalizes an address to a 0x-prefixed checksum address.\n *\n * @param address - The address to normalize.\n * @returns The normalized address as a Hex string.\n */\nfunction normalizeAddress(address: string): Hex {\n return getChecksumAddress(add0x(address));\n}\n\nexport class QrKeyring implements Keyring {\n static type = QR_KEYRING_TYPE;\n\n readonly type = QR_KEYRING_TYPE;\n\n readonly bridge: QrKeyringBridge;\n\n readonly #signer: AirgappedSigner = new AirgappedSigner();\n\n #accounts: Hex[] = [];\n\n #accountToUnlock?: number | undefined;\n\n #currentPage: number = 0;\n\n constructor(options: QrKeyringOptions) {\n this.bridge = options.bridge;\n\n if (options?.ur) {\n this.submitUR(options.ur);\n }\n }\n\n /**\n * Serializes the QrKeyring state\n *\n * @returns The serialized state\n */\n async serialize(): Promise<SerializedQrKeyringState> {\n const source = this.#signer.getSourceDetails();\n\n if (\n !source ||\n ![KeyringMode.HD, KeyringMode.ACCOUNT].includes(source.keyringMode)\n ) {\n // the keyring has not initialized with a device source yet\n return getDefaultSerializedQrKeyringState();\n }\n\n const accounts = this.#accounts.slice();\n\n if (source.keyringMode === KeyringMode.HD) {\n // These properties are only relevant for HD Keys\n return {\n initialized: true,\n name: source.name,\n keyringMode: KeyringMode.HD,\n keyringAccount: source.keyringAccount,\n xfp: source.xfp,\n xpub: source.xpub,\n hdPath: source.hdPath,\n childrenPath: source.childrenPath,\n accounts,\n indexes: source.indexes,\n };\n }\n // These properties are only relevant for Account Keys\n return {\n initialized: true,\n name: source.name,\n keyringMode: KeyringMode.ACCOUNT,\n keyringAccount: source.keyringAccount,\n xfp: source.xfp,\n paths: source.paths,\n accounts,\n indexes: source.indexes,\n };\n }\n\n /**\n * Deserializes the QrKeyring state\n *\n * @param state - The serialized state to deserialize\n */\n async deserialize(state: SerializedQrKeyringState): Promise<void> {\n if (!state.initialized) {\n this.#accounts = [];\n this.#signer.clear();\n return;\n }\n\n this.#signer.init(state);\n this.#accounts = (state.accounts ?? []).map(normalizeAddress);\n }\n\n /**\n * Adds accounts to the QrKeyring\n *\n * @param accountsToAdd - The number of accounts to add\n * @returns The accounts added\n */\n async addAccounts(accountsToAdd: number): Promise<Hex[]> {\n const lastAccount = this.#accounts[this.#accounts.length - 1];\n const startIndex =\n this.#accountToUnlock ??\n (lastAccount ? this.#signer.indexFromAddress(lastAccount) : 0);\n const newAccounts: Hex[] = [];\n\n for (let i = 0; i < accountsToAdd; i++) {\n const index = startIndex + i;\n const address = this.#signer.addressFromIndex(index);\n\n if (this.#accounts.includes(address)) {\n continue;\n }\n\n this.#accounts.push(address);\n newAccounts.push(address);\n }\n\n this.#accountToUnlock = startIndex + accountsToAdd;\n return newAccounts;\n }\n\n /**\n * Gets the accounts in the QrKeyring\n *\n * @returns The accounts in the QrKeyring\n */\n async getAccounts(): Promise<Hex[]> {\n return Array.from(this.#accounts.values());\n }\n\n /**\n * Remove an account from the keyring\n *\n * @param address - The address of the account to remove\n */\n removeAccount(address: Hex): void {\n const normalizedAddress = normalizeAddress(address);\n this.#accounts = this.#accounts.filter(\n (account) => account !== normalizedAddress,\n );\n }\n\n /**\n * Submits a CBOR encoded UR to the QrKeyring\n *\n * @param ur - The CBOR encoded UR\n */\n submitUR(ur: string | SerializedUR): void {\n this.#signer.init(ur);\n }\n\n /**\n * Sets the next account index to unlock\n *\n * @param index - The index of the account to unlock\n */\n setAccountToUnlock(index: number): void {\n this.#accountToUnlock = index;\n }\n\n /**\n * Get the name of the paired device or the keyring type\n * if unavailable.\n *\n * @returns The name of the paired device or the keyring type.\n */\n getName(): string {\n const source = this.#signer.getSourceDetails();\n return source?.name ?? QR_KEYRING_TYPE;\n }\n\n /**\n * Fetch the first page of accounts. If the keyring is not currently initialized,\n * it will trigger a scan request to initialize it.\n *\n * @returns The first page of accounts as an array of Hex strings.\n */\n async getFirstPage(): Promise<IndexedAddress[]> {\n this.#currentPage = 0;\n return this.getCurrentPage();\n }\n\n /**\n * Fetch the next page of accounts. If the keyring is not currently initialized,\n * it will trigger a scan request to initialize it.\n *\n * @returns The next page of accounts as an array of IndexedAddress objects.\n */\n async getNextPage(): Promise<IndexedAddress[]> {\n this.#currentPage += 1;\n return this.getCurrentPage();\n }\n\n /**\n * Fetch the previous page of accounts. If the keyring is not currently initialized,\n * it will trigger a scan request to initialize it.\n *\n * @returns The previous page of accounts as an array of IndexedAddress objects.\n */\n async getPreviousPage(): Promise<IndexedAddress[]> {\n if (this.#currentPage > 0) {\n this.#currentPage -= 1;\n } else {\n this.#currentPage = 0;\n }\n return this.getCurrentPage();\n }\n\n /**\n * Fetch the current page of accounts. If the keyring is not currently initialized,\n * it will trigger a scan request to initialize it.\n *\n * @returns The current page of accounts as an array of IndexedAddress objects.\n */\n async getCurrentPage(): Promise<IndexedAddress[]> {\n if (!this.#signer.isInitialized()) {\n await this.#scanAndInitialize();\n }\n\n return this.#signer.getAddressesPage(this.#currentPage);\n }\n\n /**\n * Clear the keyring state and forget any paired device or accounts.\n */\n async forgetDevice(): Promise<void> {\n this.#signer.clear();\n this.#accounts = [];\n this.#accountToUnlock = undefined;\n this.#currentPage = 0;\n }\n\n /**\n * Sign a transaction. This is equivalent to the `eth_signTransaction`\n * Ethereum JSON-RPC method. See the Ethereum JSON-RPC API documentation for\n * more details.\n *\n * @param address - The address of the account to use for signing.\n * @param transaction - The transaction to sign.\n * @returns The signed transaction.\n */\n async signTransaction(\n address: Hex,\n transaction: TypedTransaction,\n ): Promise<TypedTxData> {\n const signer = this.#signer.getSourceDetails();\n if (!signer?.xfp) {\n throw new Error('Keyring is not initialized. Please scan a QR code.');\n }\n const dataType =\n transaction.type === TransactionType.Legacy\n ? DataType.transaction\n : DataType.typedTransaction;\n let messageToSign: Buffer;\n if (transaction.type === TransactionType.Legacy) {\n messageToSign = Buffer.from(RLP.encode(transaction.getMessageToSign()));\n } else {\n messageToSign = Buffer.from(\n (transaction as FeeMarketEIP1559Transaction).getMessageToSign(),\n );\n }\n\n const hdPath = this.#signer.pathFromAddress(address);\n const chainId = Number(transaction.common.chainId());\n const requestId = uuidv4();\n const ethSignRequestUR = EthSignRequest.constructETHRequest(\n messageToSign,\n dataType,\n hdPath,\n signer.xfp,\n requestId,\n chainId,\n ).toUR();\n const { r, s, v } = await this.#requestSignature({\n requestId,\n payload: {\n type: ethSignRequestUR.type,\n cbor: ethSignRequestUR.cbor.toString('hex'),\n },\n requestTitle: 'Scan with your hardware wallet',\n requestDescription:\n 'After your device has signed this message, click on \"Scan\" to receive the signature',\n });\n\n return TransactionFactory.fromTxData(\n {\n ...transaction,\n r,\n s,\n v,\n },\n {\n common: transaction.common,\n },\n );\n }\n\n /**\n * Sign a message. This is equivalent to the `eth_signTypedData` v4 Ethereum\n * JSON-RPC method.\n *\n * @param address - The address of the account to use for signing.\n * @param data - The data to sign.\n * @returns The signed message.\n */\n async signTypedData<Types extends MessageTypes>(\n address: Hex,\n data: TypedMessage<Types>,\n ): Promise<string> {\n const signer = this.#signer.getSourceDetails();\n if (!signer?.xfp) {\n throw new Error('Keyring is not initialized. Please scan a QR code.');\n }\n\n const hdPath = this.#signer.pathFromAddress(address);\n const requestId = uuidv4();\n const ethSignRequestUR = EthSignRequest.constructETHRequest(\n Buffer.from(JSON.stringify(data), 'utf8'),\n DataType.typedData,\n hdPath,\n signer.xfp,\n requestId,\n undefined,\n address,\n ).toUR();\n\n const { r, s, v } = await this.#requestSignature({\n requestId,\n payload: {\n type: ethSignRequestUR.type,\n cbor: ethSignRequestUR.cbor.toString('hex'),\n },\n requestTitle: DEFAULT_SCAN_REQUEST_TITLE,\n requestDescription: DEFAULT_SCAN_REQUEST_DESCRIPTION,\n });\n\n return add0x(\n Buffer.concat([\n Uint8Array.from(r),\n Uint8Array.from(s),\n Uint8Array.from(v),\n ]).toString('hex'),\n );\n }\n\n /**\n * Scan for a QR code and initialize the keyring with the\n * scanned UR.\n */\n async #scanAndInitialize(): Promise<void> {\n this.submitUR(\n await this.bridge.requestScan({ type: QrScanRequestType.PAIR }),\n );\n }\n\n /**\n * Request a signature for a transaction or message.\n *\n * @param request - The signature request containing the data to sign.\n * @returns The signature as an object containing r, s, and v values.\n */\n async #requestSignature(\n request: QrSignatureRequest,\n ): Promise<{ r: Buffer; s: Buffer; v: Buffer }> {\n const response = await this.bridge.requestScan({\n type: QrScanRequestType.SIGN,\n request,\n });\n const signatureEnvelope = ETHSignature.fromCBOR(\n Buffer.from(response.cbor, 'hex'),\n );\n const signature = signatureEnvelope.getSignature();\n const requestId = signatureEnvelope.getRequestId();\n\n if (!requestId) {\n throw new Error('Signature request ID is missing.');\n }\n\n if (request.requestId !== stringify(requestId)) {\n throw new Error(\n `Signature request ID mismatch. Expected: ${\n request.requestId\n }, received: ${requestId.toString('hex')}`,\n );\n }\n\n return {\n r: signature.subarray(0, 32),\n s: signature.subarray(32, 64),\n v: signature.subarray(64),\n };\n }\n}\n"]}
1
+ {"version":3,"file":"qr-keyring.cjs","sourceRoot":"","sources":["../src/qr-keyring.ts"],"names":[],"mappings":"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","sourcesContent":["import { type TypedTransaction, type TypedTxData } from '@ethereumjs/tx';\nimport type { TypedMessage, MessageTypes } from '@metamask/eth-sig-util';\nimport type { Keyring } from '@metamask/keyring-utils';\nimport { type Hex, add0x, assert, getChecksumAddress } from '@metamask/utils';\n\nimport {\n type DeviceDetails,\n type IndexedAddress,\n Device,\n DeviceMode,\n} from './device';\n\nexport const QR_KEYRING_TYPE = 'QR Hardware Wallet Device';\n\nexport enum QrScanRequestType {\n /**\n * Request a scan for a QR code containing a UR\n * with information related to a hardware wallet.\n */\n PAIR = 'pair',\n /**\n * Request a scan for a QR code containing a\n * UR-encoded transaction signature.\n */\n SIGN = 'sign',\n}\n\nexport type QrSignatureRequest = {\n requestId: string;\n payload: SerializedUR;\n requestTitle?: string;\n requestDescription?: string;\n};\n\nexport type QrScanRequest = {\n type: QrScanRequestType;\n request?: QrSignatureRequest;\n};\n\nexport type SerializedUR = {\n type: string;\n cbor: string;\n};\n\nexport type QrKeyringBridge = {\n requestScan: (request: QrScanRequest) => Promise<SerializedUR>;\n};\n\nexport type QrKeyringOptions = {\n ur?: string;\n bridge: QrKeyringBridge;\n};\n\n/**\n * The state of the QrKeyring\n *\n * @property accounts - The accounts in the QrKeyring\n */\nexport type SerializedQrKeyringState = {\n version?: number;\n accounts?: string[];\n currentAccount?: number;\n} & (\n | {\n initialized?: false;\n }\n | ({\n initialized: true;\n } & DeviceDetails)\n);\n\n/**\n * Returns the default serialized state of the QrKeyring.\n *\n * @returns The default serialized state.\n */\nexport const getDefaultSerializedQrKeyringState =\n (): SerializedQrKeyringState => ({\n initialized: false,\n accounts: [],\n });\n\n/**\n * Normalizes an address to a 0x-prefixed checksum address.\n *\n * @param address - The address to normalize.\n * @returns The normalized address as a Hex string.\n */\nfunction normalizeAddress(address: string): Hex {\n return getChecksumAddress(add0x(address));\n}\n\nexport class QrKeyring implements Keyring {\n static type = QR_KEYRING_TYPE;\n\n readonly type = QR_KEYRING_TYPE;\n\n readonly bridge: QrKeyringBridge;\n\n #device?: Device | undefined;\n\n #accounts: Hex[] = [];\n\n #accountToUnlock?: number | undefined;\n\n #currentPage: number = 0;\n\n constructor(options: QrKeyringOptions) {\n this.bridge = options.bridge;\n\n if (options?.ur) {\n this.pairDevice(options.ur);\n }\n }\n\n /**\n * Serializes the QrKeyring state\n *\n * @returns The serialized state\n */\n async serialize(): Promise<SerializedQrKeyringState> {\n const deviceDetails = this.#device\n ? this.#device.getDeviceDetails()\n : undefined;\n\n if (\n !deviceDetails ||\n ![DeviceMode.HD, DeviceMode.ACCOUNT].includes(deviceDetails.keyringMode)\n ) {\n // the keyring has not initialized with a deviceDetails device yet\n return getDefaultSerializedQrKeyringState();\n }\n\n return {\n ...deviceDetails,\n initialized: true,\n accounts: this.#accounts.slice(),\n };\n }\n\n /**\n * Deserializes the QrKeyring state\n *\n * @param state - The serialized state to deserialize\n */\n async deserialize(state: SerializedQrKeyringState): Promise<void> {\n if (!state.initialized) {\n this.#accounts = [];\n this.#device = undefined;\n return;\n }\n\n this.#device = new Device({\n requestScan: this.bridge.requestScan.bind(this.bridge),\n source: state,\n });\n this.#accounts = (state.accounts ?? []).map(normalizeAddress);\n }\n\n /**\n * Adds accounts to the QrKeyring\n *\n * @param accountsToAdd - The number of accounts to add\n * @returns The accounts added\n */\n async addAccounts(accountsToAdd: number): Promise<Hex[]> {\n if (!this.#device) {\n throw new Error('No device paired.');\n }\n\n const newAccounts: Hex[] = [];\n\n for (let i = 0; i < accountsToAdd; i++) {\n const index = this.#accountToUnlock ?? this.#accounts.length + i;\n const address = this.#device.addressFromIndex(index);\n this.setAccountToUnlock(index + 1);\n\n if (this.#accounts.includes(address)) {\n continue;\n }\n\n this.#accounts.push(address);\n newAccounts.push(address);\n }\n\n return newAccounts;\n }\n\n /**\n * Gets the accounts in the QrKeyring\n *\n * @returns The accounts in the QrKeyring\n */\n async getAccounts(): Promise<Hex[]> {\n return this.#accounts.slice();\n }\n\n /**\n * Remove an account from the keyring\n *\n * @param address - The address of the account to remove\n */\n removeAccount(address: Hex): void {\n const normalizedAddress = normalizeAddress(address);\n this.#accounts = this.#accounts.filter(\n (account) => account !== normalizedAddress,\n );\n }\n\n /**\n * Pair a QR-based Hardware Device from a CBOR encoded UR to the QrKeyring\n *\n * @param ur - The CBOR encoded UR\n */\n pairDevice(ur: string | SerializedUR): void {\n this.#device = new Device({\n requestScan: this.bridge.requestScan.bind(this.bridge),\n source: ur,\n });\n }\n\n /**\n * Sets the next account index to unlock\n *\n * @param index - The index of the account to unlock\n */\n setAccountToUnlock(index: number): void {\n this.#accountToUnlock = index;\n }\n\n /**\n * Get the name of the paired device or the keyring type\n * if unavailable.\n *\n * @returns The name of the paired device or the keyring type.\n */\n getName(): string {\n if (!this.#device) {\n return QR_KEYRING_TYPE;\n }\n const source = this.#device.getDeviceDetails();\n return source.name;\n }\n\n /**\n * Fetch the first page of accounts. If the keyring is not currently initialized,\n * it will trigger a scan request to initialize it.\n *\n * @returns The first page of accounts as an array of Hex strings.\n */\n async getFirstPage(): Promise<IndexedAddress[]> {\n this.#currentPage = 0;\n return this.getCurrentPage();\n }\n\n /**\n * Fetch the next page of accounts. If the keyring is not currently initialized,\n * it will trigger a scan request to initialize it.\n *\n * @returns The next page of accounts as an array of IndexedAddress objects.\n */\n async getNextPage(): Promise<IndexedAddress[]> {\n this.#currentPage += 1;\n return this.getCurrentPage();\n }\n\n /**\n * Fetch the previous page of accounts. If the keyring is not currently initialized,\n * it will trigger a scan request to initialize it.\n *\n * @returns The previous page of accounts as an array of IndexedAddress objects.\n */\n async getPreviousPage(): Promise<IndexedAddress[]> {\n if (this.#currentPage > 0) {\n this.#currentPage -= 1;\n } else {\n this.#currentPage = 0;\n }\n return this.getCurrentPage();\n }\n\n /**\n * Fetch the current page of accounts. If the keyring is not currently initialized,\n * it will trigger a scan request to initialize it.\n *\n * @returns The current page of accounts as an array of IndexedAddress objects.\n */\n async getCurrentPage(): Promise<IndexedAddress[]> {\n if (!this.#device) {\n await this.#scanAndInitialize();\n }\n assert(\n this.#device,\n 'A device is expected to be paired before fetching accounts.',\n );\n return this.#device.getAddressesPage(this.#currentPage);\n }\n\n /**\n * Clear the keyring state and forget any paired device or accounts.\n */\n async forgetDevice(): Promise<void> {\n this.#device = undefined;\n this.#accounts = [];\n this.#accountToUnlock = undefined;\n this.#currentPage = 0;\n }\n\n /**\n * Sign a transaction. This is equivalent to the `eth_signTransaction`\n * Ethereum JSON-RPC method. See the Ethereum JSON-RPC API documentation for\n * more details.\n *\n * @param address - The address of the account to use for signing.\n * @param transaction - The transaction to sign.\n * @returns The signed transaction.\n */\n async signTransaction(\n address: Hex,\n transaction: TypedTransaction,\n ): Promise<TypedTxData> {\n if (!this.#device) {\n throw new Error('No device paired.');\n }\n return this.#device.signTransaction(address, transaction);\n }\n\n /**\n * Sign a message. This is equivalent to the `eth_signTypedData` v4 Ethereum\n * JSON-RPC method.\n *\n * @param address - The address of the account to use for signing.\n * @param data - The data to sign.\n * @returns The signed message.\n */\n async signTypedData<Types extends MessageTypes>(\n address: Hex,\n data: TypedMessage<Types>,\n ): Promise<string> {\n if (!this.#device) {\n throw new Error('No device paired.');\n }\n return this.#device.signTypedData(address, data);\n }\n\n /**\n * Sign a message. This is equivalent to the `eth_sign` Ethereum JSON-RPC\n * method, which is exposed by MetaMask as the method `personal_sign`. See\n * the Ethereum JSON-RPC API documentation for more details.\n *\n * For more information about this method and why we call it `personal_sign`,\n * see the {@link https://docs.metamask.io/guide/signing-data.html|MetaMask Docs}.\n *\n * @param address - The address of the account to use for signing.\n * @param message - The message to sign.\n * @returns The signed message.\n */\n async signPersonalMessage(address: Hex, message: Hex): Promise<string> {\n if (!this.#device) {\n throw new Error('No device paired.');\n }\n return this.#device.signPersonalMessage(address, message);\n }\n\n /**\n * Scan for a QR code and initialize the keyring with the\n * scanned UR.\n */\n async #scanAndInitialize(): Promise<void> {\n this.pairDevice(\n await this.bridge.requestScan({ type: QrScanRequestType.PAIR }),\n );\n }\n}\n"]}
@@ -2,7 +2,7 @@ import { type TypedTransaction, type TypedTxData } from "@ethereumjs/tx";
2
2
  import type { TypedMessage, MessageTypes } from "@metamask/eth-sig-util";
3
3
  import type { Keyring } from "@metamask/keyring-utils";
4
4
  import { type Hex } from "@metamask/utils";
5
- import { type AirgappedSignerDetails, type IndexedAddress } from "./airgapped-signer.cjs";
5
+ import { type DeviceDetails, type IndexedAddress } from "./device.cjs";
6
6
  export declare const QR_KEYRING_TYPE = "QR Hardware Wallet Device";
7
7
  export declare enum QrScanRequestType {
8
8
  /**
@@ -50,7 +50,7 @@ export type SerializedQrKeyringState = {
50
50
  initialized?: false;
51
51
  } | ({
52
52
  initialized: true;
53
- } & AirgappedSignerDetails));
53
+ } & DeviceDetails));
54
54
  /**
55
55
  * Returns the default serialized state of the QrKeyring.
56
56
  *
@@ -95,11 +95,11 @@ export declare class QrKeyring implements Keyring {
95
95
  */
96
96
  removeAccount(address: Hex): void;
97
97
  /**
98
- * Submits a CBOR encoded UR to the QrKeyring
98
+ * Pair a QR-based Hardware Device from a CBOR encoded UR to the QrKeyring
99
99
  *
100
100
  * @param ur - The CBOR encoded UR
101
101
  */
102
- submitUR(ur: string | SerializedUR): void;
102
+ pairDevice(ur: string | SerializedUR): void;
103
103
  /**
104
104
  * Sets the next account index to unlock
105
105
  *
@@ -164,5 +164,18 @@ export declare class QrKeyring implements Keyring {
164
164
  * @returns The signed message.
165
165
  */
166
166
  signTypedData<Types extends MessageTypes>(address: Hex, data: TypedMessage<Types>): Promise<string>;
167
+ /**
168
+ * Sign a message. This is equivalent to the `eth_sign` Ethereum JSON-RPC
169
+ * method, which is exposed by MetaMask as the method `personal_sign`. See
170
+ * the Ethereum JSON-RPC API documentation for more details.
171
+ *
172
+ * For more information about this method and why we call it `personal_sign`,
173
+ * see the {@link https://docs.metamask.io/guide/signing-data.html|MetaMask Docs}.
174
+ *
175
+ * @param address - The address of the account to use for signing.
176
+ * @param message - The message to sign.
177
+ * @returns The signed message.
178
+ */
179
+ signPersonalMessage(address: Hex, message: Hex): Promise<string>;
167
180
  }
168
181
  //# sourceMappingURL=qr-keyring.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"qr-keyring.d.cts","sourceRoot":"","sources":["../src/qr-keyring.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"qr-keyring.d.cts","sourceRoot":"","sources":["../src/qr-keyring.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { type TypedTransaction, type TypedTxData } from "@ethereumjs/tx";
2
2
  import type { TypedMessage, MessageTypes } from "@metamask/eth-sig-util";
3
3
  import type { Keyring } from "@metamask/keyring-utils";
4
4
  import { type Hex } from "@metamask/utils";
5
- import { type AirgappedSignerDetails, type IndexedAddress } from "./airgapped-signer.mjs";
5
+ import { type DeviceDetails, type IndexedAddress } from "./device.mjs";
6
6
  export declare const QR_KEYRING_TYPE = "QR Hardware Wallet Device";
7
7
  export declare enum QrScanRequestType {
8
8
  /**
@@ -50,7 +50,7 @@ export type SerializedQrKeyringState = {
50
50
  initialized?: false;
51
51
  } | ({
52
52
  initialized: true;
53
- } & AirgappedSignerDetails));
53
+ } & DeviceDetails));
54
54
  /**
55
55
  * Returns the default serialized state of the QrKeyring.
56
56
  *
@@ -95,11 +95,11 @@ export declare class QrKeyring implements Keyring {
95
95
  */
96
96
  removeAccount(address: Hex): void;
97
97
  /**
98
- * Submits a CBOR encoded UR to the QrKeyring
98
+ * Pair a QR-based Hardware Device from a CBOR encoded UR to the QrKeyring
99
99
  *
100
100
  * @param ur - The CBOR encoded UR
101
101
  */
102
- submitUR(ur: string | SerializedUR): void;
102
+ pairDevice(ur: string | SerializedUR): void;
103
103
  /**
104
104
  * Sets the next account index to unlock
105
105
  *
@@ -164,5 +164,18 @@ export declare class QrKeyring implements Keyring {
164
164
  * @returns The signed message.
165
165
  */
166
166
  signTypedData<Types extends MessageTypes>(address: Hex, data: TypedMessage<Types>): Promise<string>;
167
+ /**
168
+ * Sign a message. This is equivalent to the `eth_sign` Ethereum JSON-RPC
169
+ * method, which is exposed by MetaMask as the method `personal_sign`. See
170
+ * the Ethereum JSON-RPC API documentation for more details.
171
+ *
172
+ * For more information about this method and why we call it `personal_sign`,
173
+ * see the {@link https://docs.metamask.io/guide/signing-data.html|MetaMask Docs}.
174
+ *
175
+ * @param address - The address of the account to use for signing.
176
+ * @param message - The message to sign.
177
+ * @returns The signed message.
178
+ */
179
+ signPersonalMessage(address: Hex, message: Hex): Promise<string>;
167
180
  }
168
181
  //# sourceMappingURL=qr-keyring.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"qr-keyring.d.mts","sourceRoot":"","sources":["../src/qr-keyring.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"qr-keyring.d.mts","sourceRoot":"","sources":["../src/qr-keyring.ts"],"names":[],"mappings":"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"}