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

refactor: Dynamic password #7804

Merged
merged 9 commits into from
Jan 16, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
import { AnimationEnum } from '@auxiliary/animation'
import { showAppNotification } from '@auxiliary/notification'
import { OnboardingLayout } from '@components'
import { buildOnboardingSecretManager, updateOnboardingProfile, verifyAndStoreMnemonic } from '@contexts/onboarding'
import { buildOnboardingSecretManager, updateOnboardingProfile } from '@contexts/onboarding'
import { localize } from '@core/i18n'
import { MAX_STRONGHOLD_PASSWORD_LENGTH } from '@core/profile'
import { Subrouter } from '@core/router'
import { PASSWORD_REASON_MAP } from '@core/stronghold'
import { setStrongholdPassword } from '@core/wallet/actions'
import { Animation, Button, HTMLButtonType, PasswordInput, Text, TextType } from '@ui'
import zxcvbn from 'zxcvbn'

Expand Down Expand Up @@ -44,10 +43,8 @@
} else {
try {
busy = true
await setStrongholdPassword(strongholdPassword)
updateOnboardingProfile({ strongholdPassword, hasStoredMnemonic: true })
await buildOnboardingSecretManager()
await verifyAndStoreMnemonic()
router.next()
} catch (err) {
console.error(err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import {
addWalletPersistedDataToActiveProfile,
addWalletToActiveWallets,
createWallet,
IPersistedProfile,
login,
} from '@core/profile'
import { get } from 'svelte/store'
import { OnboardingType } from '../enums'
import { addWalletPersistedDataToOnboardingProfile, onboardingProfile } from '../stores'
import { onboardingProfile } from '../stores'
import { createNewProfileFromOnboardingProfile } from './createNewProfileFromOnboardingProfile'
import { showBalanceOverviewPopup } from '@contexts/dashboard/stores'
import {
Expand All @@ -18,6 +19,7 @@ import {
} from '@core/wallet'
import { DEFAULT_SYNC_OPTIONS } from '@core/wallet/constants'
import { localize } from '@core/i18n'
import { IOnboardingProfile } from '../interfaces'

export async function completeOnboardingProcess(): Promise<void> {
// if we already have an active profile
Expand All @@ -27,34 +29,36 @@ export async function completeOnboardingProcess(): Promise<void> {
createNewProfileFromOnboardingProfile()
}

const onboardingType = get(onboardingProfile)?.onboardingType
const profile = get(onboardingProfile)
if (!profile) {
return
}
const { onboardingType, strongholdPassword } = profile

const shouldRecoverWallets = onboardingType === OnboardingType.Restore || onboardingType === OnboardingType.Claim
showBalanceOverviewPopup.set(shouldRecoverWallets)

await createOnboardingWallet()
await initWallet(profile, strongholdPassword)
void login({ isFromOnboardingFlow: true, shouldRecoverWallets })

onboardingProfile.set(undefined)
}

export async function createOnboardingWallet(name?: string, color?: string): Promise<IWalletState> {
export async function initWallet(profile: IOnboardingProfile, strongholdPassword?: string): Promise<IWalletState> {
// 1. Get the wallet name
const walletName = name || `${localize('general.wallet')} ${(get(activeWallets)?.length ?? 0) + 1}`
const walletName = `${localize('general.wallet')} ${(get(activeWallets)?.length ?? 0) + 1}`

// 2. Create the wallet instance
const wallet = await createWallet() // TODO(2.0) Not sure about this, I think this should be createWallet instead
const wallet = await createWallet(profile as IPersistedProfile, strongholdPassword)

// 3. Sync the wallet with the Node
// TODO(2.0): test & fix sync when we have iota2.0 nodes
await wallet.sync(DEFAULT_SYNC_OPTIONS)

// 4. Create a wrapper over the wallet instance and the persisted data
const [walletState, walletPersistedData] = await buildWalletStateAndPersistedData(wallet, walletName, color)
const [walletState, walletPersistedData] = await buildWalletStateAndPersistedData(wallet, walletName)

// TODO(2.0) Fix
addWalletToActiveWallets(walletState)
addWalletPersistedDataToOnboardingProfile(walletState.id, walletPersistedData)
addWalletPersistedDataToActiveProfile(walletState.id, walletPersistedData) // TODO(2.0) Not sure about this,
// TODO(2.0) Fix
addWalletPersistedDataToActiveProfile(walletState.id, walletPersistedData)
addEmptyWalletActivitiesToAllWalletActivities(walletState.id)

return walletState
Expand Down
1 change: 0 additions & 1 deletion packages/shared/lib/contexts/onboarding/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,3 @@ export * from './restoreBackupFromStrongholdFile'
export * from './setProfileRecoveryTypeFromFilename'
export * from './subscribeToWalletApiEventsForShimmerClaiming'
export * from './syncShimmerClaimingAccount'
export * from './verifyAndStoreMnemonic'

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { derived, get, Readable, writable } from 'svelte/store'
import { isLedgerProfile } from '@core/profile'

import { IOnboardingProfile, IShimmerClaimingWallet } from '../interfaces'
import { IBaseToken, IPersistedWalletData } from '@core/wallet/interfaces'
import { IBaseToken } from '@core/wallet/interfaces'
import { IPersistedNetwork } from '@core/network'

export const onboardingProfile = writable<IOnboardingProfile | null | undefined>(null)
Expand Down Expand Up @@ -40,16 +40,3 @@ export function updateShimmerClaimingAccount(shimmerClaimingAccount: IShimmerCla
export function getOnboardingBaseToken(): IBaseToken {
return get(onboardingProfile)?.network?.baseToken
}

export function addWalletPersistedDataToOnboardingProfile(
walletId: string,
walletPersistedData: IPersistedWalletData
): void {
onboardingProfile?.update((state) => {
if (!state?.walletPersistedData) {
state.walletPersistedData = {}
}
state.walletPersistedData[walletId] = walletPersistedData
return state
})
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
import { onboardingProfile } from '@contexts/onboarding/stores'
import { api } from '@core/api'
import { SecretManager, SecretManagerType } from '@iota/sdk'
import { USE_LEDGER_SIMULATOR } from 'shared/lib/core/ledger'
import { getStorageDirectoryOfProfile, ProfileType } from 'shared/lib/core/profile'
import { SecretManager } from '@iota/sdk'
import { verifyMnemonic } from 'shared/lib/core/secret-manager'
import { get, writable, Writable } from 'svelte/store'

export const onboardingProfileSecretManager: Writable<SecretManager | null> = writable(null)

export async function buildOnboardingSecretManager(): Promise<void> {
const profile = get(onboardingProfile)
if (profile) {
const { id, type, strongholdPassword } = profile
const { strongholdPassword, secretManagerOptions, mnemonic } = profile
const mnemonicStringified = mnemonic?.join(' ') ?? ''

const storagePath = await getStorageDirectoryOfProfile(id)
const secretManagerOptions = getSecretManagerFromProfileType(type, {
storagePath,
strongholdPassword,
})
if (!strongholdPassword || !secretManagerOptions || !mnemonic) {
return
}

// 1. Create SecretManager
const secretManager = await api.createSecretManager(secretManagerOptions)

// 2. Load the stronghold password specified in the onboarding if necessary
if (strongholdPassword) {
await secretManager.setStrongholdPassword(strongholdPassword)
}

// 3. Verify Mnemonic
await verifyMnemonic(mnemonicStringified)

// 4. Store Mnemonic
await secretManager.storeMnemonic(mnemonicStringified)

onboardingProfileSecretManager.set(secretManager)
} else {
onboardingProfileSecretManager.set(null)
Expand All @@ -29,29 +39,3 @@ export async function buildOnboardingSecretManager(): Promise<void> {
export function isOnboardingSecretManagerInitialized(): boolean {
return !!get(onboardingProfileSecretManager)
}

export function getSecretManagerFromProfileType(
type?: ProfileType,
{
storagePath,
strongholdPassword,
}: {
storagePath?: string
strongholdPassword?: string
} = {}
): SecretManagerType {
const strongholdSecretManager = {
stronghold: { snapshotPath: `${storagePath}/wallet.stronghold`, password: strongholdPassword },
}
const ledgerSecretManager = {
ledgerNano: USE_LEDGER_SIMULATOR,
}

switch (type) {
case ProfileType.Ledger:
return ledgerSecretManager
case ProfileType.Software:
default:
return strongholdSecretManager
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ export async function login(loginOptions?: ILoginOptions): Promise<void> {
// Step 1: create profile manager if its doesn't exist
incrementLoginProgress()
await waitForPreviousManagerToBeDestroyed()
// if (!isOnboardingSecretManagerInitialized()) {
// // TODO(2.0) Not sure about this
// await initialiseOnboardingProfileWithSecretManager(true)
// }

// Step 3: load and build all the profile data
incrementLoginProgress()
Expand Down
26 changes: 11 additions & 15 deletions packages/shared/lib/core/profile/actions/createWallet.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import { api } from '@core/api'
import { get } from 'svelte/store'
import { IProfile, IWallet } from '../interfaces'
import { activeProfile as activeProfileStore } from '../stores'
import { IPersistedProfile, IWallet } from '../interfaces'
import { getSecretManagerFromProfileType, getStorageDirectoryOfProfile } from '../utils'
import { WalletOptions } from '@iota/sdk'
import { selectedWalletId } from '../../wallet'

export function getWalletOptions(profile: IProfile, storagePath: string): WalletOptions {
const walletOptions: WalletOptions = {
export function getWalletOptions(profile: IPersistedProfile, storagePath: string, password?: string): WalletOptions {
return {
clientOptions: profile.clientOptions,
storagePath,
secretManager: getSecretManagerFromProfileType(profile.type, storagePath),
secretManager: getSecretManagerFromProfileType(profile.type, storagePath, password),
bipPath: {
coinType: profile.network.coinType,
account: 0,
addressIndex: 0,
},
}

return walletOptions
}

// TODO(2.0): Fix and finish this method
Expand All @@ -28,18 +24,18 @@ export function getWalletOptions(profile: IProfile, storagePath: string): Wallet
- __wallet1__/
- __wallet2__/
*/
export async function createWallet(activeProfile = get(activeProfileStore)): Promise<IWallet> {
const id = activeProfile.id
const storagePath = await getStorageDirectoryOfProfile(id)

const walletOptions = getWalletOptions(activeProfile, storagePath)
export async function createWallet(profile: IPersistedProfile, password?: string): Promise<IWallet> {
const storagePath = await getStorageDirectoryOfProfile(profile.id)

const wallet = await api.createWallet(id, {
const walletOptions = getWalletOptions(profile, storagePath, password)
// TODO(2.0) It is weird to use the profile ID as the wallet ID,
// we should probably have one for wallet and another one for the profile
const wallet = await api.createWallet(profile.id, {
...walletOptions,
storagePath,
})

// TODO(2.0): Fix
selectedWalletId.set(id)
selectedWalletId.set(profile.id)
return wallet
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import { USE_LEDGER_SIMULATOR } from '@core/ledger'
import { ProfileType } from '@core/profile'

// TODO(2.0) Fix all usages
export function getSecretManagerFromProfileType(type?: ProfileType, storagePath?: string): SecretManagerType {
export function getSecretManagerFromProfileType(
type?: ProfileType,
storagePath?: string,
password?: string
): SecretManagerType {
const strongholdSecretManager = {
stronghold: { snapshotPath: `${storagePath}/wallet.stronghold`, password: 'mellamobego' }, // TODO(2.0) Remove this harcoded password
stronghold: { snapshotPath: `${storagePath}/wallet.stronghold`, password },
}
const ledgerSecretManager = {
ledgerNano: USE_LEDGER_SIMULATOR,
Expand Down
1 change: 0 additions & 1 deletion packages/shared/lib/core/secret-manager/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ export * from './changeStrongholdPassword'
export * from './clearStrongholdPassword'
export * from './generateEd25519Address'
export * from './getLedgerNanoStatus'
export * from './storeMnemonic'
export * from './getSecretManager'
12 changes: 0 additions & 12 deletions packages/shared/lib/core/secret-manager/actions/storeMnemonic.ts

This file was deleted.

12 changes: 9 additions & 3 deletions packages/shared/lib/core/wallet/actions/setStrongholdPassword.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { get } from 'svelte/store'
import { selectedWallet } from '../stores/selected-wallet.store'
import { getSecretManager } from '@core/secret-manager/actions'
import { getSelectedWallet } from '../stores/selected-wallet.store'

export async function setStrongholdPassword(password: string): Promise<void> {
const wallet = get(selectedWallet)
// Set in Wallet
const wallet = getSelectedWallet()
// Otherwise error is thrown, if password is still present in memory
await wallet?.clearStrongholdPassword()
await wallet?.setStrongholdPassword(password)

// Set in SecretManager
const secretManager = getSecretManager()
await secretManager.setStrongholdPassword(password)
// await secretManager?.clearStrongholdPassword() // TODO(2.0)
}
Loading