chore: sign the flow only once if approval and transaction need to be placed once after another (swap flow)
Closes #16337
This commit is contained in:
parent
684d0b4d63
commit
fe5c135486
|
@ -44,7 +44,7 @@ method stopUpdatesForSuggestedRoute*(self: AccessInterface) {.base.} =
|
|||
method suggestedRoutesReady*(self: AccessInterface, uuid: string, suggestedRoutes: SuggestedRoutesDto, errCode: string, errDescription: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method authenticateAndTransferV2*(self: AccessInterface, fromAddr: string, uuid: string, slippagePercentage: float) {.base.} =
|
||||
method authenticateAndTransfer*(self: AccessInterface, fromAddr: string, uuid: string, slippagePercentage: float) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onUserAuthenticated*(self: AccessInterface, password: string, pin: string) {.base.} =
|
||||
|
|
|
@ -26,17 +26,13 @@ const authenticationCanceled* = "authenticationCanceled"
|
|||
|
||||
# Shouldn't be public ever, use only within this module.
|
||||
type TmpSendTransactionDetails = object
|
||||
fromAddr: string
|
||||
fromAddrPath: string
|
||||
toAddr: string
|
||||
assetKey: string
|
||||
toAssetKey: string
|
||||
paths: seq[TransactionPathDto]
|
||||
uuid: string
|
||||
sendType: SendType
|
||||
pin: string
|
||||
password: string
|
||||
txHashBeingProcessed: string
|
||||
resolvedSignatures: TransactionsSignatures
|
||||
tokenName: string
|
||||
isOwnerToken: bool
|
||||
slippagePercentage: float
|
||||
|
||||
type
|
||||
|
@ -48,9 +44,7 @@ type
|
|||
controller: controller.Controller
|
||||
moduleLoaded: bool
|
||||
tmpSendTransactionDetails: TmpSendTransactionDetails
|
||||
tmpPin: string
|
||||
tmpPassword: string
|
||||
tmpTxHashBeingProcessed: string
|
||||
tmpKeepPinPass: bool
|
||||
|
||||
# Forward declaration
|
||||
method getTokenBalance*(self: Module, address: string, chainId: int, tokensKey: string): CurrencyAmount
|
||||
|
@ -79,12 +73,15 @@ method delete*(self: Module) =
|
|||
self.view.delete
|
||||
self.controller.delete
|
||||
|
||||
proc clearTmpData(self: Module) =
|
||||
self.tmpPin = ""
|
||||
self.tmpPassword = ""
|
||||
self.tmpTxHashBeingProcessed = ""
|
||||
proc clearTmpData(self: Module, keepPinPass = false) =
|
||||
if keepPinPass:
|
||||
self.tmpSendTransactionDetails = TmpSendTransactionDetails(
|
||||
sendType: self.tmpSendTransactionDetails.sendType,
|
||||
pin: self.tmpSendTransactionDetails.pin,
|
||||
password: self.tmpSendTransactionDetails.password
|
||||
)
|
||||
return
|
||||
self.tmpSendTransactionDetails = TmpSendTransactionDetails()
|
||||
writeStackTrace()
|
||||
|
||||
proc convertSendToNetworkToNetworkItem(self: Module, network: SendToNetwork): NetworkRouteItem =
|
||||
result = initNetworkRouteItem(
|
||||
|
@ -183,11 +180,22 @@ method getNetworkItem*(self: Module, chainId: int): network_service_item.Network
|
|||
return nil
|
||||
return networks[0]
|
||||
|
||||
method authenticateAndTransferV2*(self: Module, fromAddr: string, uuid: string, slippagePercentage: float) =
|
||||
proc buildTransactionsFromRoute(self: Module) =
|
||||
let err = self.controller.buildTransactionsFromRoute(self.tmpSendTransactionDetails.uuid, self.tmpSendTransactionDetails.slippagePercentage)
|
||||
if err.len > 0:
|
||||
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = err)
|
||||
self.clearTmpData()
|
||||
|
||||
method authenticateAndTransfer*(self: Module, fromAddr: string, uuid: string, slippagePercentage: float) =
|
||||
self.tmpSendTransactionDetails.uuid = uuid
|
||||
self.tmpSendTransactionDetails.slippagePercentage = slippagePercentage
|
||||
self.tmpSendTransactionDetails.resolvedSignatures.clear()
|
||||
|
||||
if self.tmpKeepPinPass:
|
||||
# no need to authenticate again, just send a swap tx
|
||||
self.buildTransactionsFromRoute()
|
||||
return
|
||||
|
||||
let kp = self.controller.getKeypairByAccountAddress(fromAddr)
|
||||
if kp.migratedToKeycard():
|
||||
let accounts = kp.accounts.filter(acc => cmpIgnoreCase(acc.address, fromAddr) == 0)
|
||||
|
@ -203,12 +211,9 @@ method onUserAuthenticated*(self: Module, password: string, pin: string) =
|
|||
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = authenticationCanceled)
|
||||
self.clearTmpData()
|
||||
else:
|
||||
self.tmpPin = pin
|
||||
self.tmpPassword = password
|
||||
let err = self.controller.buildTransactionsFromRoute(self.tmpSendTransactionDetails.uuid, self.tmpSendTransactionDetails.slippagePercentage)
|
||||
if err.len > 0:
|
||||
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = err)
|
||||
self.clearTmpData()
|
||||
self.tmpSendTransactionDetails.pin = pin
|
||||
self.tmpSendTransactionDetails.password = password
|
||||
self.buildTransactionsFromRoute()
|
||||
|
||||
proc sendSignedTransactions*(self: Module) =
|
||||
try:
|
||||
|
@ -226,17 +231,17 @@ proc sendSignedTransactions*(self: Module) =
|
|||
self.clearTmpData()
|
||||
|
||||
proc signOnKeycard(self: Module) =
|
||||
self.tmpTxHashBeingProcessed = ""
|
||||
self.tmpSendTransactionDetails.txHashBeingProcessed = ""
|
||||
for h, (r, s, v) in self.tmpSendTransactionDetails.resolvedSignatures.pairs:
|
||||
if r.len != 0 and s.len != 0 and v.len != 0:
|
||||
continue
|
||||
self.tmpTxHashBeingProcessed = h
|
||||
var txForKcFlow = self.tmpTxHashBeingProcessed
|
||||
self.tmpSendTransactionDetails.txHashBeingProcessed = h
|
||||
var txForKcFlow = self.tmpSendTransactionDetails.txHashBeingProcessed
|
||||
if txForKcFlow.startsWith("0x"):
|
||||
txForKcFlow = txForKcFlow[2..^1]
|
||||
self.controller.runSignFlow(self.tmpPin, self.tmpSendTransactionDetails.fromAddrPath, txForKcFlow)
|
||||
self.controller.runSignFlow(self.tmpSendTransactionDetails.pin, self.tmpSendTransactionDetails.fromAddrPath, txForKcFlow)
|
||||
break
|
||||
if self.tmpTxHashBeingProcessed.len == 0:
|
||||
if self.tmpSendTransactionDetails.txHashBeingProcessed.len == 0:
|
||||
self.sendSignedTransactions()
|
||||
self.clearTmpData()
|
||||
|
||||
|
@ -265,7 +270,7 @@ method prepareSignaturesForTransactions*(self:Module, txForSigning: RouterTransa
|
|||
self.tmpSendTransactionDetails.resolvedSignatures[h] = ("", "", "")
|
||||
self.signOnKeycard()
|
||||
else:
|
||||
let finalPassword = hashPassword(self.tmpPassword)
|
||||
let finalPassword = hashPassword(self.tmpSendTransactionDetails.password)
|
||||
for h in txForSigning.signingDetails.hashes:
|
||||
self.tmpSendTransactionDetails.resolvedSignatures[h] = ("", "", "")
|
||||
var
|
||||
|
@ -288,19 +293,18 @@ method onTransactionSigned*(self: Module, keycardFlowType: string, keycardEvent:
|
|||
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = err)
|
||||
self.clearTmpData()
|
||||
return
|
||||
self.tmpSendTransactionDetails.resolvedSignatures[self.tmpTxHashBeingProcessed] = (keycardEvent.txSignature.r,
|
||||
self.tmpSendTransactionDetails.resolvedSignatures[self.tmpSendTransactionDetails.txHashBeingProcessed] = (keycardEvent.txSignature.r,
|
||||
keycardEvent.txSignature.s, keycardEvent.txSignature.v)
|
||||
self.signOnKeycard()
|
||||
|
||||
method transactionWasSent*(self: Module, uuid: string, chainId: int = 0, approvalTx: bool = false, txHash: string = "", error: string = "") =
|
||||
self.tmpKeepPinPass = approvalTx # need to automate the swap flow with approval
|
||||
if txHash.len == 0:
|
||||
self.view.sendTransactionSentSignal(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error)
|
||||
return
|
||||
self.view.sendTransactionSentSignal(uuid, chainId, approvalTx, txHash, error)
|
||||
|
||||
method suggestedRoutesReady*(self: Module, uuid: string, suggestedRoutes: SuggestedRoutesDto, errCode: string, errDescription: string) =
|
||||
self.tmpSendTransactionDetails.paths = suggestedRoutes.best
|
||||
self.tmpSendTransactionDetails.slippagePercentage = 0
|
||||
let paths = suggestedRoutes.best.map(x => self.convertTransactionPathDtoToSuggestedRouteItem(x))
|
||||
let suggestedRouteModel = newSuggestedRouteModel()
|
||||
suggestedRouteModel.setItems(paths)
|
||||
|
@ -332,6 +336,7 @@ method suggestedRoutes*(self: Module,
|
|||
disabledToChainIDs: seq[int] = @[],
|
||||
lockedInAmounts: Table[string, string] = initTable[string, string](),
|
||||
extraParamsTable: Table[string, string] = initTable[string, string]()) =
|
||||
self.tmpSendTransactionDetails.sendType = sendType
|
||||
self.controller.suggestedRoutes(
|
||||
uuid,
|
||||
sendType,
|
||||
|
@ -403,4 +408,5 @@ method splitAndFormatAddressPrefix*(self: Module, text : string, updateInStore:
|
|||
return editedText
|
||||
|
||||
method transactionSendingComplete*(self: Module, txHash: string, status: string) =
|
||||
self.clearTmpData(self.tmpKeepPinPass)
|
||||
self.view.sendtransactionSendingCompleteSignal(txHash, status)
|
||||
|
|
|
@ -180,7 +180,7 @@ QtObject:
|
|||
slippagePercentage = slippagePercentageString.parseFloat()
|
||||
except:
|
||||
error "parsing slippage failed", slippage=slippagePercentageString
|
||||
self.delegate.authenticateAndTransferV2(self.selectedSenderAccountAddress, uuid, slippagePercentage)
|
||||
self.delegate.authenticateAndTransfer(self.selectedSenderAccountAddress, uuid, slippagePercentage)
|
||||
|
||||
proc suggestedRoutesReady*(self: View, suggestedRoutes: QVariant, errCode: string, errDescription: string) {.signal.}
|
||||
proc setTransactionRoute*(self: View, routes: TransactionRoutes, errCode: string, errDescription: string) =
|
||||
|
|
|
@ -129,7 +129,6 @@ QtObject:
|
|||
break
|
||||
|
||||
if ensDto.username.len == 0:
|
||||
error "Error updating ens username status", message = "no ens username found for transactionHash: " & transactionHash
|
||||
return
|
||||
|
||||
let key = makeKey(ensDto.username, chainId)
|
||||
|
|
|
@ -363,6 +363,8 @@ Item {
|
|||
verify(!!headerContentItemEmoji)
|
||||
compare(headerContentItemEmoji.asset.emoji, swapAdaptor.nonWatchAccounts.get(i).emoji)
|
||||
|
||||
waitForRendering(amountToSendInput)
|
||||
|
||||
verify(amountToSendInput.cursorVisible)
|
||||
}
|
||||
closeAndVerfyModal()
|
||||
|
@ -1399,6 +1401,7 @@ Item {
|
|||
launchAndVerfyModal()
|
||||
waitForRendering(payPanel)
|
||||
waitForRendering(receivePanel)
|
||||
waitForRendering(payAmountToSendInput)
|
||||
|
||||
let paytokenSelectorContentItemText = findChild(payPanel, "tokenSelectorContentItemText")
|
||||
verify(!!paytokenSelectorContentItemText)
|
||||
|
|
|
@ -99,8 +99,7 @@ Item {
|
|||
controlUnderTest.toTokenAmount = "1.42"
|
||||
controlUnderTest.toTokenContractAddress = "0xdeadcaff"
|
||||
|
||||
// title & subtitle
|
||||
compare(controlUnderTest.title, qsTr("Sign Swap"))
|
||||
// subtitle
|
||||
compare(controlUnderTest.subtitle, qsTr("%1 to %2").arg(controlUnderTest.formatBigNumber(controlUnderTest.fromTokenAmount, controlUnderTest.fromTokenSymbol))
|
||||
.arg(controlUnderTest.formatBigNumber(controlUnderTest.toTokenAmount, controlUnderTest.toTokenSymbol)))
|
||||
|
||||
|
|
|
@ -36,8 +36,12 @@ StatusDialog {
|
|||
property Component headerIconComponent
|
||||
|
||||
property bool feesLoading
|
||||
|
||||
property string signButtonText: qsTr("Sign")
|
||||
property bool signButtonEnabled: true
|
||||
|
||||
property string closeButtonText: qsTr("Close")
|
||||
|
||||
property date requestTimestamp: new Date()
|
||||
property int expirationSeconds
|
||||
property bool hasExpiryDate: false
|
||||
|
@ -61,14 +65,14 @@ StatusDialog {
|
|||
visible: !root.hasExpiryDate || !countdownPill.isExpired
|
||||
icon.name: Constants.authenticationIconByType[root.loginType]
|
||||
disabledColor: Theme.palette.directColor8
|
||||
text: qsTr("Sign")
|
||||
text: root.signButtonText
|
||||
onClicked: root.accept() // close and emit accepted() signal
|
||||
}
|
||||
StatusButton {
|
||||
objectName: "closeButton"
|
||||
id: closeButton
|
||||
visible: root.hasExpiryDate && countdownPill.isExpired
|
||||
text: qsTr("Close")
|
||||
text: root.closeButtonText
|
||||
onClicked: root.close()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -397,10 +397,12 @@ StatusDialog {
|
|||
: Constants.authenticationIconByType[root.loginType]
|
||||
text: {
|
||||
if(root.swapAdaptor.validSwapProposalReceived) {
|
||||
if (root.swapAdaptor.approvalPending) {
|
||||
return qsTr("Approving %1").arg(fromTokenSymbol)
|
||||
} else if(root.swapAdaptor.swapOutputData.approvalNeeded) {
|
||||
return qsTr("Approve %1").arg(fromTokenSymbol)
|
||||
if(root.swapAdaptor.swapOutputData.approvalNeeded) {
|
||||
if (root.swapAdaptor.approvalPending) {
|
||||
return qsTr("Approving %1").arg(fromTokenSymbol)
|
||||
} else if(!root.swapAdaptor.approvalSuccessful) {
|
||||
return qsTr("Approve %1").arg(fromTokenSymbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
return qsTr("Swap")
|
||||
|
@ -416,7 +418,7 @@ StatusDialog {
|
|||
onClicked: {
|
||||
if (root.swapAdaptor.validSwapProposalReceived) {
|
||||
d.addMetricsEvent("next button pressed")
|
||||
if (root.swapAdaptor.swapOutputData.approvalNeeded)
|
||||
if (root.swapAdaptor.swapOutputData.approvalNeeded && !root.swapAdaptor.approvalSuccessful)
|
||||
Global.openPopup(swapApproveModalComponent)
|
||||
else
|
||||
Global.openPopup(swapSignModalComponent)
|
||||
|
@ -483,6 +485,9 @@ StatusDialog {
|
|||
SwapSignModal {
|
||||
destroyOnClose: true
|
||||
|
||||
title: root.swapAdaptor.swapOutputData.approvalNeeded && root.swapAdaptor.approvalSuccessful? qsTr("Swap") : qsTr("Sign Swap")
|
||||
signButtonText: root.swapAdaptor.swapOutputData.approvalNeeded && root.swapAdaptor.approvalSuccessful? qsTr("Swap") : qsTr("Sign")
|
||||
|
||||
formatBigNumber: (number, symbol, noSymbolOption) => root.swapAdaptor.currencyStore.formatBigNumber(number, symbol, noSymbolOption)
|
||||
|
||||
loginType: root.swapAdaptor.selectedAccount.migratedToKeycard ? Constants.LoginType.Keycard : root.loginType
|
||||
|
|
|
@ -87,8 +87,6 @@ QObject {
|
|||
readonly property bool isEthBalanceInsufficient: d.isEthBalanceInsufficient
|
||||
readonly property bool isTokenBalanceInsufficient: d.isTokenBalanceInsufficient
|
||||
|
||||
signal suggestedRoutesReady()
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
|
@ -252,11 +250,10 @@ QObject {
|
|||
root.swapOutputData.hasError = true
|
||||
}
|
||||
root.swapOutputData.hasError = root.swapOutputData.hasError || root.swapOutputData.errCode !== ""
|
||||
root.suggestedRoutesReady()
|
||||
}
|
||||
|
||||
function onTransactionSent(uuid, chainId, approvalTx, txHash, error) {
|
||||
if(root.swapOutputData.approvalNeeded) {
|
||||
if(root.swapOutputData.approvalNeeded && !root.approvalSuccessful) {
|
||||
if (uuid !== d.uuid || !!error) {
|
||||
root.approvalPending = false
|
||||
root.approvalSuccessful = false
|
||||
|
@ -272,10 +269,6 @@ QObject {
|
|||
root.approvalPending = false
|
||||
root.approvalSuccessful = status == "Success" // TODO: make a all tx statuses Constants (success, pending, failed)
|
||||
d.txHash = ""
|
||||
|
||||
if (root.approvalSuccessful) {
|
||||
root.swapOutputData.approvalNeeded = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -335,14 +328,10 @@ QObject {
|
|||
|
||||
function sendApproveTx() {
|
||||
root.approvalPending = true
|
||||
const accountAddress = root.swapFormData.selectedAccountAddress
|
||||
|
||||
root.swapStore.authenticateAndTransfer(d.uuid, "")
|
||||
}
|
||||
|
||||
function sendSwapTx() {
|
||||
const accountAddress = root.swapFormData.selectedAccountAddress
|
||||
|
||||
root.swapStore.authenticateAndTransfer(d.uuid, root.swapFormData.selectedSlippage)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@ SignTransactionModalBase {
|
|||
required property string serviceProviderURL
|
||||
required property string serviceProviderTandCUrl
|
||||
|
||||
title: qsTr("Sign Swap")
|
||||
//: e.g. (swap) 100 DAI to 100 USDT
|
||||
subtitle: qsTr("%1 to %2").arg(formatBigNumber(fromTokenAmount, fromTokenSymbol)).arg(formatBigNumber(toTokenAmount, toTokenSymbol))
|
||||
|
||||
|
|
Loading…
Reference in New Issue