feat(@desktop/keycard): sign transaction using `Authenticate` flow
Actually this is not a signing transaction, but rather authenticating logged in user when he wants to send a transaction. An authentication is done by entering password(regular user) or pin(keycard user). A real signing transaction feature will be (hopefully) added in a near future where we're going to sign a transaction on a keycard which corresponds to a certain account, a user wants to send a transaction from. To sum up... this change just removes password from the send modal and introduces `Authenticate` flow instead. Fixes: #7510
This commit is contained in:
parent
b34b9fb347
commit
a1027ff087
|
@ -3,10 +3,13 @@ import io_interface
|
|||
import ../../../../../app_service/service/transaction/service as transaction_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||
|
||||
import ../../../../core/[main]
|
||||
import ../../../../core/tasks/[qt, threadpool]
|
||||
|
||||
const UNIQUE_WALLET_SECTION_TRANSACTION_MODULE_IDENTIFIER* = "WalletSection-TransactionModule"
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
delegate: io_interface.AccessInterface
|
||||
|
@ -69,6 +72,12 @@ proc init*(self: Controller) =
|
|||
self.events.on(SIGNAL_TRANSACTION_SENT) do(e:Args):
|
||||
self.delegate.transactionWasSent(TransactionSentArgs(e).result)
|
||||
|
||||
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
|
||||
let args = SharedKeycarModuleArgs(e)
|
||||
if args.uniqueIdentifier != UNIQUE_WALLET_SECTION_TRANSACTION_MODULE_IDENTIFIER:
|
||||
return
|
||||
self.delegate.onUserAuthenticated(args.password)
|
||||
|
||||
proc checkPendingTransactions*(self: Controller) =
|
||||
self.transactionService.checkPendingTransactions()
|
||||
|
||||
|
@ -84,6 +93,9 @@ proc getWalletAccount*(self: Controller, accountIndex: int): WalletAccountDto =
|
|||
proc getAccountByAddress*(self: Controller, address: string): WalletAccountDto =
|
||||
self.walletAccountService.getAccountByAddress(address)
|
||||
|
||||
proc getMigratedKeyPairByKeyUid*(self: Controller, keyUid: string): seq[KeyPairDto] =
|
||||
return self.walletAccountService.getMigratedKeyPairByKeyUid(keyUid)
|
||||
|
||||
proc loadTransactions*(self: Controller, address: string, toBlock: Uint256, limit: int = 20, loadMore: bool = false) =
|
||||
self.transactionService.loadTransactions(address, toBlock, limit, loadMore)
|
||||
|
||||
|
@ -95,9 +107,8 @@ proc estimateGas*(self: Controller, from_addr: string, to: string, assetSymbol:
|
|||
|
||||
proc transfer*(self: Controller, from_addr: string, to_addr: string, tokenSymbol: string,
|
||||
value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,maxFeePerGas: string,
|
||||
password: string, chainId: string, uuid: string, eip1559Enabled: bool,
|
||||
): bool =
|
||||
result = self.transactionService.transfer(from_addr, to_addr, tokenSymbol, value, gas,
|
||||
password: string, chainId: string, uuid: string, eip1559Enabled: bool) =
|
||||
discard self.transactionService.transfer(from_addr, to_addr, tokenSymbol, value, gas,
|
||||
gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, chainId, uuid, eip1559Enabled)
|
||||
|
||||
proc suggestedFees*(self: Controller, chainId: int): string =
|
||||
|
@ -119,3 +130,11 @@ proc getEstimatedTime*(self: Controller, chainId: int, maxFeePerGas: string): Es
|
|||
|
||||
proc getLastTxBlockNumber*(self: Controller): string =
|
||||
return self.transactionService.getLastTxBlockNumber(self.networkService.getNetworkForBrowser().chainId)
|
||||
|
||||
|
||||
proc authenticateUser*(self: Controller, keyUid = "", bip44Path = "", txHash = "") =
|
||||
let data = SharedKeycarModuleAuthenticationArgs(uniqueIdentifier: UNIQUE_WALLET_SECTION_TRANSACTION_MODULE_IDENTIFIER,
|
||||
keyUid: keyUid,
|
||||
bip44Path: bip44Path,
|
||||
txHash: txHash)
|
||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
|
@ -43,10 +43,13 @@ method setIsNonArchivalNode*(self: AccessInterface, isNonArchivalNode: bool) {.b
|
|||
method estimateGas*(self: AccessInterface, from_addr: string, to: string, assetSymbol: string, value: string, data: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method transfer*(self: AccessInterface, from_addr: string, to_addr: string,
|
||||
method onUserAuthenticated*(self: AccessInterface, password: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method authenticateAndTransfer*(self: AccessInterface, from_addr: string, to_addr: string,
|
||||
tokenSymbol: string, value: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string,
|
||||
chainId: string, uuid: string, eip1559Enabled: bool): bool {.base.} =
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, chainId: string, uuid: string,
|
||||
eip1559Enabled: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method transactionWasSent*(self: AccessInterface, result: string) {.base.} =
|
||||
|
|
|
@ -10,12 +10,27 @@ import ../../../../../app_service/service/network/service as network_service
|
|||
|
||||
export io_interface
|
||||
|
||||
# Shouldn't be public ever, user only within this module.
|
||||
type TmpSendTransactionDetails = object
|
||||
fromAddr: string
|
||||
toAddr: string
|
||||
tokenSymbol: string
|
||||
value: string
|
||||
gas: string
|
||||
gasPrice: string
|
||||
maxPriorityFeePerGas: string
|
||||
maxFeePerGas: string
|
||||
chainId: string
|
||||
uuid: string
|
||||
eip1559Enabled: bool
|
||||
|
||||
type
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
delegate: delegate_interface.AccessInterface
|
||||
view: View
|
||||
controller: Controller
|
||||
moduleLoaded: bool
|
||||
tmpSendTransactionDetails: TmpSendTransactionDetails
|
||||
|
||||
# Forward declarations
|
||||
method checkRecentHistory*(self: Module)
|
||||
|
@ -90,11 +105,55 @@ method estimateGas*(self: Module, from_addr: string, to: string, assetSymbol: st
|
|||
method setIsNonArchivalNode*(self: Module, isNonArchivalNode: bool) =
|
||||
self.view.setIsNonArchivalNode(isNonArchivalNode)
|
||||
|
||||
method transfer*(self: Module, from_addr: string, to_addr: string, tokenSymbol: string,
|
||||
method authenticateAndTransfer*(self: Module, from_addr: string, to_addr: string, tokenSymbol: string,
|
||||
value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,
|
||||
maxFeePerGas: string, password: string, chainId: string, uuid: string, eip1559Enabled: bool): bool =
|
||||
result = self.controller.transfer(from_addr, to_addr, tokenSymbol, value, gas, gasPrice,
|
||||
maxPriorityFeePerGas, maxFeePerGas, password, chainId, uuid, eip1559Enabled)
|
||||
maxFeePerGas: string, chainId: string, uuid: string, eip1559Enabled: bool) =
|
||||
|
||||
self.tmpSendTransactionDetails.fromAddr = from_addr
|
||||
self.tmpSendTransactionDetails.toAddr = to_addr
|
||||
self.tmpSendTransactionDetails.tokenSymbol = tokenSymbol
|
||||
self.tmpSendTransactionDetails.value = value
|
||||
self.tmpSendTransactionDetails.gas = gas
|
||||
self.tmpSendTransactionDetails.gasPrice = gasPrice
|
||||
self.tmpSendTransactionDetails.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||
self.tmpSendTransactionDetails.maxFeePerGas = maxFeePerGas
|
||||
self.tmpSendTransactionDetails.chainId = chainId
|
||||
self.tmpSendTransactionDetails.uuid = uuid
|
||||
self.tmpSendTransactionDetails.eip1559Enabled = eip1559Enabled
|
||||
|
||||
if singletonInstance.userProfile.getIsKeycardUser():
|
||||
let keyUid = singletonInstance.userProfile.getKeyUid()
|
||||
self.controller.authenticateUser(keyUid)
|
||||
else:
|
||||
self.controller.authenticateUser()
|
||||
|
||||
##################################
|
||||
## Do Not Delete
|
||||
##
|
||||
## Once we start with signing a transactions we shold check if the address we want to send a transaction from is migrated
|
||||
## or not. In case it's not we should just authenticate logged in user, otherwise we should use one of the keycards that
|
||||
## address (key pair) is migrated to and sign the transaction using it.
|
||||
##
|
||||
## The code bellow is an example how we can achieve that in future, when we start with signing transactions.
|
||||
##
|
||||
## let acc = self.controller.getAccountByAddress(from_addr)
|
||||
## if acc.isNil:
|
||||
## echo "error: selected account to send a transaction from is not known"
|
||||
## return
|
||||
## let keyPair = self.controller.getMigratedKeyPairByKeyUid(acc.keyUid)
|
||||
## if keyPair.len == 0:
|
||||
## self.controller.authenticateUser()
|
||||
## else:
|
||||
## self.controller.authenticateUser(acc.keyUid, acc.path)
|
||||
##
|
||||
##################################
|
||||
|
||||
method onUserAuthenticated*(self: Module, password: string) =
|
||||
self.controller.transfer(self.tmpSendTransactionDetails.fromAddr, self.tmpSendTransactionDetails.toAddr,
|
||||
self.tmpSendTransactionDetails.tokenSymbol, self.tmpSendTransactionDetails.value, self.tmpSendTransactionDetails.gas,
|
||||
self.tmpSendTransactionDetails.gasPrice, self.tmpSendTransactionDetails.maxPriorityFeePerGas,
|
||||
self.tmpSendTransactionDetails.maxFeePerGas, password, self.tmpSendTransactionDetails.chainId, self.tmpSendTransactionDetails.uuid,
|
||||
self.tmpSendTransactionDetails.eip1559Enabled)
|
||||
|
||||
method transactionWasSent*(self: Module, result: string) =
|
||||
self.view.transactionWasSent(result)
|
||||
|
|
|
@ -116,11 +116,11 @@ QtObject:
|
|||
proc transactionWasSent*(self: View,txResult: string) {.slot} =
|
||||
self.transactionSent(txResult)
|
||||
|
||||
proc transfer*(self: View, from_addr: string, to_addr: string, tokenSymbol: string,
|
||||
proc authenticateAndTransfer*(self: View, from_addr: string, to_addr: string, tokenSymbol: string,
|
||||
value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,
|
||||
maxFeePerGas: string, password: string, chainId: string, uuid: string, eip1559Enabled: bool): bool {.slot.} =
|
||||
result = self.delegate.transfer(from_addr, to_addr, tokenSymbol, value, gas, gasPrice,
|
||||
maxPriorityFeePerGas, maxFeePerGas, password, chainId, uuid, eip1559Enabled)
|
||||
maxFeePerGas: string, chainId: string, uuid: string, eip1559Enabled: bool) {.slot.} =
|
||||
self.delegate.authenticateAndTransfer(from_addr, to_addr, tokenSymbol, value, gas, gasPrice,
|
||||
maxPriorityFeePerGas, maxFeePerGas, chainId, uuid, eip1559Enabled)
|
||||
|
||||
proc suggestedFees*(self: View, chainId: int): string {.slot.} =
|
||||
return self.delegate.suggestedFees(chainId)
|
||||
|
|
|
@ -563,9 +563,9 @@ QtObject {
|
|||
}
|
||||
|
||||
function transfer(from, to, address, tokenSymbol, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, chainId, uuid, eip1559Enabled) {
|
||||
return walletSectionTransactions.transfer(
|
||||
return walletSectionTransactions.authenticateAndTransfer(
|
||||
from, to, address, tokenSymbol, amount, gasLimit,
|
||||
gasPrice, tipLimit, overallLimit, password, chainId, uuid,
|
||||
gasPrice, tipLimit, overallLimit, chainId, uuid,
|
||||
eip1559Enabled
|
||||
);
|
||||
}
|
||||
|
|
|
@ -137,11 +137,10 @@ QtObject {
|
|||
return profileSectionStore.ensUsernamesStore.getGasEthValue(gweiValue, gasLimit)
|
||||
}
|
||||
|
||||
|
||||
function transfer(from, to, tokenSymbol, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, chainId, uuid, eip1559Enabled) {
|
||||
return walletSectionTransactions.transfer(
|
||||
function authenticateAndTransfer(from, to, tokenSymbol, amount, gasLimit, gasPrice, tipLimit, overallLimit, chainId, uuid, eip1559Enabled) {
|
||||
walletSectionTransactions.authenticateAndTransfer(
|
||||
from, to, tokenSymbol, amount, gasLimit,
|
||||
gasPrice, tipLimit, overallLimit, password, chainId, uuid,
|
||||
gasPrice, tipLimit, overallLimit, chainId, uuid,
|
||||
eip1559Enabled
|
||||
);
|
||||
}
|
||||
|
|
|
@ -38,9 +38,8 @@ StatusDialog {
|
|||
|
||||
function sendTransaction() {
|
||||
let recipientAddress = Utils.isValidAddress(popup.addressText) ? popup.addressText : d.resolvedENSAddress
|
||||
let success = false
|
||||
d.isPending = true
|
||||
success = popup.store.transfer(
|
||||
popup.store.authenticateAndTransfer(
|
||||
popup.selectedAccount.address,
|
||||
recipientAddress,
|
||||
assetSelector.selectedAsset.symbol,
|
||||
|
@ -49,7 +48,6 @@ StatusDialog {
|
|||
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
gasSelector.selectedTipLimit,
|
||||
gasSelector.selectedOverallLimit,
|
||||
transactionSigner.enteredPassword,
|
||||
networkSelector.selectedNetwork.chainId,
|
||||
d.uuid,
|
||||
gasSelector.suggestedFees.eip1559Enabled,
|
||||
|
@ -73,8 +71,7 @@ StatusDialog {
|
|||
})
|
||||
|
||||
enum StackGroup {
|
||||
SendDetailsGroup = 0,
|
||||
AuthenticationGroup = 1
|
||||
SendDetailsGroup = 0
|
||||
}
|
||||
|
||||
QtObject {
|
||||
|
@ -484,19 +481,6 @@ StatusDialog {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column{
|
||||
id: group2
|
||||
Layout.preferredWidth: parent.width
|
||||
TransactionSigner {
|
||||
id: transactionSigner
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.margins: 32
|
||||
signingPhrase: popup.store.signingPhrase
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: SendModalFooter {
|
||||
|
@ -506,10 +490,6 @@ StatusDialog {
|
|||
isLastGroup: d.isLastGroup
|
||||
visible: d.isReady && !isNaN(parseFloat(amountToSendInput.text)) && gasValidator.isValid
|
||||
onNextButtonClicked: {
|
||||
if (isLastGroup) {
|
||||
return popup.sendTransaction()
|
||||
}
|
||||
|
||||
if(gasSelector.suggestedFees.eip1559Enabled && gasSelector.advancedMode){
|
||||
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
|
||||
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
|
||||
|
@ -523,13 +503,18 @@ StatusDialog {
|
|||
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
|
||||
showTipLimitWarning: gasSelector.showTipLimitWarning,
|
||||
onConfirm: function(){
|
||||
stack.currentIndex = SendModal.StackGroup.AuthenticationGroup
|
||||
if (isLastGroup) {
|
||||
return popup.sendTransaction()
|
||||
}
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
stack.currentIndex = SendModal.StackGroup.AuthenticationGroup
|
||||
|
||||
if (isLastGroup) {
|
||||
return popup.sendTransaction()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,10 +532,6 @@ StatusDialog {
|
|||
if (response.uuid !== d.uuid) return
|
||||
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(response.result)){
|
||||
transactionSigner.validationError = qsTr("Wrong password")
|
||||
return
|
||||
}
|
||||
sendingError.text = response.result
|
||||
return sendingError.open()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue