chore(@desktop/wallet): Move send modal logic over to nim side

fixes #11881
This commit is contained in:
Khushboo Mehta 2023-08-15 20:21:51 +02:00 committed by Khushboo-dev-cpp
parent db350dc36e
commit 330ccb58a6
43 changed files with 1621 additions and 812 deletions

View File

@ -88,7 +88,7 @@ proc setPubKeyGasEstimate*(self: Controller, chainId: int, ensUsername: string,
return self.ensService.setPubKeyGasEstimate(chainId, ensUsername, address)
proc setPubKey*(self: Controller, chainId: int, ensUsername: string, address: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string =
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): EnsTxResultArgs =
return self.ensService.setPubKey(chainId, ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
proc getSigningPhrase*(self: Controller): string =
@ -108,7 +108,7 @@ proc releaseEnsEstimate*(self: Controller, chainId: int, ensUsername: string, ad
proc release*(self: Controller, chainId: int, ensUsername: string, address: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool):
string =
EnsTxResultArgs =
return self.ensService.release(chainId, ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
proc setPreferredName*(self: Controller, preferredName: string) =
@ -137,7 +137,7 @@ proc registerEnsGasEstimate*(self: Controller, chainId: int, ensUsername: string
return self.ensService.registerEnsGasEstimate(chainId, ensUsername, address)
proc registerEns*(self: Controller, chainId: int, ensUsername: string, address: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string =
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): EnsTxResultArgs =
return self.ensService.registerEns(chainId, ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
proc getSNTBalance*(self: Controller): string =

View File

@ -155,26 +155,16 @@ proc setPubKey*(self: Module, password: string) =
password,
self.tmpSendEnsTransactionDetails.eip1559Enabled
)
if(response.len == 0):
info "expected response is empty", methodName="setPubKey"
return
let responseObj = response.parseJson
if (responseObj.kind != JObject):
info "expected response is not a json object", methodName="setPubKey"
return
var success: bool
if(not responseObj.getProp("success", success)):
if(not response.error.isEmptyOrWhitespace()):
info "remote call is not executed with success", methodName="setPubKey"
return
var respResult: string
if(responseObj.getProp("result", respResult)):
let item = Item(chainId: self.tmpSendEnsTransactionDetails.chainId,
ensUsername: self.tmpSendEnsTransactionDetails.ensUsername,
isPending: true)
self.view.model().addItem(item)
self.view.emitTransactionWasSentSignal(response)
let item = Item(chainId: self.tmpSendEnsTransactionDetails.chainId,
ensUsername: self.tmpSendEnsTransactionDetails.ensUsername,
isPending: true)
self.view.model().addItem(item)
self.view.emitTransactionWasSentSignal(response.chainId, response.txHash, response.error)
method releaseEnsEstimate*(self: Module, chainId: int, ensUsername: string, address: string): int =
return self.controller.releaseEnsEstimate(chainId, ensUsername, address)
@ -225,24 +215,12 @@ proc releaseEns*(self: Module, password: string) =
self.tmpSendEnsTransactionDetails.eip1559Enabled
)
if(response.len == 0):
info "expected response is empty", methodName="release"
return
let responseObj = response.parseJson
if(responseObj.kind != JObject):
info "expected response is not a json object", methodName="release"
return
var success: bool
if(not responseObj.getProp("success", success)):
if(not response.error.isEmptyOrWhitespace()):
info "remote call is not executed with success", methodName="release"
return
var result: string
if(responseObj.getProp("result", result)):
self.onEnsUsernameRemoved(self.tmpSendEnsTransactionDetails.chainId, self.tmpSendEnsTransactionDetails.ensUsername)
self.view.emitTransactionWasSentSignal(response)
self.onEnsUsernameRemoved(self.tmpSendEnsTransactionDetails.chainId, self.tmpSendEnsTransactionDetails.ensUsername)
self.view.emitTransactionWasSentSignal(response.chainId, response.txHash, response.error)
proc formatUsername(self: Module, ensUsername: string, isStatus: bool): string =
result = ensUsername
@ -334,18 +312,15 @@ proc registerEns(self: Module, password: string) =
self.tmpSendEnsTransactionDetails.eip1559Enabled
)
let responseObj = response.parseJson
if (responseObj.kind != JObject):
info "expected response is not a json object", methodName="registerEns"
if(not response.error.isEmptyOrWhitespace()):
info "remote call is not executed with success", methodName="registerEns"
return
var respResult: string
if(responseObj.getProp("result", respResult) and responseObj{"success"}.getBool == true):
let ensUsername = self.formatUsername(self.tmpSendEnsTransactionDetails.ensUsername, true)
let item = Item(chainId: self.tmpSendEnsTransactionDetails.chainId, ensUsername: ensUsername, isPending: true)
self.controller.fixPreferredName()
self.view.model().addItem(item)
self.view.emitTransactionWasSentSignal(response)
let ensUsername = self.formatUsername(self.tmpSendEnsTransactionDetails.ensUsername, true)
let item = Item(chainId: self.tmpSendEnsTransactionDetails.chainId, ensUsername: ensUsername, isPending: true)
self.controller.fixPreferredName()
self.view.model().addItem(item)
self.view.emitTransactionWasSentSignal(response.chainId, response.txHash, response.error)
method getSNTBalance*(self: Module): string =
return self.controller.getSNTBalance()
@ -416,8 +391,7 @@ method setPrefferedEnsUsername*(self: Module, ensUsername: string) =
method onUserAuthenticated*(self: Module, password: string) =
if password.len == 0:
let response = %* {"success": false, "result": cancelledRequest}
self.view.emitTransactionWasSentSignal($response)
self.view.emitTransactionWasSentSignal(chainId = 0, txHash = "", error = cancelledRequest)
else:
if self.tmpSendEnsTransactionDetails.isRegistration:
self.registerEns(password)

View File

@ -74,9 +74,9 @@ QtObject:
self.loading(false)
self.detailsObtained(chainId, ensUsername, address, pubkey, isStatus, expirationTime)
proc transactionWasSent(self: View, txResult: string) {.signal.}
proc emitTransactionWasSentSignal*(self: View, txResult: string) =
self.transactionWasSent(txResult)
proc transactionWasSent(self: View, chainId: int, txHash: string, error: string) {.signal.}
proc emitTransactionWasSentSignal*(self: View, chainId: int, txHash: string, error: string) =
self.transactionWasSent(chainId, txHash, error)
proc setPubKeyGasEstimate*(self: View, chainId: int, ensUsername: string, address: string): int {.slot.} =
return self.delegate.setPubKeyGasEstimate(chainId, ensUsername, address)

View File

@ -97,7 +97,7 @@ proc init*(self: Controller) =
let args = StickerPackInstalledArgs(e)
self.delegate.onStickerPackInstalled(args.packId)
proc buy*(self: Controller, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): tuple[response: string, success: bool] =
proc buy*(self: Controller, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): StickerBuyResultArgs =
self.stickerService.buy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
proc getRecentStickers*(self: Controller): seq[StickerDto] =

View File

@ -107,9 +107,9 @@ method authenticateAndBuy*(self: Module, packId: string, address: string, gas: s
method onUserAuthenticated*(self: Module, password: string) =
if password.len == 0:
let response = %* {"success": false, "error": cancelledRequest}
self.view.transactionWasSent($response)
self.view.transactionWasSent(chainId = 0, txHash = "", error = cancelledRequest)
else:
let responseTuple = self.controller.buy(
let response = self.controller.buy(
self.tmpBuyStickersTransactionDetails.packId,
self.tmpBuyStickersTransactionDetails.address,
self.tmpBuyStickersTransactionDetails.gas,
@ -119,11 +119,9 @@ method onUserAuthenticated*(self: Module, password: string) =
password,
self.tmpBuyStickersTransactionDetails.eip1559Enabled
)
let response = responseTuple.response
let success = responseTuple.success
if success:
if response.error.isEmptyOrWhitespace():
self.view.stickerPacks.updateStickerPackInList(self.tmpBuyStickersTransactionDetails.packId, false, true)
self.view.transactionWasSent($(%*{"success": success, "result": response}))
self.view.transactionWasSent(chainId = response.chainId, txHash = response.txHash, error = response.error)
method obtainMarketStickerPacks*(self: Module) =
self.controller.obtainMarketStickerPacks()

View File

@ -55,7 +55,7 @@ QtObject:
read = getRecentStickerList
notify = recentStickersUpdated
proc transactionWasSent*(self: View, txResult: string) {.signal.}
proc transactionWasSent*(self: View, chainId: int, txHash: string, error: string) {.signal.}
proc transactionCompleted*(self: View, success: bool, txHash: string) {.signal.}

View File

@ -44,7 +44,8 @@ proc delete*(self: Controller) =
proc init*(self: Controller) =
self.events.on(SIGNAL_TRANSACTION_SENT) do(e:Args):
self.delegate.transactionWasSent(TransactionSentArgs(e).result)
let args = TransactionSentArgs(e)
self.delegate.transactionWasSent(args.chainId, args.txHash, args.uuid, args.error)
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
let args = SharedKeycarModuleArgs(e)
@ -87,21 +88,14 @@ proc authenticateUser*(self: Controller, keyUid = "") =
keyUid: keyUid)
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
proc getEstimatedTime*(self: Controller, chainId: int, maxFeePerGas: string): EstimatedTime =
return self.transactionService.getEstimatedTime(chainId, maxFeePerGas)
proc suggestedRoutes*(self: Controller, account: string, amount: Uint256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], sendType: int, lockedInAmounts: string): string =
proc suggestedRoutes*(self: Controller, account: string, amount: Uint256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: int, lockedInAmounts: string): string =
let suggestedRoutes = self.transactionService.suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts)
return suggestedRoutes.toJson()
proc transfer*(self: Controller, from_addr: string, to_addr: string, tokenSymbol: string,
value: string, uuid: string, selectedRoutes: string, password: string) =
value: string, uuid: string, selectedRoutes: seq[TransactionPathDto], password: string) =
self.transactionService.transfer(from_addr, to_addr, tokenSymbol, value, uuid, selectedRoutes, password)
proc suggestedFees*(self: Controller, chainId: int): string =
let suggestedFees = self.transactionService.suggestedFees(chainId)
return suggestedFees.toJson()
proc areTestNetworksEnabled*(self: Controller): bool =
return self.walletAccountService.areTestNetworksEnabled()
@ -109,4 +103,7 @@ proc getTokensByAddress*(self: Controller, address: string): seq[WalletTokenDto]
return self.walletAccountService.getTokensByAddress(address)
proc getCurrencyBalance*(self: Controller, address: string, chainIds: seq[int], currency: string): float64 =
return self.walletAccountService.getCurrencyBalance(address, chainIds, currency)
return self.walletAccountService.getCurrencyBalance(address, chainIds, currency)
proc getNetworks*(self: Controller): seq[NetworkDto] =
return self.networkService.getNetworks()

View File

@ -0,0 +1,56 @@
import NimQml
QtObject:
type GasEstimateItem* = ref object of QObject
totalFeesInEth: float
totalTokenFees: float
totalTime: int
proc setup*(self: GasEstimateItem,
totalFeesInEth: float,
totalTokenFees: float,
totalTime: int
) =
self.QObject.setup
self.totalFeesInEth = totalFeesInEth
self.totalTokenFees = totalTokenFees
self.totalTime = totalTime
proc delete*(self: GasEstimateItem) =
self.QObject.delete
proc newGasEstimateItem*(
totalFeesInEth: float = 0,
totalTokenFees: float = 0,
totalTime: int = 0
): GasEstimateItem =
new(result, delete)
result.setup(totalFeesInEth, totalTokenFees, totalTime)
proc `$`*(self: GasEstimateItem): string =
result = "GasEstimateItem("
result = result & "\ntotalFeesInEth: " & $self.totalFeesInEth
result = result & "\ntotalTokenFees: " & $self.totalTokenFees
result = result & "\ntotalTime: " & $self.totalTime
result = result & ")"
proc totalFeesInEthChanged*(self: GasEstimateItem) {.signal.}
proc getTotalFeesInEth*(self: GasEstimateItem): float {.slot.} =
return self.totalFeesInEth
QtProperty[float] totalFeesInEth:
read = getTotalFeesInEth
notify = totalFeesInEthChanged
proc totalTokenFeesChanged*(self: GasEstimateItem) {.signal.}
proc getTotalTokenFees*(self: GasEstimateItem): float {.slot.} =
return self.totalTokenFees
QtProperty[float] totalTokenFees:
read = getTotalTokenFees
notify = totalTokenFeesChanged
proc totalTimeChanged*(self: GasEstimateItem) {.signal.}
proc getTotalTime*(self: GasEstimateItem): int {.slot.} =
return self.totalTime
QtProperty[int] totalTime:
read = getTotalTime
notify = totalTimeChanged

View File

@ -0,0 +1,104 @@
import NimQml, strformat
QtObject:
type GasFeesItem* = ref object of QObject
gasPrice: float
baseFee: float
maxPriorityFeePerGas: float
maxFeePerGasL: float
maxFeePerGasM: float
maxFeePerGasH: float
eip1559Enabled: bool
proc setup*(self: GasFeesItem,
gasPrice: float,
baseFee: float,
maxPriorityFeePerGas: float,
maxFeePerGasL: float,
maxFeePerGasM: float,
maxFeePerGasH: float,
eip1559Enabled: bool
) =
self.QObject.setup
self.gasPrice = gasPrice
self.baseFee = baseFee
self.maxPriorityFeePerGas = maxPriorityFeePerGas
self.maxFeePerGasL = maxFeePerGasL
self.maxFeePerGasM = maxFeePerGasM
self.maxFeePerGasH = maxFeePerGasH
self.eip1559Enabled = eip1559Enabled
proc delete*(self: GasFeesItem) =
self.QObject.delete
proc newGasFeesItem*(
gasPrice: float = 0,
baseFee: float = 0,
maxPriorityFeePerGas: float = 0,
maxFeePerGasL: float = 0,
maxFeePerGasM: float = 0,
maxFeePerGasH: float = 0,
eip1559Enabled: bool = false
): GasFeesItem =
new(result, delete)
result.setup(gasPrice, baseFee, maxPriorityFeePerGas, maxFeePerGasL, maxFeePerGasM, maxFeePerGasH, eip1559Enabled)
proc `$`*(self: GasFeesItem): string =
result = "GasFeesItem("
result = result & "\ngasPrice: " & $self.gasPrice
result = result & "\nbaseFee: " & $self.baseFee
result = result & "\nmaxPriorityFeePerGas: " & $self.maxPriorityFeePerGas
result = result & "\nmaxFeePerGasL: " & $self.maxFeePerGasL
result = result & "\nmaxFeePerGasM: " & $self.maxFeePerGasM
result = result & "\nmaxFeePerGasH: " & $self.maxFeePerGasH
result = result & "\neip1559Enabled: " & $self.eip1559Enabled
result = result & ")"
proc gasPriceChanged*(self: GasFeesItem) {.signal.}
proc getGasPrice*(self: GasFeesItem): float {.slot.} =
return self.gasPrice
QtProperty[float] gasPrice:
read = getGasPrice
notify = gasPriceChanged
proc baseFeeChanged*(self: GasFeesItem) {.signal.}
proc getBaseFee*(self: GasFeesItem): float {.slot.} =
return self.baseFee
QtProperty[float] baseFee:
read = getBaseFee
notify = baseFeeChanged
proc maxPriorityFeePerGasChanged*(self: GasFeesItem) {.signal.}
proc getMaxPriorityFeePerGas*(self: GasFeesItem): float {.slot.} =
return self.maxPriorityFeePerGas
QtProperty[float] maxPriorityFeePerGas:
read = getMaxPriorityFeePerGas
notify = maxPriorityFeePerGasChanged
proc maxFeePerGasLChanged*(self: GasFeesItem) {.signal.}
proc getMaxFeePerGasL*(self: GasFeesItem): float {.slot.} =
return self.maxFeePerGasL
QtProperty[float] maxFeePerGasL:
read = getMaxFeePerGasL
notify = maxFeePerGasLChanged
proc maxFeePerGasMChanged*(self: GasFeesItem) {.signal.}
proc getMaxFeePerGasM*(self: GasFeesItem): float {.slot.} =
return self.maxFeePerGasM
QtProperty[float] maxFeePerGasM:
read = getMaxFeePerGasM
notify = maxFeePerGasMChanged
proc maxFeePerGasHChanged*(self: GasFeesItem) {.signal.}
proc getMaxFeePerGasH*(self: GasFeesItem): float {.slot.} =
return self.maxFeePerGasH
QtProperty[float] maxFeePerGasH:
read = getMaxFeePerGasH
notify = maxFeePerGasHChanged
proc eip1559EnabledChanged*(self: GasFeesItem) {.signal.}
proc getEip1559Enabled*(self: GasFeesItem): bool {.slot.} =
return self.eip1559Enabled
QtProperty[bool] eip1559Enabled:
read = getEip1559Enabled
notify = eip1559EnabledChanged

View File

@ -1,5 +1,6 @@
import stint
import ../../../shared_models/currency_amount
import app_service/service/transaction/dto
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -20,26 +21,20 @@ method refreshWalletAccounts*(self: AccessInterface) {.base.} =
method getTokenBalanceOnChain*(self: AccessInterface, address: string, chainId: int, symbol: string): CurrencyAmount {.base.} =
raise newException(ValueError, "No implementation available")
method suggestedRoutes*(self: AccessInterface, account: string, amount: UInt256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], sendType: int, lockedInAmounts: string): string {.base.} =
method suggestedRoutes*(self: AccessInterface, account: string, amount: UInt256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: int, lockedInAmounts: string): string {.base.} =
raise newException(ValueError, "No implementation available")
method suggestedRoutesReady*(self: AccessInterface, suggestedRoutes: string) {.base.} =
raise newException(ValueError, "No implementation available")
method getEstimatedTime*(self: AccessInterface, chainId: int, maxFeePerGas: string): int {.base.} =
raise newException(ValueError, "No implementation available")
method suggestedFees*(self: AccessInterface, chainId: int): string {.base.} =
method suggestedRoutesReady*(self: AccessInterface, suggestedRoutes: SuggestedRoutesDto) {.base.} =
raise newException(ValueError, "No implementation available")
method authenticateAndTransfer*(self: AccessInterface, from_addr: string, to_addr: string,
tokenSymbol: string, value: string, uuid: string, selectedRoutes: string) {.base.} =
tokenSymbol: string, value: string, uuid: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onUserAuthenticated*(self: AccessInterface, password: string) {.base.} =
raise newException(ValueError, "No implementation available")
method transactionWasSent*(self: AccessInterface, result: string) {.base.} =
method transactionWasSent*(self: AccessInterface, chainId: int, txHash, uuid, error: string) {.base.} =
raise newException(ValueError, "No implementation available")
# View Delegate Interface

