@sidhujag/sysweb3-keyring 2.1.9 → 2.1.11

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 (45) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +8 -5
  3. package/cjs/hardware-signing-data.js +85 -0
  4. package/cjs/hardware-signing-data.js.map +1 -0
  5. package/cjs/hardware-wallet-manager.js +36 -13
  6. package/cjs/hardware-wallet-manager.js.map +1 -1
  7. package/cjs/ledger/index.js +41 -51
  8. package/cjs/ledger/index.js.map +1 -1
  9. package/cjs/transactions/ethereum.js +92 -70
  10. package/cjs/transactions/ethereum.js.map +1 -1
  11. package/cjs/transactions/prepared-evm.js.map +1 -1
  12. package/cjs/trezor/connect.js +155 -50
  13. package/cjs/trezor/connect.js.map +1 -1
  14. package/cjs/trezor/index.js +159 -138
  15. package/cjs/trezor/index.js.map +1 -1
  16. package/cjs/types.js.map +1 -1
  17. package/esm/hardware-signing-data.js +82 -0
  18. package/esm/hardware-signing-data.js.map +1 -0
  19. package/esm/hardware-wallet-manager.js +36 -13
  20. package/esm/hardware-wallet-manager.js.map +1 -1
  21. package/esm/ledger/dmk-evm.js +13 -48
  22. package/esm/ledger/dmk-evm.js.map +1 -1
  23. package/esm/ledger/dmk-utxo.js +9 -6
  24. package/esm/ledger/dmk-utxo.js.map +1 -1
  25. package/esm/ledger/index.js +41 -51
  26. package/esm/ledger/index.js.map +1 -1
  27. package/esm/transactions/ethereum.js +92 -70
  28. package/esm/transactions/ethereum.js.map +1 -1
  29. package/esm/transactions/prepared-evm.js.map +1 -1
  30. package/esm/trezor/connect.js +155 -50
  31. package/esm/trezor/connect.js.map +1 -1
  32. package/esm/trezor/index.js +160 -139
  33. package/esm/trezor/index.js.map +1 -1
  34. package/esm/types.js.map +1 -1
  35. package/package.json +1 -1
  36. package/types/hardware-signing-data.d.ts +2 -0
  37. package/types/hardware-wallet-manager.d.ts +3 -1
  38. package/types/ledger/host-types.d.ts +3 -3
  39. package/types/ledger/index.d.ts +2 -1
  40. package/types/ledger/types.d.ts +4 -4
  41. package/types/transactions/ethereum.d.ts +4 -2
  42. package/types/transactions/prepared-evm.d.ts +1 -0
  43. package/types/trezor/connect.d.ts +10 -1
  44. package/types/trezor/index.d.ts +21 -11
  45. package/types/types.d.ts +2 -2
@@ -19,6 +19,8 @@ const evm_cancellation_1 = require("./evm-cancellation");
19
19
  const evm_envelope_1 = require("./evm-envelope");
20
20
  const evm_local_signer_1 = require("./evm-local-signer");
21
21
  const evm_submission_1 = require("./evm-submission");
22
+ const hardware_signing_data_1 = require("../hardware-signing-data");
23
+ const hardware_transaction_authority_1 = require("../hardware-transaction-authority");
22
24
  const ledger_signing_1 = require("./ledger-signing");
23
25
  const prepared_evm_1 = require("./prepared-evm");
24
26
  const trezor_signing_1 = require("./trezor-signing");
