feat(@desktop/wallet): initial integration for swap proposal, approve tx and swap tx

Closes #14824
This commit is contained in:
Dario Gabriel Lipicar 2024-06-10 09:51:33 -03:00 committed by Khushboo-dev-cpp
parent e8e1e08a89
commit 75d755ea0f
15 changed files with 245 additions and 32 deletions

View File

@ -1,4 +1,4 @@
import sugar, sequtils, stint, json, json_serialization import sugar, sequtils, stint
import uuids, chronicles import uuids, chronicles
import io_interface import io_interface
import app_service/service/wallet_account/service as wallet_account_service import app_service/service/wallet_account/service as wallet_account_service
@ -110,10 +110,9 @@ proc authenticate*(self: Controller, keyUid = "") =
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data) self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
proc suggestedRoutes*(self: Controller, accountFrom: string, accountTo: string, amount: Uint256, token: string, toToken: string, proc suggestedRoutes*(self: Controller, accountFrom: string, accountTo: string, amount: Uint256, token: string, toToken: string,
disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: SendType, lockedInAmounts: string): string = disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: SendType, lockedInAmounts: string) =
let suggestedRoutes = self.transactionService.suggestedRoutes(accountFrom, accountTo, amount, token, toToken, disabledFromChainIDs, self.transactionService.suggestedRoutes(accountFrom, accountTo, amount, token, toToken, disabledFromChainIDs,
disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts) disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts)
return suggestedRoutes.toJson()
proc transfer*(self: Controller, from_addr: string, to_addr: string, assetKey: string, toAssetKey: string, proc transfer*(self: Controller, from_addr: string, to_addr: string, assetKey: string, toAssetKey: string,
uuid: string, selectedRoutes: seq[TransactionPathDto], password: string, sendType: SendType, uuid: string, selectedRoutes: seq[TransactionPathDto], password: string, sendType: SendType,

View File

@ -25,7 +25,7 @@ method getTokenBalance*(self: AccessInterface, address: string, chainId: int, to
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method suggestedRoutes*(self: AccessInterface, accountFrom: string, accountTo: string, amount: UInt256, token: string, toToken: string, method suggestedRoutes*(self: AccessInterface, accountFrom: string, accountTo: string, amount: UInt256, token: string, toToken: string,
disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: SendType, lockedInAmounts: string): string {.base.} = disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: SendType, lockedInAmounts: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method suggestedRoutesReady*(self: AccessInterface, suggestedRoutes: SuggestedRoutesDto) {.base.} = method suggestedRoutesReady*(self: AccessInterface, suggestedRoutes: SuggestedRoutesDto) {.base.} =
@ -35,6 +35,10 @@ method authenticateAndTransfer*(self: AccessInterface, from_addr: string, to_add
toAssetKey: string, uuid: string, sendType: SendType, selectedTokenName: string, selectedTokenIsOwnerToken: bool) {.base.} = toAssetKey: string, uuid: string, sendType: SendType, selectedTokenName: string, selectedTokenIsOwnerToken: bool) {.base.} =
raise newException(ValueError, "No implementation available") 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) {.base.} =
raise newException(ValueError, "No implementation available")
method onUserAuthenticated*(self: AccessInterface, password: string, pin: string) {.base.} = method onUserAuthenticated*(self: AccessInterface, password: string, pin: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -281,6 +281,11 @@ method authenticateAndTransfer*(self: Module, fromAddr: string, toAddr: string,
else: else:
self.controller.authenticate() 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) =
self.tmpSendTransactionDetails.paths = rawPaths.convertToTransactionPathsDto()
self.authenticateAndTransfer(fromAddr, toAddr, assetKey, toAssetKey, uuid, sendType, selectedTokenName, selectedTokenIsOwnerToken)
method onUserAuthenticated*(self: Module, password: string, pin: string) = method onUserAuthenticated*(self: Module, password: string, pin: string) =
if password.len == 0: if password.len == 0:
self.transactionWasSent(chainId = 0, txHash = "", uuid = self.tmpSendTransactionDetails.uuid, error = authenticationCanceled) self.transactionWasSent(chainId = 0, txHash = "", uuid = self.tmpSendTransactionDetails.uuid, error = authenticationCanceled)
@ -333,8 +338,8 @@ method transactionWasSent*(self: Module, chainId: int, txHash, uuid, error: stri
self.view.sendTransactionSentSignal(chainId, txHash, uuid, error) self.view.sendTransactionSentSignal(chainId, txHash, uuid, error)
method suggestedRoutes*(self: Module, accountFrom: string, accountTo: string, amount: UInt256, token: string, toToken: string, method suggestedRoutes*(self: Module, accountFrom: string, accountTo: string, amount: UInt256, token: string, toToken: string,
disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: SendType, lockedInAmounts: string): string = disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: SendType, lockedInAmounts: string) =
return self.controller.suggestedRoutes(accountFrom, accountTo, amount, token, toToken, disabledFromChainIDs, self.controller.suggestedRoutes(accountFrom, accountTo, amount, token, toToken, disabledFromChainIDs,
disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts) disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts)
method suggestedRoutesReady*(self: Module, suggestedRoutes: SuggestedRoutesDto) = method suggestedRoutesReady*(self: Module, suggestedRoutes: SuggestedRoutesDto) =
@ -351,7 +356,8 @@ method suggestedRoutesReady*(self: Module, suggestedRoutes: SuggestedRoutesDto)
suggestedRoutes = suggestedRouteModel, suggestedRoutes = suggestedRouteModel,
gasTimeEstimate = gasTimeEstimate, gasTimeEstimate = gasTimeEstimate,
amountToReceive = suggestedRoutes.amountToReceive, amountToReceive = suggestedRoutes.amountToReceive,
toNetworksModel = toNetworksModel) toNetworksModel = toNetworksModel,
rawPaths = suggestedRoutes.rawBest)
self.view.setTransactionRoute(transactionRoutes) self.view.setTransactionRoute(transactionRoutes)
method filterChanged*(self: Module, addresses: seq[string], chainIds: seq[int]) = method filterChanged*(self: Module, addresses: seq[string], chainIds: seq[int]) =

View File

@ -8,18 +8,21 @@ QtObject:
gasTimeEstimate: GasEstimateItem gasTimeEstimate: GasEstimateItem
amountToReceive: UInt256 amountToReceive: UInt256
toNetworksModel: NetworkModel toNetworksModel: NetworkModel
rawPaths: string
proc setup*(self: TransactionRoutes, proc setup*(self: TransactionRoutes,
suggestedRoutes: SuggestedRouteModel, suggestedRoutes: SuggestedRouteModel,
gasTimeEstimate: GasEstimateItem, gasTimeEstimate: GasEstimateItem,
amountToReceive: UInt256, amountToReceive: UInt256,
toNetworksModel: NetworkModel toNetworksModel: NetworkModel,
rawPaths: string
) = ) =
self.QObject.setup self.QObject.setup
self.suggestedRoutes = suggestedRoutes self.suggestedRoutes = suggestedRoutes
self.gasTimeEstimate = gasTimeEstimate self.gasTimeEstimate = gasTimeEstimate
self.amountToReceive = amountToReceive self.amountToReceive = amountToReceive
self.toNetworksModel = toNetworksModel self.toNetworksModel = toNetworksModel
self.rawPaths = rawPaths
proc delete*(self: TransactionRoutes) = proc delete*(self: TransactionRoutes) =
self.QObject.delete self.QObject.delete
@ -28,10 +31,11 @@ QtObject:
suggestedRoutes: SuggestedRouteModel = newSuggestedRouteModel(), suggestedRoutes: SuggestedRouteModel = newSuggestedRouteModel(),
gasTimeEstimate: GasEstimateItem = newGasEstimateItem(), gasTimeEstimate: GasEstimateItem = newGasEstimateItem(),
amountToReceive: UInt256 = stint.u256(0), amountToReceive: UInt256 = stint.u256(0),
toNetworksModel: NetworkModel = newNetworkModel() toNetworksModel: NetworkModel = newNetworkModel(),
rawPaths: string = ""
): TransactionRoutes = ): TransactionRoutes =
new(result, delete) new(result, delete)
result.setup(suggestedRoutes, gasTimeEstimate, amountToReceive, toNetworksModel) result.setup(suggestedRoutes, gasTimeEstimate, amountToReceive, toNetworksModel, rawPaths)
proc `$`*(self: TransactionRoutes): string = proc `$`*(self: TransactionRoutes): string =
result = fmt"""TransactionRoutes( result = fmt"""TransactionRoutes(
@ -39,6 +43,7 @@ QtObject:
gasTimeEstimate: {self.gasTimeEstimate}, gasTimeEstimate: {self.gasTimeEstimate},
amountToReceive: {self.amountToReceive}, amountToReceive: {self.amountToReceive},
toNetworksModel: {self.toNetworksModel}, toNetworksModel: {self.toNetworksModel},
rawPaths: {self.rawPaths},
]""" ]"""
proc suggestedRoutesChanged*(self: TransactionRoutes) {.signal.} proc suggestedRoutesChanged*(self: TransactionRoutes) {.signal.}
@ -68,3 +73,10 @@ QtObject:
QtProperty[QVariant] toNetworksModel: QtProperty[QVariant] toNetworksModel:
read = getToNetworks read = getToNetworks
notify = toNetworksChanged notify = toNetworksChanged
proc rawPathsChanged*(self: TransactionRoutes) {.signal.}
proc getRawPaths*(self: TransactionRoutes): string {.slot.} =
return self.rawPaths
QtProperty[string] rawPaths:
read = getRawPaths
notify = rawPathsChanged

