@sidhujag/sysweb3-keyring 2.1.3 → 2.1.4

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 (126) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +47 -47
  3. package/cjs/hardware-transaction-authority.js +36 -0
  4. package/cjs/hardware-transaction-authority.js.map +1 -0
  5. package/cjs/index.js +5 -5
  6. package/cjs/index.js.map +1 -1
  7. package/cjs/keyring-core.js +171 -220
  8. package/cjs/keyring-core.js.map +1 -1
  9. package/cjs/keyring-host.js +113 -0
  10. package/cjs/keyring-host.js.map +1 -0
  11. package/cjs/keyring-manager.js +15 -151
  12. package/cjs/keyring-manager.js.map +1 -1
  13. package/cjs/ledger/host-types.js.map +1 -1
  14. package/cjs/ledger/index.js +44 -19
  15. package/cjs/ledger/index.js.map +1 -1
  16. package/cjs/providers.js +3 -1
  17. package/cjs/providers.js.map +1 -1
  18. package/cjs/software.js +10 -56
  19. package/cjs/software.js.map +1 -1
  20. package/cjs/transactions/ethereum.js +306 -229
  21. package/cjs/transactions/ethereum.js.map +1 -1
  22. package/cjs/transactions/evm-local-signer.js +15 -0
  23. package/cjs/transactions/evm-local-signer.js.map +1 -1
  24. package/cjs/transactions/evm-submission.js +61 -65
  25. package/cjs/transactions/evm-submission.js.map +1 -1
  26. package/cjs/transactions/hardware-psbt.js +11 -8
  27. package/cjs/transactions/hardware-psbt.js.map +1 -1
  28. package/cjs/transactions/index.js +10 -2
  29. package/cjs/transactions/index.js.map +1 -1
  30. package/cjs/transactions/prepared-evm.js +10 -7
  31. package/cjs/transactions/prepared-evm.js.map +1 -1
  32. package/cjs/transactions/syscoin-core.js +282 -202
  33. package/cjs/transactions/syscoin-core.js.map +1 -1
  34. package/cjs/trezor/connect.js +19 -2
  35. package/cjs/trezor/connect.js.map +1 -1
  36. package/cjs/trezor/index.js +38 -16
  37. package/cjs/trezor/index.js.map +1 -1
  38. package/cjs/types.js.map +1 -1
  39. package/cjs/utils/owned-blockbook-account.js +45 -0
  40. package/cjs/utils/owned-blockbook-account.js.map +1 -0
  41. package/esm/current-vault-refusal.js +3 -0
  42. package/esm/current-vault-refusal.js.map +1 -0
  43. package/esm/evm-fees.js +242 -0
  44. package/esm/evm-fees.js.map +1 -0
  45. package/esm/hardware-transaction-authority.js +33 -0
  46. package/esm/hardware-transaction-authority.js.map +1 -0
  47. package/esm/initial-state.js +102 -0
  48. package/esm/initial-state.js.map +1 -0
  49. package/esm/keyring-core.js +2781 -0
  50. package/esm/keyring-core.js.map +1 -0
  51. package/esm/keyring-host.js +108 -0
  52. package/esm/keyring-host.js.map +1 -0
  53. package/esm/ledger/dmk-session.js +1 -0
  54. package/esm/ledger/dmk-session.js.map +1 -1
  55. package/esm/ledger/dmk-utxo.js +9 -3
  56. package/esm/ledger/dmk-utxo.js.map +1 -1
  57. package/esm/ledger/host-types.js.map +1 -1
  58. package/esm/ledger/index.js +44 -19
  59. package/esm/ledger/index.js.map +1 -1
  60. package/esm/network-utils.js +70 -0
  61. package/esm/network-utils.js.map +1 -0
  62. package/esm/providers.js +3 -1
  63. package/esm/providers.js.map +1 -1
  64. package/esm/software-hd-account.js +20 -0
  65. package/esm/software-hd-account.js.map +1 -0
  66. package/esm/storage-core.js +258 -0
  67. package/esm/storage-core.js.map +1 -0
  68. package/esm/transactions/ethereum.js +2753 -0
  69. package/esm/transactions/ethereum.js.map +1 -0
  70. package/esm/transactions/evm-cancellation.js +40 -0
  71. package/esm/transactions/evm-cancellation.js.map +1 -0
  72. package/esm/transactions/evm-local-signer.js +202 -0
  73. package/esm/transactions/evm-local-signer.js.map +1 -0
  74. package/esm/transactions/evm-submission.js +187 -0
  75. package/esm/transactions/evm-submission.js.map +1 -0
  76. package/esm/transactions/prepared-evm.js +194 -0
  77. package/esm/transactions/prepared-evm.js.map +1 -0
  78. package/esm/transactions/syscoin-core.js +691 -0
  79. package/esm/transactions/syscoin-core.js.map +1 -0
  80. package/esm/trezor/connect.js +19 -2
  81. package/esm/trezor/connect.js.map +1 -1
  82. package/esm/trezor/index.js +38 -16
  83. package/esm/trezor/index.js.map +1 -1
  84. package/esm/types.js.map +1 -1
  85. package/esm/utils/excluded-utxos.js +53 -0
  86. package/esm/utils/excluded-utxos.js.map +1 -0
  87. package/esm/utils/owned-blockbook-account.js +9 -0
  88. package/esm/utils/owned-blockbook-account.js.map +1 -0
  89. package/esm/utils/psbt.js +32 -0
  90. package/esm/utils/psbt.js.map +1 -0
  91. package/esm/utils/watch-descriptor.js +138 -0
  92. package/esm/utils/watch-descriptor.js.map +1 -0
  93. package/package.json +5 -11
  94. package/types/hardware-transaction-authority.d.ts +5 -0
  95. package/types/index.d.ts +3 -3
  96. package/types/keyring-core.d.ts +22 -51
  97. package/types/keyring-host.d.ts +46 -0
  98. package/types/keyring-manager.d.ts +13 -18
  99. package/types/ledger/host-types.d.ts +4 -1
  100. package/types/ledger/index.d.ts +1 -1
  101. package/types/ledger/types.d.ts +3 -2
  102. package/types/providers.d.ts +1 -1
  103. package/types/software.d.ts +6 -19
  104. package/types/transactions/ethereum.d.ts +14 -11
  105. package/types/transactions/evm-local-signer.d.ts +2 -2
  106. package/types/transactions/evm-submission.d.ts +11 -4
  107. package/types/transactions/hardware-psbt.d.ts +1 -1
  108. package/types/transactions/index.d.ts +3 -2
  109. package/types/transactions/prepared-evm.d.ts +4 -1
  110. package/types/transactions/syscoin-core.d.ts +48 -21
  111. package/types/trezor/connect.d.ts +6 -3
  112. package/types/trezor/index.d.ts +4 -3
  113. package/types/types.d.ts +95 -63
  114. package/types/utils/owned-blockbook-account.d.ts +3 -0
  115. package/cjs/hardware-wallet-manager-singleton.js +0 -34
  116. package/cjs/hardware-wallet-manager-singleton.js.map +0 -1
  117. package/cjs/storage.js +0 -20
  118. package/cjs/storage.js.map +0 -1
  119. package/cjs/transactions/syscoin.js +0 -16
  120. package/cjs/transactions/syscoin.js.map +0 -1
  121. package/cjs/utils/blockbook-cache.js +0 -76
  122. package/cjs/utils/blockbook-cache.js.map +0 -1
  123. package/types/hardware-wallet-manager-singleton.d.ts +0 -19
  124. package/types/storage.d.ts +0 -5
  125. package/types/transactions/syscoin.d.ts +0 -9
  126. package/types/utils/blockbook-cache.d.ts +0 -6