@@ -218,10 +220,30 @@ class EthereumTransactions {
218
220
  this.submitSignedHardwareTransaction = (provider, raw, broadcast, submission, beforeBroadcast, expectedUnsigned) => (0, evm_submission_1.submitSignedHardwareEvmTransaction)(raw, broadcast, submission, beforeBroadcast, expectedUnsigned,
219
221
  // A device confirmation or journal write can outlast the earlier check.
220
222
  () => provider.verifyConfiguredChainId(true));
221
- this.signTypedData = async (addr, typedData, version) => {
223
+ this.captureMessageSigning = (authority) => {
224
+ const owner = (0, hardware_transaction_authority_1.captureHardwareTransactionAuthority)(authority);
225
+ const context = this.captureEvmAccountContext();
226
+ const ledger = this.ledgerSigner, trezor = this.trezorSigner;
227
+ const assertCurrent = () => {
228
+ owner.assertCurrent();
229
+ context.assertCurrent();
230
+ if (this.ledgerSigner !== ledger || this.trezorSigner !== trezor)
231
+ throw new Error('Wallet signing SDK changed');
232
+ owner.assertCurrent();
233
+ };
234
+ assertCurrent();
235
+ return {
236
+ context,
237
+ authority: Object.freeze({ assertCurrent, signal: owner.signal }),
238
+ };
239
+ };
240
+ this.signTypedData = async (addr, typedData, version, authority) => {
241
+ const captured = this.captureMessageSigning(authority);
242
+ const owner = captured.authority;
243
+ const { activeAccountType, activeAccountId, activeAccount } = captured.context;
222
244
  const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
223
- const { activeAccountType, accounts, activeAccountId } = this.getState();
224
- const activeAccount = accounts[activeAccountType][activeAccountId];
245
+ owner.assertCurrent();
246
+ const approvedData = (0, hardware_signing_data_1.captureHardwareSigningData)(typedData, () => new Error('Invalid typed signing request'));
225
247
  // Validate that the derived address matches the active account to prevent race conditions
226
248
  if (address.toLowerCase() !== activeAccount.address.toLowerCase()) {
227
249
  throw {
@@ -236,7 +258,7 @@ class EthereumTransactions {
236
258
  const privKey = Buffer.from(stripHexPrefix(decryptedPrivateKey), 'hex');
237
259
  return (0, eth_sig_util_1.signTypedData)({
238
260
  privateKey: privKey,
239
- data: typedData,
261
+ data: approvedData,
240
262
  version,
241
263
  });
242
264
  };
@@ -249,8 +271,8 @@ class EthereumTransactions {
249
271
  version,
250
272
  accountIndex: activeAccountId,
251
273
  expectedAddress: activeAccount.address,
252
- data: typedData,
253
- });
274
+ data: approvedData,
275
+ }, owner);
254
276
  };
255
277
  const signTypedDataWithTrezor = async () => {
256
278
  if (addr.toLowerCase() !== activeAccount.address.toLowerCase())
@@ -260,17 +282,29 @@ class EthereumTransactions {
260
282
  return await this.requireTrezorSigner().signTypedData({
261
283
  version,
262
284
  address: addr,
263
- data: typedData,
285
+ data: approvedData,
264
286
  index: activeAccountId,
265
- });
287
+ }, owner);
266
288
  };
267
- switch (activeAccountType) {
268
- case types_1.KeyringAccountType.Trezor:
269
- return await signTypedDataWithTrezor();
270
- case types_1.KeyringAccountType.Ledger:
271
- return await signTypedDataWithLedger();
272
- default:
273
- return signTypedDataLocal();
289
+ try {
290
+ owner.assertCurrent();
291
+ let result;
292
+ switch (activeAccountType) {
293
+ case types_1.KeyringAccountType.Trezor:
294
+ result = await signTypedDataWithTrezor();
295
+ break;
296
+ case types_1.KeyringAccountType.Ledger:
297
+ result = await signTypedDataWithLedger();
298
+ break;
299
+ default:
300
+ result = signTypedDataLocal();
301
+ }
302
+ owner.assertCurrent();
303
+ return result;
304
+ }
305
+ catch (error) {
306
+ owner.assertCurrent();
307
+ throw error;
274
308
  }
275
309
  };
276
310
  // Verify a UTXO address on the connected hardware wallet (Ledger or Trezor)
@@ -312,12 +346,15 @@ class EthereumTransactions {
312
346
  'selectedAccount',
313
347
  'targetAccount',
314
348
  'assertCurrent',
349
+ 'signal',
315
350
  ]);
316
351
  const selectedAccount = (0, prepared_evm_1.snapshotEvmSigningIdentity)(options.selectedAccount);
317
352
  const targetAccount = (0, prepared_evm_1.snapshotEvmSigningIdentity)(options.targetAccount);
