feat(@desktop/syncing): generating connection string and inserting connection string for transferring keystore files introduced

Refers to the third part of #11779
This commit is contained in:
Sale Djenic 2023-08-21 12:56:55 +02:00 committed by saledjenic
parent c207a4aefc
commit 85d4bfdfea
12 changed files with 255 additions and 75 deletions

View File

@ -215,7 +215,8 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.privacyService = privacy_service.newService(statusFoundation.events, result.settingsService, result.privacyService = privacy_service.newService(statusFoundation.events, result.settingsService,
result.accountsService) result.accountsService)
result.savedAddressService = saved_address_service.newService(statusFoundation.events, result.networkService, result.settingsService) result.savedAddressService = saved_address_service.newService(statusFoundation.events, result.networkService, result.settingsService)
result.devicesService = devices_service.newService(statusFoundation.events, statusFoundation.threadpool, result.settingsService, result.accountsService) result.devicesService = devices_service.newService(statusFoundation.events, statusFoundation.threadpool,
result.settingsService, result.accountsService, result.walletAccountService)
result.mailserversService = mailservers_service.newService(statusFoundation.events, statusFoundation.threadpool, result.mailserversService = mailservers_service.newService(statusFoundation.events, statusFoundation.threadpool,
result.settingsService, result.nodeConfigurationService, statusFoundation.fleetConfiguration) result.settingsService, result.nodeConfigurationService, statusFoundation.fleetConfiguration)
result.nodeService = node_service.newService(statusFoundation.events, result.settingsService, result.nodeConfigurationService) result.nodeService = node_service.newService(statusFoundation.events, result.settingsService, result.nodeConfigurationService)

View File

@ -1,8 +1,8 @@
import json, tables, chronicles import json, tables, sequtils, sugar, chronicles
import base import base
import ../../../../app_service/service/accounts/dto/accounts import app_service/service/accounts/dto/accounts
import ../../../../app_service/service/devices/dto/installation import app_service/service/devices/dto/installation
import ../../../../app_service/service/devices/dto/local_pairing_event import app_service/service/devices/dto/local_pairing_event
type LocalPairingSignal* = ref object of Signal type LocalPairingSignal* = ref object of Signal
@ -11,6 +11,7 @@ type LocalPairingSignal* = ref object of Signal
error*: string error*: string
accountData*: LocalPairingAccountData accountData*: LocalPairingAccountData
installation*: InstallationDto installation*: InstallationDto
transferredKeypairs*: seq[string] ## seq[keypair_key_uid]
proc fromEvent*(T: type LocalPairingSignal, event: JsonNode): LocalPairingSignal = proc fromEvent*(T: type LocalPairingSignal, event: JsonNode): LocalPairingSignal =
result = LocalPairingSignal() result = LocalPairingSignal()
@ -29,5 +30,7 @@ proc fromEvent*(T: type LocalPairingSignal, event: JsonNode): LocalPairingSignal
result.accountData = e["data"].toLocalPairingAccountData() result.accountData = e["data"].toLocalPairingAccountData()
of EventReceivedInstallation: of EventReceivedInstallation:
result.installation = e["data"].toInstallationDto() result.installation = e["data"].toInstallationDto()
of EventReceivedKeystoreFiles:
result.transferredKeypairs = map(e["data"].getElems(), x => x.getStr())
else: else:
discard discard

View File

@ -27,7 +27,7 @@ QtObject:
result.devicesLoadingError = false result.devicesLoadingError = false
result.model = newModel() result.model = newModel()
result.modelVariant = newQVariant(result.model) result.modelVariant = newQVariant(result.model)
result.localPairingStatus = newLocalPairingStatus() result.localPairingStatus = newLocalPairingStatus(PairingType.AppSync, LocalPairingMode.Receiver)
proc load*(self: View) = proc load*(self: View) =
self.delegate.viewDidLoad() self.delegate.viewDidLoad()

View File

