feat(@desktop/wallet): initial integration for swap proposal, approve tx and swap tx
Closes #14824
This commit is contained in:
parent
e8e1e08a89
commit
75d755ea0f
|
@ -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,
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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]) =
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
|
@ -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())
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1026,6 +1026,8 @@ QtObject {
|
||||||
Bridge,
|
Bridge,
|
||||||
ERC721Transfer,
|
ERC721Transfer,
|
||||||
ERC1155Transfer,
|
ERC1155Transfer,
|
||||||
|
Swap,
|
||||||
|
Approve,
|
||||||
Unknown
|
Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 27687eb8f4afea90e67811b4613761d154c43d44
|
Subproject commit fb63f0c1e091cd42201bea4cd4d4ffc29544d928
|
Loading…
Reference in New Issue