318
- const hostGuard = (0, prepared_evm_1.preparedEvmGuard)({
353
+ const owner = (0, hardware_transaction_authority_1.captureHardwareTransactionAuthority)({
319
354
  assertCurrent: options.assertCurrent,
355
+ signal: options.signal,
320
356
  });
357
+ const hostGuard = owner.assertCurrent;
321
358
  const target = {
322
359
  id: targetAccount.id,
323
360
  type: targetAccount.type,
@@ -337,8 +374,11 @@ class EthereumTransactions {
337
374
  throw new Error('EVM digest signing context changed');
338
375
  };
339
376
  assertCurrent();
377
+ if (context.activeAccountType === types_1.KeyringAccountType.Ledger ||
378
+ context.activeAccountType === types_1.KeyringAccountType.Trezor)
379
+ throw Object.assign(new Error('Hardware raw-digest signing is unsupported; use owned typed-data signing'), { code: 'HARDWARE_RAW_DIGEST_UNSUPPORTED' });
340
380
  const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey(target);
341
- const { activeAccountId, activeAccountType, activeNetwork, activeAccount } = context;
381
+ const { activeAccount } = context;
342
382
  // Validate that the derived address matches the active account to prevent race conditions
343
383
  if (address.toLowerCase() !== activeAccount.address.toLowerCase()) {
344
384
  throw {
@@ -377,54 +417,24 @@ class EthereumTransactions {
377
417
  throw error;
378
418
  }
379
419
  };
380
- const signWithLedger = async () => {
381
- try {
382
- const response = await this.requireLedgerSigner().evm.signPersonalMessage({
383
- accountIndex: activeAccountId,
384
- expectedAddress: activeAccount.address,
385
- message: msg,
386
- });
387
- return response;
388
- }
389
- catch (error) {
390
- throw error;
391
- }
392
- };
393
- const signWithTrezor = async () => {
394
- try {
395
- // For EVM networks, Trezor expects 'eth' regardless of the network's currency
396
- const trezorCoin = activeNetwork.slip44 === 60 ? 'eth' : activeNetwork.currency;
397
- const response = await this.requireTrezorSigner().signMessage({
398
- coin: trezorCoin,
399
- address: activeAccount.address,
400
- index: activeAccountId,
401
- message: msg,
402
- slip44: activeNetwork.slip44,
403
- });
404
- return response.signature;
405
- }
406
- catch (error) {
407
- throw error;
408
- }
409
- };
410
- let signature;
411
- switch (activeAccountType) {
412
- case types_1.KeyringAccountType.Trezor:
413
- signature = await signWithTrezor();
414
- break;
415
- case types_1.KeyringAccountType.Ledger:
416
- signature = await signWithLedger();
417
- break;
418
- default:
419
- signature = sign();
420
- }
420
+ const signature = sign();
421
421
  assertCurrent();
422
422
  return signature;
423
423
  };
424
- this.signPersonalMessage = async (params) => {
424
+ this.signPersonalMessage = async (params, authority) => {
425
+ const captured = this.captureMessageSigning(authority);
426
+ const owner = captured.authority;
427
+ if (!Array.isArray(params) || params.length !== 2)
428
+ throw new Error('Invalid personal message request');
429
+ params = [0, 1].map((index) => {
430
+ const field = Object.getOwnPropertyDescriptor(params, String(index));
431
+ if (!field || !('value' in field) || typeof field.value !== 'string')
432
+ throw new Error('Invalid personal message request');
433
+ return field.value;
434
+ });
425
435
  const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
426
- const { accounts, activeAccountId, activeAccountType, activeNetwork } = this.getState();
427
- const activeAccount = accounts[activeAccountType][activeAccountId];
436
+ owner.assertCurrent();
437
+ const { activeAccountId, activeAccountType, activeNetwork, activeAccount } = captured.context;
428
438
  // Validate that the derived address matches the active account to prevent race conditions
429
439
  if (address.toLowerCase() !== activeAccount.address.toLowerCase()) {
430
440
  throw {
@@ -482,7 +492,7 @@ class EthereumTransactions {
482
492
  accountIndex: activeAccountId,
483
493
  expectedAddress: activeAccount.address,
484
494
  message: messageForLedger,
485
- });
495
+ }, owner);
486
496
  return response;
487
497
  }
488
498
  catch (error) {
@@ -509,20 +519,32 @@ class EthereumTransactions {
509
519
  index: activeAccountId,
510
520
  message: messageForTrezor,
511
521
  slip44: activeNetwork.slip44,
512
- });
522
+ }, owner);
513
523
  return response.signature;
514
524
  }
515
525
  catch (error) {
516
526
  throw error;
517
527
  }
518
528
  };
519
- switch (activeAccountType) {
520
- case types_1.KeyringAccountType.Trezor:
521
- return await signPersonalMessageWithTrezor();
522
- case types_1.KeyringAccountType.Ledger:
523
- return await signPersonalMessageWithLedger();
524
- default:
525
- return signPersonalMessageWithDefaultWallet();
529
+ try {
530
+ owner.assertCurrent();
531
+ let result;
532
+ switch (activeAccountType) {
533
+ case types_1.KeyringAccountType.Trezor:
534
+ result = await signPersonalMessageWithTrezor();
535
+ break;
536
+ case types_1.KeyringAccountType.Ledger:
537
+ result = await signPersonalMessageWithLedger();
538
+ break;
539
+ default:
540
+ result = signPersonalMessageWithDefaultWallet();
541
+ }
542
+ owner.assertCurrent();
543
+ return result;
544
+ }
545
+ catch (error) {
546
+ owner.assertCurrent();
547
+ throw error;
526
548
  }
527
549
  };
528
550
  this.parsePersonalMessage = (hexMsg) => {