@@ -71,6 +71,7 @@ const SLH_DSA_PARAMETER_SET = 'SLH-DSA-SHA2-128-24';
71
71
  const current_vault_refusal_1 = require("./current-vault-refusal");
72
72
  const ethers_v6_1 = require("./ethers-v6");
73
73
  const initial_state_1 = require("./initial-state");
74
+ const keyring_host_1 = require("./keyring-host");
74
75
  const private_records_1 = require("./private-records");
75
76
  const signers_1 = require("./signers");
76
77
  const software_hd_account_1 = require("./software-hd-account");
@@ -80,8 +81,8 @@ const evm_local_signer_1 = require("./transactions/evm-local-signer");
80
81
  const prepared_evm_1 = require("./transactions/prepared-evm");
81
82
  const syscoin_core_1 = require("./transactions/syscoin-core");
82
83
  const types_1 = require("./types");
83
- const blockbook_cache_1 = require("./utils/blockbook-cache");
84
84
  const derivation_paths_1 = require("./utils/derivation-paths");
85
+ const owned_blockbook_account_1 = require("./utils/owned-blockbook-account");
85
86
  const psbt_account_scope_1 = require("./utils/psbt-account-scope");
86
87
  const watch_descriptor_1 = require("./utils/watch-descriptor");
87
88
  const currentVaultSalt = (keys) => {
@@ -146,7 +147,7 @@ class SecureBuffer {
146
147
  }
147
148
  }