View File

@ -218,6 +218,20 @@ QtObject:
proc sendTransactionSentSignal*(self: View, chainId: int, txHash: string, uuid: string, error: string) = proc sendTransactionSentSignal*(self: View, chainId: int, txHash: string, uuid: string, error: string) =
self.transactionSent(chainId, txHash, uuid, error) self.transactionSent(chainId, txHash, uuid, error)
proc parseAmount(amount: string): Uint256 =
var parsedAmount = stint.u256(0)
try:
parsedAmount = amount.parse(Uint256)
except Exception as e:
discard
return parsedAmount
proc parseChainIds(chainIds: string): seq[int] =
var parsedChainIds: seq[int] = @[]
for chainId in chainIds.split(':'):
parsedChainIds.add(chainId.parseInt())
return parsedChainIds
proc authenticateAndTransfer*(self: View, uuid: string) {.slot.} = proc authenticateAndTransfer*(self: View, uuid: string) {.slot.} =
self.delegate.authenticateAndTransfer(self.selectedSenderAccount.address(), self.selectedRecipient, self.selectedAssetKey, self.delegate.authenticateAndTransfer(self.selectedSenderAccount.address(), self.selectedRecipient, self.selectedAssetKey,
self.selectedToAssetKey, uuid, self.sendType, self.selectedTokenName, self.selectedTokenIsOwnerToken) self.selectedToAssetKey, uuid, self.sendType, self.selectedTokenName, self.selectedTokenIsOwnerToken)
@ -227,15 +241,9 @@ QtObject:
self.transactionRoutes = routes self.transactionRoutes = routes
self.suggestedRoutesReady(newQVariant(self.transactionRoutes)) self.suggestedRoutesReady(newQVariant(self.transactionRoutes))
proc suggestedRoutes*(self: View, amount: string): string {.slot.} = proc suggestedRoutes*(self: View, amount: string) {.slot.} =
var parsedAmount = stint.u256(0) self.delegate.suggestedRoutes(self.selectedSenderAccount.address(), self.selectedRecipient,
try: parseAmount(amount), self.selectedAssetKey, self.selectedToAssetKey, self.fromNetworksModel.getRouteDisabledNetworkChainIds(),
parsedAmount = amount.parse(Uint256)
except Exception as e:
discard
return self.delegate.suggestedRoutes(self.selectedSenderAccount.address(), self.selectedRecipient,
parsedAmount, self.selectedAssetKey, self.selectedToAssetKey, self.fromNetworksModel.getRouteDisabledNetworkChainIds(),
self.toNetworksModel.getRouteDisabledNetworkChainIds(), self.toNetworksModel.getRoutePreferredNetworkChainIds(), self.toNetworksModel.getRouteDisabledNetworkChainIds(), self.toNetworksModel.getRoutePreferredNetworkChainIds(),
self.sendType, self.fromNetworksModel.getRouteLockedChainIds()) self.sendType, self.fromNetworksModel.getRouteLockedChainIds())
@ -322,3 +330,16 @@ QtObject:
proc getIconUrl*(self: View, chainId: int): string {.slot.} = proc getIconUrl*(self: View, chainId: int): string {.slot.} =
return self.fromNetworksModel.getIconUrl(chainId) return self.fromNetworksModel.getIconUrl(chainId)
# "Stateless" methods
proc fetchSuggestedRoutesWithParameters*(self: View, accountFrom: string, accountTo: string, amount: string, token: string, toToken: string,
disabledFromChainIDs: string, disabledToChainIDs: string, preferredChainIDs: string, sendType: int, lockedInAmounts: string) {.slot.} =
self.delegate.suggestedRoutes(accountFrom, accountTo,
parseAmount(amount), token, toToken,
parseChainIds(disabledFromChainIDs), parseChainIds(disabledToChainIDs), parseChainIds(preferredChainIDs),
SendType(sendType), lockedInAmounts)
proc authenticateAndTransferWithParameters*(self: View, uuid: string, accountFrom: string, accountTo: string, token: string, toToken: string,
sendType: int, tokenName: string, tokenIsOwnerToken: bool, rawPaths: string) {.slot.} =
self.delegate.authenticateAndTransferWithPaths(accountFrom, accountTo, token,
toToken, uuid, SendType(sendType), tokenName, tokenIsOwnerToken, rawPaths)