View File

@ -1,14 +1,17 @@
import tables, NimQml, sequtils, sugar, json, stint
import tables, NimQml, sequtils, sugar, json, stint, strutils
import ./io_interface, ./view, ./controller
import ./io_interface, ./view, ./controller, ./network_item, ./transaction_routes, ./suggested_route_item, ./suggested_route_model, ./gas_estimate_item, ./gas_fees_item, ./network_model
import ../io_interface as delegate_interface
import ../../../../global/global_singleton
import ../../../../core/eventemitter
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
import ../../../../../app_service/service/transaction/service as transaction_service
import ../../../shared/wallet_utils
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
import app_service/service/transaction/service as transaction_service
import app_service/service/network_connection/service
import app/modules/shared/wallet_utils
import app_service/service/transaction/dto
import app/modules/shared_models/currency_amount
export io_interface
@ -20,8 +23,8 @@ type TmpSendTransactionDetails = object
toAddr: string
tokenSymbol: string
value: string
paths: seq[TransactionPathDto]
uuid: string
selectedRoutes: string
type
Module* = ref object of io_interface.AccessInterface
@ -35,6 +38,9 @@ type
# To-do we should create a dedicated module Receive
receiveCurrentAccountIndex: int
# Forward declaration
method getTokenBalanceOnChain*(self: Module, address: string, chainId: int, symbol: string): CurrencyAmount
proc newModule*(
delegate: delegate_interface.AccessInterface,
events: EventEmitter,
@ -56,6 +62,81 @@ method delete*(self: Module) =
self.view.delete
self.controller.delete
method convertSendToNetworkToNetworkItem(self: Module, network: SendToNetwork): NetworkItem =
result = initNetworkItem(
network.chainId,
network.chainName,
network.iconUrl,
chainColor = "",
shortName = "",
layer = 0,
nativeCurrencyDecimals = 0,
nativeCurrencyName = "",
nativeCurrencySymbol = "",
true,
true,
true,
newCurrencyAmount(),
false,
lockedAmount = "",
amountIn = "",
$network.amountOut)
method convertNetworkDtoToNetworkItem(self: Module, network: NetworkDto): NetworkItem =
result = initNetworkItem(
network.chainId,
network.chainName,
network.iconUrl,
network.chainColor,
network.shortName,
network.layer,
network.nativeCurrencyDecimals,
network.nativeCurrencyName,
network.nativeCurrencySymbol,
true,
false,
true,
self.getTokenBalanceOnChain(self.view.getSelectedSenderAccountAddress(), network.chainId, self.view.getSelectedAssetSymbol())
)
method convertSuggestedFeesDtoToGasFeesItem(self: Module, gasFees: SuggestedFeesDto): GasFeesItem =
result = newGasFeesItem(
gasPrice = gasFees.gasPrice,
baseFee = gasFees.baseFee,
maxPriorityFeePerGas = gasFees.maxPriorityFeePerGas,
maxFeePerGasL = gasFees.maxFeePerGasL,
maxFeePerGasM = gasFees.maxFeePerGasM,
maxFeePerGasH = gasFees.maxFeePerGasH,
eip1559Enabled = gasFees.eip1559Enabled
)
method convertFeesDtoToGasEstimateItem(self: Module, fees: FeesDto): GasEstimateItem =
result = newGasEstimateItem(
totalFeesInEth = fees.totalFeesInEth,
totalTokenFees = fees.totalTokenFees,
totalTime = fees.totalTime
)
method convertTransactionPathDtoToSuggestedRouteItem(self: Module, path: TransactionPathDto): SuggestedRouteItem =
result = newSuggestedRouteItem(
bridgeName = path.bridgeName,
fromNetwork = path.fromNetwork.chainId,
toNetwork = path.toNetwork.chainId,
maxAmountIn = $path.maxAmountIn,
amountIn = $path.amountIn,
amountOut = $path.amountOut,
gasAmount = $path.gasAmount,
gasFees = self.convertSuggestedFeesDtoToGasFeesItem(path.gasFees),
tokenFees = path.tokenFees,
cost = path.cost,
estimatedTime = path.estimatedTime,
amountInLocked = path.amountInLocked,
isFirstSimpleTx = path.isFirstSimpleTx,
isFirstBridgeTx = path.isFirstBridgeTx,
approvalRequired = path.approvalRequired,
approvalGasFees = path.approvalGasFees
)
method refreshWalletAccounts*(self: Module) =
let walletAccounts = self.controller.getWalletAccounts()
let currency = self.controller.getCurrentCurrency()
@ -87,6 +168,12 @@ method refreshWalletAccounts*(self: Module) =
self.view.switchSenderAccount(self.senderCurrentAccountIndex)
self.view.switchReceiveAccount(self.receiveCurrentAccountIndex)
method refreshNetworks*(self: Module) =
let networks = self.controller.getNetworks()
let fromNetworks = networks.map(x => self.convertNetworkDtoToNetworkItem(x))
let toNetworks = networks.map(x => self.convertNetworkDtoToNetworkItem(x))
self.view.setNetworkItems(fromNetworks, toNetworks)
method load*(self: Module) =
singletonInstance.engine.setRootContextProperty("walletSectionSend", newQVariant(self.view))
@ -105,6 +192,7 @@ method load*(self: Module) =
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e:Args):
self.refreshWalletAccounts()
self.refreshNetworks()
self.events.on(SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT) do(e:Args):
self.refreshWalletAccounts()
@ -129,21 +217,19 @@ method isLoaded*(self: Module): bool =
method viewDidLoad*(self: Module) =
self.refreshWalletAccounts()
self.refreshNetworks()
self.moduleLoaded = true
self.delegate.sendModuleDidLoad()
method getTokenBalanceOnChain*(self: Module, address: string, chainId: int, symbol: string): CurrencyAmount =
return self.controller.getTokenBalanceOnChain(address, chainId, symbol)
method authenticateAndTransfer*(
self: Module, from_addr: string, to_addr: string, tokenSymbol: string, value: string, uuid: string, selectedRoutes: string
) =
method authenticateAndTransfer*(self: Module, from_addr: string, to_addr: string, tokenSymbol: string, value: string, uuid: string) =
self.tmpSendTransactionDetails.fromAddr = from_addr
self.tmpSendTransactionDetails.toAddr = to_addr
self.tmpSendTransactionDetails.tokenSymbol = tokenSymbol
self.tmpSendTransactionDetails.value = value
self.tmpSendTransactionDetails.uuid = uuid
self.tmpSendTransactionDetails.selectedRoutes = selectedRoutes
if singletonInstance.userProfile.getIsKeycardUser():
let keyUid = singletonInstance.userProfile.getKeyUid()
@ -174,29 +260,36 @@ method authenticateAndTransfer*(
method onUserAuthenticated*(self: Module, password: string) =
if password.len == 0:
let response = %* {"uuid": self.tmpSendTransactionDetails.uuid, "success": false, "error": cancelledRequest}
self.view.transactionWasSent($response)
self.view.transactionWasSent(chainId = 0, txHash = "", uuid = self.tmpSendTransactionDetails.uuid, error = cancelledRequest)
else:
self.controller.transfer(
self.tmpSendTransactionDetails.fromAddr, self.tmpSendTransactionDetails.toAddr,
self.tmpSendTransactionDetails.tokenSymbol, self.tmpSendTransactionDetails.value, self.tmpSendTransactionDetails.uuid,
self.tmpSendTransactionDetails.selectedRoutes, password
self.tmpSendTransactionDetails.paths, password
)
method transactionWasSent*(self: Module, result: string) =
self.view.transactionWasSent(result)
method transactionWasSent*(self: Module, chainId: int, txHash, uuid, error: string) =
self.view.transactionWasSent(chainId, txHash, uuid, error)
method suggestedFees*(self: Module, chainId: int): string =
return self.controller.suggestedFees(chainId)
method suggestedRoutes*(self: Module, account: string, amount: UInt256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], sendType: int, lockedInAmounts: string): string =
method suggestedRoutes*(self: Module, account: string, amount: UInt256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: int, lockedInAmounts: string): string =
return self.controller.suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, sendType, lockedInAmounts)
method suggestedRoutesReady*(self: Module, suggestedRoutes: string) =
self.view.suggestedRoutesReady(suggestedRoutes)
method getEstimatedTime*(self: Module, chainId: int, maxFeePerGas: string): int =
return self.controller.getEstimatedTime(chainId, maxFeePerGas).int
method suggestedRoutesReady*(self: Module, suggestedRoutes: SuggestedRoutesDto) =
self.tmpSendTransactionDetails.paths = suggestedRoutes.best
let paths = suggestedRoutes.best.map(x => self.convertTransactionPathDtoToSuggestedRouteItem(x))
let suggestedRouteModel = newSuggestedRouteModel()
suggestedRouteModel.setItems(paths)
let gasTimeEstimate = self.convertFeesDtoToGasEstimateItem(suggestedRoutes.gasTimeEstimate)
let networks = suggestedRoutes.toNetworks.map(x => self.convertSendToNetworkToNetworkItem(x))
let toNetworksModel = newNetworkModel()
toNetworksModel.setItems(networks)
self.view.updatedNetworksWithRoutes(paths, gasTimeEstimate.getTotalFeesInEth())
let transactionRoutes = newTransactionRoutes(
suggestedRoutes = suggestedRouteModel,
gasTimeEstimate = gasTimeEstimate,
amountToReceive = suggestedRoutes.amountToReceive,
toNetworksModel = toNetworksModel)
self.view.setTransactionRoute(transactionRoutes)
method filterChanged*(self: Module, addresses: seq[string], chainIds: seq[int]) =
if addresses.len == 0:

View File

@ -0,0 +1,161 @@
import strformat, strutils
import app/modules/shared_models/currency_amount
type
NetworkItem* = ref object
chainId: int
chainName: string
iconUrl: string
chainColor: string
shortName: string
layer: int
nativeCurrencyDecimals: int
nativeCurrencyName: string
nativeCurrencySymbol: string
isEnabled: bool
isPreferred: bool
hasGas: bool
tokenBalance: CurrencyAmount
locked: bool
lockedAmount: string
amountIn: string
amountOut: string
toNetworks: seq[int]
proc initNetworkItem*(
chainId: int,
chainName: string,
iconUrl: string,
chainColor: string,
shortName: string,
layer: int,
nativeCurrencyDecimals: int,
nativeCurrencyName: string,
nativeCurrencySymbol: string,
isEnabled: bool,
isPreferred: bool,
hasGas: bool,
tokenBalance: CurrencyAmount,
locked: bool = false,
lockedAmount: string = "",
amountIn: string = "",
amountOut: string = "",
toNetworks: seq[int] = @[]
): NetworkItem =
result = NetworkItem()
result.chainId = chainId
result.chainName = chainName
result.iconUrl = iconUrl
result.chainColor = chainColor
result.shortName = shortName
result.layer = layer
result.nativeCurrencyDecimals = nativeCurrencyDecimals
result.nativeCurrencyName = nativeCurrencyName
result.nativeCurrencySymbol = nativeCurrencySymbol
result.isEnabled = isEnabled
result.isPreferred = isPreferred
result.hasGas = hasGas
result.tokenBalance = tokenBalance
result.locked = locked
result.lockedAmount = lockedAmount
result.amountIn = amountIn
result.amountOut = amountOut
result.toNetworks = toNetworks
proc `$`*(self: NetworkItem): string =
result = fmt"""NetworkItem(
chainId: {self.chainId},
chainName: {self.chainName},
iconUrl:{self.iconUrl},
chainColor: {self.chainColor},
shortName: {self.shortName},
layer: {self.layer},
nativeCurrencyDecimals: {self.nativeCurrencyDecimals},
nativeCurrencyName:{self.nativeCurrencyName},
nativeCurrencySymbol:{self.nativeCurrencySymbol},
isEnabled:{self.isEnabled},
isPreferred:{self.isPreferred},
hasGas:{self.hasGas},
tokenBalance:{self.tokenBalance},
locked:{self.locked},
lockedAmount:{self.lockedAmount},
amountIn:{self.amountIn},
amountOut:{self.amountOut},
toNetworks:{self.toNetworks},
]"""
proc getChainId*(self: NetworkItem): int =
return self.chainId
proc getChainName*(self: NetworkItem): string =
return self.chainName
proc getIconURL*(self: NetworkItem): string =
return self.iconUrl
proc getShortName*(self: NetworkItem): string =
return self.shortName
proc getChainColor*(self: NetworkItem): string =
return self.chainColor
proc getLayer*(self: NetworkItem): int =
return self.layer
proc getNativeCurrencyDecimals*(self: NetworkItem): int =
return self.nativeCurrencyDecimals
proc getNativeCurrencyName*(self: NetworkItem): string =
return self.nativeCurrencyName
proc getNativeCurrencySymbol*(self: NetworkItem): string =
return self.nativeCurrencySymbol
proc getIsEnabled*(self: NetworkItem): bool =
return self.isEnabled
proc `isEnabled=`*(self: NetworkItem, value: bool) {.inline.} =
self.isEnabled = value
proc getIsPreferred*(self: NetworkItem): bool =
return self.isPreferred
proc `isPreferred=`*(self: NetworkItem, value: bool) {.inline.} =
self.isPreferred = value
proc getHasGas*(self: NetworkItem): bool =
return self.hasGas
proc `hasGas=`*(self: NetworkItem, value: bool) {.inline.} =
self.hasGas = value
proc getTokenBalance*(self: NetworkItem): CurrencyAmount =
return self.tokenBalance
proc `tokenBalance=`*(self: NetworkItem, value: CurrencyAmount) {.inline.} =
self.tokenBalance = value
proc getLocked*(self: NetworkItem): bool =
return self.locked
proc `locked=`*(self: NetworkItem, value: bool) {.inline.} =
self.locked = value
proc getLockedAmount*(self: NetworkItem): string =
return self.lockedAmount
proc `lockedAmount=`*(self: NetworkItem, value: string) {.inline.} =
self.lockedAmount = value
proc getAmountIn*(self: NetworkItem): string =
return self.amountIn
proc `amountIn=`*(self: NetworkItem, value: string) {.inline.} =
self.amountIn = value
proc getAmountOut*(self: NetworkItem): string =
return self.amountOut
proc `amountOut=`*(self: NetworkItem, value: string) {.inline.} =
self.amountOut = value
proc getToNetworks*(self: NetworkItem): string =
return self.toNetworks.join(":")
proc `toNetworks=`*(self: NetworkItem, value: int) {.inline.} =
self.toNetworks.add(value)
proc resetToNetworks*(self: NetworkItem) =
self.toNetworks = @[]

View File

