diff --git a/packages/desktop/components/popups/ConnectLedgerPopup.svelte b/packages/desktop/components/popups/ConnectLedgerPopup.svelte
index 9a44be8f36..52bf595173 100644
--- a/packages/desktop/components/popups/ConnectLedgerPopup.svelte
+++ b/packages/desktop/components/popups/ConnectLedgerPopup.svelte
@@ -5,7 +5,7 @@
LedgerAppName,
LedgerConnectionState,
determineLedgerConnectionState,
- ledgerNanoStatus,
+ ledgerDeviceState,
} from '@core/ledger'
import { isFunction } from '@core/utils'
import { closePopup } from '@desktop/auxiliary/popup'
@@ -15,7 +15,7 @@
export let onCancel: () => void
export let onContinue: () => void
- $: ledgerConnectionState = determineLedgerConnectionState($ledgerNanoStatus, ledgerAppName)
+ $: ledgerConnectionState = determineLedgerConnectionState($ledgerDeviceState, ledgerAppName)
$: isNotConnected = ledgerConnectionState === LedgerConnectionState.NotConnected
$: isLocked = ledgerConnectionState === LedgerConnectionState.Locked
diff --git a/packages/desktop/components/popups/EnableLedgerBlindSigningPopup.svelte b/packages/desktop/components/popups/EnableLedgerBlindSigningPopup.svelte
index 9577512c0d..d6b8d1502b 100644
--- a/packages/desktop/components/popups/EnableLedgerBlindSigningPopup.svelte
+++ b/packages/desktop/components/popups/EnableLedgerBlindSigningPopup.svelte
@@ -1,50 +1,35 @@
{localize('popups.enableLedgerBlindSigning.title')}
-
-
-
- {localize('popups.enableLedgerBlindSigning.info')}
-
-
-
- {#each STEPS as step}
-
- {step}. {localize(`popups.enableLedgerBlindSigning.step_${step}`)}
-
- {/each}
-
+
+ {#each STEPS as step}
+
+ {step}. {localize(`popups.enableLedgerBlindSigning.step_${step}`, { appName })}
+
+ {/each}
diff --git a/packages/desktop/lib/electron/processes/ledger.process.ts b/packages/desktop/lib/electron/processes/ledger.process.ts
index 54e8a032c7..4fb60a99c9 100644
--- a/packages/desktop/lib/electron/processes/ledger.process.ts
+++ b/packages/desktop/lib/electron/processes/ledger.process.ts
@@ -8,7 +8,13 @@
import { LedgerApiMethod } from '@core/ledger/enums'
import type { ILedgerProcessMessage } from '../interfaces/ledger-process-message.interface'
-import { closeTransport, getEvmAddress, openTransport, signTransactionData } from '../utils/ledger.utils'
+import {
+ closeTransport,
+ getEthereumAppSettings,
+ getEvmAddress,
+ openTransport,
+ signTransactionData,
+} from '../utils/ledger.utils'
/**
* CAUTION: `process` is initialized using `utilityProcess.fork()`.
@@ -29,6 +35,10 @@ async function messageHandler(message: ILedgerProcessMessage): Promise {
data = await getEvmAddress(payload[0] as string)
break
}
+ case LedgerApiMethod.GetEthereumAppSettings: {
+ data = await getEthereumAppSettings()
+ break
+ }
case LedgerApiMethod.SignEvmTransaction: {
data = await signTransactionData(payload[0] as string, payload[1] as string)
break
@@ -37,10 +47,10 @@ async function messageHandler(message: ILedgerProcessMessage): Promise {
break
}
- await closeTransport()
-
process.parentPort.postMessage({ method, payload: data })
} catch (error) {
process.parentPort.postMessage({ error })
+ } finally {
+ await closeTransport()
}
}
diff --git a/packages/desktop/lib/electron/processes/main.process.ts b/packages/desktop/lib/electron/processes/main.process.ts
index 33743a9c28..21e9e6c838 100644
--- a/packages/desktop/lib/electron/processes/main.process.ts
+++ b/packages/desktop/lib/electron/processes/main.process.ts
@@ -1,16 +1,16 @@
// Modules to control application life and create native browser window
import {
app,
+ BrowserWindow,
dialog,
ipcMain,
- shell,
- BrowserWindow,
- session,
- utilityProcess,
nativeTheme,
PopupOptions,
- UtilityProcess,
powerMonitor,
+ session,
+ shell,
+ utilityProcess,
+ UtilityProcess,
} from 'electron'
import { WebPreferences } from 'electron/main'
import path from 'path'
@@ -296,6 +296,9 @@ ipcMain.on('start-ledger-process', () => {
case LedgerApiMethod.GenerateEvmAddress:
windows.main.webContents.send('evm-address', payload)
break
+ case LedgerApiMethod.GetEthereumAppSettings:
+ windows.main.webContents.send('ethereum-app-settings', payload)
+ break
case LedgerApiMethod.SignEvmTransaction:
windows.main.webContents.send('evm-signed-transaction', payload)
break
@@ -317,12 +320,14 @@ ipcMain.on(LedgerApiMethod.GenerateEvmAddress, (_e, bip32Path, verify) => {
ledgerProcess?.postMessage({ method: LedgerApiMethod.GenerateEvmAddress, payload: [bip32Path, verify] })
})
+ipcMain.on(LedgerApiMethod.GetEthereumAppSettings, () => {
+ ledgerProcess?.postMessage({ method: LedgerApiMethod.GetEthereumAppSettings })
+})
+
ipcMain.on(LedgerApiMethod.SignEvmTransaction, (_e, transactionHex, bip32Path) => {
ledgerProcess?.postMessage({ method: LedgerApiMethod.SignEvmTransaction, payload: [transactionHex, bip32Path] })
})
-export const getWindow = (windowName: string): BrowserWindow => windows[windowName]
-
export function getOrInitWindow(windowName: string): BrowserWindow {
if (!windows[windowName]) {
if (windowName === 'main') {
diff --git a/packages/desktop/lib/electron/utils/ledger.utils.ts b/packages/desktop/lib/electron/utils/ledger.utils.ts
index 2b77cbca46..ec98d3290c 100644
--- a/packages/desktop/lib/electron/utils/ledger.utils.ts
+++ b/packages/desktop/lib/electron/utils/ledger.utils.ts
@@ -1,6 +1,7 @@
import AppEth from '@ledgerhq/hw-app-eth'
import TransportNodeHid from '@ledgerhq/hw-transport-node-hid'
import { listen } from '@ledgerhq/logs'
+import type { ILedgerEthereumAppSettings } from '@core/ledger/interfaces'
// import specifity for core modules to prevent circular dependencies
import { IEvmTransactionSignature } from '@core/layer-2/interfaces'
@@ -24,6 +25,18 @@ export async function closeTransport(): Promise {
}
}
+export async function getEthereumAppSettings(): Promise {
+ const appEth = new AppEth(transport)
+ const settings = await appEth.getAppConfiguration()
+ return {
+ version: settings.version,
+ blindSigningEnabled: Boolean(settings.arbitraryDataEnabled),
+ erc20ProvisioningNecessary: Boolean(settings.erc20ProvisioningNecessary),
+ starkEnabled: Boolean(settings.starkEnabled),
+ starkv2Supported: Boolean(settings.starkv2Supported),
+ }
+}
+
export async function getEvmAddress(bip32Path: string): Promise<{ evmAddress: string; bip32Path: string }> {
const appEth = new AppEth(transport)
const data = await appEth.getAddress(bip32Path)
diff --git a/packages/desktop/views/dashboard/Dashboard.svelte b/packages/desktop/views/dashboard/Dashboard.svelte
index b13fbd803f..39cfe13eea 100644
--- a/packages/desktop/views/dashboard/Dashboard.svelte
+++ b/packages/desktop/views/dashboard/Dashboard.svelte
@@ -2,7 +2,6 @@
import { selectedAccount, selectedAccountIndex } from '@core/account/stores'
import { Platform } from '@core/app'
import { clearLayer2TokensPoll, pollLayer2Tokens } from '@core/layer-2/actions'
- import { stopPollingLedgerNanoStatus } from '@core/ledger'
import {
addNftsToDownloadQueue,
downloadNextNftInQueue,
@@ -10,7 +9,7 @@
} from '@core/nfts/actions'
import { downloadingNftId, nftDownloadQueue, resetNftDownloadQueue, selectedAccountNfts } from '@core/nfts/stores'
import { logout, reflectLockedStronghold } from '@core/profile/actions'
- import { hasStrongholdLocked, isActiveLedgerProfile } from '@core/profile/stores'
+ import { hasStrongholdLocked } from '@core/profile/stores'
import { appRouter, dashboardRoute } from '@core/router'
import features from '@features/features'
import { Idle } from '@ui'
@@ -64,9 +63,6 @@
onDestroy(() => {
Platform.DeepLinkManager.clearDeepLinkRequest()
- if ($isActiveLedgerProfile) {
- stopPollingLedgerNanoStatus()
- }
clearLayer2TokensPoll()
})
diff --git a/packages/desktop/views/dashboard/drawers/network-config/views/ConnectLedgerDeviceDrawer.svelte b/packages/desktop/views/dashboard/drawers/network-config/views/ConnectLedgerDeviceDrawer.svelte
index 893b9d6286..206d88d4aa 100644
--- a/packages/desktop/views/dashboard/drawers/network-config/views/ConnectLedgerDeviceDrawer.svelte
+++ b/packages/desktop/views/dashboard/drawers/network-config/views/ConnectLedgerDeviceDrawer.svelte
@@ -6,7 +6,7 @@
LedgerAppName,
LedgerConnectionState,
determineLedgerConnectionState,
- ledgerNanoStatus,
+ ledgerDeviceState,
} from '@core/ledger'
import { Router } from '@core/router'
import { Animation, FontWeight, Icon, Pane, Text, TextType } from '@ui'
@@ -16,7 +16,7 @@
const LOCALE_BASE_PATH = 'views.dashboard.drawers.networkConfig.connectLedgerDevice'
- $: ledgerConnectionState = determineLedgerConnectionState($ledgerNanoStatus, LedgerAppName.Ethereum)
+ $: ledgerConnectionState = determineLedgerConnectionState($ledgerDeviceState, LedgerAppName.Ethereum)
$: isConnectedAndUnlocked =
ledgerConnectionState !== LedgerConnectionState.NotConnected &&
ledgerConnectionState !== LedgerConnectionState.Locked
diff --git a/packages/desktop/views/onboarding/views/create-from-ledger/views/InstallLedgerView.svelte b/packages/desktop/views/onboarding/views/create-from-ledger/views/InstallLedgerView.svelte
index b560f8e8fc..42cf2477ea 100644
--- a/packages/desktop/views/onboarding/views/create-from-ledger/views/InstallLedgerView.svelte
+++ b/packages/desktop/views/onboarding/views/create-from-ledger/views/InstallLedgerView.svelte
@@ -1,6 +1,6 @@
diff --git a/packages/desktop/views/onboarding/views/restore-profile/views/ClaimFinderView.svelte b/packages/desktop/views/onboarding/views/restore-profile/views/ClaimFinderView.svelte
index f0c2f1cb4a..8a28ba7e7d 100644
--- a/packages/desktop/views/onboarding/views/restore-profile/views/ClaimFinderView.svelte
+++ b/packages/desktop/views/onboarding/views/restore-profile/views/ClaimFinderView.svelte
@@ -26,8 +26,8 @@
import {
checkOrConnectLedger,
handleLedgerError,
- pollLedgerNanoStatus,
- stopPollingLedgerNanoStatus,
+ pollLedgerDeviceState,
+ stopPollingLedgerDeviceState,
} from '@core/ledger'
import { unsubscribeFromWalletApiEvents } from '@core/profile-manager'
import { closePopup } from '@desktop/auxiliary/popup'
@@ -63,14 +63,14 @@
async function ledgerRaceConditionProtectionWrapper(_function: () => unknown): Promise {
try {
if ($isOnboardingLedgerProfile) {
- stopPollingLedgerNanoStatus()
+ stopPollingLedgerDeviceState()
}
await _function()
} catch (err) {
console.error('Error in ledgerRaceConditionProtectionWrapper')
} finally {
if ($isOnboardingLedgerProfile) {
- pollLedgerNanoStatus()
+ pollLedgerDeviceState()
}
}
}
diff --git a/packages/shared/src/lib/contexts/onboarding/actions/initialiseOnboardingProfile.ts b/packages/shared/src/lib/contexts/onboarding/actions/initialiseOnboardingProfile.ts
index d994c1fcbc..33996c4416 100644
--- a/packages/shared/src/lib/contexts/onboarding/actions/initialiseOnboardingProfile.ts
+++ b/packages/shared/src/lib/contexts/onboarding/actions/initialiseOnboardingProfile.ts
@@ -1,5 +1,5 @@
import { get } from 'svelte/store'
-import { stopPollingLedgerNanoStatus } from '@core/ledger'
+import { stopPollingLedgerDeviceState } from '@core/ledger'
import { destroyProfileManager, profileManager } from '@core/profile-manager'
import { waitForPreviousManagerToBeDestroyed } from '@core/profile/utils'
import { buildInitialOnboardingProfile } from '../helpers'
@@ -13,7 +13,7 @@ export async function initialiseOnboardingProfile(): Promise {
if (get(profileManager)) {
if (get(isOnboardingLedgerProfile)) {
- stopPollingLedgerNanoStatus()
+ stopPollingLedgerDeviceState()
}
await destroyProfileManager()
}
diff --git a/packages/shared/src/lib/core/app/interfaces/platform-event-map.interface.ts b/packages/shared/src/lib/core/app/interfaces/platform-event-map.interface.ts
index e8f59b4204..a457b7623e 100644
--- a/packages/shared/src/lib/core/app/interfaces/platform-event-map.interface.ts
+++ b/packages/shared/src/lib/core/app/interfaces/platform-event-map.interface.ts
@@ -1,5 +1,6 @@
import { IAppUpdateDownloadProgress, IAppVersionDetails, INFTDownloadState } from '.'
import { IEvmAddress, IEvmTransactionSignature } from '@core/layer-2/interfaces'
+import { ILedgerEthereumAppSettings } from '@core/ledger/interfaces'
export interface IPlatformEventMap {
'menu-logout': void
@@ -17,6 +18,7 @@ export interface IPlatformEventMap {
'notification-activated': unknown
'nft-download-done': INFTDownloadState
'nft-download-interrupted': INFTDownloadState
+ 'ethereum-app-settings': ILedgerEthereumAppSettings
'evm-address': IEvmAddress
'evm-signed-transaction': IEvmTransactionSignature
'ledger-error': Error
diff --git a/packages/shared/src/lib/core/ledger/actions/checkOrConnectLedger.ts b/packages/shared/src/lib/core/ledger/actions/checkOrConnectLedger.ts
index 218397bb5b..20ebc4042d 100644
--- a/packages/shared/src/lib/core/ledger/actions/checkOrConnectLedger.ts
+++ b/packages/shared/src/lib/core/ledger/actions/checkOrConnectLedger.ts
@@ -1,7 +1,7 @@
import { openPopup, PopupId, popupState } from '../../../../../../desktop/lib/auxiliary/popup'
import { get } from 'svelte/store'
import { handleError } from '@core/error/handlers/handleError'
-import { determineLedgerConnectionState, LedgerAppName, LedgerConnectionState, ledgerNanoStatus } from '..'
+import { determineLedgerConnectionState, LedgerAppName, LedgerConnectionState, ledgerDeviceState } from '..'
export function checkOrConnectLedger(
callback: () => Promise = async (): Promise => {},
@@ -19,7 +19,7 @@ export function checkOrConnectLedger(
}
}
try {
- const ledgerConnectionState = determineLedgerConnectionState(get(ledgerNanoStatus), ledgerAppName)
+ const ledgerConnectionState = determineLedgerConnectionState(get(ledgerDeviceState), ledgerAppName)
const ledgerConnected = ledgerConnectionState === LedgerConnectionState.CorrectAppOpen
if (ledgerConnected) {
return callback()
diff --git a/packages/shared/src/lib/core/ledger/actions/getAndUpdateLedgerDeviceState.ts b/packages/shared/src/lib/core/ledger/actions/getAndUpdateLedgerDeviceState.ts
new file mode 100644
index 0000000000..ae3a984839
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/actions/getAndUpdateLedgerDeviceState.ts
@@ -0,0 +1,32 @@
+import { profileManager as _profileManager } from '@core/profile-manager/stores'
+import { getLedgerNanoStatus } from '@lib/core/profile-manager/api'
+import { Ledger } from '../classes'
+import { resetLedgerDeviceState, setLedgerDeviceState } from '../stores'
+import { sleep } from '@core/utils'
+
+let isMakingRequest: boolean = false
+
+export async function getAndUpdateLedgerDeviceState(
+ profileManager = _profileManager,
+ forwardErrors = false
+): Promise {
+ try {
+ if (!isMakingRequest) {
+ isMakingRequest = true
+ const ledgerNanoStatus = await getLedgerNanoStatus(profileManager)
+ // sleep to make sure ledger process on iota sdk is wrapped up
+ await sleep(50)
+ const ethereumAppSettings = await Ledger.getEthereumAppSettings()
+ setLedgerDeviceState(ledgerNanoStatus, ethereumAppSettings)
+ }
+ } catch (err) {
+ resetLedgerDeviceState()
+ if (forwardErrors) {
+ return Promise.reject(err)
+ } else {
+ console.error(err)
+ }
+ } finally {
+ isMakingRequest = false
+ }
+}
diff --git a/packages/shared/src/lib/core/ledger/actions/getAndUpdateLedgerNanoStatus.ts b/packages/shared/src/lib/core/ledger/actions/getAndUpdateLedgerNanoStatus.ts
deleted file mode 100644
index 731586f459..0000000000
--- a/packages/shared/src/lib/core/ledger/actions/getAndUpdateLedgerNanoStatus.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { profileManager as _profileManager } from '@core/profile-manager'
-import { getLedgerNanoStatus } from '@lib/core/profile-manager/api'
-
-import { resetLedgerNanoStatus, updateLedgerNanoStatus } from '../stores'
-
-export async function getAndUpdateLedgerNanoStatus(
- profileManager = _profileManager,
- forwardErrors = false
-): Promise {
- try {
- const ledgerNanoStatusResponse = await getLedgerNanoStatus(profileManager)
- updateLedgerNanoStatus(ledgerNanoStatusResponse)
- } catch (err) {
- resetLedgerNanoStatus()
- if (forwardErrors) {
- return Promise.reject(err)
- } else {
- console.error(err)
- }
- }
-}
diff --git a/packages/shared/src/lib/core/ledger/actions/getLedgerDeviceStatus.ts b/packages/shared/src/lib/core/ledger/actions/getLedgerDeviceStatus.ts
deleted file mode 100644
index 2bf7df3d30..0000000000
--- a/packages/shared/src/lib/core/ledger/actions/getLedgerDeviceStatus.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { get } from 'svelte/store'
-import { getLedgerNanoStatus } from '@lib/core/profile-manager/api'
-import { PopupId, closePopup, popupState } from '../../../../../../desktop/lib/auxiliary/popup'
-import { ledgerNanoStatus, updateLedgerNanoStatus } from '../stores'
-
-export async function getLedgerDeviceStatus(
- onConnected = (): void => {},
- onDisconnected = (): void => {},
- onError = (): void => {}
-): Promise {
- try {
- const status = await getLedgerNanoStatus()
- updateLedgerNanoStatus(status)
-
- if (get(ledgerNanoStatus).connected) {
- const isLedgerNotConnectedPopupOpened =
- get(popupState).active && get(popupState).id === PopupId.ConnectLedger
-
- if (isLedgerNotConnectedPopupOpened) {
- closePopup()
- }
-
- onConnected()
- } else {
- onDisconnected()
- }
- } catch (err) {
- onError()
- }
-}
diff --git a/packages/shared/src/lib/core/ledger/actions/index.ts b/packages/shared/src/lib/core/ledger/actions/index.ts
index d4849b3af9..5385fd4900 100644
--- a/packages/shared/src/lib/core/ledger/actions/index.ts
+++ b/packages/shared/src/lib/core/ledger/actions/index.ts
@@ -1,5 +1,4 @@
export * from './checkOrConnectLedger'
-export * from './getLedgerDeviceStatus'
-export * from './pollLedgerNanoStatus'
-export * from './promptUserToConnectLedger'
+export * from './getAndUpdateLedgerDeviceState'
+export * from './pollLedgerDeviceState'
export * from './registerLedgerDeviceEventHandlers'
diff --git a/packages/shared/src/lib/core/ledger/actions/pollLedgerDeviceState.ts b/packages/shared/src/lib/core/ledger/actions/pollLedgerDeviceState.ts
new file mode 100644
index 0000000000..6e13adf4ef
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/actions/pollLedgerDeviceState.ts
@@ -0,0 +1,29 @@
+import { get } from 'svelte/store'
+import { profileManager as _profileManager } from '@core/profile-manager/stores'
+import { DEFAULT_LEDGER_DEVICE_STATE_POLL_INTERVAL } from '../constants'
+import { ILedgerDeviceStatePollingConfiguration } from '../interfaces'
+import { isPollingLedgerDeviceState } from '../stores'
+import { getAndUpdateLedgerDeviceState } from './getAndUpdateLedgerDeviceState'
+
+let intervalTimer: number | undefined
+
+export function pollLedgerDeviceState(config?: ILedgerDeviceStatePollingConfiguration): void {
+ const pollInterval = config?.pollInterval ?? DEFAULT_LEDGER_DEVICE_STATE_POLL_INTERVAL
+ const profileManager = config?.profileManager ?? _profileManager
+
+ if (!get(isPollingLedgerDeviceState)) {
+ void getAndUpdateLedgerDeviceState(profileManager)
+ intervalTimer = window.setInterval(() => {
+ void getAndUpdateLedgerDeviceState(profileManager)
+ }, pollInterval)
+ isPollingLedgerDeviceState.set(true)
+ }
+}
+
+export function stopPollingLedgerDeviceState(): void {
+ if (get(isPollingLedgerDeviceState)) {
+ window.clearInterval(intervalTimer)
+ intervalTimer = undefined
+ isPollingLedgerDeviceState.set(false)
+ }
+}
diff --git a/packages/shared/src/lib/core/ledger/actions/pollLedgerNanoStatus.ts b/packages/shared/src/lib/core/ledger/actions/pollLedgerNanoStatus.ts
deleted file mode 100644
index bf1aba6fec..0000000000
--- a/packages/shared/src/lib/core/ledger/actions/pollLedgerNanoStatus.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { get } from 'svelte/store'
-
-import { deconstructLedgerNanoStatusPollingConfiguration } from '../helpers'
-import { ILedgerNanoStatusPollingConfiguration } from '../interfaces'
-import { isPollingLedgerDeviceStatus } from '../stores'
-
-import { getAndUpdateLedgerNanoStatus } from './getAndUpdateLedgerNanoStatus'
-
-let intervalTimer: ReturnType
-
-export function pollLedgerNanoStatus(config?: ILedgerNanoStatusPollingConfiguration): void {
- const { pollInterval, profileManager } = deconstructLedgerNanoStatusPollingConfiguration(config)
-
- if (!get(isPollingLedgerDeviceStatus)) {
- void getAndUpdateLedgerNanoStatus(profileManager)
- intervalTimer = setInterval(() => {
- void getAndUpdateLedgerNanoStatus(profileManager)
- }, pollInterval)
- isPollingLedgerDeviceStatus.set(true)
- }
-}
-
-export function stopPollingLedgerNanoStatus(): void {
- if (get(isPollingLedgerDeviceStatus)) {
- clearInterval(intervalTimer)
- intervalTimer = null
- isPollingLedgerDeviceStatus.set(false)
- }
-}
diff --git a/packages/shared/src/lib/core/ledger/actions/promptUserToConnectLedger.ts b/packages/shared/src/lib/core/ledger/actions/promptUserToConnectLedger.ts
deleted file mode 100644
index 75dd1b5b74..0000000000
--- a/packages/shared/src/lib/core/ledger/actions/promptUserToConnectLedger.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { get } from 'svelte/store'
-
-import { popupState } from '../../../../../../desktop/lib/auxiliary/popup'
-
-import { openLedgerNotConnectedPopup } from '../utils'
-
-import { getLedgerDeviceStatus } from './getLedgerDeviceStatus'
-import { pollLedgerNanoStatus } from './pollLedgerNanoStatus'
-
-export function promptUserToConnectLedger(
- onConnected = (): void => {},
- onCancel = (): void => {},
- overridePopup: boolean = false
-): void {
- function onDisconnected(): void {
- if (!get(popupState).active || overridePopup) {
- openLedgerNotConnectedPopup(onCancel, () => pollLedgerNanoStatus(), overridePopup)
- }
- }
-
- void getLedgerDeviceStatus(onConnected, onDisconnected, onCancel)
-}
diff --git a/packages/shared/src/lib/core/ledger/classes/ledger.class.ts b/packages/shared/src/lib/core/ledger/classes/ledger.class.ts
index e7a6d87f9d..295f18730c 100644
--- a/packages/shared/src/lib/core/ledger/classes/ledger.class.ts
+++ b/packages/shared/src/lib/core/ledger/classes/ledger.class.ts
@@ -3,7 +3,6 @@ import { Platform } from '@core/app/classes'
import { IPlatformEventMap } from '@core/app/interfaces'
import { localize } from '@core/i18n'
import { IEvmAddress, IEvmTransactionSignature } from '@core/layer-2/interfaces'
-import { EvmTransactionData } from '@core/layer-2/types'
import {
calculateMaxGasFeeFromTransactionData,
getAmountFromEvmTransactionValue,
@@ -14,9 +13,14 @@ import { TxData } from '@ethereumjs/tx'
import type { Bip44 } from '@iota/sdk/out/types'
import { PopupId, openPopup } from '../../../../../../desktop/lib/auxiliary/popup'
import { DEFAULT_LEDGER_API_REQUEST_OPTIONS } from '../constants'
-import { LedgerApiMethod } from '../enums'
+import { LedgerApiMethod, LedgerAppName } from '../enums'
import { ILedgerApiBridge } from '../interfaces'
import { LedgerApiRequestResponse } from '../types'
+import {
+ ILedgerApiRequestOptions,
+ ILedgerEthereumAppSettings,
+ isBlindSigningRequiredForEvmTransaction,
+} from '@core/ledger'
import { EvmChainId } from '@core/network/enums'
declare global {
@@ -28,6 +32,24 @@ declare global {
const ledgerApiBridge: ILedgerApiBridge = window['__LEDGER__']
export class Ledger {
+ static async getEthereumAppSettings(): Promise {
+ try {
+ return await this.callLedgerApiAsync(
+ () => ledgerApiBridge.makeRequest(LedgerApiMethod.GetEthereumAppSettings),
+ 'ethereum-app-settings',
+ {
+ timeout: 0.5 * MILLISECONDS_PER_SECOND,
+ }
+ )
+ } catch (err) {
+ return undefined
+ }
+ }
+
+ static async isBlindSigningEnabledForEvm(): Promise {
+ return Boolean((await this.getEthereumAppSettings())?.blindSigningEnabled)
+ }
+
static async generateEvmAddress(accountIndex: number, coinType: number, verify?: boolean): Promise {
const bip32Path = buildBip32PathFromBip44({
coinType,
@@ -41,62 +63,92 @@ export class Ledger {
}
static async signEvmTransaction(
- txData: TxData,
+ transactionData: TxData,
chainId: EvmChainId,
- bip44: Bip44,
- promptVerification = true
- ): Promise {
- const unsignedTransactionMessageHex = prepareEvmTransaction(txData as EvmTransactionData, chainId)
- const bip32Path = buildBip32PathFromBip44(bip44)
-
- const maxGasFee = calculateMaxGasFeeFromTransactionData(txData)
- // TODO: https://github.com/bloomwalletio/bloom/issues/432
- if (promptVerification) {
- openPopup({
- id: PopupId.VerifyLedgerTransaction,
- hideClose: true,
- preventClose: true,
- props: {
- isEvmTransaction: true,
- toAmount: getAmountFromEvmTransactionValue(txData?.value?.toString()).toString(),
- toAddress: txData.to,
- chainId,
- maxGasFee,
- },
- })
- }
+ bip44: Bip44
+ ): Promise {
+ /* eslint-disable no-async-promise-executor */
+ /* eslint-disable @typescript-eslint/no-misused-promises */
+ return new Promise(async (resolve, reject) => {
+ const unsignedTransactionMessageHex = prepareEvmTransaction(transactionData, chainId)
+ const bip32Path = buildBip32PathFromBip44(bip44)
+ const maxGasFee = calculateMaxGasFeeFromTransactionData(transactionData)
- const transactionSignature = await this.callLedgerApiAsync(
- () =>
- ledgerApiBridge.makeRequest(
- LedgerApiMethod.SignEvmTransaction,
- unsignedTransactionMessageHex,
- bip32Path
- ),
- 'evm-signed-transaction'
- )
+ const mustEnableBlindSigning =
+ isBlindSigningRequiredForEvmTransaction(transactionData) && !(await this.isBlindSigningEnabledForEvm())
+ if (mustEnableBlindSigning) {
+ let canResolve = true
+ openPopup({
+ id: PopupId.EnableLedgerBlindSigning,
+ props: {
+ appName: LedgerAppName.Ethereum,
+ onEnabled: async () => {
+ canResolve = false
+ try {
+ resolve(await this.signEvmTransaction(transactionData, chainId, bip44))
+ } catch (err) {
+ reject(err)
+ }
+ },
+ onClose: () => {
+ if (canResolve) {
+ canResolve = false
+ resolve()
+ }
+ },
+ },
+ })
+ } else {
+ openPopup({
+ id: PopupId.VerifyLedgerTransaction,
+ hideClose: true,
+ preventClose: true,
+ props: {
+ isEvmTransaction: true,
+ toAmount: getAmountFromEvmTransactionValue(transactionData?.value?.toString()),
+ toAddress: transactionData.to,
+ chainId,
+ maxGasFee,
+ },
+ })
- if (promptVerification) {
- openPopup(
- {
- id: PopupId.SendFlow,
- },
- true
- )
- }
+ const transactionSignature = await this.callLedgerApiAsync(
+ () =>
+ ledgerApiBridge.makeRequest(
+ LedgerApiMethod.SignEvmTransaction,
+ unsignedTransactionMessageHex,
+ bip32Path
+ ),
+ 'evm-signed-transaction'
+ )
- const { r, v, s } = transactionSignature
- if (r && v && s) {
- return prepareEvmTransaction(txData, chainId, { r, v, s })
- }
+ openPopup(
+ {
+ id: PopupId.SendFlow,
+ },
+ true
+ )
+
+ const { r, v, s } = transactionSignature
+ if (r && v && s) {
+ resolve(prepareEvmTransaction(transactionData, chainId, { r, v, s }))
+ } else {
+ reject(localize('error.send.cancelled'))
+ }
+ }
+ })
}
private static async callLedgerApiAsync(
callback: () => void,
- responseEvent: keyof IPlatformEventMap
+ responseEvent: keyof IPlatformEventMap,
+ requestOptions: Partial = {}
): Promise {
- const { timeout, pollingInterval } = DEFAULT_LEDGER_API_REQUEST_OPTIONS
- const iterationCount = (timeout * MILLISECONDS_PER_SECOND) / pollingInterval
+ // TODO: Do we need to stop / start polling here? Get's slightly complicated in that
+ // the Ethereum app settings polling uses this function.
+
+ const { timeout, pollingInterval } = { ...DEFAULT_LEDGER_API_REQUEST_OPTIONS, ...requestOptions }
+ const iterationCount = timeout / pollingInterval
callback()
@@ -110,6 +162,7 @@ export class Ledger {
for (let count = 0; count < iterationCount; count++) {
if (!isGenerating) {
+ Platform.removeListenersForEvent(responseEvent)
if (returnValue && Object.keys(returnValue).length !== 0) {
return returnValue
} else {
@@ -119,6 +172,7 @@ export class Ledger {
await sleep(pollingInterval)
}
+ Platform.removeListenersForEvent(responseEvent)
return Promise.reject(localize('error.ledger.timeout'))
}
}
diff --git a/packages/shared/src/lib/core/ledger/constants/default-ledger-api-request-options.constant.ts b/packages/shared/src/lib/core/ledger/constants/default-ledger-api-request-options.constant.ts
index f57983e227..8f14f1e00f 100644
--- a/packages/shared/src/lib/core/ledger/constants/default-ledger-api-request-options.constant.ts
+++ b/packages/shared/src/lib/core/ledger/constants/default-ledger-api-request-options.constant.ts
@@ -1,6 +1,7 @@
+import { MILLISECONDS_PER_SECOND } from '@core/utils'
import { ILedgerApiRequestOptions } from '../interfaces'
export const DEFAULT_LEDGER_API_REQUEST_OPTIONS: ILedgerApiRequestOptions = {
- timeout: 60,
- pollingInterval: 100,
+ timeout: 60 * MILLISECONDS_PER_SECOND, // In milliseconds
+ pollingInterval: 100, // In milliseconds
}
diff --git a/packages/shared/src/lib/core/ledger/constants/default-ledger-device-state-poll-interval.constant.ts b/packages/shared/src/lib/core/ledger/constants/default-ledger-device-state-poll-interval.constant.ts
new file mode 100644
index 0000000000..7bef48bac9
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/constants/default-ledger-device-state-poll-interval.constant.ts
@@ -0,0 +1,5 @@
+import { MILLISECONDS_PER_SECOND } from '@core/utils'
+
+const INTERVAL_IN_SECONDS = 1
+
+export const DEFAULT_LEDGER_DEVICE_STATE_POLL_INTERVAL = INTERVAL_IN_SECONDS * MILLISECONDS_PER_SECOND
diff --git a/packages/shared/src/lib/core/ledger/constants/default-ledger-nano-status-poll-interval.constant.ts b/packages/shared/src/lib/core/ledger/constants/default-ledger-nano-status-poll-interval.constant.ts
deleted file mode 100644
index eff784f11d..0000000000
--- a/packages/shared/src/lib/core/ledger/constants/default-ledger-nano-status-poll-interval.constant.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { MILLISECONDS_PER_SECOND } from '@core/utils'
-
-const INTERVAL_IN_SECONDS = 1
-
-export const DEFAULT_LEDGER_NANO_STATUS_POLL_INTERVAL = INTERVAL_IN_SECONDS * MILLISECONDS_PER_SECOND
diff --git a/packages/shared/src/lib/core/ledger/constants/index.ts b/packages/shared/src/lib/core/ledger/constants/index.ts
index 89b5fc7b5a..fcdc0fb7aa 100644
--- a/packages/shared/src/lib/core/ledger/constants/index.ts
+++ b/packages/shared/src/lib/core/ledger/constants/index.ts
@@ -1,4 +1,4 @@
export * from './default-ledger-api-request-options.constant'
-export * from './default-ledger-nano-status-poll-interval.constant'
+export * from './default-ledger-device-state-poll-interval.constant'
export * from './ledger-error-locales.constant'
export * from './use-ledger-simulator.constant'
diff --git a/packages/shared/src/lib/core/ledger/enums/index.ts b/packages/shared/src/lib/core/ledger/enums/index.ts
index 62f73b6d2d..a5c642cdb8 100644
--- a/packages/shared/src/lib/core/ledger/enums/index.ts
+++ b/packages/shared/src/lib/core/ledger/enums/index.ts
@@ -1,3 +1,4 @@
export * from './ledger-api-method.enum'
export * from './ledger-app-name.enum'
+export * from './ledger-connection-state.enum'
export * from './ledger-error.enum'
diff --git a/packages/shared/src/lib/core/ledger/enums/ledger-api-method.enum.ts b/packages/shared/src/lib/core/ledger/enums/ledger-api-method.enum.ts
index cbe3f11ae3..6faaf7e2c9 100644
--- a/packages/shared/src/lib/core/ledger/enums/ledger-api-method.enum.ts
+++ b/packages/shared/src/lib/core/ledger/enums/ledger-api-method.enum.ts
@@ -1,4 +1,5 @@
export enum LedgerApiMethod {
GenerateEvmAddress = 'generate-evm-address',
+ GetEthereumAppSettings = 'get-ethereum-app-settings',
SignEvmTransaction = 'sign-evm-transaction',
}
diff --git a/packages/shared/src/lib/core/ledger/interfaces/ledger-connection-state.interface.ts b/packages/shared/src/lib/core/ledger/enums/ledger-connection-state.enum.ts
similarity index 100%
rename from packages/shared/src/lib/core/ledger/interfaces/ledger-connection-state.interface.ts
rename to packages/shared/src/lib/core/ledger/enums/ledger-connection-state.enum.ts
diff --git a/packages/shared/src/lib/core/ledger/helpers/deconstructLedgerNanoStatusPollingConfiguration.ts b/packages/shared/src/lib/core/ledger/helpers/deconstructLedgerNanoStatusPollingConfiguration.ts
deleted file mode 100644
index e13183c59c..0000000000
--- a/packages/shared/src/lib/core/ledger/helpers/deconstructLedgerNanoStatusPollingConfiguration.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { profileManager as _profileManager } from '@core/profile-manager/stores'
-
-import { DEFAULT_LEDGER_NANO_STATUS_POLL_INTERVAL } from '../constants'
-import { ILedgerNanoStatusPollingConfiguration } from '../interfaces'
-
-export function deconstructLedgerNanoStatusPollingConfiguration(
- config: ILedgerNanoStatusPollingConfiguration
-): ILedgerNanoStatusPollingConfiguration {
- const pollInterval = config?.pollInterval ?? DEFAULT_LEDGER_NANO_STATUS_POLL_INTERVAL
- const profileManager = config?.profileManager ?? _profileManager
-
- return {
- pollInterval,
- profileManager,
- }
-}
diff --git a/packages/shared/src/lib/core/ledger/helpers/index.ts b/packages/shared/src/lib/core/ledger/helpers/index.ts
index 20f01de3f0..a33cc00d4e 100644
--- a/packages/shared/src/lib/core/ledger/helpers/index.ts
+++ b/packages/shared/src/lib/core/ledger/helpers/index.ts
@@ -1,3 +1,2 @@
-export * from './deconstructLedgerNanoStatusPollingConfiguration'
export * from './deconstructLedgerVerificationProps'
export * from './deriveLedgerError'
diff --git a/packages/shared/src/lib/core/ledger/interfaces/app-settings/base-ledger-app-settings.interface.ts b/packages/shared/src/lib/core/ledger/interfaces/app-settings/base-ledger-app-settings.interface.ts
new file mode 100644
index 0000000000..2f7d334b5c
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/interfaces/app-settings/base-ledger-app-settings.interface.ts
@@ -0,0 +1,4 @@
+export interface IBaseLedgerAppSettings {
+ blindSigningEnabled: boolean
+ version: string
+}
diff --git a/packages/shared/src/lib/core/ledger/interfaces/app-settings/index.ts b/packages/shared/src/lib/core/ledger/interfaces/app-settings/index.ts
new file mode 100644
index 0000000000..061a194729
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/interfaces/app-settings/index.ts
@@ -0,0 +1,3 @@
+export * from './base-ledger-app-settings.interface'
+export * from './ledger-app-settings.interface'
+export * from './ledger-ethereum-app-settings.interface'
diff --git a/packages/shared/src/lib/core/ledger/interfaces/app-settings/ledger-app-settings.interface.ts b/packages/shared/src/lib/core/ledger/interfaces/app-settings/ledger-app-settings.interface.ts
new file mode 100644
index 0000000000..6faf79bae2
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/interfaces/app-settings/ledger-app-settings.interface.ts
@@ -0,0 +1,8 @@
+import { LedgerAppName } from '../../enums'
+import { ILedgerEthereumAppSettings } from './ledger-ethereum-app-settings.interface'
+import { IBaseLedgerAppSettings } from './base-ledger-app-settings.interface'
+
+export interface ILedgerAppSettings {
+ [LedgerAppName.Shimmer]?: IBaseLedgerAppSettings
+ [LedgerAppName.Ethereum]?: ILedgerEthereumAppSettings
+}
diff --git a/packages/shared/src/lib/core/ledger/interfaces/app-settings/ledger-ethereum-app-settings.interface.ts b/packages/shared/src/lib/core/ledger/interfaces/app-settings/ledger-ethereum-app-settings.interface.ts
new file mode 100644
index 0000000000..9963ab81d1
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/interfaces/app-settings/ledger-ethereum-app-settings.interface.ts
@@ -0,0 +1,7 @@
+import { IBaseLedgerAppSettings } from './base-ledger-app-settings.interface'
+
+export interface ILedgerEthereumAppSettings extends IBaseLedgerAppSettings {
+ erc20ProvisioningNecessary: boolean
+ starkEnabled: boolean
+ starkv2Supported: boolean
+}
diff --git a/packages/shared/src/lib/core/ledger/interfaces/index.ts b/packages/shared/src/lib/core/ledger/interfaces/index.ts
index ff06a8e3ae..dcba5b6942 100644
--- a/packages/shared/src/lib/core/ledger/interfaces/index.ts
+++ b/packages/shared/src/lib/core/ledger/interfaces/index.ts
@@ -1,4 +1,6 @@
+export * from './app-settings'
+
export * from './ledger-api-bridge.interface'
export * from './ledger-api-request-options.interface'
-export * from './ledger-connection-state.interface'
-export * from './ledger-nano-status-polling-configuration.interface'
+export * from './ledger-device-state.interface'
+export * from './ledger-device-state-polling-configuration.interface'
diff --git a/packages/shared/src/lib/core/ledger/interfaces/ledger-api-bridge.interface.ts b/packages/shared/src/lib/core/ledger/interfaces/ledger-api-bridge.interface.ts
index 3ccfb4a000..b04c3db8df 100644
--- a/packages/shared/src/lib/core/ledger/interfaces/ledger-api-bridge.interface.ts
+++ b/packages/shared/src/lib/core/ledger/interfaces/ledger-api-bridge.interface.ts
@@ -2,5 +2,6 @@ import { LedgerApiMethod } from '../enums'
export interface ILedgerApiBridge {
makeRequest(method: LedgerApiMethod.GenerateEvmAddress, bip32Path: string, verify: boolean): void
+ makeRequest(method: LedgerApiMethod.GetEthereumAppSettings): void
makeRequest(method: LedgerApiMethod.SignEvmTransaction, transactionHex: string, bip32Path: string): void
}
diff --git a/packages/shared/src/lib/core/ledger/interfaces/ledger-nano-status-polling-configuration.interface.ts b/packages/shared/src/lib/core/ledger/interfaces/ledger-device-state-polling-configuration.interface.ts
similarity index 74%
rename from packages/shared/src/lib/core/ledger/interfaces/ledger-nano-status-polling-configuration.interface.ts
rename to packages/shared/src/lib/core/ledger/interfaces/ledger-device-state-polling-configuration.interface.ts
index 0da66b01c3..28c3117d1d 100644
--- a/packages/shared/src/lib/core/ledger/interfaces/ledger-nano-status-polling-configuration.interface.ts
+++ b/packages/shared/src/lib/core/ledger/interfaces/ledger-device-state-polling-configuration.interface.ts
@@ -2,7 +2,7 @@ import { Writable } from 'svelte/store'
import { IProfileManager } from '@core/profile-manager'
-export interface ILedgerNanoStatusPollingConfiguration {
+export interface ILedgerDeviceStatePollingConfiguration {
pollInterval?: number
profileManager?: Writable
}
diff --git a/packages/shared/src/lib/core/ledger/interfaces/ledger-device-state.interface.ts b/packages/shared/src/lib/core/ledger/interfaces/ledger-device-state.interface.ts
new file mode 100644
index 0000000000..f03305d22e
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/interfaces/ledger-device-state.interface.ts
@@ -0,0 +1,12 @@
+import { LedgerDeviceType } from '@iota/sdk/out/types'
+import { LedgerAppName } from '../enums'
+import { ILedgerAppSettings } from './app-settings'
+
+export interface ILedgerDeviceState {
+ connected?: boolean
+ locked?: boolean
+ device?: LedgerDeviceType
+ app?: LedgerAppName
+ settings?: ILedgerAppSettings
+ bufferSize?: number
+}
diff --git a/packages/shared/src/lib/core/ledger/stores/index.ts b/packages/shared/src/lib/core/ledger/stores/index.ts
index 15deb19c41..c14e6f430a 100644
--- a/packages/shared/src/lib/core/ledger/stores/index.ts
+++ b/packages/shared/src/lib/core/ledger/stores/index.ts
@@ -1,5 +1,5 @@
-export * from './is-polling-ledger-device-status.store'
+export * from './is-polling-ledger-device-state.stores'
export * from './ledger-connection-state.store'
-export * from './ledger-nano-status.store'
+export * from './ledger-device-state.store'
export * from './ledger-prepared-output.store'
export * from './show-internal-verification-popup'
diff --git a/packages/shared/src/lib/core/ledger/stores/is-polling-ledger-device-state.stores.ts b/packages/shared/src/lib/core/ledger/stores/is-polling-ledger-device-state.stores.ts
new file mode 100644
index 0000000000..7b22e967a7
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/stores/is-polling-ledger-device-state.stores.ts
@@ -0,0 +1,3 @@
+import { writable } from 'svelte/store'
+
+export const isPollingLedgerDeviceState = writable(false)
diff --git a/packages/shared/src/lib/core/ledger/stores/is-polling-ledger-device-status.store.ts b/packages/shared/src/lib/core/ledger/stores/is-polling-ledger-device-status.store.ts
deleted file mode 100644
index 7b1b7bef52..0000000000
--- a/packages/shared/src/lib/core/ledger/stores/is-polling-ledger-device-status.store.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { writable } from 'svelte/store'
-
-export const isPollingLedgerDeviceStatus = writable(false)
diff --git a/packages/shared/src/lib/core/ledger/stores/ledger-connection-state.store.ts b/packages/shared/src/lib/core/ledger/stores/ledger-connection-state.store.ts
index 670679822a..1b13b40ac4 100644
--- a/packages/shared/src/lib/core/ledger/stores/ledger-connection-state.store.ts
+++ b/packages/shared/src/lib/core/ledger/stores/ledger-connection-state.store.ts
@@ -1,9 +1,9 @@
import { Readable, derived } from 'svelte/store'
-import { LedgerConnectionState } from '../interfaces'
+import { LedgerConnectionState } from '../enums'
import { determineLedgerConnectionState } from '../utils'
-import { ledgerNanoStatus } from './ledger-nano-status.store'
+import { ledgerDeviceState } from './ledger-device-state.store'
export const ledgerConnectionState: Readable = derived(
- [ledgerNanoStatus],
- ([$ledgerNanoStatus]) => determineLedgerConnectionState($ledgerNanoStatus)
+ [ledgerDeviceState],
+ ([$ledgerNanoState]) => determineLedgerConnectionState($ledgerNanoState)
)
diff --git a/packages/shared/src/lib/core/ledger/stores/ledger-device-state.store.ts b/packages/shared/src/lib/core/ledger/stores/ledger-device-state.store.ts
new file mode 100644
index 0000000000..e75a604133
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/stores/ledger-device-state.store.ts
@@ -0,0 +1,19 @@
+import { writable } from 'svelte/store'
+import { LedgerNanoStatus } from '@iota/sdk/out/types'
+import { ILedgerEthereumAppSettings, ILedgerDeviceState } from '../interfaces'
+import { buildLedgerDeviceState } from '../utils'
+
+const DEFAULT_LEDGER_DEVICE_STATE: ILedgerDeviceState = {
+ connected: false,
+ locked: true,
+}
+
+export const ledgerDeviceState = writable(DEFAULT_LEDGER_DEVICE_STATE)
+
+export function setLedgerDeviceState(status: LedgerNanoStatus, ethereumAppSettings?: ILedgerEthereumAppSettings): void {
+ return ledgerDeviceState.set(buildLedgerDeviceState(status, ethereumAppSettings))
+}
+
+export function resetLedgerDeviceState(): void {
+ ledgerDeviceState.set(DEFAULT_LEDGER_DEVICE_STATE)
+}
diff --git a/packages/shared/src/lib/core/ledger/types/ledger-api-request-response.type.ts b/packages/shared/src/lib/core/ledger/types/ledger-api-request-response.type.ts
index 504dc4792b..7ce9e1c0d0 100644
--- a/packages/shared/src/lib/core/ledger/types/ledger-api-request-response.type.ts
+++ b/packages/shared/src/lib/core/ledger/types/ledger-api-request-response.type.ts
@@ -1,3 +1,4 @@
-import { IEvmAddress, IEvmTransactionSignature } from '@core/layer-2/interfaces'
+import type { IEvmAddress, IEvmTransactionSignature } from '@core/layer-2/interfaces'
+import { ILedgerEthereumAppSettings } from '../interfaces'
-export type LedgerApiRequestResponse = IEvmAddress | IEvmTransactionSignature
+export type LedgerApiRequestResponse = ILedgerEthereumAppSettings | IEvmAddress | IEvmTransactionSignature
diff --git a/packages/shared/src/lib/core/ledger/utils/buildLedgerDeviceState.ts b/packages/shared/src/lib/core/ledger/utils/buildLedgerDeviceState.ts
new file mode 100644
index 0000000000..d2bfebf98b
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/utils/buildLedgerDeviceState.ts
@@ -0,0 +1,27 @@
+import { LedgerNanoStatus } from '@iota/sdk/out/types'
+import { LedgerAppName } from '../enums'
+import { ILedgerAppSettings, ILedgerDeviceState, ILedgerEthereumAppSettings } from '../interfaces'
+
+export function buildLedgerDeviceState(
+ status: LedgerNanoStatus,
+ ethereumAppSettings?: ILedgerEthereumAppSettings
+): ILedgerDeviceState {
+ const app = status.app
+
+ return {
+ connected: ethereumAppSettings ? true : status.connected,
+ locked: ethereumAppSettings ? false : status.locked,
+ device: status.device,
+ app: app?.name as LedgerAppName,
+ settings: {
+ ...(app &&
+ (app?.name as LedgerAppName) === LedgerAppName.Shimmer && {
+ [LedgerAppName.Shimmer]: {
+ version: app.version,
+ blindSigningEnabled: status?.blindSigningEnabled,
+ },
+ }),
+ ...(ethereumAppSettings && { [LedgerAppName.Ethereum]: ethereumAppSettings }),
+ },
+ }
+}
diff --git a/packages/shared/src/lib/core/ledger/utils/determineLedgerConnectionState.ts b/packages/shared/src/lib/core/ledger/utils/determineLedgerConnectionState.ts
index 29ff818a84..712e83d800 100644
--- a/packages/shared/src/lib/core/ledger/utils/determineLedgerConnectionState.ts
+++ b/packages/shared/src/lib/core/ledger/utils/determineLedgerConnectionState.ts
@@ -1,21 +1,20 @@
-import { LedgerNanoStatus } from '@iota/sdk/out/types'
-import { LedgerConnectionState } from '../interfaces'
-import { LedgerAppName } from '../enums'
+import { LedgerAppName, LedgerConnectionState } from '../enums'
+import { ILedgerDeviceState } from '../interfaces'
export function determineLedgerConnectionState(
- status: LedgerNanoStatus,
+ status: ILedgerDeviceState,
appName = LedgerAppName.Shimmer
): LedgerConnectionState {
- const { connected, app } = status
+ const { connected, locked, app } = status
if (connected) {
- if (app) {
- if (app.name === (appName as string)) {
+ if (locked) {
+ return LedgerConnectionState.Locked
+ } else {
+ if (app === appName) {
return LedgerConnectionState.CorrectAppOpen
} else {
return LedgerConnectionState.AppNotOpen
}
- } else {
- return LedgerConnectionState.Locked
}
} else {
return LedgerConnectionState.NotConnected
diff --git a/packages/shared/src/lib/core/ledger/utils/handleLedgerError.ts b/packages/shared/src/lib/core/ledger/utils/handleLedgerError.ts
index 91a4db2a10..127d6e9489 100644
--- a/packages/shared/src/lib/core/ledger/utils/handleLedgerError.ts
+++ b/packages/shared/src/lib/core/ledger/utils/handleLedgerError.ts
@@ -3,13 +3,15 @@ import { get } from 'svelte/store'
import { localize } from '@core/i18n/i18n'
import { resetMintTokenDetails, resetMintNftDetails } from '@core/wallet/stores'
import { IError } from '@core/error/interfaces'
-import { handleGenericError } from '@core/error/handlers'
+import { handleError, handleGenericError } from '@core/error/handlers'
import { showNotification } from '@auxiliary/notification'
import { closePopup, openPopup, PopupId, popupState } from '../../../../../../desktop/lib/auxiliary/popup'
import { LEDGER_ERROR_LOCALES } from '../constants'
-import { LedgerError } from '../enums'
+import { LedgerAppName, LedgerError } from '../enums'
import { deriveLedgerError } from '../helpers'
+import { checkOrConnectLedger, ledgerPreparedOutput, resetLedgerPreparedOutput } from '@core/ledger'
+import { sendOutput } from '@core/wallet'
export function handleLedgerError(error: IError, resetConfirmationPropsOnDenial = true): void {
const ledgerError = deriveLedgerError(error?.error)
@@ -39,6 +41,21 @@ export function handleLedgerError(error: IError, resetConfirmationPropsOnDenial
if (hadToEnableBlindSinging) {
openPopup({
id: PopupId.EnableLedgerBlindSigning,
+ props: {
+ appName: LedgerAppName.Shimmer,
+ onEnabled: () => {
+ checkOrConnectLedger(async () => {
+ try {
+ if (get(ledgerPreparedOutput)) {
+ await sendOutput(get(ledgerPreparedOutput))
+ resetLedgerPreparedOutput()
+ }
+ } catch (err) {
+ handleError(err)
+ }
+ })
+ },
+ },
})
} else {
showNotification({
diff --git a/packages/shared/src/lib/core/ledger/utils/index.ts b/packages/shared/src/lib/core/ledger/utils/index.ts
index e1f54ba7fe..8f37e7039c 100644
--- a/packages/shared/src/lib/core/ledger/utils/index.ts
+++ b/packages/shared/src/lib/core/ledger/utils/index.ts
@@ -1,7 +1,8 @@
+export * from './buildLedgerDeviceState'
export * from './determineLedgerConnectionState'
export * from './formatAddressForLedger'
export * from './handleLedgerError'
+export * from './isBlindSigningRequiredForEvmTransaction'
export * from './isLedgerAppOpen'
export * from './isLedgerDeviceMatchingActiveProfile'
export * from './isLedgerError'
-export * from './openLedgerNotConnectedPopup'
diff --git a/packages/shared/src/lib/core/ledger/utils/isBlindSigningRequiredForEvmTransaction.ts b/packages/shared/src/lib/core/ledger/utils/isBlindSigningRequiredForEvmTransaction.ts
new file mode 100644
index 0000000000..18c1abc5fa
--- /dev/null
+++ b/packages/shared/src/lib/core/ledger/utils/isBlindSigningRequiredForEvmTransaction.ts
@@ -0,0 +1,5 @@
+import type { EvmTransactionData } from '@core/layer-2/types'
+
+export function isBlindSigningRequiredForEvmTransaction(transactionData: EvmTransactionData): boolean {
+ return Boolean(transactionData?.data)
+}
diff --git a/packages/shared/src/lib/core/ledger/utils/isLedgerAppOpen.ts b/packages/shared/src/lib/core/ledger/utils/isLedgerAppOpen.ts
index 477755c034..7d2e398c32 100644
--- a/packages/shared/src/lib/core/ledger/utils/isLedgerAppOpen.ts
+++ b/packages/shared/src/lib/core/ledger/utils/isLedgerAppOpen.ts
@@ -1,8 +1,8 @@
import { get } from 'svelte/store'
import { LedgerAppName } from '../enums'
-import { ledgerNanoStatus } from '../stores'
+import { ledgerDeviceState } from '../stores'
export function isLedgerAppOpen(appName: LedgerAppName): boolean {
- return get(ledgerNanoStatus)?.app?.name === (appName as string)
+ return get(ledgerDeviceState)?.app === appName
}
diff --git a/packages/shared/src/lib/core/ledger/utils/openLedgerNotConnectedPopup.ts b/packages/shared/src/lib/core/ledger/utils/openLedgerNotConnectedPopup.ts
deleted file mode 100644
index 123610a947..0000000000
--- a/packages/shared/src/lib/core/ledger/utils/openLedgerNotConnectedPopup.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { get } from 'svelte/store'
-import { openPopup, PopupId, popupState } from '../../../../../../desktop/lib/auxiliary/popup'
-
-export function openLedgerNotConnectedPopup(
- cancel: () => void = () => {},
- poll: () => void = () => {},
- overridePopup: boolean = false
-): void {
- if (!get(popupState).active || overridePopup) {
- openPopup({
- id: PopupId.ConnectLedger,
- props: {
- onClose: () => cancel(),
- onPoll: () => poll(),
- },
- })
- }
-}
diff --git a/packages/shared/src/lib/core/profile-manager/actions/events-handlers/handleTransactionProgressEvent.ts b/packages/shared/src/lib/core/profile-manager/actions/events-handlers/handleTransactionProgressEvent.ts
index 1aa392d59f..23e658439b 100644
--- a/packages/shared/src/lib/core/profile-manager/actions/events-handlers/handleTransactionProgressEvent.ts
+++ b/packages/shared/src/lib/core/profile-manager/actions/events-handlers/handleTransactionProgressEvent.ts
@@ -1,6 +1,7 @@
import { isOnboardingLedgerProfile } from '@contexts/onboarding'
import { selectedAccountIndex } from '@core/account/stores'
-import { ledgerNanoStatus } from '@core/ledger'
+import { LedgerAppName } from '@core/ledger/enums'
+import { ledgerDeviceState, ledgerPreparedOutput, resetLedgerPreparedOutput } from '@core/ledger/stores'
import { deconstructLedgerVerificationProps } from '@core/ledger/helpers'
import { isActiveLedgerProfile } from '@core/profile/stores'
import {
@@ -15,6 +16,9 @@ import { get } from 'svelte/store'
import { PopupId, closePopup, openPopup } from '../../../../../../../desktop/lib/auxiliary/popup'
import { MissingTransactionProgressEventPayloadError } from '../../errors'
import { validateWalletApiEvent } from '../../utils'
+import { checkOrConnectLedger } from '@core/ledger/actions'
+import { handleError } from '@core/error/handlers'
+import { sendOutput } from '@core/wallet/actions'
export function handleTransactionProgressEvent(error: Error, event: Event): void {
const walletEvent = validateWalletApiEvent(
@@ -54,12 +58,13 @@ function openPopupIfVerificationNeeded(progress: TransactionProgress): void {
},
})
} else if (type === TransactionProgressType.PreparedTransactionEssenceHash) {
- if (get(ledgerNanoStatus)?.blindSigningEnabled) {
+ if (get(ledgerDeviceState)?.settings?.[LedgerAppName.Shimmer]?.blindSigningEnabled) {
openPopup({
id: PopupId.VerifyLedgerTransaction,
hideClose: true,
preventClose: true,
props: {
+ useBlindSigning: true,
hash: (progress as PreparedTransactionEssenceHashProgress).hash,
},
})
@@ -68,6 +73,21 @@ function openPopupIfVerificationNeeded(progress: TransactionProgress): void {
id: PopupId.EnableLedgerBlindSigning,
hideClose: true,
preventClose: true,
+ props: {
+ appName: LedgerAppName.Shimmer,
+ onEnabled: () => {
+ checkOrConnectLedger(async () => {
+ try {
+ if (get(ledgerPreparedOutput)) {
+ await sendOutput(get(ledgerPreparedOutput))
+ resetLedgerPreparedOutput()
+ }
+ } catch (err) {
+ handleError(err)
+ }
+ })
+ },
+ },
})
}
} else if (type === TransactionProgressType.PerformingPow) {
diff --git a/packages/shared/src/lib/core/profile-manager/api/getLedgerNanoStatus.ts b/packages/shared/src/lib/core/profile-manager/api/getLedgerNanoStatus.ts
index 7d4eccf10b..556ce1c801 100644
--- a/packages/shared/src/lib/core/profile-manager/api/getLedgerNanoStatus.ts
+++ b/packages/shared/src/lib/core/profile-manager/api/getLedgerNanoStatus.ts
@@ -1,6 +1,6 @@
-import { LedgerNanoStatus } from '@iota/sdk/out/types'
import { get } from 'svelte/store'
import { profileManager as _profileManager } from '@core/profile-manager/stores'
+import type { LedgerNanoStatus } from '@iota/sdk/out/types'
export function getLedgerNanoStatus(profileManager = _profileManager): Promise {
const manager = get(profileManager)
diff --git a/packages/shared/src/lib/core/profile/actions/active-profile/login.ts b/packages/shared/src/lib/core/profile/actions/active-profile/login.ts
index 6d508baccd..577a263396 100644
--- a/packages/shared/src/lib/core/profile/actions/active-profile/login.ts
+++ b/packages/shared/src/lib/core/profile/actions/active-profile/login.ts
@@ -8,7 +8,7 @@ import { generateAndStoreActivitiesForAllAccounts } from '@core/activity/actions
import { Platform } from '@core/app/classes'
import { AppContext } from '@core/app/enums'
import { handleError } from '@core/error/handlers'
-import { pollLedgerNanoStatus } from '@core/ledger/actions'
+import { pollLedgerDeviceState } from '@core/ledger/actions'
import { pollMarketPrices } from '@core/market/actions'
import { pollChainStatuses, pollNetworkStatus } from '@core/network/actions'
import { loadNftsForActiveProfile } from '@core/nfts/actions'
@@ -136,7 +136,7 @@ export async function login(loginOptions?: ILoginOptions): Promise {
// Step 9: finish login
incrementLoginProgress()
if (isLedgerProfile(type)) {
- pollLedgerNanoStatus()
+ pollLedgerDeviceState()
}
setSelectedAccount(lastUsedAccountIndex ?? get(activeAccounts)?.[0]?.index ?? null)
diff --git a/packages/shared/src/lib/core/profile/actions/active-profile/logout.ts b/packages/shared/src/lib/core/profile/actions/active-profile/logout.ts
index 81924fcd57..d7f659ec51 100644
--- a/packages/shared/src/lib/core/profile/actions/active-profile/logout.ts
+++ b/packages/shared/src/lib/core/profile/actions/active-profile/logout.ts
@@ -6,8 +6,8 @@ import {
resetProposalOverviews,
resetRegisteredProposals,
} from '@contexts/governance/stores'
-import { stopPollingLedgerNanoStatus } from '@core/ledger/actions'
-import { isPollingLedgerDeviceStatus } from '@core/ledger/stores'
+import { stopPollingLedgerDeviceState } from '@core/ledger/actions'
+import { isPollingLedgerDeviceState } from '@core/ledger/stores'
import { clearMarketPricesPoll } from '@core/market/actions'
import { clearChainStatusesPoll, clearNetworkPoll } from '@core/network/actions'
import { stopDownloadingNftMediaFromQueue } from '@core/nfts/actions'
@@ -29,7 +29,7 @@ export function logout(clearActiveProfile = true, _lockStronghold = true): void
_lockStronghold && lockStronghold()
} else if (isLedgerProfile(get(activeProfile).type)) {
Platform.killLedgerProcess()
- get(isPollingLedgerDeviceStatus) && stopPollingLedgerNanoStatus()
+ get(isPollingLedgerDeviceState) && stopPollingLedgerDeviceState()
}
clearNetworkPoll()
diff --git a/packages/shared/src/lib/core/wallet/actions/send/signAndSendEvmTransaction.ts b/packages/shared/src/lib/core/wallet/actions/send/signAndSendEvmTransaction.ts
index fc0105d7f6..7cb61e046d 100644
--- a/packages/shared/src/lib/core/wallet/actions/send/signAndSendEvmTransaction.ts
+++ b/packages/shared/src/lib/core/wallet/actions/send/signAndSendEvmTransaction.ts
@@ -36,18 +36,16 @@ export async function signAndSendEvmTransaction(
if (get(isSoftwareProfile)) {
signedTransaction = await signEvmTransactionWithStronghold(transaction, bip44Path, chainId)
} else if (get(isActiveLedgerProfile)) {
- signedTransaction = await Ledger.signEvmTransaction(txData, chainId, bip44Path)
+ signedTransaction = (await Ledger.signEvmTransaction(txData, chainId, bip44Path)) as string
}
if (signedTransaction) {
return await provider?.eth.sendSignedTransaction(signedTransaction)
- } else {
- if (get(isActiveLedgerProfile)) {
- closePopup(true)
- }
- throw new Error('No signature provided')
}
} catch (err) {
+ if (get(isActiveLedgerProfile)) {
+ closePopup(true)
+ }
handleError(err)
} finally {
updateSelectedAccount({ isTransferring: false })
diff --git a/packages/shared/src/locales/en.json b/packages/shared/src/locales/en.json
index 9ad43bda99..06dc060b62 100644
--- a/packages/shared/src/locales/en.json
+++ b/packages/shared/src/locales/en.json
@@ -559,10 +559,10 @@
"popups": {
"enableLedgerBlindSigning": {
"title": "Enable Blind Signing",
- "info": "In order to confirm this transaction you need to enable Blind Signing on your ledger device.",
- "step_1": "Connect and unlock your Ledger Device",
- "step_2": "Open Shimmer Application",
- "step_3": "Press the right button to navigate to Settings. Then press both buttons to validate. Your Ledger device displays Blind Signing.",
+ "info": "In order to confirm this transaction you need to enable Blind Signing on your Ledger device.",
+ "step_1": "Connect and unlock your Ledger device",
+ "step_2": "Open the {appName} application",
+ "step_3": "Press the right button to navigate to Settings, then press both buttons to validate. Your Ledger device displays Blind Signing.",
"step_4": "Press both buttons to enable transaction blind signing. The device displays Enabled. You're done."
},
"balanceBreakdown": {