@ -69,7 +69,7 @@ QtObject:
result.loginAccountsModel = login_acc_model.newModel() result.loginAccountsModel = login_acc_model.newModel()
result.loginAccountsModelVariant = newQVariant(result.loginAccountsModel) result.loginAccountsModelVariant = newQVariant(result.loginAccountsModel)
result.remainingAttempts = -1 result.remainingAttempts = -1
result.localPairingStatus = newLocalPairingStatus() result.localPairingStatus = newLocalPairingStatus(PairingType.AppSync, LocalPairingMode.Receiver)
signalConnect(result.currentStartupState, "backActionClicked()", result, "onBackActionClicked()", 2) signalConnect(result.currentStartupState, "backActionClicked()", result, "onBackActionClicked()", 2)
signalConnect(result.currentStartupState, "primaryActionClicked()", result, "onPrimaryActionClicked()", 2) signalConnect(result.currentStartupState, "primaryActionClicked()", result, "onPrimaryActionClicked()", 2)

View File

@ -18,3 +18,8 @@ const asyncInputConnectionStringTask: Task = proc(argEncoded: string) {.gcsafe,
let arg = decode[AsyncInputConnectionStringArg](argEncoded) let arg = decode[AsyncInputConnectionStringArg](argEncoded)
let response = status_go.inputConnectionStringForBootstrapping(arg.connectionString, arg.configJSON) let response = status_go.inputConnectionStringForBootstrapping(arg.connectionString, arg.configJSON)
arg.finish(response) arg.finish(response)
const asyncInputConnectionStringForImportingKeystoreTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncInputConnectionStringArg](argEncoded)
let response = status_go.inputConnectionStringForImportingKeypairsKeystores(arg.connectionString, arg.configJSON)
arg.finish(response)

View File

@ -6,23 +6,25 @@ import installation
type type
EventType* {.pure.} = enum EventType* {.pure.} = enum
EventUnknown = -1, EventUnknown = -1
EventConnectionError = 0, EventConnectionError
EventConnectionSuccess = 1, EventConnectionSuccess
EventTransferError = 2, EventTransferError
EventTransferSuccess = 3, EventTransferSuccess
EventReceivedAccount = 4, EventReceivedAccount
EventReceivedInstallation = 5 EventReceivedInstallation
EventProcessSuccess = 6, EventProcessSuccess
EventProcessError = 7 EventProcessError
EventReceivedKeystoreFiles
type type
Action* {.pure.} = enum Action* {.pure.} = enum
ActionUnknown = 0 ActionUnknown = 0
ActionConnect = 1, ActionConnect
ActionPairingAccount = 2, ActionPairingAccount
ActionSyncDevice = 3, ActionSyncDevice
ActionPairingInstallation = 4, ActionPairingInstallation
ActionKeystoreFilesTransfer
type type
LocalPairingAccountData* = ref object LocalPairingAccountData* = ref object
@ -38,6 +40,7 @@ type
error*: string error*: string
accountData*: LocalPairingAccountData accountData*: LocalPairingAccountData
installation*: InstallationDto installation*: InstallationDto
transferredKeypairs*: seq[string] ## seq[keypair_key_uid]
proc parse*(self: string): EventType = proc parse*(self: string): EventType =
case self: case self:
@ -57,6 +60,8 @@ proc parse*(self: string): EventType =
return EventReceivedAccount return EventReceivedAccount
of "received-installation": of "received-installation":
return EventReceivedInstallation return EventReceivedInstallation
of "received-keystore-files":
return EventReceivedKeystoreFiles
else: else:
return EventUnknown return EventUnknown

View File