@ -0,0 +1,287 @@
import NimQml, Tables, strutils, strformat, sequtils, sugar, json
import app/modules/shared_models/currency_amount
import ./network_item, ./suggested_route_item
type
ModelRole* {.pure.} = enum
ChainId = UserRole + 1,
ChainName
IconUrl
ChainColor
ShortName
Layer
NativeCurrencyDecimals
NativeCurrencyName
NativeCurrencySymbol
IsEnabled
IsPreferred
HasGas
TokenBalance
Locked
LockedAmount
AmountIn
AmountOut
ToNetworks
QtObject:
type NetworkModel* = ref object of QAbstractListModel
items*: seq[NetworkItem]
proc delete(self: NetworkModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: NetworkModel) =
self.QAbstractListModel.setup
proc newNetworkModel*(): NetworkModel =
new(result, delete)
result.setup
proc `$`*(self: NetworkModel): string =
for i in 0 ..< self.items.len:
result &= fmt"""[{i}]:({$self.items[i]})"""
proc countChanged(self: NetworkModel) {.signal.}
proc getCount(self: NetworkModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
method rowCount*(self: NetworkModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: NetworkModel): Table[int, string] =
{
ModelRole.ChainId.int:"chainId",
ModelRole.ChainName.int:"chainName",
ModelRole.IconUrl.int:"iconUrl",
ModelRole.ShortName.int: "shortName",
ModelRole.Layer.int: "layer",
ModelRole.ChainColor.int: "chainColor",
ModelRole.NativeCurrencyDecimals.int:"nativeCurrencyDecimals",
ModelRole.NativeCurrencyName.int:"nativeCurrencyName",
ModelRole.NativeCurrencySymbol.int:"nativeCurrencySymbol",
ModelRole.IsEnabled.int:"isEnabled",
ModelRole.IsPreferred.int:"isPreferred",
ModelRole.HasGas.int:"hasGas",
ModelRole.TokenBalance.int:"tokenBalance",
ModelRole.Locked.int:"locked",
ModelRole.LockedAmount.int:"lockedAmount",
ModelRole.AmountIn.int:"amountIn",
ModelRole.AmountOut.int:"amountOut",
ModelRole.ToNetworks.int:"toNetworks"
}.toTable
method data(self: NetworkModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.ChainId:
result = newQVariant(item.getChainId())
of ModelRole.ChainName:
result = newQVariant(item.getChainName())
of ModelRole.IconUrl:
result = newQVariant(item.getIconURL())
of ModelRole.ShortName:
result = newQVariant(item.getShortName())
of ModelRole.Layer:
result = newQVariant(item.getLayer())
of ModelRole.ChainColor:
result = newQVariant(item.getChainColor())
of ModelRole.NativeCurrencyDecimals:
result = newQVariant(item.getNativeCurrencyDecimals())
of ModelRole.NativeCurrencyName:
result = newQVariant(item.getNativeCurrencyName())
of ModelRole.NativeCurrencySymbol:
result = newQVariant(item.getNativeCurrencySymbol())
of ModelRole.IsEnabled:
result = newQVariant(item.getIsEnabled())
of ModelRole.IsPreferred:
result = newQVariant(item.getIsPreferred())
of ModelRole.HasGas:
result = newQVariant(item.getHasGas())
of ModelRole.TokenBalance:
result = newQVariant(item.getTokenBalance())
of ModelRole.Locked:
result = newQVariant(item.getLocked())
of ModelRole.LockedAmount:
result = newQVariant(item.getLockedAmount())
of ModelRole.AmountIn:
result = newQVariant(item.getAmountIn())
of ModelRole.AmountOut:
result = newQVariant(item.getAmountOut())
of ModelRole.ToNetworks:
result = newQVariant(item.getToNetworks())
proc setItems*(self: NetworkModel, items: seq[NetworkItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
proc getAllNetworksChainIds*(self: NetworkModel): seq[int] =
return self.items.map(x => x.getChainId())
proc getNetworkNativeGasSymbol*(self: NetworkModel, chainId: int): string =
for item in self.items:
if item.getChainId() == chainId:
return item.getNativeCurrencySymbol()
return ""
proc reset*(self: NetworkModel) =
for i in 0 ..< self.items.len:
let index = self.createIndex(i, 0, nil)
self.items[i].amountIn = ""
self.items[i].amountOut = ""
self.items[i].resetToNetworks()
self.items[i].hasGas = true
self.dataChanged(index, index, @[ModelRole.AmountIn.int])
self.dataChanged(index, index, @[ModelRole.ToNetworks.int])
self.dataChanged(index, index, @[ModelRole.HasGas.int])
self.dataChanged(index, index, @[ModelRole.AmountOut.int])
proc updateTokenBalanceForSymbol*(self: NetworkModel, chainId: int, tokenBalance: CurrencyAmount) =
for i in 0 ..< self.items.len:
if(self.items[i].getChainId() == chainId):
let index = self.createIndex(i, 0, nil)
self.items[i].tokenBalance = tokenBalance
self.dataChanged(index, index, @[ModelRole.TokenBalance.int])
proc updateFromNetworks*(self: NetworkModel, path: SuggestedRouteItem, hasGas: bool) =
for i in 0 ..< self.items.len:
if path.getfromNetwork() == self.items[i].getChainId():
let index = self.createIndex(i, 0, nil)
self.items[i].amountIn = path.getAmountIn()
self.items[i].toNetworks = path.getToNetwork()
self.items[i].hasGas = hasGas
self.items[i].locked = path.getAmountInLocked()
self.dataChanged(index, index, @[ModelRole.AmountIn.int])
self.dataChanged(index, index, @[ModelRole.ToNetworks.int])
self.dataChanged(index, index, @[ModelRole.HasGas.int])
self.dataChanged(index, index, @[ModelRole.Locked.int])
proc updateToNetworks*(self: NetworkModel, path: SuggestedRouteItem) =
for i in 0 ..< self.items.len:
if path.getToNetwork() == self.items[i].getChainId():
let index = self.createIndex(i, 0, nil)
if self.items[i].getAmountOut().len != 0:
self.items[i].amountOut = $(parseInt(self.items[i].getAmountOut()) + parseInt(path.getAmountOut()))
else:
self.items[i].amountOut = path.getAmountOut()
self.dataChanged(index, index, @[ModelRole.AmountOut.int])
proc getDisabledNetworkChainIds*(self: NetworkModel): seq[int] =
var disbaledChains: seq[int] = @[]
for item in self.items:
if not item.getIsEnabled():
disbaledChains.add(item.getChainId())
return disbaledChains
proc getLockedChainIds*(self: NetworkModel): string =
var jsonObject = newJObject()
for item in self.items:
if item.getLocked():
jsonObject[$item.getChainId()] = %* ("0x" & item.getLockedAmount())
return $jsonObject
proc updatePreferredChains*(self: NetworkModel, chainIds: string) =
try:
for i in 0 ..< self.items.len:
let index = self.createIndex(i, 0, nil)
self.items[i].isPreferred = false
self.items[i].isEnabled = false
if chainIds.len == 0:
if self.items[i].getLayer() == 1:
self.items[i].isPreferred = true
self.items[i].isEnabled = true
else:
for chainID in chainIds.split(':'):
if $self.items[i].getChainId() == chainID:
self.items[i].isPreferred = true
self.items[i].isEnabled = true
self.dataChanged(index, index, @[ModelRole.IsPreferred.int])
self.dataChanged(index, index, @[ModelRole.IsEnabled.int])
except:
discard
proc getPreferredNetworkChainIds*(self: NetworkModel): seq[int] =
var preferredChains: seq[int] = @[]
for item in self.items:
if item.getIsPreferred():
preferredChains.add(item.getChainId())
return preferredChains
proc disableUnpreferredChains*(self: NetworkModel) =
for i in 0 ..< self.items.len:
if not self.items[i].getIsPreferred():
let index = self.createIndex(i, 0, nil)
self.items[i].isEnabled = false
self.dataChanged(index, index, @[ModelRole.IsEnabled.int])
proc enableUnpreferredChains*(self: NetworkModel) =
for i in 0 ..< self.items.len:
if not self.items[i].getIsPreferred():
let index = self.createIndex(i, 0, nil)
self.items[i].isEnabled = true
self.dataChanged(index, index, @[ModelRole.IsEnabled.int])
proc setAllNetworksAsPreferredChains*(self: NetworkModel) {.slot.} =
for i in 0 ..< self.items.len:
let index = self.createIndex(i, 0, nil)
self.items[i].isPreferred = true
self.dataChanged(index, index, @[ModelRole.IsPreferred.int])
proc getNetworkColor*(self: NetworkModel, shortName: string): string {.slot.} =
for item in self.items:
if cmpIgnoreCase(item.getShortName(), shortName) == 0:
return item.getChainColor()
return ""
proc getNetworkChainId*(self: NetworkModel, shortName: string): int {.slot.} =
for item in self.items:
if cmpIgnoreCase(item.getShortName(), shortName) == 0:
return item.getChainId()
return 0
proc getNetworkName*(self: NetworkModel, chainId: int): string {.slot.} =
for item in self.items:
if item.getChainId() == chainId:
return item.getChainName()
return ""
proc toggleDisabledChains*(self: NetworkModel, chainId: int) {.slot.} =
for i in 0 ..< self.items.len:
if(self.items[i].getChainId() == chainId):
let index = self.createIndex(i, 0, nil)
self.items[i].isEnabled = not self.items[i].getIsEnabled()
self.dataChanged(index, index, @[ModelRole.IsEnabled.int])
proc setDisabledChains*(self: NetworkModel, chainId: int, disabled: bool) {.slot.} =
for i in 0 ..< self.items.len:
if(self.items[i].getChainId() == chainId):
let index = self.createIndex(i, 0, nil)
self.items[i].isEnabled = not disabled
self.dataChanged(index, index, @[ModelRole.IsEnabled.int])
proc lockCard*(self: NetworkModel, chainId: int, amount: string, lock: bool) {.slot.} =
for i in 0 ..< self.items.len:
if(self.items[i].getChainId() == chainId):
let index = self.createIndex(i, 0, nil)
self.items[i].locked = lock
self.dataChanged(index, index, @[ModelRole.Locked.int])
if self.items[i].getLocked():
self.items[i].lockedAmount = amount
self.dataChanged(index, index, @[ModelRole.LockedAmount.int])

View File

@ -0,0 +1,215 @@
import NimQml, strformat
import ./gas_fees_item
QtObject:
type SuggestedRouteItem* = ref object of QObject
bridgeName: string
fromNetwork: int
toNetwork: int
maxAmountIn: string
amountIn: string
amountOut: string
gasAmount: string
gasFees: GasFeesItem
tokenFees: float
cost: float
estimatedTime: int
amountInLocked: bool
isFirstSimpleTx: bool
isFirstBridgeTx: bool
approvalRequired: bool
approvalGasFees: float
proc setup*(self: SuggestedRouteItem,
bridgeName: string,
fromNetwork: int,
toNetwork: int,
maxAmountIn: string,
amountIn: string,
amountOut: string,
gasAmount: string,
gasFees: GasFeesItem,
tokenFees: float,
cost: float,
estimatedTime: int,
amountInLocked: bool,
isFirstSimpleTx: bool,
isFirstBridgeTx: bool,
approvalRequired: bool,
approvalGasFees: float
) =
self.QObject.setup
self.bridgeName = bridgeName
self.fromNetwork = fromNetwork
self.toNetwork = toNetwork
self.maxAmountIn = maxAmountIn
self.amountIn = amountIn
self.amountOut = amountOut
self.gasAmount = gasAmount
self.gasFees = gasFees
self.tokenFees = tokenFees
self.cost = cost
self.estimatedTime = estimatedTime
self.amountInLocked = amountInLocked
self.isFirstSimpleTx = isFirstSimpleTx
self.isFirstBridgeTx = isFirstBridgeTx
self.approvalRequired = approvalRequired
self.approvalGasFees = approvalGasFees
proc delete*(self: SuggestedRouteItem) =
self.QObject.delete
proc newSuggestedRouteItem*(
bridgeName: string = "",
fromNetwork: int = 0,
toNetwork: int = 0,
maxAmountIn: string = "",
amountIn: string = "",
amountOut: string = "",
gasAmount: string = "",
gasFees: GasFeesItem = newGasFeesItem(),
tokenFees: float = 0,
cost: float = 0,
estimatedTime: int = 0,
amountInLocked: bool = false,
isFirstSimpleTx: bool = false,
isFirstBridgeTx: bool = false,
approvalRequired: bool = false,
approvalGasFees: float = 0
): SuggestedRouteItem =
new(result, delete)
result.setup(bridgeName, fromNetwork, toNetwork, maxAmountIn, amountIn, amountOut, gasAmount, gasFees, tokenFees,
cost, estimatedTime, amountInLocked, isFirstSimpleTx, isFirstBridgeTx, approvalRequired, approvalGasFees)
proc `$`*(self: SuggestedRouteItem): string =
result = "SuggestedRouteItem("
result = result & "\nbridgeName: " & $self.bridgeName
result = result & "\nfromNetwork: " & $self.fromNetwork
result = result & "\ntoNetwork: " & $self.toNetwork
result = result & "\nmaxAmountIn: " & $self.maxAmountIn
result = result & "\namountIn: " & $self.amountIn
result = result & "\namountOut: " & $self.amountOut
result = result & "\ngasAmount: " & $self.gasAmount
result = result & "\ngasFees: " & $self.gasFees
result = result & "\ntokenFees: " & $self.tokenFees
result = result & "\ncost: " & $self.cost
result = result & "\nestimatedTime: " & $self.estimatedTime
result = result & "\namountInLocked: " & $self.amountInLocked
result = result & "\nisFirstSimpleTx: " & $self.isFirstSimpleTx
result = result & "\nisFirstBridgeTx: " & $self.isFirstBridgeTx
result = result & "\napprovalRequired: " & $self.approvalRequired
result = result & "\napprovalGasFees: " & $self.approvalGasFees
result = result & ")"
proc bridgeNameChanged*(self: SuggestedRouteItem) {.signal.}
proc getBridgeName*(self: SuggestedRouteItem): string {.slot.} =
return self.bridgeName
QtProperty[string] bridgeName:
read = getBridgeName
notify = bridgeNameChanged
proc fromNetworkChanged*(self: SuggestedRouteItem) {.signal.}
proc getfromNetwork*(self: SuggestedRouteItem): int {.slot.} =
return self.fromNetwork
QtProperty[int] fromNetwork:
read = getfromNetwork
notify = fromNetworkChanged
proc toNetworkChanged*(self: SuggestedRouteItem) {.signal.}
proc getToNetwork*(self: SuggestedRouteItem): int {.slot.} =
return self.toNetwork
QtProperty[int] toNetwork:
read = getToNetwork
notify = toNetworkChanged
proc maxAmountInChanged*(self: SuggestedRouteItem) {.signal.}
proc getMaxAmountIn*(self: SuggestedRouteItem): string {.slot.} =
return self.maxAmountIn
QtProperty[string] maxAmountIn:
read = getMaxAmountIn
notify = maxAmountInChanged
proc amountInChanged*(self: SuggestedRouteItem) {.signal.}
proc getAmountIn*(self: SuggestedRouteItem): string {.slot.} =
return self.amountIn
QtProperty[string] amountIn:
read = getAmountIn
notify = amountInChanged
proc amountOutChanged*(self: SuggestedRouteItem) {.signal.}
proc getAmountOut*(self: SuggestedRouteItem): string {.slot.} =
return self.amountOut
QtProperty[string] amountOut:
read = getAmountOut
notify = amountOutChanged
proc gasAmountChanged*(self: SuggestedRouteItem) {.signal.}
proc getGasAmount*(self: SuggestedRouteItem): string {.slot.} =
return self.gasAmount
QtProperty[string] gasAmount:
read = getGasAmount
notify = gasAmountChanged
proc gasFeesChanged*(self: SuggestedRouteItem) {.signal.}
proc getGasFees*(self: SuggestedRouteItem): QVariant {.slot.} =
return newQVariant(self.gasFees)
QtProperty[QVariant] gasFees:
read = getGasFees
notify = gasFeesChanged
proc tokenFeesChanged*(self: SuggestedRouteItem) {.signal.}
proc getTokenFees*(self: SuggestedRouteItem): float {.slot.} =
return self.tokenFees
QtProperty[float] tokenFees:
read = getTokenFees
notify = tokenFeesChanged
proc costChanged*(self: SuggestedRouteItem) {.signal.}
proc getCost*(self: SuggestedRouteItem): float {.slot.} =
return self.cost
QtProperty[float] cost:
read = getCost
notify = costChanged
proc estimatedTimeChanged*(self: SuggestedRouteItem) {.signal.}
proc getEstimatedTime*(self: SuggestedRouteItem): int {.slot.} =
return self.estimatedTime
QtProperty[int] estimatedTime:
read = getEstimatedTime
notify = estimatedTimeChanged
proc amountInLockedChanged*(self: SuggestedRouteItem) {.signal.}
proc getAmountInLocked*(self: SuggestedRouteItem): bool {.slot.} =
return self.amountInLocked
QtProperty[bool] amountInLocked:
read = getAmountInLocked
notify = amountInLockedChanged
proc isFirstSimpleTxChanged*(self: SuggestedRouteItem) {.signal.}
proc getIsFirstSimpleTx*(self: SuggestedRouteItem): bool {.slot.} =
return self.isFirstSimpleTx
QtProperty[bool] isFirstSimpleTx:
read = getIsFirstSimpleTx
notify = isFirstSimpleTxChanged
proc isFirstBridgeTxChanged*(self: SuggestedRouteItem) {.signal.}
proc getIsFirstBridgeTx*(self: SuggestedRouteItem): bool {.slot.} =
return self.isFirstBridgeTx
QtProperty[bool] isFirstBridgeTx:
read = getIsFirstBridgeTx
notify = isFirstBridgeTxChanged
proc approvalRequiredChanged*(self: SuggestedRouteItem) {.signal.}
proc getApprovalRequired*(self: SuggestedRouteItem): bool {.slot.} =
return self.approvalRequired
QtProperty[bool] approvalRequired:
read = getApprovalRequired
notify = approvalRequiredChanged
proc approvalGasFeesChanged*(self: SuggestedRouteItem) {.signal.}
proc getApprovalGasFees*(self: SuggestedRouteItem): float {.slot.} =
return self.approvalGasFees
QtProperty[float] approvalGasFees:
read = getApprovalGasFees
notify = approvalGasFeesChanged

View File

@ -0,0 +1,70 @@
import NimQml, Tables, strutils, strformat
import ./suggested_route_item
type
ModelRole {.pure.} = enum
Route = UserRole + 1,
QtObject:
type
SuggestedRouteModel* = ref object of QAbstractListModel
items*: seq[SuggestedRouteItem]
proc delete(self: SuggestedRouteModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: SuggestedRouteModel) =
self.QAbstractListModel.setup
proc newSuggestedRouteModel*(): SuggestedRouteModel =
new(result, delete)
result.setup
proc `$`*(self: SuggestedRouteModel): string =
for i in 0 ..< self.items.len:
result &= fmt"""[{i}]:({$self.items[i]})"""
proc countChanged(self: SuggestedRouteModel) {.signal.}
proc getCount*(self: SuggestedRouteModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
proc firstItem*(self: SuggestedRouteModel): QVariant {.slot.} =
let index = 0
if index < 0 or index >= self.items.len:
return newQVariant(newSuggestedRouteItem())
return newQVariant(self.items[index])
method rowCount(self: SuggestedRouteModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: SuggestedRouteModel): Table[int, string] =
{
ModelRole.Route.int:"route",
}.toTable
proc setItems*(self: SuggestedRouteModel, items: seq[SuggestedRouteItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
method data(self: SuggestedRouteModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Route:
result = newQVariant(item)

View File

@ -0,0 +1,70 @@
import NimQml, strformat, stint
import ./gas_estimate_item, ./suggested_route_model, ./network_model
QtObject:
type TransactionRoutes* = ref object of QObject
suggestedRoutes: SuggestedRouteModel
gasTimeEstimate: GasEstimateItem
amountToReceive: UInt256
toNetworksModel: NetworkModel
proc setup*(self: TransactionRoutes,
suggestedRoutes: SuggestedRouteModel,
gasTimeEstimate: GasEstimateItem,
amountToReceive: UInt256,
toNetworksModel: NetworkModel
) =
self.QObject.setup
self.suggestedRoutes = suggestedRoutes
self.gasTimeEstimate = gasTimeEstimate
self.amountToReceive = amountToReceive
self.toNetworksModel = toNetworksModel
proc delete*(self: TransactionRoutes) =
self.QObject.delete
proc newTransactionRoutes*(
suggestedRoutes: SuggestedRouteModel = newSuggestedRouteModel(),
gasTimeEstimate: GasEstimateItem = newGasEstimateItem(),
amountToReceive: UInt256 = stint.u256(0),
toNetworksModel: NetworkModel = newNetworkModel()
): TransactionRoutes =
new(result, delete)
result.setup(suggestedRoutes, gasTimeEstimate, amountToReceive, toNetworksModel)
proc `$`*(self: TransactionRoutes): string =
result = fmt"""TransactionRoutes(
suggestedRoutes: {self.suggestedRoutes},
gasTimeEstimate: {self.gasTimeEstimate},
amountToReceive: {self.amountToReceive},
toNetworksModel: {self.toNetworksModel},
]"""
proc suggestedRoutesChanged*(self: TransactionRoutes) {.signal.}
proc getSuggestedRoutes*(self: TransactionRoutes): QVariant {.slot.} =
return newQVariant(self.suggestedRoutes)
QtProperty[QVariant] suggestedRoutes:
read = getSuggestedRoutes
notify = suggestedRoutesChanged
proc gasTimeEstimateChanged*(self: TransactionRoutes) {.signal.}
proc getGasTimeEstimate*(self: TransactionRoutes): QVariant {.slot.} =
return newQVariant(self.gasTimeEstimate)
QtProperty[QVariant] gasTimeEstimate:
read = getGasTimeEstimate
notify = gasTimeEstimateChanged
proc amountToReceiveChanged*(self: TransactionRoutes) {.signal.}
proc getAmountToReceive*(self: TransactionRoutes): string {.slot.} =
return self.amountToReceive.toString()
QtProperty[string] amountToReceive:
read = getAmountToReceive
notify = amountToReceiveChanged
proc toNetworksChanged*(self: TransactionRoutes) {.signal.}
proc getToNetworks*(self: TransactionRoutes): QVariant {.slot.} =
return newQVariant(self.toNetworksModel)
QtProperty[QVariant] toNetworksModel:
read = getToNetworks
notify = toNetworksChanged

View File

@ -1,11 +1,7 @@
import NimQml, sequtils, strutils, stint, sugar
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../shared_models/token_model
import ./accounts_model
import ./account_item
import ./io_interface
import ./io_interface, ./accounts_model, ./account_item, ./network_model, ./network_item, ./suggested_route_item, ./transaction_routes
import app/modules/shared_models/token_model
QtObject:
type
@ -16,17 +12,25 @@ QtObject:
senderAccounts: AccountsModel
# for send modal
selectedSenderAccount: AccountItem
fromNetworksModel: NetworkModel
toNetworksModel: NetworkModel
transactionRoutes: TransactionRoutes
selectedAssetSymbol: string
showUnPreferredChains: bool
# for receive modal
selectedReceiveAccount: AccountItem
tmpAddress: string # shouldn't be used anywhere except in prepare*/getPrepared* procs
tmpSymbol: string # shouldn't be used anywhere except in prepare*/getPrepared* procs
tmpChainID: int # shouldn't be used anywhere except in prepare*/getPrepared* procs
# Forward declaration
proc updateNetworksDisabledChains(self: View)
proc updateNetworksTokenBalance(self: View)
proc delete*(self: View) =
self.accounts.delete
self.senderAccounts.delete
self.selectedSenderAccount.delete
self.fromNetworksModel.delete
self.toNetworksModel.delete
self.transactionRoutes.delete
self.selectedReceiveAccount.delete
self.QObject.delete
@ -36,6 +40,9 @@ QtObject:
result.delegate = delegate
result.accounts = newAccountsModel()
result.senderAccounts = newAccountsModel()
result.fromNetworksModel = newNetworkModel()
result.toNetworksModel = newNetworkModel()
result.transactionRoutes = newTransactionRoutes()
proc load*(self: View) =
self.delegate.viewDidLoad()
@ -59,6 +66,7 @@ QtObject:
return newQVariant(self.selectedSenderAccount)
proc setSelectedSenderAccount*(self: View, account: AccountItem) =
self.selectedSenderAccount = account
self.updateNetworksTokenBalance()
self.selectedSenderAccountChanged()
QtProperty[QVariant] selectedSenderAccount:
read = getSelectedSenderAccount
@ -74,6 +82,55 @@ QtObject:
read = getSelectedReceiveAccount
notify = selectedReceiveAccountChanged
proc fromNetworksModelChanged*(self: View) {.signal.}
proc getFromNetworksModel(self: View): QVariant {.slot.} =
return newQVariant(self.fromNetworksModel)
QtProperty[QVariant] fromNetworksModel:
read = getFromNetworksModel
notify = fromNetworksModelChanged
proc toNetworksModelChanged*(self: View) {.signal.}
proc getToNetworksModel(self: View): QVariant {.slot.} =
return newQVariant(self.toNetworksModel)
QtProperty[QVariant] toNetworksModel:
read = getToNetworksModel
notify = toNetworksModelChanged
proc selectedAssetSymbolChanged*(self: View) {.signal.}
proc getSelectedAssetSymbol*(self: View): string {.slot.} =
return self.selectedAssetSymbol
proc setSelectedAssetSymbol(self: View, symbol: string) {.slot.} =
self.selectedAssetSymbol = symbol
self.updateNetworksTokenBalance()
self.selectedAssetSymbolChanged()
QtProperty[string] selectedAssetSymbol:
write = setSelectedAssetSymbol
read = getSelectedAssetSymbol
notify = selectedAssetSymbolChanged
proc showUnPreferredChainsChanged*(self: View) {.signal.}
proc getShowUnPreferredChains(self: View): bool {.slot.} =
return self.showUnPreferredChains
proc toggleShowUnPreferredChains*(self: View) {.slot.} =
self.showUnPreferredChains = not self.showUnPreferredChains
self.updateNetworksDisabledChains()
self.showUnPreferredChainsChanged()
QtProperty[bool] showUnPreferredChains:
read = getShowUnPreferredChains
notify = showUnPreferredChainsChanged
proc updateNetworksDisabledChains(self: View) =
# if the setting to show unpreferred chains is toggled, add all unpreferred chains to disabled chains list
if not self.showUnPreferredChains:
self.toNetworksModel.disableUnpreferredChains()
else:
self.toNetworksModel.enableUnpreferredChains()
proc updateNetworksTokenBalance(self: View) =
for chainId in self.toNetworksModel.getAllNetworksChainIds():
self.fromNetworksModel.updateTokenBalanceForSymbol(chainId, self.delegate.getTokenBalanceOnChain(self.selectedSenderAccount.address(), chainId, self.selectedAssetSymbol))
self.toNetworksModel.updateTokenBalanceForSymbol(chainId, self.delegate.getTokenBalanceOnChain(self.selectedSenderAccount.address(), chainId, self.selectedAssetSymbol))
proc setItems*(self: View, items: seq[AccountItem]) =
self.accounts.setItems(items)
self.accountsChanged()
@ -82,72 +139,35 @@ QtObject:
self.senderAccounts.setItems(items.filter(a => a.walletType() != WalletTypeWatch))
self.senderAccountsChanged()
proc prepareTokenBalanceOnChain*(self: View, address: string, chainId: int, tokenSymbol: string) {.slot.} =
self.tmpAddress = address
self.tmpChainId = chainId
self.tmpSymbol = tokenSymbol
proc setNetworkItems*(self: View, fromNetworks: seq[NetworkItem], toNetworks: seq[NetworkItem]) =
self.fromNetworksModel.setItems(fromNetworks)
self.toNetworksModel.setItems(toNetworks)
proc getPreparedTokenBalanceOnChain*(self: View): QVariant {.slot.} =
let currencyAmount = self.delegate.getTokenBalanceOnChain(self.tmpAddress, self.tmpChainId, self.tmpSymbol)
self.tmpAddress = ""
self.tmpChainId = 0
self.tmpSymbol = "ERROR"
return newQVariant(currencyAmount)
proc transactionSent*(self: View, chainId: int, txHash: string, uuid: string, error: string) {.signal.}
proc transactionSent*(self: View, txResult: string) {.signal.}
proc transactionWasSent*(self: View,txResult: string) {.slot} =
self.transactionSent(txResult)
proc transactionWasSent*(self: View, chainId: int, txHash: string, uuid: string, error: string) {.slot} =
self.transactionSent(chainId, txHash, uuid, error)
proc authenticateAndTransfer*(self: View, from_addr: string, to_addr: string, tokenSymbol: string,
value: string, uuid: string, selectedRoutes: string) {.slot.} =
self.delegate.authenticateAndTransfer(from_addr, to_addr, tokenSymbol, value, uuid, selectedRoutes)
value: string, uuid: string) {.slot.} =
self.delegate.authenticateAndTransfer(from_addr, to_addr, tokenSymbol, value, uuid)
proc suggestedFees*(self: View, chainId: int): string {.slot.} =
return self.delegate.suggestedFees(chainId)
proc suggestedRoutes*(self: View, account: string, amount: string, token: string, disabledFromChainIDs: string, disabledToChainIDs: string, preferredChainIDs: string, sendType: int, lockedInAmounts: string): string {.slot.} =
proc suggestedRoutesReady*(self: View, suggestedRoutes: QVariant) {.signal.}
proc setTransactionRoute*(self: View, routes: TransactionRoutes) =
self.transactionRoutes = routes
self.suggestedRoutesReady(newQVariant(self.transactionRoutes))
proc suggestedRoutes*(self: View, amount: string, sendType: int): string {.slot.} =
self.fromNetworksModel.reset()
self.toNetworksModel.reset()
var parsedAmount = stint.u256("0")
var seqPreferredChainIDs = seq[uint64] : @[]
var seqDisabledFromChainIDs = seq[uint64] : @[]
var seqDisabledToChainIDs = seq[uint64] : @[]
try:
for chainID in disabledFromChainIDs.split(','):
seqDisabledFromChainIDs.add(parseUInt(chainID))
except:
discard
try:
for chainID in disabledToChainIDs.split(','):
seqDisabledToChainIDs.add(parseUInt(chainID))
except:
discard
try:
for chainID in preferredChainIDs.split(','):
seqPreferredChainIDs.add(parseUInt(chainID))
except:
discard
try:
parsedAmount = fromHex(Stuint[256], amount)
except Exception as e:
discard
return self.delegate.suggestedRoutes(account, parsedAmount, token, seqDisabledFromChainIDs, seqDisabledToChainIDs, seqPreferredChainIDs, sendType, lockedInAmounts)
proc getEstimatedTime*(self: View, chainId: int, maxFeePerGas: string): int {.slot.} =
return self.delegate.getEstimatedTime(chainId, maxFeePerGas)
proc suggestedRoutesReady*(self: View, suggestedRoutes: string) {.signal.}
proc hasGas*(self: View, address: string, chainId: int, nativeGasSymbol: string, requiredGas: float): bool {.slot.} =
for account in self.accounts.items:
if account.address() == address:
return account.getAssets().hasGas(chainId, nativeGasSymbol, requiredGas)
return false
return self.delegate.suggestedRoutes(self.selectedSenderAccount.address(),
parsedAmount, self.selectedAssetSymbol, self.fromNetworksModel.getDisabledNetworkChainIds(),
self.toNetworksModel.getDisabledNetworkChainIds(), self.toNetworksModel.getPreferredNetworkChainIds(), sendType, self.fromNetworksModel.getLockedChainIds())
proc switchSenderAccountByAddress*(self: View, address: string) =
let (account, index) = self.senderAccounts.getItemByAddress(address)
@ -178,3 +198,25 @@ QtObject:
self.setSelectetReceiveAccount(account)
self.delegate.setSelectedReceiveAccountIndex(idx)
proc updatePreferredChains*(self: View, chainIds: string) {.slot.} =
self.toNetworksModel.updatePreferredChains(chainIds)
proc getSelectedSenderAccountAddress*(self: View): string =
return self.selectedSenderAccount.address()
proc updatedNetworksWithRoutes*(self: View, paths: seq[SuggestedRouteItem], totalFeesInEth: float) =
self.fromNetworksModel.reset()
self.toNetworksModel.reset()
for path in paths:
let fromChainId = path.getfromNetwork()
let hasGas = self.selectedSenderAccount.getAssets().hasGas(fromChainId, self.fromNetworksModel.getNetworkNativeGasSymbol(fromChainId), totalFeesInEth)
self.fromNetworksModel.updateFromNetworks(path, hasGas)
self.toNetworksModel.updateToNetworks(path)
proc resetStoredProperties*(self: View) {.slot.} =
self.fromNetworksModel.reset()
self.toNetworksModel.reset()
self.transactionRoutes = newTransactionRoutes()
self.selectedAssetSymbol = ""
self.showUnPreferredChains = false

View File

@ -57,6 +57,11 @@ type
ensUsername*: string
transactionType*: string
EnsTxResultArgs* = ref object of Args
chainId*: int
txHash*: string
error*: string
# Signals which may be emitted by this service:
const SIGNAL_ENS_USERNAME_AVAILABILITY_CHECKED* = "ensUsernameAvailabilityChecked"
const SIGNAL_ENS_USERNAME_DETAILS_FETCHED* = "ensUsernameDetailsFetched"
@ -284,7 +289,7 @@ QtObject:
maxFeePerGas: string,
password: string,
eip1559Enabled: bool,
): string =
): EnsTxResultArgs =
try:
let txData = ens_utils.buildTransaction(parseAddress(address), 0.u256, gas, gasPrice,
eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
@ -300,10 +305,10 @@ QtObject:
let dto = EnsUsernameDto(chainId: chainId, username: ensUsername)
self.pendingEnsUsernames.incl(dto)
result = $(%* { "result": hash, "success": true })
result = EnsTxResultArgs(chainId: chainId, txHash: hash, error: "")
except Exception as e:
error "error occurred", procName="setPubKey", msg = e.msg
result = $(%* { "result": e.msg, "success": false })
result = EnsTxResultArgs(chainId: 0, txHash: "", error: e.msg)
proc releaseEnsEstimate*(self: Service, chainId: int, ensUsername: string, address: string): int =
try:
@ -332,7 +337,7 @@ QtObject:
maxFeePerGas: string,
password: string,
eip1559Enabled: bool
): string =
): EnsTxResultArgs =
try:
let
txData = ens_utils.buildTransaction(parseAddress(address), 0.u256, gas, gasPrice,
@ -353,10 +358,10 @@ QtObject:
let dto = EnsUsernameDto(chainId: chainId, username: ensUsername)
self.pendingEnsUsernames.excl(dto)
result = $(%* { "result": hash, "success": true })
result = EnsTxResultArgs(chainId: chainId, txHash: hash, error: "")
except Exception as e:
error "error occurred", procName="release", msg = e.msg
result = $(%* { "result": e.msg, "success": false })
result = EnsTxResultArgs(chainId: 0, txHash: "", error: e.msg)
proc registerENSGasEstimate*(self: Service, chainId: int, ensUsername: string, address: string): int =
try:
@ -383,7 +388,7 @@ QtObject:
maxFeePerGas: string,
password: string,
eip1559Enabled: bool,
): string =
): EnsTxResultArgs =
try:
let txData = ens_utils.buildTransaction(parseAddress(address), 0.u256, gas, gasPrice,
eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
@ -400,10 +405,10 @@ QtObject:
let dto = EnsUsernameDto(chainId: chainId, username: ensUsername)
self.pendingEnsUsernames.incl(dto)
result = $(%* { "result": hash, "success": true })
result = EnsTxResultArgs(chainId: chainId, txHash: hash, error: "")
except Exception as e:
error "error occurred", procName="registerEns", msg = e.msg
result = $(%* { "result": e.msg, "success": false })
result = EnsTxResultArgs(chainId: 0, txHash: "", error: e.msg)
proc getSNTBalance*(self: Service): string =
let token = self.getStatusToken()

View File

@ -54,6 +54,10 @@ type
stickers*: seq[StickerDto]
StickerPacksArgs* = ref object of Args
packs*: Table[string, StickerPackDto]
StickerBuyResultArgs* = ref object of Args
chainId*: int
txHash*: string
error*: string
# Signals which may be emitted by this service:
const SIGNAL_STICKER_PACK_LOADED* = "stickerPackLoaded"
@ -204,11 +208,10 @@ QtObject:
return self.tokenService.findTokenBySymbol(networkDto.chainId, networkDto.sntSymbol())
proc buyPack*(self: Service, packId: string, address, gas, gasPrice: string, eip1559Enabled: bool, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, success: var bool): tuple[txHash: string, error: string] =
proc buyPack*(self: Service, packId: string, address, gas, gasPrice: string, eip1559Enabled: bool, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): tuple[txHash: string, error: string] =
let
chainId = self.networkService.getNetworkForStickers().chainId
txData = buildTransaction(parseAddress(address), gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
try:
let transactionResponse = status_stickers.buy(chainId, %txData, packId, password)
let transactionHash = transactionResponse.result.getStr()
@ -232,23 +235,16 @@ QtObject:
except RpcException:
error "Error sending transaction", message = getCurrentExceptionMsg()
proc buy*(self: Service, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): tuple[response: string, success: bool] =
proc buy*(self: Service, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): StickerBuyResultArgs =
try:
status_utils.validateTransactionInput(address, address, "", "0", gas, gasPrice, "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, "ok")
except Exception as e:
error "Error buying sticker pack", msg = e.msg
return (response: e.msg, success: false)
return StickerBuyResultArgs(chainId: 0, txHash: "", error: e.msg)
var success: bool
var (response, err) = self.buyPack(packId, address, gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, password, success)
var (txHash, err) = self.buyPack(packId, address, gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, password)
if err != "":
response = err
success = false
else:
success = true
result = (response: $response, success: success)
return StickerBuyResultArgs(chainId: self.networkService.getNetworkForStickers().chainId, txHash: txHash, error: err)
proc setMarketStickerPacks*(self: Service, strickersJSON: string) {.slot.} =
let stickersResult = Json.decode(strickersJSON, tuple[packs: seq[StickerPackDto], error: string])

View File

@ -17,9 +17,9 @@ type
account: string
amount: Uint256
token: string
disabledFromChainIDs: seq[uint64]
disabledToChainIDs: seq[uint64]
preferredChainIDs: seq[uint64]
disabledFromChainIDs: seq[int]
disabledToChainIDs: seq[int]
preferredChainIDs: seq[int]
sendType: int
lockedInAmounts: string
@ -28,8 +28,8 @@ proc getGasEthValue*(gweiValue: float, gasLimit: uint64): float =
let ethValue = parseFloat(service_conversion.wei2Eth(weiValue))
return ethValue
proc getFeesTotal*(paths: seq[TransactionPathDto]): Fees =
var fees: Fees = Fees()
proc getFeesTotal*(paths: seq[TransactionPathDto]): FeesDto =
var fees: FeesDto = FeesDto()
if(paths.len == 0):
return fees
@ -65,11 +65,10 @@ proc addFirstSimpleBridgeTxFlag(paths: seq[TransactionPathDto]) : seq[Transactio
var firstBridgePath: bool = false
for path in txPaths:
if path.bridgeName == "Simple":
if not firstSimplePath:
firstSimplePath = true
path.isFirstSimpleTx = true
else:
if not firstSimplePath:
firstSimplePath = true
path.isFirstSimpleTx = true
if path.bridgeName != "Simple":
if not firstBridgePath:
firstBridgePath = false
path.isFirstBridgeTx = true
@ -84,8 +83,8 @@ const getSuggestedRoutesTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall
var lockedInAmounts = Table[string, string] : initTable[string, string]()
try:
for lockedAmount in parseJson(arg.lockedInAmounts):
lockedInAmounts[$lockedAmount["chainID"].getInt] = "0x" & lockedAmount["value"].getStr
for chainId, lockedAmount in parseJson(arg.lockedInAmounts):
lockedInAmounts[chainId] = lockedAmount.getStr
except:
discard
@ -110,7 +109,7 @@ const getSuggestedRoutesTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall
except Exception as e:
let output = %* {
"suggestedRoutes": SuggestedRoutesDto(best: @[], gasTimeEstimate: Fees(), amountToReceive: stint.u256(0), toNetworks: @[]),
"suggestedRoutes": SuggestedRoutesDto(best: @[], gasTimeEstimate: FeesDto(), amountToReceive: stint.u256(0), toNetworks: @[]),
"error": fmt"Error getting suggested routes: {e.msg}"
}
arg.finish(output)
@ -183,4 +182,4 @@ const fetchDecodedTxDataTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall
data["result"] = response.result
except Exception as e:
error "Error decoding tx input", message = e.msg
arg.finish(data)
arg.finish(data)

View File

@ -1,4 +1,4 @@
import json, strutils, stint, json_serialization, strformat
import json, strutils, stint, json_serialization, strformat, sugar, sequtils
import
web3/ethtypes
@ -284,6 +284,9 @@ proc convertToTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto =
result.amountIn = stint.u256(jsonObj{"amountIn"}.getStr)
result.amountOut = stint.u256(jsonObj{"amountOut"}.getStr)
result.estimatedTime = jsonObj{"estimatedTime"}.getInt
result.amountInLocked = jsonObj{"amountInLocked"}.getBool
result.isFirstSimpleTx = jsonObj{"isFirstSimpleTx"}.getBool
result.isFirstBridgeTx = jsonObj{"isFirstBridgeTx"}.getBool
discard jsonObj.getProp("gasAmount", result.gasAmount)
discard jsonObj.getProp("approvalRequired", result.approvalRequired)
result.approvalAmountRequired = stint.u256(jsonObj{"approvalAmountRequired"}.getStr)
@ -291,11 +294,17 @@ proc convertToTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto =
discard jsonObj.getProp("approvalContractAddress", result.approvalContractAddress)
type
Fees* = ref object
FeesDto* = ref object
totalFeesInEth*: float
totalTokenFees*: float
totalTime*: int
proc convertToFeesDto*(jsonObj: JsonNode): FeesDto =
result = FeesDto()
discard jsonObj.getProp("totalFeesInEth", result.totalFeesInEth)
discard jsonObj.getProp("totalTokenFees", result.totalTokenFees)
discard jsonObj.getProp("totalTime", result.totalTime)
type
SendToNetwork* = ref object
chainId*: int
@ -303,9 +312,23 @@ type
iconUrl*: string
amountOut*: UInt256
proc convertSendToNetwork*(jsonObj: JsonNode): SendToNetwork =
result = SendToNetwork()
discard jsonObj.getProp("chainId", result.chainId)
discard jsonObj.getProp("chainName", result.chainName)
discard jsonObj.getProp("iconUrl", result.iconUrl)
result.amountOut = stint.u256(jsonObj{"amountOut"}.getStr)
type
SuggestedRoutesDto* = ref object
best*: seq[TransactionPathDto]
gasTimeEstimate*: Fees
gasTimeEstimate*: FeesDto
amountToReceive*: UInt256
toNetworks*: seq[SendToNetwork]
proc convertToSuggestedRoutesDto*(jsonObj: JsonNode): SuggestedRoutesDto =
result = SuggestedRoutesDto()
result.best = jsonObj["suggestedRoutes"]["best"].getElems().map(x => x.convertToTransactionPathDto())
result.gasTimeEstimate = jsonObj["suggestedRoutes"]["gasTimeEstimate"].convertToFeesDto()
result.amountToReceive = stint.u256(jsonObj["suggestedRoutes"]["amountToReceive"].getStr)
result.toNetworks = jsonObj["suggestedRoutes"]["toNetworks"].getElems().map(x => x.convertSendToNetwork())

View File

@ -72,11 +72,14 @@ proc `$`*(self: TransactionMinedArgs): string =
type
TransactionSentArgs* = ref object of Args
result*: string
chainId*: int
txHash*: string
uuid*: string
error*: string
type
SuggestedRoutesArgs* = ref object of Args
suggestedRoutes*: string
suggestedRoutes*: SuggestedRoutesDto
type
CryptoServicesArgs* = ref object of Args
@ -287,11 +290,9 @@ QtObject:
for route in routes:
for hash in response.result["hashes"][$route.fromNetwork.chainID]:
self.watchTransaction(hash.getStr, from_addr, to_addr, $PendingTransactionTypeDto.WalletTransfer, " ", route.fromNetwork.chainID, track = false)
let output = %* {"result": response.result{"hashes"}, "success":true, "uuid": %uuid }
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(chainId: route.fromNetwork.chainID, txHash: hash.getStr, uuid: uuid , error: ""))
except Exception as e:
let output = %* {"success":false, "uuid": %uuid, "error":fmt"Error sending token transfer transaction: {e.msg}"}
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(chainId: 0, txHash: "", uuid: uuid, error: fmt"Error sending token transfer transaction: {e.msg}"))
proc transferToken*(
self: Service,
@ -354,11 +355,9 @@ QtObject:
for route in routes:
for hash in response.result["hashes"][$route.fromNetwork.chainID]:
self.watchTransaction(hash.getStr, from_addr, to_addr, $PendingTransactionTypeDto.WalletTransfer, " ", route.fromNetwork.chainID, track = false)
let output = %* {"result": response.result{"hashes"}, "success":true, "uuid": %uuid }
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(chainId: route.fromNetwork.chainID, txHash: hash.getStr, uuid: uuid , error: ""))
except Exception as e:
let output = %* {"success":false, "uuid": %uuid, "error":fmt"Error sending token transfer transaction: {e.msg}"}
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(chainId: 0, txHash: "", uuid: uuid, error: fmt"Error sending token transfer transaction: {e.msg}"))
proc transfer*(
self: Service,
@ -367,31 +366,27 @@ QtObject:
tokenSymbol: string,
value: string,
uuid: string,
selectedRoutes: string,
selectedRoutes: seq[TransactionPathDto],
password: string,
) =
try:
var chainID = 0
let selRoutes = parseJson(selectedRoutes)
let routes = selRoutes.getElems().map(x => x.convertToTransactionPathDto())
var isEthTx = false
if(routes.len > 0):
chainID = routes[0].fromNetwork.chainID
if(selectedRoutes.len > 0):
chainID = selectedRoutes[0].fromNetwork.chainID
let network = self.networkService.getNetwork(chainID)
if network.nativeCurrencySymbol == tokenSymbol:
isEthTx = true
if(isEthTx):
self.transferEth(from_addr, to_addr, tokenSymbol, value, uuid, routes, password)
self.transferEth(from_addr, to_addr, tokenSymbol, value, uuid, selectedRoutes, password)
else:
self.transferToken(from_addr, to_addr, tokenSymbol, value, uuid, routes, password)
self.transferToken(from_addr, to_addr, tokenSymbol, value, uuid, selectedRoutes, password)
except Exception as e:
let output = %* {"success":false, "uuid": %uuid, "error":fmt"Error sending token transfer transaction: {e.msg}"}
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(chainId: 0, txHash: "", uuid: uuid, error: fmt"Error sending token transfer transaction: {e.msg}"))
proc suggestedFees*(self: Service, chainId: int): SuggestedFeesDto =
try:
@ -401,9 +396,15 @@ QtObject:
error "Error getting suggested fees", msg = e.msg
proc suggestedRoutesReady*(self: Service, suggestedRoutes: string) {.slot.} =
self.events.emit(SIGNAL_SUGGESTED_ROUTES_READY, SuggestedRoutesArgs(suggestedRoutes: suggestedRoutes))
var suggestedRoutesDto: SuggestedRoutesDto = SuggestedRoutesDto()
try:
let responseObj = suggestedRoutes.parseJson
suggestedRoutesDto = responseObj.convertToSuggestedRoutesDto()
except Exception as e:
error "error handling suggestedRoutesReady response", errDesription=e.msg
self.events.emit(SIGNAL_SUGGESTED_ROUTES_READY, SuggestedRoutesArgs(suggestedRoutes: suggestedRoutesDto))
proc suggestedRoutes*(self: Service, account: string, amount: Uint256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], sendType: int, lockedInAmounts: string): SuggestedRoutesDto =
proc suggestedRoutes*(self: Service, account: string, amount: Uint256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: int, lockedInAmounts: string): SuggestedRoutesDto =
let arg = GetSuggestedRoutesTaskArg(
tptr: cast[ByteAddress](getSuggestedRoutesTask),
vptr: cast[ByteAddress](self.vptr),

View File

@ -28,6 +28,6 @@ proc suggestedFees*(chainId: int): RpcResponse[JsonNode] {.raises: [Exception].}
let payload = %* [chainId]
return core.callPrivateRPC("wallet_getSuggestedFees", payload)
proc suggestedRoutes*(account: string, amount: string, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], sendType: int, lockedInAmounts: var Table[string, string]): RpcResponse[JsonNode] {.raises: [Exception].} =
proc suggestedRoutes*(account: string, amount: string, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[int], sendType: int, lockedInAmounts: var Table[string, string]): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [sendType, account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, 1 , lockedInAmounts]
return core.callPrivateRPC("wallet_getSuggestedRoutes", payload)

View File

@ -53,7 +53,7 @@ SplitView {
}
}
function splitAndFormatAddressPrefix(textAddrss, isBridgeTx, showUnpreferredNetworks) {
function splitAndFormatAddressPrefix(textAddrss, isBridgeTx) {
return textAddrss
}
@ -84,8 +84,6 @@ SplitView {
return text
}
function setDefaultPreferredDisabledChains() {}
function prepareTransactionsForAddress(address) {
console.log("prepareTransactionsForAddress:", address)
}

View File

@ -29,7 +29,7 @@ Item {
cardIconName: "status"
advancedInputText: "75,0000000"
disabledText: "Disabled"
onCardLocked: locked = isLocked
onLockCard: locked = !lock
disableText: "Disable"
enableText: "Enable"
}
@ -99,7 +99,7 @@ Item {
advancedMode: card.advancedMode
advancedInputText: tokensToSend
disabledText: "Disabled"
onCardLocked: locked = isLocked
onLockCard: locked = !lock
disableText: "Disable"
enableText: "Enable"
}
@ -121,7 +121,7 @@ Item {
advancedMode: card.advancedMode
advancedInputText: tokensToReceive
disabledText: "Disabled"
onCardLocked: locked = isLocked
onLockCard: locked = !lock
disableText: "Disable"
enableText: "Enable"
}

View File

@ -176,10 +176,10 @@ Rectangle {
signal clicked()
/*!
\qmlsignal StatusCard::cardLocked
\qmlsignal StatusCard::lockCard
This signal is emitted when the card is locked or unlocked
*/
signal cardLocked(bool isLocked)
signal lockCard(bool lock)
/*!
\qmlproperty string StatusCard::state
@ -285,7 +285,6 @@ Rectangle {
}
StatusInput {
id: advancedInput
property bool tempLock: false
Layout.preferredWidth: layout.width
maximumHeight: 32
topPadding: 0
@ -305,17 +304,13 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: 12
height: 12
icon.name: root.locked && advancedInput.tempLock ? "lock" : "unlock"
icon.name: root.locked ? "lock" : "unlock"
icon.width: 12
icon.height: 12
icon.color: root.locked && advancedInput.tempLock ? Theme.palette.primaryColor1 : Theme.palette.baseColor1
icon.color: root.locked ? Theme.palette.primaryColor1 : Theme.palette.baseColor1
type: StatusFlatRoundButton.Type.Secondary
enabled: !disabled
onClicked: {
advancedInput.tempLock = !advancedInput.tempLock
root.locked = advancedInput.tempLock
root.cardLocked(advancedInput.tempLock)
}
onClicked: root.lockCard(!root.locked)
}
}
validators: [
@ -328,18 +323,13 @@ Rectangle {
}
]
text: root.preCalculatedAdvancedText
onTextChanged: {
advancedInput.tempLock = false
waitTimer.restart()
}
onTextChanged: waitTimer.restart()
Timer {
id: waitTimer
interval: lockTimeout
onTriggered: {
advancedInput.tempLock = true
if(!!advancedInput.text && root.preCalculatedAdvancedText !== advancedInput.text) {
root.locked = advancedInput.tempLock
root.cardLocked(advancedInput.tempLock)
root.lockCard(true)
}
}
}

View File

@ -142,20 +142,12 @@ QtObject {
return ensUsernamesModule.getGasEthValue(gweiValue, gasLimit)
}
function getEstimatedTime(chainId, maxFeePerGas) {
return walletSectionSend.getEstimatedTime(chainId, maxFeePerGas)
}
function getStatusToken() {
if(!root.ensUsernamesModule)
return ""
return ensUsernamesModule.getStatusToken()
}
function suggestedFees(chainId) {
return JSON.parse(walletSectionSend.suggestedFees(chainId))
}
function removeEnsUsername(chainId, ensUsername) {
if(!root.ensUsernamesModule)
return ""

View File

@ -122,8 +122,8 @@ Item {
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(0)
preSelectedAsset: store.getAsset(releaseEnsModal.store.assets, "ETH")
sendTransaction: function() {
if(bestRoutes.length === 1) {
let path = bestRoutes[0]
if(bestRoutes.count === 1) {
let path = bestRoutes.firstItem()
let eip1559Enabled = path.gasFees.eip1559Enabled
let maxFeePerGas = path.gasFees.maxFeePerGasM
root.ensUsernamesStore.authenticateAndReleaseEns(
@ -140,29 +140,22 @@ Item {
}
Connections {
target: root.ensUsernamesStore.ensUsernamesModule
function onTransactionWasSent(txResult: string) {
try {
let response = JSON.parse(txResult)
if (!response.success) {
if (response.result.includes(Constants.walletSection.cancelledMessage)) {
return
}
releaseEnsModal.sendingError.text = response.result
return releaseEnsModal.sendingError.open()
function onTransactionWasSent(chainId: int, txHash: string, error: string) {
if (!!error) {
if (error.includes(Constants.walletSection.cancelledMessage)) {
return
}
for(var i=0; i<releaseEnsModal.bestRoutes.length; i++) {
usernameReleased()
let url = "%1/%2".arg(releaseEnsModal.store.getEtherscanLink(releaseEnsModal.bestRoutes[i].fromNetwork.chainId)).arg(response.result)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
}
} catch (e) {
console.error('Error parsing the response', e)
releaseEnsModal.sendingError.text = error
return releaseEnsModal.sendingError.open()
}
usernameReleased()
let url = "%1/%2".arg(releaseEnsModal.store.getEtherscanLink(chainId)).arg(txHash)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
releaseEnsModal.close()
}
}

View File

@ -68,8 +68,8 @@ Item {
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(0)
preSelectedAsset: store.getAsset(connectEnsModal.store.assets, "ETH")
sendTransaction: function() {
if(bestRoutes.length === 1) {
let path = bestRoutes[0]
if(bestRoutes.count === 1) {
let path = bestRoutes.firstItem()
let eip1559Enabled = path.gasFees.eip1559Enabled
root.ensUsernamesStore.authenticateAndSetPubKey(
root.ensUsernamesStore.chainId,
@ -85,29 +85,22 @@ Item {
}
Connections {
target: root.ensUsernamesStore.ensUsernamesModule
function onTransactionWasSent(txResult: string) {
try {
let response = JSON.parse(txResult)
if (!response.success) {
if (response.result.includes(Constants.walletSection.cancelledMessage)) {
return
}
connectEnsModal.sendingError.text = response.result
return connectEnsModal.sendingError.open()
function onTransactionWasSent(chainId: int, txHash: string, error: string) {
if (!!error) {
if (error.includes(Constants.walletSection.cancelledMessage)) {
return
}
for(var i=0; i<connectEnsModal.bestRoutes.length; i++) {
usernameUpdated(ensUsername.text);
let url = "%1/%2".arg(connectEnsModal.store.getEtherscanLink(connectEnsModal.bestRoutes[i].fromNetwork.chainId)).arg(response.result)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
}
} catch (e) {
console.error('Error parsing the response', e)
connectEnsModal.sendingError.text = error
return connectEnsModal.sendingError.open()
}
usernameUpdated(ensUsername.text);
let url = "%1/%2".arg(connectEnsModal.store.getEtherscanLink(chainId)).arg(txHash)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
connectEnsModal.close()
}
}

View File

@ -52,8 +52,8 @@ Item {
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(10)
preSelectedAsset: store.getAsset(buyEnsModal.store.assets, JSON.parse(root.stickersStore.getStatusToken()).symbol)
sendTransaction: function() {
if(bestRoutes.length === 1) {
let path = bestRoutes[0]
if(bestRoutes.count === 1) {
let path = bestRoutes.firstItem()
let eip1559Enabled = path.gasFees.eip1559Enabled
let maxFeePerGas = path.gasFees.maxFeePerGasM
root.ensUsernamesStore.authenticateAndRegisterEns(
@ -70,29 +70,22 @@ Item {
}
Connections {
target: root.ensUsernamesStore.ensUsernamesModule
function onTransactionWasSent(txResult: string) {
try {
let response = JSON.parse(txResult)
if (!response.success) {
if (response.result.includes(Constants.walletSection.cancelledMessage)) {
function onTransactionWasSent(chainId: int, txHash: string, error: string) {
if (!!error) {
if (error.includes(Constants.walletSection.cancelledMessage)) {
return
}
buyEnsModal.sendingError.text = response.result
buyEnsModal.sendingError.text = error
return buyEnsModal.sendingError.open()
}
for(var i=0; i<buyEnsModal.bestRoutes.length; i++) {
usernameRegistered(username)
let url = "%1/%2".arg(buyEnsModal.store.getEtherscanLink(buyEnsModal.bestRoutes[i].fromNetwork.chainId)).arg(response.result)
let url = "%1/%2".arg(buyEnsModal.store.getEtherscanLink(chainId)).arg(txHash)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
}
} catch (e) {
console.error('Error parsing the response', e)
}
}
}
}

View File

@ -200,14 +200,6 @@ QtObject {
return profileSectionStore.ensUsernamesStore.getGasEthValue(gweiValue, gasLimit)
}
function suggestedFees(chainId) {
return JSON.parse(walletSectionSendInst.suggestedFees(chainId))
}
function getEstimatedTime(chainId, maxFeePerGas) {
return walletSectionSendInst.getEstimatedTime(chainId, maxFeePerGas)
}
function hex2Eth(value) {
return globalUtils.hex2Eth(value)
}

View File

@ -17,10 +17,11 @@ Item {
property string selectedTokenSymbol
property string currentCurrency
property var bestRoutes: []
property var bestRoutes
property var getGasEthValue: function () {}
property var getFiatValue: function () {}
property var formatCurrencyAmount: function () {}
property var getNetworkName: function () {}
width: parent.width
height: visible ? advancedGasSelector.height + Style.current.halfPadding : 0
@ -47,7 +48,7 @@ Item {
asset.color: Theme.palette.directColor1
statusListItemIcon.active: true
statusListItemIcon.opacity: modelData.isFirstSimpleTx
title: qsTr("%1 transaction fee").arg(modelData.fromNetwork.chainName)
title: qsTr("%1 transaction fee").arg(root.getNetworkName(modelData.fromNetwork))
subTitle: root.formatCurrencyAmount(totalGasAmountEth, "ETH")
property double totalGasAmountEth: {
let maxFees = modelData.gasFees.maxFeePerGasM
@ -64,8 +65,6 @@ Item {
text: root.formatCurrencyAmount(totalGasAmountFiat, root.currentCurrency)
font.pixelSize: 15
color: Theme.palette.baseColor1
width: listItem.width/2 - Style.current.padding
elide: Text.ElideRight
}
]
}
@ -75,19 +74,19 @@ Item {
Repeater {
model: root.bestRoutes
StatusListItem {
id: listItem
id: listItem1
color: Theme.palette.statusListItem.backgroundColor
width: parent.width
asset.name: "tiny/checkmark"
asset.color: Theme.palette.directColor1
statusListItemIcon.active: true
statusListItemIcon.opacity: modelData.isFirstSimpleTx
title: qsTr("Approve %1 %2 Bridge").arg(modelData.fromNetwork.chainName).arg(root.selectedTokenSymbol)
title: qsTr("Approve %1 %2 Bridge").arg(root.getNetworkName(modelData.fromNetwork)).arg(root.selectedTokenSymbol)
property double approvalGasFees: modelData.approvalGasFees
property string approvalGasFeesSymbol: "ETH"
property double approvalGasFeesFiat: root.getFiatValue(approvalGasFees, approvalGasFeesSymbol, root.currentCurrency)
subTitle: root.formatCurrencyAmount(approvalGasFees, approvalGasFeesSymbol)
statusListItemSubTitle.width: listItem.width/2 - Style.current.smallPadding
statusListItemSubTitle.width: listItem1.width/2 - Style.current.smallPadding
statusListItemSubTitle.elide: Text.ElideMiddle
statusListItemSubTitle.wrapMode: Text.NoWrap
visible: modelData.approvalRequired
@ -97,8 +96,6 @@ Item {
text: root.formatCurrencyAmount(approvalGasFeesFiat, root.currentCurrency)
font.pixelSize: 15
color: Theme.palette.baseColor1
width: listItem.width/2 - Style.current.padding
elide: Text.ElideRight
}
]
}
@ -116,7 +113,7 @@ Item {
asset.color: Theme.palette.directColor1
statusListItemIcon.active: true
statusListItemIcon.opacity: modelData.isFirstBridgeTx
title: qsTr("%1 -> %2 bridge").arg(modelData.fromNetwork.chainName).arg(modelData.toNetwork.chainName)
title: qsTr("%1 -> %2 bridge").arg(root.getNetworkName(modelData.fromNetwork)).arg(root.getNetworkName(modelData.toNetwork))
property double tokenFees: modelData.tokenFees
property double tokenFeesFiat: root.getFiatValue(tokenFees, root.selectedTokenSymbol, root.currentCurrency)
subTitle: root.formatCurrencyAmount(tokenFees, root.selectedTokenSymbol)
@ -129,8 +126,6 @@ Item {
text: root.formatCurrencyAmount(tokenFeesFiat, root.currentCurrency)
font.pixelSize: 15
color: Theme.palette.baseColor1
width: listItem2.width/2 - Style.current.padding
elide: Text.ElideRight
}
]
}

View File

@ -34,7 +34,6 @@ StatusDialog {
property alias modalHeader: modalHeader.text
property var store: TransactionStore{}
property var contactsStore: store.contactStore
property var currencyStore: store.currencyStore
property var selectedAccount: store.selectedSenderAccount
property var bestRoutes
@ -56,45 +55,34 @@ StatusDialog {
recipientAddress,
d.selectedSymbol,
amountToSendInput.cryptoValueToSend,
d.uuid,
JSON.stringify(popup.bestRoutes)
)
d.uuid)
}
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
if(!!popup.selectedAccount && !!assetSelector.selectedAsset && recipientLoader.ready && amountToSendInput.inputNumberValid) {
popup.isLoading = true
let amount = Math.round(amountToSendInput.cryptoValueToSend * Math.pow(10, assetSelector.selectedAsset.decimals))
popup.store.suggestedRoutes(popup.selectedAccount.address, amount.toString(16), assetSelector.selectedAsset.symbol,
store.disabledChainIdsFromList, store.disabledChainIdsToList,
store.preferredChainIds, popup.sendType, store.lockedInAmounts)
popup.store.suggestedRoutes(amount.toString(16), popup.sendType)
}
})
QtObject {
id: d
readonly property int errorType: !amountToSendInput.input.valid ? Constants.SendAmountExceedsBalance :
(networkSelector.bestRoutes && networkSelector.bestRoutes.length <= 0 && !!amountToSendInput.input.text && recipientLoader.ready && !popup.isLoading) ?
(popup.bestRoutes && popup.bestRoutes.count === 0 &&
!!amountToSendInput.input.text && recipientLoader.ready && !popup.isLoading) ?
Constants.NoRoute : Constants.NoError
readonly property double maxFiatBalance: !!assetSelector.selectedAsset ? assetSelector.selectedAsset.totalCurrencyBalance.amount : 0
readonly property double maxCryptoBalance: !!assetSelector.selectedAsset ? assetSelector.selectedAsset.totalBalance.amount : 0
readonly property double maxInputBalance: amountToSendInput.inputIsFiat ? maxFiatBalance : maxCryptoBalance
readonly property string selectedSymbol: !!assetSelector.selectedAsset ? assetSelector.selectedAsset.symbol : ""
readonly property string inputSymbol: amountToSendInput.inputIsFiat ? popup.store.currentCurrency : selectedSymbol
readonly property string selectedSymbol: store.selectedAssetSymbol
readonly property string inputSymbol: amountToSendInput.inputIsFiat ? popup.currencyStore.currentCurrency : selectedSymbol
readonly property bool errorMode: popup.isLoading || !recipientLoader.ready ? false : errorType !== Constants.NoError || networkSelector.errorMode || !amountToSendInput.inputNumberValid
readonly property string uuid: Utils.uuid()
property bool isPendingTx: false
property string totalTimeEstimate
property double totalFeesInEth
property double totalFeesInFiat
property double totalAmountToReceive
readonly property NetworkConnectionStore networkConnectionStore: NetworkConnectionStore {}
onErrorTypeChanged: {
if(errorType === Constants.SendAmountExceedsBalance)
bestRoutes = []
}
}
width: 556
@ -106,18 +94,9 @@ StatusDialog {
color: Theme.palette.baseColor3
}
onIsLoadingChanged: if(isLoading) bestRoutes = []
onSelectedAccountChanged: popup.recalculateRoutesAndFees()
onOpened: {
if(!isBridgeTx) {
store.setDefaultPreferredDisabledChains()
}
else {
store.setAllNetworksAsPreferredChains()
}
amountToSendInput.input.input.edit.forceActiveFocus()
if(!!popup.preSelectedAsset) {
@ -137,13 +116,6 @@ StatusDialog {
recipientLoader.selectedRecipientType = TabAddressSelectorView.Type.Address
recipientLoader.selectedRecipient = {address: popup.selectedAccount.address}
}
// add networks that are down to disabled list
if(d.networkConnectionStore.blockchainNetworksDown.length !== 0) {
for(let i in d.networkConnectionStore.blockchainNetworksDown) {
store.addRemoveDisabledToChain(parseInt(d.networkConnectionStore.blockchainNetworksDown[i]), true)
}
}
}
onClosed: popup.store.resetTxStoreProperties()
@ -236,6 +208,7 @@ StatusDialog {
assetSelector.selectedAsset = store.getAsset(selectedAccount.assets, assetSelector.selectedAsset.symbol)
}
onSelectedAssetChanged: {
store.setSelectedAssetSymbol(assetSelector.selectedAsset.symbol)
if (!assetSelector.selectedAsset || !amountToSendInput.inputNumberValid) {
return
}
@ -299,7 +272,7 @@ StatusDialog {
interactive: popup.interactive
selectedSymbol: d.selectedSymbol
maxInputBalance: d.maxInputBalance
currentCurrency: popup.store.currentCurrency
currentCurrency: popup.currencyStore.currentCurrency
getFiatValue: function(cryptoValue) {
return selectedSymbol ? popup.currencyStore.getFiatValue(cryptoValue, selectedSymbol, currentCurrency) : 0.0
}
@ -317,8 +290,7 @@ StatusDialog {
id: amountToReceive
Layout.alignment: Qt.AlignRight
Layout.fillWidth:true
visible: popup.bestRoutes !== undefined && popup.bestRoutes.length > 0 && amountToSendInput.inputNumberValid
store: popup.store
visible: !!popup.bestRoutes && popup.bestRoutes !== undefined && popup.bestRoutes.count > 0 && amountToSendInput.inputNumberValid
isLoading: popup.isLoading
selectedSymbol: d.selectedSymbol
isBridgeTx: popup.isBridgeTx
@ -326,7 +298,7 @@ StatusDialog {
inputIsFiat: amountToSendInput.inputIsFiat
minCryptoDecimals: amountToSendInput.minReceiveCryptoDecimals
minFiatDecimals: amountToSendInput.minReceiveFiatDecimals
currentCurrency: popup.store.currentCurrency
currentCurrency: popup.currencyStore.currentCurrency
getFiatValue: function(cryptoValue) {
return popup.currencyStore.getFiatValue(cryptoValue, selectedSymbol, currentCurrency)
}
@ -385,7 +357,6 @@ StatusDialog {
isBridgeTx: popup.isBridgeTx
interactive: popup.interactive
selectedAsset: assetSelector.selectedAsset
showUnpreferredNetworks: networkSelector.showUnpreferredNetworks
onIsLoading: popup.isLoading = true
onRecalculateRoutesAndFees: popup.recalculateRoutesAndFees()
}
@ -419,13 +390,11 @@ StatusDialog {
amountToSend: amountToSendInput.cryptoValueToSend
minSendCryptoDecimals: amountToSendInput.minSendCryptoDecimals
minReceiveCryptoDecimals: amountToSendInput.minReceiveCryptoDecimals
requiredGasInEth: d.totalFeesInEth
selectedAsset: assetSelector.selectedAsset
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
visible: recipientLoader.ready && !!assetSelector.selectedAsset && amountToSendInput.inputNumberValid
errorType: d.errorType
isLoading: popup.isLoading
bestRoutes: popup.bestRoutes
isBridgeTx: popup.isBridgeTx
}
@ -450,7 +419,7 @@ StatusDialog {
footer: SendModalFooter {
nextButtonText: popup.isBridgeTx ? qsTr("Bridge") : qsTr("Send")
maxFiatFees: popup.isLoading ? "..." : popup.currencyStore.formatCurrencyAmount(d.totalFeesInFiat, popup.store.currentCurrency)
maxFiatFees: popup.isLoading ? "..." : popup.currencyStore.formatCurrencyAmount(d.totalFeesInFiat, popup.currencyStore.currentCurrency)
totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate
pending: d.isPendingTx || popup.isLoading
visible: recipientLoader.ready && amountToSendInput.inputNumberValid && !d.errorMode
@ -464,54 +433,38 @@ StatusDialog {
Connections {
target: popup.store.walletSectionSendInst
function onSuggestedRoutesReady(suggestedRoutes: string) {
let response = JSON.parse(suggestedRoutes)
if(!!response.error) {
popup.isLoading = false
return
}
popup.bestRoutes = response.suggestedRoutes.best
let gasTimeEstimate = response.suggestedRoutes.gasTimeEstimate
function onSuggestedRoutesReady(txRoutes) {
popup.bestRoutes = txRoutes.suggestedRoutes
let gasTimeEstimate = txRoutes.gasTimeEstimate
d.totalTimeEstimate = popup.store.getLabelForEstimatedTxTime(gasTimeEstimate.totalTime)
d.totalFeesInEth = gasTimeEstimate.totalFeesInEth
d.totalFeesInFiat = popup.currencyStore.getFiatValue( gasTimeEstimate.totalFeesInEth, "ETH", popup.store.currentCurrency) +
popup.currencyStore.getFiatValue(gasTimeEstimate.totalTokenFees, fees.selectedTokenSymbol, popup.store.currentCurrency)
d.totalAmountToReceive = popup.store.getWei2Eth(response.suggestedRoutes.amountToReceive, assetSelector.selectedAsset.decimals)
networkSelector.toNetworksList = response.suggestedRoutes.toNetworks
d.totalFeesInFiat = popup.currencyStore.getFiatValue( gasTimeEstimate.totalFeesInEth, "ETH", popup.currencyStore.currentCurrency) +
popup.currencyStore.getFiatValue(gasTimeEstimate.totalTokenFees, fees.selectedTokenSymbol, popup.currencyStore.currentCurrency)
d.totalAmountToReceive = popup.store.getWei2Eth(txRoutes.amountToReceive, assetSelector.selectedAsset.decimals)
networkSelector.toNetworksList = txRoutes.toNetworksModel
popup.isLoading = false
}
}
Connections {
target: popup.store.walletSectionSendInst
function onTransactionSent(txResult: string) {
function onTransactionSent(chainId: int, txHash: string, uuid: string, error: string) {
d.isPendingTx = false
try {
let response = JSON.parse(txResult)
if (response.uuid !== d.uuid) return
if (!response.success) {
if (response.error.includes(Constants.walletSection.cancelledMessage)) {
return
}
sendingError.text = response.error
return sendingError.open()
if (uuid !== d.uuid) return
if (!!error) {
if (error.includes(Constants.walletSection.cancelledMessage)) {
return
}
for(var i=0; i<popup.bestRoutes.length; i++) {
let txHash = response.result[popup.bestRoutes[i].fromNetwork.chainId]
let url = "%1/%2".arg(popup.store.getEtherscanLink(popup.bestRoutes[i].fromNetwork.chainId)).arg(txHash)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
}
popup.close()
} catch (e) {
console.error('Error parsing the response', e)
sendingError.text = error
return sendingError.open()
}
let url = "%1/%2".arg(popup.store.getEtherscanLink(chainId)).arg(txHash)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
popup.close()
}
}
}

View File

@ -148,7 +148,7 @@ Item {
onCancelClicked: root.cancelClicked(packId)
onUpdateClicked: root.updateClicked(packId)
onBuyClicked: {
Global.openPopup(stickerPackPurchaseModal, {price})
Global.openPopup(stickerPackPurchaseModal, {price, packId})
root.buyClicked(packId)
}
}
@ -181,7 +181,7 @@ Item {
onCancelClicked: root.cancelClicked(packId)
onUpdateClicked: root.updateClicked(packId)
onBuyClicked: {
Global.openPopup(stickerPackPurchaseModal, {price})
Global.openPopup(stickerPackPurchaseModal, {price, packId})
root.buyClicked(packId)
}
}
@ -196,6 +196,7 @@ Item {
id: buyStickersModal
required property int price
required property string packId
interactive: false
sendType: Constants.SendType.StickersBuy
@ -203,8 +204,8 @@ Item {
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(parseFloat(price))
preSelectedAsset: store.getAsset(buyStickersModal.store.assets, JSON.parse(root.store.stickersStore.getStatusToken()).symbol)
sendTransaction: function() {
if(bestRoutes.length === 1) {
let path = bestRoutes[0]
if(bestRoutes.count === 1) {
let path = bestRoutes.firstItem()
let eip1559Enabled = path.gasFees.eip1559Enabled
let maxFeePerGas = path.gasFees.maxFeePerGasM
root.store.stickersStore.authenticateAndBuy(packId,
@ -218,29 +219,22 @@ Item {
}
Connections {
target: root.store.stickersStore.stickersModule
function onTransactionWasSent(txResult: string) {
try {
let response = JSON.parse(txResult)
if (!response.success) {
if (response.result.includes(Constants.walletSection.cancelledMessage)) {
return
}
buyStickersModal.sendingError.text = response.result
return buyStickersModal.sendingError.open()
function onTransactionWasSent(chainId: int, txHash: string, error: string) {
if (!!error) {
if (error.includes(Constants.walletSection.cancelledMessage)) {
return
}
for(var i=0; i<buyStickersModal.bestRoutes.length; i++) {
let url = "%1/%2".arg(buyStickersModal.store.getEtherscanLink(buyStickersModal.bestRoutes[i].fromNetwork.chainId)).arg(response.result)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
}
buyStickersModal.close()
} catch (e) {
console.error('Error parsing the response', e)
buyStickersModal.sendingError.text = error
return buyStickersModal.sendingError.open()
}
let url = "%1/%2".arg(buyStickersModal.store.getEtherscanLink(chainId)).arg(txHash)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
buyStickersModal.close()
}
}
}

View File

@ -73,8 +73,8 @@ ModalPopup {
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(parseFloat(price))
preSelectedAsset: store.getAsset(buyStickersPackModal.store.assets, JSON.parse(stickerPackDetailsPopup.store.stickersStore.getStatusToken()).symbol)
sendTransaction: function() {
if(bestRoutes.length === 1) {
let path = bestRoutes[0]
if(bestRoutes.count === 1) {
let path = bestRoutes.firstItem()
let eip1559Enabled = path.gasFees.eip1559Enabled
let maxFeePerGas = path.gasFees.maxFeePerGasM
stickerPackDetailsPopup.store.stickersStore.authenticateAndBuy(packId,
@ -88,30 +88,22 @@ ModalPopup {
}
Connections {
target: stickerPackDetailsPopup.store.stickersStore.stickersModule
function onTransactionWasSent(txResult: string) {
try {
let response = JSON.parse(txResult)
if (!response.success) {
if (response.result.includes(Constants.walletSection.cancelledMessage)) {
return
}
buyStickersPackModal.sendingError.text = response.result
return buyStickersPackModal.sendingError.open()
function onTransactionWasSent(chainId: int, txHash: string, error: string) {
if (!!error) {
if (error.includes(Constants.walletSection.cancelledMessage)) {
return
}
for(var i=0; i<buyStickersPackModal.bestRoutes.length; i++) {
let txHash = response.result[buyStickersPackModal.bestRoutes[i].fromNetwork.chainId]
let url = "%1/%2".arg(buyStickersPackModal.store.getEtherscanLink(buyStickersPackModal.bestRoutes[i].fromNetwork.chainId)).arg(response.result)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
}
buyStickersPackModal.close()
} catch (e) {
console.error('Error parsing the response', e)
buyStickersPackModal.sendingError.text = error
return buyStickersPackModal.sendingError.open()
}
let url = "%1/%2".arg(buyStickersPackModal.store.getEtherscanLink(chainId)).arg(txHash)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
buyStickersPackModal.close()
}
}
}

View File

@ -1,32 +1,26 @@
import QtQuick 2.13
import utils 1.0
import SortFilterProxyModel 0.2
import shared.stores 1.0
import "../../../app/AppLayouts/Profile/stores"
import SortFilterProxyModel 0.2
import utils 1.0
QtObject {
id: root
property CurrenciesStore currencyStore: CurrenciesStore {}
property ProfileSectionStore profileSectionStore: ProfileSectionStore {}
property var contactStore: profileSectionStore.contactsStore
property var mainModuleInst: mainModule
property var walletSectionSendInst: walletSectionSend
property var walletSectionInst: walletSection
property var tmpActivityController: walletSectionInst.tmpActivityController
property string currentCurrency: walletSectionInst.currentCurrency
property var allNetworks: networksModule.all
property var overview: walletSectionOverview
property var accounts: walletSectionSendInst.accounts
property var fromNetworksModel: walletSectionSendInst.fromNetworksModel
property var toNetworksModel: walletSectionSendInst.toNetworksModel
property var senderAccounts: walletSectionSendInst.senderAccounts
property var selectedSenderAccount: walletSectionSendInst.selectedSenderAccount
property string signingPhrase: walletSectionInst.signingPhrase
property var accounts: walletSectionSendInst.accounts
property bool areTestNetworksEnabled: networksModule.areTestNetworksEnabled
property var tmpActivityController: walletSection.tmpActivityController
property var savedAddressesModel: SortFilterProxyModel {
sourceModel: walletSectionSavedAddresses.model
filters: [
@ -36,38 +30,8 @@ QtObject {
}
]
}
property var disabledChainIdsFromList: []
property var disabledChainIdsToList: []
property var assets: walletSectionAssets.assets
function addRemoveDisabledFromChain(chainID, isDisabled) {
if(isDisabled) {
if(!root.disabledChainIdsFromList.includes(chainID))
disabledChainIdsFromList.push(chainID)
}
else {
for(var i = 0; i < disabledChainIdsFromList.length;i++) {
if(disabledChainIdsFromList[i] === chainID) {
disabledChainIdsFromList.splice(i, 1)
}
}
}
}
function addRemoveDisabledToChain(chainID, isDisabled) {
if(isDisabled) {
if(!root.disabledChainIdsToList.includes(chainID))
root.disabledChainIdsToList.push(chainID)
}
else {
for(var i = 0; i < root.disabledChainIdsToList.length;i++) {
if(root.disabledChainIdsToList[i] === chainID) {
root.disabledChainIdsToList.splice(i, 1)
}
}
}
}
property string selectedAssetSymbol: walletSectionSendInst.selectedAssetSymbol
property bool showUnPreferredChains: walletSectionSendInst.showUnPreferredChains
function getEtherscanLink(chainID) {
return networksModule.all.getBlockExplorerURL(chainID)
@ -77,24 +41,12 @@ QtObject {
globalUtils.copyToClipboard(text)
}
function authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, selectedRoutes) {
walletSectionSendInst.authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, selectedRoutes)
function authenticateAndTransfer(from, to, tokenSymbol, amount, uuid) {
walletSectionSendInst.authenticateAndTransfer(from, to, tokenSymbol, amount, uuid)
}
function suggestedFees(chainId) {
return JSON.parse(walletSectionSendInst.suggestedFees(chainId))
}
function getEstimatedTime(chainId, maxFeePerGas) {
return walletSectionSendInst.getEstimatedTime(chainId, maxFeePerGas)
}
function suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, sendType, lockedInAmounts) {
walletSectionSendInst.suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, sendType, JSON.stringify(lockedInAmounts))
}
function hex2Eth(value) {
return globalUtils.hex2Eth(value)
function suggestedRoutes(amount, sendType) {
walletSectionSendInst.suggestedRoutes(amount, sendType)
}
function resolveENS(value) {
@ -105,113 +57,10 @@ QtObject {
return globalUtils.wei2Eth(wei, decimals)
}
function getEth2Wei(eth, decimals) {
return globalUtils.eth2Wei(eth, decimals)
}
function plainText(text) {
return globalUtils.plainText(text)
}
function setDefaultPreferredDisabledChains() {
let mainnetChainId = getMainnetChainId()
preferredChainIds.push(mainnetChainId)
addUnpreferredChainsToDisabledChains()
}
function setAllNetworksAsPreferredChains() {
var preferredChains = []
for(var i = 0; i < allNetworks.count; i++) {
let chainId = allNetworks.rowData(i, "chainId") * 1
if(!preferredChainIds.includes(chainId)) {
preferredChainIds.push(chainId)
}
}
}
function resetTxStoreProperties() {
disabledChainIdsFromList = []
disabledChainIdsToList = []
preferredChainIds = []
lockedInAmounts = []
}
property var preferredChainIds: []
function getMainnetChainId() {
return networksModule.getMainnetChainId()
}
// We should move all this over to nim
function addPreferredChains(preferredchains, showUnpreferredNetworks) {
let tempPreferredChains = preferredChainIds
for(const chain of preferredchains) {
if(!tempPreferredChains.includes(chain)) {
tempPreferredChains.push(chain)
// remove from disabled accounts as it was added as preferred
addRemoveDisabledToChain(chain, false)
}
}
// here we are trying to remove chains that are not preferred from the list and
// also disable them incase the showUnpreferredNetworks toggle is turned off
for(var i = 0; i < tempPreferredChains.length; i++) {
if(!preferredchains.includes(tempPreferredChains[i])) {
if(!showUnpreferredNetworks)
addRemoveDisabledToChain(tempPreferredChains[i], true)
tempPreferredChains.splice(i, 1)
}
}
preferredChainIds = tempPreferredChains
}
function addUnpreferredChainsToDisabledChains() {
for(var i = 0; i < allNetworks.count; i++) {
let chainId = allNetworks.rowData(i, "chainId") * 1
if(!preferredChainIds.includes(chainId)) {
addRemoveDisabledToChain(chainId, true)
}
}
}
function splitAndFormatAddressPrefix(text, isBridgeTx, showUnpreferredNetworks) {
let address = ""
let tempPreferredChains = []
let chainFound = false
let splitWords = plainText(text).split(':')
let editedText = ""
for(var i=0; i<splitWords.length; i++) {
const word = splitWords[i]
if(word.startsWith("0x")) {
address = word
editedText += word
} else {
let chainColor = allNetworks.getNetworkColor(word)
if(!!chainColor) {
chainFound = true
if(!isBridgeTx)
tempPreferredChains.push(allNetworks.getNetworkChainId(word))
editedText += `<span style='color: %1'>%2</span>`.arg(chainColor).arg(word)+':'
}
}
}
if(!isBridgeTx) {
if(!chainFound)
addPreferredChains([getMainnetChainId()], showUnpreferredNetworks)
else
addPreferredChains(tempPreferredChains, showUnpreferredNetworks)
}
editedText +="</a></p>"
return {
formattedText: editedText,
address: address
}
}
enum EstimatedTime {
Unknown = 0,
LessThanOneMin,
@ -235,33 +84,6 @@ QtObject {
}
}
property var lockedInAmounts: []
function addLockedInAmount(chainID, value, decimals, locked) {
let amount = value * Math.pow(10, decimals)
let index = lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === chainID)
if(index === -1) {
lockedInAmounts.push({"chainID": chainID, "value": amount.toString(16)})
}
else {
if(locked) {
lockedInAmounts[index].value = amount.toString(16)
} else {
lockedInAmounts.splice(index,1)
}
}
}
function getTokenBalanceOnChain(selectedAccount, chainId: int, tokenSymbol: string) {
if (!selectedAccount) {
console.warn("selectedAccount invalid")
return undefined
}
walletSectionSendInst.prepareTokenBalanceOnChain(selectedAccount.address, chainId, tokenSymbol)
return walletSectionSendInst.getPreparedTokenBalanceOnChain()
}
function findTokenSymbolByAddress(address) {
if (Global.appIsReady)
return walletSectionAllTokens.findTokenSymbolByAddress(address)
@ -283,10 +105,6 @@ QtObject {
return {}
}
function getAllNetworksSupportedPrefix() {
return networksModule.getAllNetworksSupportedPrefix()
}
function switchSenderAccount(index) {
walletSectionSendInst.switchSenderAccount(index)
}
@ -294,4 +112,82 @@ QtObject {
function getNetworkShortNames(chainIds) {
return networksModule.getNetworkShortNames(chainIds)
}
function toggleFromDisabledChains(chainId) {
fromNetworksModel.toggleDisabledChains(chainId)
}
function toggleToDisabledChains(chainId) {
toNetworksModel.toggleDisabledChains(chainId)
}
function setDisabledChains(chainId, disabled) {
toNetworksModel.setDisabledChains(chainId, disabled)
}
function setSelectedAssetSymbol(symbol) {
walletSectionSendInst.setSelectedAssetSymbol(symbol)
}
function getNetworkName(chainId) {
return fromNetworksModel.getNetworkName(chainId)
}
function updatePreferredChains(chainIds) {
walletSectionSendInst.updatePreferredChains(chainIds)
}
function toggleShowUnPreferredChains() {
walletSectionSendInst.toggleShowUnPreferredChains()
}
function setAllNetworksAsPreferredChains() {
toNetworksModel.setAllNetworksAsPreferredChains()
}
function lockCard(chainId, amount, lock) {
fromNetworksModel.lockCard(chainId, amount, lock)
}
function resetStoredProperties() {
walletSectionSendInst.resetStoredProperties()
}
// TODO: move to nim
function splitAndFormatAddressPrefix(text, isBridgeTx) {
let address = ""
let tempPreferredChains = []
let chainFound = false
let splitWords = plainText(text).split(':')
let editedText = ""
for(var i=0; i<splitWords.length; i++) {
const word = splitWords[i]
if(word.startsWith("0x")) {
address = word
editedText += word
} else {
let chainColor = fromNetworksModel.getNetworkColor(word)
if(!!chainColor) {
chainFound = true
if(!isBridgeTx)
tempPreferredChains.push(fromNetworksModel.getNetworkChainId(word))
editedText += `<span style='color: %1'>%2</span>`.arg(chainColor).arg(word)+':'
}
}
}
if(!isBridgeTx) {
if(!chainFound)
updatePreferredChains(networksModule.getMainnetChainId())
else
updatePreferredChains(tempPreferredChains.join(":"))
}
editedText +="</a></p>"
return {
formattedText: editedText,
address: address
}
}
}

View File

@ -10,7 +10,6 @@ import shared.stores 1.0
ColumnLayout {
id: root
property var store
property string selectedSymbol
property bool isLoading: false
property double cryptoValueToReceive

View File

@ -63,7 +63,7 @@ Rectangle {
text: root.isLoading ? "..." : root.currencyStore.formatCurrencyAmount(root.gasFiatAmount, root.currencyStore.currentCurrency)
font.pixelSize: 15
color: Theme.palette.directColor1
visible: !!root.bestRoutes && root.bestRoutes !== undefined && root.bestRoutes.length > 0
visible: !!root.bestRoutes && root.bestRoutes !== undefined && root.bestRoutes.count > 0
}
}
GasSelector {
@ -76,6 +76,7 @@ Rectangle {
visible: root.errorType === Constants.NoError && !root.isLoading
bestRoutes: root.bestRoutes
selectedTokenSymbol: root.selectedTokenSymbol
getNetworkName: root.store.getNetworkName
}
GasValidator {
id: gasValidator

View File

@ -17,20 +17,14 @@ Item {
property var store
readonly property var currencyStore: store.currencyStore
property var bestRoutes
property var selectedAccount
property string ensAddressOrEmpty: ""
property string receiverIdentityText
property var selectedAsset
readonly property string selectedSymbol: !!selectedAsset ? selectedAsset.symbol : ""
property var allNetworks
property bool customMode: false
property double amountToSend
property int minSendCryptoDecimals: 0
property int minReceiveCryptoDecimals: 0
property double requiredGasInEth
property bool errorMode: d.customAmountToSend > root.amountToSend
property bool interactive: true
property bool showPreferredChains: false
property var weiToEth: function(wei) {}
property var reCalculateSuggestedRoute: function() {}
property int errorType: Constants.NoError
@ -39,13 +33,11 @@ Item {
QtObject {
id: d
property double customAmountToSend: 0
property bool thereIsApossibleRoute: false
readonly property string selectedSymbol: !!selectedAsset ? selectedAsset.symbol : ""
function resetAllSetValues() {
for(var i = 0; i<fromNetworksRepeater.count; i++) {
fromNetworksRepeater.itemAt(i).amountToSend = 0
fromNetworksRepeater.itemAt(i).routeOnNetwork = 0
toNetworksRepeater.itemAt(i).amountToReceive = 0
toNetworksRepeater.itemAt(i).routeOnNetwork = 0
toNetworksRepeater.itemAt(i).bentLine = 0
}
@ -68,7 +60,6 @@ Item {
}
onVisibleChanged: if(visible) d.draw()
onBestRoutesChanged: d.draw()
onErrorModeChanged: if(errorMode) d.draw()
height: visible ? networkCardsLayout.height : 0
@ -89,55 +80,49 @@ Item {
}
Repeater {
id: fromNetworksRepeater
model: root.allNetworks
model: store.fromNetworksModel
StatusCard {
id: fromNetwork
locale: LocaleUtils.userInputLocale
objectName: model.chainId
property double amountToSend: 0
property double advancedInputCurrencyAmount: selectedAsset !== undefined && advancedInput.valid ? LocaleUtils.numberFromLocaleString(advancedInput.text, LocaleUtils.userInputLocale) : 0.0
property var tokenBalance: model.tokenBalance
onTokenBalanceChanged: maxAdvancedValue = model.tokenBalance.amount
property var toNetworks: model.toNetworks
property int routeOnNetwork: 0
property bool selectedAssetValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined
property double tokenBalanceOnChain: selectedAssetValid ? root.store.getTokenBalanceOnChain(selectedAccount, model.chainId, root.selectedSymbol).amount : 0.0
property bool hasGas: selectedAssetValid && requiredGasInEth !== undefined ? root.store.walletSectionSendInst.hasGas(selectedAccount.address, model.chainId, model.nativeCurrencySymbol, requiredGasInEth) : false
property double advancedInputCurrencyAmount: selectedAssetValid && advancedInput.valid ? LocaleUtils.numberFromLocaleString(advancedInputText, LocaleUtils.userInputLocale) : 0.0
onToNetworksChanged: d.draw()
primaryText: model.chainName
secondaryText: (tokenBalanceOnChain == 0 && root.amountToSend > 0) ?
qsTr("No Balance") : !hasGas ? qsTr("No Gas") : root.currencyStore.formatCurrencyAmount(advancedInputCurrencyAmount, root.selectedSymbol, {"minDecimals": root.minSendCryptoDecimals})
tertiaryText: root.errorMode && advancedInputCurrencyAmount > 0 ? qsTr("EXCEEDS SEND AMOUNT"): qsTr("BALANCE: ") + root.currencyStore.formatCurrencyAmount(tokenBalanceOnChain, root.selectedSymbol)
locked: store.lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === model.chainId) !== -1
secondaryText: (model.tokenBalance.amount === 0 && root.amountToSend > 0) ?
qsTr("No Balance") : !model.hasGas ? qsTr("No Gas") : root.currencyStore.formatCurrencyAmount(advancedInputCurrencyAmount, d.selectedSymbol, {"minDecimals": root.minSendCryptoDecimals})
tertiaryText: root.errorMode && advancedInputCurrencyAmount > 0 ? qsTr("EXCEEDS SEND AMOUNT"): qsTr("BALANCE: ") + root.currencyStore.formatCurrencyAmount(model.tokenBalance.amount, d.selectedSymbol)
locked: model.locked
preCalculatedAdvancedText: {
let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem!== undefined && lockedItem.chainID === model.chainId)
if(locked && index !== -1) {
let amount = root.weiToEth(parseInt(store.lockedInAmounts[index].value, 16))
if(locked && model.lockedAmount) {
let amount = root.weiToEth(parseInt(model.lockedAmount, 16))
return LocaleUtils.numberToLocaleString(amount, -1, LocaleUtils.userInputLocale)
}
else return LocaleUtils.numberToLocaleString(fromNetwork.amountToSend, -1, LocaleUtils.userInputLocale)
else return LocaleUtils.numberToLocaleString(root.weiToEth(model.amountIn), -1, LocaleUtils.userInputLocale)
}
maxAdvancedValue: tokenBalanceOnChain
state: tokenBalanceOnChain === 0 || !hasGas ?
"unavailable" :
(root.errorMode || !advancedInput.valid) && advancedInputCurrencyAmount > 0 ? "error" : "default"
maxAdvancedValue: tokenBalance.amount
state: (model.tokenBalance.amount === 0 && root.amountToSend > 0) || !model.hasGas ? "unavailable" :
(root.errorMode || !advancedInput.valid) && advancedInputCurrencyAmount > 0 ? "error" : "default"
cardIcon.source: Style.svg(model.iconUrl)
disabledText: qsTr("Disabled")
disableText: qsTr("Disable")
enableText: qsTr("Enable")
advancedMode: root.customMode
disabled: store.disabledChainIdsFromList.includes(model.chainId)
disabled: !model.isEnabled
clickable: root.interactive
onClicked: {
store.addRemoveDisabledFromChain(model.chainId, disabled)
store.toggleFromDisabledChains(model.chainId)
// only recalculate if the a best route was disabled
if(root.bestRoutes.length === 0 || routeOnNetwork !== 0 || !disabled)
if(!!model.toNetworks || !disabled)
root.reCalculateSuggestedRoute()
}
onVisibleChanged: {
if(visible)
disabled = store.disabledChainIdsFromList.includes(model.chainId)
}
onCardLocked: {
store.addLockedInAmount(model.chainId, advancedInputCurrencyAmount, root.selectedAsset.decimals, isLocked)
onLockCard: {
let amount = lock ? (advancedInputCurrencyAmount * Math.pow(10, root.selectedAsset.decimals)).toString(16) : ""
store.lockCard(model.chainId, amount, lock)
d.calculateCustomAmounts()
if(!locked || (d.customAmountToSend <= root.amountToSend && advancedInput.valid))
root.reCalculateSuggestedRoute()
@ -164,9 +149,7 @@ Item {
StatusBaseText {
id: receiverIdentityText
text: root.ensAddressOrEmpty.length > 0
? root.ensAddressOrEmpty
: !!selectedAccount ? StatusQUtils.Utils.elideText(selectedAccount.address, 6, 4).toUpperCase() : ""
text: root.receiverIdentityText
Layout.fillWidth: true
font.pixelSize: 10
@ -183,50 +166,36 @@ Item {
Repeater {
id: toNetworksRepeater
model: root.allNetworks
model: store.toNetworksModel
StatusCard {
id: toCard
locale: LocaleUtils.userInputLocale
objectName: model.chainId
property int routeOnNetwork: 0
property bool preferred: model.isPreferred
property int bentLine: 0
property double amountToReceive: 0
property var preferredChains: store.preferredChainIds
property bool preferred: store.preferredChainIds.includes(model.chainId)
property int routeOnNetwork: 0
primaryText: model.chainName
secondaryText: root.currencyStore.formatCurrencyAmount(amountToReceive, root.selectedSymbol, {"minDecimals": root.minReceiveCryptoDecimals})
secondaryText: root.currencyStore.formatCurrencyAmount(root.weiToEth(model.amountOut), d.selectedSymbol, {"minDecimals": root.minReceiveCryptoDecimals})
tertiaryText: state === "unpreferred" ? qsTr("UNPREFERRED") : ""
state: !preferred ? "unpreferred" : "default"
opacity: preferred || showPreferredChains ? 1 : 0
opacity: preferred || store.showUnPreferredChains ? 1 : 0
cardIcon.source: Style.svg(model.iconUrl)
disabledText: qsTr("Disabled")
disableText: qsTr("Disable")
enableText: qsTr("Enable")
disabled: store.disabledChainIdsToList.includes(model.chainId)
disabled: !model.isEnabled
clickable: root.interactive
loading: root.isLoading
onClicked: {
store.addRemoveDisabledToChain(model.chainId, disabled)
store.toggleToDisabledChains(model.chainId)
// only recalculate if the a best route was disabled
if((root.bestRoutes !== undefined && root.bestRoutes.length === 0) || routeOnNetwork !== 0 || !disabled)
if(root.weiToEth(model.amountOut) > 0 || !disabled)
root.reCalculateSuggestedRoute()
}
onVisibleChanged: {
if(visible) {
disabled = store.disabledChainIdsToList.includes(model.chainId)
preferred = store.preferredChainIds.includes(model.chainId)
}
}
onOpacityChanged: {
if(opacity === 1) {
disabled = store.disabledChainIdsToList.includes(model.chainId)
} else {
if(opacity === 0 && routeOnNetwork > 0)
if(opacity === 0 && root.weiToEth(model.amountOut) > 0)
root.reCalculateSuggestedRoute()
}
}
// Only needed until we move preferredChains to nim side
onPreferredChainsChanged: preferred = store.preferredChainIds.includes(model.chainId)
}
}
}
@ -249,10 +218,6 @@ Item {
onPaint: {
d.resetAllSetValues()
d.thereIsApossibleRoute = false
if(bestRoutes === undefined)
return
// in case you are drawing multiple routes we need an offset so that the lines dont overlap
let yOffsetFrom = 0
@ -261,39 +226,30 @@ Item {
// Get the canvas context
var ctx = getContext("2d");
for(var i = 0; i< bestRoutes.length; i++) {
for(var j = 0; j<fromNetworksRepeater.count; j++) {
var fromN, toN = null
for(var j = 0; j<fromNetworksRepeater.count; j++) {
if(bestRoutes[i].fromNetwork.chainId === parseInt(fromNetworksRepeater.itemAt(j).objectName) &&
!store.disabledChainIdsFromList.includes(bestRoutes[i].fromNetwork.chainId)) {
fromN = fromNetworksRepeater.itemAt(j)
fromN = fromNetworksRepeater.itemAt(j)
const toNetworks = fromN.toNetworks.split(":")
for(var i = 0; i<toNetworks.length; i++) {
for(var k = 0; k<toNetworksRepeater.count; k++) {
if(toNetworks[i] === toNetworksRepeater.itemAt(k).objectName && !toNetworksRepeater.itemAt(k).disabled) {
toN = toNetworksRepeater.itemAt(k)
yOffsetFrom = toN.objectName === fromN.objectName && toN.routeOnNetwork !== 0 ? toN.routeOnNetwork * 16 : 0
yOffsetTo = toN.routeOnNetwork * 16
xOffset = (fromN.y - toN.y > 0 ? -1 : 1) * toN.bentLine * 16
fromN.routeOnNetwork += 1
toN.routeOnNetwork += 1
toN.bentLine = toN.objectName !== fromN.objectName
let routeColor = root.errorMode ? Theme.palette.dangerColor1 : toN.preferred ? '#627EEA' : Theme.palette.pinColor1
StatusQUtils.Utils.drawArrow(ctx, fromN.x + fromN.width,
fromN.y + fromN.cardIconPosition + yOffsetFrom,
toNetworksLayout.x + toN.x,
toNetworksLayout.y + toN.y + toN.cardIconPosition + yOffsetTo,
routeColor, xOffset)
break
}
}
}
for(var k = 0; k<toNetworksRepeater.count; k++) {
if(bestRoutes[i].toNetwork.chainId === parseInt(toNetworksRepeater.itemAt(k).objectName) &&
!store.disabledChainIdsToList.includes(bestRoutes[i].toNetwork.chainId)) {
toN = toNetworksRepeater.itemAt(k)
}
}
if(toN !== null && fromN !== null) {
yOffsetFrom = toN.objectName === fromN.objectName && toN.routeOnNetwork !== 0 ? toN.routeOnNetwork * 16 : 0
yOffsetTo = toN.routeOnNetwork * 16
xOffset = (fromN.y - toN.y > 0 ? -1 : 1) * toN.bentLine * 16
let amountToSend = root.weiToEth(bestRoutes[i].amountIn)
let amountToReceive = root.weiToEth(bestRoutes[i].amountOut)
fromN.amountToSend = amountToSend
toN.amountToReceive += amountToReceive
fromN.routeOnNetwork += 1
toN.routeOnNetwork += 1
toN.bentLine = toN.objectName !== fromN.objectName
d.thereIsApossibleRoute = true
let routeColor = root.errorMode ? Theme.palette.dangerColor1 : toN.preferred ? '#627EEA' : Theme.palette.pinColor1
StatusQUtils.Utils.drawArrow(ctx, fromN.x + fromN.width,
fromN.y + fromN.cardIconPosition + yOffsetFrom,
toNetworksLayout.x + toN.x,
toNetworksLayout.y + toN.y + toN.cardIconPosition + yOffsetTo,
routeColor, xOffset)
}
}
d.calculateCustomAmounts()
}

View File

@ -25,15 +25,12 @@ Item {
property var amountToSend
property int minSendCryptoDecimals: 0
property int minReceiveCryptoDecimals: 0
property var requiredGasInEth
property var bestRoutes
property bool isLoading: false
property bool advancedOrCustomMode: (tabBar.currentIndex === 1) || (tabBar.currentIndex === 2)
property bool errorMode: advancedNetworkRoutingPage.errorMode
property bool interactive: true
property bool isBridgeTx: false
property bool showUnpreferredNetworks: advancedNetworkRoutingPage.showUnpreferredNetworks
property var toNetworksList: []
property var toNetworksList
property int errorType: Constants.NoError
signal reCalculateSuggestedRoute()
@ -78,19 +75,18 @@ Item {
anchors.left: parent.left
anchors.margins: Style.current.padding
width: stackLayout.width - Style.current.bigPadding
bestRoutes: root.bestRoutes
isBridgeTx: root.isBridgeTx
amountToSend: root.amountToSend
minReceiveCryptoDecimals: root.minReceiveCryptoDecimals
isLoading: root.isLoading
store: root.store
selectedAsset: root.selectedAsset
selectedAccount: root.selectedAccount
errorMode: root.errorMode
errorType: root.errorType
toNetworksList: root.toNetworksList
weiToEth: function(wei) {
return parseFloat(store.getWei2Eth(wei, selectedAsset.decimals))
if(root.selectedAsset !== undefined)
return parseFloat(store.getWei2Eth(wei, root.selectedAsset.decimals))
}
formatCurrencyAmount: root.currencyStore.formatCurrencyAmount
reCalculateSuggestedRoute: function() {
@ -114,18 +110,17 @@ Item {
selectedAccount: root.selectedAccount
ensAddressOrEmpty: root.ensAddressOrEmpty
amountToSend: root.amountToSend
requiredGasInEth: root.requiredGasInEth
minSendCryptoDecimals: root.minSendCryptoDecimals
minReceiveCryptoDecimals: root.minReceiveCryptoDecimals
selectedAsset: root.selectedAsset
onReCalculateSuggestedRoute: root.reCalculateSuggestedRoute()
bestRoutes: root.bestRoutes
isLoading: root.isLoading
interactive: root.interactive
isBridgeTx: root.isBridgeTx
errorType: root.errorType
weiToEth: function(wei) {
return parseFloat(store.getWei2Eth(wei, selectedAsset.decimals))
if(selectedAsset !== undefined)
return parseFloat(store.getWei2Eth(wei, selectedAsset.decimals))
}
}
}

View File

@ -8,6 +8,7 @@ import StatusQ.Popups 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as StatusQUtils
import "../controls"
@ -20,16 +21,13 @@ ColumnLayout {
property double amountToSend
property int minSendCryptoDecimals: 0
property int minReceiveCryptoDecimals: 0
property double requiredGasInEth
property bool customMode: false
property var selectedAsset
property var bestRoutes
property bool isLoading: false
property bool errorMode: networksLoader.item ? networksLoader.item.errorMode : false
property var weiToEth: function(wei) {}
property bool interactive: true
property bool isBridgeTx: false
property bool showUnpreferredNetworks: preferredToggleButton.checked
property int errorType: Constants.NoError
signal reCalculateSuggestedRoute()
@ -58,7 +56,6 @@ ColumnLayout {
wrapMode: Text.WordWrap
}
StatusButton {
id: preferredToggleButton
Layout.alignment: Qt.AlignRight
Layout.preferredHeight: 22
verticalPadding: -1
@ -68,8 +65,12 @@ ColumnLayout {
icon.height: 16
icon.width: 16
text: checked ? qsTr("Hide Unpreferred Networks"): qsTr("Show Unpreferred Networks")
onToggled: if(!checked) store.addUnpreferredChainsToDisabledChains()
visible: !isBridgeTx
checked: root.store.showUnPreferredChains
onClicked: {
root.store.toggleShowUnPreferredChains()
root.reCalculateSuggestedRoute()
}
}
}
StatusBaseText {
@ -87,20 +88,17 @@ ColumnLayout {
visible: active
sourceComponent: NetworkCardsComponent {
store: root.store
selectedAccount: root.selectedAccount
ensAddressOrEmpty: root.ensAddressOrEmpty
allNetworks: root.store.allNetworks
receiverIdentityText: root.ensAddressOrEmpty.length > 0 ?
root.ensAddressOrEmpty : !!root.selectedAccount ?
StatusQUtils.Utils.elideText(root.selectedAccount.address, 6, 4).toUpperCase() : ""
amountToSend: root.amountToSend
minSendCryptoDecimals: root.minSendCryptoDecimals
minReceiveCryptoDecimals: root.minReceiveCryptoDecimals
customMode: root.customMode
requiredGasInEth: root.requiredGasInEth
selectedAsset: root.selectedAsset
reCalculateSuggestedRoute: function() {
root.reCalculateSuggestedRoute()
}
showPreferredChains: preferredToggleButton.checked
bestRoutes: root.bestRoutes
weiToEth: root.weiToEth
interactive: root.interactive
errorType: root.errorType

View File

@ -16,14 +16,12 @@ RowLayout {
id: root
property var store
property var bestRoutes
property double amountToSend
property int minReceiveCryptoDecimals: 0
property bool isLoading: false
property bool isBridgeTx: false
property var selectedAsset
property var selectedAccount
property var toNetworksList: []
property var toNetworksList
property var weiToEth: function(wei) {}
property var formatCurrencyAmount: function () {}
property var reCalculateSuggestedRoute: function() {}
@ -73,7 +71,7 @@ RowLayout {
Repeater {
id: repeater
objectName: "networksList"
model: isBridgeTx ? store.allNetworks : root.toNetworksList
model: isBridgeTx ? store.fromNetworksModel : root.toNetworksList
delegate: isBridgeTx ? networkItem : routeItem
}
}
@ -96,25 +94,19 @@ RowLayout {
Component {
id: routeItem
StatusListItem {
objectName: modelData.chainName
objectName: model.chainName
leftPadding: 5
rightPadding: 5
implicitWidth: 410
title: modelData.chainName
title: model.chainName
subTitle: {
let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === modelData.chainId)
var amountOut
if(!root.errorMode || index === -1)
amountOut = root.weiToEth(modelData.amountOut)
else {
amountOut = root.weiToEth(parseInt(store.lockedInAmounts[index].value, 16))
}
return root.formatCurrencyAmount(amountOut, selectedAsset.symbol, {"minDecimals": root.minReceiveCryptoDecimals})
let amountOut = root.weiToEth(model.amountOut)
return root.formatCurrencyAmount(amountOut, store.selectedAssetSymbol, {"minDecimals": root.minReceiveCryptoDecimals})
}
statusListItemSubTitle.color: root.errorMode ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
asset.width: 32
asset.height: 32
asset.name: Style.svg("tiny/" + modelData.iconUrl)
asset.name: Style.svg("tiny/" + model.iconUrl)
asset.isImage: true
color: "transparent"
}
@ -132,9 +124,7 @@ RowLayout {
rightPadding: 5
implicitWidth: 410
title: chainName
property bool tokenBalanceOnChainValid: selectedAccount && selectedAccount !== undefined && selectedAsset && selectedAsset !== undefined
property double tokenBalanceOnChain: tokenBalanceOnChainValid ? root.store.getTokenBalanceOnChain(selectedAccount, chainId, selectedAsset.symbol).amount : 0.0
subTitle: tokenBalanceOnChainValid ? root.formatCurrencyAmount(tokenBalanceOnChain, selectedAsset.symbol) : "N/A"
subTitle: root.formatCurrencyAmount(tokenBalance.amount, store.selectedAssetSymbol)
statusListItemSubTitle.color: Theme.palette.primaryColor1
asset.width: 32
asset.height: 32
@ -150,7 +140,7 @@ RowLayout {
onClicked: gasRectangle.toggle()
}
onCheckedChanged: {
store.addRemoveDisabledToChain(chainId, !gasRectangle.checked)
store.setDisabledChains(chainId, !gasRectangle.checked)
if(checked)
root.reCalculateSuggestedRoute()
}
@ -160,7 +150,7 @@ RowLayout {
height: card.height
}
Component.onCompleted: {
store.addRemoveDisabledToChain(chainId, !gasRectangle.checked)
store.setDisabledChains(chainId, !gasRectangle.checked)
if(index === (repeater.count -1))
root.reCalculateSuggestedRoute()
}

View File

@ -18,7 +18,6 @@ Loader {
property var store
property bool isBridgeTx: false
property bool interactive: true
property bool showUnpreferredNetworks: false
property var selectedAsset
property var selectedRecipient: null
property int selectedRecipientType
@ -36,6 +35,10 @@ Loader {
onSelectedRecipientChanged: {
root.isLoading()
d.waitTimer.restart()
if(!root.isBridgeTx)
root.store.updatePreferredChains(root.selectedRecipient.preferredSharingChainIds)
else
root.store.setAllNetworksAsPreferredChains()
if(!!root.selectedRecipient && root.selectedRecipientType !== TabAddressSelectorView.Type.None) {
switch(root.selectedRecipientType) {
case TabAddressSelectorView.Type.SavedAddress: {
@ -85,10 +88,10 @@ Loader {
if(!!root.item.input)
root.item.input.text = root.resolvedENSAddress
root.addressText = root.resolvedENSAddress
store.splitAndFormatAddressPrefix(root.address, root.isBridgeTx, root.showUnpreferredNetworks)
store.splitAndFormatAddressPrefix(root.address, root.isBridgeTx)
} else {
let address = d.getAddress()
let result = store.splitAndFormatAddressPrefix(address, root.isBridgeTx, root.showUnpreferredNetworks)
let result = store.splitAndFormatAddressPrefix(address, root.isBridgeTx)
if(!!result.address) {
root.addressText = result.address
if(!!root.item.input)
@ -139,7 +142,7 @@ Loader {
Component {
id: myAccountRecipient
WalletAccountListItem {
property string chainShortNames: store.getNetworkShortNames(modelData.preferredSharingChainIds)
property string chainShortNames: !!modelData ? store.getNetworkShortNames(modelData.preferredSharingChainIds): ""
implicitWidth: parent.width
modelData: root.selectedRecipient
radius: 8