View File

@ -20,6 +20,7 @@ type
ERC721Transfer ERC721Transfer
ERC1155Transfer ERC1155Transfer
Swap Swap
Approve
type type
PendingTransactionTypeDto* {.pure.} = enum PendingTransactionTypeDto* {.pure.} = enum
@ -325,6 +326,15 @@ proc convertToTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto =
discard jsonObj.getProp("approvalGasFees", result.approvalGasFees) discard jsonObj.getProp("approvalGasFees", result.approvalGasFees)
discard jsonObj.getProp("approvalContractAddress", result.approvalContractAddress) discard jsonObj.getProp("approvalContractAddress", result.approvalContractAddress)
proc convertToTransactionPathsDto*(jsonObj: JsonNode): seq[TransactionPathDto] =
result = @[]
for path in jsonObj.getElems():
result.add(path.convertToTransactionPathDto())
return result
proc convertToTransactionPathsDto*(paths: string): seq[TransactionPathDto] =
return paths.parseJson.convertToTransactionPathsDto()
type type
FeesDto* = ref object FeesDto* = ref object
totalFeesInEth*: float totalFeesInEth*: float
@ -369,6 +379,7 @@ proc convertSendToNetwork*(jsonObj: JsonNode): SendToNetwork =
type type
SuggestedRoutesDto* = ref object SuggestedRoutesDto* = ref object
best*: seq[TransactionPathDto] best*: seq[TransactionPathDto]
rawBest*: string
gasTimeEstimate*: FeesDto gasTimeEstimate*: FeesDto
amountToReceive*: UInt256 amountToReceive*: UInt256
toNetworks*: seq[SendToNetwork] toNetworks*: seq[SendToNetwork]
@ -376,6 +387,7 @@ type
proc `$`*(self: SuggestedRoutesDto): string = proc `$`*(self: SuggestedRoutesDto): string =
return fmt"""SuggestedRoutesDto( return fmt"""SuggestedRoutesDto(
best:{self.best}, best:{self.best},
rawBest:{self.rawBest},
gasTimeEstimate:{self.gasTimeEstimate}, gasTimeEstimate:{self.gasTimeEstimate},
amountToReceive:{self.amountToReceive}, amountToReceive:{self.amountToReceive},
toNetworks:{self.toNetworks}, toNetworks:{self.toNetworks},
@ -383,7 +395,8 @@ proc `$`*(self: SuggestedRoutesDto): string =
proc convertToSuggestedRoutesDto*(jsonObj: JsonNode): SuggestedRoutesDto = proc convertToSuggestedRoutesDto*(jsonObj: JsonNode): SuggestedRoutesDto =
result = SuggestedRoutesDto() result = SuggestedRoutesDto()
result.best = jsonObj["suggestedRoutes"]["best"].getElems().map(x => x.convertToTransactionPathDto()) result.rawBest = $jsonObj["suggestedRoutes"]["best"]
result.best = result.rawBest.convertToTransactionPathsDto()
result.gasTimeEstimate = jsonObj["suggestedRoutes"]["gasTimeEstimate"].convertToFeesDto() result.gasTimeEstimate = jsonObj["suggestedRoutes"]["gasTimeEstimate"].convertToFeesDto()
result.amountToReceive = stint.u256(jsonObj["suggestedRoutes"]["amountToReceive"].getStr) result.amountToReceive = stint.u256(jsonObj["suggestedRoutes"]["amountToReceive"].getStr)
result.toNetworks = jsonObj["suggestedRoutes"]["toNetworks"].getElems().map(x => x.convertSendToNetwork()) result.toNetworks = jsonObj["suggestedRoutes"]["toNetworks"].getElems().map(x => x.convertSendToNetwork())

View File

@ -325,6 +325,15 @@ QtObject:
proc isCollectiblesTransfer(self: Service, sendType: SendType): bool = proc isCollectiblesTransfer(self: Service, sendType: SendType): bool =
return sendType == ERC721Transfer or sendType == ERC1155Transfer 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
else:
return transactions.MultiTransactionType.MultiTransactionSend
proc transferEth( proc transferEth(
self: Service, self: Service,
from_addr: string, from_addr: string,
@ -364,12 +373,9 @@ QtObject:
fromAsset: tokenSymbol, fromAsset: tokenSymbol,
toAsset: toTokenSymbol, toAsset: toTokenSymbol,
fromAmount: "0x" & totalAmountToSend.toHex, fromAmount: "0x" & totalAmountToSend.toHex,
multiTxType: transactions.MultiTransactionType.MultiTransactionSend, multiTxType: sendTypeToMultiTxType(sendType),
) )
if sendType == Swap:
mtCommand.multiTxType = transactions.MultiTransactionType.MultiTransactionSwap
let response = transactions.createMultiTransaction( let response = transactions.createMultiTransaction(
mtCommand, mtCommand,
paths, paths,
@ -407,7 +413,7 @@ QtObject:
toAddress: to_addr, toAddress: to_addr,
fromAsset: if not asset.isNil: asset.symbol else: assetKey, fromAsset: if not asset.isNil: asset.symbol else: assetKey,
toAsset: if not toAsset.isNil: toAsset.symbol else: toAssetKey, toAsset: if not toAsset.isNil: toAsset.symbol else: toAssetKey,
multiTxType: transactions.MultiTransactionType.MultiTransactionSend, multiTxType: sendTypeToMultiTxType(sendType),
) )
# if collectibles transfer ... # if collectibles transfer ...
@ -421,9 +427,6 @@ QtObject:
error "Invalid assetKey for collectibles transfer", assetKey=assetKey error "Invalid assetKey for collectibles transfer", assetKey=assetKey
return return
if sendType == Swap:
mtCommand.multiTxType = transactions.MultiTransactionType.MultiTransactionSwap
try: try:
for route in routes: for route in routes:
var txData = TransactionDataDto() var txData = TransactionDataDto()
@ -449,6 +452,11 @@ QtObject:
paths.add(approvalPath) paths.add(approvalPath)
totalAmountToSend += route.amountIn totalAmountToSend += route.amountIn
if sendType == SendType.Approve:
# We only do the approvals
continue
let transfer = Transfer( let transfer = Transfer(
to: parseAddress(mtCommand.toAddress), to: parseAddress(mtCommand.toAddress),
value: route.amountIn, value: route.amountIn,
@ -558,7 +566,7 @@ QtObject:
self.events.emit(SIGNAL_SUGGESTED_ROUTES_READY, SuggestedRoutesArgs(suggestedRoutes: suggestedRoutesDto)) self.events.emit(SIGNAL_SUGGESTED_ROUTES_READY, SuggestedRoutesArgs(suggestedRoutes: suggestedRoutesDto))
proc suggestedRoutes*(self: Service, accountFrom: string, accountTo: string, amount: Uint256, token: string, toToken: string, proc suggestedRoutes*(self: Service, accountFrom: string, accountTo: string, amount: Uint256, token: string, toToken: string,
disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: SendType, lockedInAmounts: string): SuggestedRoutesDto = disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: SendType, lockedInAmounts: string) =
var var
tokenId: string tokenId: string
toTokenId: string toTokenId: string

View File

@ -11,7 +11,8 @@ type
MultiTransactionType* = enum MultiTransactionType* = enum
MultiTransactionSend = 0, MultiTransactionSend = 0,
MultiTransactionSwap = 1, MultiTransactionSwap = 1,
MultiTransactionBridge = 2 MultiTransactionBridge = 2,
MultiTransactionApprove = 3
MultiTransactionCommandDto* = ref object of RootObj MultiTransactionCommandDto* = ref object of RootObj
fromAddress* {.serializedFieldName("fromAddress").}: string fromAddress* {.serializedFieldName("fromAddress").}: string

View File

@ -95,6 +95,13 @@ SplitView {
readonly property var accounts: d.accountsModel readonly property var accounts: d.accountsModel
readonly property var flatNetworks: d.flatNetworksModel readonly property var flatNetworks: d.flatNetworksModel
readonly property bool areTestNetworksEnabled: areTestNetworksEnabledCheckbox.checked readonly property bool areTestNetworksEnabled: areTestNetworksEnabledCheckbox.checked
signal suggestedRoutesReady(var txRoutes)
function fetchSuggestedRoutes(accountFrom, accountTo, amount, tokenFrom, tokenTo,
disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts) {}
function authenticateAndTransfer(uuid, accountFrom, accountTo,
tokenFrom, tokenTo, sendType, tokenName, tokenIsOwnerToken, paths) {}
} }
walletAssetsStore: WalletAssetsStore { walletAssetsStore: WalletAssetsStore {
id: thisWalletAssetStore id: thisWalletAssetStore

View File

@ -55,6 +55,10 @@ QtObject {
return modelToArray(model, [role]).map(entry => entry[role]) return modelToArray(model, [role]).map(entry => entry[role])
} }
function joinModelEntries(model, role, separator) {
return modelToFlatArray(model, role).join(separator)
}
function indexOf(model, role, key) { function indexOf(model, role, key) {
if (!model) if (!model)
return -1 return -1

View File

@ -4,8 +4,10 @@ import QtQml.Models 2.15
import utils 1.0 import utils 1.0
import StatusQ.Controls 0.1
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as SQUtils
import StatusQ.Popups.Dialog 0.1 import StatusQ.Popups.Dialog 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
@ -108,6 +110,36 @@ StatusDialog {
StatusBaseText { StatusBaseText {
text: qsTr("to token amount: %1").arg(swapInputParamsForm.toTokenAmount) text: qsTr("to token amount: %1").arg(swapInputParamsForm.toTokenAmount)
} }
StatusButton {
text: "Fetch Suggested Routes"
onClicked: {
swapAdaptor.fetchSuggestedRoutes()
}
}
StatusButton {
text: "Send Approve Tx"
onClicked: {
swapAdaptor.sendApproveTx()
}
}
StatusButton {
text: "Send Swap Tx"
onClicked: {
swapAdaptor.sendSwapTx()
}
}
StatusScrollView {
Layout.fillWidth: true
Layout.preferredHeight: 200
StatusTextArea {
text: {
let routes = SQUtils.ModelUtils.modelToArray(swapAdaptor.suggestedRoutes)
let routesString = JSON.stringify(routes, null, " ")
return qsTr("Suggested routes: \n%1").arg(routesString)
}
}
}
// End temporary placeholders // End temporary placeholders
EditSlippagePanel { EditSlippagePanel {

View File

@ -26,6 +26,28 @@ QObject {
readonly property var fromToken: ModelUtils.getByKey(root.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel, "key", root.swapFormData.fromTokensKey) readonly property var fromToken: ModelUtils.getByKey(root.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel, "key", root.swapFormData.fromTokensKey)
readonly property var toToken: ModelUtils.getByKey(root.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel, "key", root.swapFormData.toTokenKey) readonly property var toToken: ModelUtils.getByKey(root.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel, "key", root.swapFormData.toTokenKey)
readonly property alias suggestedRoutes: d.suggestedRoutes
QtObject {
id: d
property string uuid
// TODO: Remove these properties swap proposal is properly handled
property var suggestedRoutes
property string rawPaths
}
Connections {
target: root.swapStore
function onSuggestedRoutesReady(txRoutes) {
root.swapProposalReady = txRoutes.suggestedRoutes.count > 0
root.swapProposalLoading = false
d.suggestedRoutes = txRoutes.suggestedRoutes
d.rawPaths = txRoutes.rawPaths
}
}
readonly property var nonWatchAccounts: SortFilterProxyModel { readonly property var nonWatchAccounts: SortFilterProxyModel {
sourceModel: root.swapStore.accounts sourceModel: root.swapStore.accounts
filters: ValueFilter { filters: ValueFilter {
@ -72,6 +94,21 @@ QObject {
return root.currencyStore.formatCurrencyAmountFromBigInt(balance, symbol, decimals) return root.currencyStore.formatCurrencyAmountFromBigInt(balance, symbol, decimals)
} }
function getAllChainIds() {
return ModelUtils.joinModelEntries(root.filteredFlatNetworksModel, "chainId", ":")
}
function getDisabledChainIds(enabledChainId) {
let disabledChainIds = []
let chainIds = ModelUtils.modelToFlatArray(root.filteredFlatNetworksModel, "chainId")
for (let i = 0; i < chainIds.length; i++) {
if (chainIds[i] !== enabledChainId) {
disabledChainIds.push(chainIds[i])
}
}
return disabledChainIds.join(":")
}
// TODO: remove once the AccountsModalHeader is reworked!! // TODO: remove once the AccountsModalHeader is reworked!!
function getSelectedAccount(index) { function getSelectedAccount(index) {
if (root.nonWatchAccounts.count > 0 && index >= 0) { if (root.nonWatchAccounts.count > 0 && index >= 0) {
@ -198,4 +235,42 @@ QObject {
} }
return totalBalance return totalBalance
} }
function fetchSuggestedRoutes() {
root.swapProposalReady = false
root.swapProposalLoading = true
// Identify new swap with a different uuid
d.uuid = Utils.uuid()
let account = getSelectedAccount(root.swapFormData.selectedAccountIndex)
let accountAddress = account.address
let disabledChainIds = getDisabledChainIds(root.swapFormData.selectedNetworkChainId)
let preferedChainIds = getAllChainIds()
// TODO #14825: amount should be in BigInt string representation (fromTokenAmount * 10^decimals)
// Make sure that's replaced when the input component is integrated
root.swapStore.fetchSuggestedRoutes(accountAddress, accountAddress,
root.swapFormData.fromTokenAmount, root.swapFormData.fromTokensKey, root.swapFormData.toTokenKey,
disabledChainIds, disabledChainIds, preferedChainIds,
Constants.SendType.Swap, "")
}
function sendApproveTx() {
let account = getSelectedAccount(root.swapFormData.selectedAccountIndex)
let accountAddress = account.address
root.swapStore.authenticateAndTransfer(d.uuid, accountAddress, accountAddress,
root.swapFormData.fromTokensKey, root.swapFormData.toTokenKey,
Constants.SendType.Approve, "", false, d.rawPaths)
}
function sendSwapTx() {
let account = getSelectedAccount(root.swapFormData.selectedAccountIndex)
let accountAddress = account.address
root.swapStore.authenticateAndTransfer(d.uuid, accountAddress, accountAddress,
root.swapFormData.fromTokensKey, root.swapFormData.toTokenKey,
Constants.SendType.Swap, "", false, d.rawPaths)
}
} }

View File

@ -1,5 +1,8 @@
import QtQuick 2.15 import QtQuick 2.15
import StatusQ 0.1
import StatusQ.Core.Utils 0.1
QtObject { QtObject {
id: root id: root
@ -8,4 +11,30 @@ QtObject {
readonly property var accounts: walletSectionAccounts.accounts readonly property var accounts: walletSectionAccounts.accounts
readonly property var flatNetworks: networksModule.flatNetworks readonly property var flatNetworks: networksModule.flatNetworks
readonly property bool areTestNetworksEnabled: networksModule.areTestNetworksEnabled readonly property bool areTestNetworksEnabled: networksModule.areTestNetworksEnabled
/* TODO: Send module should be reworked into a lighter, generic, "stateless" module.
Remove these and use the new TransactorStore in SwapModalAdaptor when that happens. */
readonly property var walletSectionSendInst: walletSectionSend
signal suggestedRoutesReady(var txRoutes)
readonly property Connections walletSectionSendConnections: Connections {
target: root.walletSectionSendInst
function onSuggestedRoutesReady(txRoutes) {
root.suggestedRoutesReady(txRoutes)
}
}
function fetchSuggestedRoutes(accountFrom, accountTo, amount, tokenFrom, tokenTo,
disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts) {
const value = AmountsArithmetic.fromNumber(amount)
root.walletSectionSendInst.fetchSuggestedRoutesWithParameters(accountFrom, accountTo, value.toFixed(),
tokenFrom, tokenTo, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts)
}
function authenticateAndTransfer(uuid, accountFrom, accountTo,
tokenFrom, tokenTo, sendType, tokenName, tokenIsOwnerToken, paths) {
root.walletSectionSendInst.authenticateAndTransferWithParameters(uuid, accountFrom, accountTo,
tokenFrom, tokenTo, sendType, tokenName, tokenIsOwnerToken, paths)
}
} }

View File

@ -1026,6 +1026,8 @@ QtObject {
Bridge, Bridge,
ERC721Transfer, ERC721Transfer,
ERC1155Transfer, ERC1155Transfer,
Swap,
Approve,
Unknown Unknown
} }

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 27687eb8f4afea90e67811b4613761d154c43d44 Subproject commit fb63f0c1e091cd42201bea4cd4d4ffc29544d928