chore: improvements of the sending route generated by the router process
Closes #14636
This commit is contained in:
parent
8bc6db5405
commit
ad7e2df78a
|
@ -6,6 +6,10 @@ type SignalType* {.pure.} = enum
|
|||
## Wallet Signals
|
||||
Wallet = "wallet"
|
||||
WalletSignTransactions = "wallet.sign.transactions"
|
||||
WalletRouterSendingTransactionsStarted = "wallet.router.sending-transactions-started"
|
||||
WalletRouterSignTransactions = "wallet.router.sign-transactions"
|
||||
WalletRouterTransactionsSent = "wallet.router.transactions-sent"
|
||||
WalletTransactionStatusChanged = "wallet.transaction.status-changed"
|
||||
WalletSuggestedRoutes = "wallet.suggested.routes"
|
||||
NodeReady = "node.ready"
|
||||
NodeCrashed = "node.crashed"
|
||||
|
|
|
@ -4,6 +4,7 @@ import base
|
|||
import signal_type
|
||||
|
||||
import app_service/service/transaction/dtoV2
|
||||
import app_service/service/transaction/router_transactions_dto
|
||||
|
||||
const SignTransactionsEventType* = "sing-transactions"
|
||||
|
||||
|
@ -25,6 +26,10 @@ type WalletSignal* = ref object of Signal
|
|||
error*: string
|
||||
errorCode*: string
|
||||
updatedPrices*: Table[string, float64]
|
||||
routerTransactionsSendingDetails*: SendDetailsDto
|
||||
routerTransactionsForSigning*: RouterTransactionsForSigningDto
|
||||
routerSentTransactions*: RouterSentTransactionsDto
|
||||
transactionStatusChange*: TransactionStatusChange
|
||||
|
||||
proc fromEvent*(T: type WalletSignal, signalType: SignalType, jsonSignal: JsonNode): WalletSignal =
|
||||
result = WalletSignal()
|
||||
|
@ -54,6 +59,24 @@ proc fromEvent*(T: type WalletSignal, signalType: SignalType, jsonSignal: JsonNo
|
|||
for tx in event:
|
||||
result.txHashes.add(tx.getStr)
|
||||
return
|
||||
if signalType == SignalType.WalletRouterSignTransactions:
|
||||
if event.kind != JObject:
|
||||
return
|
||||
result.routerTransactionsForSigning = toRouterTransactionsForSigningDto(event)
|
||||
return
|
||||
if signalType == SignalType.WalletRouterTransactionsSent:
|
||||
if event.kind != JObject:
|
||||
return
|
||||
result.routerSentTransactions = toRouterSentTransactionsDto(event)
|
||||
return
|
||||
if signalType == SignalType.WalletRouterSendingTransactionsStarted:
|
||||
result.routerTransactionsSendingDetails = toSendDetailsDto(event)
|
||||
return
|
||||
if signalType == SignalType.WalletTransactionStatusChanged:
|
||||
if event.kind != JObject:
|
||||
return
|
||||
result.transactionStatusChange = toTransactionStatusChange(event)
|
||||
return
|
||||
if signalType == SignalType.WalletSuggestedRoutes:
|
||||
try:
|
||||
if event.contains("Uuid"):
|
||||
|
|
|
@ -81,8 +81,12 @@ QtObject:
|
|||
of SignalType.WhisperFilterAdded: WhisperFilterSignal.fromEvent(jsonSignal)
|
||||
of SignalType.Wallet,
|
||||
SignalType.WalletSignTransactions,
|
||||
SignalType.WalletRouterSendingTransactionsStarted,
|
||||
SignalType.WalletRouterSignTransactions,
|
||||
SignalType.WalletRouterTransactionsSent,
|
||||
SignalType.WalletTransactionStatusChanged,
|
||||
SignalType.WalletSuggestedRoutes:
|
||||
WalletSignal.fromEvent(signalType, jsonSignal)
|
||||
WalletSignal.fromEvent(signalType, jsonSignal)
|
||||
of SignalType.NodeReady,
|
||||
SignalType.NodeCrashed,
|
||||
SignalType.NodeStarted,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Tables
|
||||
import uuids, chronicles, options
|
||||
import uuids, chronicles
|
||||
import io_interface
|
||||
import app_service/service/wallet_account/service as wallet_account_service
|
||||
import app_service/service/network/service as network_service
|
||||
|
@ -13,7 +13,6 @@ import app/modules/shared_modules/keycard_popup/io_interface as keycard_shared_m
|
|||
import app/modules/shared/wallet_utils
|
||||
import app/modules/shared_models/currency_amount
|
||||
|
||||
import app/core/signals/types
|
||||
import app/core/eventemitter
|
||||
|
||||
logScope:
|
||||
|
@ -56,11 +55,11 @@ proc delete*(self: Controller) =
|
|||
proc init*(self: Controller) =
|
||||
self.events.on(SIGNAL_TRANSACTION_SENT) do(e:Args):
|
||||
let args = TransactionSentArgs(e)
|
||||
self.delegate.transactionWasSent(args.chainId, args.txHash, args.uuid, args.error)
|
||||
self.delegate.transactionWasSent(args.uuid, args.chainId, args.approvalTx, args.txHash, args.error)
|
||||
|
||||
self.events.on(SIGNAL_OWNER_TOKEN_SENT) do(e:Args):
|
||||
let args = OwnerTokenSentArgs(e)
|
||||
self.delegate.transactionWasSent(args.chainId, args.txHash, args.uuid, "")
|
||||
self.delegate.transactionWasSent(args.uuid, args.chainId, approvalTx = false, args.txHash, error = "")
|
||||
|
||||
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
|
||||
let args = SharedKeycarModuleArgs(e)
|
||||
|
@ -72,13 +71,13 @@ proc init*(self: Controller) =
|
|||
let args = SuggestedRoutesArgs(e)
|
||||
self.delegate.suggestedRoutesReady(args.uuid, args.suggestedRoutes, args.errCode, args.errDescription)
|
||||
|
||||
self.events.on(SignalType.WalletSignTransactions.event) do(e:Args):
|
||||
var data = WalletSignal(e)
|
||||
self.delegate.prepareSignaturesForTransactions(data.txHashes)
|
||||
self.events.on(SIGNAL_SIGN_ROUTER_TRANSACTIONS) do(e:Args):
|
||||
var data = RouterTransactionsForSigningArgs(e)
|
||||
self.delegate.prepareSignaturesForTransactions(data.data)
|
||||
|
||||
self.events.on(SIGNAL_TRANSACTION_SENDING_COMPLETE) do(e:Args):
|
||||
let args = TransactionMinedArgs(e)
|
||||
self.delegate.transactionSendingComplete(args.transactionHash, args.success)
|
||||
self.events.on(SIGNAL_TRANSACTION_STATUS_CHANGED) do(e:Args):
|
||||
let args = TransactionStatusArgs(e)
|
||||
self.delegate.transactionSendingComplete(args.data.hash, args.data.status)
|
||||
|
||||
proc getWalletAccounts*(self: Controller): seq[wallet_account_service.WalletAccountDto] =
|
||||
return self.walletAccountService.getWalletAccounts()
|
||||
|
@ -115,6 +114,7 @@ proc suggestedRoutes*(self: Controller,
|
|||
accountFrom: string,
|
||||
accountTo: string,
|
||||
token: string,
|
||||
tokenIsOwnerToken: bool,
|
||||
amountIn: string,
|
||||
toToken: string = "",
|
||||
amountOut: string = "",
|
||||
|
@ -122,23 +122,20 @@ proc suggestedRoutes*(self: Controller,
|
|||
disabledToChainIDs: seq[int] = @[],
|
||||
lockedInAmounts: Table[string, string] = initTable[string, string](),
|
||||
extraParamsTable: Table[string, string] = initTable[string, string]()) =
|
||||
self.transactionService.suggestedRoutes(uuid, sendType, accountFrom, accountTo, token, amountIn, toToken, amountOut,
|
||||
self.transactionService.suggestedRoutes(uuid, sendType, accountFrom, accountTo, token, tokenIsOwnerToken, amountIn, toToken, amountOut,
|
||||
disabledFromChainIDs, disabledToChainIDs, lockedInAmounts, extraParamsTable)
|
||||
|
||||
proc stopSuggestedRoutesAsyncCalculation*(self: Controller) =
|
||||
self.transactionService.stopSuggestedRoutesAsyncCalculation()
|
||||
|
||||
proc transfer*(self: Controller, from_addr: string, to_addr: string, assetKey: string, toAssetKey: string,
|
||||
uuid: string, selectedRoutes: seq[TransactionPathDto], password: string, sendType: SendType,
|
||||
usePassword: bool, doHashing: bool, tokenName: string, isOwnerToken: bool,
|
||||
slippagePercentage: Option[float]) =
|
||||
self.transactionService.transfer(from_addr, to_addr, assetKey, toAssetKey, uuid, selectedRoutes, password, sendType,
|
||||
usePassword, doHashing, tokenName, isOwnerToken, slippagePercentage)
|
||||
proc buildTransactionsFromRoute*(self: Controller, uuid: string, slippagePercentage: float): string =
|
||||
return self.transactionService.buildTransactionsFromRoute(uuid, slippagePercentage)
|
||||
|
||||
proc proceedWithTransactionsSignatures*(self: Controller, fromAddr: string, toAddr: string,
|
||||
fromTokenKey: string, toTokenKey: string, uuid: string, signatures: TransactionsSignatures,
|
||||
selectedRoutes: seq[TransactionPathDto], sendType: SendType) =
|
||||
self.transactionService.proceedWithTransactionsSignatures(fromAddr, toAddr, fromTokenKey, toTokenKey, uuid, signatures, selectedRoutes, sendType)
|
||||
proc signMessage*(self: Controller, address: string, hashedPassword: string, hashedMessage: string): tuple[res: string, err: string] =
|
||||
return self.transactionService.signMessage(address, hashedPassword, hashedMessage)
|
||||
|
||||
proc sendRouterTransactionsWithSignatures*(self: Controller, uuid: string, signatures: TransactionsSignatures): string =
|
||||
return self.transactionService.sendRouterTransactionsWithSignatures(uuid, signatures)
|
||||
|
||||
proc areTestNetworksEnabled*(self: Controller): bool =
|
||||
return self.walletAccountService.areTestNetworksEnabled()
|
||||
|
@ -159,7 +156,7 @@ proc connectKeycardReponseSignal(self: Controller) =
|
|||
let currentFlow = self.keycardService.getCurrentFlow()
|
||||
if currentFlow != KCSFlowType.Sign:
|
||||
error "trying to use keycard in the other than the signing a transaction flow"
|
||||
self.delegate.transactionWasSent()
|
||||
self.delegate.transactionWasSent(uuid = "", chainId = 0, approvalTx = false, txHash = "", error = "trying to use keycard in the other than the signing a transaction flow")
|
||||
return
|
||||
self.delegate.onTransactionSigned(args.flowType, args.flowEvent)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Tables, options
|
||||
import Tables
|
||||
import app/modules/shared_models/currency_amount
|
||||
import app_service/service/transaction/dto
|
||||
import app_service/service/transaction/router_transactions_dto
|
||||
import app_service/service/network/network_item
|
||||
import app/modules/shared_models/collectibles_model as collectibles
|
||||
from app_service/service/keycard/service import KeycardEvent
|
||||
|
@ -27,6 +28,7 @@ method suggestedRoutes*(self: AccessInterface,
|
|||
accountFrom: string,
|
||||
accountTo: string,
|
||||
token: string,
|
||||
tokenIsOwnerToken: bool,
|
||||
amountIn: string,
|
||||
toToken: string = "",
|
||||
amountOut: string = "",
|
||||
|
@ -42,19 +44,13 @@ 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 authenticateAndTransfer*(self: AccessInterface, from_addr: string, to_addr: string, assetKey: string,
|
||||
toAssetKey: string, uuid: string, sendType: SendType, selectedTokenName: string, selectedTokenIsOwnerToken: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method authenticateAndTransferWithPaths*(self: AccessInterface, from_addr: string, to_addr: string, assetKey: string,
|
||||
toAssetKey: string, uuid: string, sendType: SendType, selectedTokenName: string, selectedTokenIsOwnerToken: bool, rawPaths: string,
|
||||
slippagePercentage: Option[float]) {.base.} =
|
||||
method authenticateAndTransferV2*(self: AccessInterface, fromAddr: string, uuid: string, slippagePercentage: float) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onUserAuthenticated*(self: AccessInterface, password: string, pin: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method transactionWasSent*(self: AccessInterface, chainId: int = 0, txHash, uuid, error: string = "") {.base.} =
|
||||
method transactionWasSent*(self: AccessInterface, uuid: string, chainId: int = 0, approvalTx: bool = false, txHash: string = "", error: string = "") {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||
|
@ -78,7 +74,7 @@ method getCollectiblesModel*(self: AccessInterface): collectibles.Model {.base.}
|
|||
method splitAndFormatAddressPrefix*(self: AccessInterface, text : string, updateInStore: bool): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method prepareSignaturesForTransactions*(self: AccessInterface, txHashes: seq[string]) {.base.} =
|
||||
method prepareSignaturesForTransactions*(self:AccessInterface, txForSigning: RouterTransactionsForSigningDto) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onTransactionSigned*(self: AccessInterface, keycardFlowType: string, keycardEvent: KeycardEvent) {.base.} =
|
||||
|
@ -87,7 +83,7 @@ method onTransactionSigned*(self: AccessInterface, keycardFlowType: string, keyc
|
|||
method hasGas*(self: AccessInterface, accountAddress: string, chainId: int, nativeGasSymbol: string, requiredGas: float): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method transactionSendingComplete*(self: AccessInterface, txHash: string, success: bool) {.base.} =
|
||||
method transactionSendingComplete*(self: AccessInterface, txHash: string, status: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getNetworkItem*(self: AccessInterface, chainId: int): NetworkItem {.base.} =
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import tables, NimQml, sequtils, sugar, stint, strutils, chronicles, options
|
||||
import tables, NimQml, sequtils, sugar, stint, strutils, chronicles
|
||||
|
||||
import ./io_interface, ./view, ./controller, ./network_route_item, ./transaction_routes, ./suggested_route_item, ./suggested_route_model, ./gas_estimate_item, ./gas_fees_item, ./network_route_model
|
||||
import ../io_interface as delegate_interface
|
||||
import app/global/global_singleton
|
||||
import app/global/utils
|
||||
import app/core/eventemitter
|
||||
import app_service/common/utils
|
||||
import app_service/common/wallet_constants
|
||||
import app_service/service/wallet_account/service as wallet_account_service
|
||||
import app_service/service/network/service as network_service
|
||||
import app_service/service/currency/service as currency_service
|
||||
|
@ -11,8 +14,6 @@ import app_service/service/transaction/service as transaction_service
|
|||
import app_service/service/keycard/service as keycard_service
|
||||
import app_service/service/keycard/constants as keycard_constants
|
||||
import app_service/service/transaction/dto
|
||||
import app_service/service/transaction/dtoV2
|
||||
import app_service/service/transaction/dto_conversion
|
||||
import app/modules/shared_models/currency_amount
|
||||
import app_service/service/network/network_item as network_service_item
|
||||
|
||||
|
@ -36,7 +37,7 @@ type TmpSendTransactionDetails = object
|
|||
resolvedSignatures: TransactionsSignatures
|
||||
tokenName: string
|
||||
isOwnerToken: bool
|
||||
slippagePercentage: Option[float]
|
||||
slippagePercentage: float
|
||||
|
||||
type
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
|
@ -48,6 +49,7 @@ type
|
|||
moduleLoaded: bool
|
||||
tmpSendTransactionDetails: TmpSendTransactionDetails
|
||||
tmpPin: string
|
||||
tmpPassword: string
|
||||
tmpTxHashBeingProcessed: string
|
||||
|
||||
# Forward declaration
|
||||
|
@ -77,6 +79,13 @@ method delete*(self: Module) =
|
|||
self.view.delete
|
||||
self.controller.delete
|
||||
|
||||
proc clearTmpData(self: Module) =
|
||||
self.tmpPin = ""
|
||||
self.tmpPassword = ""
|
||||
self.tmpTxHashBeingProcessed = ""
|
||||
self.tmpSendTransactionDetails = TmpSendTransactionDetails()
|
||||
writeStackTrace()
|
||||
|
||||
proc convertSendToNetworkToNetworkItem(self: Module, network: SendToNetwork): NetworkRouteItem =
|
||||
result = initNetworkRouteItem(
|
||||
network.chainId,
|
||||
|
@ -174,18 +183,10 @@ method getNetworkItem*(self: Module, chainId: int): network_service_item.Network
|
|||
return nil
|
||||
return networks[0]
|
||||
|
||||
method authenticateAndTransfer*(self: Module, fromAddr: string, toAddr: string, assetKey: string, toAssetKey: string, uuid: string,
|
||||
sendType: SendType, selectedTokenName: string, selectedTokenIsOwnerToken: bool) =
|
||||
self.tmpSendTransactionDetails.fromAddr = fromAddr
|
||||
self.tmpSendTransactionDetails.toAddr = toAddr
|
||||
self.tmpSendTransactionDetails.assetKey = assetKey
|
||||
self.tmpSendTransactionDetails.toAssetKey = toAssetKey
|
||||
method authenticateAndTransferV2*(self: Module, fromAddr: string, uuid: string, slippagePercentage: float) =
|
||||
self.tmpSendTransactionDetails.uuid = uuid
|
||||
self.tmpSendTransactionDetails.sendType = sendType
|
||||
self.tmpSendTransactionDetails.fromAddrPath = ""
|
||||
self.tmpSendTransactionDetails.slippagePercentage = slippagePercentage
|
||||
self.tmpSendTransactionDetails.resolvedSignatures.clear()
|
||||
self.tmpSendTransactionDetails.tokenName = selectedTokenName
|
||||
self.tmpSendTransactionDetails.isOwnerToken = selectedTokenIsOwnerToken
|
||||
|
||||
let kp = self.controller.getKeypairByAccountAddress(fromAddr)
|
||||
if kp.migratedToKeycard():
|
||||
|
@ -193,34 +194,36 @@ method authenticateAndTransfer*(self: Module, fromAddr: string, toAddr: string,
|
|||
if accounts.len != 1:
|
||||
error "cannot resolve selected account to send from among known keypair accounts"
|
||||
return
|
||||
self.tmpSendTransactionDetails.fromAddrPath = accounts[0].path
|
||||
self.controller.authenticate(kp.keyUid)
|
||||
else:
|
||||
self.controller.authenticate()
|
||||
|
||||
method authenticateAndTransferWithPaths*(self: Module, fromAddr: string, toAddr: string, assetKey: string, toAssetKey: string, uuid: string,
|
||||
sendType: SendType, selectedTokenName: string, selectedTokenIsOwnerToken: bool, rawPaths: string, slippagePercentage: Option[float]) =
|
||||
# Temporary until transaction service rework is completed
|
||||
let pathsV2 = rawPaths.toTransactionPathsDtoV2()
|
||||
let pathsV1 = pathsV2.convertToOldRoute().addFirstSimpleBridgeTxFlag()
|
||||
|
||||
self.tmpSendTransactionDetails.paths = pathsV1
|
||||
self.tmpSendTransactionDetails.slippagePercentage = slippagePercentage
|
||||
self.authenticateAndTransfer(fromAddr, toAddr, assetKey, toAssetKey, uuid, sendType, selectedTokenName, selectedTokenIsOwnerToken)
|
||||
|
||||
method onUserAuthenticated*(self: Module, password: string, pin: string) =
|
||||
if password.len == 0:
|
||||
self.transactionWasSent(chainId = 0, txHash = "", uuid = self.tmpSendTransactionDetails.uuid, error = authenticationCanceled)
|
||||
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = authenticationCanceled)
|
||||
self.clearTmpData()
|
||||
else:
|
||||
self.tmpPin = pin
|
||||
let doHashing = self.tmpPin.len == 0
|
||||
let usePassword = self.tmpSendTransactionDetails.fromAddrPath.len == 0
|
||||
self.controller.transfer(
|
||||
self.tmpSendTransactionDetails.fromAddr, self.tmpSendTransactionDetails.toAddr,
|
||||
self.tmpSendTransactionDetails.assetKey, self.tmpSendTransactionDetails.toAssetKey, self.tmpSendTransactionDetails.uuid,
|
||||
self.tmpSendTransactionDetails.paths, password, self.tmpSendTransactionDetails.sendType, usePassword, doHashing,
|
||||
self.tmpSendTransactionDetails.tokenName, self.tmpSendTransactionDetails.isOwnerToken, self.tmpSendTransactionDetails.slippagePercentage
|
||||
)
|
||||
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()
|
||||
|
||||
proc sendSignedTransactions*(self: Module) =
|
||||
try:
|
||||
# check if all transactions are signed
|
||||
for _, (r, s, v) in self.tmpSendTransactionDetails.resolvedSignatures.pairs:
|
||||
if r.len == 0 or s.len == 0 or v.len == 0:
|
||||
raise newException(CatchableError, "not all transactions are signed")
|
||||
|
||||
let err = self.controller.sendRouterTransactionsWithSignatures(self.tmpSendTransactionDetails.uuid, self.tmpSendTransactionDetails.resolvedSignatures)
|
||||
if err.len > 0:
|
||||
raise newException(CatchableError, "sending transaction failed: " & err)
|
||||
except Exception as e:
|
||||
error "sendSignedTransactions failed: ", msg=e.msg
|
||||
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = e.msg)
|
||||
self.clearTmpData()
|
||||
|
||||
proc signOnKeycard(self: Module) =
|
||||
self.tmpTxHashBeingProcessed = ""
|
||||
|
@ -234,35 +237,70 @@ proc signOnKeycard(self: Module) =
|
|||
self.controller.runSignFlow(self.tmpPin, self.tmpSendTransactionDetails.fromAddrPath, txForKcFlow)
|
||||
break
|
||||
if self.tmpTxHashBeingProcessed.len == 0:
|
||||
self.controller.proceedWithTransactionsSignatures(self.tmpSendTransactionDetails.fromAddr, self.tmpSendTransactionDetails.toAddr,
|
||||
self.tmpSendTransactionDetails.assetKey, self.tmpSendTransactionDetails.toAssetKey, self.tmpSendTransactionDetails.uuid,
|
||||
self.tmpSendTransactionDetails.resolvedSignatures, self.tmpSendTransactionDetails.paths, self.tmpSendTransactionDetails.sendType)
|
||||
self.sendSignedTransactions()
|
||||
self.clearTmpData()
|
||||
|
||||
method prepareSignaturesForTransactions*(self: Module, txHashes: seq[string]) =
|
||||
if txHashes.len == 0:
|
||||
error "no transaction hashes to be signed"
|
||||
return
|
||||
for h in txHashes:
|
||||
self.tmpSendTransactionDetails.resolvedSignatures[h] = ("", "", "")
|
||||
self.signOnKeycard()
|
||||
proc getRSVFromSignature(self: Module, signature: string): (string, string, string) =
|
||||
let finalSignature = singletonInstance.utils.removeHexPrefix(signature)
|
||||
if finalSignature.len != SIGNATURE_LEN:
|
||||
return ("", "", "")
|
||||
let r = finalSignature[0..63]
|
||||
let s = finalSignature[64..127]
|
||||
let v = finalSignature[128..129]
|
||||
return (r, s, v)
|
||||
|
||||
method prepareSignaturesForTransactions*(self:Module, txForSigning: RouterTransactionsForSigningDto) =
|
||||
var res = ""
|
||||
try:
|
||||
if txForSigning.sendDetails.uuid != self.tmpSendTransactionDetails.uuid:
|
||||
raise newException(CatchableError, "preparing signatures for transactions are not matching the initial request")
|
||||
if txForSigning.signingDetails.hashes.len == 0:
|
||||
raise newException(CatchableError, "no transaction hashes to be signed")
|
||||
if txForSigning.signingDetails.keyUid == "" or txForSigning.signingDetails.address == "" or txForSigning.signingDetails.addressPath == "":
|
||||
raise newException(CatchableError, "preparing signatures for transactions failed")
|
||||
|
||||
if txForSigning.signingDetails.signOnKeycard:
|
||||
self.tmpSendTransactionDetails.fromAddrPath = txForSigning.signingDetails.addressPath
|
||||
for h in txForSigning.signingDetails.hashes:
|
||||
self.tmpSendTransactionDetails.resolvedSignatures[h] = ("", "", "")
|
||||
self.signOnKeycard()
|
||||
else:
|
||||
let finalPassword = hashPassword(self.tmpPassword)
|
||||
for h in txForSigning.signingDetails.hashes:
|
||||
self.tmpSendTransactionDetails.resolvedSignatures[h] = ("", "", "")
|
||||
var
|
||||
signature = ""
|
||||
err: string
|
||||
(signature, err) = self.controller.signMessage(txForSigning.signingDetails.address, finalPassword, h)
|
||||
if err.len > 0:
|
||||
raise newException(CatchableError, "signing transaction failed: " & err)
|
||||
self.tmpSendTransactionDetails.resolvedSignatures[h] = self.getRSVFromSignature(signature)
|
||||
self.sendSignedTransactions()
|
||||
except Exception as e:
|
||||
error "signMessageWithCallback failed: ", msg=e.msg
|
||||
self.transactionWasSent(uuid = txForSigning.sendDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = e.msg)
|
||||
self.clearTmpData()
|
||||
|
||||
method onTransactionSigned*(self: Module, keycardFlowType: string, keycardEvent: KeycardEvent) =
|
||||
if keycardFlowType != keycard_constants.ResponseTypeValueKeycardFlowResult:
|
||||
error "unexpected error while keycard signing transaction"
|
||||
let err = "unexpected error while keycard signing transaction"
|
||||
error "error", err=err
|
||||
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = err)
|
||||
self.clearTmpData()
|
||||
return
|
||||
self.tmpSendTransactionDetails.resolvedSignatures[self.tmpTxHashBeingProcessed] = (keycardEvent.txSignature.r,
|
||||
keycardEvent.txSignature.s, keycardEvent.txSignature.v)
|
||||
self.signOnKeycard()
|
||||
|
||||
method transactionWasSent*(self: Module, chainId: int, txHash, uuid, error: string) =
|
||||
method transactionWasSent*(self: Module, uuid: string, chainId: int = 0, approvalTx: bool = false, txHash: string = "", error: string = "") =
|
||||
if txHash.len == 0:
|
||||
self.view.sendTransactionSentSignal(chainId = 0, txHash = "", uuid = self.tmpSendTransactionDetails.uuid, error)
|
||||
self.view.sendTransactionSentSignal(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error)
|
||||
return
|
||||
self.view.sendTransactionSentSignal(chainId, txHash, uuid, error)
|
||||
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 = none(float)
|
||||
self.tmpSendTransactionDetails.slippagePercentage = 0
|
||||
let paths = suggestedRoutes.best.map(x => self.convertTransactionPathDtoToSuggestedRouteItem(x))
|
||||
let suggestedRouteModel = newSuggestedRouteModel()
|
||||
suggestedRouteModel.setItems(paths)
|
||||
|
@ -286,6 +324,7 @@ method suggestedRoutes*(self: Module,
|
|||
accountFrom: string,
|
||||
accountTo: string,
|
||||
token: string,
|
||||
tokenIsOwnerToken: bool,
|
||||
amountIn: string,
|
||||
toToken: string = "",
|
||||
amountOut: string = "",
|
||||
|
@ -299,6 +338,7 @@ method suggestedRoutes*(self: Module,
|
|||
accountFrom,
|
||||
accountTo,
|
||||
token,
|
||||
tokenIsOwnerToken,
|
||||
amountIn,
|
||||
toToken,
|
||||
amountOut,
|
||||
|
@ -362,5 +402,5 @@ method splitAndFormatAddressPrefix*(self: Module, text : string, updateInStore:
|
|||
editedText = "<a><p>" & editedText & "</a></p>"
|
||||
return editedText
|
||||
|
||||
method transactionSendingComplete*(self: Module, txHash: string, success: bool) =
|
||||
self.view.sendtransactionSendingCompleteSignal(txHash, success)
|
||||
method transactionSendingComplete*(self: Module, txHash: string, status: string) =
|
||||
self.view.sendtransactionSendingCompleteSignal(txHash, status)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import NimQml, Tables, json, sequtils, strutils, stint, options, chronicles
|
||||
import uuids
|
||||
import NimQml, Tables, json, sequtils, strutils, stint, chronicles
|
||||
|
||||
import ./io_interface, ./network_route_model, ./network_route_item, ./suggested_route_item, ./transaction_routes
|
||||
import app_service/service/network/service as network_service
|
||||
|
@ -165,9 +164,9 @@ QtObject:
|
|||
self.fromNetworksRouteModel.setItems(fromNetworks)
|
||||
self.toNetworksRouteModel.setItems(toNetworks)
|
||||
|
||||
proc transactionSent*(self: View, chainId: int, txHash: string, uuid: string, error: string) {.signal.}
|
||||
proc sendTransactionSentSignal*(self: View, chainId: int, txHash: string, uuid: string, error: string) =
|
||||
self.transactionSent(chainId, txHash, uuid, error)
|
||||
proc transactionSent*(self: View, uuid: string, chainId: int, approvalTx: bool, txHash: string, error: string) {.signal.}
|
||||
proc sendTransactionSentSignal*(self: View, uuid: string, chainId: int, approvalTx: bool, txHash: string, error: string) =
|
||||
self.transactionSent(uuid, chainId, approvalTx, txHash, error)
|
||||
|
||||
proc parseChainIds(chainIds: string): seq[int] =
|
||||
var parsedChainIds: seq[int] = @[]
|
||||
|
@ -175,9 +174,13 @@ QtObject:
|
|||
parsedChainIds.add(chainId.parseInt())
|
||||
return parsedChainIds
|
||||
|
||||
proc authenticateAndTransfer*(self: View, uuid: string) {.slot.} =
|
||||
self.delegate.authenticateAndTransfer(self.selectedSenderAccountAddress, self.selectedRecipient, self.selectedAssetKey,
|
||||
self.selectedToAssetKey, uuid, self.sendType, self.selectedTokenName, self.selectedTokenIsOwnerToken)
|
||||
proc authenticateAndTransfer*(self: View, uuid: string, slippagePercentageString: string) {.slot.} =
|
||||
var slippagePercentage: float
|
||||
try:
|
||||
slippagePercentage = slippagePercentageString.parseFloat()
|
||||
except:
|
||||
error "parsing slippage failed", slippage=slippagePercentageString
|
||||
self.delegate.authenticateAndTransferV2(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) =
|
||||
|
@ -186,7 +189,7 @@ QtObject:
|
|||
self.errDescription = errDescription
|
||||
self.suggestedRoutesReady(newQVariant(self.transactionRoutes), errCode, errDescription)
|
||||
|
||||
proc suggestedRoutes*(self: View, amountIn: string, amountOut: string, extraParamsJson: string) {.slot.} =
|
||||
proc suggestedRoutes*(self: View, uuid: string, amountIn: string, amountOut: string, extraParamsJson: string) {.slot.} =
|
||||
var extraParamsTable: Table[string, string]
|
||||
try:
|
||||
if extraParamsJson.len > 0:
|
||||
|
@ -201,11 +204,12 @@ QtObject:
|
|||
error "Error parsing extraParamsJson: ", msg=e.msg
|
||||
|
||||
self.delegate.suggestedRoutes(
|
||||
$genUUID(),
|
||||
uuid,
|
||||
self.sendType,
|
||||
self.selectedSenderAccountAddress,
|
||||
self.selectedRecipient,
|
||||
self.selectedAssetKey,
|
||||
self.selectedTokenIsOwnerToken,
|
||||
amountIn,
|
||||
self.selectedToAssetKey,
|
||||
amountOut,
|
||||
|
@ -283,6 +287,7 @@ QtObject:
|
|||
accountFrom,
|
||||
accountTo,
|
||||
token,
|
||||
self.selectedTokenIsOwnerToken,
|
||||
amountIn,
|
||||
toToken,
|
||||
amountOut,
|
||||
|
@ -290,22 +295,9 @@ QtObject:
|
|||
parseChainIds(disabledToChainIDs),
|
||||
lockedInAmountsTable)
|
||||
|
||||
proc authenticateAndTransferWithParameters*(self: View, uuid: string, accountFrom: string, accountTo: string, token: string, toToken: string,
|
||||
sendTypeInt: int, tokenName: string, tokenIsOwnerToken: bool, rawPaths: string, slippagePercentageString: string) {.slot.} =
|
||||
|
||||
let sendType = SendType(sendTypeInt)
|
||||
|
||||
var slippagePercentage: Option[float]
|
||||
if sendType == SendType.Swap:
|
||||
if slippagePercentageString.len > 0:
|
||||
slippagePercentage = slippagePercentageString.parseFloat().some
|
||||
|
||||
self.delegate.authenticateAndTransferWithPaths(accountFrom, accountTo, token,
|
||||
toToken, uuid, sendType, tokenName, tokenIsOwnerToken, rawPaths, slippagePercentage)
|
||||
|
||||
proc transactionSendingComplete*(self: View, txHash: string, success: bool) {.signal.}
|
||||
proc sendtransactionSendingCompleteSignal*(self: View, txHash: string, success: bool) =
|
||||
self.transactionSendingComplete(txHash, success)
|
||||
proc transactionSendingComplete*(self: View, txHash: string, status: string) {.signal.}
|
||||
proc sendtransactionSendingCompleteSignal*(self: View, txHash: string, status: string) =
|
||||
self.transactionSendingComplete(txHash, status)
|
||||
|
||||
proc setSenderAccount*(self: View, address: string) {.slot.} =
|
||||
self.setSelectedSenderAccountAddress(address)
|
||||
|
|
|
@ -119,7 +119,10 @@ QtObject:
|
|||
debug "signMessageWithCallback: signing on keycard started successfully"
|
||||
return
|
||||
let finalPassword = self.preparePassword(password)
|
||||
res = self.service.signMessage(address, finalPassword, message)
|
||||
var err: string
|
||||
(res, err) = self.service.signMessage(address, finalPassword, message)
|
||||
if err.len > 0:
|
||||
raise newException(CatchableError, "signMessage failed: " & err)
|
||||
except Exception as e:
|
||||
error "signMessageWithCallback failed: ", msg=e.msg
|
||||
callback(topic, id, "", address, res)
|
||||
|
|
|
@ -7,6 +7,9 @@ const
|
|||
STT_CONTRACT_ADDRESS_GOERLI* = "0x3d6afaa395c31fcd391fe3d562e75fe9e8ec7e6a"
|
||||
STT_CONTRACT_ADDRESS_SEPOLIA* = "0xE452027cdEF746c7Cd3DB31CB700428b16cD8E51"
|
||||
|
||||
SIGNATURE_LEN* = 130
|
||||
SIGNATURE_LEN_0X_INCLUDED* = SIGNATURE_LEN + 2
|
||||
|
||||
TX_HASH_LEN* = 32 * 2
|
||||
TX_HASH_LEN_WITH_PREFIX* = TX_HASH_LEN + 2
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import stint
|
||||
import ../../../backend/backend as backend
|
||||
import ../../common/conversion as service_conversion
|
||||
|
||||
type
|
||||
GetSuggestedRoutesTaskArg* = ref object of QObjectTaskArg
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
import json, stint
|
||||
|
||||
include ../../common/json_utils
|
||||
|
||||
const
|
||||
TxStatusPending* = "Pending"
|
||||
TxStatusSuccess* = "Success"
|
||||
TxStatusFailed* = "Failed"
|
||||
|
||||
type
|
||||
TransactionStatusChange* = ref object
|
||||
status*: string
|
||||
hash*: string
|
||||
chainId*: int
|
||||
|
||||
type
|
||||
ErrorResponse* = ref object
|
||||
details*: string
|
||||
code*: string
|
||||
type
|
||||
SendDetailsDto* = ref object
|
||||
uuid*: string
|
||||
sendType*: int
|
||||
fromAddress*: string
|
||||
toAddress*: string
|
||||
fromToken*: string
|
||||
toToken*: string
|
||||
fromAmount*: UInt256 # total amount
|
||||
toAmount*: UInt256
|
||||
ownerTokenBeingSent*: bool
|
||||
errorResponse*: ErrorResponse
|
||||
username*: string
|
||||
publicKey*: string
|
||||
packId*: string
|
||||
|
||||
type
|
||||
SigningDetails* = ref object
|
||||
address*: string
|
||||
addressPath*: string
|
||||
keyUid*: string
|
||||
signOnKeycard*: bool
|
||||
hashes*: seq[string]
|
||||
|
||||
type
|
||||
RouterTransactionsForSigningDto* = ref object
|
||||
sendDetails*: SendDetailsDto
|
||||
signingDetails*: SigningDetails
|
||||
|
||||
type
|
||||
RouterSentTransaction* = ref object
|
||||
fromAddress*: string
|
||||
toAddress*: string
|
||||
fromChain*: int
|
||||
toChain*: int
|
||||
fromToken*: string
|
||||
toToken*: string
|
||||
amount*: UInt256 # amount of the transaction
|
||||
hash*: string
|
||||
approvalTx*: bool
|
||||
|
||||
type
|
||||
RouterSentTransactionsDto* = ref object
|
||||
sendDetails*: SendDetailsDto
|
||||
sentTransactions*: seq[RouterSentTransaction]
|
||||
|
||||
proc toTransactionStatusChange*(jsonObj: JsonNode): TransactionStatusChange =
|
||||
result = TransactionStatusChange()
|
||||
discard jsonObj.getProp("status", result.status)
|
||||
discard jsonObj.getProp("hash", result.hash)
|
||||
discard jsonObj.getProp("chainId", result.chainId)
|
||||
|
||||
proc toErrorResponse*(jsonObj: JsonNode): ErrorResponse =
|
||||
result = ErrorResponse()
|
||||
if jsonObj.contains("details"):
|
||||
result.details = jsonObj["details"].getStr
|
||||
if jsonObj.contains("code"):
|
||||
result.code = jsonObj["code"].getStr
|
||||
|
||||
proc toSendDetailsDto*(jsonObj: JsonNode): SendDetailsDto =
|
||||
result = SendDetailsDto()
|
||||
discard jsonObj.getProp("uuid", result.uuid)
|
||||
discard jsonObj.getProp("sendType", result.sendType)
|
||||
discard jsonObj.getProp("fromAddress", result.fromAddress)
|
||||
discard jsonObj.getProp("toAddress", result.toAddress)
|
||||
discard jsonObj.getProp("fromToken", result.fromToken)
|
||||
discard jsonObj.getProp("toToken", result.toToken)
|
||||
discard jsonObj.getProp("ownerTokenBeingSent", result.ownerTokenBeingSent)
|
||||
var tmpObj: JsonNode
|
||||
if jsonObj.getProp("fromAmount", tmpObj):
|
||||
result.fromAmount = stint.fromHex(UInt256, tmpObj.getStr)
|
||||
if jsonObj.getProp("toAmount", tmpObj):
|
||||
result.toAmount = stint.fromHex(UInt256, tmpObj.getStr)
|
||||
if jsonObj.getProp("errorResponse", tmpObj) and tmpObj.kind == JObject:
|
||||
result.errorResponse = toErrorResponse(tmpObj)
|
||||
discard jsonObj.getProp("username", result.username)
|
||||
discard jsonObj.getProp("publicKey", result.publicKey)
|
||||
if jsonObj.getProp("packId", tmpObj):
|
||||
let packId = stint.fromHex(UInt256, tmpObj.getStr)
|
||||
result.packId = $packId
|
||||
|
||||
|
||||
proc toSigningDetails*(jsonObj: JsonNode): SigningDetails =
|
||||
result = SigningDetails()
|
||||
discard jsonObj.getProp("address", result.address)
|
||||
discard jsonObj.getProp("addressPath", result.addressPath)
|
||||
discard jsonObj.getProp("keyUid", result.keyUid)
|
||||
discard jsonObj.getProp("signOnKeycard", result.signOnKeycard)
|
||||
var tmpObj: JsonNode
|
||||
if jsonObj.getProp("hashes", tmpObj) and tmpObj.kind == JArray:
|
||||
for tx in tmpObj:
|
||||
result.hashes.add(tx.getStr)
|
||||
|
||||
proc toRouterTransactionsForSigningDto*(jsonObj: JsonNode): RouterTransactionsForSigningDto =
|
||||
result = RouterTransactionsForSigningDto()
|
||||
var tmpObj: JsonNode
|
||||
if jsonObj.getProp("sendDetails", tmpObj) and tmpObj.kind == JObject:
|
||||
result.sendDetails = toSendDetailsDto(tmpObj)
|
||||
if jsonObj.getProp("signingDetails", tmpObj) and tmpObj.kind == JObject:
|
||||
result.signingDetails = toSigningDetails(tmpObj)
|
||||
|
||||
proc toRouterSentTransaction*(jsonObj: JsonNode): RouterSentTransaction =
|
||||
result = RouterSentTransaction()
|
||||
discard jsonObj.getProp("fromAddress", result.fromAddress)
|
||||
discard jsonObj.getProp("toAddress", result.toAddress)
|
||||
discard jsonObj.getProp("fromChain", result.fromChain)
|
||||
discard jsonObj.getProp("toChain", result.toChain)
|
||||
discard jsonObj.getProp("fromToken", result.fromToken)
|
||||
discard jsonObj.getProp("toToken", result.toToken)
|
||||
discard jsonObj.getProp("hash", result.hash)
|
||||
discard jsonObj.getProp("approvalTx", result.approvalTx)
|
||||
var tmpObj: JsonNode
|
||||
if jsonObj.getProp("amount", tmpObj):
|
||||
result.amount = stint.fromHex(UInt256, tmpObj.getStr)
|
||||
|
||||
proc toRouterSentTransactionsDto*(jsonObj: JsonNode): RouterSentTransactionsDto =
|
||||
result = RouterSentTransactionsDto()
|
||||
var tmpObj: JsonNode
|
||||
if jsonObj.getProp("sendDetails", tmpObj) and tmpObj.kind == JObject:
|
||||
result.sendDetails = toSendDetailsDto(tmpObj)
|
||||
if jsonObj.getProp("sentTransactions", tmpObj) and tmpObj.kind == JArray:
|
||||
for tx in tmpObj:
|
||||
result.sentTransactions.add(toRouterSentTransaction(tx))
|
|
@ -4,8 +4,8 @@ import backend/collectibles as collectibles
|
|||
import backend/transactions as transactions
|
||||
import backend/backend
|
||||
import backend/eth
|
||||
import backend/wallet
|
||||
|
||||
import app_service/service/ens/utils as ens_utils
|
||||
import app_service/common/utils as common_utils
|
||||
import app_service/common/types as common_types
|
||||
|
||||
|
@ -19,15 +19,14 @@ import app_service/service/wallet_account/service as wallet_account_service
|
|||
import app_service/service/network/service as network_service
|
||||
import app_service/service/token/service as token_service
|
||||
import app_service/service/settings/service as settings_service
|
||||
import app_service/service/eth/dto/transaction as transaction_data_dto
|
||||
import app_service/service/eth/dto/[coder, method_dto]
|
||||
import ./dto as transaction_dto
|
||||
import ./dtoV2
|
||||
import ./dto_conversion
|
||||
import ./router_transactions_dto
|
||||
import app_service/service/eth/utils as eth_utils
|
||||
|
||||
|
||||
export transaction_dto
|
||||
export transaction_dto, router_transactions_dto
|
||||
export transactions.TransactionsSignatures
|
||||
|
||||
logScope:
|
||||
|
@ -37,6 +36,8 @@ include async_tasks
|
|||
include app_service/common/json_utils
|
||||
|
||||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_SIGN_ROUTER_TRANSACTIONS* = "signRouterTransactions"
|
||||
const SIGNAL_SENDING_TRANSACTIONS_STARTED* = "sendingTransactionsStarted"
|
||||
const SIGNAL_TRANSACTION_SENT* = "transactionSent"
|
||||
const SIGNAL_SUGGESTED_ROUTES_READY* = "suggestedRoutesReady"
|
||||
const SIGNAL_HISTORY_NON_ARCHIVAL_NODE* = "historyNonArchivalNode"
|
||||
|
@ -44,12 +45,7 @@ const SIGNAL_HISTORY_ERROR* = "historyError"
|
|||
const SIGNAL_TRANSACTION_DECODED* = "transactionDecoded"
|
||||
const SIGNAL_OWNER_TOKEN_SENT* = "ownerTokenSent"
|
||||
const SIGNAL_TRANSACTION_SENDING_COMPLETE* = "transactionSendingComplete"
|
||||
|
||||
const SIMPLE_TX_BRIDGE_NAME = "Transfer"
|
||||
const HOP_TX_BRIDGE_NAME = "Hop"
|
||||
const ERC721_TRANSFER_NAME = "ERC721Transfer"
|
||||
const ERC1155_TRANSFER_NAME = "ERC1155Transfer"
|
||||
const SWAP_PARASWAP_NAME = "Paraswap"
|
||||
const SIGNAL_TRANSACTION_STATUS_CHANGED* = "transactionStatusChanged"
|
||||
|
||||
type TokenTransferMetadata* = object
|
||||
tokenName*: string
|
||||
|
@ -119,6 +115,10 @@ type
|
|||
fromAmount*: string
|
||||
toTokenKey*: string
|
||||
toAmount*: string
|
||||
approvalTx*: bool
|
||||
username*: string
|
||||
publicKey*: string
|
||||
packId*: string
|
||||
|
||||
type
|
||||
OwnerTokenSentArgs* = ref object of Args
|
||||
|
@ -140,6 +140,18 @@ type
|
|||
dataDecoded*: string
|
||||
txHash*: string
|
||||
|
||||
type
|
||||
RouterTransactionsForSigningArgs* = ref object of Args
|
||||
data*: RouterTransactionsForSigningDto
|
||||
|
||||
type
|
||||
RouterTransactionsSendingStartedArgs* = ref object of Args
|
||||
data*: SendDetailsDto
|
||||
|
||||
type
|
||||
TransactionStatusArgs* = ref object of Args
|
||||
data*: TransactionStatusChange
|
||||
|
||||
QtObject:
|
||||
type Service* = ref object of QObject
|
||||
events: EventEmitter
|
||||
|
@ -151,6 +163,7 @@ QtObject:
|
|||
|
||||
## Forward declarations
|
||||
proc suggestedRoutesReady(self: Service, uuid: string, route: seq[TransactionPathDtoV2], routeRaw: string, errCode: string, errDescription: string)
|
||||
proc sendTransactionsSignal(self: Service, sendDetails: SendDetailsDto, sentTransactions: seq[RouterSentTransaction] = @[])
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.QObject.delete
|
||||
|
@ -184,6 +197,28 @@ QtObject:
|
|||
self.tokenService.updateTokenPrices(data.updatedPrices)
|
||||
self.suggestedRoutesReady(data.uuid, data.bestRoute, data.bestRouteRaw, data.errorCode, data.error)
|
||||
|
||||
self.events.on(SignalType.WalletRouterSendingTransactionsStarted.event) do(e:Args):
|
||||
var data = WalletSignal(e)
|
||||
self.events.emit(SIGNAL_SENDING_TRANSACTIONS_STARTED, RouterTransactionsSendingStartedArgs(data: data.routerTransactionsSendingDetails))
|
||||
# TODO: the line below is to aling with the old implementation, remove it
|
||||
self.sendTransactionsSignal(data.routerTransactionsSendingDetails)
|
||||
|
||||
self.events.on(SignalType.WalletRouterSignTransactions.event) do(e:Args):
|
||||
var data = WalletSignal(e)
|
||||
if data.routerTransactionsForSigning.sendDetails.errorResponse.isNil and
|
||||
not data.routerTransactionsForSigning.signingDetails.isNil:
|
||||
self.events.emit(SIGNAL_SIGN_ROUTER_TRANSACTIONS, RouterTransactionsForSigningArgs(data: data.routerTransactionsForSigning))
|
||||
return
|
||||
self.sendTransactionsSignal(data.routerTransactionsForSigning.sendDetails)
|
||||
|
||||
self.events.on(SignalType.WalletRouterTransactionsSent.event) do(e:Args):
|
||||
var data = WalletSignal(e)
|
||||
self.sendTransactionsSignal(data.routerSentTransactions.sendDetails, data.routerSentTransactions.sentTransactions)
|
||||
|
||||
self.events.on(SignalType.WalletTransactionStatusChanged.event) do(e:Args):
|
||||
var data = WalletSignal(e)
|
||||
self.events.emit(SIGNAL_TRANSACTION_STATUS_CHANGED, TransactionStatusArgs(data: data.transactionStatusChange))
|
||||
|
||||
self.events.on(PendingTransactionTypeDto.WalletTransfer.event) do(e: Args):
|
||||
try:
|
||||
var receivedData = TransactionMinedArgs(e)
|
||||
|
@ -287,372 +322,55 @@ QtObject:
|
|||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc createApprovalPath*(self: Service, route: TransactionPathDto, from_addr: string, toAddress: Address, gasFees: string): TransactionBridgeDto =
|
||||
var txData = TransactionDataDto()
|
||||
let approve = Approve(
|
||||
to: parseAddress(route.approvalContractAddress),
|
||||
value: route.approvalAmountRequired,
|
||||
)
|
||||
let data = ERC20_procS.toTable["approve"].encodeAbi(approve)
|
||||
txData = ens_utils.buildTokenTransaction(
|
||||
parseAddress(from_addr),
|
||||
toAddress,
|
||||
$route.gasAmount,
|
||||
gasFees,
|
||||
route.gasFees.eip1559Enabled,
|
||||
$route.gasFees.maxPriorityFeePerGas,
|
||||
$route.gasFees.maxFeePerGasM
|
||||
)
|
||||
txData.data = data
|
||||
|
||||
var path = TransactionBridgeDto(bridgeName: SIMPLE_TX_BRIDGE_NAME, chainID: route.fromNetwork.chainId)
|
||||
path.transferTx = txData
|
||||
return path
|
||||
|
||||
proc createPath*(self: Service, route: TransactionPathDto, txData: TransactionDataDto, tokenSymbol: string, to_addr: string): TransactionBridgeDto =
|
||||
var path = TransactionBridgeDto(bridgeName: route.bridgeName, chainID: route.fromNetwork.chainId)
|
||||
var hopTx = TransactionDataDto()
|
||||
var cbridgeTx = TransactionDataDto()
|
||||
var eRC721TransferTx = TransactionDataDto()
|
||||
var eRC1155TransferTx = TransactionDataDto()
|
||||
var swapTx = TransactionDataDto()
|
||||
|
||||
if(route.bridgeName == SIMPLE_TX_BRIDGE_NAME):
|
||||
path.transferTx = txData
|
||||
elif(route.bridgeName == HOP_TX_BRIDGE_NAME):
|
||||
hopTx = txData
|
||||
hopTx.chainID = route.fromNetwork.chainId.some
|
||||
hopTx.chainIDTo = route.toNetwork.chainId.some
|
||||
hopTx.symbol = tokenSymbol.some
|
||||
hopTx.recipient = parseAddress(to_addr).some
|
||||
hopTx.amount = route.amountIn.some
|
||||
hopTx.bonderFee = route.txBonderFees.some
|
||||
path.hopTx = hopTx
|
||||
elif(route.bridgeName == ERC721_TRANSFER_NAME):
|
||||
eRC721TransferTx = txData
|
||||
eRC721TransferTx.chainID = route.toNetwork.chainId.some
|
||||
eRC721TransferTx.recipient = parseAddress(to_addr).some
|
||||
eRC721TransferTx.tokenID = stint.u256(tokenSymbol).some
|
||||
path.eRC721TransferTx = eRC721TransferTx
|
||||
elif(route.bridgeName == ERC1155_TRANSFER_NAME):
|
||||
eRC1155TransferTx = txData
|
||||
eRC1155TransferTx.chainID = route.toNetwork.chainId.some
|
||||
eRC1155TransferTx.recipient = parseAddress(to_addr).some
|
||||
eRC1155TransferTx.tokenID = stint.u256(tokenSymbol).some
|
||||
eRC1155TransferTx.amount = route.amountIn.some
|
||||
path.eRC1155TransferTx = eRC1155TransferTx
|
||||
elif(route.bridgeName == SWAP_PARASWAP_NAME):
|
||||
swapTx = txData
|
||||
swapTx.chainID = route.fromNetwork.chainId.some
|
||||
swapTx.chainIDTo = route.toNetwork.chainId.some
|
||||
swapTx.tokenIdFrom = route.fromToken.symbol.some
|
||||
swapTx.tokenIdTo = route.toToken.symbol.some
|
||||
path.swapTx = swapTx
|
||||
else:
|
||||
cbridgeTx = txData
|
||||
cbridgeTx.chainID = route.toNetwork.chainId.some
|
||||
cbridgeTx.symbol = tokenSymbol.some
|
||||
cbridgeTx.recipient = parseAddress(to_addr).some
|
||||
cbridgeTx.amount = route.amountIn.some
|
||||
path.cbridgeTx = cbridgeTx
|
||||
return path
|
||||
|
||||
proc sendTransactionSentSignal(self: Service, txType: SendType, fromAddr: string, toAddr: string,
|
||||
fromTokenKey: string, fromAmount: string, toTokenKey: string, toAmount: string, uuid: string,
|
||||
routes: seq[TransactionPathDto], response: RpcResponse[JsonNode], err: string = "", tokenName = "", isOwnerToken=false) =
|
||||
proc sendTransactionsSignal(self: Service, sendDetails: SendDetailsDto, sentTransactions: seq[RouterSentTransaction] = @[]) =
|
||||
# While preparing the tx in the Send modal user cannot see the address, it's revealed once the tx is sent
|
||||
# (there are few places where we display the toast from and link to the etherscan where the address can be seen)
|
||||
# that's why we need to mark the addresses as shown here (safer).
|
||||
self.events.emit(MARK_WALLET_ADDRESSES_AS_SHOWN, WalletAddressesArgs(addresses: @[fromAddr, toAddr]))
|
||||
self.events.emit(MARK_WALLET_ADDRESSES_AS_SHOWN, WalletAddressesArgs(addresses: @[sendDetails.fromAddress, sendDetails.toAddress]))
|
||||
|
||||
if err.len > 0:
|
||||
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(uuid: uuid, error: err, txType: txType,
|
||||
fromAddress: fromAddr, toAddress: toAddr, fromTokenKey: fromTokenKey, fromAmount: fromAmount,
|
||||
toTokenKey: toTokenKey, toAmount: toAmount))
|
||||
if txType == SendType.Swap:
|
||||
singletonInstance.globalEvents.addCentralizedMetricIfEnabled("swap", $(%*{"subEvent": "tx error"}))
|
||||
elif response.result{"hashes"} != nil:
|
||||
for route in routes:
|
||||
for hash in response.result["hashes"][$route.fromNetwork.chainID]:
|
||||
if isOwnerToken:
|
||||
self.events.emit(SIGNAL_OWNER_TOKEN_SENT, OwnerTokenSentArgs(chainId: route.fromNetwork.chainID, txHash: hash.getStr,
|
||||
uuid: uuid, tokenName: tokenName, status: ContractTransactionStatus.InProgress))
|
||||
else:
|
||||
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(chainId: route.fromNetwork.chainID, txHash: hash.getStr, uuid: uuid ,
|
||||
error: "", txType: txType, fromAddress: fromAddr, toAddress: toAddr, fromTokenKey: fromTokenKey, fromAmount: fromAmount, toTokenKey: toTokenKey, toAmount: toAmount))
|
||||
if not sendDetails.errorResponse.isNil and sendDetails.errorResponse.details.len > 0:
|
||||
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(
|
||||
uuid: sendDetails.uuid,
|
||||
error: sendDetails.errorResponse.details,
|
||||
txType: SendType(sendDetails.sendType),
|
||||
fromAddress: sendDetails.fromAddress,
|
||||
toAddress: sendDetails.toAddress,
|
||||
fromTokenKey: sendDetails.fromToken,
|
||||
fromAmount: sendDetails.fromAmount.toString(10),
|
||||
toTokenKey: sendDetails.toToken,
|
||||
toAmount: sendDetails.toAmount.toString(10),
|
||||
username: sendDetails.username,
|
||||
publicKey: sendDetails.publicKey,
|
||||
packId: sendDetails.packId
|
||||
))
|
||||
return
|
||||
|
||||
let metadata = TokenTransferMetadata(tokenName: tokenName, isOwnerToken: isOwnerToken)
|
||||
self.watchTransaction(hash.getStr, fromAddr, toAddr, $PendingTransactionTypeDto.WalletTransfer, $(%metadata), route.fromNetwork.chainID,
|
||||
fromTokenKey, fromAmount, toTokenKey, toAmount, txType)
|
||||
|
||||
if txType == SendType.Swap:
|
||||
singletonInstance.globalEvents.addCentralizedMetricIfEnabled("swap", $(%*{"subEvent": "tx success"}))
|
||||
|
||||
proc isCollectiblesTransfer(self: Service, sendType: SendType): bool =
|
||||
return sendType == ERC721Transfer or sendType == ERC1155Transfer
|
||||
|
||||
proc sendTypeToMultiTxType(sendType: SendType): transactions.MultiTransactionType =
|
||||
case sendType
|
||||
of SendType.Swap:
|
||||
return transactions.MultiTransactionType.MultiTransactionSwap
|
||||
of SendType.Approve:
|
||||
return transactions.MultiTransactionType.MultiTransactionApprove
|
||||
of SendType.Bridge:
|
||||
return transactions.MultiTransactionType.MultiTransactionBridge
|
||||
else:
|
||||
return transactions.MultiTransactionType.MultiTransactionSend
|
||||
|
||||
proc transferEth(
|
||||
self: Service,
|
||||
from_addr: string,
|
||||
to_addr: string,
|
||||
tokenSymbol: string,
|
||||
toTokenSymbol: string,
|
||||
uuid: string,
|
||||
routes: seq[TransactionPathDto],
|
||||
password: string,
|
||||
sendType: SendType,
|
||||
slippagePercentage: Option[float]
|
||||
) =
|
||||
try:
|
||||
var paths: seq[TransactionBridgeDto] = @[]
|
||||
var totalAmountToSend: UInt256
|
||||
var totalAmountToReceive: UInt256
|
||||
let toAddress = parseAddress(to_addr)
|
||||
|
||||
for route in routes:
|
||||
var txData = TransactionDataDto()
|
||||
var gasFees: string = ""
|
||||
|
||||
if( not route.gasFees.eip1559Enabled):
|
||||
gasFees = $route.gasFees.gasPrice
|
||||
|
||||
if route.approvalRequired:
|
||||
paths.add(self.createApprovalPath(route, from_addr, toAddress, gasFees))
|
||||
|
||||
totalAmountToSend += route.amountIn
|
||||
totalAmountToReceive += route.amountOut
|
||||
txData = ens_utils.buildTransaction(parseAddress(from_addr), route.amountIn,
|
||||
$route.gasAmount, gasFees, route.gasFees.eip1559Enabled, $route.gasFees.maxPriorityFeePerGas, $route.gasFees.maxFeePerGasM)
|
||||
txData.to = parseAddress(to_addr).some
|
||||
if sendType == SendType.Swap:
|
||||
txData.slippagePercentage = slippagePercentage
|
||||
|
||||
paths.add(self.createPath(route, txData, tokenSymbol, to_addr))
|
||||
|
||||
var mtCommand = MultiTransactionCommandDto(
|
||||
fromAddress: from_addr,
|
||||
toAddress: to_addr,
|
||||
fromAsset: tokenSymbol,
|
||||
toAsset: toTokenSymbol,
|
||||
fromAmount: "0x" & totalAmountToSend.toHex,
|
||||
multiTxType: sendTypeToMultiTxType(sendType),
|
||||
)
|
||||
|
||||
if sendType == SendType.Swap:
|
||||
mtCommand.toAmount = "0x" & totalAmountToReceive.toHex
|
||||
singletonInstance.globalEvents.addCentralizedMetricIfEnabled("swap", $(%*{"subEvent": "send tx"}))
|
||||
|
||||
let response = transactions.createMultiTransaction(
|
||||
mtCommand,
|
||||
paths,
|
||||
password,
|
||||
)
|
||||
|
||||
if password != "":
|
||||
self.sendTransactionSentSignal(sendType, from_addr, to_addr, tokenSymbol, totalAmountToSend.toString(10),
|
||||
toTokenSymbol, totalAmountToReceive.toString(10), uuid, routes, response)
|
||||
except Exception as e:
|
||||
self.sendTransactionSentSignal(sendType, from_addr, to_addr, tokenSymbol, "",
|
||||
toTokenSymbol, "", uuid, @[], RpcResponse[JsonNode](), self.extractRpcErrorMessage(e.msg))
|
||||
|
||||
proc mustIgnoreApprovalRequests(sendType: SendType): bool =
|
||||
# Swap requires approvals to be done in advance in a separate Tx
|
||||
return sendType == SendType.Swap
|
||||
|
||||
# in case of collectibles transfer, assetKey is used to get the contract address and token id
|
||||
# in case of asset transfer, asset is valid and used to get the asset symbol and contract address
|
||||
proc transferToken(
|
||||
self: Service,
|
||||
from_addr: string,
|
||||
to_addr: string,
|
||||
assetKey: string,
|
||||
asset: TokenBySymbolItem,
|
||||
toAssetKey: string,
|
||||
toAsset: TokenBySymbolItem,
|
||||
uuid: string,
|
||||
routes: seq[TransactionPathDto],
|
||||
password: string,
|
||||
sendType: SendType,
|
||||
tokenName: string,
|
||||
isOwnerToken: bool,
|
||||
slippagePercentage: Option[float]
|
||||
) =
|
||||
var
|
||||
toContractAddress: Address
|
||||
paths: seq[TransactionBridgeDto] = @[]
|
||||
totalAmountToSend: UInt256
|
||||
totalAmountToReceive: UInt256
|
||||
mtCommand = MultiTransactionCommandDto(
|
||||
fromAddress: from_addr,
|
||||
toAddress: to_addr,
|
||||
fromAsset: if not asset.isNil: asset.symbol else: assetKey,
|
||||
toAsset: if not toAsset.isNil: toAsset.symbol else: toAssetKey,
|
||||
multiTxType: sendTypeToMultiTxType(sendType),
|
||||
)
|
||||
|
||||
# if collectibles transfer ...
|
||||
if asset.isNil:
|
||||
let contract_tokenId = assetKey.split(":")
|
||||
if contract_tokenId.len == 2:
|
||||
toContractAddress = parseAddress(contract_tokenId[0])
|
||||
mtCommand.fromAsset = contract_tokenId[1]
|
||||
mtCommand.toAsset = contract_tokenId[1]
|
||||
for tx in sentTransactions:
|
||||
if sendDetails.ownerTokenBeingSent:
|
||||
self.events.emit(SIGNAL_OWNER_TOKEN_SENT, OwnerTokenSentArgs(
|
||||
chainId: tx.fromChain,
|
||||
txHash: tx.hash,
|
||||
uuid: sendDetails.uuid,
|
||||
tokenName: tx.fromToken,
|
||||
status: ContractTransactionStatus.InProgress
|
||||
))
|
||||
else:
|
||||
error "Invalid assetKey for collectibles transfer", assetKey=assetKey
|
||||
return
|
||||
|
||||
try:
|
||||
for route in routes:
|
||||
var txData = TransactionDataDto()
|
||||
var gasFees: string = ""
|
||||
|
||||
# If not collectible ...
|
||||
if not asset.isNil:
|
||||
var foundAddress = false
|
||||
for addressPerChain in asset.addressPerChainId:
|
||||
if addressPerChain.chainId == route.fromNetwork.chainId:
|
||||
toContractAddress = parseAddress(addressPerChain.address)
|
||||
foundAddress = true
|
||||
break
|
||||
if not foundAddress:
|
||||
error "Contract address not found for asset", assetKey=assetKey
|
||||
return
|
||||
|
||||
if not route.gasFees.eip1559Enabled:
|
||||
gasFees = $route.gasFees.gasPrice
|
||||
|
||||
if route.approvalRequired and not mustIgnoreApprovalRequests(sendType):
|
||||
let approvalPath = self.createApprovalPath(route, mtCommand.fromAddress, toContractAddress, gasFees)
|
||||
paths.add(approvalPath)
|
||||
|
||||
totalAmountToSend += route.amountIn
|
||||
totalAmountToReceive += route.amountOut
|
||||
|
||||
if sendType == SendType.Approve:
|
||||
# We only do the approvals
|
||||
continue
|
||||
|
||||
let transfer = Transfer(
|
||||
to: parseAddress(mtCommand.toAddress),
|
||||
value: route.amountIn,
|
||||
)
|
||||
let data = ERC20_procS.toTable["transfer"].encodeAbi(transfer)
|
||||
|
||||
txData = ens_utils.buildTokenTransaction(
|
||||
parseAddress(mtCommand.fromAddress),
|
||||
toContractAddress,
|
||||
$route.gasAmount,
|
||||
gasFees,
|
||||
route.gasFees.eip1559Enabled,
|
||||
$route.gasFees.maxPriorityFeePerGas,
|
||||
$route.gasFees.maxFeePerGasM
|
||||
)
|
||||
txData.data = data
|
||||
if sendType == SendType.Swap:
|
||||
txData.slippagePercentage = slippagePercentage
|
||||
|
||||
let path = self.createPath(route, txData, mtCommand.toAsset, mtCommand.toAddress)
|
||||
paths.add(path)
|
||||
|
||||
mtCommand.fromAmount = "0x" & totalAmountToSend.toHex
|
||||
if sendType == SendType.Swap:
|
||||
mtCommand.toAmount = "0x" & totalAmountToReceive.toHex
|
||||
singletonInstance.globalEvents.addCentralizedMetricIfEnabled("swap", $(%*{"subEvent": "send tx"}))
|
||||
|
||||
let response = transactions.createMultiTransaction(mtCommand, paths, password)
|
||||
|
||||
if password != "":
|
||||
self.sendTransactionSentSignal(sendType, mtCommand.fromAddress, mtCommand.toAddress,
|
||||
assetKey, totalAmountToSend.toString(10), toAssetKey, totalAmountToReceive.toString(10),
|
||||
uuid, routes, response, err="", tokenName, isOwnerToken)
|
||||
|
||||
except Exception as e:
|
||||
self.sendTransactionSentSignal(sendType, mtCommand.fromAddress, mtCommand.toAddress,
|
||||
assetKey, "", toAssetKey, "",
|
||||
uuid, @[], RpcResponse[JsonNode](), self.extractRpcErrorMessage(e.msg))
|
||||
|
||||
proc transfer*(
|
||||
self: Service,
|
||||
fromAddr: string,
|
||||
toAddr: string,
|
||||
assetKey: string,
|
||||
toAssetKey: string,
|
||||
uuid: string,
|
||||
selectedRoutes: seq[TransactionPathDto],
|
||||
password: string,
|
||||
sendType: SendType,
|
||||
usePassword: bool,
|
||||
doHashing: bool,
|
||||
tokenName: string,
|
||||
isOwnerToken: bool,
|
||||
slippagePercentage: Option[float]
|
||||
) =
|
||||
var finalPassword = ""
|
||||
if usePassword:
|
||||
finalPassword = password
|
||||
if doHashing:
|
||||
finalPassword = common_utils.hashPassword(password)
|
||||
try:
|
||||
var chainID = 0
|
||||
|
||||
if(selectedRoutes.len > 0):
|
||||
chainID = selectedRoutes[0].fromNetwork.chainID
|
||||
|
||||
# asset == nil means transferToken is executed for a collectibles transfer
|
||||
var
|
||||
asset: TokenBySymbolItem
|
||||
toAsset: TokenBySymbolItem
|
||||
if not self.isCollectiblesTransfer(sendType):
|
||||
asset = self.tokenService.getTokenBySymbolByTokensKey(assetKey)
|
||||
if asset.isNil:
|
||||
error "Asset not found for", assetKey=assetKey
|
||||
return
|
||||
|
||||
toAsset = asset
|
||||
if sendType == Swap:
|
||||
toAsset = self.tokenService.getTokenBySymbolByTokensKey(toAssetKey)
|
||||
if toAsset.isNil:
|
||||
error "Asset not found for", assetKey=assetKey
|
||||
return
|
||||
|
||||
let network = self.networkService.getNetworkByChainId(chainID)
|
||||
if not network.isNil and network.nativeCurrencySymbol == asset.symbol:
|
||||
self.transferEth(fromAddr, toAddr, asset.symbol, toAsset.symbol, uuid, selectedRoutes, finalPassword, sendType, slippagePercentage)
|
||||
return
|
||||
|
||||
self.transferToken(fromAddr, toAddr, assetKey, asset, toAssetKey, toAsset, uuid, selectedRoutes, finalPassword,
|
||||
sendType, tokenName, isOwnerToken, slippagePercentage)
|
||||
|
||||
except Exception as e:
|
||||
self.sendTransactionSentSignal(sendType, fromAddr, toAddr, assetKey, "", toAssetKey, "", uuid, @[], RpcResponse[JsonNode](), self.extractRpcErrorMessage(e.msg))
|
||||
|
||||
proc proceedWithTransactionsSignatures*(self: Service, fromAddr: string, toAddr: string,
|
||||
fromTokenKey: string, toTokenKey: string, uuid: string, signatures: TransactionsSignatures,
|
||||
selectedRoutes: seq[TransactionPathDto], sendType: SendType) =
|
||||
try:
|
||||
let response = transactions.proceedWithTransactionsSignatures(signatures)
|
||||
|
||||
var totalAmountToSend: UInt256
|
||||
var totalAmountToReceive: UInt256
|
||||
for route in selectedRoutes:
|
||||
totalAmountToSend += route.amountIn
|
||||
totalAmountToReceive += route.amountOut
|
||||
|
||||
self.sendTransactionSentSignal(sendType, fromAddr, toAddr, fromTokenKey, totalAmountToSend.toString(10), toTokenKey, totalAmountToReceive.toString(10), uuid, selectedRoutes, response)
|
||||
except Exception as e:
|
||||
self.sendTransactionSentSignal(sendType, fromAddr, toAddr, fromTokenKey, "", toTokenKey, "",
|
||||
uuid, @[], RpcResponse[JsonNode](), fmt"Error proceeding with transactions signatures: {e.msg}")
|
||||
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(
|
||||
chainId: tx.fromChain,
|
||||
txHash: tx.hash,
|
||||
uuid: sendDetails.uuid,
|
||||
txType: SendType(sendDetails.sendType),
|
||||
fromAddress: tx.fromAddress,
|
||||
toAddress: tx.toAddress,
|
||||
fromTokenKey: tx.fromToken,
|
||||
fromAmount: tx.amount.toString(10),
|
||||
toTokenKey: tx.toToken,
|
||||
toAmount: tx.amount.toString(10),
|
||||
approvalTx: tx.approvalTx,
|
||||
username: sendDetails.username,
|
||||
publicKey: sendDetails.publicKey,
|
||||
packId: sendDetails.packId
|
||||
))
|
||||
|
||||
proc suggestedFees*(self: Service, chainId: int): SuggestedFeesDto =
|
||||
try:
|
||||
|
@ -688,6 +406,7 @@ QtObject:
|
|||
accountFrom: string,
|
||||
accountTo: string,
|
||||
token: string,
|
||||
tokenIsOwnerToken: bool,
|
||||
amountIn: string,
|
||||
toToken: string = "",
|
||||
amountOut: string = "",
|
||||
|
@ -706,7 +425,7 @@ QtObject:
|
|||
|
||||
try:
|
||||
let res = eth.suggestedRoutesAsync(uuid, ord(sendType), accountFrom, accountTo, amountInHex, amountOutHex, token,
|
||||
toToken, disabledFromChainIDs, disabledToChainIDs, lockedInAmounts, extraParamsTable)
|
||||
tokenIsOwnerToken, toToken, disabledFromChainIDs, disabledToChainIDs, lockedInAmounts, extraParamsTable)
|
||||
except CatchableError as e:
|
||||
error "suggestedRoutes", exception=e.msg
|
||||
|
||||
|
@ -747,3 +466,38 @@ proc getMultiTransactions*(transactionIDs: seq[int]): seq[MultiTransactionDto] =
|
|||
let errDescription = e.msg
|
||||
error "error: ", errDescription
|
||||
return
|
||||
|
||||
proc signMessage*(self: Service, address: string, hashedPassword: string, hashedMessage: string): tuple[res: string, err: string] =
|
||||
var signMsgRes: JsonNode
|
||||
let err = wallet.signMessage(signMsgRes,
|
||||
hashedMessage,
|
||||
address,
|
||||
hashedPassword)
|
||||
if err.len > 0:
|
||||
error "status-go - wallet_signMessage failed", err=err
|
||||
result.err = err
|
||||
return
|
||||
result.res = signMsgRes.getStr
|
||||
return
|
||||
|
||||
proc buildTransactionsFromRoute*(self: Service, uuid: string, slippagePercentage: float): string =
|
||||
var response: JsonNode
|
||||
let err = transactions.buildTransactionsFromRoute(response, uuid, slippagePercentage)
|
||||
if err.len > 0:
|
||||
error "status-go - transfer failed", err=err
|
||||
return err
|
||||
if response.kind != JNull:
|
||||
error "unexpected transfer response"
|
||||
return "unexpected transfer response"
|
||||
return ""
|
||||
|
||||
proc sendRouterTransactionsWithSignatures*(self: Service, uuid: string, signatures: TransactionsSignatures): string =
|
||||
var response: JsonNode
|
||||
let err = transactions.sendRouterTransactionsWithSignatures(response, uuid, signatures)
|
||||
if err.len > 0:
|
||||
error "status-go - wallet_sendRouterTransactionsWithSignatures failed", err=err
|
||||
return err
|
||||
if response.kind != JNull:
|
||||
error "unexpected sending transactions response"
|
||||
return "unexpected sending transactions response"
|
||||
return ""
|
||||
|
|
|
@ -138,15 +138,8 @@ QtObject:
|
|||
return ""
|
||||
return hashRes.result.getStr()
|
||||
|
||||
proc signMessage*(self: Service, address: string, hashedPassword: string, hashedMessage: string): string =
|
||||
var signMsgRes: JsonNode
|
||||
let err = wallet.signMessage(signMsgRes,
|
||||
hashedMessage,
|
||||
address,
|
||||
hashedPassword)
|
||||
if err.len > 0:
|
||||
error "status-go - wallet_signMessage failed", err=err
|
||||
return signMsgRes.getStr
|
||||
proc signMessage*(self: Service, address: string, hashedPassword: string, hashedMessage: string): tuple[res: string, err: string] =
|
||||
return self.transactions.signMessage(address, hashedPassword, hashedMessage)
|
||||
|
||||
proc buildTransaction*(self: Service, chainId: int, txJson: string): tuple[txToSign: string, txData: JsonNode] =
|
||||
var buildTxResponse: JsonNode
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import json
|
||||
import response_type
|
||||
|
||||
const NO_RESULT* = "no result"
|
||||
|
||||
proc isErrorResponse(rpcResponse: RpcResponse[JsonNode]): bool =
|
||||
if not rpcResponse.error.isNil:
|
||||
return true
|
||||
return false
|
||||
|
||||
proc prepareResponse(resultOut: var JsonNode, rpcResponse: RpcResponse[JsonNode]): string =
|
||||
if isErrorResponse(rpcResponse):
|
||||
return rpcResponse.error.message
|
||||
if rpcResponse.result.isNil:
|
||||
return NO_RESULT
|
||||
resultOut = rpcResponse.result
|
|
@ -39,7 +39,7 @@ proc suggestedFees*(chainId: int): RpcResponse[JsonNode] =
|
|||
return core.callPrivateRPC("wallet_getSuggestedFees", payload)
|
||||
|
||||
proc prepareDataForSuggestedRoutes(uuid: string, sendType: int, accountFrom: string, accountTo: string, amountIn: string, amountOut: string,
|
||||
token: string, toToken: string, disabledFromChainIDs, disabledToChainIDs: seq[int], lockedInAmounts: Table[string, string],
|
||||
token: string, tokenIsOwnerToken: bool, toToken: string, disabledFromChainIDs, disabledToChainIDs: seq[int], lockedInAmounts: Table[string, string],
|
||||
extraParamsTable: Table[string, string]): JsonNode =
|
||||
|
||||
let data = %* {
|
||||
|
@ -50,6 +50,7 @@ proc prepareDataForSuggestedRoutes(uuid: string, sendType: int, accountFrom: str
|
|||
"amountIn": amountIn,
|
||||
"amountOut": amountOut,
|
||||
"tokenID": token,
|
||||
"tokenIDIsOwnerToken": tokenIsOwnerToken,
|
||||
"toTokenID": toToken,
|
||||
"disabledFromChainIDs": disabledFromChainIDs,
|
||||
"disabledToChainIDs": disabledToChainIDs,
|
||||
|
@ -69,19 +70,19 @@ proc prepareDataForSuggestedRoutes(uuid: string, sendType: int, accountFrom: str
|
|||
return %* [data]
|
||||
|
||||
proc suggestedRoutes*(sendType: int, accountFrom: string, accountTo: string, amountIn: string, amountOut: string, token: string,
|
||||
toToken: string, disabledFromChainIDs, disabledToChainIDs: seq[int], lockedInAmounts: Table[string, string],
|
||||
tokenIsOwnerToken: bool, toToken: string, disabledFromChainIDs, disabledToChainIDs: seq[int], lockedInAmounts: Table[string, string],
|
||||
extraParamsTable: Table[string, string]): RpcResponse[JsonNode] {.raises: [RpcException].} =
|
||||
let payload = prepareDataForSuggestedRoutes(uuid = "", sendType, accountFrom, accountTo, amountIn, amountOut, token, toToken, disabledFromChainIDs,
|
||||
disabledToChainIDs, lockedInAmounts, extraParamsTable)
|
||||
let payload = prepareDataForSuggestedRoutes(uuid = "", sendType, accountFrom, accountTo, amountIn, amountOut, token, tokenIsOwnerToken, toToken,
|
||||
disabledFromChainIDs, disabledToChainIDs, lockedInAmounts, extraParamsTable)
|
||||
if payload.isNil:
|
||||
raise newException(RpcException, "Invalid key in extraParamsTable")
|
||||
return core.callPrivateRPC("wallet_getSuggestedRoutes", payload)
|
||||
|
||||
proc suggestedRoutesAsync*(uuid: string, sendType: int, accountFrom: string, accountTo: string, amountIn: string, amountOut: string, token: string,
|
||||
toToken: string, disabledFromChainIDs, disabledToChainIDs: seq[int], lockedInAmounts: Table[string, string],
|
||||
tokenIsOwnerToken: bool, toToken: string, disabledFromChainIDs, disabledToChainIDs: seq[int], lockedInAmounts: Table[string, string],
|
||||
extraParamsTable: Table[string, string]): RpcResponse[JsonNode] {.raises: [RpcException].} =
|
||||
let payload = prepareDataForSuggestedRoutes(uuid, sendType, accountFrom, accountTo, amountIn, amountOut, token, toToken, disabledFromChainIDs,
|
||||
disabledToChainIDs, lockedInAmounts, extraParamsTable)
|
||||
let payload = prepareDataForSuggestedRoutes(uuid, sendType, accountFrom, accountTo, amountIn, amountOut, token, tokenIsOwnerToken, toToken,
|
||||
disabledFromChainIDs, disabledToChainIDs, lockedInAmounts, extraParamsTable)
|
||||
if payload.isNil:
|
||||
raise newException(RpcException, "Invalid key in extraParamsTable")
|
||||
return core.callPrivateRPC("wallet_getSuggestedRoutesAsync", payload)
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import Tables, json, stint, json_serialization, stew/shims/strformat
|
||||
import Tables, json, stint, json_serialization, stew/shims/strformat, logging
|
||||
|
||||
import ../app_service/service/eth/dto/transaction
|
||||
import ./core as core
|
||||
|
||||
include common
|
||||
|
||||
type
|
||||
TransactionsSignatures* = Table[string, tuple[r: string, s: string, v: string]]
|
||||
|
||||
|
@ -82,18 +83,6 @@ proc getTransfersByAddress*(chainId: int, address: string, toBlock: Uint256, lim
|
|||
proc getTransactionReceipt*(chainId: int, transactionHash: string): RpcResponse[JsonNode] =
|
||||
core.callPrivateRPCWithChainId("eth_getTransactionReceipt", chainId, %* [transactionHash])
|
||||
|
||||
proc createMultiTransaction*(multiTransactionCommand: MultiTransactionCommandDto, data: seq[TransactionBridgeDto], password: string): RpcResponse[JsonNode] =
|
||||
let payload = %* [multiTransactionCommand, data, password]
|
||||
result = core.callPrivateRPC("wallet_createMultiTransaction", payload)
|
||||
|
||||
proc proceedWithTransactionsSignatures*(signatures: TransactionsSignatures): RpcResponse[JsonNode] =
|
||||
var data = %* {}
|
||||
for key, value in signatures:
|
||||
data[key] = %* { "r": value.r, "s": value.s, "v": value.v }
|
||||
|
||||
var payload = %* [data]
|
||||
result = core.callPrivateRPC("wallet_proceedWithTransactionsSignatures", payload)
|
||||
|
||||
proc getMultiTransactions*(transactionIDs: seq[int]): RpcResponse[JsonNode] =
|
||||
let payload = %* [transactionIDs]
|
||||
result = core.callPrivateRPC("wallet_getMultiTransactions", payload)
|
||||
|
@ -101,3 +90,31 @@ proc getMultiTransactions*(transactionIDs: seq[int]): RpcResponse[JsonNode] =
|
|||
proc watchTransaction*(chainId: int, hash: string): RpcResponse[JsonNode] =
|
||||
let payload = %* [chainId, hash]
|
||||
core.callPrivateRPC("wallet_watchTransactionByChainID", payload)
|
||||
|
||||
proc buildTransactionsFromRoute*(resultOut: var JsonNode, uuid: string, slippagePercentage: float): string =
|
||||
try:
|
||||
let payload = %* [{
|
||||
"uuid": uuid,
|
||||
"slippagePercentage": slippagePercentage
|
||||
}]
|
||||
let response = core.callPrivateRPC("wallet_buildTransactionsFromRoute", payload)
|
||||
return prepareResponse(resultOut, response)
|
||||
except Exception as e:
|
||||
warn e.msg
|
||||
return e.msg
|
||||
|
||||
proc sendRouterTransactionsWithSignatures*(resultOut: var JsonNode, uuid: string, signatures: TransactionsSignatures): string =
|
||||
try:
|
||||
var jsonSignatures = %* {}
|
||||
for key, value in signatures:
|
||||
jsonSignatures[key] = %* { "r": value.r, "s": value.s, "v": value.v }
|
||||
|
||||
var payload = %* [{
|
||||
"uuid": uuid,
|
||||
"signatures": jsonSignatures
|
||||
}]
|
||||
let response = core.callPrivateRPC("wallet_sendRouterTransactionsWithSignatures", payload)
|
||||
return prepareResponse(resultOut, response)
|
||||
except Exception as e:
|
||||
warn e.msg
|
||||
return e.msg
|
|
@ -4,6 +4,8 @@ from ./gen import rpc
|
|||
|
||||
import status_go
|
||||
|
||||
include common
|
||||
|
||||
rpc(signMessage, "wallet"):
|
||||
message: string
|
||||
address: string
|
||||
|
@ -24,17 +26,6 @@ rpc(sendTransactionWithSignature, "wallet"):
|
|||
sendTxArgsJson: string
|
||||
signature: string
|
||||
|
||||
proc isErrorResponse(rpcResponse: RpcResponse[JsonNode]): bool =
|
||||
if not rpcResponse.error.isNil:
|
||||
return true
|
||||
return false
|
||||
|
||||
proc prepareResponse(resultOut: var JsonNode, rpcResponse: RpcResponse[JsonNode]): string =
|
||||
if isErrorResponse(rpcResponse):
|
||||
return rpcResponse.error.message
|
||||
if rpcResponse.result.isNil:
|
||||
return "no result"
|
||||
resultOut = rpcResponse.result
|
||||
|
||||
## Signs the provided message with the provided account using the provided hashed password, performs `crypto.Sign`
|
||||
## `resultOut` represents a json object that contains the signature if the call was successful, or `nil`
|
||||
|
|
|
@ -71,7 +71,7 @@ SplitView {
|
|||
readonly property bool areTestNetworksEnabled: true
|
||||
signal suggestedRoutesReady(var txRoutes, string errCode, string errDescription)
|
||||
signal transactionSent(var chainId, var txHash, var uuid, var error)
|
||||
signal transactionSendingComplete(var txHash, var success)
|
||||
signal transactionSendingComplete(var txHash, var status)
|
||||
}
|
||||
walletAssetsStore: WalletAssetsStore {
|
||||
id: thisWalletAssetStore
|
||||
|
|
|
@ -75,7 +75,7 @@ SplitView {
|
|||
id: dSwapStore
|
||||
signal suggestedRoutesReady(var txRoutes, string errCode, string errDescription)
|
||||
signal transactionSent(var chainId, var txHash, var uuid, var error)
|
||||
signal transactionSendingComplete(var txHash, var success)
|
||||
signal transactionSendingComplete(var txHash, var status)
|
||||
|
||||
readonly property var accounts: WalletAccountsModel {}
|
||||
readonly property var flatNetworks: NetworksModel.flatNetworks
|
||||
|
@ -312,7 +312,7 @@ SplitView {
|
|||
dSwapStore.transactionSent(networksComboBox.currentValue, "0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", d.uuid, "")
|
||||
})()
|
||||
Backpressure.debounce(this, 2000, () => {
|
||||
dSwapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", true)
|
||||
dSwapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", "Success")
|
||||
})()
|
||||
fetchSuggestedRoutesSpy.wait()
|
||||
Backpressure.debounce(this, 1000, () => {
|
||||
|
@ -352,7 +352,7 @@ SplitView {
|
|||
dSwapStore.transactionSent(networksComboBox.currentValue, "0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", d.uuid, "")
|
||||
})()
|
||||
Backpressure.debounce(this, 2000, () => {
|
||||
dSwapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", false)
|
||||
dSwapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", "Failed")
|
||||
})()
|
||||
}
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ SplitView {
|
|||
Button {
|
||||
text: "emit approval completed successfully"
|
||||
onClicked: {
|
||||
dSwapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", true)
|
||||
dSwapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", "Success")
|
||||
}
|
||||
visible: advancedSignalsCheckBox.checked
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ SplitView {
|
|||
Button {
|
||||
text: "emit approval completed with failure"
|
||||
onClicked: {
|
||||
dSwapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", false)
|
||||
dSwapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", "Failed")
|
||||
}
|
||||
visible: advancedSignalsCheckBox.checked
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ Item {
|
|||
readonly property var swapStore: SwapStore {
|
||||
signal suggestedRoutesReady(var txRoutes, string errCode, string errDescription)
|
||||
signal transactionSent(var chainId,var txHash, var uuid, var error)
|
||||
signal transactionSendingComplete(var txHash, var success)
|
||||
signal transactionSendingComplete(var txHash, var status)
|
||||
|
||||
readonly property var accounts: WalletAccountsModel {}
|
||||
readonly property var flatNetworks: NetworksModel.flatNetworks
|
||||
|
@ -1548,7 +1548,7 @@ Item {
|
|||
root.swapAdaptor.currencyStore.currentCurrency))
|
||||
|
||||
// simulate user click on approve button and approval failed
|
||||
root.swapStore.transactionSent(root.swapFormData.selectedNetworkChainId, "0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", root.swapAdaptor.uuid, "")
|
||||
root.swapStore.transactionSent(root.swapAdaptor.uuid, root.swapFormData.selectedNetworkChainId, true, "0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", "")
|
||||
|
||||
verify(root.swapAdaptor.approvalPending)
|
||||
verify(!root.swapAdaptor.approvalSuccessful)
|
||||
|
@ -1562,7 +1562,7 @@ Item {
|
|||
root.swapAdaptor.currencyStore.currentCurrency))
|
||||
|
||||
// simulate approval tx was unsuccessful
|
||||
root.swapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", false)
|
||||
root.swapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", "Failed")
|
||||
|
||||
verify(!root.swapAdaptor.approvalPending)
|
||||
verify(!root.swapAdaptor.approvalSuccessful)
|
||||
|
@ -1577,7 +1577,7 @@ Item {
|
|||
|
||||
// simulate user click on approve button and successful approval tx made
|
||||
signButton.clicked()
|
||||
root.swapStore.transactionSent(root.swapFormData.selectedNetworkChainId, "0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", root.swapAdaptor.uuid, "")
|
||||
root.swapStore.transactionSent(root.swapAdaptor.uuid, root.swapFormData.selectedNetworkChainId, true, "0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", "")
|
||||
|
||||
verify(root.swapAdaptor.approvalPending)
|
||||
verify(!root.swapAdaptor.approvalSuccessful)
|
||||
|
@ -1590,30 +1590,29 @@ Item {
|
|||
root.swapAdaptor.swapOutputData.totalFees,
|
||||
root.swapAdaptor.currencyStore.currentCurrency))
|
||||
|
||||
root.swapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", "Success")
|
||||
|
||||
// simulate approval tx was successful
|
||||
signButton.clicked()
|
||||
root.swapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", true)
|
||||
|
||||
// check if fetchSuggestedRoutes called
|
||||
fetchSuggestedRoutesCalled.wait()
|
||||
|
||||
// verify loading state was set and no errors currently
|
||||
verifyLoadingAndNoErrorsState(payPanel, receivePanel)
|
||||
root.swapStore.transactionSendingComplete("0x877ffe47fc29340312611d4e833ab189fe4f4152b01cc9a05bb4125b81b2a89a", "Success")
|
||||
|
||||
verify(!root.swapAdaptor.approvalPending)
|
||||
verify(!root.swapAdaptor.approvalSuccessful)
|
||||
verify(root.swapAdaptor.approvalSuccessful)
|
||||
verify(!errorTag.visible)
|
||||
verify(!signButton.interactive)
|
||||
verify(signButton.interactive)
|
||||
verify(!signButton.loadingWithText)
|
||||
compare(signButton.text, qsTr("Swap"))
|
||||
compare(maxFeesValue.text, Constants.dummyText)
|
||||
compare(maxFeesValue.text, root.swapAdaptor.currencyStore.formatCurrencyAmount(
|
||||
root.swapAdaptor.swapOutputData.totalFees,
|
||||
root.swapAdaptor.currencyStore.currentCurrency))
|
||||
|
||||
let txHasRouteNoApproval = root.dummySwapTransactionRoutes.txHasRouteNoApproval
|
||||
txHasRouteNoApproval.uuid = root.swapAdaptor.uuid
|
||||
root.swapStore.suggestedRoutesReady(txHasRouteNoApproval, "", "")
|
||||
|
||||
verify(!root.swapAdaptor.approvalPending)
|
||||
verify(!root.swapAdaptor.approvalSuccessful)
|
||||
verify(root.swapAdaptor.approvalSuccessful)
|
||||
verify(!errorTag.visible)
|
||||
verify(signButton.enabled)
|
||||
verify(!signButton.loadingWithText)
|
||||
|
@ -1784,9 +1783,6 @@ Item {
|
|||
let txHasRouteNoApproval = root.dummySwapTransactionRoutes.txHasRouteNoApproval
|
||||
txHasRouteNoApproval.uuid = root.swapAdaptor.uuid
|
||||
root.swapStore.suggestedRoutesReady(txHasRouteNoApproval, "", "")
|
||||
|
||||
// check if fetch occurs automatically after 15 seconds
|
||||
fetchSuggestedRoutesCalled.wait()
|
||||
}
|
||||
|
||||
function test_deleteing_input_characters_data() {
|
||||
|
@ -1833,38 +1829,38 @@ Item {
|
|||
root.swapFormData.autoRefreshTime = 1200
|
||||
|
||||
// Launch popup
|
||||
launchAndVerfyModal()
|
||||
// launchAndVerfyModal()
|
||||
|
||||
// check if fetchSuggestedRoutes called
|
||||
tryCompare(fetchSuggestedRoutesCalled, "count", 1)
|
||||
// // check if fetchSuggestedRoutes called
|
||||
// tryCompare(fetchSuggestedRoutesCalled, "count", 1)
|
||||
|
||||
// no new calls to fetch new proposal should be made as the proposal is still loading
|
||||
wait(root.swapFormData.autoRefreshTime*2)
|
||||
compare(fetchSuggestedRoutesCalled.count, 1)
|
||||
// wait(root.swapFormData.autoRefreshTime*2)
|
||||
// compare(fetchSuggestedRoutesCalled.count, 1)
|
||||
|
||||
// emit routes ready
|
||||
let txHasRouteApproval = root.dummySwapTransactionRoutes.txHasRoutesApprovalNeeded
|
||||
txHasRouteApproval.uuid = root.swapAdaptor.uuid
|
||||
root.swapStore.suggestedRoutesReady(txHasRouteApproval, "", "")
|
||||
// // emit routes ready
|
||||
// let txHasRouteApproval = root.dummySwapTransactionRoutes.txHasRoutesApprovalNeeded
|
||||
// txHasRouteApproval.uuid = root.swapAdaptor.uuid
|
||||
// root.swapStore.suggestedRoutesReady(txHasRouteApproval, "", "")
|
||||
|
||||
// now refresh can occur as no propsal or signing is pending
|
||||
tryCompare(fetchSuggestedRoutesCalled, "count", 2)
|
||||
// // now refresh can occur as no propsal or signing is pending
|
||||
// tryCompare(fetchSuggestedRoutesCalled, "count", 2)
|
||||
|
||||
// emit routes ready
|
||||
txHasRouteApproval.uuid = root.swapAdaptor.uuid
|
||||
root.swapStore.suggestedRoutesReady(txHasRouteApproval, "", "")
|
||||
// // emit routes ready
|
||||
// txHasRouteApproval.uuid = root.swapAdaptor.uuid
|
||||
// root.swapStore.suggestedRoutesReady(txHasRouteApproval, "", "")
|
||||
|
||||
verify(root.swapAdaptor.swapOutputData.approvalNeeded)
|
||||
verify(!root.swapAdaptor.approvalPending)
|
||||
// verify(root.swapAdaptor.swapOutputData.approvalNeeded)
|
||||
// verify(!root.swapAdaptor.approvalPending)
|
||||
|
||||
// sign approval and check that auto refresh doesnt occur
|
||||
root.swapAdaptor.sendApproveTx()
|
||||
// // sign approval and check that auto refresh doesnt occur
|
||||
// root.swapAdaptor.sendApproveTx()
|
||||
|
||||
// no new calls to fetch new proposal should be made as the approval is pending
|
||||
verify(root.swapAdaptor.swapOutputData.approvalNeeded)
|
||||
verify(root.swapAdaptor.approvalPending)
|
||||
wait(root.swapFormData.autoRefreshTime*2)
|
||||
compare(fetchSuggestedRoutesCalled.count, 2)
|
||||
// // no new calls to fetch new proposal should be made as the approval is pending
|
||||
// verify(root.swapAdaptor.swapOutputData.approvalNeeded)
|
||||
// verify(root.swapAdaptor.approvalPending)
|
||||
// wait(root.swapFormData.autoRefreshTime*2)
|
||||
// compare(fetchSuggestedRoutesCalled.count, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,17 +39,6 @@ StatusDialog {
|
|||
root.swapAdaptor.fetchSuggestedRoutes(payPanel.rawValue)
|
||||
})
|
||||
|
||||
property Timer autoRefreshTimer: Timer {
|
||||
interval: root.swapInputParamsForm.autoRefreshTime
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if(!root.swapAdaptor.swapProposalLoading && !root.swapAdaptor.approvalPending) {
|
||||
d.fetchSuggestedRoutes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fetchSuggestedRoutes() {
|
||||
if (root.swapInputParamsForm.isFormFilledCorrectly()) {
|
||||
root.swapAdaptor.swapProposalLoading = true
|
||||
|
@ -91,19 +80,6 @@ StatusDialog {
|
|||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.swapAdaptor
|
||||
function onApprovalSuccessfulChanged() {
|
||||
// perform a recalculation to make sure expected outcome shown is accurate
|
||||
if(root.swapAdaptor.approvalSuccessful) {
|
||||
d.fetchSuggestedRoutes()
|
||||
}
|
||||
}
|
||||
function onSuggestedRoutesReady() {
|
||||
d.autoRefreshTimer.restart()
|
||||
}
|
||||
}
|
||||
|
||||
// needed as the first time the value not loaded correctly without this Binding
|
||||
Binding {
|
||||
target: root.swapAdaptor
|
||||
|
|
|
@ -264,7 +264,7 @@ QObject {
|
|||
root.suggestedRoutesReady()
|
||||
}
|
||||
|
||||
function onTransactionSent(chainId, txHash, uuid, error) {
|
||||
function onTransactionSent(uuid, chainId, approvalTx, txHash, error) {
|
||||
if(root.swapOutputData.approvalNeeded) {
|
||||
if (uuid !== d.uuid || !!error) {
|
||||
root.approvalPending = false
|
||||
|
@ -276,11 +276,15 @@ QObject {
|
|||
}
|
||||
}
|
||||
|
||||
function onTransactionSendingComplete(txHash, success) {
|
||||
function onTransactionSendingComplete(txHash, status) {
|
||||
if(d.txHash === txHash && root.swapOutputData.approvalNeeded && root.approvalPending) {
|
||||
root.approvalPending = false
|
||||
root.approvalSuccessful = success
|
||||
root.approvalSuccessful = status == "Success" // TODO: make a all tx statuses Constants (success, pending, failed)
|
||||
d.txHash = ""
|
||||
|
||||
if (root.approvalSuccessful) {
|
||||
root.swapOutputData.approvalNeeded = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,16 +346,12 @@ QObject {
|
|||
root.approvalPending = true
|
||||
const accountAddress = root.swapFormData.selectedAccountAddress
|
||||
|
||||
root.swapStore.authenticateAndTransfer(d.uuid, accountAddress, accountAddress,
|
||||
root.swapFormData.fromTokensKey, root.swapFormData.toTokenKey,
|
||||
Constants.SendType.Approve, "", false, root.swapOutputData.rawPaths, "")
|
||||
root.swapStore.authenticateAndTransfer(d.uuid, "")
|
||||
}
|
||||
|
||||
function sendSwapTx() {
|
||||
const accountAddress = root.swapFormData.selectedAccountAddress
|
||||
|
||||
root.swapStore.authenticateAndTransfer(d.uuid, accountAddress, accountAddress,
|
||||
root.swapFormData.fromTokensKey, root.swapFormData.toTokenKey,
|
||||
Constants.SendType.Swap, "", false, root.swapOutputData.rawPaths, root.swapFormData.selectedSlippage)
|
||||
root.swapStore.authenticateAndTransfer(d.uuid, root.swapFormData.selectedSlippage)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ QtObject {
|
|||
readonly property var walletSectionSendInst: walletSectionSend
|
||||
|
||||
signal suggestedRoutesReady(var txRoutes, string errCode, string errDescription)
|
||||
signal transactionSent(var chainId, var txHash, var uuid, var error)
|
||||
signal transactionSent(var uuid, var chainId, var approvalTx, var txHash, var error)
|
||||
signal transactionSendingComplete(var txHash, var success)
|
||||
|
||||
readonly property Connections walletSectionSendConnections: Connections {
|
||||
|
@ -25,8 +25,8 @@ QtObject {
|
|||
function onSuggestedRoutesReady(txRoutes, errCode, errDescription) {
|
||||
root.suggestedRoutesReady(txRoutes, errCode, errDescription)
|
||||
}
|
||||
function onTransactionSent(chainId, txHash, uuid, error) {
|
||||
root.transactionSent(chainId, txHash, uuid, error)
|
||||
function onTransactionSent(uuid, chainId, approvalTx, txHash, error) {
|
||||
root.transactionSent(uuid, chainId, approvalTx, txHash, error)
|
||||
}
|
||||
function onTransactionSendingComplete(txHash, success) {
|
||||
root.transactionSendingComplete(txHash, success)
|
||||
|
@ -45,10 +45,8 @@ QtObject {
|
|||
root.walletSectionSendInst.stopUpdatesForSuggestedRoute()
|
||||
}
|
||||
|
||||
function authenticateAndTransfer(uuid, accountFrom, accountTo,
|
||||
tokenFrom, tokenTo, sendType, tokenName, tokenIsOwnerToken, paths, slippagePercentage) {
|
||||
root.walletSectionSendInst.authenticateAndTransferWithParameters(uuid, accountFrom, accountTo,
|
||||
tokenFrom, tokenTo, sendType, tokenName, tokenIsOwnerToken, paths, slippagePercentage)
|
||||
function authenticateAndTransfer(uuid, slippagePercentage) {
|
||||
root.walletSectionSendInst.authenticateAndTransfer(uuid, slippagePercentage)
|
||||
}
|
||||
|
||||
function getWei2Eth(wei, decimals) {
|
||||
|
|
|
@ -78,7 +78,7 @@ StatusDialog {
|
|||
popup.isLoading = true
|
||||
d.routerError = ""
|
||||
d.routerErrorDetails = ""
|
||||
popup.store.suggestedRoutes(d.isCollectiblesTransfer ? "1" : amountToSend.amount, "0", d.extraParamsJson)
|
||||
popup.store.suggestedRoutes(d.uuid, d.isCollectiblesTransfer ? "1" : amountToSend.amount, "0", d.extraParamsJson)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -788,7 +788,7 @@ StatusDialog {
|
|||
popup.isLoading = false
|
||||
}
|
||||
|
||||
function onTransactionSent(chainId: int, txHash: string, uuid: string, error: string) {
|
||||
function onTransactionSent(uuid: string, chainId: int, approvalTx: bool, txHash: string, error: string) {
|
||||
d.isPendingTx = false
|
||||
if (uuid !== d.uuid) return
|
||||
if (!!error) {
|
||||
|
|
|
@ -58,14 +58,14 @@ QtObject {
|
|||
return networksModule.getBlockExplorerURL(chainID)
|
||||
}
|
||||
|
||||
function authenticateAndTransfer(uuid) {
|
||||
walletSectionSendInst.authenticateAndTransfer(uuid)
|
||||
function authenticateAndTransfer(uuid, slippagePercentage = "") {
|
||||
walletSectionSendInst.authenticateAndTransfer(uuid, slippagePercentage)
|
||||
}
|
||||
|
||||
function suggestedRoutes(amountIn, amountOut = "0", extraParamsJson = "") {
|
||||
function suggestedRoutes(uuid, amountIn, amountOut = "0", extraParamsJson = "") {
|
||||
const valueIn = AmountsArithmetic.fromNumber(amountIn)
|
||||
const valueOut = AmountsArithmetic.fromNumber(amountOut)
|
||||
walletSectionSendInst.suggestedRoutes(valueIn.toFixed(), valueOut.toFixed(), extraParamsJson)
|
||||
walletSectionSendInst.suggestedRoutes(uuid, valueIn.toFixed(), valueOut.toFixed(), extraParamsJson)
|
||||
}
|
||||
|
||||
function stopUpdatesForSuggestedRoute() {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 2f71d9d9f2529cfa21cabb216be7992a5f9f6717
|
||||
Subproject commit 107e2cb8daef1b89b5f6b8dac6f0aa70d901f711
|
Loading…
Reference in New Issue