@ -3,6 +3,11 @@ import ../../accounts/dto/accounts
import installation import installation
import local_pairing_event import local_pairing_event
type
PairingType* {.pure.} = enum
AppSync = 0
KeypairSync
type type
LocalPairingState* {.pure.} = enum LocalPairingState* {.pure.} = enum
Idle = 0 Idle = 0
@ -18,29 +23,25 @@ type
type type
LocalPairingStatus* = ref object of Args LocalPairingStatus* = ref object of Args
pairingType*: PairingType
mode*: LocalPairingMode mode*: LocalPairingMode
state*: LocalPairingState state*: LocalPairingState
account*: AccountDto account*: AccountDto
password*: string password*: string
chatKey*: string chatKey*: string
installation*: InstallationDto installation*: InstallationDto
transferredKeypairs*: seq[string] ## seq[keypair_key_uid]
error*: string error*: string
proc reset*(self: LocalPairingStatus) =
self.mode = LocalPairingMode.Idle
self.state = LocalPairingState.Idle
self.error = ""
self.installation = InstallationDto()
proc setup(self: LocalPairingStatus) =
self.reset()
proc delete*(self: LocalPairingStatus) = proc delete*(self: LocalPairingStatus) =
discard discard
proc newLocalPairingStatus*(): LocalPairingStatus = proc newLocalPairingStatus*(pairingType: PairingType, mode: LocalPairingMode): LocalPairingStatus =
new(result, delete) new(result, delete)
result.setup() result.pairingType = pairingType
result.mode = mode
result.state = LocalPairingState.Idle
result.installation = InstallationDto()
proc update*(self: LocalPairingStatus, data: LocalPairingEventArgs) = proc update*(self: LocalPairingStatus, data: LocalPairingEventArgs) =
@ -54,6 +55,8 @@ proc update*(self: LocalPairingStatus, data: LocalPairingEventArgs) =
self.chatKey = data.accountData.chatKey self.chatKey = data.accountData.chatKey
of EventReceivedInstallation: of EventReceivedInstallation:
self.installation = data.installation self.installation = data.installation
of EventReceivedKeystoreFiles:
self.transferredKeypairs = data.transferredKeypairs
of EventConnectionError: of EventConnectionError:
self.state = LocalPairingState.Error self.state = LocalPairingState.Error
of EventTransferError: of EventTransferError:
@ -67,15 +70,19 @@ proc update*(self: LocalPairingStatus, data: LocalPairingEventArgs) =
return return
# Detect finished state # Detect finished state
if (self.mode == LocalPairingMode.Sender and if self.mode == LocalPairingMode.Sender and
data.eventType == EventProcessSuccess and data.eventType == EventProcessSuccess:
data.action == ActionPairingInstallation): if self.pairingType == PairingType.AppSync and
self.state = LocalPairingState.Finished data.action == ActionPairingInstallation or
self.pairingType == PairingType.KeypairSync:
self.state = LocalPairingState.Finished
if (self.mode == LocalPairingMode.Receiver and if self.mode == LocalPairingMode.Receiver and
data.eventType == EventTransferSuccess and data.eventType == EventTransferSuccess:
data.action == ActionPairingInstallation): if self.pairingType == PairingType.AppSync and
self.state = LocalPairingState.Finished data.action == ActionPairingInstallation or
self.pairingType == PairingType.KeypairSync:
self.state = LocalPairingState.Finished
if self.state == LocalPairingState.Finished: if self.state == LocalPairingState.Finished:
return return

View File