148
149
  class KeyringCore {
149
- constructor(dependencies) {
150
+ constructor(binding, hardware) {
150
151
  _KeyringCore_instances.add(this);
151
152
  // Store getter function for accessing Redux state
152
153
  this.getVaultState = null;
@@ -194,7 +195,7 @@ class KeyringCore {
194
195
  this.privateRecordSessionRevision = 0;
195
196
  _KeyringCore_deviceUnlockRetired.set(this, false);
196
197
  _KeyringCore_sessionOwnership.set(this, void 0);
197
- this.createSyscoinTransactions = () => new syscoin_core_1.SyscoinTransactionsCore(this.getSigner, this.getReadOnlySigner, this.getAccountsState, this.getAddress, this.syscoinHardwareSigners, this.capturePsbtSigningContext);
198
+ this.createSyscoinTransactions = () => new syscoin_core_1.SyscoinTransactionsCore(this.getSigner, this.getReadOnlySigner, this.getAccountsState, this.syscoinHardwareSigners, this.capturePsbtSigningContext);
198
199
  this.requireLedgerSigner = () => {
199
200
  if (!this.ledgerSigner)
200
201
  throw (0, syscoin_core_1.createHardwareSignerUnavailableError)('Ledger');
@@ -206,12 +207,6 @@ class KeyringCore {
206
207
  return this.trezorSigner;
207
208
  };
208
209
  // ===================================== PUBLIC METHODS - KEYRING MANAGER FOR HD - SYS ALL ===================================== //
209
- this.setStorage = (client) => {
210
- if (!this.storage.setClient) {
211
- throw new Error('Storage replacement is unavailable in this host');
212
- }
213
- this.storage.setClient(client);
214
- };
215
210
  this.validateAccountType = (account) => {
216
211
  return account.isImported === true
217
212
  ? types_1.KeyringAccountType.Imported
@@ -230,7 +225,7 @@ class KeyringCore {
230
225
  this.sessionMnemonic = null;
231
226
  }
232
227
  const ownership = __classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f");
233
- if (ownership && ownership.tracker.current === ownership.token) {
228
+ if (ownership.tracker.current === ownership.token) {
234
229
  ownership.tracker.current = undefined;
235
230
  ownership.tracker.epoch++;
236
231
  }
@@ -284,8 +279,6 @@ class KeyringCore {
284
279
  this.sessionPassword = null;
285
280
  this.sessionMnemonic = null;
286
281
  };
287
- // Legacy trusted-host API. SoftwareKeyring disables direct buffer injection.
288
- this.receiveSessionOwnership = (sessionPassword, sessionMnemonic) => __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_replaceSessionBuffers).call(this, sessionPassword, sessionMnemonic);
289
282
  this.addNewAccount = async (label) => {
290
283
  // Check if wallet is unlocked
291
284
  if (!this.isUnlocked()) {
@@ -332,91 +325,41 @@ class KeyringCore {
332
325
  xpub: derived.address,
333
326
  };
334
327
  };
335
- this.getNewChangeAddress = async () => {
336
- const vault = this.getVault();
337
- const { accounts, activeAccount } = vault;
338
- const account = accounts[activeAccount.type]?.[activeAccount.id];
339
- if (!account) {
340
- throw new Error('Active account not found');
341
- }
342
- const { xpub, isImported, address } = account;
343
- // For imported single-address accounts, always return the single address
344
- const looksLikeSingleAddress = isImported &&
345
- xpub === address &&
346
- !this.isDescriptor(xpub) &&
347
- !this.isXpubLike(xpub);
348
- if (looksLikeSingleAddress)
349
- return address;
350
- return await this.getAddress(xpub, true); // Don't skip increment - get next unused
351
- };
352
- this.getChangeAddress = async (id) => {
353
- const vault = this.getVault();
354
- const { accounts, activeAccount } = vault;
355
- const account = accounts[activeAccount.type]?.[id];
356
- if (!account) {
357
- throw new Error(`Account with id ${id} not found`);
358
- }
359
- const { xpub, isImported, address } = account;
360
- if (isImported &&
361
- xpub === address &&
362
- !this.isDescriptor(xpub) &&
363
- !this.isXpubLike(xpub))
364
- return address;
365
- return await this.getAddress(xpub, true);
366
- };
367
- this.getPubkey = async (id, isChangeAddress) => {
368
- const vault = this.getVault();
369
- const { accounts, activeAccount } = vault;
370
- const account = accounts[activeAccount.type]?.[id];
371
- if (!account) {
372
- throw new Error(`Account with id ${id} not found`);
373
- }
374
- const { xpub, isImported, address } = account;
375
- // Guard: single-address imported are watch-only
376
- if (isImported && xpub === address) {
377
- throw new Error('Public key not available for single-address imported accounts');
378
- }
379
- // Guard: descriptor/xpub watch-only (no xprv and not hardware)
380
- if (this.isWatchOnlyAccount(account)) {
381
- throw new Error('Public key not available for watch-only accounts');
382
- }
383
- return await this.getCurrentAddressPubkey(xpub, isChangeAddress);
384
- };
385
- this.getBip32Path = async (id, isChangeAddress) => {
386
- const vault = this.getVault();
387
- const { accounts, activeAccount } = vault;
388
- const account = accounts[activeAccount.type]?.[id];
389
- if (!account) {
390
- throw new Error(`Account with id ${id} not found`);
391
- }
392
- const { xpub, isImported, address } = account;
393
- // Guard: single-address imported are watch-only
394
- if (isImported && xpub === address) {
395
- throw new Error('BIP32 path not available for single-address imported accounts');
396
- }
397
- // Guard: descriptor/xpub watch-only (no xprv and not hardware)
398
- if (this.isWatchOnlyAccount(account)) {
399
- throw new Error('BIP32 path not available for watch-only accounts');
400
- }
401
- return await this.getCurrentAddressBip32Path(xpub, isChangeAddress);
402
- };
403
- this.updateReceivingAddress = async () => {
404
- const vault = this.getVault();
405
- const { accounts, activeAccount } = vault;
406
- const account = accounts[activeAccount.type]?.[activeAccount.id];
407
- if (!account) {
408
- throw new Error('Active account not found');
409
- }
328
+ this.getActiveUtxoAddressAccount = (id, ownedRead) => {
329
+ const captured = (0, syscoin_core_1.captureOwnedSyscoinRead)(ownedRead, this.getAccountsState, this.capturePsbtSigningContext);
330
+ if (id !== captured.accountId)
331
+ throw new Error('UTXO account is not active');
332
+ const account = this.getVault().accounts[captured.accountType]?.[id];
333
+ captured.read.assertCurrent();
334
+ return { account, read: captured.read };
335
+ };
336
+ this.getNewChangeAddress = (ownedRead) => this.getChangeAddress(this.getVault().activeAccount.id, ownedRead);
337
+ this.getChangeAddress = async (id, ownedRead) => {
338
+ const { account, read } = this.getActiveUtxoAddressAccount(id, ownedRead);
339
+ return this.getAddressForUtxoAccount(account, true, read);
340
+ };
341
+ this.getPubkey = async (id, isChangeAddress, ownedRead) => {
342
+ const { account, read } = this.getActiveUtxoAddressAccount(id, ownedRead);
343
+ this.assertUtxoDerivationAvailable(account, 'Public key');
344
+ return this.getAddressPubkey(isChangeAddress, read);
345
+ };
346
+ this.getBip32Path = async (id, isChangeAddress, ownedRead) => {
347
+ const { account, read } = this.getActiveUtxoAddressAccount(id, ownedRead);
348
+ this.assertUtxoDerivationAvailable(account, 'BIP32 path');
349
+ return this.getAddressBip32Path(id, isChangeAddress, read);
350
+ };
351
+ this.updateReceivingAddress = async (ownedRead) => {
352
+ const { account, read } = this.getActiveUtxoAddressAccount(this.getVault().activeAccount.id, ownedRead);
353
+ return this.getAddressForUtxoAccount(account, false, read);
354
+ };
355
+ this.getAddressForUtxoAccount = (account, change, read) => {
410
356
  const { xpub, isImported, address } = account;
411
357
  if (isImported &&
412
358
  xpub === address &&
413
359
  !this.isDescriptor(xpub) &&
414
360
  !this.isXpubLike(xpub))
415
- return address;
416
- const nextAddress = await this.getAddress(xpub, false);
417
- // NOTE: Address updates should be dispatched to Redux store, not updated here
418
- // The calling code should handle the Redux dispatch
419
- return nextAddress;
361
+ return Promise.resolve(address);
362
+ return this.discoverUtxoAddress(change, read);
420
363
  };
421
364
  this.getAccountById = (id, accountType) => {
422
365
  const vault = this.getVault();
@@ -694,62 +637,56 @@ class KeyringCore {
694
637
  };
695
638
  this.getNetwork = () => this.getVault().activeNetwork;
696
639
  this.createEthAccount = (privateKey) => (0, evm_local_signer_1.privateKeyToAccount)(privateKey);
697
- // Helper to get current account data from backend
698
- this.fetchCurrentAccountData = async (xpub, isChangeAddress) => {
699
- const vault = this.getVault();
700
- const { activeNetwork } = vault;
701
- // Use read-only signer for backend calls - works for all account types including hardware wallets
702
- const { main } = this.getReadOnlySigner();
703
- const options = 'tokens=used&details=tokens';
704
- // In-flight deduplicated: concurrent callers within a send flow
705
- // (fee estimation, PSBT creation, signing) share a single request
706
- const { tokens } = await (0, blockbook_cache_1.fetchBackendAccountCached)(main.blockbookURL, xpub, options);
640
+ this.fetchCurrentAccountData = async (isChangeAddress, read) => {
641
+ read.assertCurrent();
642
+ const { tokens } = await (0, owned_blockbook_account_1.fetchOwnedBlockbookAccount)(read.network.url, read.xpub, read.transport);
643
+ read.assertCurrent();
707
644
  const { receivingIndex, changeIndex } = this.setLatestIndexesFromXPubTokens(tokens);
708
- // Get network configuration for BIP84 using network-provided pub type macros
709
- const networkConfig = (0, sysweb3_network_1.getNetworkConfig)(activeNetwork.slip44, activeNetwork.currency);
710
- const pubTypes = networkConfig?.types?.zPubType;
711
- if (!pubTypes) {
712
- throw new Error('Missing zPubType in network configuration');
713
- }
714
- const networks = networkConfig.networks;
715
- const currentAccount = new BIP84.fromZPub(xpub, pubTypes, networks);
716
- const addressIndex = isChangeAddress ? changeIndex : receivingIndex;
717
645
  return {
718
- currentAccount,
719
- addressIndex,
720
- main,
646
+ currentAccount: this.loadBip84AddressAccount(read.xpub, read.network),
647
+ addressIndex: isChangeAddress ? changeIndex : receivingIndex,
721
648
  };
722
649
  };
723
- this.getAddress = async (xpub, isChangeAddress, options) => {
724
- if (this.isDescriptor(xpub)) {
725
- // The BIP84 history scanner below cannot choose a descriptor's next
726
- // unused index. Import can derive index zero locally, but rotation must
727
- // not reinterpret a descriptor as a BIP84 extended key.
728
- if (!options?.forceIndex0) {
729
- throw new Error('Address rotation is not supported for watch-only descriptors');
730
- }
731
- return (0, watch_descriptor_1.deriveDescriptorAddress)(xpub, this.getVault().activeNetwork, {
732
- change: isChangeAddress,
733
- });
734
- }
735
- const { currentAccount, addressIndex } = await this.fetchCurrentAccountData(xpub, isChangeAddress);
736
- const effectiveIndex = options?.forceIndex0 ? 0 : addressIndex;
737
- const address = currentAccount.getAddress(effectiveIndex, isChangeAddress, 84);
738
- return address;
739
- };
740
- this.getCurrentAddressPubkey = async (xpub, isChangeAddress) => {
741
- const { currentAccount, addressIndex } = await this.fetchCurrentAccountData(xpub, isChangeAddress);
742
- // BIP84 returns the public key as a hex string directly
650
+ this.discoverUtxoAddress = async (isChangeAddress, read) => {
651
+ read.assertCurrent();
652
+ if (this.isDescriptor(read.xpub))
653
+ throw new Error('Address rotation is not supported for watch-only descriptors');
654
+ const { currentAccount, addressIndex } = await this.fetchCurrentAccountData(isChangeAddress, read);
655
+ read.assertCurrent();
656
+ return currentAccount.getAddress(addressIndex, isChangeAddress, 84);
657
+ };
658
+ this.getAddress = async (xpub, isChangeAddress, ownedRead) => {
659
+ const id = this.getVault().activeAccount.id;
660
+ const { account, read } = this.getActiveUtxoAddressAccount(id, ownedRead);
661
+ if (xpub !== read.xpub)
662
+ throw new Error('UTXO account is not active');
663
+ return this.getAddressForUtxoAccount(account, isChangeAddress, read);
664
+ };
665
+ this.getAddressPubkey = async (isChangeAddress, read) => {
666
+ const { currentAccount, addressIndex } = await this.fetchCurrentAccountData(isChangeAddress, read);
667
+ read.assertCurrent();
743
668
  return currentAccount.getPublicKey(addressIndex, isChangeAddress);
744
669
  };
745
- this.getCurrentAddressBip32Path = async (xpub, isChangeAddress) => {
746
- const vault = this.getVault();
747
- const { activeAccount, activeNetwork } = vault;
748
- const { addressIndex } = await this.fetchCurrentAccountData(xpub, isChangeAddress);
749
- // Use the utility function to generate the proper derivation path
750
- const coinShortcut = activeNetwork.currency.toLowerCase(); // e.g., 'sys', 'btc'
751
- const path = (0, derivation_paths_1.getAddressDerivationPath)(coinShortcut, activeNetwork.slip44, activeAccount.id, isChangeAddress, addressIndex);
752
- return path;
670
+ this.getCurrentAddressPubkey = async (xpub, isChangeAddress, ownedRead) => {
671
+ const id = this.getVault().activeAccount.id;
672
+ const { account, read } = this.getActiveUtxoAddressAccount(id, ownedRead);
673
+ if (xpub !== read.xpub)
674
+ throw new Error('UTXO account is not active');
675
+ this.assertUtxoDerivationAvailable(account, 'Public key');
676
+ return this.getAddressPubkey(isChangeAddress, read);
677
+ };
678
+ this.getAddressBip32Path = async (id, isChangeAddress, read) => {
679
+ const { addressIndex } = await this.fetchCurrentAccountData(isChangeAddress, read);
680
+ read.assertCurrent();
681
+ return (0, derivation_paths_1.getAddressDerivationPath)(read.network.currency.toLowerCase(), read.network.slip44, id, isChangeAddress, addressIndex);
682
+ };
683
+ this.getCurrentAddressBip32Path = async (xpub, isChangeAddress, ownedRead) => {
684
+ const id = this.getVault().activeAccount.id;
685
+ const { account, read } = this.getActiveUtxoAddressAccount(id, ownedRead);
686
+ if (xpub !== read.xpub)
687
+ throw new Error('UTXO account is not active');
688
+ this.assertUtxoDerivationAvailable(account, 'BIP32 path');
689
+ return this.getAddressBip32Path(id, isChangeAddress, read);
753
690
  };
754
691
  this.logout = () => {
755
692
  this.lockWallet();
@@ -835,8 +772,9 @@ class KeyringCore {
835
772
  throw error;
836
773
  }
837
774
  };
838
- this.capturePsbtSigningContext = () => {
775
+ this.capturePsbtSigningContext = (bindSessionRevision = true) => {
839
776
  const session = this.sessionPassword;
777
+ const revision = this.privateRecordSessionRevision;
840
778
  const vault = this.getVault();
841
779
  const selected = { ...vault.activeAccount };
842
780
  const account = vault.accounts[selected.type]?.[selected.id];
@@ -848,6 +786,8 @@ class KeyringCore {
848
786
  if (!session ||
849
787
  session.isCleared() ||
850
788
  this.sessionPassword !== session ||
789
+ (bindSessionRevision &&
790
+ this.privateRecordSessionRevision !== revision) ||
851
791
  current.activeAccount.id !== selected.id ||
852
792
  current.activeAccount.type !== selected.type ||
853
793
  currentAccount?.address !== identity.address ||
@@ -950,22 +890,32 @@ class KeyringCore {
950
890
  };
951
891
  };
952
892
  // Read-only version that works when wallet is locked
953
- this.getReadOnlySigner = () => {
954
- if (this.getActiveChain() !== sysweb3_network_1.INetworkType.Syscoin) {
893
+ this.getReadOnlySigner = (ownedRead) => {
894
+ ownedRead?.assertCurrent();
895
+ if ((ownedRead ? ownedRead.network.kind : this.getActiveChain()) !==
896
+ sysweb3_network_1.INetworkType.Syscoin) {
955
897
  throw new Error('Switch to UTXO chain');
956
898
  }
957
899
  // Create syscoinjs instance without HD signer for read-only operations
958
- const vault = this.getVault();
959
- const network = vault.activeNetwork;
900
+ const network = ownedRead?.network ?? this.getVault().activeNetwork;
960
901
  const networkConfig = (0, sysweb3_network_1.getNetworkConfig)(network.slip44, network.currency);
961
902
  const isTestnet = network.slip44 === 1;
962
903
  const bitcoinjsNetwork = isTestnet
963
904
  ? networkConfig?.networks?.testnet
964
905
  : networkConfig?.networks?.mainnet;
906
+ if (ownedRead && !bitcoinjsNetwork)
907
+ throw new Error('Missing owned UTXO network configuration');
965
908
  const syscoinMainSigner = new syscoinjs.SyscoinJSLib(null, // No HD signer needed for read-only operations
966
- network.url, bitcoinjsNetwork);
909
+ network.url, bitcoinjsNetwork, ...(ownedRead ? [ownedRead.transport] : []));
910
+ if (!ownedRead)
911
+ return { main: syscoinMainSigner };
967
912
  return {
968
913
  main: syscoinMainSigner,
914
+ getOwnedAddress: (xpub, isChangeAddress) => {
915
+ if (xpub !== ownedRead.xpub)
916
+ throw new Error('UTXO account is not active');
917
+ return this.discoverUtxoAddress(isChangeAddress, ownedRead);
918
+ },
969
919
  };
970
920
  };
971
921
  this.getAccountsState = () => {
@@ -1157,10 +1107,13 @@ class KeyringCore {
1157
1107
  if (!BIP84.validateMnemonic(seedPhrase)) {
1158
1108
  throw new Error('Invalid Seed');
1159
1109
  }
1110
+ const assertCurrent = __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_captureSessionGuard).call(this);
1111
+ assertCurrent();
1160
1112
  const [vault, vaultKeys] = await Promise.all([
1161
1113
  this.storage.get('vault'),
1162
1114
  this.storage.get('vault-keys'),
1163
1115
  ]);
1116
+ assertCurrent();
1164
1117
  const hasVault = vault !== undefined && vault !== null;
1165
1118
  const hasVaultKeys = vaultKeys !== undefined && vaultKeys !== null;
1166
1119
  const livePassword = this.sessionPassword;
@@ -1175,6 +1128,7 @@ class KeyringCore {
1175
1128
  throw new Error('Cannot initialize a new vault over existing wallet storage');
1176
1129
  }
1177
1130
  const sessionPasswordSaltedHash = await this.deriveStoredSessionKey(password, vaultKeys);
1131
+ assertCurrent();
1178
1132
  if (livePassword === this.sessionPassword &&
1179
1133
  liveMnemonic === this.sessionMnemonic &&
1180
1134
  sessionPasswordSaltedHash === this.getSessionPasswordString()) {
@@ -1190,6 +1144,7 @@ class KeyringCore {
1190
1144
  }
1191
1145
  if (currentMnemonic === seedPhrase) {
1192
1146
  const storedVault = await this.vaultPersistence.getDecryptedVault(sessionPasswordSaltedHash);
1147
+ assertCurrent();
1193
1148
  if (livePassword === this.sessionPassword &&
1194
1149
  liveMnemonic === this.sessionMnemonic &&
1195
1150
  !livePassword.isCleared() &&
@@ -1215,8 +1170,10 @@ class KeyringCore {
1215
1170
  mnemonic: seedPhrase, // Store plain mnemonic - setEncryptedVault will encrypt the entire vault
1216
1171
  },
1217
1172
  // v4 vault is encrypted with the derived session password key (PBKDF2 output)
1218
- sessionPasswordSaltedHash, { salt });
1219
- await __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_recreateSessionFromVault).call(this, sessionPasswordSaltedHash);
1173
+ sessionPasswordSaltedHash, { salt }, assertCurrent);
1174
+ assertCurrent();
1175
+ const assertInstalled = await __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_recreateSessionFromVault).call(this, sessionPasswordSaltedHash, assertCurrent);
1176
+ assertInstalled();
1220
1177
  };
1221
1178
  // NEW: Create first account without signer setup
1222
1179
  this.createFirstAccount = async (label) => {
@@ -1255,27 +1212,17 @@ class KeyringCore {
1255
1212
  await this.initializeSession(seedPhrase, password);
1256
1213
  return await this.createFirstAccount();
1257
1214
  };
1258
- if (!dependencies ||
1259
- typeof dependencies.authority !== 'object' ||
1260
- dependencies.authority === null) {
1261
- throw new TypeError('Keyring core requires an explicit wallet authority');
1262
- }
1263
- if (typeof dependencies.vaultPersistence?.getDecryptedVault !== 'function' ||
1264
- typeof dependencies.vaultPersistence?.setEncryptedVault !== 'function') {
1265
- throw new TypeError('Keyring core requires bound vault persistence');
1266
- }
1215
+ const dependencies = (0, keyring_host_1.takeKeyringHostBinding)(binding);
1267
1216
  this.authority = dependencies.authority;
1268
- if (dependencies.sessionOwner) {
1269
- __classPrivateFieldSet(this, _KeyringCore_sessionOwnership, {
1270
- tracker: dependencies.sessionOwner,
1271
- token: Symbol(),
1272
- }, "f");
1273
- }
1217
+ __classPrivateFieldSet(this, _KeyringCore_sessionOwnership, {
1218
+ tracker: dependencies.sessionOwner,
1219
+ token: Symbol(),
1220
+ }, "f");
1274
1221
  this.storage = dependencies.storage;
1275
1222
  this.vaultPersistence = dependencies.vaultPersistence;
1276
- this.ledgerSigner = dependencies.ledgerSigner;
1277
- this.trezorSigner = dependencies.trezorSigner;
1278
- this.syscoinHardwareSigners = { ...dependencies.syscoinHardwareSigners };
1223
+ this.ledgerSigner = hardware.ledgerSigner;
1224
+ this.trezorSigner = hardware.trezorSigner;
1225
+ this.syscoinHardwareSigners = { ...hardware.syscoinHardwareSigners };
1279
1226
  this.writeUtf8Diagnostic(false);
1280
1227
  this.utf8Error = false;
1281
1228
  this.initialTrezorAccountState = initial_state_1.initialActiveTrezorAccountState;
@@ -1283,8 +1230,6 @@ class KeyringCore {
1283
1230
  this.syscoinTransaction = this.createSyscoinTransactions();
1284
1231
  this.ethereumTransaction = new ethereum_1.EthereumTransactions(this.getNetwork, this.getDecryptedPrivateKey, this.getAccountsState, this.ledgerSigner, this.trezorSigner, this.capturePsbtSigningContext, dependencies.captureEvmSubmission);
1285
1232
  if (dependencies.deviceUnlock) {
1286
- if (!__classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f"))
1287
- throw new TypeError('Device unlock requires a session owner');
1288
1233
  const { port, receive } = dependencies.deviceUnlock;
1289
1234
  const readVaultPair = this.storage.readDeviceUnlockVaultPair;
1290
1235
  if (typeof readVaultPair !== 'function')
@@ -1313,25 +1258,28 @@ class KeyringCore {
1313
1258
  let assertCurrent = __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_captureSessionGuard).call(this);
1314
1259
  let authenticated = false;
1315
1260
  try {
1316
- assertCurrent?.();
1261
+ assertCurrent();
1317
1262
  const vaultKeys = await this.storage.get('vault-keys');
1318
- assertCurrent?.();
1319
1263
  if (!vaultKeys) {
1264
+ assertCurrent();
1320
1265
  throw new Error('Vault keys not found. Reload the wallet and try again.');
1321
1266
  }
1322
1267
  // v4: Validate password by deriving the session key once and decrypting the vault with it.
1323
1268
  // This avoids an extra KDF pass just for a stored verifier.
1324
1269
  const { salt } = vaultKeys;
1325
- const readVaultPair = assertCurrent
1326
- ? this.storage.readDeviceUnlockVaultPair
1327
- : undefined;
1270
+ const readVaultPair = this.storage.readDeviceUnlockVaultPair;
1328
1271
  const accountingSalt = readVaultPair
1329
1272
  ? currentVaultSalt(vaultKeys)
1330
1273
  : undefined;
1274
+ // Permit only an authenticated negative verdict for the same atomic
1275
+ // pair after cancellation. Legacy migration and positive results stay guarded.
1276
+ if (accountingSalt === undefined)
1277
+ assertCurrent();
1331
1278
  // Derive session encryption key (in-memory only) used to encrypt/decrypt xprv fields
1332
1279
  // IMPORTANT: This MUST NOT be the same value as the stored verifier above.
1333
1280
  let sessionPasswordKey = await this.deriveStoredSessionKey(password, accountingSalt === undefined ? vaultKeys : { salt: accountingSalt });
1334
- assertCurrent?.();
1281
+ if (accountingSalt === undefined)
1282
+ assertCurrent();
1335
1283
  // Handle migration from old vault format with currentSessionSalt
1336
1284
  if (vaultKeys.currentSessionSalt) {
1337
1285
  console.log('[KeyringManager] Detected old vault format, handling session migration...');
@@ -1342,7 +1290,7 @@ class KeyringCore {
1342
1290
  // derived key. Selecting by stored format also permits a safe retry
1343
1291
  // if the vault write succeeded but the metadata write was interrupted.
1344
1292
  const { mnemonic } = await this.vaultPersistence.getDecryptedVault(sessionPasswordKey, password);
1345
- assertCurrent?.();
1293
+ assertCurrent();
1346
1294
  authenticated = true;
1347
1295
  const isValidSecret = (value) => {
1348
1296
  if (typeof value !== 'string' || !value)
@@ -1383,15 +1331,15 @@ class KeyringCore {
1383
1331
  }
1384
1332
  // Do not change either stored record until a valid secret is recovered.
1385
1333
  await this.vaultPersistence.setEncryptedVault({ mnemonic: decryptedMnemonic }, sessionPasswordKey, undefined, assertCurrent);
1386
- assertCurrent?.();
1334
+ assertCurrent();
1387
1335
  console.log('[KeyringManager] Vault mnemonic format normalized');
1388
1336
  // Remove currentSessionSalt from vault-keys (v4 keeps only the salt on disk)
1389
1337
  const migratedVaultKeys = {
1390
1338
  salt: vaultKeys.salt,
1391
1339
  };
1392
- assertCurrent?.();
1340
+ assertCurrent();
1393
1341
  await this.storage.set('vault-keys', migratedVaultKeys);
1394
- assertCurrent?.();
1342
+ assertCurrent();
1395
1343
  console.log('[KeyringManager] Old vault format migration completed');
1396
1344
  }
1397
1345
  // v4 vault is encrypted with the derived session password key (PBKDF2 output).
@@ -1420,7 +1368,7 @@ class KeyringCore {
1420
1368
  // available for the host counter even if its owner just retired.
1421
1369
  return { canLogin: false };
1422
1370
  }
1423
- assertCurrent?.();
1371
+ assertCurrent();
1424
1372
  // Only the historical CBC fallback used the 20k key without metadata.
1425
1373
  // Never try it for GCM, malformed records, or platform/storage failures.
1426
1374
  const rawVault = error instanceof storage_core_1.VaultAuthenticationError &&
@@ -1428,14 +1376,14 @@ class KeyringCore {
1428
1376
  !vaultKeys.currentSessionSalt
1429
1377
  ? await this.storage.get('vault')
1430
1378
  : undefined;
1431
- assertCurrent?.();
1379
+ assertCurrent();
1432
1380
  if (typeof rawVault !== 'string' || rawVault.trim().startsWith('{')) {
1433
1381
  throw error;
1434
1382
  }
1435
1383
  const legacyKey = await this.deriveLegacySessionKey(password, salt);
1436
- assertCurrent?.();
1384
+ assertCurrent();
1437
1385
  decryptedVault = await this.vaultPersistence.getDecryptedVault(legacyKey);
1438
- assertCurrent?.();
1386
+ assertCurrent();
1439
1387
  authenticated = true;
1440
1388
  sessionPasswordKey = legacyKey;
1441
1389
  // Keep the historical account wrapping key. Persist its profile before
@@ -1444,40 +1392,38 @@ class KeyringCore {
1444
1392
  ...vaultKeys,
1445
1393
  keyDerivation: LEGACY_ENCRYPTION_KDF,
1446
1394
  };
1447
- assertCurrent?.();
1395
+ assertCurrent();
1448
1396
  await this.storage.set('vault-keys', migratedVaultKeys);
1449
- assertCurrent?.();
1397
+ assertCurrent();
1450
1398
  legacyProfile = true;
1451
1399
  }
1452
- assertCurrent?.();
1400
+ assertCurrent();
1453
1401
  authenticated = true;
1454
1402
  if (legacyProfile && this.hasWebCrypto()) {
1455
1403
  const storedVault = await this.storage.get('vault');
1456
- assertCurrent?.();
1404
+ assertCurrent();
1457
1405
  if (typeof storedVault === 'string' &&
1458
1406
  !storedVault.trim().startsWith('{')) {
1459
1407
  // A failed earlier rewrap can leave the authenticated profile plus
1460
1408
  // CBC. Retry that write without changing the account wrapping key.
1461
1409
  await this.vaultPersistence.setEncryptedVault(decryptedVault, sessionPasswordKey, undefined, assertCurrent);
1462
- assertCurrent?.();
1410
+ assertCurrent();
1463
1411
  }
1464
1412
  }
1465
1413
  // If session data missing or corrupted, recreate from vault
1466
1414
  if (!this.sessionMnemonic) {
1467
1415
  assertCurrent = await __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_recreateSessionFromVault).call(this, sessionPasswordKey, assertCurrent);
1468
- if (assertCurrent) {
1469
- assertCurrent();
1470
- console.log('[KeyringManager] Session data recreated from vault');
1471
- }
1416
+ assertCurrent();
1417
+ console.log('[KeyringManager] Session data recreated from vault');
1472
1418
  }
1473
- assertCurrent?.();
1419
+ assertCurrent();
1474
1420
  const result = __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_finishUnlock).call(this);
1475
- assertCurrent?.();
1421
+ assertCurrent();
1476
1422
  return result;
1477
1423
  }
1478
1424
  catch (error) {
1479
1425
  // A superseded attempt must not report authentication or clear its winner.
1480
- assertCurrent?.();
1426
+ assertCurrent();
1481
1427
  if (!authenticated && error instanceof storage_core_1.VaultAuthenticationError) {
1482
1428
  return { canLogin: false };
1483
1429
  }
@@ -1489,6 +1435,12 @@ class KeyringCore {
1489
1435
  throw error;
1490
1436
  }
1491
1437
  }
1438
+ assertUtxoDerivationAvailable(account, field) {
1439
+ if (account.isImported && account.xpub === account.address)
1440
+ throw new Error(`${field} not available for single-address imported accounts`);
1441
+ if (this.isWatchOnlyAccount(account))
1442
+ throw new Error(`${field} not available for watch-only accounts`);
1443
+ }
1492
1444
  isWatchOnlyAccount(a) {
1493
1445
  if (a.isLedgerWallet || a.isTrezorWallet)
1494
1446
  return false;
@@ -1599,6 +1551,17 @@ class KeyringCore {
1599
1551
  throw error;
1600
1552
  }
1601
1553
  }
1554
+ loadBip84AddressAccount(xpub, network) {
1555
+ const { types, networks } = (0, sysweb3_network_1.getNetworkConfig)(network.slip44, network.currency);
1556
+ if (!types?.zPubType)
1557
+ throw new Error('Missing zPubType in network configuration');
1558
+ return new BIP84.fromZPub(xpub, types.zPubType, networks);
1559
+ }
1560
+ deriveFirstUtxoAddress(xpub, network) {
1561
+ if (this.isDescriptor(xpub))
1562
+ return (0, watch_descriptor_1.deriveDescriptorAddress)(xpub, network);
1563
+ return this.loadBip84AddressAccount(xpub, network).getAddress(0, false, 84);
1564
+ }
1602
1565
  async importAccount(privKey, label, options) {
1603
1566
  // Check if wallet is unlocked
1604
1567
  if (!this.isUnlocked()) {
@@ -1636,9 +1599,7 @@ class KeyringCore {
1636
1599
  ? types.zPubType.testnet.vpub
1637
1600
  : types.zPubType.mainnet.zpub;
1638
1601
  const bip84Key = (0, derivation_paths_1.convertExtendedKeyVersion)(identifier, target);
1639
- addressToStore = await this.getAddress(bip84Key, false, {
1640
- forceIndex0: true,
1641
- });
1602
+ addressToStore = this.deriveFirstUtxoAddress(bip84Key, activeNetwork);
1642
1603
  }
1643
1604
  // Validate duplicates across all account buckets, including passkey smart accounts.
1644
1605
  if (this.accountAddressExists(accounts, addressToStore) ||
@@ -1939,7 +1900,7 @@ class KeyringCore {
1939
1900
  if ((0, ethers_v6_1.getAddress)(key.address) !== request.account.expectedAddress)
1940
1901
  throw new Error('Prepared EVM signer address mismatch');
1941
1902
  assertCurrent();
1942
- const signed = (0, prepared_evm_1.signPreparedEvmEnvelope)(request.transaction, key.decryptedPrivateKey);
1903
+ const { signed } = (0, prepared_evm_1.signPreparedEvmEnvelope)(request.transaction, key.decryptedPrivateKey);
1943
1904
  hostGuard();
1944
1905
  assertCurrent();
1945
1906
  return signed;
@@ -2043,7 +2004,7 @@ class KeyringCore {
2043
2004
  else {
2044
2005
  // For UTXO, use the xpub to derive the address
2045
2006
  // Always use first receive address (index 0) for imported account display
2046
- address = await this.getAddress(xpub, false, { forceIndex0: true });
2007
+ address = this.deriveFirstUtxoAddress(xpub, vault.activeNetwork);
2047
2008
  }
2048
2009
  if (this.accountAddressExists(accounts, address, isEVM))
2049
2010
  throw new Error('Account already exists on your Wallet.');
@@ -2112,7 +2073,7 @@ class KeyringCore {
2112
2073
  : types.zPubType.mainnet.zpub;
2113
2074
  xpub = (0, derivation_paths_1.convertExtendedKeyVersion)(ledgerXpub, bip84Target);
2114
2075
  // Always use first receive address (index 0) for imported account display
2115
- address = await this.getAddress(xpub, false, { forceIndex0: true });
2076
+ address = this.deriveFirstUtxoAddress(xpub, vault.activeNetwork);
2116
2077
  }
2117
2078
  if (this.accountAddressExists(accounts, address, (0, derivation_paths_1.isEvmCoin)(coin, slip44)))
2118
2079
  throw new Error('Account already exists on your Wallet.');
@@ -2631,8 +2592,7 @@ class KeyringCore {
2631
2592
  */
2632
2593
  async destroy() {
2633
2594
  __classPrivateFieldSet(this, _KeyringCore_deviceUnlockRetired, true, "f");
2634
- if (__classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f"))
2635
- __classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f").destroyed = true;
2595
+ __classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f").destroyed = true;
2636
2596
  await this.lockWallet();
2637
2597
  // Clear any remaining references
2638
2598
  this.ethereumTransaction = {};
@@ -2662,7 +2622,7 @@ _KeyringCore_deviceUnlockRetired = new WeakMap(), _KeyringCore_sessionOwnership
2662
2622
  (!issuing && (this.sessionPassword || this.sessionMnemonic))) {
2663
2623
  throw new Error('Device unlock session changed');
2664
2624
  }
2665
- assertOwnership?.();
2625
+ assertOwnership();
2666
2626
  };
2667
2627
  let key;
2668
2628
  try {
@@ -2753,17 +2713,15 @@ _KeyringCore_deviceUnlockRetired = new WeakMap(), _KeyringCore_sessionOwnership
2753
2713
  if (source.authority !== this.authority ||
2754
2714
  source.storage !== this.storage ||
2755
2715
  source.vaultPersistence !== this.vaultPersistence ||
2756
- __classPrivateFieldGet(source, _KeyringCore_sessionOwnership, "f")?.tracker !== __classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f")?.tracker) {
2716
+ __classPrivateFieldGet(source, _KeyringCore_sessionOwnership, "f").tracker !== __classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f").tracker) {
2757
2717
  throw new Error('Cannot transfer session between different wallet authorities');
2758
2718
  }
2759
2719
  if (!source.sessionPassword || !source.sessionMnemonic) {
2760
2720
  throw new Error('Session data is missing during transfer');
2761
2721
  }
2762
- __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_replaceSessionBuffers).call(this, source.sessionPassword, source.sessionMnemonic, __classPrivateFieldGet(source, _KeyringCore_sessionOwnership, "f")?.token);
2722
+ __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_replaceSessionBuffers).call(this, source.sessionPassword, source.sessionMnemonic, __classPrivateFieldGet(source, _KeyringCore_sessionOwnership, "f").token);
2763
2723
  }, _KeyringCore_assertSessionOwner = function _KeyringCore_assertSessionOwner(sourceToken) {
2764
2724
  const ownership = __classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f");
2765
- if (!ownership)
2766
- return;
2767
2725
  if (ownership.destroyed)
2768
2726
  throw new Error('Wallet keyring was destroyed');
2769
2727
  const owner = ownership.tracker.current;
@@ -2774,8 +2732,6 @@ _KeyringCore_deviceUnlockRetired = new WeakMap(), _KeyringCore_sessionOwnership
2774
2732
  }
2775
2733
  }, _KeyringCore_captureSessionGuard = function _KeyringCore_captureSessionGuard(message = 'Wallet unlock session changed') {
2776
2734
  const ownership = __classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f");
2777
- if (!ownership)
2778
- return undefined;
2779
2735
  const revision = this.privateRecordSessionRevision;
2780
2736
  const epoch = ownership.tracker.epoch;
2781
2737
  return () => {
@@ -2800,10 +2756,8 @@ _KeyringCore_deviceUnlockRetired = new WeakMap(), _KeyringCore_sessionOwnership
2800
2756
  this.sessionPassword = sessionPassword;
2801
2757
  this.sessionMnemonic = sessionMnemonic;
2802
2758
  const ownership = __classPrivateFieldGet(this, _KeyringCore_sessionOwnership, "f");
2803
- if (ownership) {
2804
- ownership.tracker.current = ownership.token;
2805
- ownership.tracker.epoch++;
2806
- }
2759
+ ownership.tracker.current = ownership.token;
2760
+ ownership.tracker.epoch++;
2807
2761
  }, _KeyringCore_finishUnlock = function _KeyringCore_finishUnlock() {
2808
2762
  // Re-initialize syscoin transaction handler if it was cleared on lock.
2809
2763
  // `lockWallet()` intentionally replaces it with a plain object to drop signer references,
@@ -2851,16 +2805,13 @@ _KeyringCore_deviceUnlockRetired = new WeakMap(), _KeyringCore_sessionOwnership
2851
2805
  // v4 vault is encrypted with the derived session password key (PBKDF2 output)
2852
2806
  // `saltedHashPassword` is the derived session password key passed by caller.
2853
2807
  const { mnemonic } = await this.vaultPersistence.getDecryptedVault(saltedHashPassword);
2854
- assertCurrent?.();
2808
+ assertCurrent();
2855
2809
  if (!mnemonic) {
2856
2810
  throw new Error('Mnemonic not found in vault');
2857
2811
  }
2858
2812
  __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_installVaultSession).call(this, mnemonic, saltedHashPassword, assertCurrent);
2859
2813
  // Capture the installed revision before returning to the async caller.
2860
- if (assertCurrent)
2861
- return __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_captureSessionGuard).call(this);
2862
- console.log('[KeyringManager] Session data recreated from vault');
2863
- return undefined;
2814
+ return __classPrivateFieldGet(this, _KeyringCore_instances, "m", _KeyringCore_captureSessionGuard).call(this);
2864
2815
  }
2865
2816
  catch (error) {
2866
2817
  console.error('ERROR recreateSessionFromVault', { error });