Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: regtest addresses, closes #4223 #4331

Merged
merged 1 commit into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<string, { policy: string } | undefined>,
network: NetworkModes
network: BitcoinNetworkModes
) => (accountIndex: number) => BitcoinAccount | undefined
) {
return createSelector(
Expand All @@ -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'),
};
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useSelector } from 'react-redux';
import { createSelector } from '@reduxjs/toolkit';

import {
bitcoinNetworkModeToCoreNetworkMode,
deriveAddressIndexZeroFromAccount,
lookUpLedgerKeysByPath,
} from '@shared/crypto/bitcoin/bitcoin.utils';
Expand Down Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import { useSelector } from 'react-redux';
import { createSelector } from '@reduxjs/toolkit';

import { BitcoinNetworkModes } from '@shared/constants';
import {
bitcoinNetworkModeToCoreNetworkMode,
lookUpLedgerKeysByPath,
} from '@shared/crypto/bitcoin/bitcoin.utils';
import { lookUpLedgerKeysByPath } from '@shared/crypto/bitcoin/bitcoin.utils';
import {
deriveTaprootAccount,
getTaprootAccountDerivationPath,
Expand Down Expand Up @@ -35,8 +32,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,
Expand Down
4 changes: 2 additions & 2 deletions src/app/store/accounts/blockchain/stacks/stacks-accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { deriveStxPrivateKey, generateWallet } from '@stacks/wallet-sdk';
import { atom } from 'jotai';

import { DATA_DERIVATION_PATH, deriveStacksSalt } from '@shared/crypto/stacks/stacks-address-gen';
import { defaultWalletKeyId } from '@shared/utils';

import { derivePublicKey } from '@app/common/keychain/keychain';
import { createNullArrayOfLength } from '@app/common/utils';
Expand All @@ -25,7 +26,6 @@ import {
import { selectLedgerKey } from '@app/store/keys/key.selectors';
import { addressNetworkVersionState } from '@app/store/transactions/transaction';

import { defaultKeyId } from '../../../keys/key.slice';
import {
HardwareStacksAccount,
SoftwareStacksAccount,
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 4 additions & 2 deletions src/app/store/chains/stx-chain.slice.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { PayloadAction, createSlice } from '@reduxjs/toolkit';

import { defaultKeyId, keySlice } from '../keys/key.slice';
import { defaultWalletKeyId } from '@shared/utils';

import { keySlice } from '../keys/key.slice';

interface StxChainKeyState {
highestAccountIndex: number;
currentAccountIndex: number;
}

const initialState: Record<string, StxChainKeyState> = {
[defaultKeyId]: {
[defaultWalletKeyId]: {
highestAccountIndex: 0,
currentAccountIndex: 0,
},
Expand Down
5 changes: 3 additions & 2 deletions src/app/store/in-memory-key/in-memory-key.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import { useSelector } from 'react-redux';

import { createSelector } from '@reduxjs/toolkit';

import { defaultWalletKeyId } from '@shared/utils';

import { mnemonicToRootNode } from '@app/common/keychain/keychain';

import { RootState } from '..';
import { defaultKeyId } 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 => {
Expand Down
9 changes: 5 additions & 4 deletions src/app/store/in-memory-key/in-memory-key.slice.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { PayloadAction, createSlice } from '@reduxjs/toolkit';

import { logger } from '@shared/logger';
import { defaultWalletKeyId } from '@shared/utils';

import { defaultKeyId, keySlice } from '../keys/key.slice';
import { keySlice } from '../keys/key.slice';

interface InMemoryKeyState {
hasRestoredKeys: boolean;
Expand All @@ -20,15 +21,15 @@ export const inMemoryKeySlice = createSlice({

reducers: {
generateWalletKey(state, action: PayloadAction<string>) {
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<string>) {
state.keys[defaultKeyId] = action.payload;
state.keys[defaultWalletKeyId] = action.payload;
},

setKeysInMemory(state, action: PayloadAction<Record<string, string>>) {
Expand Down
5 changes: 3 additions & 2 deletions src/app/store/keys/key.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { AddressVersion } from '@stacks/transactions';

import { decryptMnemonic, encryptMnemonic } from '@shared/crypto/mnemonic-encryption';
import { logger } from '@shared/logger';
import { defaultWalletKeyId } from '@shared/utils';
import { identifyUser } from '@shared/utils/analytics';

import { recurseAccountsForActivity } from '@app/common/account-restoration/account-restore';
Expand All @@ -19,7 +20,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 { keySlice } from './key.slice';

function setWalletEncryptionPassword(args: {
password: string;
Expand Down Expand Up @@ -86,7 +87,7 @@ function setWalletEncryptionPassword(args: {
dispatch(
keySlice.actions.createStacksSoftwareWalletComplete({
type: 'software',
id: defaultKeyId,
id: defaultWalletKeyId,
salt,
encryptedSecretKey,
})
Expand Down
7 changes: 4 additions & 3 deletions src/app/store/keys/key.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import { useSelector } from 'react-redux';

import { createSelector } from '@reduxjs/toolkit';

import { defaultWalletKeyId } from '@shared/utils';

import { initialSearchParams } from '@app/common/initial-search-params';
import { initBigNumber } from '@app/common/math/helpers';
import { RootState } from '@app/store';

import { selectStacksChain } from '../chains/stx-chain.selectors';
import { defaultKeyId } 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() {
Expand All @@ -25,7 +26,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 => {
Expand Down
6 changes: 3 additions & 3 deletions src/app/store/keys/key.slice.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { PayloadAction, createEntityAdapter, createSlice } from '@reduxjs/toolkit';

import { defaultWalletKeyId } from '@shared/utils';

import { StxAndIdentityPublicKeys } from '@app/features/ledger/utils/stacks-ledger-utils';

import { migrateVaultReducerStoreToNewStateStructure } from '../utils/vault-reducer-migration';

export const defaultKeyId = 'default' as const;

interface KeyConfigSoftware {
type: 'software';
id: string;
Expand Down Expand Up @@ -38,7 +38,7 @@ export const keySlice = createSlice({
},

signOut(state) {
keyAdapter.removeOne(state, defaultKeyId);
keyAdapter.removeOne(state, defaultWalletKeyId);
},

debugKillStacks(state) {
Expand Down
5 changes: 3 additions & 2 deletions src/app/store/ledger/bitcoin-key.slice.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { PayloadAction, createEntityAdapter, createSlice } from '@reduxjs/toolkit';

import { defaultWalletKeyId } from '@shared/utils';

import { BitcoinLedgerAccountDetails } from '@app/features/ledger/utils/bitcoin-ledger-utils';

import { RootState } from '..';
import { defaultKeyId } from '../keys/key.slice';

interface PersistedBitcoinKeys extends BitcoinLedgerAccountDetails {
walletId: string;
Expand All @@ -19,7 +20,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 }))
);
},
},
Expand Down
9 changes: 5 additions & 4 deletions src/app/store/utils/vault-reducer-migration.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { LocalStorageMock } from '@tests/unit/local-storage-mock';
import { vi } from 'vitest';

import { defaultKeyId } from '../keys/key.slice';
import { defaultWalletKeyId } from '@shared/utils';

import { migrateVaultReducerStoreToNewStateStructure } from './vault-reducer-migration';

(globalThis as any).localStorage = new LocalStorageMock();
Expand Down Expand Up @@ -32,11 +33,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',
},
Expand Down
4 changes: 2 additions & 2 deletions src/shared/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export const KEBAB_REGEX = /[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g;

export const MICROBLOCKS_ENABLED = !IS_TEST_ENV && true;

export const GITHUB_ORG = 'hirosystems';
export const GITHUB_REPO = 'wallet';
export const GITHUB_ORG = 'leather-wallet';
export const GITHUB_REPO = 'extension';

export enum WalletDefaultNetworkConfigurationIds {
mainnet = 'mainnet',
Expand Down
12 changes: 8 additions & 4 deletions src/shared/crypto/bitcoin/bitcoin.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as btc from '@scure/btc-signer';

import { BitcoinNetworkModes, NetworkModes } from '@shared/constants';
import { whenNetwork } from '@shared/utils';
import { defaultWalletKeyId } from '@shared/utils';

import { DerivationPathDepth } from '../derivation-path.utils';
import { BtcSignerNetwork } from './bitcoin.network';
Expand Down Expand Up @@ -173,13 +174,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<string, { policy: string } | undefined>, network: NetworkModes) =>
return (
ledgerKeyMap: Record<string, { policy: string } | undefined>,
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);
};
Expand Down
7 changes: 5 additions & 2 deletions src/shared/crypto/bitcoin/p2wpkh-address-gen.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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',
Expand Down
2 changes: 2 additions & 0 deletions src/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,5 @@ export function whenNetwork(mode: NetworkModes) {
export function isEmptyArray(data: unknown[]) {
return data.length === 0;
}

export const defaultWalletKeyId = 'default' as const;
Loading