@ -8,6 +8,7 @@ import ./dto/local_pairing_status
import app_service/service/settings/service as settings_service import app_service/service/settings/service as settings_service
import app_service/service/accounts/service as accounts_service import app_service/service/accounts/service as accounts_service
import app_service/service/wallet_account/service as wallet_account_service
import app/global/global_singleton import app/global/global_singleton
import app/core/[main] import app/core/[main]
@ -55,23 +56,26 @@ QtObject:
threadpool: ThreadPool threadpool: ThreadPool
settingsService: settings_service.Service settingsService: settings_service.Service
accountsService: accounts_service.Service accountsService: accounts_service.Service
walletAccountService: wallet_account_service.Service
localPairingStatus: LocalPairingStatus localPairingStatus: LocalPairingStatus
proc delete*(self: Service) = proc delete*(self: Service) =
self.QObject.delete self.QObject.delete
self.localPairingStatus.delete if not self.localPairingStatus.isNil:
self.localPairingStatus.delete
proc newService*(events: EventEmitter, proc newService*(events: EventEmitter,
threadpool: ThreadPool, threadpool: ThreadPool,
settingsService: settings_service.Service, settingsService: settings_service.Service,
accountsService: accounts_service.Service): Service = accountsService: accounts_service.Service,
new(result, delete) walletAccountService: wallet_account_service.Service): Service =
result.QObject.setup new(result, delete)
result.events = events result.QObject.setup
result.threadpool = threadpool result.events = events
result.settingsService = settingsService result.threadpool = threadpool
result.accountsService = accountsService result.settingsService = settingsService
result.localPairingStatus = newLocalPairingStatus() result.accountsService = accountsService
result.walletAccountService = walletAccountService
proc updateLocalPairingStatus(self: Service, data: LocalPairingEventArgs) = proc updateLocalPairingStatus(self: Service, data: LocalPairingEventArgs) =
self.localPairingStatus.update(data) self.localPairingStatus.update(data)
@ -98,15 +102,23 @@ QtObject:
self.events.on(SignalType.LocalPairing.event) do(e:Args): self.events.on(SignalType.LocalPairing.event) do(e:Args):
let signalData = LocalPairingSignal(e) let signalData = LocalPairingSignal(e)
if not signalData.accountData.isNil and signalData.accountData.keycardPairings.len > 0: if self.localPairingStatus.pairingType == PairingType.AppSync:
createKeycardPairingFile(signalData.accountData.keycardPairings) if not signalData.accountData.isNil and signalData.accountData.keycardPairings.len > 0:
let data = LocalPairingEventArgs( createKeycardPairingFile(signalData.accountData.keycardPairings)
eventType: signalData.eventType, let data = LocalPairingEventArgs(
action: signalData.action, eventType: signalData.eventType,
accountData: signalData.accountData, action: signalData.action,
installation: signalData.installation, accountData: signalData.accountData,
error: signalData.error) installation: signalData.installation,
self.updateLocalPairingStatus(data) error: signalData.error)
self.updateLocalPairingStatus(data)
elif self.localPairingStatus.pairingType == PairingType.KeypairSync:
let data = LocalPairingEventArgs(
eventType: signalData.eventType,
action: signalData.action,
error: signalData.error,
transferredKeypairs: signalData.transferredKeypairs)
self.updateLocalPairingStatus(data)
proc init*(self: Service) = proc init*(self: Service) =
self.doConnect() self.doConnect()
@ -185,6 +197,10 @@ QtObject:
self.updateLocalPairingStatus(data) self.updateLocalPairingStatus(data)
proc validateConnectionString*(self: Service, connectionString: string): string = proc validateConnectionString*(self: Service, connectionString: string): string =
if connectionString.len == 0:
result = "an empty connection string provided"
error "error", msg=result
return
return status_go.validateConnectionString(connectionString) return status_go.validateConnectionString(connectionString)
proc getConnectionStringForBootstrappingAnotherDevice*(self: Service, password: string, chatKey: string): string = proc getConnectionStringForBootstrappingAnotherDevice*(self: Service, password: string, chatKey: string): string =
@ -209,8 +225,7 @@ QtObject:
"timeout": 5 * 60 * 1000, "timeout": 5 * 60 * 1000,
} }
} }
self.localPairingStatus.reset() self.localPairingStatus = newLocalPairingStatus(PairingType.AppSync, LocalPairingMode.Sender)
self.localPairingStatus.mode = LocalPairingMode.Sender
return status_go.getConnectionStringForBootstrappingAnotherDevice($configJSON) return status_go.getConnectionStringForBootstrappingAnotherDevice($configJSON)
proc inputConnectionStringForBootstrapping*(self: Service, connectionString: string): string = proc inputConnectionStringForBootstrapping*(self: Service, connectionString: string): string =
@ -226,8 +241,7 @@ QtObject:
}, },
"clientConfig": %* {} "clientConfig": %* {}
} }
self.localPairingStatus.reset() self.localPairingStatus = newLocalPairingStatus(PairingType.AppSync, LocalPairingMode.Receiver)
self.localPairingStatus.mode = LocalPairingMode.Receiver
let arg = AsyncInputConnectionStringArg( let arg = AsyncInputConnectionStringArg(
tptr: cast[ByteAddress](asyncInputConnectionStringTask), tptr: cast[ByteAddress](asyncInputConnectionStringTask),
@ -237,3 +251,127 @@ QtObject:
configJSON: $configJSON configJSON: $configJSON
) )
self.threadpool.start(arg) self.threadpool.start(arg)
proc validateKeyUids*(self: Service, keyUids: seq[string], validateForExport: bool): tuple[finalKeyUids: seq[string], err: string] =
if keyUids.len > 0:
for keyUid in keyUids:
let kp = self.walletAccountService.getKeypairByKeyUid(keyUid)
if kp.isNil:
result.err = "cannot resolve keypair for provided keyUid"
return
let migratedToKeycard = kp.keycards.len > 0
if migratedToKeycard or kp.keypairType == KeypairTypeProfile:
result.err = "keypair is migrated to a keycard or refers to a profile keypair"
return
if validateForExport:
if kp.getOperability() == AccountNonOperable:
result.err = "cannot export non operable keypair"
return
elif kp.getOperability() != AccountNonOperable:
result.err = "keypair is already fully or partially operable"
return
result.finalKeyUids.add(kp.keyUid)
else:
let keypairs = self.walletAccountService.getKeypairs()
for kp in keypairs:
let migratedToKeycard = kp.keycards.len > 0
if migratedToKeycard or
kp.keypairType == KeypairTypeProfile or
validateForExport and kp.getOperability() == AccountNonOperable or
not validateForExport and kp.getOperability() != AccountNonOperable:
continue
result.finalKeyUids.add(kp.keyUid)
if result.finalKeyUids.len == 0:
result.err = "there is no valid keypair"
## Providing an empty array of keyUids means generating a connection string and transferring all non operable keypairs
proc generateConnectionStringForExportingKeypairsKeystores*(self: Service, keyUids: seq[string], password: string): tuple[res: string, err: string] =
if password.len == 0:
result.err = "emtpy password provided"
error "error", msg=result.err
return
let(finalKeyUids, err) = self.validateKeyUids(keyUids, validateForExport=true)
if err.len > 0:
result.err = err
error "error", msg=err
return
let loggedInUserKeyUid = singletonInstance.userProfile.getKeyUid()
let keycardUser = singletonInstance.userProfile.getIsKeycardUser()
var finalPassword = utils.hashPassword(password)
if keycardUser:
finalPassword = password
let configJSON = %* {
"senderConfig": %* {
"keystorePath": joinPath(main_constants.ROOTKEYSTOREDIR, loggedInUserKeyUid),
"loggedInKeyUid": loggedInUserKeyUid,
"password": finalPassword,
"keypairsToExport": finalKeyUids,
},
"serverConfig": %* {
"timeout": 5 * 60 * 1000,
}
}
self.localPairingStatus = newLocalPairingStatus(PairingType.KeypairSync, LocalPairingMode.Sender)
let response = status_go.getConnectionStringForExportingKeypairsKeystores($configJSON)
try:
let jsonObj = response.parseJson
if jsonObj.hasKey("error"):
return ("", jsonObj["error"].getStr)
except Exception:
return (response, "")
proc inputConnectionStringForImportingKeystoreFinished*(self: Service, responseJson: string) {.slot.} =
try:
let jsonObj = responseJson.parseJson
if jsonObj.hasKey("error") and jsonObj["error"].getStr.len == 0:
info "keystore files successfully transferred"
self.walletAccountService.updateKeypairOperabilityInLocalStoreAndNotify(self.localPairingStatus.transferredKeypairs)
return
let errorDescription = jsonObj["error"].getStr
error "failed to start transferring keystore files", errorDescription
self.events.emit(SIGNAL_IMPORTED_KEYPAIRS, KeypairsArgs(error: errorDescription))
except Exception as e:
error "unexpected error", msg=e.msg
## Providing an empty array of keyUids means expecting keystore files for all non operable keypairs to be received
proc inputConnectionStringForImportingKeypairsKeystores*(self: Service, keyUids: seq[string], connectionString: string, password: string): string =
if password.len == 0:
result = "emtpy password provided"
error "error", msg=result
return
let(finalKeyUids, err) = self.validateKeyUids(keyUids, validateForExport=false)
if err.len > 0:
result = err
error "error", msg=result
return
let loggedInUserKeyUid = singletonInstance.userProfile.getKeyUid()
let keycardUser = singletonInstance.userProfile.getIsKeycardUser()
var finalPassword = utils.hashPassword(password)
if keycardUser:
finalPassword = password
let configJSON = %* {
"receiverConfig": %* {
"keystorePath": main_constants.ROOTKEYSTOREDIR,
"loggedInKeyUid": loggedInUserKeyUid,
"password": finalPassword,
"keypairsToImport": finalKeyUids,
},
"clientConfig": %* {}
}
self.localPairingStatus = newLocalPairingStatus(PairingType.KeypairSync, LocalPairingMode.Receiver)
let arg = AsyncInputConnectionStringArg(
tptr: cast[ByteAddress](asyncInputConnectionStringForImportingKeystoreTask),
vptr: cast[ByteAddress](self.vptr),
slot: "inputConnectionStringForImportingKeystoreFinished",
connectionString: connectionString,
configJSON: $configJSON
)
self.threadpool.start(arg)

