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

feat: Support creating Ledger Nano profiles #8003

Merged
merged 81 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
0e58e1a
refactor(2.0): Dynamic password
marc2332 Dec 21, 2023
2b25b9b
refactor(2.0): Remove Profile Manager (wip)
marc2332 Dec 22, 2023
027b69d
clean up and fix
marc2332 Dec 22, 2023
4bf970b
clean up
marc2332 Dec 22, 2023
d5f50d5
Merge branch 'refactor/dynamic-password' into refactor/remove-profile…
marc2332 Dec 22, 2023
a5a8969
clean up more code
marc2332 Dec 22, 2023
628f376
clean up
marc2332 Jan 8, 2024
60c6836
adapt and remove for profile-manager related code
marc2332 Jan 9, 2024
cc59db7
clean up more code
marc2332 Jan 10, 2024
3080203
fmt
marc2332 Jan 10, 2024
7457f42
Merge branch 'develop-iota2.0' into refactor/dynamic-password
marc2332 Jan 10, 2024
cff2fa6
more cleanup
marc2332 Jan 10, 2024
064d8c5
more cleanup
marc2332 Jan 11, 2024
10105c0
small tweaks
marc2332 Jan 12, 2024
38b7c9b
more cleanup
marc2332 Jan 15, 2024
3a885f6
Merge branch 'develop-iota2.0' into refactor/dynamic-password
marc2332 Jan 15, 2024
071bffc
format
marc2332 Jan 15, 2024
8445a28
Merge branch 'refactor/dynamic-password' into refactor/remove-profile…
marc2332 Jan 15, 2024
df286ea
Merge branch 'develop-iota2.0' into refactor/dynamic-password
begonaalvarezd Jan 16, 2024
67eba8c
update
marc2332 Jan 16, 2024
f8ba63f
clean up
marc2332 Jan 16, 2024
63e6125
Merge branch 'refactor/dynamic-password' into refactor/remove-profile…
marc2332 Jan 16, 2024
5f2a5fd
Merge branch 'develop-iota2.0' into refactor/remove-profile-manager
marc2332 Jan 16, 2024
c5d653d
resolve conflicts and clean up other stuff
marc2332 Jan 17, 2024
f5acc83
https://api.testnet.shimmer.network
marc2332 Jan 17, 2024
84b875f
revert Wallet.svelte
marc2332 Jan 17, 2024
71e06b9
clean up
marc2332 Jan 17, 2024
4cf6327
remove account debris
marc2332 Jan 18, 2024
e4a884e
resolve conflicts
marc2332 Jan 29, 2024
6ecfa1d
feat: Profile-centric file scheme for wallets
marc2332 Jan 29, 2024
ecb5fa1
chore: Clean up 2.0 comments
marc2332 Jan 29, 2024
7637dbb
more
marc2332 Jan 29, 2024
73779d8
more
marc2332 Jan 29, 2024
3673d25
more
marc2332 Jan 29, 2024
1d645e4
Merge branch 'chore/clean-up-2.0-comments' into feat/profile-centric-…
marc2332 Jan 30, 2024
6e8dcd5
works
marc2332 Jan 30, 2024
72383a7
clean up
marc2332 Jan 31, 2024
d4dc55c
clean up
marc2332 Jan 31, 2024
599a98f
clean up
marc2332 Jan 31, 2024
bb26153
Merge branch 'chore/clean-up-2.0-comments' of https://github.com/iota…
marc2332 Jan 31, 2024
c994e77
chore: Simplify path management
marc2332 Jan 31, 2024
52c1e02
fmt
marc2332 Jan 31, 2024
e901a40
chore: Adapt to sdk changes
marc2332 Jan 31, 2024
2cb0e27
Merge branch 'chore/adapt-to-sdk-changes' into chore/simplify-path-ma…
marc2332 Jan 31, 2024
e2e2ae1
Merge branch 'chore/clean-up-2.0-comments' into chore/adapt-to-sdk-ch…
marc2332 Jan 31, 2024
1b19967
Merge branch 'chore/adapt-to-sdk-changes' into chore/simplify-path-ma…
marc2332 Jan 31, 2024
7d8912f
Merge branch 'chore/adapt-to-sdk-changes' into feat/profile-centric-w…
marc2332 Jan 31, 2024
9b8bc3e
Merge branch 'feat/profile-centric-wallet-file-scheme' into chore/sim…
marc2332 Jan 31, 2024
c87689b
Merge branch 'refactor/remove-account-debris' into chore/clean-up-2.0…
marc2332 Jan 31, 2024
f9cf60e
Merge branch 'chore/clean-up-2.0-comments' into chore/adapt-to-sdk-ch…
marc2332 Jan 31, 2024
442cfbd
fmt
marc2332 Jan 31, 2024
dbd8405
Merge branch 'chore/adapt-to-sdk-changes' into feat/profile-centric-w…
marc2332 Jan 31, 2024
6aa8dde
Merge branch 'feat/profile-centric-wallet-file-scheme' into chore/sim…
marc2332 Jan 31, 2024
57c779c
clean up
marc2332 Jan 31, 2024
0593fb1
feat: Restore from mnemonic
marc2332 Feb 1, 2024
e36facb
resolve conflicts
marc2332 Feb 2, 2024
f26de9b
Merge branch 'develop-iota2.0' into chore/simplify-path-management
marc2332 Feb 5, 2024
a079de7
Merge branch 'chore/simplify-path-management' into feat/restore-from-…
marc2332 Feb 5, 2024
0eccdd3
resolve conflicts
marc2332 Feb 6, 2024
f070fa7
enable features
marc2332 Feb 6, 2024
a234219
feat: WIP Support for LedgerNano profiles
marc2332 Feb 6, 2024
e4f3d30
Merge branch 'develop-iota2.0' into feat/support-ledger-profiles
marc2332 Feb 6, 2024
8f18489
fixes and improvements
marc2332 Feb 8, 2024
7f3116b
Merge branch 'develop-iota2.0' into feat/support-ledger-profiles
marc2332 Feb 9, 2024
c5f6bd2
small improvements
marc2332 Feb 12, 2024
a102c98
resolve conflicts
marc2332 Feb 20, 2024
b23a540
mm
marc2332 Feb 20, 2024
5fb3396
Merge branch 'develop-iota2.0' of https://github.com/iotaledger/firef…
marc2332 Feb 21, 2024
9017be1
I think this is working
marc2332 Feb 27, 2024
8bef248
:(
marc2332 Feb 28, 2024
171376e
clean up
marc2332 Feb 28, 2024
1ab6700
fixes and improvements
marc2332 Feb 29, 2024
2aed389
tweaks
marc2332 Mar 1, 2024
0fcedd7
fix: Sync with SDK types
marc2332 Mar 1, 2024
44dfdd7
Merge branch 'fix/sync-with-sdk-types' into feat/support-ledger-profiles
marc2332 Mar 1, 2024
ed861ac
fmt
marc2332 Mar 4, 2024
b2fa036
Merge branch 'develop-iota2.0' into feat/support-ledger-profiles
marc2332 Mar 4, 2024
6baf822
tweaks
marc2332 Mar 5, 2024
a169280
Merge branch 'feat/support-ledger-profiles' of https://github.com/iot…
marc2332 Mar 5, 2024
47efb73
Merge branches 'feat/support-ledger-profiles' and 'develop-iota2.0' o…
cpl121 Mar 6, 2024
74a651b
Merge branch 'develop-iota2.0' into feat/support-ledger-profiles
begonaalvarezd Mar 7, 2024
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 @@ -16,7 +16,7 @@
const STEPS = [1, 2, 3, 4]

$: if ($ledgerNanoStatus.blindSigningEnabled) {
closePopup()
closePopup(true)
checkOrConnectLedger(async () => {
try {
if ($ledgerPreparedOutput) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { localize } from '@core/i18n'
import { formatHexString } from '@core/utils'
import { onDestroy } from 'svelte'
import { showInternalVerificationPopup, resetShowInternalVerificationPopup } from '@core/ledger'
import { verificationPopupMode, resetShowInternalVerificationPopup, VerificationPopupMode } from '@core/ledger'
import { TextHintVariant, TextType } from '@ui/enums'
import { AnimationEnum } from '@auxiliary/animation'

Expand All @@ -12,10 +12,18 @@
export let hash: string

const hasSendConfirmationProps = (toAddress && toAmount) || hash

const locale = $showInternalVerificationPopup
? 'popups.verifyInternalLedgerTransaction'
: 'popups.verifyLedgerTransaction'
let locale
$: switch ($verificationPopupMode) {
case VerificationPopupMode.Block:
locale = 'popups.verifyLedgerBlock'
break
case VerificationPopupMode.Internal:
locale = 'popups.verifyInternalLedgerTransaction'
break
case VerificationPopupMode.Default:
locale = 'popups.verifyLedgerTransaction'
break
}

onDestroy(() => {
resetShowInternalVerificationPopup()
Expand All @@ -36,7 +44,7 @@
<KeyValueBox keyText={localize('general.sendTo')} valueText={toAddress} />
<KeyValueBox keyText={localize('general.amount')} valueText={toAmount} />
{/if}
{:else if $showInternalVerificationPopup}
{:else if $verificationPopupMode === VerificationPopupMode.Internal}
<TextHint variant={TextHintVariant.Info} text={localize('popups.verifyInternalLedgerTransaction.hint')} />
{/if}
</div>
2 changes: 1 addition & 1 deletion packages/desktop/features/onboarding.features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const onboardingFeaturesForTestnet: IOnboardingFeaturesForNetwork = {
enabled: true,
},
ledgerProfile: {
enabled: false,
enabled: true,
},
},
restoreProfile: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
<script lang="ts">
import { Button, FontWeight, PasswordInput, Text, TextType } from '@ui'
import { Button, FontWeight, PasswordInput, Text, TextType, LedgerAnimation } from '@ui'
import { localize } from '@core/i18n'
import { selectedWallet, selectedWalletId } from '@core/wallet'
import { unlockStronghold, updateActiveWallet } from '@core/profile'
import { Icon } from '@auxiliary/icon'
import { LedgerAppName, ledgerAppName } from '@core/ledger'
import { IllustrationEnum } from '@auxiliary/illustration'
import { unlockStronghold, updateActiveWallet, isSoftwareProfile } from '@core/profile'
import { OutputId } from '@iota/sdk/out/types'

export let outputId: string | undefined

let error = ''
let isBusy = false
let strongholdPassword = ''
$: validStronghold = $isSoftwareProfile ? strongholdPassword && strongholdPassword.length !== 0 : true
$: disabledActive = !validStronghold || isBusy
$: iconNetwork = $ledgerAppName === LedgerAppName.Shimmer ? Icon.Shimmer : Icon.Iota

async function unlockWalletAndCreateAccount(): Promise<void> {
isBusy = true
error = ''
try {
if (!strongholdPassword || $selectedWallet?.implicitAccountOutputs.length === 0) return
if ($selectedWallet?.implicitAccountOutputs.length === 0) return

if ($isSoftwareProfile) {
if (!strongholdPassword) return
await unlockStronghold(strongholdPassword)
}

let outputIdForTransition: OutputId
await unlockStronghold(strongholdPassword)
if (outputId) {
outputIdForTransition = $selectedWallet?.implicitAccountOutputs.find(
(implicitAccounts) => implicitAccounts.outputId.toString() === outputId
Expand All @@ -42,31 +52,32 @@
<step-content class="flex flex-col items-center justify-between h-full pt-28">
<div class="flex flex-col h-full justify-between space-y-8">
<div class="flex flex-col text-center justify-center px-4 space-y-9 max-w-md">
<div class="flex items-center justify-center">
<img
src="assets/illustrations/implicit-account-creation/step3.svg"
alt={localize('views.implicit-account-creation.steps.step3.title')}
{#if $isSoftwareProfile}
<div class="flex items-center justify-center">
<img
src="assets/illustrations/implicit-account-creation/step3.svg"
alt={localize('views.implicit-account-creation.steps.step3.title')}
/>
</div>
<Text type={TextType.h3} fontWeight={FontWeight.semibold}
>{localize('views.implicit-account-creation.steps.step3.view.title')}</Text
>
<PasswordInput
bind:error
bind:value={strongholdPassword}
autofocus
submitHandler={unlockWalletAndCreateAccount}
placeholder={localize('views.implicit-account-creation.steps.step3.view.placeholder')}
disabled={$selectedWallet?.hasImplicitAccountCreationTransactionInProgress}
/>
</div>
<Text type={TextType.h3} fontWeight={FontWeight.semibold}
>{localize('views.implicit-account-creation.steps.step3.view.title')}</Text
>
<PasswordInput
bind:error
bind:value={strongholdPassword}
autofocus
submitHandler={unlockWalletAndCreateAccount}
placeholder={localize('views.implicit-account-creation.steps.step3.view.placeholder')}
disabled={$selectedWallet?.hasImplicitAccountCreationTransactionInProgress}
/>
{:else}
<LedgerAnimation illustration={IllustrationEnum.LedgerConnected2Desktop} {iconNetwork} />
{/if}
<button-wrapper class="flex items-center justify-center">
<Button onClick={unlockWalletAndCreateAccount} disabled={disabledActive} {isBusy}
>{localize('views.implicit-account-creation.steps.step2.view.action')}</Button
>
</button-wrapper>
</div>
<button-wrapper class="flex items-center justify-center">
<Button
onClick={unlockWalletAndCreateAccount}
disabled={!strongholdPassword || strongholdPassword.length === 0 || isBusy}
isBusy={$selectedWallet?.hasImplicitAccountCreationTransactionInProgress}
>{localize('views.implicit-account-creation.steps.step2.view.action')}</Button
></button-wrapper
>
</div>
</step-content>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import { createFromLedgerRouter } from '@core/router'
import { Icon as IconEnum } from '@auxiliary/icon'
import { IllustrationEnum } from '@auxiliary/illustration'
import { buildOnboardingSecretManager, onboardingProfileSecretManager } from '@contexts/onboarding'
import { get } from 'svelte/store'

function onContinueClick(): void {
$createFromLedgerRouter.next()
Expand All @@ -24,8 +26,9 @@
})
}

onMount(() => {
pollLedgerNanoStatus()
onMount(async () => {
await buildOnboardingSecretManager()
pollLedgerNanoStatus(get(onboardingProfileSecretManager))
})
</script>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import { Icon as IconEnum } from '@lib/auxiliary/icon'
import { Position, TextHintVariant } from '@ui/enums'
import { localize } from '@core/i18n'
import { showInternalVerificationPopup } from '@core/ledger'
import { VerificationPopupMode, verificationPopupMode } from '@core/ledger'
import { checkActiveProfileAuth, isActiveLedgerProfile } from '@core/profile'
import { closePopup, openPopup, PopupId } from '@auxiliary/popup'

Expand Down Expand Up @@ -45,7 +45,7 @@

function onClaimClick(): void {
if ($isActiveLedgerProfile) {
$showInternalVerificationPopup = true
$verificationPopupMode = VerificationPopupMode.Internal
}
checkActiveProfileAuth(() => claimActivity(activity))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function buildOnboardingSecretManager(): Promise<void> {
const { strongholdPassword, secretManagerOptions, mnemonic } = profile
const mnemonicStringified = mnemonic?.join(' ') ?? ''

if (!strongholdPassword || !secretManagerOptions || !mnemonic) {
if (!secretManagerOptions) {
return
}

Expand All @@ -24,11 +24,13 @@ export async function buildOnboardingSecretManager(): Promise<void> {
await secretManager.setStrongholdPassword(strongholdPassword)
}

// 3. Verify Mnemonic
await verifyMnemonic(mnemonicStringified)
if (mnemonicStringified) {
// 3. Verify Mnemonic
await verifyMnemonic(mnemonicStringified)

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

onboardingProfileSecretManager.set(secretManager)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { getLedgerNanoStatus } from '@core/secret-manager'
import { SecretManager } from '@iota/sdk'
import { resetLedgerNanoStatus, updateLedgerNanoStatus } from '../stores'

export async function getAndUpdateLedgerNanoStatus(secretManager: SecretManager, forwardErrors = false): Promise<void> {
export async function getAndUpdateLedgerNanoStatus(
secretManager?: SecretManager,
forwardErrors = false
): Promise<void> {
try {
const ledgerNanoStatusResponse = await getLedgerNanoStatus(secretManager)
updateLedgerNanoStatus(ledgerNanoStatusResponse)
Expand Down
1 change: 0 additions & 1 deletion packages/shared/lib/core/ledger/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@ export * from './checkOrConnectLedger'
export * from './displayNotificationForLedgerProfile'
export * from './getLedgerDeviceStatus'
export * from './pollLedgerNanoStatus'
export * from './promptUserToConnectLedger'
11 changes: 4 additions & 7 deletions packages/shared/lib/core/ledger/actions/pollLedgerNanoStatus.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import { get } from 'svelte/store'
import { DEFAULT_LEDGER_NANO_STATUS_POLL_INTERVAL } from '../constants'
import { deconstructLedgerNanoStatusPollingConfiguration } from '../helpers'
import { ILedgerNanoStatusPollingConfiguration } from '../interfaces'
import { isPollingLedgerDeviceStatus, ledgerNanoStatus } from '../stores'
import { getAndUpdateLedgerNanoStatus } from './getAndUpdateLedgerNanoStatus'
import { SecretManager } from '@iota/sdk'

let timeoutTimer: ReturnType<typeof setTimeout> | undefined

export function pollLedgerNanoStatus(config?: ILedgerNanoStatusPollingConfiguration): void {
const { pollInterval, secretManager } = deconstructLedgerNanoStatusPollingConfiguration(config)

const defaultPollInterval = pollInterval || DEFAULT_LEDGER_NANO_STATUS_POLL_INTERVAL
export function pollLedgerNanoStatus(secretManager?: SecretManager): void {
const defaultPollInterval = DEFAULT_LEDGER_NANO_STATUS_POLL_INTERVAL
const slowedPollInterval = 10 * defaultPollInterval

if (!get(isPollingLedgerDeviceStatus)) {
isPollingLedgerDeviceStatus.set(true)
const pollingFunction = async (): Promise<void> => {
await getAndUpdateLedgerNanoStatus(get(secretManager))
await getAndUpdateLedgerNanoStatus(secretManager)
const isLedgerBusy = get(ledgerNanoStatus)?.busy
const currentPollInterval = isLedgerBusy ? slowedPollInterval : defaultPollInterval
timeoutTimer = setTimeout(() => void pollingFunction(), currentPollInterval)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const USE_LEDGER_SIMULATOR = false
export const USE_LEDGER_SIMULATOR = true
1 change: 0 additions & 1 deletion packages/shared/lib/core/ledger/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './deconstructLedgerNanoStatusPollingConfiguration'
export * from './deconstructLedgerVerificationProps'
export * from './deriveLedgerError'
2 changes: 1 addition & 1 deletion packages/shared/lib/core/ledger/stores/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ export * from './is-polling-ledger-device-status.store'
export * from './ledger-connection-state.store'
export * from './ledger-nano-status.store'
export * from './ledger-prepared-output.store'
export * from './show-internal-verification-popup'
export * from './verification-popup-mode'
export * from './ledger-app-name.store'

This file was deleted.

13 changes: 13 additions & 0 deletions packages/shared/lib/core/ledger/stores/verification-popup-mode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { writable } from 'svelte/store'

export enum VerificationPopupMode {
Default,
Internal,
Block,
}

export const verificationPopupMode = writable<VerificationPopupMode>(VerificationPopupMode.Default)

export function resetShowInternalVerificationPopup(): void {
verificationPopupMode.set(VerificationPopupMode.Default)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { LedgerConnectionState } from '../interfaces'
import { LedgerAppName } from '../enums'
import { LedgerNanoStatus } from '@iota/sdk/out/types'
import { USE_LEDGER_SIMULATOR } from '../constants'
import { LedgerAppName } from '../enums'
import { LedgerConnectionState } from '../interfaces'

export function determineLedgerConnectionState(
status: LedgerNanoStatus,
Expand All @@ -9,10 +10,18 @@ export function determineLedgerConnectionState(
const { connected, app } = status
if (connected) {
if (app) {
if (app.name === appName) {
return LedgerConnectionState.CorrectAppOpen
if (USE_LEDGER_SIMULATOR) {
if (app?.version === '0.8.7') {
return LedgerConnectionState.CorrectAppOpen
} else {
return LedgerConnectionState.AppNotOpen
}
} else {
return LedgerConnectionState.AppNotOpen
if (app.name === appName) {
return LedgerConnectionState.CorrectAppOpen
} else {
return LedgerConnectionState.AppNotOpen
}
}
} else {
return LedgerConnectionState.Locked
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { LedgerNanoStatus } from '@iota/sdk/out/types'
import { get } from 'svelte/store'
import { activeProfileSecretManager } from '../stores'

// TODO(2.0): Fix all of usages of this
export async function getLedgerNanoStatus(
secretManager = get(activeProfileSecretManager)
): Promise<LedgerNanoStatus | null> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ let oldSecretManagerOptions: SecretManagerType | null = null
// activeProfileSecretManager is used outside of svelte components too
activeProfile.subscribe((profile) => {
// Dont create a new instance of secretManager when it is already initialized
if (profile.secretManagerOptions && oldSecretManagerOptions !== profile.secretManagerOptions) {
api.createSecretManager(profile.secretManagerOptions).then((secretManager) => {
activeProfileSecretManager.set(secretManager)
})
oldSecretManagerOptions = profile.secretManagerOptions
if (profile.secretManagerOptions) {
if (oldSecretManagerOptions !== profile.secretManagerOptions) {
api.createSecretManager(profile.secretManagerOptions).then((secretManager) => {
activeProfileSecretManager.set(secretManager)
})
oldSecretManagerOptions = profile.secretManagerOptions
}
} else {
activeProfileSecretManager.set(null)
oldSecretManagerOptions = null
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ export async function handleNewOutputEventInternal(walletId: string, payload: Ne
isTransferring: false,
})
}
closePopup() // close ActivateAccountPopup when the account output is created
}
}

Expand Down
Loading
Loading