diff --git a/src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts b/src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts index e8d872f3161..f3863e6ae63 100644 --- a/src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts +++ b/src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts @@ -3,7 +3,7 @@ import { useMemo } from 'react'; import { createSelector } from '@reduxjs/toolkit'; import { HDKey, Versions } from '@scure/bip32'; -import { NetworkModes } from '@shared/constants'; +import { BitcoinNetworkModes } from '@shared/constants'; import { getBtcSignerLibNetworkConfigByMode } from '@shared/crypto/bitcoin/bitcoin.network'; import { BitcoinAccount, @@ -25,11 +25,11 @@ import { useCurrentNetwork } from '@app/store/networks/networks.selectors'; export function bitcoinAccountBuilderFactory( softwareKeychainDerivationFn: ( key: HDKey, - network: NetworkModes + network: BitcoinNetworkModes ) => (accountIndex: number) => BitcoinAccount, ledgerKeychainLookupFn: ( keyMap: Record, - network: NetworkModes + network: BitcoinNetworkModes ) => (accountIndex: number) => BitcoinAccount | undefined ) { return createSelector( @@ -42,12 +42,16 @@ export function bitcoinAccountBuilderFactory( return { mainnet: ledgerKeychainLookupFn(bitcoinLedgerKeys, 'mainnet'), testnet: ledgerKeychainLookupFn(bitcoinLedgerKeys, 'testnet'), + signet: ledgerKeychainLookupFn(bitcoinLedgerKeys, 'signet'), + regtest: ledgerKeychainLookupFn(bitcoinLedgerKeys, 'regtest'), }; } if (!rootKeychain) throw new Error('No in-memory key found'); return { mainnet: softwareKeychainDerivationFn(rootKeychain, 'mainnet'), testnet: softwareKeychainDerivationFn(rootKeychain, 'testnet'), + signet: softwareKeychainDerivationFn(rootKeychain, 'signet'), + regtest: softwareKeychainDerivationFn(rootKeychain, 'regtest'), }; } ); diff --git a/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts b/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts index decaef452bb..1cd16177fc1 100644 --- a/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts +++ b/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts @@ -4,7 +4,6 @@ import { useSelector } from 'react-redux'; import { createSelector } from '@reduxjs/toolkit'; import { - bitcoinNetworkModeToCoreNetworkMode, deriveAddressIndexZeroFromAccount, lookUpLedgerKeysByPath, } from '@shared/crypto/bitcoin/bitcoin.utils'; @@ -36,8 +35,7 @@ const selectNativeSegwitAccountBuilder = bitcoinAccountBuilderFactory( const selectCurrentNetworkNativeSegwitAccountBuilder = createSelector( selectNativeSegwitAccountBuilder, selectCurrentNetwork, - (nativeSegwitKeychain, network) => - nativeSegwitKeychain[bitcoinNetworkModeToCoreNetworkMode(network.chain.bitcoin.network)] + (nativeSegwitKeychains, network) => nativeSegwitKeychains[network.chain.bitcoin.network] ); export function useNativeSegwitAccountBuilder() { @@ -72,6 +70,7 @@ function useNativeSegwitSigner(accountIndex: number) { return useMemo(() => { if (!account) return; + // console.log(account); return bitcoinAddressIndexSignerFactory({ accountIndex, accountKeychain: account.keychain, diff --git a/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts b/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts index d7f8b7c1c6a..156cea61933 100644 --- a/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts +++ b/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts @@ -35,8 +35,7 @@ const selectTaprootAccountBuilder = bitcoinAccountBuilderFactory( const selectCurrentNetworkTaprootAccountBuilder = createSelector( selectTaprootAccountBuilder, selectCurrentNetwork, - (taprootKeychain, network) => - taprootKeychain[bitcoinNetworkModeToCoreNetworkMode(network.chain.bitcoin.network)] + (taprootKeychains, network) => taprootKeychains[network.chain.bitcoin.network] ); const selectCurrentTaprootAccount = createSelector( selectCurrentNetworkTaprootAccountBuilder, diff --git a/src/app/store/accounts/blockchain/stacks/stacks-accounts.ts b/src/app/store/accounts/blockchain/stacks/stacks-accounts.ts index ab866a0871e..bb00b258fbf 100644 --- a/src/app/store/accounts/blockchain/stacks/stacks-accounts.ts +++ b/src/app/store/accounts/blockchain/stacks/stacks-accounts.ts @@ -25,7 +25,7 @@ import { import { selectLedgerKey } from '@app/store/keys/key.selectors'; import { addressNetworkVersionState } from '@app/store/transactions/transaction'; -import { defaultKeyId } from '../../../keys/key.slice'; +import { defaultWalletKeyId } from '../../../keys/key.slice'; import { HardwareStacksAccount, SoftwareStacksAccount, @@ -62,7 +62,7 @@ const selectStacksWalletState = createSelector( selectStacksChain, (keychain, chain) => { if (!keychain) return; - const { highestAccountIndex, currentAccountIndex } = chain[defaultKeyId]; + const { highestAccountIndex, currentAccountIndex } = chain[defaultWalletKeyId]; const numberOfAccountsToDerive = Math.max(highestAccountIndex, currentAccountIndex) + 1; return createNullArrayOfLength(numberOfAccountsToDerive).map((_, index) => initalizeStacksAccount(keychain, index) diff --git a/src/app/store/chains/stx-chain.slice.ts b/src/app/store/chains/stx-chain.slice.ts index 4412b542ffb..dc3005b4a81 100644 --- a/src/app/store/chains/stx-chain.slice.ts +++ b/src/app/store/chains/stx-chain.slice.ts @@ -1,6 +1,6 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; -import { defaultKeyId, keySlice } from '../keys/key.slice'; +import { defaultWalletKeyId, keySlice } from '../keys/key.slice'; interface StxChainKeyState { highestAccountIndex: number; @@ -8,7 +8,7 @@ interface StxChainKeyState { } const initialState: Record = { - [defaultKeyId]: { + [defaultWalletKeyId]: { highestAccountIndex: 0, currentAccountIndex: 0, }, diff --git a/src/app/store/in-memory-key/in-memory-key.selectors.ts b/src/app/store/in-memory-key/in-memory-key.selectors.ts index 80bd6032180..de0b863c35d 100644 --- a/src/app/store/in-memory-key/in-memory-key.selectors.ts +++ b/src/app/store/in-memory-key/in-memory-key.selectors.ts @@ -5,13 +5,13 @@ import { createSelector } from '@reduxjs/toolkit'; import { mnemonicToRootNode } from '@app/common/keychain/keychain'; import { RootState } from '..'; -import { defaultKeyId } from '../keys/key.slice'; +import { defaultWalletKeyId } from '../keys/key.slice'; const selectInMemoryKey = (state: RootState) => state.inMemoryKeys; export const selectDefaultWalletKey = createSelector( selectInMemoryKey, - state => state.keys[defaultKeyId] + state => state.keys[defaultWalletKeyId] ); export const selectRootKeychain = createSelector(selectDefaultWalletKey, key => { diff --git a/src/app/store/in-memory-key/in-memory-key.slice.ts b/src/app/store/in-memory-key/in-memory-key.slice.ts index f95ef155d7e..ba15ed0a099 100644 --- a/src/app/store/in-memory-key/in-memory-key.slice.ts +++ b/src/app/store/in-memory-key/in-memory-key.slice.ts @@ -2,7 +2,7 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; import { logger } from '@shared/logger'; -import { defaultKeyId, keySlice } from '../keys/key.slice'; +import { defaultWalletKeyId, keySlice } from '../keys/key.slice'; interface InMemoryKeyState { hasRestoredKeys: boolean; @@ -20,15 +20,15 @@ export const inMemoryKeySlice = createSlice({ reducers: { generateWalletKey(state, action: PayloadAction) { - if (state.keys[defaultKeyId]) { + if (state.keys[defaultWalletKeyId]) { logger.warn('Not generating another wallet, already exists.'); return; } - state.keys[defaultKeyId] = action.payload; + state.keys[defaultWalletKeyId] = action.payload; }, saveUsersSecretKeyToBeRestored(state, action: PayloadAction) { - state.keys[defaultKeyId] = action.payload; + state.keys[defaultWalletKeyId] = action.payload; }, setKeysInMemory(state, action: PayloadAction>) { diff --git a/src/app/store/keys/key.actions.ts b/src/app/store/keys/key.actions.ts index 71c92cce452..9a29be844a8 100644 --- a/src/app/store/keys/key.actions.ts +++ b/src/app/store/keys/key.actions.ts @@ -19,7 +19,7 @@ import { stxChainSlice } from '../chains/stx-chain.slice'; import { selectDefaultWalletKey } from '../in-memory-key/in-memory-key.selectors'; import { inMemoryKeySlice } from '../in-memory-key/in-memory-key.slice'; import { selectCurrentKey } from './key.selectors'; -import { defaultKeyId, keySlice } from './key.slice'; +import { defaultWalletKeyId, keySlice } from './key.slice'; function setWalletEncryptionPassword(args: { password: string; @@ -86,7 +86,7 @@ function setWalletEncryptionPassword(args: { dispatch( keySlice.actions.createStacksSoftwareWalletComplete({ type: 'software', - id: defaultKeyId, + id: defaultWalletKeyId, salt, encryptedSecretKey, }) diff --git a/src/app/store/keys/key.selectors.ts b/src/app/store/keys/key.selectors.ts index be2e9db854a..016d0df3b51 100644 --- a/src/app/store/keys/key.selectors.ts +++ b/src/app/store/keys/key.selectors.ts @@ -7,13 +7,13 @@ import { initBigNumber } from '@app/common/math/helpers'; import { RootState } from '@app/store'; import { selectStacksChain } from '../chains/stx-chain.selectors'; -import { defaultKeyId } from './key.slice'; +import { defaultWalletKeyId } from './key.slice'; const selectKeysSlice = (state: RootState) => state.keys; export const selectCurrentKey = createSelector( selectKeysSlice, - state => state.entities[defaultKeyId] + state => state.entities[defaultWalletKeyId] ); export function useCurrentKeyDetails() { @@ -25,7 +25,7 @@ export const selectCurrentAccountIndex = createSelector(selectStacksChain, state if (customAccountIndex && initBigNumber(customAccountIndex).isInteger()) { return initBigNumber(customAccountIndex).toNumber(); } - return state[defaultKeyId].currentAccountIndex; + return state[defaultWalletKeyId].currentAccountIndex; }); export const selectLedgerKey = createSelector(selectKeysSlice, keys => { diff --git a/src/app/store/keys/key.slice.ts b/src/app/store/keys/key.slice.ts index 1e2fc8a79a6..8e55b28e133 100644 --- a/src/app/store/keys/key.slice.ts +++ b/src/app/store/keys/key.slice.ts @@ -4,7 +4,7 @@ import { StxAndIdentityPublicKeys } from '@app/features/ledger/utils/stacks-ledg import { migrateVaultReducerStoreToNewStateStructure } from '../utils/vault-reducer-migration'; -export const defaultKeyId = 'default' as const; +export const defaultWalletKeyId = 'default' as const; interface KeyConfigSoftware { type: 'software'; @@ -38,7 +38,7 @@ export const keySlice = createSlice({ }, signOut(state) { - keyAdapter.removeOne(state, defaultKeyId); + keyAdapter.removeOne(state, defaultWalletKeyId); }, debugKillStacks(state) { diff --git a/src/app/store/ledger/bitcoin-key.slice.ts b/src/app/store/ledger/bitcoin-key.slice.ts index 8a3a36f32f4..f33a46e7162 100644 --- a/src/app/store/ledger/bitcoin-key.slice.ts +++ b/src/app/store/ledger/bitcoin-key.slice.ts @@ -3,7 +3,7 @@ import { PayloadAction, createEntityAdapter, createSlice } from '@reduxjs/toolki import { BitcoinLedgerAccountDetails } from '@app/features/ledger/utils/bitcoin-ledger-utils'; import { RootState } from '..'; -import { defaultKeyId } from '../keys/key.slice'; +import { defaultWalletKeyId } from '../keys/key.slice'; interface PersistedBitcoinKeys extends BitcoinLedgerAccountDetails { walletId: string; @@ -19,7 +19,7 @@ export const bitcoinKeysSlice = createSlice({ bitcoinKeyAdapter.addMany( state, // While we only support a single wallet, we default to the `default` walletId - payload.map(key => ({ ...key, walletId: defaultKeyId })) + payload.map(key => ({ ...key, walletId: defaultWalletKeyId })) ); }, }, diff --git a/src/app/store/utils/vault-reducer-migration.spec.ts b/src/app/store/utils/vault-reducer-migration.spec.ts index ca09465ca3a..f2ae9ad840a 100644 --- a/src/app/store/utils/vault-reducer-migration.spec.ts +++ b/src/app/store/utils/vault-reducer-migration.spec.ts @@ -1,7 +1,7 @@ import { LocalStorageMock } from '@tests/unit/local-storage-mock'; import { vi } from 'vitest'; -import { defaultKeyId } from '../keys/key.slice'; +import { defaultWalletKeyId } from '../keys/key.slice'; import { migrateVaultReducerStoreToNewStateStructure } from './vault-reducer-migration'; (globalThis as any).localStorage = new LocalStorageMock(); @@ -32,11 +32,11 @@ describe(migrateVaultReducerStoreToNewStateStructure.name, () => { test('that it returns a migrated state object when wallet values are detected', () => { const returnedValue = migrateVaultReducerStoreToNewStateStructure({} as any); expect(returnedValue).toEqual({ - ids: [defaultKeyId], + ids: [defaultWalletKeyId], entities: { - [defaultKeyId]: { + [defaultWalletKeyId]: { type: 'software', - id: defaultKeyId, + id: defaultWalletKeyId, encryptedSecretKey: 'test-encrypted-key', salt: 'test-salt', }, diff --git a/src/shared/crypto/bitcoin/bitcoin.utils.ts b/src/shared/crypto/bitcoin/bitcoin.utils.ts index 5b9b2e27592..8f0ee95076d 100644 --- a/src/shared/crypto/bitcoin/bitcoin.utils.ts +++ b/src/shared/crypto/bitcoin/bitcoin.utils.ts @@ -6,6 +6,8 @@ import * as btc from '@scure/btc-signer'; import { BitcoinNetworkModes, NetworkModes } from '@shared/constants'; import { whenNetwork } from '@shared/utils'; +import { defaultWalletKeyId } from '@app/store/keys/key.slice'; + import { DerivationPathDepth } from '../derivation-path.utils'; import { BtcSignerNetwork } from './bitcoin.network'; import { getTaprootPayment } from './p2tr-address-gen'; @@ -173,13 +175,16 @@ export function getHdKeyVersionsFromNetwork(network: NetworkModes) { // Ledger wallets are keyed by their derivation path. To reuse the look up logic // between payment types, this factory fn accepts a fn that generates the path export function lookUpLedgerKeysByPath( - derivationPathFn: (network: BitcoinNetworkModes, accountIndex: number) => string + getDerivationPath: (network: BitcoinNetworkModes, accountIndex: number) => string ) { - return (keyMap: Record, network: NetworkModes) => + return ( + ledgerKeyMap: Record, + network: BitcoinNetworkModes + ) => (accountIndex: number) => { - const path = derivationPathFn(network, accountIndex); + const path = getDerivationPath(network, accountIndex); // Single wallet mode, hardcoded default walletId - const account = keyMap[path.replace('m', 'default')]; + const account = ledgerKeyMap[path.replace('m', defaultWalletKeyId)]; if (!account) return; return initBitcoinAccount(path, account.policy); }; diff --git a/src/shared/crypto/bitcoin/p2wpkh-address-gen.ts b/src/shared/crypto/bitcoin/p2wpkh-address-gen.ts index cf288af4a05..e21d418c608 100644 --- a/src/shared/crypto/bitcoin/p2wpkh-address-gen.ts +++ b/src/shared/crypto/bitcoin/p2wpkh-address-gen.ts @@ -1,7 +1,7 @@ import { HDKey } from '@scure/bip32'; import * as btc from '@scure/btc-signer'; -import { BitcoinNetworkModes, NetworkModes } from '@shared/constants'; +import { BitcoinNetworkModes } from '@shared/constants'; import { DerivationPathDepth } from '../derivation-path.utils'; import { getBtcSignerLibNetworkConfigByMode } from './bitcoin.network'; @@ -26,7 +26,10 @@ export function getNativeSegwitAddressIndexDerivationPath( return getNativeSegwitAccountDerivationPath(network, accountIndex) + `/0/${addressIndex}`; } -export function deriveNativeSegwitAccountFromRootKeychain(keychain: HDKey, network: NetworkModes) { +export function deriveNativeSegwitAccountFromRootKeychain( + keychain: HDKey, + network: BitcoinNetworkModes +) { if (keychain.depth !== DerivationPathDepth.Root) throw new Error('Keychain passed is not a root'); return (accountIndex: number): BitcoinAccount => ({ type: 'p2wpkh',