View File

@ -1,4 +1,4 @@
import tables, json, strformat, strutils, chronicles import tables, json, strformat, strutils, sequtils, sugar, chronicles
import account_dto, keycard_dto import account_dto, keycard_dto
@ -73,3 +73,10 @@ proc `$`*(self: KeypairDto): string =
""" """
result &= """ result &= """
]""" ]"""
proc getOperability*(self: KeypairDto): string =
if self.accounts.any(x => x.operable == AccountNonOperable):
return AccountNonOperable
if self.accounts.any(x => x.operable == AccountPartiallyOperable):
return AccountPartiallyOperable
return AccountFullyOperable

View File

@ -215,14 +215,24 @@ proc removeAccountFromLocalStoreAndNotify(self: Service, address: string, notify
if notify: if notify:
self.events.emit(SIGNAL_WALLET_ACCOUNT_DELETED, AccountArgs(account: acc)) self.events.emit(SIGNAL_WALLET_ACCOUNT_DELETED, AccountArgs(account: acc))
proc updateKeypairOperabilityInLocalStoreAndNotify(self: Service, keyUid: string) = proc updateKeypairOperabilityInLocalStoreAndNotify*(self: Service, importedKeyUids: seq[string]) =
let kp = self.getKeypairByKeyUid(keyUid) var updatedKeypairs: seq[KeypairDto]
if kp.isNil: let localKeypairs = self.getKeypairs()
error "there is no known keypair", keyUid=keyUid, procName="updateKeypairOperabilityInLocalStoreAndNotify" for keyUid in importedKeyUids:
var foundKp: KeypairDto = nil
for kp in localKeypairs:
if keyUid == kp.keyUid:
foundKp = kp
break
if foundKp.isNil:
error "there is no known keypair", keyUid=keyUid, procName="updateKeypairOperabilityInLocalStoreAndNotify"
return
for acc in foundKp.accounts:
acc.operable = AccountFullyOperable
updatedKeypairs.add(foundKp)
if updatedKeypairs.len == 0:
return return
for acc in kp.accounts: self.events.emit(SIGNAL_IMPORTED_KEYPAIRS, KeypairsArgs(keypairs: updatedKeypairs))
acc.operable = AccountFullyOperable
self.events.emit(SIGNAL_KEYPAIR_OPERABILITY_CHANGED, KeypairArgs(keypair: kp))
proc updateAccountsPositions(self: Service) = proc updateAccountsPositions(self: Service) =
let dbAccounts = getAccountsFromDb() let dbAccounts = getAccountsFromDb()
@ -326,7 +336,7 @@ proc makePrivateKeyKeypairFullyOperable*(self: Service, keyUid, privateKey, pass
if not response.error.isNil: if not response.error.isNil:
error "status-go error", procName="makePrivateKeyKeypairFullyOperable", errCode=response.error.code, errDesription=response.error.message error "status-go error", procName="makePrivateKeyKeypairFullyOperable", errCode=response.error.code, errDesription=response.error.message
return response.error.message return response.error.message
self.updateKeypairOperabilityInLocalStoreAndNotify(keyUid) self.updateKeypairOperabilityInLocalStoreAndNotify(@[keyUid])
return "" return ""
except Exception as e: except Exception as e:
error "error: ", procName="makePrivateKeyKeypairFullyOperable", errName=e.name, errDesription=e.msg error "error: ", procName="makePrivateKeyKeypairFullyOperable", errName=e.name, errDesription=e.msg
@ -367,7 +377,7 @@ proc makeSeedPhraseKeypairFullyOperable*(self: Service, keyUid, mnemonic, passwo
if not response.error.isNil: if not response.error.isNil:
error "status-go error", procName="makeSeedPhraseKeypairFullyOperable", errCode=response.error.code, errDesription=response.error.message error "status-go error", procName="makeSeedPhraseKeypairFullyOperable", errCode=response.error.code, errDesription=response.error.message
return response.error.message return response.error.message
self.updateKeypairOperabilityInLocalStoreAndNotify(keyUid) self.updateKeypairOperabilityInLocalStoreAndNotify(@[keyUid])
return "" return ""
except Exception as e: except Exception as e:
error "error: ", procName="makeSeedPhraseKeypairFullyOperable", errName=e.name, errDesription=e.msg error "error: ", procName="makeSeedPhraseKeypairFullyOperable", errName=e.name, errDesription=e.msg

View File

@ -19,7 +19,7 @@ const SIGNAL_WALLET_ACCOUNT_PREFERRED_SHARING_CHAINS_UPDATED* = "walletAccount/p
const SIGNAL_KEYPAIR_SYNCED* = "keypairSynced" const SIGNAL_KEYPAIR_SYNCED* = "keypairSynced"
const SIGNAL_KEYPAIR_NAME_CHANGED* = "keypairNameChanged" const SIGNAL_KEYPAIR_NAME_CHANGED* = "keypairNameChanged"
const SIGNAL_KEYPAIR_DELETED* = "keypairDeleted" const SIGNAL_KEYPAIR_DELETED* = "keypairDeleted"
const SIGNAL_KEYPAIR_OPERABILITY_CHANGED* = "keypairOperabilityChanged" const SIGNAL_IMPORTED_KEYPAIRS* = "importedKeypairs"
const SIGNAL_NEW_KEYCARD_SET* = "newKeycardSet" const SIGNAL_NEW_KEYCARD_SET* = "newKeycardSet"
const SIGNAL_KEYCARD_REBUILD* = "keycardRebuild" const SIGNAL_KEYCARD_REBUILD* = "keycardRebuild"
@ -43,6 +43,10 @@ type KeypairArgs* = ref object of Args
keyPairName*: string keyPairName*: string
oldKeypairName*: string oldKeypairName*: string
type KeypairsArgs* = ref object of Args
keypairs*: seq[KeypairDto]
error*: string
type KeycardArgs* = ref object of Args type KeycardArgs* = ref object of Args
success*: bool success*: bool
oldKeycardUid*: string oldKeycardUid*: string

@ -1 +1 @@
Subproject commit 0a0b5f0f320a7ed3adf53218e5b18fc41d0fbef0 Subproject commit f75bbc383157285d8260365e3b95def7b259e340