fix(@desktop/wallet): importing keypairs at the account level (navigating into an account page in Wallet) (point 9)
Point 9 of #11968
This commit is contained in:
parent
fadad5f4f6
commit
aec5dc62c9
|
@ -197,7 +197,7 @@ proc newModule*[T](
|
|||
result, events, tokenService, currencyService,
|
||||
transactionService, walletAccountService,
|
||||
settingsService, savedAddressService, networkService, accountsService,
|
||||
keycardService, nodeService, networkConnectionService
|
||||
keycardService, nodeService, networkConnectionService, devicesService
|
||||
)
|
||||
result.browserSectionModule = browser_section_module.newModule(
|
||||
result, events, bookmarkService, settingsService, networkService,
|
||||
|
@ -1355,6 +1355,6 @@ method communityMembersRevealedAccountsLoaded*[T](self: Module[T], communityId:
|
|||
if revealedAccount.isAirdropAddress:
|
||||
communityMembersAirdropAddress[pubkey] = revealedAccount.address
|
||||
discard
|
||||
|
||||
|
||||
self.view.model.setMembersAirdropAddress(communityId, communityMembersAirdropAddress)
|
||||
|
||||
|
|
|
@ -68,3 +68,9 @@ proc toggleIncludeWatchOnlyAccount*(self: Controller) =
|
|||
|
||||
proc isIncludeWatchOnlyAccount*(self: Controller): bool =
|
||||
return self.walletAccountService.isIncludeWatchOnlyAccount()
|
||||
|
||||
proc getKeypairByAccountAddress*(self: Controller, address: string): KeypairDto =
|
||||
return self.walletAccountService.getKeypairByAccountAddress(address)
|
||||
|
||||
proc hasPairedDevices*(self: Controller): bool =
|
||||
return self.walletAccountService.hasPairedDevices()
|
|
@ -99,3 +99,18 @@ method getLatestBlockNumber*(self: AccessInterface, chainId: int): string {.base
|
|||
|
||||
method fetchDecodedTxData*(self: AccessInterface, txHash: string, data: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method runKeypairImportPopup*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getKeypairImportModule*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onKeypairImportModuleLoaded*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method destroyKeypairImportPopup*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method hasPairedDevices*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
|
@ -1,4 +1,4 @@
|
|||
import NimQml, chronicles, sequtils, sugar
|
||||
import NimQml, chronicles, sequtils, strutils, sugar
|
||||
|
||||
import ./controller, ./view, ./filter
|
||||
import ./io_interface as io_interface
|
||||
|
@ -12,25 +12,27 @@ import ./buy_sell_crypto/module as buy_sell_crypto_module
|
|||
import ./networks/module as networks_module
|
||||
import ./overview/module as overview_module
|
||||
import ./send/module as send_module
|
||||
import ../../shared_modules/add_account/module as add_account_module
|
||||
|
||||
import ./activity/controller as activityc
|
||||
import app/modules/shared_modules/collectibles/controller as collectiblesc
|
||||
import app/modules/shared_modules/collectible_details/controller as collectible_detailsc
|
||||
|
||||
import ../../../global/global_singleton
|
||||
import ../../../core/eventemitter
|
||||
import ../../../../app_service/service/keycard/service as keycard_service
|
||||
import ../../../../app_service/service/token/service as token_service
|
||||
import ../../../../app_service/service/currency/service as currency_service
|
||||
import ../../../../app_service/service/transaction/service as transaction_service
|
||||
import ../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../app_service/service/settings/service as settings_service
|
||||
import ../../../../app_service/service/saved_address/service as saved_address_service
|
||||
import ../../../../app_service/service/network/service as network_service
|
||||
import ../../../../app_service/service/accounts/service as accounts_service
|
||||
import ../../../../app_service/service/node/service as node_service
|
||||
import ../../../../app_service/service/network_connection/service as network_connection_service
|
||||
import app/global/global_singleton
|
||||
import app/core/eventemitter
|
||||
import app/modules/shared_modules/add_account/module as add_account_module
|
||||
import app/modules/shared_modules/keypair_import/module as keypair_import_module
|
||||
import app_service/service/keycard/service as keycard_service
|
||||
import app_service/service/token/service as token_service
|
||||
import app_service/service/currency/service as currency_service
|
||||
import app_service/service/transaction/service as transaction_service
|
||||
import app_service/service/wallet_account/service as wallet_account_service
|
||||
import app_service/service/settings/service as settings_service
|
||||
import app_service/service/saved_address/service as saved_address_service
|
||||
import app_service/service/network/service as network_service
|
||||
import app_service/service/accounts/service as accounts_service
|
||||
import app_service/service/node/service as node_service
|
||||
import app_service/service/network_connection/service as network_connection_service
|
||||
import app_service/service/devices/service as devices_service
|
||||
|
||||
import backend/collectibles as backend_collectibles
|
||||
|
||||
|
@ -52,13 +54,16 @@ type
|
|||
view: View
|
||||
filter: Filter
|
||||
|
||||
# shared modules
|
||||
addAccountModule: add_account_module.AccessInterface
|
||||
keypairImportModule: keypair_import_module.AccessInterface
|
||||
# modules
|
||||
accountsModule: accounts_module.AccessInterface
|
||||
allTokensModule: all_tokens_module.AccessInterface
|
||||
assetsModule: assets_module.AccessInterface
|
||||
sendModule: send_module.AccessInterface
|
||||
savedAddressesModule: saved_addresses_module.AccessInterface
|
||||
buySellCryptoModule: buy_sell_crypto_module.AccessInterface
|
||||
addAccountModule: add_account_module.AccessInterface
|
||||
overviewModule: overview_module.AccessInterface
|
||||
networksModule: networks_module.AccessInterface
|
||||
networksService: network_service.Service
|
||||
|
@ -66,6 +71,7 @@ type
|
|||
keycardService: keycard_service.Service
|
||||
accountsService: accounts_service.Service
|
||||
walletAccountService: wallet_account_service.Service
|
||||
devicesService: devices_service.Service
|
||||
|
||||
activityController: activityc.Controller
|
||||
collectiblesController: collectiblesc.Controller
|
||||
|
@ -73,6 +79,10 @@ type
|
|||
# instance to be used in temporary, short-lived, workflows (e.g. send popup)
|
||||
tmpActivityController: activityc.Controller
|
||||
|
||||
## Forward declaration
|
||||
proc onUpdatedKeypairsOperability*(self: Module, updatedKeypairs: seq[KeypairDto])
|
||||
proc onLocalPairingStatusUpdate*(self: Module, data: LocalPairingStatus)
|
||||
|
||||
proc newModule*(
|
||||
delegate: delegate_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
|
@ -86,7 +96,8 @@ proc newModule*(
|
|||
accountsService: accounts_service.Service,
|
||||
keycardService: keycard_service.Service,
|
||||
nodeService: node_service.Service,
|
||||
networkConnectionService: network_connection_service.Service
|
||||
networkConnectionService: network_connection_service.Service,
|
||||
devicesService: devices_service.Service
|
||||
): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
|
@ -94,6 +105,7 @@ proc newModule*(
|
|||
result.keycardService = keycardService
|
||||
result.accountsService = accountsService
|
||||
result.walletAccountService = walletAccountService
|
||||
result.devicesService = devicesService
|
||||
result.moduleLoaded = false
|
||||
result.controller = newController(result, settingsService, walletAccountService, currencyService, networkService)
|
||||
|
||||
|
@ -132,6 +144,8 @@ method delete*(self: Module) =
|
|||
|
||||
if not self.addAccountModule.isNil:
|
||||
self.addAccountModule.delete
|
||||
if not self.keypairImportModule.isNil:
|
||||
self.keypairImportModule.delete
|
||||
|
||||
method updateCurrency*(self: Module, currency: string) =
|
||||
self.controller.updateCurrency(currency)
|
||||
|
@ -167,10 +181,16 @@ method toggleWatchOnlyAccounts*(self: Module) =
|
|||
self.filter.toggleWatchOnlyAccounts()
|
||||
|
||||
method setFilterAddress*(self: Module, address: string) =
|
||||
let keypair = self.controller.getKeypairByAccountAddress(address)
|
||||
if keypair.isNil:
|
||||
self.view.setKeypairOperabilityForObservedAccount("")
|
||||
else:
|
||||
self.view.setKeypairOperabilityForObservedAccount(keypair.getOperability())
|
||||
self.filter.setAddress(address)
|
||||
self.notifyFilterChanged()
|
||||
|
||||
method setFillterAllAddresses*(self: Module) =
|
||||
self.view.setKeypairOperabilityForObservedAccount("")
|
||||
self.filter.setFillterAllAddresses()
|
||||
self.notifyFilterChanged()
|
||||
|
||||
|
@ -189,8 +209,7 @@ method load*(self: Module) =
|
|||
self.events.on(SIGNAL_WALLET_ACCOUNT_SAVED) do(e:Args):
|
||||
let args = AccountArgs(e)
|
||||
self.setTotalCurrencyBalance()
|
||||
self.filter.setAddress(args.account.address)
|
||||
self.notifyFilterChanged()
|
||||
self.setFilterAddress(args.account.address)
|
||||
self.events.on(SIGNAL_WALLET_ACCOUNT_DELETED) do(e:Args):
|
||||
let args = AccountArgs(e)
|
||||
self.setTotalCurrencyBalance()
|
||||
|
@ -223,6 +242,14 @@ method load*(self: Module) =
|
|||
self.events.on(SIGNAL_TRANSACTION_DECODED) do(e: Args):
|
||||
let args = TransactionDecodedArgs(e)
|
||||
self.view.txDecoded(args.txHash, args.dataDecoded)
|
||||
self.events.on(SIGNAL_IMPORTED_KEYPAIRS) do(e:Args):
|
||||
let args = KeypairsArgs(e)
|
||||
if args.error.len != 0:
|
||||
return
|
||||
self.onUpdatedKeypairsOperability(args.keypairs)
|
||||
self.events.on(SIGNAL_LOCAL_PAIRING_STATUS_UPDATE) do(e:Args):
|
||||
let data = LocalPairingStatus(e)
|
||||
self.onLocalPairingStatusUpdate(data)
|
||||
|
||||
self.controller.init()
|
||||
self.view.load()
|
||||
|
@ -344,3 +371,44 @@ method getLatestBlockNumber*(self: Module, chainId: int): string =
|
|||
|
||||
method fetchDecodedTxData*(self: Module, txHash: string, data: string) =
|
||||
self.transactionService.fetchDecodedTxData(txHash, data)
|
||||
|
||||
proc onUpdatedKeypairsOperability*(self: Module, updatedKeypairs: seq[KeypairDto]) =
|
||||
if self.filter.addresses.len != 1:
|
||||
return
|
||||
for kp in updatedKeypairs:
|
||||
for acc in kp.accounts:
|
||||
if cmpIgnoreCase(acc.address, self.filter.addresses[0]) == 0:
|
||||
self.view.setKeypairOperabilityForObservedAccount(kp.getOperability())
|
||||
return
|
||||
|
||||
method destroyKeypairImportPopup*(self: Module) =
|
||||
if self.keypairImportModule.isNil:
|
||||
return
|
||||
self.view.emitDestroyKeypairImportPopup()
|
||||
self.keypairImportModule.delete
|
||||
self.keypairImportModule = nil
|
||||
|
||||
method runKeypairImportPopup*(self: Module) =
|
||||
if self.filter.addresses.len != 1:
|
||||
return
|
||||
let keypair = self.controller.getKeypairByAccountAddress(self.filter.addresses[0])
|
||||
if keypair.isNil:
|
||||
return
|
||||
self.keypairImportModule = keypair_import_module.newModule(self, self.events, self.accountsService,
|
||||
self.walletAccountService, self.devicesService)
|
||||
self.keypairImportModule.load(keypair.keyUid, ImportKeypairModuleMode.SelectImportMethod)
|
||||
|
||||
method getKeypairImportModule*(self: Module): QVariant =
|
||||
if self.keypairImportModule.isNil:
|
||||
return newQVariant()
|
||||
return self.keypairImportModule.getModuleAsVariant()
|
||||
|
||||
method onKeypairImportModuleLoaded*(self: Module) =
|
||||
self.view.emitDisplayKeypairImportPopup()
|
||||
|
||||
method hasPairedDevices*(self: Module): bool =
|
||||
return self.controller.hasPairedDevices()
|
||||
|
||||
proc onLocalPairingStatusUpdate*(self: Module, data: LocalPairingStatus) =
|
||||
if data.state == LocalPairingState.Finished:
|
||||
self.view.emitHasPairedDevicesChangedSignal()
|
|
@ -20,6 +20,7 @@ QtObject:
|
|||
collectiblesController: collectiblesc.Controller
|
||||
collectibleDetailsController: collectible_detailsc.Controller
|
||||
isNonArchivalNode: bool
|
||||
keypairOperabilityForObservedAccount: string
|
||||
|
||||
proc setup(self: View) =
|
||||
self.QObject.setup
|
||||
|
@ -167,3 +168,38 @@ QtObject:
|
|||
notify = isNonArchivalNodeChanged
|
||||
|
||||
proc txDecoded*(self: View, txHash: string, dataDecoded: string) {.signal.}
|
||||
|
||||
proc hasPairedDevicesChanged*(self: View) {.signal.}
|
||||
proc emitHasPairedDevicesChangedSignal*(self: View) =
|
||||
self.hasPairedDevicesChanged()
|
||||
proc getHasPairedDevices(self: View): bool {.slot.} =
|
||||
return self.delegate.hasPairedDevices()
|
||||
QtProperty[bool] hasPairedDevices:
|
||||
read = getHasPairedDevices
|
||||
notify = hasPairedDevicesChanged
|
||||
|
||||
proc keypairOperabilityForObservedAccountChanged(self: View) {.signal.}
|
||||
proc getKeypairOperabilityForObservedAccount(self: View): string {.slot.} =
|
||||
return self.keypairOperabilityForObservedAccount
|
||||
QtProperty[string] keypairOperabilityForObservedAccount:
|
||||
read = getKeypairOperabilityForObservedAccount
|
||||
notify = keypairOperabilityForObservedAccountChanged
|
||||
proc setKeypairOperabilityForObservedAccount*(self: View, value: string) =
|
||||
self.keypairOperabilityForObservedAccount = value
|
||||
self.keypairOperabilityForObservedAccountChanged()
|
||||
|
||||
proc runKeypairImportPopup*(self: View) {.slot.} =
|
||||
self.delegate.runKeypairImportPopup()
|
||||
|
||||
proc getKeypairImportModule(self: View): QVariant {.slot.} =
|
||||
return self.delegate.getKeypairImportModule()
|
||||
QtProperty[QVariant] keypairImportModule:
|
||||
read = getKeypairImportModule
|
||||
|
||||
proc displayKeypairImportPopup*(self: View) {.signal.}
|
||||
proc emitDisplayKeypairImportPopup*(self: View) =
|
||||
self.displayKeypairImportPopup()
|
||||
|
||||
proc destroyKeypairImportPopup*(self: View) {.signal.}
|
||||
proc emitDestroyKeypairImportPopup*(self: View) =
|
||||
self.destroyKeypairImportPopup()
|
|
@ -30,6 +30,12 @@ proc getKeypairByKeyUid*(self: Service, keyUid: string): KeypairDto =
|
|||
return
|
||||
return self.keypairs[keyUid]
|
||||
|
||||
proc getKeypairByAccountAddress*(self: Service, address: string): KeypairDto =
|
||||
for _, kp in self.keypairs:
|
||||
for acc in kp.accounts:
|
||||
if cmpIgnoreCase(acc.address, address) == 0:
|
||||
return kp
|
||||
|
||||
proc getWatchOnlyAccounts*(self: Service): seq[WalletAccountDto] =
|
||||
return toSeq(self.watchOnlyAccounts.values)
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import AppLayouts.Wallet 1.0
|
|||
import AppLayouts.Wallet.controls 1.0
|
||||
import AppLayouts.Profile.popups 1.0
|
||||
|
||||
import shared.controls 1.0
|
||||
import shared.popups 1.0
|
||||
import shared.panels 1.0
|
||||
import utils 1.0
|
||||
|
@ -79,50 +80,17 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
ImportKeypairInfo {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.bigPadding
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
visible: !!root.keyPair && root.keyPair.operability === Constants.keypair.operability.nonOperable
|
||||
radius: Style.current.radius
|
||||
border.width: 1
|
||||
border.color: Theme.palette.directColor8
|
||||
color: Theme.palette.transparent
|
||||
|
||||
ColumnLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
spacing: Style.current.halfPadding
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.padding
|
||||
text: qsTr("Import keypair to use this account")
|
||||
color: Theme.palette.warningColor1
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
text: qsTr("This account was added to one of your synced devices. To use this account you will first need import the associated keypair to this device.")
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.bottomMargin: Style.current.padding
|
||||
text: qsTr("Import keypair")
|
||||
type: StatusBaseButton.Type.Warning
|
||||
icon.name: "download"
|
||||
onClicked: {
|
||||
root.runImportMissingKeypairFlow()
|
||||
}
|
||||
}
|
||||
onRunImport: {
|
||||
root.runImportMissingKeypairFlow()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StatusBaseText {
|
||||
Layout.topMargin: Style.current.bigPadding
|
||||
text: qsTr("Account details")
|
||||
|
|
|
@ -6,6 +6,7 @@ import StatusQ.Layout 0.1
|
|||
|
||||
import utils 1.0
|
||||
import shared.controls 1.0
|
||||
import shared.popups.keypairimport 1.0
|
||||
|
||||
import "popups"
|
||||
import "panels"
|
||||
|
@ -32,6 +33,14 @@ Item {
|
|||
function onFilterChanged(address, includeWatchOnly, allAddresses) {
|
||||
root.showAllAccounts = allAddresses
|
||||
}
|
||||
|
||||
function onDisplayKeypairImportPopup() {
|
||||
keypairImport.active = true
|
||||
}
|
||||
|
||||
function onDestroyKeypairImportPopup() {
|
||||
keypairImport.active = false
|
||||
}
|
||||
}
|
||||
|
||||
function showSigningPhrasePopup(){
|
||||
|
@ -150,4 +159,18 @@ Item {
|
|||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: keypairImport
|
||||
active: false
|
||||
asynchronous: true
|
||||
|
||||
sourceComponent: KeypairImportPopup {
|
||||
store.keypairImportModule: root.store.walletSectionInst.keypairImportModule
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
keypairImport.item.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import StatusQ.Core 0.1
|
|||
import StatusQ.Controls 0.1
|
||||
|
||||
import utils 1.0
|
||||
import shared.controls 1.0
|
||||
import shared.views 1.0
|
||||
import shared.stores 1.0
|
||||
|
||||
|
@ -76,6 +77,18 @@ Item {
|
|||
onLaunchShareAddressModal: root.launchShareAddressModal()
|
||||
onSwitchHideWatchOnlyAccounts: RootStore.toggleWatchOnlyAccounts()
|
||||
}
|
||||
|
||||
ImportKeypairInfo {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.bigPadding
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
visible: root.store.walletSectionInst.hasPairedDevices && root.store.walletSectionInst.keypairOperabilityForObservedAccount === Constants.keypair.operability.nonOperable
|
||||
|
||||
onRunImport: {
|
||||
root.store.walletSectionInst.runKeypairImportPopup()
|
||||
}
|
||||
}
|
||||
|
||||
StatusTabBar {
|
||||
id: walletTabBar
|
||||
objectName: "rightSideWalletTabBar"
|
||||
|
|
|
@ -11,6 +11,7 @@ QtObject {
|
|||
id: root
|
||||
|
||||
property var mainModuleInst: mainModule
|
||||
property var walletSectionInst: walletSection
|
||||
property var aboutModuleInst: aboutModule
|
||||
property var communitiesModuleInst: communitiesModule
|
||||
property bool newVersionAvailable: false
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property string title: qsTr("Import keypair to use this account")
|
||||
property string info: qsTr("This account was added to one of your synced devices. To use this account you will first need import the associated keypair to this device.")
|
||||
property string buttonName: qsTr("Import keypair")
|
||||
|
||||
signal runImport()
|
||||
|
||||
radius: Style.current.radius
|
||||
border.width: 1
|
||||
border.color: Theme.palette.directColor8
|
||||
color: Theme.palette.transparent
|
||||
|
||||
ColumnLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
spacing: Style.current.halfPadding
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.padding
|
||||
text: root.title
|
||||
color: Theme.palette.warningColor1
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
text: root.info
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.bottomMargin: Style.current.padding
|
||||
text: root.buttonName
|
||||
type: StatusBaseButton.Type.Warning
|
||||
icon.name: "download"
|
||||
onClicked: {
|
||||
root.runImport()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,3 +45,4 @@ ErrorDetails 1.0 ErrorDetails.qml
|
|||
CopyButton 1.0 CopyButton.qml
|
||||
DisabledTooltipButton 1.0 DisabledTooltipButton.qml
|
||||
WalletAccountListItem 1.0 WalletAccountListItem.qml
|
||||
ImportKeypairInfo 1.0 ImportKeypairInfo.qml
|
||||
|
|
Loading…
Reference in New Issue