feat(@desktop/wallet): Updated UI for bridge and multi routing support
fixes #7334
This commit is contained in:
parent
68fbaeadc1
commit
aec7a30d03
|
@ -24,4 +24,7 @@ proc getWalletAccount*(self: Controller, accountIndex: int): wallet_account_serv
|
|||
return self.walletAccountService.getWalletAccount(accountIndex)
|
||||
|
||||
proc getIndex*(self: Controller, address: string): int =
|
||||
return self.walletAccountService.getIndex(address)
|
||||
return self.walletAccountService.getIndex(address)
|
||||
|
||||
method findTokenSymbolByAddress*(self: Controller, address: string): string =
|
||||
return self.walletAccountService.findTokenSymbolByAddress(address)
|
||||
|
|
|
@ -14,6 +14,9 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
|
|||
method switchAccountByAddress*(self: AccessInterface, address: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method findTokenSymbolByAddress*(self: AccessInterface, address: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
# View Delegate Interface
|
||||
# Delegate for the view must be declared here due to use of QtObject and multi
|
||||
# inheritance, which is not well supported in Nim.
|
||||
|
|
|
@ -62,6 +62,7 @@ proc setAssets(self: Module, tokens: seq[WalletTokenDto]) =
|
|||
t.changePct24hour,
|
||||
t.change24hour,
|
||||
t.currencyPrice,
|
||||
t.decimals,
|
||||
)
|
||||
items.add(item)
|
||||
|
||||
|
@ -104,3 +105,6 @@ proc onTokensRebuilt(self: Module, accountsTokens: OrderedTable[string, seq[Wall
|
|||
if not accountsTokens.contains(walletAccount.address):
|
||||
return
|
||||
self.setAssets(accountsTokens[walletAccount.address])
|
||||
|
||||
method findTokenSymbolByAddress*(self: Module, address: string): string =
|
||||
return self.controller.findTokenSymbolByAddress(address)
|
||||
|
|
|
@ -134,6 +134,15 @@ QtObject:
|
|||
|
||||
proc connectedAccountDeleted*(self: View) {.signal.}
|
||||
|
||||
proc findTokenSymbolByAddress*(self: View, address: string): string {.slot.} =
|
||||
return self.delegate.findTokenSymbolByAddress(address)
|
||||
|
||||
proc hasGas*(self: View, chainId: int, nativeGasSymbol: string, requiredGas: float): bool {.slot.} =
|
||||
return self.assets.hasGas(chainId, nativeGasSymbol, requiredGas)
|
||||
|
||||
proc getTokenBalanceOnChain*(self: View, chainId: int, tokenSymbol: string): string {.slot.} =
|
||||
return self.assets.getTokenBalanceOnChain(chainId, tokenSymbol)
|
||||
|
||||
proc setData*(self: View, dto: wallet_account_service.WalletAccountDto) =
|
||||
self.name = dto.name
|
||||
self.nameChanged()
|
||||
|
|
|
@ -6,6 +6,9 @@ import ../../../../../app_service/service/network/service as network_service
|
|||
import ../../../../../app_service/service/settings/service as settings_service
|
||||
import ../../../../../app_service/service/provider/service as provider_service
|
||||
import ../../../../../app_service/service/wallet_account/service
|
||||
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||
|
||||
const UNIQUE_BROWSER_SECTION_TRANSACTION_MODULE_IDENTIFIER* = "BrowserSection-TransactionModule"
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
|
@ -43,6 +46,12 @@ proc init*(self: Controller) =
|
|||
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e: Args):
|
||||
self.delegate.updateNetwork(self.getNetwork())
|
||||
|
||||
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
|
||||
let args = SharedKeycarModuleArgs(e)
|
||||
if args.uniqueIdentifier != UNIQUE_BROWSER_SECTION_TRANSACTION_MODULE_IDENTIFIER:
|
||||
return
|
||||
self.delegate.onUserAuthenticated(args.password)
|
||||
|
||||
proc getDappsAddress*(self: Controller): string =
|
||||
return self.settingsService.getDappsAddress()
|
||||
|
||||
|
@ -55,3 +64,10 @@ proc postMessage*(self: Controller, payloadMethod: string, requestType: string,
|
|||
|
||||
proc ensResourceURL*(self: Controller, ens: string, url: string): (string, string, string, string, bool) =
|
||||
return self.providerService.ensResourceURL(ens, url)
|
||||
|
||||
proc authenticateUser*(self: Controller, keyUid = "", bip44Path = "", txHash = "") =
|
||||
let data = SharedKeycarModuleAuthenticationArgs(uniqueIdentifier: UNIQUE_BROWSER_SECTION_TRANSACTION_MODULE_IDENTIFIER,
|
||||
keyUid: keyUid,
|
||||
bip44Path: bip44Path,
|
||||
txHash: txHash)
|
||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
||||
|
|
|
@ -34,4 +34,10 @@ method viewDidLoad*(self: AccessInterface) {.base.} =
|
|||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method updateNetwork*(self: AccessInterface, network: NetworkDto) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method authenticateToPostMessage*(self: AccessInterface, payloadMethod: string, requestType: string, message: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onUserAuthenticated*(self: AccessInterface, password: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -2,6 +2,7 @@ import NimQml
|
|||
import io_interface
|
||||
import view
|
||||
import controller
|
||||
import std/json
|
||||
import ../../../../core/eventemitter
|
||||
|
||||
import ../io_interface as delegate_interface
|
||||
|
@ -11,6 +12,12 @@ import ../../../../../app_service/service/provider/service as provider_service
|
|||
import ../../../../global/global_singleton
|
||||
export io_interface
|
||||
|
||||
# Shouldn't be public ever, user only within this module.
|
||||
type TmpSendTransactionDetails = object
|
||||
payloadMethod: string
|
||||
requestType: string
|
||||
message: string
|
||||
|
||||
type
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
delegate: delegate_interface.AccessInterface
|
||||
|
@ -18,6 +25,7 @@ type
|
|||
viewVariant: QVariant
|
||||
moduleLoaded: bool
|
||||
controller: Controller
|
||||
tmpSendTransactionDetails: TmpSendTransactionDetails
|
||||
|
||||
proc newModule*(
|
||||
delegate: delegate_interface.AccessInterface,
|
||||
|
@ -72,3 +80,24 @@ method ensResourceURL*(self: Module, ens: string, url: string): (string, string,
|
|||
method updateNetwork*(self: Module, network: NetworkDto) =
|
||||
self.view.chainId = network.chainId
|
||||
self.view.chainName = network.chainName
|
||||
|
||||
method authenticateToPostMessage*(self: Module, payloadMethod: string, requestType: string, message: string) {.slot.} =
|
||||
self.tmpSendTransactionDetails.payloadMethod = payloadMethod
|
||||
self.tmpSendTransactionDetails.requestType = requestType
|
||||
self.tmpSendTransactionDetails.message = message
|
||||
|
||||
if singletonInstance.userProfile.getIsKeycardUser():
|
||||
let keyUid = singletonInstance.userProfile.getKeyUid()
|
||||
self.controller.authenticateUser(keyUid)
|
||||
else:
|
||||
self.controller.authenticateUser()
|
||||
|
||||
method onUserAuthenticated*(self: Module, password: string) =
|
||||
let jsonNode = parseJson(self.tmpSendTransactionDetails.message)
|
||||
|
||||
if jsonNode.kind == JObject and jsonNode.contains("payload"):
|
||||
jsonNode["payload"]["password"] = %* password
|
||||
self.tmpSendTransactionDetails.message = $jsonNode
|
||||
self.postMessage(self.tmpSendTransactionDetails.payloadMethod,
|
||||
self.tmpSendTransactionDetails.requestType,
|
||||
self.tmpSendTransactionDetails.message)
|
||||
|
|
|
@ -85,3 +85,7 @@ QtObject:
|
|||
newHost = base
|
||||
|
||||
result = url_replaceHostAndAddPath(url, newHost, http_scheme, "")
|
||||
|
||||
proc authenticateToPostMessage*(self: View, payloadMethod: string, requestType: string, message: string) {.slot.} =
|
||||
self.delegate.authenticateToPostMessage(payloadMethod, requestType, message)
|
||||
|
||||
|
|
|
@ -109,6 +109,26 @@ QtObject:
|
|||
of ModelRole.Balance:
|
||||
result = newQVariant(item.getBalance())
|
||||
|
||||
proc rowData(self: Model, index: int, column: string): string {.slot.} =
|
||||
if (index >= self.items.len):
|
||||
return
|
||||
let item = self.items[index]
|
||||
case column:
|
||||
of "chainId": result = $item.getChainId()
|
||||
of "nativeCurrencyDecimals": result = $item.getNativeCurrencyDecimals()
|
||||
of "layer": result = $item.getLayer()
|
||||
of "chainName": result = $item.getChainName()
|
||||
of "rpcURL": result = $item.getRpcURL()
|
||||
of "blockExplorerURL": result = $item.getBlockExplorerURL()
|
||||
of "nativeCurrencyName": result = $item.getNativeCurrencyName()
|
||||
of "nativeCurrencySymbol": result = $item.getNativeCurrencySymbol()
|
||||
of "isTest": result = $item.getIsTest()
|
||||
of "isEnabled": result = $item.getIsEnabled()
|
||||
of "iconUrl": result = $item.getIconURL()
|
||||
of "chainColor": result = $item.getChainColor()
|
||||
of "shortName": result = $item.getShortName()
|
||||
of "balance": result = $item.getBalance()
|
||||
|
||||
proc setItems*(self: Model, items: seq[Item]) =
|
||||
self.beginResetModel()
|
||||
self.items = items
|
||||
|
@ -143,4 +163,16 @@ QtObject:
|
|||
for item in self.items:
|
||||
if(item.getShortName() == toLowerAscii(shortName)):
|
||||
return item.getChainName()
|
||||
return ""
|
||||
|
||||
proc getNetworkColor*(self: Model, shortName: string): string {.slot.} =
|
||||
for item in self.items:
|
||||
if(item.getShortName() == toLowerAscii(shortName)):
|
||||
return item.getChainColor()
|
||||
return ""
|
||||
|
||||
proc getNetworkChainId*(self: Model, shortName: string): int {.slot.} =
|
||||
for item in self.items:
|
||||
if(item.getShortName() == toLowerAscii(shortName)):
|
||||
return item.getChainId()
|
||||
return 0
|
||||
|
|
|
@ -8,10 +8,13 @@ import ../../../../../app_service/service/ens/service as ens_service
|
|||
import ../../../../../app_service/service/network/service as network_service
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/token/dto
|
||||
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||
|
||||
logScope:
|
||||
topics = "profile-section-ens-usernames-module-controller"
|
||||
|
||||
const UNIQUE_ENS_SECTION_TRANSACTION_MODULE_IDENTIFIER* = "EnsSection-TransactionModule"
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
delegate: io_interface.AccessInterface
|
||||
|
@ -54,6 +57,12 @@ proc init*(self: Controller) =
|
|||
let args = EnsTransactionArgs(e)
|
||||
self.delegate.ensTransactionReverted(args.transactionType, args.ensUsername, args.transactionHash, args.revertReason)
|
||||
|
||||
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
|
||||
let args = SharedKeycarModuleArgs(e)
|
||||
if args.uniqueIdentifier != UNIQUE_ENS_SECTION_TRANSACTION_MODULE_IDENTIFIER:
|
||||
return
|
||||
self.delegate.onUserAuthenticated(args.password)
|
||||
|
||||
proc checkEnsUsernameAvailability*(self: Controller, desiredEnsUsername: string, statusDomain: bool) =
|
||||
self.ensService.checkEnsUsernameAvailability(desiredEnsUsername, statusDomain)
|
||||
|
||||
|
@ -129,4 +138,11 @@ proc getStatusToken*(self: Controller): string =
|
|||
return $jsonObj
|
||||
|
||||
proc getNetwork*(self: Controller): NetworkDto =
|
||||
return self.networkService.getNetworkForEns()
|
||||
return self.networkService.getNetworkForEns()
|
||||
|
||||
proc authenticateUser*(self: Controller, keyUid = "", bip44Path = "", txHash = "") =
|
||||
let data = SharedKeycarModuleAuthenticationArgs(uniqueIdentifier: UNIQUE_ENS_SECTION_TRANSACTION_MODULE_IDENTIFIER,
|
||||
keyUid: keyUid,
|
||||
bip44Path: bip44Path,
|
||||
txHash: txHash)
|
||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
||||
|
|
|
@ -45,15 +45,15 @@ method fetchDetailsForEnsUsername*(self: AccessInterface, ensUsername: string) {
|
|||
method setPubKeyGasEstimate*(self: AccessInterface, ensUsername: string, address: string): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setPubKey*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.base.} =
|
||||
method authenticateAndSetPubKey*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method releaseEnsEstimate*(self: AccessInterface, ensUsername: string, address: string): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method release*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.base.} =
|
||||
method authenticateAndReleaseEns*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method connectOwnedUsername*(self: AccessInterface, ensUsername: string, isStatus: bool) {.base.} =
|
||||
|
@ -65,8 +65,8 @@ method getEnsRegisteredAddress*(self: AccessInterface): string {.base.} =
|
|||
method registerEnsGasEstimate*(self: AccessInterface, ensUsername: string, address: string): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method registerEns*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.base.} =
|
||||
method authenticateAndRegisterEns*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getSNTBalance*(self: AccessInterface): string {.base.} =
|
||||
|
@ -93,3 +93,6 @@ method getChainIdForEns*(self: AccessInterface): int {.base.} =
|
|||
|
||||
method setPrefferedEnsUsername*(self: AccessInterface, ensUsername: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onUserAuthenticated*(self: AccessInterface, password: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -4,6 +4,7 @@ import io_interface
|
|||
import ../io_interface as delegate_interface
|
||||
import view, controller, model
|
||||
|
||||
import ../../../../global/global_singleton
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../../app_service/common/conversion as service_conversion
|
||||
import ../../../../../app_service/service/settings/service as settings_service
|
||||
|
@ -19,6 +20,19 @@ logScope:
|
|||
|
||||
include ../../../../../app_service/common/json_utils
|
||||
|
||||
# Shouldn't be public ever, user only within this module.
|
||||
type TmpSendEnsTransactionDetails = object
|
||||
ensUsername: string
|
||||
address: string
|
||||
gas: string
|
||||
gasPrice: string
|
||||
maxPriorityFeePerGas: string
|
||||
maxFeePerGas: string
|
||||
eip1559Enabled: bool
|
||||
isRegistration: bool
|
||||
isRelease: bool
|
||||
isSetPubKey: bool
|
||||
|
||||
type
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
delegate: delegate_interface.AccessInterface
|
||||
|
@ -26,6 +40,7 @@ type
|
|||
viewVariant: QVariant
|
||||
controller: Controller
|
||||
moduleLoaded: bool
|
||||
tmpSendEnsTransactionDetails: TmpSendEnsTransactionDetails
|
||||
|
||||
proc newModule*(
|
||||
delegate: delegate_interface.AccessInterface, events: EventEmitter,
|
||||
|
@ -90,9 +105,36 @@ method onDetailsForEnsUsername*(self: Module, ensUsername: string, address: stri
|
|||
method setPubKeyGasEstimate*(self: Module, ensUsername: string, address: string): int =
|
||||
return self.controller.setPubKeyGasEstimate(ensUsername, address)
|
||||
|
||||
method setPubKey*(self: Module, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string =
|
||||
let response = self.controller.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
method authenticateAndSetPubKey*(self: Module, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) =
|
||||
self.tmpSendEnsTransactionDetails.ensUsername = ensUsername
|
||||
self.tmpSendEnsTransactionDetails.address = address
|
||||
self.tmpSendEnsTransactionDetails.gas = gas
|
||||
self.tmpSendEnsTransactionDetails.gasPrice = gasPrice
|
||||
self.tmpSendEnsTransactionDetails.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||
self.tmpSendEnsTransactionDetails.maxFeePerGas = maxFeePerGas
|
||||
self.tmpSendEnsTransactionDetails.eip1559Enabled = eip1559Enabled
|
||||
self.tmpSendEnsTransactionDetails.isRegistration = false
|
||||
self.tmpSendEnsTransactionDetails.isRelease = false
|
||||
self.tmpSendEnsTransactionDetails.isSetPubKey = true
|
||||
|
||||
if singletonInstance.userProfile.getIsKeycardUser():
|
||||
let keyUid = singletonInstance.userProfile.getKeyUid()
|
||||
self.controller.authenticateUser(keyUid)
|
||||
else:
|
||||
self.controller.authenticateUser()
|
||||
|
||||
method setPubKey*(self: Module, password: string) =
|
||||
let response = self.controller.setPubKey(
|
||||
self.tmpSendEnsTransactionDetails.ensUsername,
|
||||
self.tmpSendEnsTransactionDetails.address,
|
||||
self.tmpSendEnsTransactionDetails.gas,
|
||||
self.tmpSendEnsTransactionDetails.gasPrice,
|
||||
self.tmpSendEnsTransactionDetails.maxPriorityFeePerGas,
|
||||
self.tmpSendEnsTransactionDetails.maxFeePerGas,
|
||||
password,
|
||||
self.tmpSendEnsTransactionDetails.eip1559Enabled
|
||||
)
|
||||
if(response.len == 0):
|
||||
info "expected response is empty", methodName="setPubKey"
|
||||
return
|
||||
|
@ -103,23 +145,48 @@ method setPubKey*(self: Module, ensUsername: string, address: string, gas: strin
|
|||
return
|
||||
|
||||
var success: bool
|
||||
if(not responseObj.getProp("success", success) or not success):
|
||||
if(not responseObj.getProp("success", success)):
|
||||
info "remote call is not executed with success", methodName="setPubKey"
|
||||
return response
|
||||
|
||||
var respResult: string
|
||||
if(responseObj.getProp("result", respResult)):
|
||||
self.view.model().addItem(Item(ensUsername: ensUsername, isPending: true))
|
||||
self.view.emitTransactionWasSentSignal(respResult)
|
||||
|
||||
return response
|
||||
self.view.model().addItem(Item(ensUsername: self.tmpSendEnsTransactionDetails.ensUsername, isPending: true))
|
||||
self.view.emitTransactionWasSentSignal(response)
|
||||
|
||||
method releaseEnsEstimate*(self: Module, ensUsername: string, address: string): int =
|
||||
return self.controller.releaseEnsEstimate(ensUsername, address)
|
||||
|
||||
method release*(self: Module, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string =
|
||||
let response = self.controller.release(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
method authenticateAndReleaseEns*(self: Module, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) =
|
||||
self.tmpSendEnsTransactionDetails.ensUsername = ensUsername
|
||||
self.tmpSendEnsTransactionDetails.address = address
|
||||
self.tmpSendEnsTransactionDetails.gas = gas
|
||||
self.tmpSendEnsTransactionDetails.gasPrice = gasPrice
|
||||
self.tmpSendEnsTransactionDetails.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||
self.tmpSendEnsTransactionDetails.maxFeePerGas = maxFeePerGas
|
||||
self.tmpSendEnsTransactionDetails.eip1559Enabled = eip1559Enabled
|
||||
self.tmpSendEnsTransactionDetails.isRegistration = false
|
||||
self.tmpSendEnsTransactionDetails.isRelease = true
|
||||
self.tmpSendEnsTransactionDetails.isSetPubKey = false
|
||||
|
||||
if singletonInstance.userProfile.getIsKeycardUser():
|
||||
let keyUid = singletonInstance.userProfile.getKeyUid()
|
||||
self.controller.authenticateUser(keyUid)
|
||||
else:
|
||||
self.controller.authenticateUser()
|
||||
|
||||
method releaseEns*(self: Module, password: string) =
|
||||
let response = self.controller.release(
|
||||
self.tmpSendEnsTransactionDetails.ensUsername,
|
||||
self.tmpSendEnsTransactionDetails.address,
|
||||
self.tmpSendEnsTransactionDetails.gas,
|
||||
self.tmpSendEnsTransactionDetails.gasPrice,
|
||||
self.tmpSendEnsTransactionDetails.maxPriorityFeePerGas,
|
||||
self.tmpSendEnsTransactionDetails.maxFeePerGas,
|
||||
password,
|
||||
self.tmpSendEnsTransactionDetails.eip1559Enabled
|
||||
)
|
||||
|
||||
if(response.len == 0):
|
||||
info "expected response is empty", methodName="release"
|
||||
return
|
||||
|
@ -130,17 +197,15 @@ method release*(self: Module, ensUsername: string, address: string, gas: string,
|
|||
return
|
||||
|
||||
var success: bool
|
||||
if(not responseObj.getProp("success", success) or not success):
|
||||
if(not responseObj.getProp("success", success)):
|
||||
info "remote call is not executed with success", methodName="release"
|
||||
return
|
||||
|
||||
var result: string
|
||||
if(responseObj.getProp("result", result)):
|
||||
self.controller.setPreferredName("")
|
||||
self.view.model().removeItemByEnsUsername(ensUsername)
|
||||
self.view.emitTransactionWasSentSignal(result)
|
||||
|
||||
return response
|
||||
self.view.model().removeItemByEnsUsername(self.tmpSendEnsTransactionDetails.ensUsername)
|
||||
self.view.emitTransactionWasSentSignal(response)
|
||||
|
||||
proc formatUsername(self: Module, ensUsername: string, isStatus: bool): string =
|
||||
result = ensUsername
|
||||
|
@ -178,10 +243,58 @@ method getEnsRegisteredAddress*(self: Module): string =
|
|||
method registerEnsGasEstimate*(self: Module, ensUsername: string, address: string): int =
|
||||
return self.controller.registerEnsGasEstimate(ensUsername, address)
|
||||
|
||||
method registerEns*(self: Module, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string =
|
||||
let response = self.controller.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
|
||||
method authenticateAndRegisterEns*(self: Module, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) =
|
||||
self.tmpSendEnsTransactionDetails.ensUsername = ensUsername
|
||||
self.tmpSendEnsTransactionDetails.address = address
|
||||
self.tmpSendEnsTransactionDetails.gas = gas
|
||||
self.tmpSendEnsTransactionDetails.gasPrice = gasPrice
|
||||
self.tmpSendEnsTransactionDetails.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||
self.tmpSendEnsTransactionDetails.maxFeePerGas = maxFeePerGas
|
||||
self.tmpSendEnsTransactionDetails.eip1559Enabled = eip1559Enabled
|
||||
self.tmpSendEnsTransactionDetails.isRegistration = true
|
||||
self.tmpSendEnsTransactionDetails.isRelease = false
|
||||
self.tmpSendEnsTransactionDetails.isSetPubKey = false
|
||||
|
||||
if singletonInstance.userProfile.getIsKeycardUser():
|
||||
let keyUid = singletonInstance.userProfile.getKeyUid()
|
||||
self.controller.authenticateUser(keyUid)
|
||||
else:
|
||||
self.controller.authenticateUser()
|
||||
|
||||
##################################
|
||||
## Do Not Delete
|
||||
##
|
||||
## Once we start with signing a transactions we shold check if the address we want to send a transaction from is migrated
|
||||
## or not. In case it's not we should just authenticate logged in user, otherwise we should use one of the keycards that
|
||||
## address (key pair) is migrated to and sign the transaction using it.
|
||||
##
|
||||
## The code bellow is an example how we can achieve that in future, when we start with signing transactions.
|
||||
##
|
||||
## let acc = self.controller.getAccountByAddress(from_addr)
|
||||
## if acc.isNil:
|
||||
## echo "error: selected account to send a transaction from is not known"
|
||||
## return
|
||||
## let keyPair = self.controller.getMigratedKeyPairByKeyUid(acc.keyUid)
|
||||
## if keyPair.len == 0:
|
||||
## self.controller.authenticateUser()
|
||||
## else:
|
||||
## self.controller.authenticateUser(acc.keyUid, acc.path)
|
||||
##
|
||||
##################################
|
||||
|
||||
method registerEns(self: Module, password: string) =
|
||||
let response = self.controller.registerEns(
|
||||
self.tmpSendEnsTransactionDetails.ensUsername,
|
||||
self.tmpSendEnsTransactionDetails.address,
|
||||
self.tmpSendEnsTransactionDetails.gas,
|
||||
self.tmpSendEnsTransactionDetails.gasPrice,
|
||||
self.tmpSendEnsTransactionDetails.maxPriorityFeePerGas,
|
||||
self.tmpSendEnsTransactionDetails.maxFeePerGas,
|
||||
password,
|
||||
self.tmpSendEnsTransactionDetails.eip1559Enabled
|
||||
)
|
||||
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind != JObject):
|
||||
info "expected response is not a json object", methodName="registerEns"
|
||||
|
@ -189,10 +302,8 @@ method registerEns*(self: Module, ensUsername: string, address: string, gas: str
|
|||
|
||||
var respResult: string
|
||||
if(responseObj.getProp("result", respResult) and responseObj{"success"}.getBool == true):
|
||||
self.view.model().addItem(Item(ensUsername: self.formatUsername(ensUsername, true), isPending: true))
|
||||
self.view.emitTransactionWasSentSignal(respResult)
|
||||
|
||||
return response
|
||||
self.view.model().addItem(Item(ensUsername: self.formatUsername(self.tmpSendEnsTransactionDetails.ensUsername, true), isPending: true))
|
||||
self.view.emitTransactionWasSentSignal(response)
|
||||
|
||||
method getSNTBalance*(self: Module): string =
|
||||
return self.controller.getSNTBalance()
|
||||
|
@ -203,13 +314,19 @@ method getWalletDefaultAddress*(self: Module): string =
|
|||
method getCurrentCurrency*(self: Module): string =
|
||||
return self.controller.getCurrentCurrency()
|
||||
|
||||
method getFiatValue*(self: Module, cryptoBalance: string, cryptoSymbol: string, fiatSymbol: string): string =
|
||||
method getFiatValue*(self: Module, cryptoBalance: string, cryptoSymbol: string, fiatSymbol: string): string =
|
||||
var floatCryptoBalance: float = 0
|
||||
try:
|
||||
floatCryptoBalance = parseFloat(cryptoBalance)
|
||||
except ValueError:
|
||||
return "0.00"
|
||||
|
||||
if (cryptoBalance == "" or cryptoSymbol == "" or fiatSymbol == ""):
|
||||
return "0.00"
|
||||
|
||||
let price = self.controller.getPrice(cryptoSymbol, fiatSymbol)
|
||||
let value = parseFloat(cryptoBalance) * price
|
||||
return fmt"{value:.2f}"
|
||||
let value = floatCryptoBalance * price
|
||||
return fmt"{value}"
|
||||
|
||||
method getGasEthValue*(self: Module, gweiValue: string, gasLimit: string): string {.slot.} =
|
||||
var gasLimitInt:int
|
||||
|
@ -240,3 +357,12 @@ method getChainIdForEns*(self: Module): int =
|
|||
|
||||
method setPrefferedEnsUsername*(self: Module, ensUsername: string) =
|
||||
self.controller.setPreferredName(ensUsername)
|
||||
|
||||
method onUserAuthenticated*(self: Module, password: string) =
|
||||
if self.tmpSendEnsTransactionDetails.isRegistration:
|
||||
self.registerEns(password)
|
||||
elif self.tmpSendEnsTransactionDetails.isRelease:
|
||||
self.releaseEns(password)
|
||||
elif self.tmpSendEnsTransactionDetails.isSetPubKey:
|
||||
self.setPubKey(password)
|
||||
|
||||
|
|
|
@ -71,9 +71,9 @@ QtObject:
|
|||
proc setPubKeyGasEstimate*(self: View, ensUsername: string, address: string): int {.slot.} =
|
||||
return self.delegate.setPubKeyGasEstimate(ensUsername, address)
|
||||
|
||||
proc setPubKey*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.slot.} =
|
||||
return self.delegate.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
proc authenticateAndSetPubKey*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) {.slot.} =
|
||||
self.delegate.authenticateAndSetPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, eip1559Enabled)
|
||||
|
||||
proc getEtherscanLink*(self: View): string {.slot.} =
|
||||
return self.etherscanLink
|
||||
|
@ -94,9 +94,9 @@ QtObject:
|
|||
proc releaseEnsEstimate*(self: View, ensUsername: string, address: string): int {.slot.} =
|
||||
return self.delegate.releaseEnsEstimate(ensUsername, address)
|
||||
|
||||
proc releaseEns*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.slot.} =
|
||||
return self.delegate.release(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
proc authenticateAndReleaseEns*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) {.slot.} =
|
||||
self.delegate.authenticateAndReleaseEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, eip1559Enabled)
|
||||
|
||||
proc connectOwnedUsername*(self: View, ensUsername: string, isStatus: bool) {.slot.} =
|
||||
self.delegate.connectOwnedUsername(ensUsername, isStatus)
|
||||
|
@ -107,9 +107,9 @@ QtObject:
|
|||
proc registerEnsGasEstimate*(self: View, ensUsername: string, address: string): int {.slot.} =
|
||||
return self.delegate.registerEnsGasEstimate(ensUsername, address)
|
||||
|
||||
proc registerEns*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.slot.} =
|
||||
return self.delegate.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
proc authenticateAndRegisterEns*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) {.slot.} =
|
||||
self.delegate.authenticateAndRegisterEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, eip1559Enabled)
|
||||
|
||||
proc getSNTBalance*(self: View): string {.slot.} =
|
||||
return self.delegate.getSNTBalance()
|
||||
|
|
|
@ -10,7 +10,9 @@ import ../../../../app_service/service/settings/service as settings_service
|
|||
import ../../../../app_service/service/network/service as network_service
|
||||
import ../../../../app_service/service/eth/utils as eth_utils
|
||||
import ../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||
|
||||
const UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER* = "StickersSection-TransactionModule"
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
|
@ -92,6 +94,12 @@ proc init*(self: Controller) =
|
|||
let args = StickerTransactionArgs(e)
|
||||
self.delegate.stickerTransactionReverted(args.transactionType, args.packID, args.transactionHash, args.revertReason)
|
||||
|
||||
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
|
||||
let args = SharedKeycarModuleArgs(e)
|
||||
if args.uniqueIdentifier != UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER:
|
||||
return
|
||||
self.delegate.onUserAuthenticated(args.password)
|
||||
|
||||
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] =
|
||||
self.stickerService.buy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
|
||||
|
@ -156,4 +164,11 @@ proc getStatusToken*(self: Controller): string =
|
|||
"symbol": token.symbol,
|
||||
"address": token.addressAsString()
|
||||
}
|
||||
return $jsonObj
|
||||
return $jsonObj
|
||||
|
||||
proc authenticateUser*(self: Controller, keyUid = "", bip44Path = "", txHash = "") =
|
||||
let data = SharedKeycarModuleAuthenticationArgs(uniqueIdentifier: UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER,
|
||||
keyUid: keyUid,
|
||||
bip44Path: bip44Path,
|
||||
txHash: txHash)
|
||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
||||
|
|
|
@ -19,7 +19,7 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
|
|||
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method buy*(self: AccessInterface, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): tuple[response: string, success: bool] {.base.} =
|
||||
method authenticateAndBuy*(self: AccessInterface, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool){.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getInstalledStickerPacks*(self: AccessInterface): Table[string, StickerPackDto] {.base.} =
|
||||
|
@ -95,3 +95,6 @@ method stickerTransactionConfirmed*(self: AccessInterface, trxType: string, pack
|
|||
method stickerTransactionReverted*(self: AccessInterface, trxType: string, packID: string, transactionHash: string,
|
||||
revertReason: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onUserAuthenticated*(self: AccessInterface, password: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -11,6 +11,17 @@ import ../../../../app_service/service/wallet_account/service as wallet_account_
|
|||
|
||||
export io_interface
|
||||
|
||||
# Shouldn't be public ever, user only within this module.
|
||||
type TmpBuyStickersTransactionDetails = object
|
||||
packId: string
|
||||
address: string
|
||||
gas: string
|
||||
gasPrice: string
|
||||
maxPriorityFeePerGas: string
|
||||
maxFeePerGas: string
|
||||
eip1559Enabled: bool
|
||||
|
||||
|
||||
type
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
delegate: delegate_interface.AccessInterface
|
||||
|
@ -18,6 +29,7 @@ type
|
|||
view: View
|
||||
viewVariant: QVariant
|
||||
moduleLoaded: bool
|
||||
tmpBuyStickersTransactionDetails: TmpBuyStickersTransactionDetails
|
||||
|
||||
proc newModule*(
|
||||
delegate: delegate_interface.AccessInterface,
|
||||
|
@ -52,8 +64,58 @@ method viewDidLoad*(self: Module) =
|
|||
self.moduleLoaded = true
|
||||
self.delegate.stickersDidLoad()
|
||||
|
||||
method buy*(self: Module, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): tuple[response: string, success: bool] =
|
||||
return self.controller.buy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
method authenticateAndBuy*(self: Module, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) =
|
||||
self.tmpBuyStickersTransactionDetails.packId = packId
|
||||
self.tmpBuyStickersTransactionDetails.address = address
|
||||
self.tmpBuyStickersTransactionDetails.gas = gas
|
||||
self.tmpBuyStickersTransactionDetails.gasPrice = gasPrice
|
||||
self.tmpBuyStickersTransactionDetails.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||
self.tmpBuyStickersTransactionDetails.maxFeePerGas = maxFeePerGas
|
||||
self.tmpBuyStickersTransactionDetails.eip1559Enabled = eip1559Enabled
|
||||
|
||||
if singletonInstance.userProfile.getIsKeycardUser():
|
||||
let keyUid = singletonInstance.userProfile.getKeyUid()
|
||||
self.controller.authenticateUser(keyUid)
|
||||
else:
|
||||
self.controller.authenticateUser()
|
||||
|
||||
##################################
|
||||
## Do Not Delete
|
||||
##
|
||||
## Once we start with signing a transactions we shold check if the address we want to send a transaction from is migrated
|
||||
## or not. In case it's not we should just authenticate logged in user, otherwise we should use one of the keycards that
|
||||
## address (key pair) is migrated to and sign the transaction using it.
|
||||
##
|
||||
## The code bellow is an example how we can achieve that in future, when we start with signing transactions.
|
||||
##
|
||||
## let acc = self.controller.getAccountByAddress(from_addr)
|
||||
## if acc.isNil:
|
||||
## echo "error: selected account to send a transaction from is not known"
|
||||
## return
|
||||
## let keyPair = self.controller.getMigratedKeyPairByKeyUid(acc.keyUid)
|
||||
## if keyPair.len == 0:
|
||||
## self.controller.authenticateUser()
|
||||
## else:
|
||||
## self.controller.authenticateUser(acc.keyUid, acc.path)
|
||||
##
|
||||
##################################
|
||||
|
||||
method onUserAuthenticated*(self: Module, password: string) =
|
||||
let responseTuple = self.controller.buy(
|
||||
self.tmpBuyStickersTransactionDetails.packId,
|
||||
self.tmpBuyStickersTransactionDetails.address,
|
||||
self.tmpBuyStickersTransactionDetails.gas,
|
||||
self.tmpBuyStickersTransactionDetails.gasPrice,
|
||||
self.tmpBuyStickersTransactionDetails.maxPriorityFeePerGas,
|
||||
self.tmpBuyStickersTransactionDetails.maxFeePerGas,
|
||||
password,
|
||||
self.tmpBuyStickersTransactionDetails.eip1559Enabled
|
||||
)
|
||||
let response = responseTuple.response
|
||||
let success = responseTuple.success
|
||||
if success:
|
||||
self.view.stickerPacks.updateStickerPackInList(self.tmpBuyStickersTransactionDetails.packId, false, true)
|
||||
self.view.transactionWasSent($(%*{"success": success, "result": response}))
|
||||
|
||||
method getInstalledStickerPacks*(self: Module): Table[string, StickerPackDto] =
|
||||
self.controller.getInstalledStickerPacks()
|
||||
|
|
|
@ -61,18 +61,8 @@ QtObject:
|
|||
|
||||
proc gasEstimateReturned*(self: View, estimate: int, uuid: string) {.signal.}
|
||||
|
||||
proc buy*(self: View, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.slot.} =
|
||||
let responseTuple = self.delegate.buy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
let response = responseTuple.response
|
||||
let success = responseTuple.success
|
||||
if success:
|
||||
self.stickerPacks.updateStickerPackInList(packId, false, true)
|
||||
self.transactionWasSent(response)
|
||||
|
||||
result = $(%*{
|
||||
"success": success,
|
||||
"result": response
|
||||
})
|
||||
proc authenticateAndBuy*(self: View, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, eip1559Enabled: bool) {.slot.} =
|
||||
self.delegate.authenticateAndBuy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, eip1559Enabled)
|
||||
|
||||
proc stickerPacksLoaded*(self: View) {.signal.}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ method refreshWalletAccounts*(self: Module) =
|
|||
t.changePct24hour,
|
||||
t.change24hour,
|
||||
t.currencyPrice,
|
||||
t.decimals,
|
||||
))
|
||||
)
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ proc setAssetsAndBalance(self: Module, tokens: seq[WalletTokenDto]) =
|
|||
t.changePct24hour,
|
||||
t.change24hour,
|
||||
t.currencyPrice,
|
||||
t.decimals,
|
||||
)
|
||||
items.add(item)
|
||||
totalCurrencyBalanceForAllAssets += t.enabledNetworkBalance.currencybalance
|
||||
|
|
|
@ -224,3 +224,9 @@ QtObject:
|
|||
|
||||
proc findTokenSymbolByAddress*(self: View, address: string): string {.slot.} =
|
||||
return self.delegate.findTokenSymbolByAddress(address)
|
||||
|
||||
proc hasGas*(self: View, chainId: int, nativeGasSymbol: string, requiredGas: float): bool {.slot.} =
|
||||
return self.assets.hasGas(chainId, nativeGasSymbol, requiredGas)
|
||||
|
||||
proc getTokenBalanceOnChain*(self: View, chainId: int, tokenSymbol: string): string {.slot.} =
|
||||
return self.assets.getTokenBalanceOnChain(chainId, tokenSymbol)
|
||||
|
|
|
@ -78,6 +78,9 @@ proc init*(self: Controller) =
|
|||
return
|
||||
self.delegate.onUserAuthenticated(args.password)
|
||||
|
||||
self.events.on(SIGNAL_SUGGESTED_ROUTES_READY) do(e:Args):
|
||||
self.delegate.suggestedRoutesReady(SuggestedRoutesArgs(e).suggestedRoutes)
|
||||
|
||||
proc checkPendingTransactions*(self: Controller) =
|
||||
self.transactionService.checkPendingTransactions()
|
||||
|
||||
|
@ -106,17 +109,15 @@ proc estimateGas*(self: Controller, from_addr: string, to: string, assetSymbol:
|
|||
result = "0"
|
||||
|
||||
proc transfer*(self: Controller, from_addr: string, to_addr: string, tokenSymbol: string,
|
||||
value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,maxFeePerGas: string,
|
||||
password: string, chainId: string, uuid: string, eip1559Enabled: bool) =
|
||||
discard self.transactionService.transfer(from_addr, to_addr, tokenSymbol, value, gas,
|
||||
gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, chainId, uuid, eip1559Enabled)
|
||||
value: string, uuid: string, priority: int, selectedRoutes: string, password: string) =
|
||||
self.transactionService.transfer(from_addr, to_addr, tokenSymbol, value, uuid, priority, selectedRoutes, password)
|
||||
|
||||
proc suggestedFees*(self: Controller, chainId: int): string =
|
||||
let suggestedFees = self.transactionService.suggestedFees(chainId)
|
||||
return suggestedFees.toJson()
|
||||
|
||||
proc suggestedRoutes*(self: Controller, account: string, amount: float64, token: string, disabledChainIDs: seq[uint64]): string =
|
||||
let suggestedRoutes = self.transactionService.suggestedRoutes(account, amount, token, disabledChainIDs)
|
||||
proc suggestedRoutes*(self: Controller, account: string, amount: Uint256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], priority: int, sendType: int): string =
|
||||
let suggestedRoutes = self.transactionService.suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, priority, sendType)
|
||||
return suggestedRoutes.toJson()
|
||||
|
||||
proc getChainIdForChat*(self: Controller): int =
|
||||
|
@ -137,4 +138,4 @@ proc authenticateUser*(self: Controller, keyUid = "", bip44Path = "", txHash = "
|
|||
keyUid: keyUid,
|
||||
bip44Path: bip44Path,
|
||||
txHash: txHash)
|
||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
||||
|
|
|
@ -47,9 +47,8 @@ method onUserAuthenticated*(self: AccessInterface, password: string) {.base.} =
|
|||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method authenticateAndTransfer*(self: AccessInterface, from_addr: string, to_addr: string,
|
||||
tokenSymbol: string, value: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, chainId: string, uuid: string,
|
||||
eip1559Enabled: bool) {.base.} =
|
||||
tokenSymbol: string, value: string, uuid: string,
|
||||
priority: int, selectedRoutes: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method transactionWasSent*(self: AccessInterface, result: string) {.base.} =
|
||||
|
@ -58,7 +57,7 @@ method transactionWasSent*(self: AccessInterface, result: string) {.base.} =
|
|||
method suggestedFees*(self: AccessInterface, chainId: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method suggestedRoutes*(self: AccessInterface, account: string, amount: float64, token: string, disabledChainIDs: seq[uint64]): string {.base.} =
|
||||
method suggestedRoutes*(self: AccessInterface, account: string, amount: UInt256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], priority: int, sendType: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getChainIdForChat*(self: AccessInterface): int =
|
||||
|
@ -78,3 +77,6 @@ method viewDidLoad*(self: AccessInterface) {.base.} =
|
|||
|
||||
method getLastTxBlockNumber*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method suggestedRoutesReady*(self: AccessInterface, suggestedRoutes: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -15,14 +15,10 @@ type TmpSendTransactionDetails = object
|
|||
fromAddr: string
|
||||
toAddr: string
|
||||
tokenSymbol: string
|
||||
value: string
|
||||
gas: string
|
||||
gasPrice: string
|
||||
maxPriorityFeePerGas: string
|
||||
maxFeePerGas: string
|
||||
chainId: string
|
||||
value: string
|
||||
uuid: string
|
||||
eip1559Enabled: bool
|
||||
priority: int
|
||||
selectedRoutes: string
|
||||
|
||||
type
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
|
@ -105,21 +101,16 @@ method estimateGas*(self: Module, from_addr: string, to: string, assetSymbol: st
|
|||
method setIsNonArchivalNode*(self: Module, isNonArchivalNode: bool) =
|
||||
self.view.setIsNonArchivalNode(isNonArchivalNode)
|
||||
|
||||
method authenticateAndTransfer*(self: Module, from_addr: string, to_addr: string, tokenSymbol: string,
|
||||
value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,
|
||||
maxFeePerGas: string, chainId: string, uuid: string, eip1559Enabled: bool) =
|
||||
|
||||
method authenticateAndTransfer*(self: Module, from_addr: string, to_addr: string,
|
||||
tokenSymbol: string, value: string, uuid: string,
|
||||
priority: int, selectedRoutes: string) =
|
||||
self.tmpSendTransactionDetails.fromAddr = from_addr
|
||||
self.tmpSendTransactionDetails.toAddr = to_addr
|
||||
self.tmpSendTransactionDetails.tokenSymbol = tokenSymbol
|
||||
self.tmpSendTransactionDetails.value = value
|
||||
self.tmpSendTransactionDetails.gas = gas
|
||||
self.tmpSendTransactionDetails.gasPrice = gasPrice
|
||||
self.tmpSendTransactionDetails.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||
self.tmpSendTransactionDetails.maxFeePerGas = maxFeePerGas
|
||||
self.tmpSendTransactionDetails.chainId = chainId
|
||||
self.tmpSendTransactionDetails.uuid = uuid
|
||||
self.tmpSendTransactionDetails.eip1559Enabled = eip1559Enabled
|
||||
self.tmpSendTransactionDetails.priority = priority
|
||||
self.tmpSendTransactionDetails.selectedRoutes = selectedRoutes
|
||||
|
||||
if singletonInstance.userProfile.getIsKeycardUser():
|
||||
let keyUid = singletonInstance.userProfile.getKeyUid()
|
||||
|
@ -149,11 +140,9 @@ method authenticateAndTransfer*(self: Module, from_addr: string, to_addr: string
|
|||
##################################
|
||||
|
||||
method onUserAuthenticated*(self: Module, password: string) =
|
||||
self.controller.transfer(self.tmpSendTransactionDetails.fromAddr, self.tmpSendTransactionDetails.toAddr,
|
||||
self.tmpSendTransactionDetails.tokenSymbol, self.tmpSendTransactionDetails.value, self.tmpSendTransactionDetails.gas,
|
||||
self.tmpSendTransactionDetails.gasPrice, self.tmpSendTransactionDetails.maxPriorityFeePerGas,
|
||||
self.tmpSendTransactionDetails.maxFeePerGas, password, self.tmpSendTransactionDetails.chainId, self.tmpSendTransactionDetails.uuid,
|
||||
self.tmpSendTransactionDetails.eip1559Enabled)
|
||||
self.controller.transfer(self.tmpSendTransactionDetails.fromAddr, self.tmpSendTransactionDetails.toAddr,
|
||||
self.tmpSendTransactionDetails.tokenSymbol, self.tmpSendTransactionDetails.value, self.tmpSendTransactionDetails.uuid,
|
||||
self.tmpSendTransactionDetails.priority, self.tmpSendTransactionDetails.selectedRoutes, password)
|
||||
|
||||
method transactionWasSent*(self: Module, result: string) =
|
||||
self.view.transactionWasSent(result)
|
||||
|
@ -161,8 +150,8 @@ method transactionWasSent*(self: Module, result: string) =
|
|||
method suggestedFees*(self: Module, chainId: int): string =
|
||||
return self.controller.suggestedFees(chainId)
|
||||
|
||||
method suggestedRoutes*(self: Module, account: string, amount: float64, token: string, disabledChainIDs: seq[uint64]): string =
|
||||
return self.controller.suggestedRoutes(account, amount, token, disabledChainIDs)
|
||||
method suggestedRoutes*(self: Module, account: string, amount: UInt256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], priority: int, sendType: int): string =
|
||||
return self.controller.suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, priority, sendType)
|
||||
|
||||
method getChainIdForChat*(self: Module): int =
|
||||
return self.controller.getChainIdForChat()
|
||||
|
@ -175,3 +164,6 @@ method getEstimatedTime*(self: Module, chainId: int, maxFeePerGas: string): int
|
|||
|
||||
method getLastTxBlockNumber*(self: Module): string =
|
||||
return self.controller.getLastTxBlockNumber()
|
||||
|
||||
method suggestedRoutesReady*(self: Module, suggestedRoutes: string) =
|
||||
self.view.suggestedRoutesReady(suggestedRoutes)
|
||||
|
|
|
@ -117,30 +117,42 @@ QtObject:
|
|||
self.transactionSent(txResult)
|
||||
|
||||
proc authenticateAndTransfer*(self: View, from_addr: string, to_addr: string, tokenSymbol: string,
|
||||
value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,
|
||||
maxFeePerGas: string, chainId: string, uuid: string, eip1559Enabled: bool) {.slot.} =
|
||||
self.delegate.authenticateAndTransfer(from_addr, to_addr, tokenSymbol, value, gas, gasPrice,
|
||||
maxPriorityFeePerGas, maxFeePerGas, chainId, uuid, eip1559Enabled)
|
||||
value: string, uuid: string, priority: int, selectedRoutes: string) {.slot.} =
|
||||
self.delegate.authenticateAndTransfer(from_addr, to_addr, tokenSymbol, value, uuid, priority, selectedRoutes)
|
||||
|
||||
proc suggestedFees*(self: View, chainId: int): string {.slot.} =
|
||||
return self.delegate.suggestedFees(chainId)
|
||||
|
||||
proc suggestedRoutes*(self: View, account: string, amount: string, token: string, disabledChainIDs: string): string {.slot.} =
|
||||
var parsedAmount = 0.0
|
||||
var seqDisabledChainIds = seq[uint64] : @[]
|
||||
proc suggestedRoutes*(self: View, account: string, amount: string, token: string, disabledFromChainIDs: string, disabledToChainIDs: string, preferredChainIDs: string, priority: int, sendType: int): string {.slot.} =
|
||||
var parsedAmount = stint.u256("0")
|
||||
var seqPreferredChainIDs = seq[uint64] : @[]
|
||||
var seqDisabledFromChainIDs = seq[uint64] : @[]
|
||||
var seqDisabledToChainIDs = seq[uint64] : @[]
|
||||
|
||||
try:
|
||||
for chainID in disabledChainIDs.split(','):
|
||||
seqDisabledChainIds.add(parseUInt(chainID))
|
||||
for chainID in disabledFromChainIDs.split(','):
|
||||
seqDisabledFromChainIDs.add(parseUInt(chainID))
|
||||
except:
|
||||
discard
|
||||
|
||||
try:
|
||||
parsedAmount = parsefloat(amount)
|
||||
for chainID in disabledToChainIDs.split(','):
|
||||
seqDisabledToChainIDs.add(parseUInt(chainID))
|
||||
except:
|
||||
discard
|
||||
|
||||
return self.delegate.suggestedRoutes(account, parsedAmount, token, seqDisabledChainIds)
|
||||
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, priority, sendType)
|
||||
|
||||
proc getChainIdForChat*(self: View): int {.slot.} =
|
||||
return self.delegate.getChainIdForChat()
|
||||
|
@ -153,3 +165,5 @@ QtObject:
|
|||
|
||||
proc getLastTxBlockNumber*(self: View): string {.slot.} =
|
||||
return self.delegate.getLastTxBlockNumber()
|
||||
|
||||
proc suggestedRoutesReady*(self: View, suggestedRoutes: string) {.signal.}
|
||||
|
|
|
@ -25,6 +25,7 @@ type
|
|||
changePct24hour: string
|
||||
change24hour: string
|
||||
currencyPrice: float
|
||||
decimals: int
|
||||
|
||||
proc initItem*(
|
||||
name, symbol: string,
|
||||
|
@ -45,7 +46,8 @@ proc initItem*(
|
|||
changePctDay: string,
|
||||
changePct24hour: string,
|
||||
change24hour: string,
|
||||
currencyPrice: float
|
||||
currencyPrice: float,
|
||||
decimals: int,
|
||||
): Item =
|
||||
result.name = name
|
||||
result.symbol = symbol
|
||||
|
@ -68,6 +70,7 @@ proc initItem*(
|
|||
result.changePct24hour = changePct24hour
|
||||
result.change24hour = change24hour
|
||||
result.currencyPrice = currencyPrice
|
||||
result.decimals = decimals
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""AllTokensItem(
|
||||
|
@ -90,6 +93,7 @@ proc `$`*(self: Item): string =
|
|||
changePct24hour: {self.changePct24hour},
|
||||
change24hour: {self.change24hour},
|
||||
currencyPrice: {self.currencyPrice},
|
||||
decimals: {self.decimals},
|
||||
]"""
|
||||
|
||||
proc getName*(self: Item): string =
|
||||
|
@ -151,3 +155,6 @@ proc getChange24hour*(self: Item): string =
|
|||
|
||||
proc getCurrencyPrice*(self: Item): float =
|
||||
return self.currencyPrice
|
||||
|
||||
proc getDecimals*(self: Item): int =
|
||||
return self.decimals
|
||||
|
|
|
@ -24,6 +24,7 @@ type
|
|||
ChangePct24hour
|
||||
Change24hour
|
||||
CurrencyPrice
|
||||
Decimals
|
||||
|
||||
QtObject:
|
||||
type
|
||||
|
@ -79,6 +80,7 @@ QtObject:
|
|||
ModelRole.ChangePct24hour.int:"changePct24hour",
|
||||
ModelRole.Change24hour.int:"change24hour",
|
||||
ModelRole.CurrencyPrice.int:"currencyPrice",
|
||||
ModelRole.Decimals.int:"decimals",
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -132,6 +134,8 @@ QtObject:
|
|||
result = newQVariant(item.getChange24hour())
|
||||
of ModelRole.CurrencyPrice:
|
||||
result = newQVariant(item.getCurrencyPrice())
|
||||
of ModelRole.Decimals:
|
||||
result = newQVariant(item.getDecimals())
|
||||
|
||||
proc rowData(self: Model, index: int, column: string): string {.slot.} =
|
||||
if (index >= self.items.len):
|
||||
|
@ -157,6 +161,7 @@ QtObject:
|
|||
of "changePct24hour": result = $item.getChangePct24hour()
|
||||
of "change24hour": result = $item.getChange24hour()
|
||||
of "currencyPrice": result = $item.getCurrencyPrice()
|
||||
of "decimals": result = $item.getDecimals()
|
||||
|
||||
proc setItems*(self: Model, items: seq[Item]) =
|
||||
self.beginResetModel()
|
||||
|
@ -172,16 +177,30 @@ QtObject:
|
|||
|
||||
return false
|
||||
|
||||
proc hasGas*(self: Model, chainId: int, nativeGasSymbol: string, requiredGas: float): bool {.slot.} =
|
||||
proc hasGas*(self: Model, chainId: int, nativeGasSymbol: string, requiredGas: float): bool =
|
||||
for item in self.items:
|
||||
if(item.getSymbol() != nativeGasSymbol):
|
||||
continue
|
||||
if(item.getSymbol() != nativeGasSymbol):
|
||||
continue
|
||||
|
||||
for balance in item.getBalances().items:
|
||||
if (balance.chainId != chainId):
|
||||
continue
|
||||
for balance in item.getBalances().items:
|
||||
if (balance.chainId != chainId):
|
||||
continue
|
||||
|
||||
if(balance.balance >= requiredGas):
|
||||
return true
|
||||
if(balance.balance >= requiredGas):
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
proc getTokenBalanceOnChain*(self: Model, chainId: int, tokenSymbol: string): string =
|
||||
var tokenBalance: float64 = 0.0
|
||||
for item in self.items:
|
||||
if(item.getSymbol() != tokenSymbol):
|
||||
continue
|
||||
|
||||
for balance in item.getBalances().items:
|
||||
if (balance.chainId != chainId):
|
||||
continue
|
||||
|
||||
tokenBalance = balance.balance
|
||||
|
||||
return $tokenBalance
|
||||
|
|
|
@ -324,7 +324,7 @@ QtObject:
|
|||
self.pendingEnsUsernames.excl(ensUsername)
|
||||
|
||||
result = $(%* { "result": hash, "success": true })
|
||||
except RpcException as e:
|
||||
except Exception as e:
|
||||
error "error occurred", procName="release", msg = e.msg
|
||||
result = $(%* { "result": e.msg, "success": false })
|
||||
|
||||
|
@ -395,4 +395,4 @@ QtObject:
|
|||
return (response.result{"Scheme"}.getStr, response.result{"Host"}.getStr, response.result{"Path"}.getStr)
|
||||
except Exception as e:
|
||||
error "Error getting ENS resourceUrl", username=username, exception=e.msg
|
||||
raise
|
||||
raise
|
||||
|
|
|
@ -12,9 +12,17 @@ type
|
|||
maxFeePerGas*: Option[Uint256]
|
||||
value*: Option[Uint256] # (optional) integer of the value sent with this transaction.
|
||||
data*: string # the compiled code of a contract OR the hash of the invoked proc signature and encoded parameters. For details see Ethereum Contract ABI.
|
||||
input*: string
|
||||
nonce*: Option[Nonce] # (optional) integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce
|
||||
txType*: string
|
||||
|
||||
chainID*: Option[int] # (optional) chainID in case of a bridge hop transaction
|
||||
symbol*: Option[string] # (optional) symbol in case of a bridge hop transaction
|
||||
recipient*: Option[Address] # (optional) recipient in case of a bridge hop transaction
|
||||
amount*: Option[UInt256] # (optional) amount in case of a bridge hop transaction
|
||||
amountOutMin*: Option[UInt256] # (optional) amountOutMin in case of a bridge hop transaction
|
||||
bonderFee*: Option[string] # (optional) bonderFee in case of a bridge hop transaction
|
||||
|
||||
proc `%`*(x: TransactionDataDto): JsonNode =
|
||||
result = newJobject()
|
||||
result["from"] = %x.source
|
||||
|
@ -32,5 +40,31 @@ proc `%`*(x: TransactionDataDto): JsonNode =
|
|||
if x.value.isSome:
|
||||
result["value"] = %("0x" & x.value.unsafeGet.toHex)
|
||||
result["data"] = %x.data
|
||||
result["input"] = %x.input
|
||||
if x.nonce.isSome:
|
||||
result["nonce"] = %x.nonce.unsafeGet
|
||||
if x.chainID.isSome:
|
||||
result["chainId"] = %x.chainID.unsafeGet
|
||||
if x.symbol.isSome:
|
||||
result["symbol"] = %x.symbol.unsafeGet
|
||||
if x.recipient.isSome:
|
||||
result["recipient"] = %x.recipient.unsafeGet
|
||||
if x.amount.isSome:
|
||||
result["amount"] = %x.amount.unsafeGet
|
||||
if x.amountOutMin.isSome:
|
||||
result["amountOutMin"] = %x.amountOutMin.unsafeGet
|
||||
if x.bonderFee.isSome:
|
||||
result["bonderFee"] = %x.bonderFee.unsafeGet
|
||||
|
||||
type TransactionBridgeDto* = object
|
||||
bridgeName*: string
|
||||
chainID*: int
|
||||
simpleTx*: TransactionDataDto
|
||||
hopTx*: TransactionDataDto
|
||||
|
||||
proc `%`*(x: TransactionBridgeDto): JsonNode =
|
||||
result = newJobject()
|
||||
result["bridgeName"] = %x.bridgeName
|
||||
result["chainID"] = %x.chainID
|
||||
result["simpleTx"] = %x.simpleTx
|
||||
result["hopTx"] = %x.hopTx
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
# Async load transactions
|
||||
#################################################
|
||||
|
||||
import stint
|
||||
import ../../common/conversion as service_conversion
|
||||
|
||||
type
|
||||
LoadTransactionsTaskArg* = ref object of QObjectTaskArg
|
||||
chainId: int
|
||||
|
@ -21,3 +24,72 @@ const loadTransactionsTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.}
|
|||
"loadMore": arg.loadMore
|
||||
}
|
||||
arg.finish(output)
|
||||
|
||||
|
||||
type
|
||||
GetSuggestedRoutesTaskArg* = ref object of QObjectTaskArg
|
||||
account: string
|
||||
amount: Uint256
|
||||
token: string
|
||||
disabledFromChainIDs: seq[uint64]
|
||||
disabledToChainIDs: seq[uint64]
|
||||
preferredChainIDs: seq[uint64]
|
||||
priority: int
|
||||
sendType: int
|
||||
|
||||
proc getGasEthValue*(gweiValue: float, gasLimit: uint64): float =
|
||||
let weiValue = service_conversion.gwei2Wei(gweiValue) * u256(gasLimit)
|
||||
let ethValue = parseFloat(service_conversion.wei2Eth(weiValue))
|
||||
return ethValue
|
||||
|
||||
proc getFeesTotal*(paths: seq[TransactionPathDto]): seq[Fees] =
|
||||
if(paths.len == 0):
|
||||
return @[]
|
||||
|
||||
var fees: seq[Fees] = @[Fees(), Fees(), Fees()]
|
||||
for path in paths:
|
||||
var slowPrice = path.gasFees.gasPrice
|
||||
var optimalPrice = path.gasFees.gasPrice
|
||||
var fastPrice = path.gasFees.gasPrice
|
||||
if path.gasFees.eip1559Enabled:
|
||||
slowPrice = path.gasFees.maxFeePerGasL
|
||||
optimalPrice = path.gasFees.maxFeePerGasM
|
||||
fastPrice = path.gasFees.maxFeePerGasH
|
||||
|
||||
fees[0].totalFeesInEth += getGasEthValue(slowPrice, path.gasAmount)
|
||||
fees[1].totalFeesInEth += getGasEthValue(optimalPrice, path.gasAmount)
|
||||
fees[2].totalFeesInEth += getGasEthValue(fastPrice, path.gasAmount)
|
||||
|
||||
fees[0].totalTokenFees += path.tokenFees
|
||||
fees[1].totalTokenFees += path.tokenFees
|
||||
fees[2].totalTokenFees += path.tokenFees
|
||||
|
||||
# keeping it same for all as path will change when priority changes changing the time needed and so on
|
||||
fees[0].totalTime += path.estimatedTime
|
||||
fees[1].totalTime += path.estimatedTime
|
||||
fees[2].totalTime += path.estimatedTime
|
||||
return fees
|
||||
|
||||
const getSuggestedRoutesTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[GetSuggestedRoutesTaskArg](argEncoded)
|
||||
|
||||
try:
|
||||
let amountAsHex = "0x" & eth_utils.stripLeadingZeros(arg.amount.toHex)
|
||||
let response = eth.suggestedRoutes(arg.account, amountAsHex, arg.token, arg.disabledFromChainIDs, arg.disabledToChainIDs, arg.preferredChainIDs, arg.priority, arg.sendType).result
|
||||
|
||||
let bestPaths = response["Best"].getElems().map(x => x.toTransactionPathDto())
|
||||
let output = %*{
|
||||
"suggestedRoutes": SuggestedRoutesDto(
|
||||
best: bestPaths,
|
||||
candidates: response["Candidates"].getElems().map(x => x.toTransactionPathDto()),
|
||||
gasTimeEstimates: getFeesTotal(bestPaths)),
|
||||
"error": ""
|
||||
}
|
||||
arg.finish(output)
|
||||
|
||||
except Exception as e:
|
||||
let output = %* {
|
||||
"suggestedRoutes": SuggestedRoutesDto(best: @[], candidates: @[],gasTimeEstimates: @[]),
|
||||
"error": fmt"Error getting suggested routes: {e.msg}"
|
||||
}
|
||||
arg.finish(output)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import json, strutils, stint, json_serialization
|
||||
import json, strutils, stint, json_serialization, strformat
|
||||
include ../../common/json_utils
|
||||
import ../network/dto
|
||||
|
||||
type
|
||||
PendingTransactionTypeDto* {.pure.} = enum
|
||||
|
@ -99,3 +100,109 @@ proc cmpTransactions*(x, y: TransactionDto): int =
|
|||
if result == 0:
|
||||
result = cmp(x.nonce, y.nonce)
|
||||
|
||||
type
|
||||
SuggestedFeesDto* = ref object
|
||||
gasPrice*: float
|
||||
baseFee*: float
|
||||
maxPriorityFeePerGas*: float
|
||||
maxFeePerGasL*: float
|
||||
maxFeePerGasM*: float
|
||||
maxFeePerGasH*: float
|
||||
eip1559Enabled*: bool
|
||||
|
||||
proc toSuggestedFeesDto*(jsonObj: JsonNode): SuggestedFeesDto =
|
||||
result = SuggestedFeesDto()
|
||||
result.gasPrice = parseFloat(jsonObj["gasPrice"].getStr)
|
||||
result.baseFee = parseFloat(jsonObj["baseFee"].getStr)
|
||||
result.maxPriorityFeePerGas = parseFloat(jsonObj{"maxPriorityFeePerGas"}.getStr)
|
||||
result.maxFeePerGasL = parseFloat(jsonObj{"maxFeePerGasLow"}.getStr)
|
||||
result.maxFeePerGasM = parseFloat(jsonObj{"maxFeePerGasMedium"}.getStr)
|
||||
result.maxFeePerGasH = parseFloat(jsonObj{"maxFeePerGasHigh"}.getStr)
|
||||
result.eip1559Enabled = jsonObj{"eip1559Enabled"}.getbool
|
||||
|
||||
proc `$`*(self: SuggestedFeesDto): string =
|
||||
return fmt"""SuggestedFees(
|
||||
gasPrice:{self.gasPrice},
|
||||
baseFee:{self.baseFee},
|
||||
maxPriorityFeePerGas:{self.maxPriorityFeePerGas},
|
||||
maxFeePerGasL:{self.maxFeePerGasL},
|
||||
maxFeePerGasM:{self.maxFeePerGasM},
|
||||
maxFeePerGasH:{self.maxFeePerGasH},
|
||||
eip1559Enabled:{self.eip1559Enabled}
|
||||
)"""
|
||||
|
||||
type
|
||||
TransactionPathDto* = ref object
|
||||
bridgeName*: string
|
||||
fromNetwork*: NetworkDto
|
||||
toNetwork*: NetworkDto
|
||||
maxAmountIn* : UInt256
|
||||
amountIn*: UInt256
|
||||
amountOut*: UInt256
|
||||
gasAmount*: uint64
|
||||
gasFees*: SuggestedFeesDto
|
||||
tokenFees*: float
|
||||
bonderFees*: string
|
||||
cost*: float
|
||||
preferred*: bool
|
||||
estimatedTime*: int
|
||||
|
||||
proc `$`*(self: TransactionPathDto): string =
|
||||
return fmt"""TransactionPath(
|
||||
bridgeName:{self.bridgeName},
|
||||
fromNetwork:{self.fromNetwork},
|
||||
toNetwork:{self.toNetwork},
|
||||
maxAmountIn:{self.maxAmountIn},
|
||||
amountIn:{self.amountIn},
|
||||
amountOut:{self.amountOut},
|
||||
gasAmount:{self.gasAmount},
|
||||
tokenFees:{self.tokenFees},
|
||||
bonderFees:{self.bonderFees},
|
||||
cost:{self.cost},
|
||||
preferred:{self.preferred},
|
||||
estimatedTime:{self.estimatedTime}
|
||||
)"""
|
||||
|
||||
proc toTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto =
|
||||
result = TransactionPathDto()
|
||||
discard jsonObj.getProp("BridgeName", result.bridgeName)
|
||||
result.fromNetwork = Json.decode($jsonObj["From"], NetworkDto, allowUnknownFields = true)
|
||||
result.toNetwork = Json.decode($jsonObj["To"], NetworkDto, allowUnknownFields = true)
|
||||
result.gasFees = jsonObj["GasFees"].toSuggestedFeesDto()
|
||||
result.cost = parseFloat(jsonObj{"Cost"}.getStr)
|
||||
result.tokenFees = parseFloat(jsonObj{"TokenFees"}.getStr)
|
||||
result.bonderFees = jsonObj{"BonderFees"}.getStr
|
||||
result.maxAmountIn = stint.fromHex(UInt256, jsonObj{"MaxAmountIn"}.getStr)
|
||||
result.amountIn = stint.fromHex(UInt256, jsonObj{"AmountIn"}.getStr)
|
||||
result.amountOut = stint.fromHex(UInt256, jsonObj{"AmountOut"}.getStr)
|
||||
result.estimatedTime = jsonObj{"EstimatedTime"}.getInt
|
||||
discard jsonObj.getProp("GasAmount", result.gasAmount)
|
||||
discard jsonObj.getProp("Preferred", result.preferred)
|
||||
|
||||
proc convertToTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto =
|
||||
result = TransactionPathDto()
|
||||
discard jsonObj.getProp("bridgeName", result.bridgeName)
|
||||
result.fromNetwork = Json.decode($jsonObj["fromNetwork"], NetworkDto, allowUnknownFields = true)
|
||||
result.toNetwork = Json.decode($jsonObj["toNetwork"], NetworkDto, allowUnknownFields = true)
|
||||
result.gasFees = Json.decode($jsonObj["gasFees"], SuggestedFeesDto, allowUnknownFields = true)
|
||||
discard jsonObj.getProp("cost", result.cost)
|
||||
discard jsonObj.getProp("tokenFees", result.tokenFees)
|
||||
discard jsonObj.getProp("bonderFees", result.bonderFees)
|
||||
result.maxAmountIn = stint.u256(jsonObj{"maxAmountIn"}.getStr)
|
||||
result.amountIn = stint.u256(jsonObj{"amountIn"}.getStr)
|
||||
result.amountOut = stint.u256(jsonObj{"amountOut"}.getStr)
|
||||
result.estimatedTime = jsonObj{"estimatedTime"}.getInt
|
||||
discard jsonObj.getProp("gasAmount", result.gasAmount)
|
||||
discard jsonObj.getProp("preferred", result.preferred)
|
||||
|
||||
type
|
||||
Fees* = ref object
|
||||
totalFeesInEth*: float
|
||||
totalTokenFees*: float
|
||||
totalTime*: int
|
||||
|
||||
type
|
||||
SuggestedRoutesDto* = ref object
|
||||
best*: seq[TransactionPathDto]
|
||||
candidates*: seq[TransactionPathDto]
|
||||
gasTimeEstimates*: seq[Fees]
|
||||
|
|
|
@ -32,6 +32,7 @@ include ../../common/json_utils
|
|||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_TRANSACTIONS_LOADED* = "transactionsLoaded"
|
||||
const SIGNAL_TRANSACTION_SENT* = "transactionSent"
|
||||
const SIGNAL_SUGGESTED_ROUTES_READY* = "suggestedRoutesReady"
|
||||
|
||||
type
|
||||
EstimatedTime* {.pure.} = enum
|
||||
|
@ -59,18 +60,9 @@ type
|
|||
TransactionSentArgs* = ref object of Args
|
||||
result*: string
|
||||
|
||||
type SuggestedFees = object
|
||||
gasPrice: float
|
||||
baseFee: float
|
||||
maxPriorityFeePerGas: float
|
||||
maxFeePerGasL: float
|
||||
maxFeePerGasM: float
|
||||
maxFeePerGasH: float
|
||||
eip1559Enabled: bool
|
||||
|
||||
# Initial version of suggested routes is a list of network where the tx is possible
|
||||
type SuggestedRoutes = object
|
||||
networks: seq[NetworkDto]
|
||||
type
|
||||
SuggestedRoutesArgs* = ref object of Args
|
||||
suggestedRoutes*: string
|
||||
|
||||
QtObject:
|
||||
type Service* = ref object of QObject
|
||||
|
@ -253,145 +245,131 @@ QtObject:
|
|||
error "Error estimating gas", msg = e.msg
|
||||
return $(%* { "result": "-1", "success": false, "error": { "message": e.msg } })
|
||||
|
||||
proc transferEth(
|
||||
self: Service,
|
||||
from_addr: string,
|
||||
to_addr: string,
|
||||
value: string,
|
||||
gas: string,
|
||||
gasPrice: string,
|
||||
maxPriorityFeePerGas: string,
|
||||
maxFeePerGas: string,
|
||||
password: string,
|
||||
chainId: string,
|
||||
uuid: string,
|
||||
eip1559Enabled: bool,
|
||||
): bool {.slot.} =
|
||||
try:
|
||||
eth_utils.validateTransactionInput(from_addr, to_addr, assetAddress = "", value, gas,
|
||||
gasPrice, data = "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, uuid)
|
||||
|
||||
var tx = ens_utils.buildTransaction(parseAddress(from_addr), eth2Wei(parseFloat(value), 18),
|
||||
gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
|
||||
tx.to = parseAddress(to_addr).some
|
||||
|
||||
let response = transactions.createMultiTransaction(
|
||||
MultiTransactionDto(
|
||||
fromAddress: from_addr,
|
||||
toAddress: to_addr,
|
||||
fromAsset: "ETH",
|
||||
toAsset: "ETH",
|
||||
fromAmount: "0x" & tx.value.unsafeGet.toHex,
|
||||
multiTxtype: MultiTransactionType.MultiTransactionSend,
|
||||
),
|
||||
{chainId: @[tx]}.toTable,
|
||||
password,
|
||||
)
|
||||
let output = %* { "result": response.result{"hashes"}{chainId}[0].getStr, "success": %(response.error.isNil), "uuid": %uuid }
|
||||
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
|
||||
except Exception as e:
|
||||
error "Error sending eth transfer transaction", msg = e.msg
|
||||
return false
|
||||
return true
|
||||
|
||||
proc transferTokens*(
|
||||
proc transfer*(
|
||||
self: Service,
|
||||
from_addr: string,
|
||||
to_addr: string,
|
||||
tokenSymbol: string,
|
||||
value: string,
|
||||
gas: string,
|
||||
gasPrice: string,
|
||||
maxPriorityFeePerGas: string,
|
||||
maxFeePerGas: string,
|
||||
password: string,
|
||||
chainId: string,
|
||||
uuid: string,
|
||||
eip1559Enabled: bool,
|
||||
): bool =
|
||||
# TODO move this to another thread
|
||||
priority: int,
|
||||
selectedRoutes: string,
|
||||
password: string,
|
||||
) =
|
||||
try:
|
||||
let network = self.networkService.getNetwork(parseInt(chainId))
|
||||
let token = self.tokenService.findTokenBySymbol(network, tokenSymbol)
|
||||
let selRoutes = parseJson(selectedRoutes)
|
||||
let routes = selRoutes.getElems().map(x => x.convertToTransactionPathDto())
|
||||
|
||||
eth_utils.validateTransactionInput(from_addr, to_addr, token.addressAsString(), value, gas,
|
||||
gasPrice, data = "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, uuid)
|
||||
|
||||
var tx = ens_utils.buildTokenTransaction(parseAddress(from_addr), token.address,
|
||||
gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
|
||||
var paths: seq[TransactionBridgeDto] = @[]
|
||||
var isEthTx = false
|
||||
var chainID = 0
|
||||
var amountToSend: UInt256
|
||||
var toAddress: Address
|
||||
var data = ""
|
||||
|
||||
let weiValue = conversion.eth2Wei(parseFloat(value), token.decimals)
|
||||
let transfer = Transfer(
|
||||
to: parseAddress(to_addr),
|
||||
value: weiValue,
|
||||
)
|
||||
if(routes.len > 0):
|
||||
chainID = routes[0].fromNetwork.chainID
|
||||
let network = self.networkService.getNetwork(chainID)
|
||||
if network.nativeCurrencySymbol == tokenSymbol:
|
||||
isEthTx = true
|
||||
|
||||
if(isEthTx):
|
||||
amountToSend = conversion.eth2Wei(parseFloat(value), 18)
|
||||
toAddress = parseAddress(to_addr)
|
||||
else:
|
||||
let token = self.tokenService.findTokenBySymbol(network, tokenSymbol)
|
||||
amountToSend = conversion.eth2Wei(parseFloat(value), token.decimals)
|
||||
toAddress = token.address
|
||||
let transfer = Transfer(
|
||||
to: parseAddress(to_addr),
|
||||
value: amountToSend,
|
||||
)
|
||||
data = ERC20_procS.toTable["transfer"].encodeAbi(transfer)
|
||||
|
||||
for route in routes:
|
||||
var simpleTx = TransactionDataDto()
|
||||
var hopTx = TransactionDataDto()
|
||||
var txData = TransactionDataDto()
|
||||
var maxFees: float = 0
|
||||
var gasFees: string = ""
|
||||
|
||||
case(priority):
|
||||
of 0: maxFees = route.gasFees.maxFeePerGasL
|
||||
of 1: maxFees = route.gasFees.maxFeePerGasM
|
||||
of 2: maxFees = route.gasFees.maxFeePerGasH
|
||||
else: maxFees = 0
|
||||
|
||||
if( not route.gasFees.eip1559Enabled):
|
||||
gasFees = $route.gasFees.gasPrice
|
||||
|
||||
if(isEthTx) :
|
||||
txData = ens_utils.buildTransaction(parseAddress(from_addr), eth2Wei(parseFloat(value), 18),
|
||||
$route.gasAmount, gasFees, route.gasFees.eip1559Enabled, $route.gasFees.maxPriorityFeePerGas, $maxFees)
|
||||
txData.to = parseAddress(to_addr).some
|
||||
else:
|
||||
txData = ens_utils.buildTokenTransaction(parseAddress(from_addr), toAddress,
|
||||
$route.gasAmount, gasFees, route.gasFees.eip1559Enabled, $route.gasFees.maxPriorityFeePerGas, $maxFees)
|
||||
txData.data = data
|
||||
|
||||
var path = TransactionBridgeDto(bridgeName: route.bridgeName, chainID: route.fromNetwork.chainId)
|
||||
if(route.bridgeName == "Simple"):
|
||||
path.simpleTx = txData
|
||||
else:
|
||||
hopTx = txData
|
||||
hopTx.chainID = route.toNetwork.chainId.some
|
||||
hopTx.symbol = tokenSymbol.some
|
||||
hopTx.recipient = parseAddress(to_addr).some
|
||||
hopTx.amount = route.amountIn.some
|
||||
hopTx.bonderFee = route.bonderFees.some
|
||||
path.hopTx = hopTx
|
||||
|
||||
paths.add(path)
|
||||
|
||||
tx.data = ERC20_procS.toTable["transfer"].encodeAbi(transfer)
|
||||
let response = transactions.createMultiTransaction(
|
||||
MultiTransactionDto(
|
||||
fromAddress: from_addr,
|
||||
toAddress: to_addr,
|
||||
fromAsset: tokenSymbol,
|
||||
toAsset: tokenSymbol,
|
||||
fromAmount: "0x" & weiValue.toHex,
|
||||
fromAmount: "0x" & amountToSend.toHex,
|
||||
multiTxtype: MultiTransactionType.MultiTransactionSend,
|
||||
),
|
||||
{chainId: @[tx]}.toTable,
|
||||
),
|
||||
paths,
|
||||
password,
|
||||
)
|
||||
let txHash = response.result.getStr
|
||||
let output = %* { "result": response.result{"hashes"}{chainId}[0].getStr, "success":true, "uuid": %uuid }
|
||||
let output = %* {"result": response.result{"hashes"}, "success":true, "uuid": %uuid }
|
||||
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
|
||||
except Exception as e:
|
||||
error "Error sending token transfer transaction", msg = e.msg
|
||||
return false
|
||||
return true
|
||||
let err = fmt"Error sending token transfer transaction: {e.msg}"
|
||||
let output = %* {"success":false, "uuid": %uuid, "error":fmt"Error sending token transfer transaction: {e.msg}"}
|
||||
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
|
||||
|
||||
proc transfer*(
|
||||
self: Service,
|
||||
from_addr: string,
|
||||
to_addr: string,
|
||||
assetSymbol: string,
|
||||
value: string,
|
||||
gas: string,
|
||||
gasPrice: string,
|
||||
maxPriorityFeePerGas: string,
|
||||
maxFeePerGas: string,
|
||||
password: string,
|
||||
chainId: string,
|
||||
uuid: string,
|
||||
eip1559Enabled: bool,
|
||||
): bool =
|
||||
let network = self.networkService.getNetwork(parseInt(chainId))
|
||||
|
||||
if network.nativeCurrencySymbol == assetSymbol:
|
||||
return self.transferEth(from_addr, to_addr, value, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, chainId, uuid, eip1559Enabled)
|
||||
|
||||
return self.transferTokens(from_addr, to_addr, assetSymbol, value, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, chainId, uuid, eip1559Enabled)
|
||||
|
||||
proc suggestedFees*(self: Service, chainId: int): SuggestedFees =
|
||||
proc suggestedFees*(self: Service, chainId: int): SuggestedFeesDto =
|
||||
try:
|
||||
let response = eth.suggestedFees(chainId).result
|
||||
return SuggestedFees(
|
||||
gasPrice: parseFloat(response{"gasPrice"}.getStr),
|
||||
baseFee: parseFloat(response{"baseFee"}.getStr),
|
||||
maxPriorityFeePerGas: parseFloat(response{"maxPriorityFeePerGas"}.getStr),
|
||||
maxFeePerGasL: parseFloat(response{"maxFeePerGasLow"}.getStr),
|
||||
maxFeePerGasM: parseFloat(response{"maxFeePerGasMedium"}.getStr),
|
||||
maxFeePerGasH: parseFloat(response{"maxFeePerGasHigh"}.getStr),
|
||||
eip1559Enabled: response{"eip1559Enabled"}.getbool,
|
||||
)
|
||||
return response.toSuggestedFeesDto()
|
||||
except Exception as e:
|
||||
error "Error getting suggested fees", msg = e.msg
|
||||
|
||||
proc suggestedRoutes*(self: Service, account: string, amount: float64, token: string, disabledChainIDs: seq[uint64]): SuggestedRoutes =
|
||||
try:
|
||||
let response = eth.suggestedRoutes(account, amount, token, disabledChainIDs)
|
||||
return SuggestedRoutes(
|
||||
networks: Json.decode($response.result{"networks"}, seq[NetworkDto], allowUnknownFields = true)
|
||||
)
|
||||
except Exception as e:
|
||||
error "Error getting suggested routes", msg = e.msg
|
||||
proc suggestedRoutesReady*(self: Service, suggestedRoutes: string) {.slot.} =
|
||||
self.events.emit(SIGNAL_SUGGESTED_ROUTES_READY, SuggestedRoutesArgs(suggestedRoutes: suggestedRoutes))
|
||||
|
||||
proc suggestedRoutes*(self: Service, account: string, amount: Uint256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], priority: int, sendType: int): SuggestedRoutesDto =
|
||||
let arg = GetSuggestedRoutesTaskArg(
|
||||
tptr: cast[ByteAddress](getSuggestedRoutesTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "suggestedRoutesReady",
|
||||
account: account,
|
||||
amount: amount,
|
||||
token: token,
|
||||
disabledFromChainIDs: disabledFromChainIDs,
|
||||
disabledToChainIDs: disabledToChainIDs,
|
||||
preferredChainIDs: preferredChainIDs,
|
||||
priority: priority,
|
||||
sendType: sendType
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc fetchCryptoServices*(self: Service): seq[CryptoRampDto] =
|
||||
try:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import json
|
||||
import json, stint
|
||||
import ./core, ./response_type
|
||||
|
||||
export response_type
|
||||
|
@ -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: float64, token: string, disabledChainIDs: seq[uint64]): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [account, amount, token, disabledChainIDs]
|
||||
proc suggestedRoutes*(account: string, amount: string, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], priority: int, sendType: int): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [sendType, account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs, priority]
|
||||
return core.callPrivateRPC("wallet_getSuggestedRoutes", payload)
|
||||
|
|
|
@ -45,7 +45,7 @@ proc getPendingOutboundTransactionsByAddress*(chainIds: seq[int], address: strin
|
|||
proc fetchCryptoServices*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
result = core.callPrivateRPC("wallet_getCryptoOnRamps", %* [])
|
||||
|
||||
proc createMultiTransaction*(multiTransaction: MultiTransactionDto, data: Table[string, seq[TransactionDataDto]], password: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
proc createMultiTransaction*(multiTransaction: MultiTransactionDto, data: seq[TransactionBridgeDto], password: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
var hashed_password = "0x" & $keccak_256.digest(password)
|
||||
let payload = %* [multiTransaction, data, hashed_password]
|
||||
result = core.callPrivateRPC("wallet_createMultiTransaction", payload)
|
||||
result = core.callPrivateRPC("wallet_createMultiTransaction", payload)
|
||||
|
|
|
@ -33,9 +33,6 @@ mainWallet_Send_Popup_Password_Input = {"container": statusDesktop_mainWindow, "
|
|||
mainWallet_Send_Popup_Asset_Selector = {"container": statusDesktop_mainWindow, "objectName": "assetSelectorButton", "type": "StatusComboBox"}
|
||||
mainWallet_Send_Popup_Asset_List = {"container": statusDesktop_mainWindow, "objectName": "assetSelectorList", "type": "StatusListView"}
|
||||
mainWallet_Send_Popup_GasPrice_Input = {"container": statusDesktop_mainWindow, "objectName": "gasPriceSelectorInput", "type": "StyledTextField"}
|
||||
mainWallet_Send_Popup_GasSelector_LowGas_Button = {"container": statusDesktop_mainWindow, "objectName": "GasSelector_lowGasButton", "type": "GasSelectorButton"}
|
||||
mainWallet_Send_Popup_GasSelector_OptimalGas_Button = {"container": statusDesktop_mainWindow, "objectName": "GasSelector_optimalGasButton", "type": "GasSelectorButton"}
|
||||
mainWallet_Send_Popup_GasSelector_HighGas_Button = {"container": statusDesktop_mainWindow, "objectName": "GasSelector_highGasButton", "type": "GasSelectorButton"}
|
||||
|
||||
# Add account popup:
|
||||
mainWallet_Add_Account_Popup_Main = {"container": statusDesktop_mainWindow, "objectName": "AddAccountModalContent", "type": "StatusScrollView", "visible": True}
|
||||
|
|
|
@ -178,6 +178,8 @@ Rectangle {
|
|||
id: basicInput
|
||||
StatusBaseText {
|
||||
id: secondaryLabel
|
||||
Layout.maximumWidth: root.width - 12
|
||||
elide: Text.ElideRight
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
@ -246,6 +248,8 @@ Rectangle {
|
|||
}
|
||||
StatusBaseText {
|
||||
id: tertiaryText
|
||||
Layout.maximumWidth: root.width - 12
|
||||
elide: Text.ElideRight
|
||||
font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="20" height="15" viewBox="0 0 20 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 1.00413H6.22C5.11 -0.225866 3.21 -0.315866 2 0.804134C1.36 1.36413 1 2.16413 1 3.00413V12.0041C0.734784 12.0041 0.48043 12.1095 0.292893 12.297C0.105357 12.4846 0 12.7389 0 13.0041V14.0041H8V13.0041C8 12.7389 7.89464 12.4846 7.70711 12.297C7.51957 12.1095 7.26522 12.0041 7 12.0041V5.00413H18C18.5304 5.00413 19.0391 4.79342 19.4142 4.41835C19.7893 4.04327 20 3.53457 20 3.00413C20 2.4737 19.7893 1.96499 19.4142 1.58992C19.0391 1.21485 18.5304 1.00413 18 1.00413ZM5.5 12.0041H2.5V5.60413C3.43 6.14413 4.57 6.14413 5.5 5.60413V12.0041ZM4 4.50413C3.60218 4.50413 3.22064 4.3461 2.93934 4.06479C2.65804 3.78349 2.5 3.40196 2.5 3.00413C2.5 2.60631 2.65804 2.22478 2.93934 1.94347C3.22064 1.66217 3.60218 1.50413 4 1.50413C4.39782 1.50413 4.77936 1.66217 5.06066 1.94347C5.34196 2.22478 5.5 2.60631 5.5 3.00413C5.5 3.40196 5.34196 3.78349 5.06066 4.06479C4.77936 4.3461 4.39782 4.50413 4 4.50413V4.50413ZM8.5 4.00413L7 2.00413H8.5L10 4.00413H8.5ZM12.5 4.00413L11 2.00413H12.5L14 4.00413H12.5ZM16.5 4.00413L15 2.00413H16.5L18 4.00413H16.5Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg width="17" height="18" viewBox="0 0 17 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.75 0.00390625C1.67893 0.00390625 0 1.68284 0 3.75391V15.7539C0 16.7204 0.783502 17.5039 1.75 17.5039H7.75C8.7165 17.5039 9.5 16.7204 9.5 15.7539V10.0039H9.75C10.4404 10.0039 11 10.5635 11 11.2539V14.7539C11 16.2727 12.2312 17.5039 13.75 17.5039C15.2688 17.5039 16.5 16.2727 16.5 14.7539V6.11521C16.5 5.03385 16.0332 4.00513 15.2194 3.29305L12.2439 0.689474C11.9322 0.416712 11.4583 0.4483 11.1856 0.760028C10.9128 1.07176 10.9444 1.54558 11.2561 1.81834L12.744 3.12024C11.7328 3.44065 11 4.3867 11 5.50391C11 6.88462 12.1193 8.00391 13.5 8.00391C14.0628 8.00391 14.5822 7.81793 15 7.50409V14.7539C15 15.4443 14.4404 16.0039 13.75 16.0039C13.0596 16.0039 12.5 15.4443 12.5 14.7539V11.2539C12.5 9.73512 11.2688 8.50391 9.75 8.50391H9.5V3.75391C9.5 1.68284 7.82107 0.00390625 5.75 0.00390625H3.75ZM1.5 3.75391C1.5 2.51127 2.50736 1.50391 3.75 1.50391H5.75C6.99264 1.50391 8 2.51127 8 3.75391V6.25391L1.5 6.25391V3.75391ZM1.5 7.75391V15.7539C1.5 15.892 1.61193 16.0039 1.75 16.0039H7.75C7.88807 16.0039 8 15.892 8 15.7539V7.75391L1.5 7.75391ZM13.5 4.50391C12.9477 4.50391 12.5 4.95162 12.5 5.50391C12.5 6.05619 12.9477 6.50391 13.5 6.50391C14.0523 6.50391 14.5 6.05619 14.5 5.50391C14.5 4.95162 14.0523 4.50391 13.5 4.50391Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -59,12 +59,10 @@ StatusSectionLayout {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO we'll need a new dialog at one point because this one is not using the same call, but it's good for now
|
||||
property Component sendTransactionModalComponent: SignTransactionModal {
|
||||
property Component sendTransactionModalComponent: SendModal {
|
||||
anchors.centerIn: parent
|
||||
store: root.globalStore
|
||||
contactsStore: root.globalStore.profileSectionStore.contactsStore
|
||||
chainId: root.globalStore.getChainIdForBrowser()
|
||||
selectedAccount: WalletStore.dappBrowserAccount
|
||||
preSelectedAsset: _internal.getEthAsset()
|
||||
}
|
||||
|
||||
property Component signMessageModalComponent: SignMessageModal {}
|
||||
|
@ -142,6 +140,22 @@ StatusSectionLayout {
|
|||
findBar.reset();
|
||||
browserHeader.addressBar.text = Web3ProviderStore.obtainAddress(currentWebView.url)
|
||||
}
|
||||
|
||||
function getEthAsset() {
|
||||
let assetsList = WalletStore.dappBrowserAccount.assets
|
||||
for(var i=0; i< assetsList.count;i++) {
|
||||
if("ETH" === assetsList.rowData(i, "symbol"))
|
||||
return {
|
||||
name: assetsList.rowData(i, "name"),
|
||||
symbol: assetsList.rowData(i, "symbol"),
|
||||
totalBalance: assetsList.rowData(i, "totalBalance"),
|
||||
totalCurrencyBalance: assetsList.rowData(i, "totalCurrencyBalance"),
|
||||
balances: assetsList.rowData(i, "balances"),
|
||||
decimals: assetsList.rowData(i, "decimals")
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
centerPanel: Rectangle {
|
||||
|
@ -156,26 +170,8 @@ StatusSectionLayout {
|
|||
}
|
||||
createSendTransactionModalComponent: function(request) {
|
||||
return _internal.sendTransactionModalComponent.createObject(root, {
|
||||
trxData: request.payload.params[0].data || "",
|
||||
selectedAccount: {
|
||||
name: WalletStore.dappBrowserAccount.name,
|
||||
address: request.payload.params[0].from,
|
||||
iconColor: WalletStore.dappBrowserAccount.color,
|
||||
assets: WalletStore.dappBrowserAccount.assets
|
||||
},
|
||||
selectedRecipient: {
|
||||
address: request.payload.params[0].to,
|
||||
identicon: "",
|
||||
name: RootStore.activeChannelName,
|
||||
type: RecipientSelector.Type.Address
|
||||
},
|
||||
selectedAsset: {
|
||||
name: "ETH",
|
||||
symbol: "ETH",
|
||||
address: Constants.zeroAddress
|
||||
},
|
||||
selectedFiatAmount: "42", // TODO calculate that
|
||||
selectedAmount: RootStore.getWei2Eth(request.payload.params[0].value, 18)
|
||||
preSelectedRecipient: request.payload.params[0].to,
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(RootStore.getWei2Eth(request.payload.params[0].value, 18)),
|
||||
})
|
||||
}
|
||||
createSignMessageModalComponent: function(request) {
|
||||
|
|
|
@ -91,22 +91,27 @@ QtObject {
|
|||
request.payload.method === "eth_sendTransaction") {
|
||||
var acc = WalletStore.dappBrowserAccount
|
||||
const value = RootStore.getWei2Eth(request.payload.params[0].value, 18);
|
||||
const sendDialog = createSendTransactionModalComponent(request)
|
||||
const sendDialog = createSendTransactionModalComponent(request, requestType)
|
||||
|
||||
sendDialog.sendTransaction = function (selectedGasLimit, selectedGasPrice, selectedTipLimit, selectedOverallLimit, enteredPassword) {
|
||||
let trx = request.payload.params[0]
|
||||
// TODO: use bignumber instead of floats
|
||||
trx.value = RootStore.getEth2Hex(parseFloat(value))
|
||||
trx.gas = "0x" + parseInt(selectedGasLimit, 10).toString(16)
|
||||
trx.maxPriorityFeePerGas = RootStore.getGwei2Hex(parseFloat(selectedTipLimit))
|
||||
trx.maxFeePerGas = RootStore.getGwei2Hex(parseFloat(selectedOverallLimit))
|
||||
sendDialog.sendTransaction = function () {
|
||||
if(sendDialog.bestRoutes.length === 1) {
|
||||
let path = sendDialog.bestRoutes[0]
|
||||
let eip1559Enabled = path.gasFees.eip1559Enabled
|
||||
let maxFeePerGas = (sendDialog.selectedPriority === 0) ? path.gasFees.maxFeePerGasL:
|
||||
(sendDialog.selectedPriority === 1) ? path.gasFees.maxFeePerGasM:
|
||||
path.gasFees.maxFeePerGasH
|
||||
let trx = request.payload.params[0]
|
||||
// TODO: use bignumber instead of floats
|
||||
trx.value = RootStore.getEth2Hex(parseFloat(value))
|
||||
trx.gas = "0x" + parseInt(path.gasAmount, 10).toString(16)
|
||||
trx.maxPriorityFeePerGas = RootStore.getGwei2Hex(parseFloat(eip1559Enabled ? path.gasFees.maxPriorityFeePerGas : "0"))
|
||||
trx.maxFeePerGas = RootStore.getGwei2Hex(parseFloat(eip1559Enabled ? maxFeePerGas : path.gasFees.gasPrice))
|
||||
|
||||
request.payload.password = enteredPassword
|
||||
request.payload.params[0] = trx
|
||||
request.payload.params[0] = trx
|
||||
|
||||
Web3ProviderStore.web3ProviderInst.postMessage(request.payload.method, requestType, JSON.stringify(request))
|
||||
sendDialog.close()
|
||||
sendDialog.destroy()
|
||||
Web3ProviderStore.web3ProviderInst.authenticateToPostMessage(request.payload.method, requestType, JSON.stringify(request))
|
||||
sendDialog.close()
|
||||
}
|
||||
}
|
||||
|
||||
sendDialog.open();
|
||||
|
|
|
@ -2,6 +2,7 @@ import QtQuick 2.13
|
|||
|
||||
import utils 1.0
|
||||
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||
import shared.stores 1.0
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
@ -138,10 +139,6 @@ QtObject {
|
|||
|
||||
property var userProfileInst: userProfile
|
||||
|
||||
property var accounts: walletSectionAccounts.model
|
||||
property var currentAccount: walletSectionCurrent
|
||||
|
||||
property string currentCurrency: walletSection.currentCurrency
|
||||
property string signingPhrase: walletSection.signingPhrase
|
||||
|
||||
property string channelEmoji: chatCommunitySectionModule && chatCommunitySectionModule.emoji ? chatCommunitySectionModule.emoji : ""
|
||||
|
@ -475,38 +472,46 @@ QtObject {
|
|||
return userProfile.getPubKey()
|
||||
}
|
||||
|
||||
// Needed for TX in chat for stickers and via contact
|
||||
|
||||
property var accounts: walletSectionAccounts.model
|
||||
property var currentAccount: walletSectionCurrent
|
||||
property string currentCurrency: walletSection.currentCurrency
|
||||
property CurrenciesStore currencyStore: CurrenciesStore { }
|
||||
property var allNetworks: networksModule.all
|
||||
property var savedAddressesModel: walletSectionSavedAddresses.model
|
||||
|
||||
property var disabledChainIds: []
|
||||
property var disabledChainIdsFromList: []
|
||||
property var disabledChainIdsToList: []
|
||||
|
||||
function addRemoveDisabledChain(suggestedRoutes, chainID, isDisbaled) {
|
||||
if(isDisbaled) {
|
||||
for(var i = 0; i < suggestedRoutes.length;i++) {
|
||||
if(suggestedRoutes[i].chainId === chainID) {
|
||||
disabledChainIds.push(suggestedRoutes[i].chainId)
|
||||
}
|
||||
}
|
||||
function addRemoveDisabledFromChain(chainID, isDisabled) {
|
||||
if(isDisabled) {
|
||||
disabledChainIdsFromList.push(chainID)
|
||||
}
|
||||
else {
|
||||
for(var i = 0; i < disabledChainIds.length;i++) {
|
||||
if(disabledChainIds[i] === chainID) {
|
||||
disabledChainIds.splice(i, 1)
|
||||
for(var i = 0; i < disabledChainIdsFromList.length;i++) {
|
||||
if(disabledChainIdsFromList[i] === chainID) {
|
||||
disabledChainIdsFromList.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkIfDisabledByUser(chainID) {
|
||||
for(var i = 0; i < disabledChainIds.length;i++) {
|
||||
if(disabledChainIds[i] === chainID) {
|
||||
return true
|
||||
function addRemoveDisabledToChain(chainID, isDisabled) {
|
||||
if(isDisabled) {
|
||||
disabledChainIdsToList.push(chainID)
|
||||
}
|
||||
else {
|
||||
for(var i = 0; i < disabledChainIdsToList.length;i++) {
|
||||
if(disabledChainIdsToList[i] === chainID) {
|
||||
disabledChainIdsToList.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function getFiatValue(balance, cryptoSymbo, fiatSymbol) {
|
||||
return profileSectionModule.ensUsernamesModule.getFiatValue(balance, cryptoSymbo, fiatSymbol)
|
||||
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
|
||||
return profileSectionModule.ensUsernamesModule.getFiatValue(balance, cryptoSymbol, fiatSymbol)
|
||||
}
|
||||
|
||||
function acceptRequestTransaction(transactionHash, messageId, signature) {
|
||||
|
@ -533,12 +538,8 @@ QtObject {
|
|||
return walletSectionTransactions.estimateGas(from_addr, to, assetSymbol, value === "" ? "0.00" : value, chainId, data)
|
||||
}
|
||||
|
||||
function transfer(from, to, address, tokenSymbol, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, chainId, uuid, eip1559Enabled) {
|
||||
return walletSectionTransactions.authenticateAndTransfer(
|
||||
from, to, address, tokenSymbol, amount, gasLimit,
|
||||
gasPrice, tipLimit, overallLimit, chainId, uuid,
|
||||
eip1559Enabled
|
||||
);
|
||||
function authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, priority, selectedRoutes) {
|
||||
walletSectionTransactions.authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, priority, selectedRoutes)
|
||||
}
|
||||
|
||||
function getAccountNameByAddress(address) {
|
||||
|
@ -558,7 +559,34 @@ QtObject {
|
|||
return JSON.parse(walletSectionTransactions.suggestedFees(chainId))
|
||||
}
|
||||
|
||||
function suggestedRoutes(account, amount, token, disabledChainIds) {
|
||||
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token, disabledChainIds)).networks
|
||||
function suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, priority, sendType) {
|
||||
walletSectionTransactions.suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, priority, sendType)
|
||||
}
|
||||
|
||||
function resolveENS(value) {
|
||||
mainModuleInst.resolveENS(value, "")
|
||||
}
|
||||
|
||||
function getWei2Eth(wei) {
|
||||
return globalUtils.wei2Eth(wei,18)
|
||||
}
|
||||
|
||||
function getEth2Wei(eth) {
|
||||
return globalUtils.eth2Wei(eth, 18)
|
||||
}
|
||||
|
||||
function switchAccount(newIndex) {
|
||||
if(Constants.isCppApp)
|
||||
walletSectionAccounts.switchAccount(newIndex)
|
||||
else
|
||||
walletSection.switchAccount(newIndex)
|
||||
}
|
||||
|
||||
function getEtherscanLink() {
|
||||
return profileSectionModule.ensUsernamesModule.getEtherscanLink()
|
||||
}
|
||||
|
||||
function hex2Eth(value) {
|
||||
return globalUtils.hex2Eth(value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,10 +38,10 @@ QtObject {
|
|||
return stickersModule.getCurrentCurrency()
|
||||
}
|
||||
|
||||
function getFiatValue(balance, cryptoSymbo, fiatSymbol) {
|
||||
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
|
||||
if(!root.stickersModule)
|
||||
return ""
|
||||
return stickersModule.getFiatValue(balance, cryptoSymbo, fiatSymbol)
|
||||
return stickersModule.getFiatValue(balance, cryptoSymbol, fiatSymbol)
|
||||
}
|
||||
|
||||
function getGasEthValue(gweiValue, gasLimit) {
|
||||
|
@ -62,10 +62,10 @@ QtObject {
|
|||
return stickersModule.estimate(packId, selectedAccount, price, uuid)
|
||||
}
|
||||
|
||||
function buy(packId, address, price, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
|
||||
function authenticateAndBuy(packId, address, price, gasLimit, gasPrice, tipLimit, overallLimit, eip1559Enabled) {
|
||||
if(!root.stickersModule)
|
||||
return ""
|
||||
return stickersModule.buy(packId, address, price, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled)
|
||||
return stickersModule.authenticateAndBuy(packId, address, price, gasLimit, gasPrice, tipLimit, overallLimit, eip1559Enabled)
|
||||
}
|
||||
|
||||
function getChainIdForStickers() {
|
||||
|
|
|
@ -365,12 +365,9 @@ Item {
|
|||
id: cmpSendTransactionWithEns
|
||||
SendModal {
|
||||
id: sendTransactionWithEns
|
||||
store: root.rootStore
|
||||
contactsStore: root.contactsStore
|
||||
onClosed: {
|
||||
destroy()
|
||||
}
|
||||
launchedFromChat: true
|
||||
preSelectedRecipient: {
|
||||
parentModule.prepareChatContentModuleForChatId(activeChatId)
|
||||
let chatContentModule = parentModule.getChatContentModule()
|
||||
|
|
|
@ -46,10 +46,10 @@ QtObject {
|
|||
return ensUsernamesModule.setPubKeyGasEstimate(ensUsername, address)
|
||||
}
|
||||
|
||||
function setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled) {
|
||||
function authenticateAndSetPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, eip1559Enabled) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
return ensUsernamesModule.authenticateAndSetPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, eip1559Enabled)
|
||||
}
|
||||
|
||||
function getEtherscanLink() {
|
||||
|
@ -68,16 +68,10 @@ QtObject {
|
|||
globalUtils.copyToClipboard(value)
|
||||
}
|
||||
|
||||
function releaseEnsEstimate(ensUsername, address) {
|
||||
function authenticateAndReleaseEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, eip1559Enabled) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.releaseEnsEstimate(ensUsername, address)
|
||||
}
|
||||
|
||||
function releaseEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.releaseEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
|
||||
return ensUsernamesModule.authenticateAndReleaseEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, eip1559Enabled)
|
||||
}
|
||||
|
||||
function ensConnectOwnedUsername(name, isStatus) {
|
||||
|
@ -92,16 +86,10 @@ QtObject {
|
|||
return ensUsernamesModule.getEnsRegisteredAddress()
|
||||
}
|
||||
|
||||
function registerEnsGasEstimate(ensUsername, address) {
|
||||
function authenticateAndRegisterEns(ensUsername, address, gasLimit, gasPrice, tipLimit, overallLimit, eip1559Enabled) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return 0
|
||||
return ensUsernamesModule.registerEnsGasEstimate(ensUsername, address)
|
||||
}
|
||||
|
||||
function registerEns(ensUsername, address, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.registerEns(ensUsername, address, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled)
|
||||
return
|
||||
ensUsernamesModule.authenticateAndRegisterEns(ensUsername, address, gasLimit, gasPrice, tipLimit, overallLimit, eip1559Enabled)
|
||||
}
|
||||
|
||||
function getEnsRegistry() {
|
||||
|
@ -128,10 +116,10 @@ QtObject {
|
|||
return ensUsernamesModule.getCurrentCurrency()
|
||||
}
|
||||
|
||||
function getFiatValue(balance, cryptoSymbo, fiatSymbol) {
|
||||
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getFiatValue(balance, cryptoSymbo, fiatSymbol)
|
||||
return ensUsernamesModule.getFiatValue(balance, cryptoSymbol, fiatSymbol)
|
||||
}
|
||||
|
||||
function getGasEthValue(gweiValue, gasLimit) {
|
||||
|
@ -159,9 +147,5 @@ QtObject {
|
|||
return ""
|
||||
return ensUsernamesModule.getChainIdForEns()
|
||||
}
|
||||
|
||||
function suggestedRoutes(account, amount, token) {
|
||||
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token)).networks
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import StatusQ.Components 0.1
|
|||
|
||||
import utils 1.0
|
||||
import shared.status 1.0
|
||||
import shared.popups 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
@ -103,35 +104,73 @@ Item {
|
|||
|
||||
Component {
|
||||
id: transactionDialogComponent
|
||||
StatusETHTransactionModal {
|
||||
ensUsernamesStore: root.ensUsernamesStore
|
||||
contactsStore: root.contactsStore
|
||||
ensUsername: root.username
|
||||
chainId: root.ensUsernamesStore.getChainIdForEns()
|
||||
title: qsTr("Release your username")
|
||||
onClosed: {
|
||||
destroy()
|
||||
SendModal {
|
||||
id: releaseEnsModal
|
||||
modalHeader: qsTr("Release your username")
|
||||
interactive: false
|
||||
sendType: Constants.SendType.ENSRelease
|
||||
preSelectedRecipient: root.ensUsernamesStore.getEnsRegisteredAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(0)
|
||||
preSelectedAsset: {
|
||||
let assetsList = releaseEnsModal.store.currentAccount.assets
|
||||
for(var i=0; i< assetsList.count;i++) {
|
||||
if("ETH" === assetsList.rowData(i, "symbol"))
|
||||
return {
|
||||
name: assetsList.rowData(i, "name"),
|
||||
symbol: assetsList.rowData(i, "symbol"),
|
||||
totalBalance: assetsList.rowData(i, "totalBalance"),
|
||||
totalCurrencyBalance: assetsList.rowData(i, "totalCurrencyBalance"),
|
||||
balances: assetsList.rowData(i, "balances"),
|
||||
decimals: assetsList.rowData(i, "decimals")
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
estimateGasFunction: function(selectedAccount) {
|
||||
if (username === "" || !selectedAccount) return 100000;
|
||||
return root.ensUsernamesStore.releaseEnsEstimate(username, selectedAccount.address)
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.length === 1) {
|
||||
let path = bestRoutes[0]
|
||||
let eip1559Enabled = path.gasFees.eip1559Enabled
|
||||
let maxFeePerGas = (selectedPriority === 0) ? path.gasFees.maxFeePerGasL:
|
||||
(selectedPriority === 1) ? path.gasFees.maxFeePerGasM:
|
||||
path.gasFees.maxFeePerGasH
|
||||
root.ensUsernamesStore.authenticateAndReleaseEns(
|
||||
root.username,
|
||||
selectedAccount.address,
|
||||
path.gasAmount,
|
||||
eip1559Enabled ? "" : path.gasFees.gasPrice,
|
||||
eip1559Enabled ? path.gasFees.maxPriorityFeePerGas : "",
|
||||
eip1559Enabled ? maxFeePerGas: path.gasFees.gasPrice,
|
||||
eip1559Enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
onSendTransaction: function(userAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled){
|
||||
return root.ensUsernamesStore.releaseEns(username,
|
||||
userAddress,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
tipLimit,
|
||||
overallLimit,
|
||||
password,
|
||||
eip1559Enabled)
|
||||
Connections {
|
||||
target: root.ensUsernamesStore.ensUsernamesModule
|
||||
onTransactionWasSent: {
|
||||
try {
|
||||
let response = JSON.parse(txResult)
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(response.result)) {
|
||||
releaseEnsModal.setSendTxError()
|
||||
return
|
||||
}
|
||||
releaseEnsModal.sendingError.text = response.result
|
||||
return releaseEnsModal.sendingError.open()
|
||||
}
|
||||
usernameReleased(username);
|
||||
let url = `${releaseEnsModal.store.getEtherscanLink()}/${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.close()
|
||||
}
|
||||
}
|
||||
onSuccess: function(){
|
||||
usernameReleased(username);
|
||||
}
|
||||
|
||||
width: 475
|
||||
height: 500
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import shared 1.0
|
|||
import shared.panels 1.0
|
||||
import shared.status 1.0
|
||||
import shared.controls 1.0
|
||||
import shared.popups 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
@ -57,35 +58,72 @@ Item {
|
|||
|
||||
Component {
|
||||
id: transactionDialogComponent
|
||||
StatusETHTransactionModal {
|
||||
ensUsernamesStore: root.ensUsernamesStore
|
||||
contactsStore: root.contactsStore
|
||||
chainId: root.ensUsernamesStore.getChainIdForEns()
|
||||
title: qsTr("Connect username with your pubkey")
|
||||
onClosed: {
|
||||
destroy()
|
||||
SendModal {
|
||||
id: releaseEnsModal
|
||||
modalHeader: qsTr("Connect username with your pubkey")
|
||||
interactive: false
|
||||
sendType: Constants.SendType.ENSSetPubKey
|
||||
preSelectedRecipient: root.ensUsernamesStore.getEnsRegisteredAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(0)
|
||||
preSelectedAsset: {
|
||||
let assetsList = releaseEnsModal.store.currentAccount.assets
|
||||
for(var i=0; i< assetsList.count;i++) {
|
||||
if("ETH" === assetsList.rowData(i, "symbol"))
|
||||
return {
|
||||
name: assetsList.rowData(i, "name"),
|
||||
symbol: assetsList.rowData(i, "symbol"),
|
||||
totalBalance: assetsList.rowData(i, "totalBalance"),
|
||||
totalCurrencyBalance: assetsList.rowData(i, "totalCurrencyBalance"),
|
||||
balances: assetsList.rowData(i, "balances"),
|
||||
decimals: assetsList.rowData(i, "decimals")
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
estimateGasFunction: function(selectedAccount) {
|
||||
if (ensUsername.text === "" || !selectedAccount) return 80000;
|
||||
return root.ensUsernamesStore.setPubKeyGasEstimate(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ), selectedAccount.address)
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.length === 1) {
|
||||
let path = bestRoutes[0]
|
||||
let eip1559Enabled = path.gasFees.eip1559Enabled
|
||||
root.ensUsernamesStore.authenticateAndSetPubKey(
|
||||
ensUsername.text + (isStatus ? ".stateofus.eth" : "" ),
|
||||
selectedAccount.address,
|
||||
path.gasAmount,
|
||||
eip1559Enabled ? "" : path.gasFees.gasPrice,
|
||||
"",
|
||||
"",
|
||||
eip1559Enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password, eip1559Enabled) {
|
||||
return root.ensUsernamesStore.setPubKey(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ),
|
||||
selectedAddress,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
"",
|
||||
"",
|
||||
password,
|
||||
eip1559Enabled)
|
||||
Connections {
|
||||
target: root.ensUsernamesStore.ensUsernamesModule
|
||||
onTransactionWasSent: {
|
||||
try {
|
||||
let response = JSON.parse(txResult)
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(response.result)) {
|
||||
releaseEnsModal.setSendTxError()
|
||||
return
|
||||
}
|
||||
releaseEnsModal.sendingError.text = response.result
|
||||
return releaseEnsModal.sendingError.open()
|
||||
}
|
||||
usernameUpdated(ensUsername.text);
|
||||
let url = `${releaseEnsModal.store.getEtherscanLink()}/${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.close()
|
||||
}
|
||||
}
|
||||
onSuccess: function(){
|
||||
usernameUpdated(ensUsername.text);
|
||||
}
|
||||
|
||||
width: 475
|
||||
height: 500
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
|
@ -44,35 +44,71 @@ Item {
|
|||
function closed() {
|
||||
this.active = false // kill an opened instance
|
||||
}
|
||||
sourceComponent: StatusSNTTransactionModal {
|
||||
store: root.ensUsernamesStore
|
||||
contactsStore: root.contactsStore
|
||||
stickersStore: root.stickersStore
|
||||
asyncGasEstimateTarget: root.stickersStore.stickersModule
|
||||
assetPrice: "10"
|
||||
chainId: root.ensUsernamesStore.getChainIdForEns()
|
||||
contractAddress: root.ensUsernamesStore.getEnsRegisteredAddress()
|
||||
estimateGasFunction: function(selectedAccount, uuid) {
|
||||
if (username === "" || !selectedAccount) return 380000;
|
||||
return root.ensUsernamesStore.registerEnsGasEstimate(username, selectedAccount.address)
|
||||
sourceComponent: SendModal {
|
||||
id: buyEnsModal
|
||||
interactive: false
|
||||
sendType: Constants.SendType.ENSRegister
|
||||
preSelectedRecipient: root.ensUsernamesStore.getEnsRegisteredAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(10)
|
||||
preSelectedAsset: {
|
||||
let assetsList = buyEnsModal.store.currentAccount.assets
|
||||
for(var i=0; i< assetsList.count;i++) {
|
||||
let symbol = JSON.parse(root.stickersStore.getStatusToken()).symbol
|
||||
if(symbol === assetsList.rowData(i, "symbol"))
|
||||
return {
|
||||
name: assetsList.rowData(i, "name"),
|
||||
symbol: assetsList.rowData(i, "symbol"),
|
||||
totalBalance: assetsList.rowData(i, "totalBalance"),
|
||||
totalCurrencyBalance: assetsList.rowData(i, "totalCurrencyBalance"),
|
||||
balances: assetsList.rowData(i, "balances"),
|
||||
decimals: assetsList.rowData(i, "decimals")
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
|
||||
return root.ensUsernamesStore.registerEns(
|
||||
username,
|
||||
selectedAddress,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
tipLimit,
|
||||
overallLimit,
|
||||
password,
|
||||
eip1559Enabled,
|
||||
)
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.length === 1) {
|
||||
let path = bestRoutes[0]
|
||||
let eip1559Enabled = path.gasFees.eip1559Enabled
|
||||
let maxFeePerGas = (selectedPriority === 0) ? path.gasFees.maxFeePerGasL:
|
||||
(selectedPriority === 1) ? path.gasFees.maxFeePerGasM:
|
||||
path.gasFees.maxFeePerGasH
|
||||
root.ensUsernamesStore.authenticateAndRegisterEns(
|
||||
username,
|
||||
selectedAccount.address,
|
||||
path.gasAmount,
|
||||
eip1559Enabled ? "" : path.gasFees.gasPrice,
|
||||
eip1559Enabled ? path.gasFees.maxPriorityFeePerGas : "",
|
||||
eip1559Enabled ? maxFeePerGas: path.gasFees.gasPrice,
|
||||
eip1559Enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
onSuccess: function(){
|
||||
usernameRegistered(username);
|
||||
}
|
||||
onClosed: {
|
||||
transactionDialog.closed()
|
||||
Connections {
|
||||
target: root.ensUsernamesStore.ensUsernamesModule
|
||||
onTransactionWasSent: {
|
||||
try {
|
||||
let response = JSON.parse(txResult)
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(response.result)) {
|
||||
buyEnsModal.setSendTxError()
|
||||
return
|
||||
}
|
||||
buyEnsModal.sendingError.text = response.result
|
||||
return buyEnsModal.sendingError.open()
|
||||
}
|
||||
usernameRegistered(username)
|
||||
let url = `${buyEnsModal.store.getEtherscanLink()}/${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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -322,15 +322,6 @@ Item {
|
|||
|
||||
Connections {
|
||||
target: ensView.ensUsernamesStore.ensUsernamesModule
|
||||
onTransactionWasSent: {
|
||||
let url = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txResult}`;
|
||||
Global.displayToastMessage(qsTr("Transaction pending..."),
|
||||
qsTr("View on etherscan"),
|
||||
"",
|
||||
true,
|
||||
Constants.ephemeralNotificationType.normal,
|
||||
url);
|
||||
}
|
||||
onTransactionCompleted: {
|
||||
let title = ""
|
||||
switch(trxType){
|
||||
|
|
|
@ -19,7 +19,7 @@ Item {
|
|||
property var store
|
||||
property var contactsStore
|
||||
property var emojiPopup: null
|
||||
property var sendModal
|
||||
property var sendModalPopup
|
||||
|
||||
function showSigningPhrasePopup(){
|
||||
if(!hideSignPhraseModal && !RootStore.hideSignPhraseModal){
|
||||
|
@ -46,7 +46,7 @@ Item {
|
|||
anchors.left: parent ? parent.left: undefined
|
||||
anchors.right: parent ? parent.right: undefined
|
||||
contactsStore: root.contactsStore
|
||||
sendModal: root.sendModal
|
||||
sendModal: root.sendModalPopup
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ Item {
|
|||
RightTabView {
|
||||
store: root.store
|
||||
contactsStore: root.contactsStore
|
||||
sendModal: root.sendModal
|
||||
sendModal: root.sendModalPopup
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,30 +79,6 @@ QtObject {
|
|||
|
||||
property var allNetworks: networksModule.all
|
||||
|
||||
property var disabledChainIds: []
|
||||
|
||||
function addRemoveDisabledChain(suggestedRoutes, chainID, isDisbaled) {
|
||||
if(isDisbaled) {
|
||||
disabledChainIds.push(chainID)
|
||||
}
|
||||
else {
|
||||
for(var i = 0; i < disabledChainIds.length;i++) {
|
||||
if(disabledChainIds[i] === chainID) {
|
||||
disabledChainIds.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkIfDisabledByUser(chainID) {
|
||||
for(var i = 0; i < disabledChainIds.length;i++) {
|
||||
if(disabledChainIds[i] === chainID) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function getEtherscanLink() {
|
||||
return profileSectionModule.ensUsernamesModule.getEtherscanLink()
|
||||
}
|
||||
|
@ -135,21 +111,13 @@ QtObject {
|
|||
function estimateGas(from_addr, to, assetSymbol, value, chainId, data) {
|
||||
return walletSectionTransactions.estimateGas(from_addr, to, assetSymbol, value, chainId, data)
|
||||
}
|
||||
function getFiatValue(balance, cryptoSymbo, fiatSymbol) {
|
||||
return profileSectionStore.ensUsernamesStore.getFiatValue(balance, cryptoSymbo, fiatSymbol)
|
||||
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
|
||||
return profileSectionStore.ensUsernamesStore.getFiatValue(balance, cryptoSymbol, fiatSymbol)
|
||||
}
|
||||
function getGasEthValue(gweiValue, gasLimit) {
|
||||
return profileSectionStore.ensUsernamesStore.getGasEthValue(gweiValue, gasLimit)
|
||||
}
|
||||
|
||||
function authenticateAndTransfer(from, to, tokenSymbol, amount, gasLimit, gasPrice, tipLimit, overallLimit, chainId, uuid, eip1559Enabled) {
|
||||
walletSectionTransactions.authenticateAndTransfer(
|
||||
from, to, tokenSymbol, amount, gasLimit,
|
||||
gasPrice, tipLimit, overallLimit, chainId, uuid,
|
||||
eip1559Enabled
|
||||
);
|
||||
}
|
||||
|
||||
function suggestedFees(chainId) {
|
||||
return JSON.parse(walletSectionTransactions.suggestedFees(chainId))
|
||||
}
|
||||
|
@ -166,10 +134,6 @@ QtObject {
|
|||
return walletSectionTransactions.getChainIdForBrowser()
|
||||
}
|
||||
|
||||
function suggestedRoutes(account, amount, token, disabledChainIds) {
|
||||
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token, disabledChainIds)).networks
|
||||
}
|
||||
|
||||
function hex2Eth(value) {
|
||||
return globalUtils.hex2Eth(value)
|
||||
}
|
||||
|
|
|
@ -818,7 +818,7 @@ Item {
|
|||
store: appMain.rootStore
|
||||
contactsStore: appMain.rootStore.profileSectionStore.contactsStore
|
||||
emojiPopup: statusEmojiPopup
|
||||
sendModal: sendModal
|
||||
sendModalPopup: sendModal
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1045,8 +1045,6 @@ Item {
|
|||
}
|
||||
property var selectedAccount
|
||||
sourceComponent: SendModal {
|
||||
store: appMain.rootStore
|
||||
contactsStore: appMain.rootStore.profileSectionStore.contactsStore
|
||||
onClosed: {
|
||||
sendModal.closed()
|
||||
}
|
||||
|
|
|
@ -15,8 +15,9 @@ ColumnLayout {
|
|||
|
||||
property bool transferPossible: false
|
||||
property double amountToSend: 0
|
||||
property bool isLoading: true
|
||||
|
||||
visible: !balancedExceededError.transferPossible && balancedExceededError.amountToSend > 0
|
||||
visible: !balancedExceededError.transferPossible && balancedExceededError.amountToSend > 0 || isLoading
|
||||
|
||||
StatusIcon {
|
||||
Layout.preferredHeight: 20
|
||||
|
@ -24,6 +25,14 @@ ColumnLayout {
|
|||
Layout.alignment: Qt.AlignHCenter
|
||||
icon: "cancel"
|
||||
color: Theme.palette.dangerColor1
|
||||
visible: !isLoading
|
||||
}
|
||||
StatusLoadingIndicator {
|
||||
Layout.preferredHeight: 24
|
||||
Layout.preferredWidth: 24
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
color: Theme.palette.baseColor1
|
||||
visible: isLoading
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
@ -31,7 +40,7 @@ ColumnLayout {
|
|||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Theme.palette.dangerColor1
|
||||
text: balancedExceededError.amountToSend > 0 ? qsTr("Balance exceeded"): qsTr("No networks available")
|
||||
text: isLoading ? qsTr("Calculating fees"): balancedExceededError.amountToSend > 0 ? qsTr("Balance exceeded"): qsTr("No networks available")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,437 +8,195 @@ import shared.controls 1.0
|
|||
import shared.controls.chat 1.0
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: parent.width
|
||||
height: visible ? Style.current.smallPadding + prioritytext.height +
|
||||
(advancedMode ? advancedModeItemGroup.height : selectorButtons.height) : 0
|
||||
|
||||
property var suggestedFees: ({
|
||||
eip1559Enabled: true
|
||||
})
|
||||
property var getGasGweiValue: function () {}
|
||||
property string selectedTokenSymbol
|
||||
property string currentCurrency
|
||||
property string currentCurrencySymbol
|
||||
property bool advancedOrCustomMode: false
|
||||
|
||||
property var bestRoutes: []
|
||||
property var estimatedGasFeesTime: []
|
||||
|
||||
property int selectedPriority: 1
|
||||
property double selectedGasEthValue
|
||||
property string selectedGasFiatValue
|
||||
property string selectedTimeEstimate
|
||||
|
||||
property var getGasEthValue: function () {}
|
||||
property var getFiatValue: function () {}
|
||||
property var getEstimatedTime: function () {}
|
||||
property string defaultCurrency: "USD"
|
||||
property alias selectedGasPrice: inputGasPrice.text
|
||||
property alias selectedGasLimit: inputGasLimit.text
|
||||
property string defaultGasLimit: "0"
|
||||
property string maxFiatFees: selectedGasFiatValue + root.defaultCurrency.toUpperCase()
|
||||
property int estimatedTxTimeFlag: Constants.transactionEstimatedTime.unknown
|
||||
property int chainId: 1
|
||||
|
||||
property alias selectedTipLimit: inputPerGasTipLimit.text
|
||||
property alias selectedOverallLimit: inputGasPrice.text
|
||||
|
||||
property double selectedGasEthValue
|
||||
property double selectedGasFiatValue
|
||||
property string greaterThan0ErrorMessage: qsTr("Must be greater than 0")
|
||||
property string invalidInputErrorMessage: qsTr("This needs to be a number")
|
||||
property string noInputErrorMessage: qsTr("Please enter an amount")
|
||||
property bool isValid: true
|
||||
readonly property string uuid: Utils.uuid()
|
||||
|
||||
property bool advancedMode: false
|
||||
|
||||
// TODO: change these values false once EIP1559 suggestions are revised
|
||||
property double perGasTipLimitFloor: 1 // Matches status-mobile minimum-priority-fee
|
||||
property double perGasTipLimitAverage: formatDec(root.suggestedFees.maxPriorityFeePerGas, 2) // 1.5 // Matches status-mobile average-priority-fee
|
||||
|
||||
|
||||
property bool showPriceLimitWarning : false
|
||||
property bool showTipLimitWarning : false
|
||||
|
||||
function formatDec(num, dec){
|
||||
return Math.round((num + Number.EPSILON) * Math.pow(10, dec)) / Math.pow(10, dec)
|
||||
enum Priority {
|
||||
SLOW, // 0
|
||||
OPTIMAL, // 1
|
||||
FAST // 2
|
||||
}
|
||||
|
||||
function updateGasEthValue() {
|
||||
// causes error on application load without this null check
|
||||
if (!inputGasPrice || !inputGasLimit) {
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
Qt.callLater(function () {
|
||||
let ethValue = root.getGasEthValue(inputGasPrice.text, inputGasLimit.text)
|
||||
let fiatValue = root.getFiatValue(ethValue, "ETH", root.defaultCurrency)
|
||||
selectedGasEthValue = ethValue
|
||||
selectedGasFiatValue = fiatValue
|
||||
root.estimatedTxTimeFlag = root.getEstimatedTime(root.chainId, inputGasPrice.text)
|
||||
})
|
||||
enum EstimatedTime {
|
||||
Unknown = 0,
|
||||
LessThanOneMin,
|
||||
LessThanThreeMins,
|
||||
LessThanFiveMins,
|
||||
MoreThanFiveMins
|
||||
}
|
||||
|
||||
function appendError(accum, error, nonBlocking = false) {
|
||||
return accum + ` <span class="${nonBlocking ? "non-blocking" : ""}">${error}.</span>`
|
||||
}
|
||||
|
||||
|
||||
function checkLimits(){
|
||||
if(!root.suggestedFees.eip1559Enabled) return;
|
||||
|
||||
let inputTipLimit = parseFloat(inputPerGasTipLimit.text || "0.00")
|
||||
let inputOverallLimit = parseFloat(inputGasPrice.text || "0.00")
|
||||
let gasLimit = parseInt(inputGasLimit.text, 10)
|
||||
errorsText.text = "";
|
||||
|
||||
showPriceLimitWarning = false
|
||||
showTipLimitWarning = false
|
||||
|
||||
let errorMsg = "";
|
||||
|
||||
if(gasLimit < 21000) {
|
||||
errorMsg = appendError(errorMsg, qsTr("Min 21000 units"))
|
||||
} else if (gasLimit < parseInt(defaultGasLimit)){
|
||||
errorMsg = appendError(errorMsg, qsTr("Not enough gas").arg(perGasTipLimitAverage), true)
|
||||
}
|
||||
|
||||
// Per-gas tip limit rules
|
||||
if(inputTipLimit < perGasTipLimitFloor){
|
||||
errorMsg = appendError(errorMsg, qsTr("Miners will currently not process transactions with a tip below %1 Gwei, the average is %2 Gwei").arg(perGasTipLimitFloor).arg(perGasTipLimitAverage))
|
||||
showTipLimitWarning = true
|
||||
} else if (inputTipLimit < perGasTipLimitAverage) {
|
||||
errorMsg = appendError(errorMsg, qsTr("The average miner tip is %1 Gwei").arg(perGasTipLimitAverage), true)
|
||||
}
|
||||
|
||||
errorsText.text = `<style type="text/css">span { color: "#ff0000" } span.non-blocking { color: "#FE8F59" }</style>${errorMsg}`
|
||||
|
||||
}
|
||||
|
||||
function checkOptimal() {
|
||||
if (!optimalGasButton.checked) {
|
||||
optimalGasButton.toggle()
|
||||
QtObject {
|
||||
id: d
|
||||
function getLabelForEstimatedTxTime(estimatedFlag) {
|
||||
switch(estimatedFlag) {
|
||||
case GasSelector.EstimatedTime.Unknown:
|
||||
return qsTr("~ Unknown")
|
||||
case GasSelector.EstimatedTime.LessThanOneMin :
|
||||
return qsTr("< 1 minute")
|
||||
case GasSelector.EstimatedTime.LessThanThreeMins :
|
||||
return qsTr("< 3 minutes")
|
||||
case GasSelector.EstimatedTime.LessThanFiveMins:
|
||||
return qsTr("< 5 minutes")
|
||||
default:
|
||||
return qsTr("> 5 minutes")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validate() {
|
||||
// causes error on application load without a null check
|
||||
if (!inputGasLimit || !inputGasPrice || !inputPerGasTipLimit) {
|
||||
return
|
||||
}
|
||||
width: parent.width
|
||||
height: visible ? (!advancedOrCustomMode ? selectorButtons.height : advancedGasSelector.height) + Style.current.halfPadding : 0
|
||||
|
||||
inputGasLimit.validationError = ""
|
||||
inputGasPrice.validationError = ""
|
||||
inputPerGasTipLimit.validationError = ""
|
||||
|
||||
const noInputLimit = inputGasLimit.text === ""
|
||||
const noInputPrice = inputGasPrice.text === ""
|
||||
const noPerGasTip = inputPerGasTipLimit.text === ""
|
||||
|
||||
if (noInputLimit) {
|
||||
inputGasLimit.validationError = root.noInputErrorMessage
|
||||
}
|
||||
|
||||
if (noInputPrice) {
|
||||
inputGasPrice.validationError = root.noInputErrorMessage
|
||||
}
|
||||
|
||||
if (root.suggestedFees.eip1559Enabled && noPerGasTip) {
|
||||
inputPerGasTipLimit.validationError = root.noInputErrorMessage
|
||||
}
|
||||
|
||||
if (isNaN(inputGasLimit.text)) {
|
||||
inputGasLimit.validationError = invalidInputErrorMessage
|
||||
}
|
||||
if (isNaN(inputGasPrice.text)) {
|
||||
inputGasPrice.validationError = invalidInputErrorMessage
|
||||
}
|
||||
|
||||
if (root.suggestedFees.eip1559Enabled && isNaN(inputPerGasTipLimit.text)) {
|
||||
inputPerGasTipLimit.validationError = invalidInputErrorMessage
|
||||
}
|
||||
|
||||
let inputLimit = parseFloat(inputGasLimit.text || "0.00")
|
||||
let inputPrice = parseFloat(inputGasPrice.text || "0.00")
|
||||
let inputTipLimit = parseFloat(inputPerGasTipLimit.text || "0.00")
|
||||
|
||||
if (inputLimit <= 0.00) {
|
||||
inputGasLimit.validationError = root.greaterThan0ErrorMessage
|
||||
}
|
||||
|
||||
if (inputPrice <= 0.00) {
|
||||
inputGasPrice.validationError = root.greaterThan0ErrorMessage
|
||||
}
|
||||
if (root.suggestedFees.eip1559Enabled && inputTipLimit <= 0.00) {
|
||||
inputPerGasTipLimit.validationError = root.greaterThan0ErrorMessage
|
||||
}
|
||||
return inputGasLimit.validationError === "" && inputGasPrice.validationError === "" && (!root.suggestedFees.eip1559Enabled || (root.suggestedFees.eip1559Enabled && inputPerGasTipLimit.validationError === ""))
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
id: prioritytext
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text: root.suggestedFees.eip1559Enabled ? qsTr("Priority") : qsTr("Gas Price")
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: 13
|
||||
color: Style.current.textColor
|
||||
visible: root.suggestedFees.eip1559Enabled && advancedMode
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: baseFeeText
|
||||
visible: root.suggestedFees.eip1559Enabled && advancedMode
|
||||
anchors.top: parent.top
|
||||
anchors.left: prioritytext.right
|
||||
anchors.leftMargin: Style.current.smallPadding
|
||||
text: qsTr("Current base fee: %1 %2").arg(root.suggestedFees.baseFee).arg("Gwei")
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: 13
|
||||
color: Style.current.secondaryText
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
anchors.verticalCenter: prioritytext.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.bigPadding
|
||||
height: 22
|
||||
verticalPadding: 2
|
||||
size: StatusBaseButton.Size.Tiny
|
||||
visible: root.suggestedFees.eip1559Enabled
|
||||
text: advancedMode ?
|
||||
qsTr("Use suggestions") :
|
||||
qsTr("Use custom")
|
||||
font.pixelSize: 13
|
||||
onClicked: advancedMode = !advancedMode
|
||||
}
|
||||
|
||||
Row {
|
||||
id: selectorButtons
|
||||
visible: root.suggestedFees.eip1559Enabled && !advancedMode
|
||||
anchors.top: prioritytext.bottom
|
||||
visible: !root.advancedOrCustomMode
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.current.halfPadding
|
||||
spacing: 11
|
||||
|
||||
GasSelectorButton {
|
||||
id: lowGasButton
|
||||
objectName: "GasSelector_lowGasButton"
|
||||
primaryText: qsTr("Low")
|
||||
gasLimit: inputGasLimit ? inputGasLimit.text : ""
|
||||
getGasEthValue: root.getGasEthValue
|
||||
getFiatValue: root.getFiatValue
|
||||
defaultCurrency: root.defaultCurrency
|
||||
price: {
|
||||
if (!root.suggestedFees.eip1559Enabled) return root.suggestedFees.gasPrice;
|
||||
return formatDec(root.suggestedFees.maxFeePerGasL, 6)
|
||||
}
|
||||
onCheckedChanged: {
|
||||
if(checked) {
|
||||
if (root.suggestedFees.eip1559Enabled){
|
||||
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
|
||||
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasL, 2);
|
||||
} else {
|
||||
inputGasPrice.text = price
|
||||
}
|
||||
root.updateGasEthValue()
|
||||
root.checkLimits()
|
||||
}
|
||||
}
|
||||
ButtonGroup {
|
||||
buttons: gasPrioRepeater.children
|
||||
}
|
||||
|
||||
GasSelectorButton {
|
||||
id: optimalGasButton
|
||||
objectName: "GasSelector_optimalGasButton"
|
||||
primaryText: qsTr("Optimal")
|
||||
price: {
|
||||
if (!root.suggestedFees.eip1559Enabled) {
|
||||
// Setting the gas price field here because the binding didn't work
|
||||
inputGasPrice.text = root.suggestedFees.gasPrice
|
||||
return root.suggestedFees.gasPrice
|
||||
}
|
||||
|
||||
return formatDec(root.suggestedFees.maxFeePerGasM, 6)
|
||||
}
|
||||
gasLimit: inputGasLimit ? inputGasLimit.text : ""
|
||||
getGasEthValue: root.getGasEthValue
|
||||
getFiatValue: root.getFiatValue
|
||||
defaultCurrency: root.defaultCurrency
|
||||
onCheckedChanged: {
|
||||
if(checked) {
|
||||
if (root.suggestedFees.eip1559Enabled){
|
||||
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
|
||||
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasM, 2);
|
||||
} else {
|
||||
inputGasPrice.text = root.suggestedFees.gasPrice
|
||||
Repeater {
|
||||
id: gasPrioRepeater
|
||||
model: root.estimatedGasFeesTime
|
||||
GasSelectorButton {
|
||||
objectName: "GasSelector_slowGasButton"
|
||||
property double totalFeesInFiat: parseFloat(root.getFiatValue(modelData.totalFeesInEth, "ETH", currentCurrency)) +
|
||||
parseFloat(root.getFiatValue(modelData.totalTokenFees, root.selectedTokenSymbol, currentCurrency))
|
||||
primaryText: index === 0 ? qsTr("Slow") : index === 1 ? qsTr("Optimal"): qsTr("Fast")
|
||||
timeText: index === selectedPriority ? d.getLabelForEstimatedTxTime(modelData.totalTime): qsTr("~ Unknown")
|
||||
totalGasEthValue: modelData.totalFeesInEth
|
||||
totalGasFiatValue: index === selectedPriority ? "%1 %2".arg(LocaleUtils.numberToLocaleString(totalFeesInFiat)).arg(root.currentCurrency.toUpperCase()): qsTr("...")
|
||||
checked: index === selectedPriority
|
||||
onCheckedChanged: {
|
||||
if(checked) {
|
||||
root.selectedPriority = index
|
||||
root.selectedGasEthValue = totalGasEthValue
|
||||
root.selectedGasFiatValue = totalGasFiatValue
|
||||
root.selectedTimeEstimate = timeText
|
||||
}
|
||||
root.updateGasEthValue()
|
||||
root.checkLimits()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GasSelectorButton {
|
||||
id: highGasButton
|
||||
objectName: "GasSelector_highGasButton"
|
||||
primaryText: qsTr("High")
|
||||
price: {
|
||||
if (!root.suggestedFees.eip1559Enabled) return root.suggestedFees.gasPrice;
|
||||
return formatDec(root.suggestedFees.maxFeePerGasH,6);
|
||||
}
|
||||
gasLimit: inputGasLimit ? inputGasLimit.text : ""
|
||||
getGasEthValue: root.getGasEthValue
|
||||
getFiatValue: root.getFiatValue
|
||||
defaultCurrency: root.defaultCurrency
|
||||
onCheckedChanged: {
|
||||
if(checked) {
|
||||
if (root.suggestedFees.eip1559Enabled){
|
||||
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
|
||||
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasH, 2);
|
||||
} else {
|
||||
inputGasPrice.text = price
|
||||
}
|
||||
root.updateGasEthValue()
|
||||
root.checkLimits()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: advancedModeItemGroup
|
||||
anchors.top: prioritytext.bottom
|
||||
anchors.topMargin: 14
|
||||
visible: !root.suggestedFees.eip1559Enabled || root.advancedMode
|
||||
Column {
|
||||
id: advancedGasSelector
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.current.halfPadding
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 10
|
||||
visible: root.advancedOrCustomMode
|
||||
|
||||
Input {
|
||||
id: inputGasLimit
|
||||
label: qsTr("Gas amount limit")
|
||||
text: "21000"
|
||||
inputLabel.color: Style.current.secondaryText
|
||||
customHeight: 56
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: root.suggestedFees.eip1559Enabled ? inputPerGasTipLimit.left : inputGasPrice.left
|
||||
anchors.rightMargin: Style.current.padding
|
||||
placeholderText: "21000"
|
||||
validator: IntValidator{
|
||||
bottom: 1
|
||||
}
|
||||
validationErrorAlignment: TextEdit.AlignRight
|
||||
validationErrorTopMargin: 8
|
||||
onTextChanged: {
|
||||
if (root.validate()) {
|
||||
root.updateGasEthValue()
|
||||
root.checkLimits()
|
||||
}
|
||||
}
|
||||
}
|
||||
spacing: Style.current.halfPadding
|
||||
|
||||
Input {
|
||||
id: inputPerGasTipLimit
|
||||
label: qsTr("Per-gas tip limit")
|
||||
inputLabel.color: Style.current.secondaryText
|
||||
anchors.top: parent.top
|
||||
anchors.right: inputGasPrice.left
|
||||
anchors.rightMargin: Style.current.padding
|
||||
visible: root.suggestedFees.eip1559Enabled
|
||||
width: 125
|
||||
customHeight: 56
|
||||
text: formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
|
||||
placeholderText: "20"
|
||||
onTextChanged: {
|
||||
if (root.validate()) {
|
||||
root.updateGasEthValue()
|
||||
root.checkLimits()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
color: Style.current.secondaryText
|
||||
text: qsTr("Gwei")
|
||||
visible: root.suggestedFees.eip1559Enabled
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 42
|
||||
anchors.right: inputPerGasTipLimit.right
|
||||
anchors.rightMargin: Style.current.padding
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
||||
Input {
|
||||
id: inputGasPrice
|
||||
textField.objectName: "gasPriceSelectorInput"
|
||||
label: qsTr("Per-gas overall limit")
|
||||
inputLabel.color: Style.current.secondaryText
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
width: 125
|
||||
customHeight: 56
|
||||
placeholderText: "20"
|
||||
onTextChanged: {
|
||||
if (root.validate()) {
|
||||
root.updateGasEthValue()
|
||||
root.checkLimits()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
color: Style.current.secondaryText
|
||||
text: qsTr("Gwei")
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 42
|
||||
anchors.right: inputGasPrice.right
|
||||
anchors.rightMargin: Style.current.padding
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: errorsText
|
||||
text: ""
|
||||
width: parent.width - Style.current.padding
|
||||
visible: text != ""
|
||||
height: visible ? undefined : 0
|
||||
anchors.top: inputGasLimit.bottom
|
||||
anchors.topMargin: Style.current.smallPadding + 5
|
||||
font.pixelSize: 13
|
||||
textFormat: Text.RichText
|
||||
color: Style.current.secondaryText
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: maxPriorityFeeText
|
||||
anchors.left: parent.left
|
||||
visible: root.suggestedFees.eip1559Enabled
|
||||
text: {
|
||||
let v = selectedGasEthValue > 0.00009 ? selectedGasEthValue :
|
||||
(selectedGasEthValue < 0.000001 ? "0.000000..." : selectedGasEthValue.toFixed(6))
|
||||
return qsTr("Maximum priority fee: %1 ETH").arg(v)
|
||||
}
|
||||
anchors.top: errorsText.bottom
|
||||
anchors.topMargin: Style.current.smallPadding + 5
|
||||
font.pixelSize: 13
|
||||
color: Style.current.textColor
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: maxPriorityFeeFiatText
|
||||
text: root.maxFiatFees
|
||||
visible: root.suggestedFees.eip1559Enabled
|
||||
anchors.verticalCenter: maxPriorityFeeText.verticalCenter
|
||||
anchors.left: maxPriorityFeeText.right
|
||||
anchors.leftMargin: 6
|
||||
color: Style.current.secondaryText
|
||||
anchors.topMargin: 19
|
||||
font.pixelSize: 13
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: maxPriorityFeeDetailsText
|
||||
text: qsTr("Maximum overall price for the transaction. If the block base fee exceeds this, it will be included in a following block with a lower base fee.")
|
||||
visible: root.suggestedFees.eip1559Enabled
|
||||
StatusSwitchTabBar {
|
||||
id: tabBar
|
||||
width: parent.width
|
||||
anchors.top: maxPriorityFeeText.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
font.pixelSize: 13
|
||||
color: Style.current.secondaryText
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: root.advancedOrCustomMode
|
||||
StatusSwitchTabButton {
|
||||
text: qsTr("Slow")
|
||||
}
|
||||
StatusSwitchTabButton {
|
||||
text: qsTr("Optimal")
|
||||
}
|
||||
StatusSwitchTabButton {
|
||||
text: qsTr("Fast")
|
||||
}
|
||||
|
||||
currentIndex: GasSelector.Priority.OPTIMAL
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
root.selectedPriority = currentIndex
|
||||
if(gasPrioRepeater.count === 3) {
|
||||
root.selectedGasFiatValue = gasPrioRepeater.itemAt(currentIndex).totalGasFiatValue
|
||||
root.selectedGasEthValue = gasPrioRepeater.itemAt(currentIndex).totalGasEthValue
|
||||
root.selectedTimeEstimate = gasPrioRepeater.itemAt(currentIndex).timeText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normal transaction
|
||||
Repeater {
|
||||
model: root.bestRoutes
|
||||
StatusListItem {
|
||||
id: listItem
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
width: parent.width
|
||||
asset.name: index == 0 ? "tiny/gas" : ""
|
||||
title: qsTr("%1 transaction fee").arg(modelData.fromNetwork.chainName)
|
||||
subTitle: "%1 eth".arg(LocaleUtils.numberToLocaleString(parseFloat(totalGasAmount)))
|
||||
property string totalGasAmount : {
|
||||
let maxFees = (tabBar.currentIndex === GasSelector.Priority.SLOW) ? modelData.gasFees.maxFeePerGasL :
|
||||
(tabBar.currentIndex === GasSelector.Priority.OPTIMAL) ?
|
||||
modelData.gasFees.maxFeePerGasM : modelData.gasFees.maxFeePerGasH
|
||||
let gasPrice = modelData.gasFees.eip1559Enabled ? maxFees : modelData.gasFees.gasPrice
|
||||
return root.getGasEthValue(gasPrice , modelData.gasAmount)
|
||||
}
|
||||
statusListItemSubTitle.width: listItem.width/2 - Style.current.smallPadding
|
||||
statusListItemSubTitle.elide: Text.ElideMiddle
|
||||
statusListItemSubTitle.wrapMode: Text.NoWrap
|
||||
components: [
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: "%1%2".arg(currentCurrencySymbol).arg(LocaleUtils.numberToLocaleString(parseFloat(root.getFiatValue(totalGasAmount, "ETH", root.currentCurrency))))
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
width: listItem.width/2 - Style.current.padding
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Bridge
|
||||
Repeater {
|
||||
model: root.bestRoutes
|
||||
StatusListItem {
|
||||
id: listItem2
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
width: parent.width
|
||||
asset.name: index == 0 ? "tiny/bridge" : ""
|
||||
title: qsTr("%1 -> %2 bridge").arg(modelData.fromNetwork.chainName).arg(modelData.toNetwork.chainName)
|
||||
subTitle: "%1 %2".arg(LocaleUtils.numberToLocaleString(modelData.tokenFees)).arg(root.selectedTokenSymbol)
|
||||
visible: modelData.bridgeName !== "Simple"
|
||||
statusListItemSubTitle.width: 100//parent.width - Style.current.smallPadding
|
||||
statusListItemSubTitle.elide: Text.ElideMiddle
|
||||
components: [
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: "%1%2".arg(currentCurrencySymbol).arg(LocaleUtils.numberToLocaleString(parseFloat(root.getFiatValue(modelData.tokenFees, root.selectedTokenSymbol, root.currentCurrency))))
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
width: listItem2.width/2 - Style.current.padding
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,62 +4,41 @@ import QtQuick.Layouts 1.13
|
|||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import utils 1.0
|
||||
import "../status"
|
||||
import "../"
|
||||
|
||||
import "../panels"
|
||||
|
||||
// TODO: use StatusQ components here
|
||||
Column {
|
||||
id: root
|
||||
|
||||
visible: !isValid
|
||||
visible: !isValid || isLoading
|
||||
spacing: 5
|
||||
|
||||
property alias errorMessage: txtValidationError.text
|
||||
property var selectedAccount
|
||||
property double selectedAmount
|
||||
property var selectedAsset
|
||||
property double selectedGasEthValue
|
||||
property var selectedNetwork
|
||||
property bool isValid: false
|
||||
property bool isValid: true
|
||||
property bool isLoading: false
|
||||
|
||||
onSelectedAccountChanged: validate()
|
||||
onSelectedAmountChanged: validate()
|
||||
onSelectedAssetChanged: validate()
|
||||
onSelectedGasEthValueChanged: validate()
|
||||
onSelectedNetworkChanged: validate()
|
||||
|
||||
function validate() {
|
||||
let isValid = false
|
||||
if (!(selectedAccount && selectedAccount.assets && selectedAsset && selectedGasEthValue > 0)) {
|
||||
return root.isValid
|
||||
}
|
||||
let gasTotal = selectedGasEthValue
|
||||
if (selectedAsset && selectedAsset.symbol && selectedAsset.symbol.toUpperCase() === "ETH") {
|
||||
gasTotal += selectedAmount
|
||||
}
|
||||
const chainId = selectedNetwork && selectedNetwork.chainId
|
||||
|
||||
const currAcctGasAsset = Utils.findAssetByChainAndSymbol(chainId, selectedAccount.assets, "ETH")
|
||||
if (currAcctGasAsset && currAcctGasAsset.totalBalance > gasTotal) {
|
||||
isValid = true
|
||||
}
|
||||
root.isValid = isValid
|
||||
return isValid
|
||||
}
|
||||
StatusIcon {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 20
|
||||
width: 20
|
||||
icon: "cancel"
|
||||
color: Theme.palette.dangerColor1
|
||||
visible: !isValid && !isLoading
|
||||
}
|
||||
StatusLoadingIndicator {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 24
|
||||
height: 24
|
||||
color: Theme.palette.baseColor1
|
||||
visible: isLoading && isValid
|
||||
}
|
||||
StyledText {
|
||||
id: txtValidationError
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Not enough ETH for gas")
|
||||
text: isLoading? qsTr("Calculating fees"): qsTr("Balance exceeded")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 13
|
||||
|
|
|
@ -11,27 +11,10 @@ import utils 1.0
|
|||
StatusRadioButton {
|
||||
id: gasRectangle
|
||||
|
||||
property string primaryText: qsTr("Low")
|
||||
property string gasLimit
|
||||
property string defaultCurrency: "USD"
|
||||
property double price: 1
|
||||
property var getGasEthValue: function () {}
|
||||
property var getFiatValue: function () {}
|
||||
|
||||
function formatDec(num, dec){
|
||||
return Math.round((num + Number.EPSILON) * Math.pow(10, dec)) / Math.pow(10, dec)
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property double fiatValue: getFiatValue(ethValue, "ETH", defaultCurrency)
|
||||
property double ethValue: {
|
||||
if (!gasLimit) {
|
||||
return 0
|
||||
}
|
||||
return formatDec(parseFloat(getGasEthValue(gasRectangle.price, gasLimit)), 6)
|
||||
}
|
||||
}
|
||||
property string primaryText
|
||||
property string timeText
|
||||
property string totalGasFiatValue
|
||||
property double totalGasEthValue
|
||||
|
||||
width: contentItem.implicitWidth
|
||||
|
||||
|
@ -64,15 +47,17 @@ StatusRadioButton {
|
|||
}
|
||||
StatusBaseText {
|
||||
id: secondaryLabel
|
||||
Layout.maximumWidth: card.width - Style.current.smallPadding
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
text: d.ethValue + " ETH"
|
||||
text: gasRectangle.totalGasFiatValue
|
||||
color: Theme.palette.primaryColor1
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
StatusBaseText {
|
||||
id: tertiaryText
|
||||
font.pixelSize: 10
|
||||
text: d.fiatValue + " " + gasRectangle.defaultCurrency.toUpperCase()
|
||||
text: gasRectangle.timeText
|
||||
color: Theme.palette.directColor5
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,14 +125,14 @@ Item {
|
|||
// TODO: move this out of StatusQ, this involves dependency on BE code
|
||||
// WARNING: Wrong ComboBox value processing. Check `StatusAccountSelector` for more info.
|
||||
root.userSelectedToken = symbol
|
||||
root.selectedAsset = {name: name, symbol: symbol, totalBalance: totalBalance, totalCurrencyBalance: totalCurrencyBalance, balances: balances}
|
||||
root.selectedAsset = {name: name, symbol: symbol, totalBalance: totalBalance, totalCurrencyBalance: totalCurrencyBalance, balances: balances, decimals: decimals}
|
||||
}
|
||||
|
||||
// TODO: move this out of StatusQ, this involves dependency on BE code
|
||||
// WARNING: Wrong ComboBox value processing. Check `StatusAccountSelector` for more info.
|
||||
Component.onCompleted: {
|
||||
if ((userSelectedToken === "" && index === 0) || symbol === userSelectedToken)
|
||||
root.selectedAsset = { name: name, symbol: symbol, totalBalance: totalBalance, totalCurrencyBalance: totalCurrencyBalance, balances: balances}
|
||||
root.selectedAsset = { name: name, symbol: symbol, totalBalance: totalBalance, totalCurrencyBalance: totalCurrencyBalance, balances: balances, decimals: decimals}
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
|
|
|
@ -47,7 +47,8 @@ Popup {
|
|||
text: qsTr("Send transaction")
|
||||
icon.color: Style.current.purple
|
||||
icon.name: "send"
|
||||
onClicked: root.sendTransactionCommandButtonClicked()
|
||||
// this flow doesnt work, commenting it out till it is worked on
|
||||
// onClicked: root.sendTransactionCommandButtonClicked()
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,7 +57,8 @@ Popup {
|
|||
icon.color: Style.current.orange
|
||||
icon.name: "send"
|
||||
icon.rotation: 180
|
||||
onClicked: root.receiveTransactionCommandButtonClicked()
|
||||
// this flow doesnt work, commenting it out till it is worked on
|
||||
// onClicked: root.receiveTransactionCommandButtonClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,13 +22,21 @@ import "../views"
|
|||
StatusDialog {
|
||||
id: popup
|
||||
|
||||
property alias addressText: recipientSelector.input.text
|
||||
property string preSelectedRecipient
|
||||
property string preDefinedAmountToSend
|
||||
property var preSelectedAsset
|
||||
property bool interactive: true
|
||||
|
||||
property var store
|
||||
property var contactsStore
|
||||
property alias modalHeader: modalHeader.text
|
||||
|
||||
property alias selectedPriority: gasSelector.selectedPriority
|
||||
property var store: TransactionStore{}
|
||||
property var contactsStore: store.contactStore
|
||||
property var selectedAccount: store.currentAccount
|
||||
property var preSelectedRecipient
|
||||
property bool launchedFromChat: false
|
||||
property var bestRoutes
|
||||
property string addressText
|
||||
property bool isLoading: false
|
||||
property int sendType: Constants.SendType.Transfer
|
||||
property MessageDialog sendingError: MessageDialog {
|
||||
id: sendingError
|
||||
title: qsTr("Error sending the transaction")
|
||||
|
@ -36,63 +44,91 @@ StatusDialog {
|
|||
standardButtons: StandardButton.Ok
|
||||
}
|
||||
|
||||
function sendTransaction() {
|
||||
property var sendTransaction: function() {
|
||||
let recipientAddress = Utils.isValidAddress(popup.addressText) ? popup.addressText : d.resolvedENSAddress
|
||||
d.isPending = true
|
||||
d.isPendingTx = true
|
||||
popup.store.authenticateAndTransfer(
|
||||
popup.selectedAccount.address,
|
||||
recipientAddress,
|
||||
assetSelector.selectedAsset.symbol,
|
||||
amountToSendInput.text,
|
||||
gasSelector.selectedGasLimit,
|
||||
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
gasSelector.selectedTipLimit,
|
||||
gasSelector.selectedOverallLimit,
|
||||
networkSelector.selectedNetwork.chainId,
|
||||
d.uuid,
|
||||
gasSelector.suggestedFees.eip1559Enabled,
|
||||
gasSelector.selectedPriority,
|
||||
JSON.stringify(popup.bestRoutes)
|
||||
)
|
||||
}
|
||||
|
||||
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function(disabledChainIds) {
|
||||
if (disabledChainIds === undefined) disabledChainIds = []
|
||||
networkSelector.suggestedRoutes = popup.store.suggestedRoutes(
|
||||
popup.selectedAccount.address, amountToSendInput.text, assetSelector.selectedAsset.symbol, disabledChainIds
|
||||
)
|
||||
if (networkSelector.suggestedRoutes.length) {
|
||||
networkSelector.selectedNetwork = networkSelector.suggestedRoutes[0]
|
||||
gasSelector.suggestedFees = popup.store.suggestedFees(networkSelector.suggestedRoutes[0].chainId)
|
||||
gasSelector.checkOptimal()
|
||||
gasSelector.visible = true
|
||||
} else {
|
||||
networkSelector.selectedNetwork = ""
|
||||
gasSelector.visible = false
|
||||
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
|
||||
d.sendTxError = false
|
||||
if(popup.selectedAccount && assetSelector.selectedAsset) {
|
||||
popup.isLoading = true
|
||||
let amount = parseFloat(amountToSendInput.text) * Math.pow(10, assetSelector.selectedAsset.decimals)
|
||||
popup.store.suggestedRoutes(popup.selectedAccount.address, amount.toString(16), assetSelector.selectedAsset.symbol,
|
||||
store.disabledChainIdsFromList, store.disabledChainIdsToList,
|
||||
d.preferredChainIds, gasSelector.selectedPriority, popup.sendType)
|
||||
}
|
||||
})
|
||||
|
||||
enum StackGroup {
|
||||
SendDetailsGroup = 0
|
||||
function setSendTxError() {
|
||||
d.sendTxError = true
|
||||
d.sendTxErrorString = qsTr("Wrong password")
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property string maxFiatBalance: Utils.stripTrailingZeros(parseFloat(assetSelector.selectedAsset.totalBalance).toFixed(4))
|
||||
readonly property double maxFiatBalance: {
|
||||
console.error(assetSelector.selectedAsset.name," >>> recalaculayte maxFiatBalance = ", assetSelector.selectedAsset.totalBalance)
|
||||
return assetSelector.selectedAsset ? assetSelector.selectedAsset.totalBalance: 0
|
||||
}
|
||||
readonly property bool isReady: amountToSendInput.valid && !amountToSendInput.pending && recipientReady
|
||||
readonly property bool errorMode: networkSelector.suggestedRoutes && networkSelector.suggestedRoutes.length <= 0 || networkSelector.errorMode
|
||||
readonly property bool errorMode: (networkSelector.bestRoutes && networkSelector.bestRoutes.length <= 0) || networkSelector.errorMode || isNaN(amountToSendInput.text)
|
||||
readonly property bool recipientReady: (isAddressValid || isENSValid) && !recipientSelector.isPending
|
||||
readonly property bool isAddressValid: Utils.isValidAddress(recipientSelector.input.text)
|
||||
property bool isAddressValid: false
|
||||
property bool isENSValid: false
|
||||
readonly property var resolveENS: Backpressure.debounce(popup, 500, function (ensName) {
|
||||
store.resolveENS(ensName)
|
||||
})
|
||||
property string resolvedENSAddress
|
||||
onIsReadyChanged: {
|
||||
if(!isReady && isLastGroup)
|
||||
stack.currentIndex = SendModal.StackGroup.SendDetailsGroup
|
||||
}
|
||||
readonly property string uuid: Utils.uuid()
|
||||
readonly property bool isLastGroup: stack.currentIndex === (stack.count - 1)
|
||||
property bool isPending: false
|
||||
property bool isPendingTx: false
|
||||
property var preferredChainIds: []
|
||||
property bool sendTxError: false
|
||||
property string sendTxErrorString
|
||||
|
||||
property Timer waitTimer: Timer {
|
||||
interval: 1000
|
||||
onTriggered: {
|
||||
d.isAddressValid = false
|
||||
let splitWords = popup.store.plainText(recipientSelector.input.text).split(':')
|
||||
let editedText = ""
|
||||
for(var i=0; i<splitWords.length; i++) {
|
||||
if(splitWords[i].startsWith("0x")) {
|
||||
d.isAddressValid = Utils.isValidAddress(splitWords[i])
|
||||
popup.addressText = splitWords[i]
|
||||
editedText += splitWords[i]
|
||||
} else {
|
||||
let chainColor = popup.store.allNetworks.getNetworkColor(splitWords[i])
|
||||
if(!!chainColor) {
|
||||
d.addPreferredChain(popup.store.allNetworks.getNetworkChainId(splitWords[i]))
|
||||
editedText += `<span style='color: %1'>%2</span>`.arg(chainColor).arg(splitWords[i])+':'
|
||||
}
|
||||
}
|
||||
}
|
||||
editedText +="</a></p>"
|
||||
recipientSelector.input.text = editedText
|
||||
popup.recalculateRoutesAndFees()
|
||||
}
|
||||
}
|
||||
|
||||
function addPreferredChain(chainID) {
|
||||
if(!chainID)
|
||||
return
|
||||
|
||||
if(preferredChainIds.includes(chainID))
|
||||
return
|
||||
|
||||
preferredChainIds.push(chainID)
|
||||
}
|
||||
}
|
||||
|
||||
width: 556
|
||||
|
@ -106,14 +142,22 @@ StatusDialog {
|
|||
onSelectedAccountChanged: popup.recalculateRoutesAndFees()
|
||||
|
||||
onOpened: {
|
||||
popup.store.disabledChainIdsFromList = []
|
||||
popup.store.disabledChainIdsToList = []
|
||||
amountToSendInput.input.edit.forceActiveFocus()
|
||||
|
||||
if(popup.launchedFromChat) {
|
||||
recipientSelector.input.edit.readOnly = true
|
||||
recipientSelector.input.text = popup.preSelectedRecipient.name
|
||||
if(!!popup.preSelectedAsset) {
|
||||
assetSelector.selectedAsset = popup.preSelectedAsset
|
||||
}
|
||||
|
||||
popup.recalculateRoutesAndFees()
|
||||
if(!!popup.preDefinedAmountToSend) {
|
||||
amountToSendInput.text = popup.preDefinedAmountToSend
|
||||
}
|
||||
|
||||
if(!!popup.preSelectedRecipient) {
|
||||
recipientSelector.input.text = popup.preSelectedRecipient
|
||||
d.waitTimer.restart()
|
||||
}
|
||||
}
|
||||
|
||||
header: SendModalHeader {
|
||||
|
@ -152,7 +196,6 @@ StatusDialog {
|
|||
color: Theme.palette.dropShadow
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
id: assetAndAmmountSelector
|
||||
anchors.left: parent.left
|
||||
|
@ -164,6 +207,7 @@ StatusDialog {
|
|||
Row {
|
||||
spacing: 16
|
||||
StatusBaseText {
|
||||
id: modalHeader
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: qsTr("Send")
|
||||
font.pixelSize: 15
|
||||
|
@ -172,11 +216,11 @@ StatusDialog {
|
|||
StatusListItemTag {
|
||||
height: 22
|
||||
width: childrenRect.width
|
||||
title: assetSelector.selectedAsset.totalBalance > 0 ? qsTr("Max: %1").arg(assetSelector.selectedAsset ? d.maxFiatBalance : "0.00") : qsTr("No balances active")
|
||||
title: d.sendTxError ? d.sendTxErrorString : d.maxFiatBalance > 0 ? qsTr("Max: %1").arg(LocaleUtils.numberToLocaleString(d.maxFiatBalance)) : qsTr("No balances active")
|
||||
closeButtonVisible: false
|
||||
titleText.font.pixelSize: 12
|
||||
color: d.errorMode ? Theme.palette.dangerColor2 : Theme.palette.primaryColor3
|
||||
titleText.color: d.errorMode ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
|
||||
color: d.errorMode || d.sendTxError ? Theme.palette.dangerColor2 : Theme.palette.primaryColor3
|
||||
titleText.color: d.errorMode || d.sendTxError ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
Item {
|
||||
|
@ -188,13 +232,14 @@ StatusDialog {
|
|||
anchors.left: parent.left
|
||||
anchors.leftMargin: -Style.current.padding
|
||||
width: parent.width - assetSelector.width
|
||||
placeholderText: "0.00 %1".arg(assetSelector.selectedAsset.symbol)
|
||||
placeholderText: assetSelector.selectedAsset ? "%1 %2".arg(LocaleUtils.numberToLocaleString(0, 2)).arg(assetSelector.selectedAsset.symbol) : ""
|
||||
input.edit.color: d.errorMode ? Theme.palette.dangerColor1 : Theme.palette.directColor1
|
||||
input.edit.readOnly: !popup.interactive
|
||||
validators: [
|
||||
StatusFloatValidator{
|
||||
id: floatValidator
|
||||
bottom: 0
|
||||
top: d.maxFiatBalance
|
||||
top: assetSelector.selectedAsset ? assetSelector.selectedAsset.totalBalance: 0
|
||||
errorMessage: ""
|
||||
}
|
||||
]
|
||||
|
@ -204,12 +249,6 @@ StatusDialog {
|
|||
if (!Utils.containsOnlyDigits(amount) || isNaN(amount)) {
|
||||
return
|
||||
}
|
||||
if (amount === "") {
|
||||
txtFiatBalance.text = "0.00"
|
||||
} else {
|
||||
txtFiatBalance.text = popup.store.getFiatValue(amount, assetSelector.selectedAsset.symbol, popup.store.currentCurrency)
|
||||
}
|
||||
gasSelector.estimateGas()
|
||||
popup.recalculateRoutesAndFees()
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +256,8 @@ StatusDialog {
|
|||
id: assetSelector
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
assets: popup.selectedAccount.assets
|
||||
enabled: popup.interactive
|
||||
assets: popup.selectedAccount && popup.selectedAccount.assets ? popup.selectedAccount.assets : []
|
||||
defaultToken: Style.png("tokens/DEFAULT-TOKEN@3x")
|
||||
getCurrencyBalanceString: function (currencyBalance) {
|
||||
return "%1 %2".arg(Utils.toLocaleString(currencyBalance.toFixed(2), popup.store.locale, {"currency": true})).arg(popup.store.currentCurrency.toUpperCase())
|
||||
|
@ -238,8 +278,6 @@ StatusDialog {
|
|||
if (amountToSendInput.text === "" || isNaN(amountToSendInput.text)) {
|
||||
return
|
||||
}
|
||||
txtFiatBalance.text = popup.store.getFiatValue(amountToSendInput.text, assetSelector.selectedAsset.symbol, popup.store.currentCurrency)
|
||||
gasSelector.estimateGas()
|
||||
popup.recalculateRoutesAndFees()
|
||||
}
|
||||
}
|
||||
|
@ -261,8 +299,11 @@ StatusDialog {
|
|||
input.background.color: "transparent"
|
||||
input.background.border.width: 0
|
||||
input.edit.color: txtFiatBalance.input.edit.activeFocus ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
text: "0.00"
|
||||
placeholderText: "0.00"
|
||||
input.edit.readOnly: true
|
||||
text: {
|
||||
let fiatValue = popup.store.getFiatValue(amountToSendInput.text, assetSelector.selectedAsset.symbol, popup.store.currentCurrency)
|
||||
return parseFloat(fiatValue) === 0 ? LocaleUtils.numberToLocaleString(parseFloat(fiatValue), 2) : LocaleUtils.numberToLocaleString(parseFloat(fiatValue))
|
||||
}
|
||||
input.implicitHeight: 15
|
||||
implicitWidth: txtFiatBalance.input.edit.contentWidth + 50
|
||||
input.rightComponent: StatusBaseText {
|
||||
|
@ -313,8 +354,10 @@ StatusDialog {
|
|||
input.background.color: Theme.palette.indirectColor1
|
||||
input.background.border.width: 0
|
||||
input.implicitHeight: 56
|
||||
input.clearable: true
|
||||
input.clearable: popup.interactive
|
||||
input.edit.readOnly: !popup.interactive
|
||||
multiline: false
|
||||
input.edit.textFormat: TextEdit.RichText
|
||||
input.rightComponent: RowLayout {
|
||||
StatusButton {
|
||||
visible: recipientSelector.text === ""
|
||||
|
@ -333,10 +376,14 @@ StatusDialog {
|
|||
icon.height: 16
|
||||
icon.color: Theme.palette.baseColor1
|
||||
backgroundHoverColor: "transparent"
|
||||
onClicked: recipientSelector.input.edit.clear()
|
||||
onClicked: {
|
||||
recipientSelector.input.edit.clear()
|
||||
d.waitTimer.restart()
|
||||
}
|
||||
}
|
||||
}
|
||||
Keys.onReleased: {
|
||||
d.waitTimer.restart()
|
||||
if(!d.isAddressValid) {
|
||||
isPending = true
|
||||
Qt.callLater(d.resolveENS, input.edit.text)
|
||||
|
@ -365,6 +412,7 @@ StatusDialog {
|
|||
store: popup.store
|
||||
onContactSelected: {
|
||||
recipientSelector.input.text = address
|
||||
d.waitTimer.restart()
|
||||
}
|
||||
visible: !d.recipientReady
|
||||
}
|
||||
|
@ -377,17 +425,16 @@ StatusDialog {
|
|||
anchors.leftMargin: Style.current.bigPadding
|
||||
anchors.rightMargin: Style.current.bigPadding
|
||||
store: popup.store
|
||||
interactive: popup.interactive
|
||||
selectedAccount: popup.selectedAccount
|
||||
amountToSend: isNaN(parseFloat(amountToSendInput.text)) ? 0 : parseFloat(amountToSendInput.text)
|
||||
requiredGasInEth: gasSelector.selectedGasEthValue
|
||||
assets: popup.selectedAccount.assets
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
onNetworkChanged: function(chainId) {
|
||||
gasSelector.suggestedFees = popup.store.suggestedFees(chainId)
|
||||
gasSelector.updateGasEthValue()
|
||||
}
|
||||
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees(disabledChainIds)
|
||||
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
|
||||
visible: d.recipientReady
|
||||
|
||||
isLoading: popup.isLoading
|
||||
bestRoutes: popup.bestRoutes
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
@ -418,62 +465,46 @@ StatusDialog {
|
|||
Column {
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
Layout.preferredWidth: fees.width - feesIcon.width - Style.current.xlPadding
|
||||
StatusBaseText {
|
||||
id: text
|
||||
width: 410
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Medium
|
||||
color: Theme.palette.directColor1
|
||||
text: qsTr("Fees")
|
||||
wrapMode: Text.WordWrap
|
||||
Item {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
StatusBaseText {
|
||||
id: text
|
||||
anchors.left: parent.left
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Medium
|
||||
color: Theme.palette.directColor1
|
||||
text: qsTr("Fees")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
StatusBaseText {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.padding
|
||||
id: totalFeesAdvanced
|
||||
text: popup.isLoading ? "..." : gasSelector.selectedGasFiatValue
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
visible: networkSelector.advancedOrCustomMode && popup.bestRoutes.length > 0
|
||||
}
|
||||
}
|
||||
GasSelector {
|
||||
id: gasSelector
|
||||
width: parent.width
|
||||
getGasEthValue: popup.store.getGasEthValue
|
||||
getFiatValue: popup.store.getFiatValue
|
||||
getEstimatedTime: popup.store.getEstimatedTime
|
||||
defaultCurrency: popup.store.currentCurrency
|
||||
chainId: networkSelector.selectedNetwork && networkSelector.selectedNetwork.chainId ? networkSelector.selectedNetwork.chainId : 1
|
||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||
if (!(popup.selectedAccount && popup.selectedAccount.address &&
|
||||
popup.addressText && assetSelector.selectedAsset &&
|
||||
assetSelector.selectedAsset.symbol && amountToSendInput.text)) {
|
||||
selectedGasLimit = 250000
|
||||
defaultGasLimit = selectedGasLimit
|
||||
return
|
||||
}
|
||||
|
||||
var chainID = networkSelector.selectedNetwork ? networkSelector.selectedNetwork.chainId: 1
|
||||
|
||||
var recipientAddress = popup.launchedFromChat ? popup.preSelectedRecipient.address : popup.addressText
|
||||
|
||||
let gasEstimate = JSON.parse(popup.store.estimateGas(
|
||||
popup.selectedAccount.address,
|
||||
recipientAddress,
|
||||
assetSelector.selectedAsset.symbol,
|
||||
amountToSendInput.text,
|
||||
chainID,
|
||||
""))
|
||||
|
||||
if (!gasEstimate.success) {
|
||||
console.warn("error estimating gas: ", gasEstimate.error.message)
|
||||
return
|
||||
}
|
||||
|
||||
selectedGasLimit = gasEstimate.result
|
||||
defaultGasLimit = selectedGasLimit
|
||||
})
|
||||
currentCurrency: popup.store.currencyStore.currentCurrency
|
||||
currentCurrencySymbol: popup.store.currencyStore.currentCurrencySymbol
|
||||
visible: gasValidator.isValid && !popup.isLoading
|
||||
advancedOrCustomMode: networkSelector.advancedOrCustomMode
|
||||
bestRoutes: popup.bestRoutes
|
||||
selectedTokenSymbol: assetSelector.selectedAsset ? assetSelector.selectedAsset.symbol: ""
|
||||
onSelectedPriorityChanged: popup.recalculateRoutesAndFees()
|
||||
}
|
||||
GasValidator {
|
||||
id: gasValidator
|
||||
width: parent.width
|
||||
selectedAccount: popup.selectedAccount
|
||||
selectedAmount: amountToSendInput.text === "" ? 0.0 :
|
||||
parseFloat(amountToSendInput.text)
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
selectedGasEthValue: gasSelector.selectedGasEthValue
|
||||
selectedNetwork: networkSelector.selectedNetwork ? networkSelector.selectedNetwork: null
|
||||
isLoading: popup.isLoading
|
||||
isValid: popup.bestRoutes ? popup.bestRoutes.length > 0 : true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -484,38 +515,11 @@ StatusDialog {
|
|||
}
|
||||
|
||||
footer: SendModalFooter {
|
||||
maxFiatFees: gasSelector.maxFiatFees
|
||||
estimatedTxTimeFlag: gasSelector.estimatedTxTimeFlag
|
||||
pending: d.isPending
|
||||
isLastGroup: d.isLastGroup
|
||||
visible: d.isReady && !isNaN(parseFloat(amountToSendInput.text)) && gasValidator.isValid
|
||||
onNextButtonClicked: {
|
||||
if(gasSelector.suggestedFees.eip1559Enabled && gasSelector.advancedMode){
|
||||
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
|
||||
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
|
||||
currentBaseFee: gasSelector.suggestedFees.baseFee,
|
||||
currentMinimumTip: gasSelector.perGasTipLimitFloor,
|
||||
currentAverageTip: gasSelector.perGasTipLimitAverage,
|
||||
tipLimit: gasSelector.selectedTipLimit,
|
||||
suggestedTipLimit: gasSelector.perGasTipLimitFloor,
|
||||
priceLimit: gasSelector.selectedOverallLimit,
|
||||
suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
|
||||
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
|
||||
showTipLimitWarning: gasSelector.showTipLimitWarning,
|
||||
onConfirm: function(){
|
||||
if (isLastGroup) {
|
||||
return popup.sendTransaction()
|
||||
}
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (isLastGroup) {
|
||||
return popup.sendTransaction()
|
||||
}
|
||||
}
|
||||
maxFiatFees: popup.isLoading ? "..." : gasSelector.selectedGasFiatValue
|
||||
selectedTimeEstimate: popup.isLoading? "..." : gasSelector.selectedTimeEstimate
|
||||
pending: d.isPendingTx
|
||||
visible: d.isReady && !isNaN(amountToSendInput.text) && gasValidator.isValid && !d.errorMode
|
||||
onNextButtonClicked: popup.sendTransaction()
|
||||
}
|
||||
|
||||
Component {
|
||||
|
@ -523,47 +527,53 @@ StatusDialog {
|
|||
TransactionSettingsConfirmationPopup {}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: popup.store.walletSectionTransactionsInst
|
||||
onSuggestedRoutesReady: {
|
||||
let response = JSON.parse(suggestedRoutes)
|
||||
if(!!response.error) {
|
||||
popup.isLoading = false
|
||||
return
|
||||
}
|
||||
popup.bestRoutes = response.suggestedRoutes.best
|
||||
gasSelector.estimatedGasFeesTime = response.suggestedRoutes.gasTimeEstimates
|
||||
popup.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: popup.store.walletSectionTransactionsInst
|
||||
onTransactionSent: {
|
||||
d.isPending = false
|
||||
d.isPendingTx = false
|
||||
try {
|
||||
let response = JSON.parse(txResult)
|
||||
if (response.uuid !== d.uuid) return
|
||||
|
||||
if (!response.success) {
|
||||
sendingError.text = response.result
|
||||
if (Utils.isInvalidPasswordMessage(response.error)) {
|
||||
d.sendTxError = true
|
||||
d.sendTxErrorString = qsTr("Wrong password")
|
||||
return
|
||||
}
|
||||
sendingError.text = response.error
|
||||
return sendingError.open()
|
||||
}
|
||||
for(var i=0; i<popup.bestRoutes.length; i++) {
|
||||
let txHash = response.result[popup.bestRoutes[i].fromNetwork.chainId]
|
||||
let url = `${popup.store.getEtherscanLink()}/${txHash}`
|
||||
Global.displayToastMessage(qsTr("Transaction pending..."),
|
||||
qsTr("View on etherscan"),
|
||||
"",
|
||||
true,
|
||||
Constants.ephemeralNotificationType.normal,
|
||||
url)
|
||||
}
|
||||
|
||||
let url = `${popup.store.getEtherscanLink()}/${response.result}`
|
||||
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)
|
||||
}
|
||||
}
|
||||
// Not Refactored Yet
|
||||
// onTransactionCompleted: {
|
||||
// if (success) {
|
||||
// //% "Transaction completed"
|
||||
// Global.toastMessage.title = qsTr("Wrong password")
|
||||
// Global.toastMessage.source = Style.svg("check-circle")
|
||||
// Global.toastMessage.iconColor = Style.current.success
|
||||
// } else {
|
||||
// //% "Transaction failed"
|
||||
// Global.toastMessage.title = qsTr("Wrong password")
|
||||
// Global.toastMessage.source = Style.svg("block-icon")
|
||||
// Global.toastMessage.iconColor = Style.current.danger
|
||||
// }
|
||||
// Global.toastMessage.link = `${walletModel.utilsView.etherscanLink}/${txHash}`
|
||||
// Global.toastMessage.open()
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,32 +34,32 @@ StatusModal {
|
|||
property string trxData: ""
|
||||
property int chainId
|
||||
|
||||
property alias transactionSigner: transactionSigner
|
||||
// property alias transactionSigner: transactionSigner
|
||||
|
||||
property var sendTransaction: function() {
|
||||
stack.currentGroup.isPending = true
|
||||
let success = false
|
||||
success = root.store.transfer(
|
||||
selectFromAccount.selectedAccount.address,
|
||||
selectRecipient.selectedRecipient.address,
|
||||
root.selectedAsset.symbol,
|
||||
root.selectedAmount,
|
||||
gasSelector.selectedGasLimit,
|
||||
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
gasSelector.selectedTipLimit,
|
||||
gasSelector.selectedOverallLimit,
|
||||
transactionSigner.enteredPassword,
|
||||
root.chainId,
|
||||
stack.uuid,
|
||||
gasSelector.suggestedFees.eip1559Enabled,
|
||||
)
|
||||
// TODO remove this else once the thread and connection are back
|
||||
// if(!success){
|
||||
// //% "Invalid transaction parameters"
|
||||
// sendingError.text = qsTr("Invalid transaction parameters")
|
||||
// sendingError.open()
|
||||
// }
|
||||
}
|
||||
// property var sendTransaction: function() {
|
||||
// stack.currentGroup.isPending = true
|
||||
// let success = false
|
||||
// success = root.store.transfer(
|
||||
// selectFromAccount.selectedAccount.address,
|
||||
// selectRecipient.selectedRecipient.address,
|
||||
// root.selectedAsset.symbol,
|
||||
// root.selectedAmount,
|
||||
// gasSelector.selectedGasLimit,
|
||||
// gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
// gasSelector.selectedTipLimit,
|
||||
// gasSelector.selectedOverallLimit,
|
||||
// transactionSigner.enteredPassword,
|
||||
// root.chainId,
|
||||
// stack.uuid,
|
||||
// gasSelector.suggestedFees.eip1559Enabled,
|
||||
// )
|
||||
// // TODO remove this else once the thread and connection are back
|
||||
//// if(!success){
|
||||
//// //% "Invalid transaction parameters"
|
||||
//// sendingError.text = qsTr("Invalid transaction parameters")
|
||||
//// sendingError.open()
|
||||
//// }
|
||||
// }
|
||||
|
||||
property MessageDialog sendingError: MessageDialog {
|
||||
id: sendingError
|
||||
|
@ -69,296 +69,296 @@ StatusModal {
|
|||
}
|
||||
signal openGasEstimateErrorPopup(string message)
|
||||
|
||||
onClosed: {
|
||||
stack.pop(groupPreview, StackView.Immediate)
|
||||
}
|
||||
// onClosed: {
|
||||
// stack.pop(groupPreview, StackView.Immediate)
|
||||
// }
|
||||
|
||||
onOpened: {
|
||||
gasSelector.suggestedFees = root.store.suggestedFees(root.chainId)
|
||||
gasSelector.checkOptimal()
|
||||
}
|
||||
// onOpened: {
|
||||
// gasSelector.suggestedFees = root.store.suggestedFees(root.chainId)
|
||||
// gasSelector.checkOptimal()
|
||||
// }
|
||||
|
||||
contentItem: Item {
|
||||
width: root.width
|
||||
height: childrenRect.height
|
||||
TransactionStackView {
|
||||
id: stack
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
initialItem: groupPreview
|
||||
isLastGroup: stack.currentGroup === groupSignTx
|
||||
onGroupActivated: {
|
||||
root.header.title = group.headerText
|
||||
btnNext.text = group.footerText
|
||||
}
|
||||
TransactionFormGroup {
|
||||
id: groupSelectAcct
|
||||
headerText: {
|
||||
// Not Refactored Yet
|
||||
// if(trxData.startsWith("0x095ea7b3")){
|
||||
// const approveData = JSON.parse(root.store.walletModelInst.tokensView.decodeTokenApproval(selectedRecipient.address, trxData))
|
||||
// if(approveData.symbol)
|
||||
// //% "Authorize %1 %2"
|
||||
// return qsTr("Error sending the transaction").arg(approveData.amount).arg(approveData.symbol)
|
||||
// contentItem: Item {
|
||||
// width: root.width
|
||||
// height: childrenRect.height
|
||||
// TransactionStackView {
|
||||
// id: stack
|
||||
// anchors.leftMargin: Style.current.padding
|
||||
// anchors.rightMargin: Style.current.padding
|
||||
// initialItem: groupPreview
|
||||
// isLastGroup: stack.currentGroup === groupSignTx
|
||||
// onGroupActivated: {
|
||||
// root.header.title = group.headerText
|
||||
// btnNext.text = group.footerText
|
||||
// }
|
||||
// TransactionFormGroup {
|
||||
// id: groupSelectAcct
|
||||
// headerText: {
|
||||
// // Not Refactored Yet
|
||||
//// if(trxData.startsWith("0x095ea7b3")){
|
||||
//// const approveData = JSON.parse(root.store.walletModelInst.tokensView.decodeTokenApproval(selectedRecipient.address, trxData))
|
||||
//// if(approveData.symbol)
|
||||
//// //% "Authorize %1 %2"
|
||||
//// return qsTr("Error sending the transaction").arg(approveData.amount).arg(approveData.symbol)
|
||||
//// }
|
||||
// return qsTr("Send");
|
||||
// }
|
||||
// footerText: qsTr("Continue")
|
||||
// showNextBtn: false
|
||||
// onBackClicked: function() {
|
||||
// if(validate()) {
|
||||
// stack.pop()
|
||||
// }
|
||||
return qsTr("Send");
|
||||
}
|
||||
footerText: qsTr("Continue")
|
||||
showNextBtn: false
|
||||
onBackClicked: function() {
|
||||
if(validate()) {
|
||||
stack.pop()
|
||||
}
|
||||
}
|
||||
StatusAccountSelector {
|
||||
id: selectFromAccount
|
||||
accounts: root.store.accounts
|
||||
currency: root.store.currentCurrency
|
||||
width: stack.width
|
||||
selectedAccount: root.selectedAccount
|
||||
label: qsTr("Choose account")
|
||||
showBalanceForAssetSymbol: root.selectedAsset.symbol
|
||||
chainId: root.chainId
|
||||
minRequiredAssetBalance: parseFloat(root.selectedAmount)
|
||||
onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
|
||||
}
|
||||
RecipientSelector {
|
||||
id: selectRecipient
|
||||
visible: false
|
||||
accounts: root.store.accounts
|
||||
contactsStore: root.contactsStore
|
||||
selectedRecipient: root.selectedRecipient
|
||||
selectedType: root.selectedType
|
||||
readOnly: true
|
||||
}
|
||||
}
|
||||
TransactionFormGroup {
|
||||
id: groupSelectGas
|
||||
headerText: qsTr("Network fee")
|
||||
footerText: qsTr("Continue")
|
||||
showNextBtn: false
|
||||
onBackClicked: function() {
|
||||
stack.pop()
|
||||
}
|
||||
GasSelector {
|
||||
id: gasSelector
|
||||
anchors.topMargin: Style.current.padding
|
||||
getGasEthValue: root.store.getGasEthValue
|
||||
getFiatValue: root.store.getFiatValue
|
||||
defaultCurrency: root.store.currentCurrency
|
||||
width: stack.width
|
||||
// }
|
||||
// StatusAccountSelector {
|
||||
// id: selectFromAccount
|
||||
// accounts: root.store.accounts
|
||||
// currency: root.store.currentCurrency
|
||||
// width: stack.width
|
||||
// selectedAccount: root.selectedAccount
|
||||
// label: qsTr("Choose account")
|
||||
// showBalanceForAssetSymbol: root.selectedAsset.symbol
|
||||
// chainId: root.chainId
|
||||
// minRequiredAssetBalance: parseFloat(root.selectedAmount)
|
||||
// onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
|
||||
// }
|
||||
// RecipientSelector {
|
||||
// id: selectRecipient
|
||||
// visible: false
|
||||
// accounts: root.store.accounts
|
||||
// contactsStore: root.contactsStore
|
||||
// selectedRecipient: root.selectedRecipient
|
||||
// selectedType: root.selectedType
|
||||
// readOnly: true
|
||||
// }
|
||||
// }
|
||||
// TransactionFormGroup {
|
||||
// id: groupSelectGas
|
||||
// headerText: qsTr("Network fee")
|
||||
// footerText: qsTr("Continue")
|
||||
// showNextBtn: false
|
||||
// onBackClicked: function() {
|
||||
// stack.pop()
|
||||
// }
|
||||
// GasSelector {
|
||||
// id: gasSelector
|
||||
// anchors.topMargin: Style.current.padding
|
||||
// getGasEthValue: root.store.getGasEthValue
|
||||
// getFiatValue: root.store.getFiatValue
|
||||
// currentCurrency: root.store.currentCurrency
|
||||
// width: stack.width
|
||||
|
||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||
if (!(selectFromAccount.selectedAccount && selectFromAccount.selectedAccount.address &&
|
||||
selectRecipient.selectedRecipient && selectRecipient.selectedRecipient.address &&
|
||||
root.selectedAsset && root.selectedAsset.symbol &&
|
||||
root.selectedAmount)) {
|
||||
selectedGasLimit = 250000
|
||||
defaultGasLimit = selectedGasLimit
|
||||
return
|
||||
}
|
||||
// property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||
// if (!(selectFromAccount.selectedAccount && selectFromAccount.selectedAccount.address &&
|
||||
// selectRecipient.selectedRecipient && selectRecipient.selectedRecipient.address &&
|
||||
// root.selectedAsset && root.selectedAsset.symbol &&
|
||||
// root.selectedAmount)) {
|
||||
// selectedGasLimit = 250000
|
||||
// defaultGasLimit = selectedGasLimit
|
||||
// return
|
||||
// }
|
||||
|
||||
let gasEstimate = JSON.parse(root.store.estimateGas(
|
||||
selectFromAccount.selectedAccount.address,
|
||||
selectRecipient.selectedRecipient.address,
|
||||
root.selectedAsset.symbol,
|
||||
root.selectedAmount,
|
||||
root.chainId,
|
||||
trxData
|
||||
))
|
||||
// let gasEstimate = JSON.parse(root.store.estimateGas(
|
||||
// selectFromAccount.selectedAccount.address,
|
||||
// selectRecipient.selectedRecipient.address,
|
||||
// root.selectedAsset.symbol,
|
||||
// root.selectedAmount,
|
||||
// root.chainId,
|
||||
// trxData
|
||||
// ))
|
||||
|
||||
if (!gasEstimate.success) {
|
||||
let message = qsTr("Error estimating gas: %1").arg(gasEstimate.error.message)
|
||||
root.openGasEstimateErrorPopup(message);
|
||||
return
|
||||
}
|
||||
selectedGasLimit = gasEstimate.result
|
||||
defaultGasLimit = selectedGasLimit
|
||||
})
|
||||
}
|
||||
GasValidator {
|
||||
id: gasValidator
|
||||
anchors.top: gasSelector.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
selectedAccount: selectFromAccount.selectedAccount
|
||||
selectedAmount: parseFloat(root.selectedAmount)
|
||||
selectedAsset: root.selectedAsset
|
||||
selectedGasEthValue: gasSelector.selectedGasEthValue
|
||||
}
|
||||
}
|
||||
// if (!gasEstimate.success) {
|
||||
// let message = qsTr("Error estimating gas: %1").arg(gasEstimate.error.message)
|
||||
// root.openGasEstimateErrorPopup(message);
|
||||
// return
|
||||
// }
|
||||
// selectedGasLimit = gasEstimate.result
|
||||
// defaultGasLimit = selectedGasLimit
|
||||
// })
|
||||
// }
|
||||
// GasValidator {
|
||||
// id: gasValidator
|
||||
// anchors.top: gasSelector.bottom
|
||||
// anchors.horizontalCenter: parent.horizontalCenter
|
||||
//// selectedAccount: selectFromAccount.selectedAccount
|
||||
//// selectedAmount: parseFloat(root.selectedAmount)
|
||||
//// selectedAsset: root.selectedAsset
|
||||
//// selectedGasEthValue: gasSelector.selectedGasEthValue
|
||||
// }
|
||||
// }
|
||||
|
||||
TransactionFormGroup {
|
||||
id: groupPreview
|
||||
headerText: qsTr("Transaction preview")
|
||||
footerText: qsTr("Sign with password")
|
||||
showBackBtn: false
|
||||
onNextClicked: function() {
|
||||
stack.push(groupSignTx, StackView.Immediate)
|
||||
}
|
||||
isValid: groupSelectAcct.isValid && groupSelectGas.isValid && pvwTransaction.isValid
|
||||
// TransactionFormGroup {
|
||||
// id: groupPreview
|
||||
// headerText: qsTr("Transaction preview")
|
||||
// footerText: qsTr("Sign with password")
|
||||
// showBackBtn: false
|
||||
// onNextClicked: function() {
|
||||
// stack.push(groupSignTx, StackView.Immediate)
|
||||
// }
|
||||
// isValid: groupSelectAcct.isValid && groupSelectGas.isValid && pvwTransaction.isValid
|
||||
|
||||
TransactionPreview {
|
||||
id: pvwTransaction
|
||||
width: stack.width
|
||||
fromAccount: selectFromAccount.selectedAccount
|
||||
gas: {
|
||||
"value": gasSelector.selectedGasEthValue,
|
||||
"symbol": "ETH",
|
||||
"fiatValue": gasSelector.selectedGasFiatValue
|
||||
}
|
||||
toAccount: selectRecipient.selectedRecipient
|
||||
asset: root.selectedAsset
|
||||
amount: { "value": root.selectedAmount, "fiatValue": root.selectedFiatAmount }
|
||||
currency: root.store.currentCurrency
|
||||
isFromEditable: false
|
||||
trxData: root.trxData
|
||||
isGasEditable: true
|
||||
fromValid: balanceValidator.isValid
|
||||
gasValid: gasValidator.isValid
|
||||
onFromClicked: { stack.push(groupSelectAcct, StackView.Immediate) }
|
||||
onGasClicked: { stack.push(groupSelectGas, StackView.Immediate) }
|
||||
}
|
||||
BalanceValidator {
|
||||
id: balanceValidator
|
||||
anchors.top: pvwTransaction.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
account: selectFromAccount.selectedAccount
|
||||
amount: !!root.selectedAmount ? parseFloat(root.selectedAmount) : 0.0
|
||||
chainId: root.chainId
|
||||
asset: root.selectedAsset
|
||||
}
|
||||
GasValidator {
|
||||
id: gasValidator2
|
||||
anchors.top: balanceValidator.visible ? balanceValidator.bottom : pvwTransaction.bottom
|
||||
anchors.topMargin: balanceValidator.visible ? 5 : 0
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
selectedAccount: selectFromAccount.selectedAccount
|
||||
selectedAmount: parseFloat(root.selectedAmount)
|
||||
selectedAsset: root.selectedAsset
|
||||
selectedGasEthValue: gasSelector.selectedGasEthValue
|
||||
}
|
||||
}
|
||||
TransactionFormGroup {
|
||||
id: groupSignTx
|
||||
headerText: qsTr("Sign with password")
|
||||
footerText: qsTr("Send %1 %2").arg(root.selectedAmount).arg(!!root.selectedAsset ? root.selectedAsset.symbol : "")
|
||||
onBackClicked: function() {
|
||||
stack.pop()
|
||||
}
|
||||
// TransactionPreview {
|
||||
// id: pvwTransaction
|
||||
// width: stack.width
|
||||
// fromAccount: selectFromAccount.selectedAccount
|
||||
// gas: {
|
||||
// "value": gasSelector.selectedGasEthValue,
|
||||
// "symbol": "ETH",
|
||||
// "fiatValue": gasSelector.selectedGasFiatValue
|
||||
// }
|
||||
// toAccount: selectRecipient.selectedRecipient
|
||||
// asset: root.selectedAsset
|
||||
// amount: { "value": root.selectedAmount, "fiatValue": root.selectedFiatAmount }
|
||||
// currency: root.store.currentCurrency
|
||||
// isFromEditable: false
|
||||
// trxData: root.trxData
|
||||
// isGasEditable: true
|
||||
// fromValid: balanceValidator.isValid
|
||||
// gasValid: gasValidator.isValid
|
||||
// onFromClicked: { stack.push(groupSelectAcct, StackView.Immediate) }
|
||||
// onGasClicked: { stack.push(groupSelectGas, StackView.Immediate) }
|
||||
// }
|
||||
// BalanceValidator {
|
||||
// id: balanceValidator
|
||||
// anchors.top: pvwTransaction.bottom
|
||||
// anchors.horizontalCenter: parent.horizontalCenter
|
||||
// account: selectFromAccount.selectedAccount
|
||||
// amount: !!root.selectedAmount ? parseFloat(root.selectedAmount) : 0.0
|
||||
// chainId: root.chainId
|
||||
// asset: root.selectedAsset
|
||||
// }
|
||||
// GasValidator {
|
||||
// id: gasValidator2
|
||||
// anchors.top: balanceValidator.visible ? balanceValidator.bottom : pvwTransaction.bottom
|
||||
// anchors.topMargin: balanceValidator.visible ? 5 : 0
|
||||
// anchors.horizontalCenter: parent.horizontalCenter
|
||||
//// selectedAccount: selectFromAccount.selectedAccount
|
||||
//// selectedAmount: parseFloat(root.selectedAmount)
|
||||
//// selectedAsset: root.selectedAsset
|
||||
//// selectedGasEthValue: gasSelector.selectedGasEthValue
|
||||
// }
|
||||
// }
|
||||
// TransactionFormGroup {
|
||||
// id: groupSignTx
|
||||
// headerText: qsTr("Sign with password")
|
||||
// footerText: qsTr("Send %1 %2").arg(root.selectedAmount).arg(!!root.selectedAsset ? root.selectedAsset.symbol : "")
|
||||
// onBackClicked: function() {
|
||||
// stack.pop()
|
||||
// }
|
||||
|
||||
TransactionSigner {
|
||||
id: transactionSigner
|
||||
width: stack.width
|
||||
signingPhrase: root.store.signingPhrase
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TransactionSigner {
|
||||
// id: transactionSigner
|
||||
// width: stack.width
|
||||
// signingPhrase: root.store.signingPhrase
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
leftButtons: [
|
||||
StatusBackButton {
|
||||
id: btnBack
|
||||
visible: stack.currentGroup.showBackBtn
|
||||
enabled: stack.currentGroup.isValid || stack.isLastGroup
|
||||
onClicked: {
|
||||
if (typeof stack.currentGroup.onBackClicked === "function") {
|
||||
return stack.currentGroup.onBackClicked()
|
||||
}
|
||||
stack.back()
|
||||
}
|
||||
}
|
||||
]
|
||||
// leftButtons: [
|
||||
// StatusBackButton {
|
||||
// id: btnBack
|
||||
// visible: stack.currentGroup.showBackBtn
|
||||
// enabled: stack.currentGroup.isValid || stack.isLastGroup
|
||||
// onClicked: {
|
||||
// if (typeof stack.currentGroup.onBackClicked === "function") {
|
||||
// return stack.currentGroup.onBackClicked()
|
||||
// }
|
||||
// stack.back()
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
id: btnNext
|
||||
text: qsTr("Next")
|
||||
enabled: stack.currentGroup.isValid && !stack.currentGroup.isPending
|
||||
visible: stack.currentGroup.showNextBtn
|
||||
onClicked: {
|
||||
const validity = stack.currentGroup.validate()
|
||||
if (validity.isValid && !validity.isPending) {
|
||||
if (stack.isLastGroup) {
|
||||
return root.sendTransaction(gasSelector.selectedGasLimit,
|
||||
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
gasSelector.selectedTipLimit,
|
||||
gasSelector.selectedOverallLimit,
|
||||
transactionSigner.enteredPassword)
|
||||
}
|
||||
// rightButtons: [
|
||||
// StatusButton {
|
||||
// id: btnNext
|
||||
// text: qsTr("Next")
|
||||
// enabled: stack.currentGroup.isValid && !stack.currentGroup.isPending
|
||||
// visible: stack.currentGroup.showNextBtn
|
||||
// onClicked: {
|
||||
// const validity = stack.currentGroup.validate()
|
||||
// if (validity.isValid && !validity.isPending) {
|
||||
// if (stack.isLastGroup) {
|
||||
// return root.sendTransaction(gasSelector.selectedGasLimit,
|
||||
// gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
// gasSelector.selectedTipLimit,
|
||||
// gasSelector.selectedOverallLimit,
|
||||
// transactionSigner.enteredPassword)
|
||||
// }
|
||||
|
||||
if(gasSelector.suggestedFees.eip1559Enabled && stack.currentGroup === groupSelectGas && gasSelector.advancedMode){
|
||||
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
|
||||
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
|
||||
currentBaseFee: gasSelector.suggestedFees.baseFee,
|
||||
currentMinimumTip: gasSelector.perGasTipLimitFloor,
|
||||
currentAverageTip: gasSelector.perGasTipLimitAverage,
|
||||
tipLimit: gasSelector.selectedTipLimit,
|
||||
suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO:
|
||||
priceLimit: gasSelector.selectedOverallLimit,
|
||||
suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
|
||||
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
|
||||
showTipLimitWarning: gasSelector.showTipLimitWarning,
|
||||
onConfirm: function(){
|
||||
stack.next();
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
// if(gasSelector.suggestedFees.eip1559Enabled && stack.currentGroup === groupSelectGas && gasSelector.advancedMode){
|
||||
// if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
|
||||
// Global.openPopup(transactionSettingsConfirmationPopupComponent, {
|
||||
// currentBaseFee: gasSelector.suggestedFees.baseFee,
|
||||
// currentMinimumTip: gasSelector.perGasTipLimitFloor,
|
||||
// currentAverageTip: gasSelector.perGasTipLimitAverage,
|
||||
// tipLimit: gasSelector.selectedTipLimit,
|
||||
// suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO:
|
||||
// priceLimit: gasSelector.selectedOverallLimit,
|
||||
// suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
|
||||
// showPriceLimitWarning: gasSelector.showPriceLimitWarning,
|
||||
// showTipLimitWarning: gasSelector.showTipLimitWarning,
|
||||
// onConfirm: function(){
|
||||
// stack.next();
|
||||
// }
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
if (typeof stack.currentGroup.onNextClicked === "function") {
|
||||
return stack.currentGroup.onNextClicked()
|
||||
}
|
||||
stack.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
// if (typeof stack.currentGroup.onNextClicked === "function") {
|
||||
// return stack.currentGroup.onNextClicked()
|
||||
// }
|
||||
// stack.next()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
|
||||
Component {
|
||||
id: transactionSettingsConfirmationPopupComponent
|
||||
TransactionSettingsConfirmationPopup { }
|
||||
}
|
||||
// Component {
|
||||
// id: transactionSettingsConfirmationPopupComponent
|
||||
// TransactionSettingsConfirmationPopup { }
|
||||
// }
|
||||
|
||||
Connections {
|
||||
target: root.store.walletSectionTransactionsInst
|
||||
onTransactionSent: {
|
||||
try {
|
||||
let response = JSON.parse(txResult)
|
||||
if (response.uuid !== stack.uuid)
|
||||
return
|
||||
// Connections {
|
||||
// target: root.store.walletSectionTransactionsInst
|
||||
// onTransactionSent: {
|
||||
// try {
|
||||
// let response = JSON.parse(txResult)
|
||||
// if (response.uuid !== stack.uuid)
|
||||
// return
|
||||
|
||||
stack.currentGroup.isPending = false
|
||||
// stack.currentGroup.isPending = false
|
||||
|
||||
let transactionId = response.result
|
||||
// let transactionId = response.result
|
||||
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(transactionId)){
|
||||
transactionSigner.validationError = qsTr("Wrong password")
|
||||
return
|
||||
}
|
||||
sendingError.text = transactionId
|
||||
return sendingError.open()
|
||||
}
|
||||
// if (!response.success) {
|
||||
// if (Utils.isInvalidPasswordMessage(transactionId)){
|
||||
// transactionSigner.validationError = qsTr("Wrong password")
|
||||
// return
|
||||
// }
|
||||
// sendingError.text = transactionId
|
||||
// return sendingError.open()
|
||||
// }
|
||||
|
||||
if(isARequest)
|
||||
root.store.acceptRequestTransaction(transactionId, msgId, root.store.getPubkey() + transactionId.substr(2))
|
||||
// if(isARequest)
|
||||
// root.store.acceptRequestTransaction(transactionId, msgId, root.store.getPubkey() + transactionId.substr(2))
|
||||
|
||||
// Refactor this
|
||||
let url = "" //`${walletModel.utilsView.etherscanLink}/${response.result}`
|
||||
Global.displayToastMessage(qsTr("Transaction pending..."),
|
||||
qsTr("View on etherscan"),
|
||||
"",
|
||||
true,
|
||||
Constants.ephemeralNotificationType.normal,
|
||||
url)
|
||||
// // Refactor this
|
||||
// let url = "" //`${walletModel.utilsView.etherscanLink}/${response.result}`
|
||||
// Global.displayToastMessage(qsTr("Transaction pending..."),
|
||||
// qsTr("View on etherscan"),
|
||||
// "",
|
||||
// true,
|
||||
// Constants.ephemeralNotificationType.normal,
|
||||
// url)
|
||||
|
||||
root.close()
|
||||
} catch (e) {
|
||||
console.error('Error parsing the response', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
// root.close()
|
||||
// } catch (e) {
|
||||
// console.error('Error parsing the response', e)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
|
|
@ -1,242 +0,0 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import shared.views 1.0
|
||||
import shared.popups 1.0
|
||||
import shared.stores 1.0
|
||||
import shared.controls 1.0
|
||||
|
||||
// TODO: replace with StatusModal
|
||||
ModalPopup {
|
||||
id: root
|
||||
|
||||
property var ensUsernamesStore
|
||||
property var contactsStore
|
||||
property string ensUsername
|
||||
|
||||
property int chainId
|
||||
readonly property var asset: {"name": "Ethereum", "symbol": "ETH"}
|
||||
|
||||
title: qsTr("Contract interaction")
|
||||
|
||||
property var estimateGasFunction: (function(userAddress) { return 0; })
|
||||
property var onSendTransaction: (function(userAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled){ return ""; })
|
||||
property var onSuccess: (function(){})
|
||||
|
||||
height: 540
|
||||
|
||||
function sendTransaction() {
|
||||
try {
|
||||
let responseStr = onSendTransaction(
|
||||
selectFromAccount.selectedAccount.address,
|
||||
gasSelector.selectedGasLimit,
|
||||
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
gasSelector.selectedTipLimit,
|
||||
gasSelector.selectedOverallLimit,
|
||||
transactionSigner.enteredPassword,
|
||||
gasSelector.suggestedFees.eip1559Enabled);
|
||||
|
||||
let response = JSON.parse(responseStr)
|
||||
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(response.result)){
|
||||
transactionSigner.validationError = qsTr("Wrong password")
|
||||
return
|
||||
}
|
||||
sendingError.text = response.result
|
||||
return sendingError.open()
|
||||
}
|
||||
|
||||
onSuccess();
|
||||
root.close();
|
||||
} catch (e) {
|
||||
console.error('Error sending the transaction', e)
|
||||
sendingError.text = qsTr("Error sending the transaction: %1").arg(e.message);
|
||||
return sendingError.open()
|
||||
}
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
gasSelector.suggestedFees = root.ensUsernamesStore.suggestedFees(root.chainId)
|
||||
gasSelector.checkOptimal()
|
||||
}
|
||||
|
||||
property MessageDialog sendingError: MessageDialog {
|
||||
id: sendingError
|
||||
title: qsTr("Error sending the transaction")
|
||||
icon: StandardIcon.Critical
|
||||
standardButtons: StandardButton.Ok
|
||||
}
|
||||
|
||||
TransactionStackView {
|
||||
id: stack
|
||||
height: parent.height
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
onGroupActivated: {
|
||||
root.title = group.headerText
|
||||
btnNext.text = group.footerText
|
||||
}
|
||||
TransactionFormGroup {
|
||||
id: group1
|
||||
headerText: root.title
|
||||
footerText: qsTr("Continue")
|
||||
|
||||
StatusAccountSelector {
|
||||
id: selectFromAccount
|
||||
accounts: walletSectionAccounts.model
|
||||
selectedAccount: {
|
||||
const currAcc = walletSectionCurrent
|
||||
if (currAcc.walletType !== Constants.watchWalletType) {
|
||||
return currAcc
|
||||
}
|
||||
return null
|
||||
}
|
||||
currency: root.ensUsernamesStore.getCurrentCurrency()
|
||||
width: stack.width
|
||||
chainId: root.chainId
|
||||
label: qsTr("Choose account")
|
||||
showBalanceForAssetSymbol: "ETH"
|
||||
minRequiredAssetBalance: 0
|
||||
onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
|
||||
}
|
||||
GasSelector {
|
||||
id: gasSelector
|
||||
visible: true
|
||||
anchors.top: selectFromAccount.bottom
|
||||
anchors.topMargin: Style.current.padding
|
||||
getGasEthValue: root.ensUsernamesStore.getGasEthValue
|
||||
getEstimatedTime: root.ensUsernamesStore.getEstimatedTime
|
||||
getFiatValue: root.ensUsernamesStore.getFiatValue
|
||||
defaultCurrency: root.ensUsernamesStore.getCurrentCurrency()
|
||||
|
||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||
let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount);
|
||||
gasSelector.selectedGasLimit = estimatedGas
|
||||
return estimatedGas;
|
||||
})
|
||||
}
|
||||
GasValidator {
|
||||
id: gasValidator
|
||||
anchors.top: gasSelector.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
selectedAccount: selectFromAccount.selectedAccount
|
||||
selectedAsset: root.asset
|
||||
selectedAmount: 0
|
||||
selectedGasEthValue: gasSelector.selectedGasEthValue
|
||||
selectedNetwork: {
|
||||
return {chainId: root.chainId}
|
||||
}
|
||||
}
|
||||
}
|
||||
TransactionFormGroup {
|
||||
id: group3
|
||||
headerText: root.title
|
||||
footerText: qsTr("Sign with password")
|
||||
|
||||
TransactionPreview {
|
||||
id: pvwTransaction
|
||||
width: stack.width
|
||||
fromAccount: selectFromAccount.selectedAccount
|
||||
gas: {
|
||||
"value": gasSelector.selectedGasEthValue,
|
||||
"symbol": "ETH",
|
||||
"fiatValue": gasSelector.selectedGasFiatValue
|
||||
}
|
||||
toAccount: { "address": root.ensUsernamesStore.getEnsRegisteredAddress(), "type": RecipientSelector.Type.Address }
|
||||
asset: root.asset
|
||||
currency: root.ensUsernamesStore.getCurrentCurrency()
|
||||
amount: {
|
||||
const fiatValue = root.ensUsernamesStore.getFiatValue(0, root.asset.symbol, currency)
|
||||
return { "value": 0, "fiatValue": fiatValue }
|
||||
}
|
||||
}
|
||||
}
|
||||
TransactionFormGroup {
|
||||
id: group4
|
||||
headerText: root.title
|
||||
footerText: qsTr("Sign with password")
|
||||
|
||||
TransactionSigner {
|
||||
id: transactionSigner
|
||||
width: stack.width
|
||||
signingPhrase: root.ensUsernamesStore.getSigningPhrase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: Item {
|
||||
width: parent.width
|
||||
height: btnNext.height
|
||||
|
||||
StatusBackButton {
|
||||
id: btnBack
|
||||
anchors.left: parent.left
|
||||
visible: stack.currentGroup.showBackBtn
|
||||
enabled: stack.currentGroup.isValid || stack.isLastGroup
|
||||
onClicked: {
|
||||
if (typeof stack.currentGroup.onBackClicked === "function") {
|
||||
return stack.currentGroup.onBackClicked()
|
||||
}
|
||||
stack.back()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: transactionSettingsConfirmationPopupComponent
|
||||
TransactionSettingsConfirmationPopup {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
id: btnNext
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Next")
|
||||
enabled: stack.currentGroup.isValid
|
||||
onClicked: {
|
||||
const validity = stack.currentGroup.validate()
|
||||
if (validity.isValid && !validity.isPending) {
|
||||
if (stack.isLastGroup) {
|
||||
return root.sendTransaction()
|
||||
}
|
||||
|
||||
if(gasSelector.suggestedFees.eip1559Enabled && stack.currentGroup === group3 && gasSelector.advancedMode){
|
||||
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
|
||||
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
|
||||
currentBaseFee: gasSelector.suggestedFees.baseFee,
|
||||
currentMinimumTip: gasSelector.perGasTipLimitFloor,
|
||||
currentAverageTip: gasSelector.perGasTipLimitAverage,
|
||||
tipLimit: gasSelector.selectedTipLimit,
|
||||
suggestedTipLimit: gasSelector.perGasTipLimitFloor,
|
||||
priceLimit: gasSelector.selectedOverallLimit,
|
||||
suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
|
||||
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
|
||||
showTipLimitWarning: gasSelector.showTipLimitWarning,
|
||||
onConfirm: function(){
|
||||
stack.next();
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
stack.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*##^##
|
||||
Designer {
|
||||
D{i:0;autoSize:true;height:480;width:640}
|
||||
}
|
||||
##^##*/
|
|
@ -1,272 +0,0 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import shared.views 1.0
|
||||
import shared.popups 1.0
|
||||
import shared.stores 1.0
|
||||
import shared.controls 1.0
|
||||
|
||||
// TODO: replace with StatusModal
|
||||
ModalPopup {
|
||||
id: root
|
||||
|
||||
property var store
|
||||
property var stickersStore
|
||||
property var contactsStore
|
||||
|
||||
readonly property var asset: JSON.parse(root.stickersStore.getStatusToken())
|
||||
property string assetPrice
|
||||
property string contractAddress
|
||||
property int chainId
|
||||
property var estimateGasFunction: (function(userAddress, uuid) { return 0; })
|
||||
property var onSendTransaction: (function(userAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled){ return ""; })
|
||||
property var onSuccess: (function(){})
|
||||
property var asyncGasEstimateTarget
|
||||
|
||||
Component.onCompleted: {
|
||||
gasSelector.estimateGas();
|
||||
}
|
||||
|
||||
height: 540
|
||||
|
||||
title: qsTr("Authorize %1 %2").arg(Utils.stripTrailingZeros(assetPrice)).arg(asset.symbol)
|
||||
|
||||
property MessageDialog sendingError: MessageDialog {
|
||||
id: sendingError
|
||||
title: qsTr("Error sending the transaction")
|
||||
icon: StandardIcon.Critical
|
||||
standardButtons: StandardButton.Ok
|
||||
}
|
||||
|
||||
function setAsyncGasLimitResult(uuid, value) {
|
||||
if (uuid === gasSelector.uuid) {
|
||||
gasSelector.selectedGasLimit = value
|
||||
gasSelector.defaultGasLimit = value
|
||||
gasSelector.updateGasEthValue();
|
||||
}
|
||||
}
|
||||
|
||||
function sendTransaction() {
|
||||
let responseStr = onSendTransaction(selectFromAccount.selectedAccount.address,
|
||||
gasSelector.selectedGasLimit,
|
||||
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
gasSelector.selectedTipLimit,
|
||||
gasSelector.selectedOverallLimit,
|
||||
transactionSigner.enteredPassword,
|
||||
gasSelector.suggestedFees.eip1559Enabled);
|
||||
|
||||
let response = JSON.parse(responseStr)
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(response.result)){
|
||||
transactionSigner.validationError = qsTr("Wrong password")
|
||||
return
|
||||
}
|
||||
sendingError.text = response.result
|
||||
return sendingError.open()
|
||||
}
|
||||
|
||||
onSuccess();
|
||||
root.close();
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
gasSelector.suggestedFees = root.store.suggestedFees(root.chainId)
|
||||
gasSelector.checkOptimal()
|
||||
}
|
||||
|
||||
TransactionStackView {
|
||||
id: stack
|
||||
height: parent.height
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
initialItem: group1
|
||||
isLastGroup: stack.currentGroup === group3
|
||||
onGroupActivated: {
|
||||
root.title = group.headerText
|
||||
btnNext.text = group.footerText
|
||||
}
|
||||
TransactionFormGroup {
|
||||
id: group1
|
||||
headerText: qsTr("Authorize %1 %2").arg(Utils.stripTrailingZeros(root.assetPrice)).arg(root.asset.symbol)
|
||||
footerText: qsTr("Continue")
|
||||
showBackBtn: false
|
||||
StatusAccountSelector {
|
||||
id: selectFromAccount
|
||||
accounts: walletSectionAccounts.model
|
||||
selectedAccount: {
|
||||
const currAcc = walletSectionCurrent
|
||||
if (currAcc.walletType !== Constants.watchWalletType) {
|
||||
return currAcc
|
||||
}
|
||||
return null
|
||||
}
|
||||
currency: walletSection.currentCurrency
|
||||
width: stack.width
|
||||
label: qsTr("Choose account")
|
||||
showBalanceForAssetSymbol: root.asset.symbol
|
||||
minRequiredAssetBalance: root.assetPrice
|
||||
chainId: root.chainId
|
||||
onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
|
||||
}
|
||||
RecipientSelector {
|
||||
id: selectRecipient
|
||||
visible: false
|
||||
accounts: root.stickersStore.walletAccounts
|
||||
contactsStore: root.contactsStore
|
||||
selectedRecipient: { "address": contractAddress, "type": RecipientSelector.Type.Address }
|
||||
readOnly: true
|
||||
isValid: true
|
||||
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: asyncGasEstimateTarget
|
||||
onGasEstimateReturned: {
|
||||
root.setAsyncGasLimitResult(uuid, estimate)
|
||||
}
|
||||
}
|
||||
|
||||
GasSelector {
|
||||
id: gasSelector
|
||||
anchors.top: selectFromAccount.bottom
|
||||
anchors.topMargin: Style.current.padding
|
||||
getGasEthValue: root.stickersStore.getGasEthValue
|
||||
getFiatValue: root.stickersStore.getFiatValue
|
||||
defaultCurrency: root.stickersStore.getCurrentCurrency()
|
||||
width: stack.width
|
||||
|
||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||
let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount, uuid);
|
||||
if (estimatedGas !== undefined) {
|
||||
gasSelector.selectedGasLimit = estimatedGas
|
||||
}
|
||||
return estimatedGas;
|
||||
})
|
||||
}
|
||||
GasValidator {
|
||||
id: gasValidator
|
||||
anchors.top: gasSelector.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
selectedAccount: selectFromAccount.selectedAccount
|
||||
selectedAsset: root.asset
|
||||
selectedAmount: parseFloat(root.assetPrice)
|
||||
selectedGasEthValue: gasSelector.selectedGasEthValue
|
||||
selectedNetwork: {
|
||||
return {chainId: root.chainId}
|
||||
}
|
||||
}
|
||||
}
|
||||
TransactionFormGroup {
|
||||
id: group2
|
||||
headerText: qsTr("Authorize %1 %2").arg(Utils.stripTrailingZeros(root.assetPrice)).arg(root.asset.symbol)
|
||||
footerText: qsTr("Sign with password")
|
||||
|
||||
TransactionPreview {
|
||||
id: pvwTransaction
|
||||
width: stack.width
|
||||
fromAccount: selectFromAccount.selectedAccount
|
||||
gas: {
|
||||
"value": gasSelector.selectedGasEthValue,
|
||||
"symbol": "ETH",
|
||||
"fiatValue": gasSelector.selectedGasFiatValue
|
||||
}
|
||||
toAccount: selectRecipient.selectedRecipient
|
||||
asset: root.asset
|
||||
amount: {
|
||||
const fiatValue = root.stickersStore.getFiatValue(root.assetPrice || 0, root.asset.symbol, currency)
|
||||
return { "value": root.assetPrice, "fiatValue": fiatValue }
|
||||
}
|
||||
currency: root.stickersStore.getCurrentCurrency()
|
||||
}
|
||||
}
|
||||
TransactionFormGroup {
|
||||
id: group3
|
||||
headerText: qsTr("Send %1 %2").arg(Utils.stripTrailingZeros(root.assetPrice)).arg(root.asset.symbol)
|
||||
footerText: qsTr("Sign with password")
|
||||
|
||||
TransactionSigner {
|
||||
id: transactionSigner
|
||||
width: stack.width
|
||||
signingPhrase: root.stickersStore.getSigningPhrase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: Item {
|
||||
width: parent.width
|
||||
height: btnNext.height
|
||||
|
||||
StatusBackButton {
|
||||
id: btnBack
|
||||
anchors.left: parent.left
|
||||
visible: stack.currentGroup.showBackBtn
|
||||
enabled: {
|
||||
stack.currentGroup.isValid || stack.isLastGroup
|
||||
}
|
||||
onClicked: {
|
||||
if (typeof stack.currentGroup.onBackClicked === "function") {
|
||||
return stack.currentGroup.onBackClicked()
|
||||
}
|
||||
stack.back()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: transactionSettingsConfirmationPopupComponent
|
||||
TransactionSettingsConfirmationPopup {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
id: btnNext
|
||||
anchors.right: parent.right
|
||||
text: qsTr("Next")
|
||||
objectName: "sendNextButton"
|
||||
enabled: stack.currentGroup.isValid && !stack.currentGroup.isPending
|
||||
loading: stack.currentGroup.isPending
|
||||
onClicked: {
|
||||
const validity = stack.currentGroup.validate()
|
||||
if (validity.isValid && !validity.isPending) {
|
||||
if (stack.isLastGroup) {
|
||||
return root.sendTransaction()
|
||||
}
|
||||
|
||||
if(gasSelector.suggestedFees.eip1559Enabled && stack.currentGroup === group2 && gasSelector.advancedMode){
|
||||
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
|
||||
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
|
||||
currentBaseFee: gasSelector.suggestedFees.baseFee,
|
||||
currentMinimumTip: gasSelector.perGasTipLimitFloor,
|
||||
currentAverageTip: gasSelector.perGasTipLimitAverage,
|
||||
tipLimit: gasSelector.selectedTipLimit,
|
||||
suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO:
|
||||
priceLimit: gasSelector.selectedOverallLimit,
|
||||
suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
|
||||
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
|
||||
showTipLimitWarning: gasSelector.showTipLimitWarning,
|
||||
onConfirm: function(){
|
||||
stack.next();
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
stack.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*##^##
|
||||
Designer {
|
||||
D{i:0;autoSize:true;height:480;width:640}
|
||||
}
|
||||
##^##*/
|
|
@ -149,33 +149,70 @@ Item {
|
|||
}
|
||||
Component {
|
||||
id: stickerPackPurchaseModal
|
||||
StatusSNTTransactionModal {
|
||||
store: root.store
|
||||
stickersStore: root.store.stickersStore
|
||||
contractAddress: root.store.stickersStore.getStickersMarketAddress()
|
||||
contactsStore: root.store.contactsStore
|
||||
assetPrice: price
|
||||
chainId: root.store.stickersStore.getChainIdForStickers()
|
||||
estimateGasFunction: function(selectedAccount, uuid) {
|
||||
if (packId < 0 || !selectedAccount || !price) return 325000
|
||||
return root.store.stickersStore.estimate(packId, selectedAccount.address, price, uuid)
|
||||
SendModal {
|
||||
id: buyStickersModal
|
||||
interactive: false
|
||||
sendType: Constants.SendType.StickersBuy
|
||||
preSelectedRecipient: root.store.stickersStore.getStickersMarketAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(parseFloat(price))
|
||||
preSelectedAsset: {
|
||||
let assetsList = buyStickersModal.store.currentAccount.assets
|
||||
for(var i=0; i< assetsList.count;i++) {
|
||||
let symbol = JSON.parse(root.store.stickersStore.getStatusToken()).symbol
|
||||
if(symbol === assetsList.rowData(i, "symbol"))
|
||||
return {
|
||||
name: assetsList.rowData(i, "name"),
|
||||
symbol: assetsList.rowData(i, "symbol"),
|
||||
totalBalance: assetsList.rowData(i, "totalBalance"),
|
||||
totalCurrencyBalance: assetsList.rowData(i, "totalCurrencyBalance"),
|
||||
balances: assetsList.rowData(i, "balances"),
|
||||
decimals: assetsList.rowData(i, "decimals")
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
|
||||
return root.store.stickersStore.buy(packId,
|
||||
selectedAddress,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
tipLimit,
|
||||
overallLimit,
|
||||
password,
|
||||
eip1559Enabled)
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.length === 1) {
|
||||
let path = bestRoutes[0]
|
||||
let eip1559Enabled = path.gasFees.eip1559Enabled
|
||||
let maxFeePerGas = (selectedPriority === 0) ? path.gasFees.maxFeePerGasL:
|
||||
(selectedPriority === 1) ? path.gasFees.maxFeePerGasM:
|
||||
path.gasFees.maxFeePerGasH
|
||||
root.store.stickersStore.authenticateAndBuy(packId,
|
||||
selectedAccount.address,
|
||||
path.gasAmount,
|
||||
eip1559Enabled ? "" : path.gasFees.gasPrice,
|
||||
eip1559Enabled ? path.gasFees.maxPriorityFeePerGas : "",
|
||||
eip1559Enabled ? maxFeePerGas : path.gasFees.gasPrice,
|
||||
eip1559Enabled)
|
||||
}
|
||||
}
|
||||
onClosed: {
|
||||
destroy()
|
||||
Connections {
|
||||
target: root.store.stickersStore.stickersModule
|
||||
onTransactionWasSent: {
|
||||
try {
|
||||
let response = JSON.parse(txResult)
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(response.result)) {
|
||||
buyStickersModal.setSendTxError()
|
||||
return
|
||||
}
|
||||
buyStickersModal.sendingError.text = response.result
|
||||
return buyStickersModal.sendingError.open()
|
||||
}
|
||||
let url = `${buyStickersModal.store.getEtherscanLink()}/${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)
|
||||
}
|
||||
}
|
||||
}
|
||||
asyncGasEstimateTarget: root.store.stickersStore.stickersModule
|
||||
width: stickerPackDetailsPopup.width
|
||||
height: stickerPackDetailsPopup.height
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,33 +62,70 @@ ModalPopup {
|
|||
packId: stickerPackDetailsPopup.packId
|
||||
Component {
|
||||
id: stickerPackPurchaseModal
|
||||
StatusSNTTransactionModal {
|
||||
store: stickerPackDetailsPopup.store
|
||||
stickersStore: stickerPackDetailsPopup.store.stickersStore
|
||||
contactsStore: stickerPackDetailsPopup.store.contactsStore
|
||||
contractAddress: root.store.stickersStore.getStickersMarketAddress()
|
||||
assetPrice: price
|
||||
chainId: root.store.stickersStore.getChainIdForStickers()
|
||||
estimateGasFunction: function(selectedAccount, uuid) {
|
||||
if (packId < 0 || !selectedAccount || !price) return 325000
|
||||
return stickerPackDetailsPopup.store.stickersStore.estimate(packId, selectedAccount.address, price, uuid)
|
||||
SendModal {
|
||||
id: buyStickersPackModal
|
||||
interactive: false
|
||||
sendType: Constants.SendType.StickersBuy
|
||||
preSelectedRecipient: stickerPackDetailsPopup.store.stickersStore.getStickersMarketAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(parseFloat(price))
|
||||
preSelectedAsset: {
|
||||
let assetsList = buyStickersPackModal.store.currentAccount.assets
|
||||
for(var i=0; i< assetsList.count;i++) {
|
||||
let symbol = JSON.parse(stickerPackDetailsPopup.store.stickersStore.getStatusToken()).symbol
|
||||
if(symbol === assetsList.rowData(i, "symbol"))
|
||||
return {
|
||||
name: assetsList.rowData(i, "name"),
|
||||
symbol: assetsList.rowData(i, "symbol"),
|
||||
totalBalance: assetsList.rowData(i, "totalBalance"),
|
||||
totalCurrencyBalance: assetsList.rowData(i, "totalCurrencyBalance"),
|
||||
balances: assetsList.rowData(i, "balances"),
|
||||
decimals: assetsList.rowData(i, "decimals")
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
|
||||
return root.store.stickersStore.buy(packId,
|
||||
selectedAddress,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
tipLimit,
|
||||
overallLimit,
|
||||
password,
|
||||
eip1559Enabled)
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.length === 1) {
|
||||
let path = bestRoutes[0]
|
||||
let eip1559Enabled = path.gasFees.eip1559Enabled
|
||||
let maxFeePerGas = (selectedPriority === 0) ? path.gasFees.maxFeePerGasL:
|
||||
(selectedPriority === 1) ? path.gasFees.maxFeePerGasM:
|
||||
path.gasFees.maxFeePerGasH
|
||||
stickerPackDetailsPopup.store.stickersStore.authenticateAndBuy(packId,
|
||||
selectedAccount.address,
|
||||
path.gasAmount,
|
||||
eip1559Enabled ? "" : path.gasFees.gasPrice,
|
||||
eip1559Enabled ? path.gasFees.maxPriorityFeePerGas : "",
|
||||
eip1559Enabled ? maxFeePerGas : path.gasFees.gasPrice,
|
||||
eip1559Enabled)
|
||||
}
|
||||
}
|
||||
onClosed: {
|
||||
destroy()
|
||||
Connections {
|
||||
target: stickerPackDetailsPopup.store.stickersStore.stickersModule
|
||||
onTransactionWasSent: {
|
||||
try {
|
||||
let response = JSON.parse(txResult)
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(response.result)) {
|
||||
buyStickersPackModal.setSendTxError()
|
||||
return
|
||||
}
|
||||
buyStickersPackModal.sendingError.text = response.result
|
||||
return buyStickersPackModal.sendingError.open()
|
||||
}
|
||||
let url = `${buyStickersPackModal.store.getEtherscanLink()}/${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)
|
||||
}
|
||||
}
|
||||
}
|
||||
asyncGasEstimateTarget: stickerPackDetailsPopup.store.stickersStore.stickersModule
|
||||
width: stickerPackDetailsPopup.width
|
||||
height: stickerPackDetailsPopup.height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ StatusChatInputTextFormationAction 1.0 StatusChatInputTextFormationAction.qml
|
|||
StatusEmojiPopup 1.0 StatusEmojiPopup.qml
|
||||
StatusEmojiSection 1.0 StatusEmojiSection.qml
|
||||
StatusEmojiSuggestionPopup 1.0 StatusEmojiSuggestionPopup.qml
|
||||
StatusETHTransactionModal 1.0 StatusETHTransactionModal.qml
|
||||
StatusExpandableAddress 1.0 StatusExpandableAddress.qml
|
||||
StatusGifPopup 1.0 StatusGifPopup.qml
|
||||
StatusImageModal 1.0 StatusImageModal.qml
|
||||
|
@ -23,7 +22,6 @@ StatusSearchListPopup 1.0 StatusSearchListPopup.qml
|
|||
StatusSectionDescItem 1.0 StatusSectionDescItem.qml
|
||||
StatusSectionHeadline 1.0 StatusSectionHeadline.qml
|
||||
StatusSettingsLineButton 1.0 StatusSettingsLineButton.qml
|
||||
StatusSNTTransactionModal 1.0 StatusSNTTransactionModal.qml
|
||||
StatusSticker 1.0 StatusSticker.qml
|
||||
StatusStickerButton 1.0 StatusStickerButton.qml
|
||||
StatusStickerList 1.0 StatusStickerList.qml
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
import QtQuick 2.13
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import shared.stores 1.0
|
||||
import "../../../app/AppLayouts/Profile/stores"
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
property CurrenciesStore currencyStore: CurrenciesStore { }
|
||||
property ProfileSectionStore profileSectionStore: ProfileSectionStore {}
|
||||
property var contactStore: profileSectionStore.contactsStore
|
||||
|
||||
property var mainModuleInst: mainModule
|
||||
property var walletSectionTransactionsInst: walletSectionTransactions
|
||||
|
||||
property string locale: localAppSettings.language
|
||||
property string currentCurrency: walletSection.currentCurrency
|
||||
property var allNetworks: networksModule.all
|
||||
property var accounts: walletSectionAccounts.model
|
||||
property var currentAccount: walletSectionCurrent
|
||||
property string signingPhrase: walletSection.signingPhrase
|
||||
property var savedAddressesModel: walletSectionSavedAddresses.model
|
||||
property var disabledChainIdsFromList: []
|
||||
property var disabledChainIdsToList: []
|
||||
|
||||
function addRemoveDisabledFromChain(chainID, isDisabled) {
|
||||
var tempList = disabledChainIdsFromList
|
||||
if(isDisabled) {
|
||||
tempList.push(chainID)
|
||||
}
|
||||
else {
|
||||
for(var i = 0; i < tempList.length;i++) {
|
||||
if(tempList[i] === chainID) {
|
||||
tempList.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
disabledChainIdsFromList = tempList
|
||||
}
|
||||
|
||||
function addRemoveDisabledToChain(chainID, isDisabled) {
|
||||
var tempList = disabledChainIdsToList
|
||||
if(isDisabled) {
|
||||
tempList.push(chainID)
|
||||
}
|
||||
else {
|
||||
for(var i = 0; i < tempList.length;i++) {
|
||||
if(tempList[i] === chainID) {
|
||||
tempList.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
disabledChainIdsToList = tempList
|
||||
}
|
||||
|
||||
function getEtherscanLink() {
|
||||
return profileSectionModule.ensUsernamesModule.getEtherscanLink()
|
||||
}
|
||||
|
||||
function copyToClipboard(text) {
|
||||
globalUtils.copyToClipboard(text)
|
||||
}
|
||||
|
||||
function estimateGas(from_addr, to, assetSymbol, value, chainId, data) {
|
||||
return walletSectionTransactions.estimateGas(from_addr, to, assetSymbol, value, chainId, data)
|
||||
}
|
||||
|
||||
function getFiatValue(balance, cryptoSymbol, fiatSymbol) {
|
||||
return profileSectionStore.ensUsernamesStore.getFiatValue(balance, cryptoSymbol, fiatSymbol)
|
||||
}
|
||||
|
||||
function getGasEthValue(gweiValue, gasLimit) {
|
||||
return profileSectionStore.ensUsernamesStore.getGasEthValue(gweiValue, gasLimit)
|
||||
}
|
||||
|
||||
function authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, priority, selectedRoutes) {
|
||||
walletSectionTransactions.authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, priority, selectedRoutes)
|
||||
}
|
||||
|
||||
function suggestedFees(chainId) {
|
||||
return JSON.parse(walletSectionTransactions.suggestedFees(chainId))
|
||||
}
|
||||
|
||||
function getEstimatedTime(chainId, maxFeePerGas) {
|
||||
return walletSectionTransactions.getEstimatedTime(chainId, maxFeePerGas)
|
||||
}
|
||||
|
||||
function getChainIdForChat() {
|
||||
return walletSectionTransactions.getChainIdForChat()
|
||||
}
|
||||
|
||||
function getChainIdForBrowser() {
|
||||
return walletSectionTransactions.getChainIdForBrowser()
|
||||
}
|
||||
|
||||
function suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, priority, sendType) {
|
||||
walletSectionTransactions.suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, priority, sendType)
|
||||
}
|
||||
|
||||
function hex2Eth(value) {
|
||||
return globalUtils.hex2Eth(value)
|
||||
}
|
||||
|
||||
function switchAccount(newIndex) {
|
||||
if(Constants.isCppApp)
|
||||
walletSectionAccounts.switchAccount(newIndex)
|
||||
else
|
||||
walletSection.switchAccount(newIndex)
|
||||
}
|
||||
|
||||
function resolveENS(value) {
|
||||
mainModuleInst.resolveENS(value, "")
|
||||
}
|
||||
|
||||
function getWei2Eth(wei) {
|
||||
return globalUtils.wei2Eth(wei,18)
|
||||
}
|
||||
|
||||
function getEth2Wei(eth) {
|
||||
return globalUtils.eth2Wei(eth, 18)
|
||||
}
|
||||
|
||||
function plainText(text) {
|
||||
return globalUtils.plainText(text)
|
||||
}
|
||||
}
|
|
@ -1,2 +1,4 @@
|
|||
singleton RootStore 1.0 RootStore.qml
|
||||
CurrenciesStore 1.0 CurrenciesStore.qml
|
||||
TransactionStore 1.0 TransactionStore.qml
|
||||
BIP39_en 1.0 BIP39_en.qml
|
||||
|
|
|
@ -11,54 +11,51 @@ import StatusQ.Core.Theme 0.1
|
|||
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||
|
||||
Item {
|
||||
id: networkCardsComponent
|
||||
id: root
|
||||
|
||||
property var assets
|
||||
property var store
|
||||
property string locale: ""
|
||||
property var selectedAsset
|
||||
property var suggestedRoutes
|
||||
property bool customMode: false
|
||||
property var selectedNetwork
|
||||
property var bestRoutes
|
||||
property var selectedAccount
|
||||
property var selectedAsset
|
||||
property var allNetworks
|
||||
property bool customMode: false
|
||||
property double amountToSend: 0
|
||||
property double requiredGasInEth: 0
|
||||
property bool errorMode: (d.customAmountToSend > amountToSend) ||
|
||||
(d.customAmountToSend < amountToSend) ||
|
||||
(d.customAmountToReceive > amountToSend) ||
|
||||
(d.customAmountToReceive < amountToSend)
|
||||
property bool errorMode: {
|
||||
if(customMode) {
|
||||
return (d.customAmountToSend > amountToSend) || (d.customAmountToSend < amountToSend) ||
|
||||
(d.customAmountToReceive > amountToSend) || (d.customAmountToReceive < amountToSend)
|
||||
}
|
||||
else {
|
||||
return !d.thereIsApossibleRoute
|
||||
}
|
||||
}
|
||||
property bool interactive: true
|
||||
property var weiToEth: function(wei) {}
|
||||
|
||||
signal reCalculateSuggestedRoute(var disabled)
|
||||
signal reCalculateSuggestedRoute()
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property var selectedFromNetwork
|
||||
property var selectedToNetwork
|
||||
property double customAmountToSend: 0
|
||||
property double customAmountToReceive: 0
|
||||
property bool thereIsApossibleRoute: false
|
||||
|
||||
function getBalance(chainID) {
|
||||
for(var i=0; i< selectedAsset.balances.count; i++) {
|
||||
if(selectedAsset.balances.rowData(i, "chainId") === chainID.toString()) {
|
||||
return selectedAsset.balances.rowData(i, "balance")
|
||||
}
|
||||
function resetAllSetValues() {
|
||||
for(var i = 0; i<fromNetworksRepeater.count; i++) {
|
||||
fromNetworksRepeater.itemAt(i).amountToSend = 0
|
||||
toNetworksRepeater.itemAt(i).amountToReceive = 0
|
||||
}
|
||||
}
|
||||
|
||||
onSelectedFromNetworkChanged: {
|
||||
canvas.clear()
|
||||
canvas.requestPaint()
|
||||
}
|
||||
|
||||
onSelectedToNetworkChanged: {
|
||||
canvas.clear()
|
||||
canvas.requestPaint()
|
||||
}
|
||||
}
|
||||
|
||||
width: 410
|
||||
height: networkCardsLayout.height
|
||||
height: visible ? networkCardsLayout.height : 0
|
||||
|
||||
onBestRoutesChanged: {
|
||||
canvas.clear()
|
||||
canvas.requestPaint()
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: networkCardsLayout
|
||||
|
@ -73,44 +70,35 @@ Item {
|
|||
text: qsTr("Your Balances").toUpperCase()
|
||||
}
|
||||
Repeater {
|
||||
model: networkCardsComponent.allNetworks
|
||||
id: fromNetworksRepeater
|
||||
model: root.allNetworks
|
||||
StatusCard {
|
||||
id: fromNetwork
|
||||
property var tokenBalanceOnChain: Utils.toLocaleString(parseFloat(d.getBalance(model.chainId)).toFixed(4), locale, {"currency": true})
|
||||
property var hasGas: assets.hasGas(model.chainId, model.nativeCurrencySymbol, requiredGasInEth + parseFloat(amountToSend))
|
||||
objectName: model.chainId
|
||||
property double amountToSend: 0
|
||||
property string tokenBalanceOnChain: selectedAccount && selectedAccount!== undefined && selectedAsset!== undefined ? selectedAccount.getTokenBalanceOnChain(model.chainId, selectedAsset.symbol) : ""
|
||||
property var hasGas: selectedAccount.hasGas(model.chainId, model.nativeCurrencySymbol, requiredGasInEth)
|
||||
primaryText: model.chainName
|
||||
secondaryText: (parseFloat(tokenBalanceOnChain) === 0 && amountToSend !== 0) ?
|
||||
qsTr("No Balance") : !hasGas ? qsTr("No Gas") :
|
||||
(selectedNetwork && selectedNetwork.chainName === model.chainName) ?
|
||||
amountToSend: 0
|
||||
tertiaryText: qsTr("BALANCE: ") + tokenBalanceOnChain
|
||||
state: tokenBalanceOnChain === 0 || !hasGas ? "unavailable" : networkCardsComponent.errorMode ? "error" : "default"
|
||||
cardIcon.source: Style.png(model.iconUrl)
|
||||
secondaryText: (parseFloat(tokenBalanceOnChain) === 0 && root.amountToSend !== 0) ?
|
||||
qsTr("No Balance") : !hasGas ? qsTr("No Gas") : LocaleUtils.numberToLocaleString(fromNetwork.amountToSend)
|
||||
tertiaryText: qsTr("BALANCE: ") + LocaleUtils.numberToLocaleString(parseFloat(tokenBalanceOnChain))
|
||||
state: tokenBalanceOnChain === 0 || !hasGas ? "unavailable" : root.errorMode ? "error" : "default"
|
||||
cardIcon.source: Style.svg(model.iconUrl)
|
||||
disabledText: qsTr("Disabled")
|
||||
advancedMode: networkCardsComponent.customMode
|
||||
advancedInputText: (selectedNetwork && selectedNetwork.chainName === model.chainName) ? amountToSend: 0
|
||||
Component.onCompleted: {
|
||||
disabled = store.checkIfDisabledByUser(model.chainId)
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName)
|
||||
d.selectedFromNetwork = this
|
||||
}
|
||||
Connections {
|
||||
target: networkCardsComponent
|
||||
onSelectedNetworkChanged: {
|
||||
if(selectedNetwork.chainName === model.chainName) {
|
||||
d.selectedFromNetwork = fromNetwork
|
||||
}
|
||||
}
|
||||
}
|
||||
advancedMode: root.customMode
|
||||
advancedInputText: LocaleUtils.numberToLocaleString(fromNetwork.amountToSend)
|
||||
disabled: store.disabledChainIdsFromList.includes(model.chainId)
|
||||
clickable: root.interactive
|
||||
onClicked: {
|
||||
store.addRemoveDisabledChain(suggestedRoutes, model.chainId, disabled)
|
||||
reCalculateSuggestedRoute(store.disabledChainIds)
|
||||
}
|
||||
onAdvancedInputTextChanged: {
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName) {
|
||||
d.customAmountToSend = isNaN(parseFloat(advancedInputText)) ? 0 : parseFloat(advancedInputText)
|
||||
}
|
||||
store.addRemoveDisabledFromChain(model.chainId, disabled)
|
||||
root.reCalculateSuggestedRoute()
|
||||
}
|
||||
// To-do needed for custom view
|
||||
// onAdvancedInputTextChanged: {
|
||||
// if(selectedNetwork && selectedNetwork.chainName === model.chainName) {
|
||||
// d.customAmountToSend = isNaN(parseFloat(advancedInputText)) ? 0 : parseFloat(advancedInputText)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,39 +115,33 @@ Item {
|
|||
elide: Text.ElideMiddle
|
||||
}
|
||||
Repeater {
|
||||
model: networkCardsComponent.allNetworks
|
||||
id: toNetworksRepeater
|
||||
model: root.allNetworks
|
||||
StatusCard {
|
||||
id: toCard
|
||||
objectName: model.chainId
|
||||
property double amountToReceive: 0
|
||||
primaryText: model.chainName
|
||||
secondaryText: (selectedNetwork && selectedNetwork.chainName === model.chainName) ? amountToSend: 0
|
||||
secondaryText: LocaleUtils.numberToLocaleString(amountToReceive)
|
||||
tertiaryText: ""
|
||||
// To-do preferred in not something that is supported yet
|
||||
state: networkCardsComponent.errorMode ? "error" : "default"
|
||||
state: root.errorMode ? "error" : "default"
|
||||
// opacity: preferred ? 1 : 0
|
||||
cardIcon.source: Style.png(model.iconUrl)
|
||||
cardIcon.source: Style.svg(model.iconUrl)
|
||||
disabledText: qsTr("Disabled")
|
||||
advancedMode: networkCardsComponent.customMode
|
||||
advancedInputText: (selectedNetwork && selectedNetwork.chainName === model.chainName) ? amountToSend: 0
|
||||
Component.onCompleted: {
|
||||
disabled = store.checkIfDisabledByUser(model.chainId)
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName)
|
||||
d.selectedToNetwork = this
|
||||
}
|
||||
Connections {
|
||||
target: networkCardsComponent
|
||||
onSelectedNetworkChanged: {
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName)
|
||||
d.selectedToNetwork = toCard
|
||||
}
|
||||
}
|
||||
advancedMode: root.customMode
|
||||
advancedInputText: LocaleUtils.numberToLocaleString(amountToReceive)
|
||||
disabled: store.disabledChainIdsToList.includes(model.chainId)
|
||||
clickable: root.interactive
|
||||
onClicked: {
|
||||
store.addRemoveDisabledChain(suggestedRoutes, model.chainId, disabled)
|
||||
reCalculateSuggestedRoute(store.disabledChainIds)
|
||||
}
|
||||
onAdvancedInputTextChanged: {
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName)
|
||||
d.customAmountToReceive = isNaN(parseFloat(advancedInputText)) ? 0 : parseFloat(advancedInputText)
|
||||
store.addRemoveDisabledToChain(model.chainId, disabled)
|
||||
root.reCalculateSuggestedRoute()
|
||||
}
|
||||
// To-do needed for custom view
|
||||
// onAdvancedInputTextChanged: {
|
||||
// if(selectedNetwork && selectedNetwork.chainName === model.chainName)
|
||||
// d.customAmountToReceive = isNaN(parseFloat(advancedInputText)) ? 0 : parseFloat(advancedInputText)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,21 +156,47 @@ Item {
|
|||
|
||||
function clear() {
|
||||
if(available) {
|
||||
var ctx = getContext("2d");
|
||||
if(ctx)
|
||||
ctx.reset()
|
||||
var ctx = getContext("2d");
|
||||
if(ctx)
|
||||
ctx.reset()
|
||||
}
|
||||
}
|
||||
|
||||
onPaint: {
|
||||
if(d.selectedFromNetwork && d.selectedToNetwork) {
|
||||
// Get the canvas context
|
||||
var ctx = getContext("2d");
|
||||
StatusQUtils.Utils.drawArrow(ctx, d.selectedFromNetwork.x + d.selectedFromNetwork.width,
|
||||
d.selectedFromNetwork.y + d.selectedFromNetwork.height/2,
|
||||
toNetworksLayout.x + d.selectedToNetwork.x,
|
||||
d.selectedToNetwork.y + d.selectedToNetwork.height/2,
|
||||
'#627EEA')
|
||||
d.resetAllSetValues()
|
||||
d.thereIsApossibleRoute = false
|
||||
|
||||
if(bestRoutes === undefined)
|
||||
return
|
||||
|
||||
// Get the canvas context
|
||||
var ctx = getContext("2d");
|
||||
for(var i = 0; i< bestRoutes.length; i++) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
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) {
|
||||
let amountToSend = weiToEth(bestRoutes[i].amountIn)
|
||||
let amountToReceive = weiToEth(bestRoutes[i].amountOut)
|
||||
fromN.amountToSend = amountToSend
|
||||
toN.amountToReceive += amountToReceive
|
||||
d.thereIsApossibleRoute = true
|
||||
StatusQUtils.Utils.drawArrow(ctx, fromN.x + fromN.width,
|
||||
fromN.y + fromN.height/2,
|
||||
toNetworksLayout.x + toN.x,
|
||||
toN.y + toN.height/2,
|
||||
'#627EEA')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,17 +17,20 @@ Item {
|
|||
implicitHeight: visible ? tabBar.height + stackLayout.height + 2* Style.current.xlPadding : 0
|
||||
|
||||
property var store
|
||||
property var suggestedRoutes
|
||||
property var selectedNetwork
|
||||
property var selectedAccount
|
||||
property var selectedAsset
|
||||
property var assets
|
||||
property double amountToSend: 0
|
||||
property double requiredGasInEth: 0
|
||||
property bool errorMode: customNetworkRoutingPage.errorMode
|
||||
property var bestRoutes
|
||||
property bool isLoading: false
|
||||
property bool advancedOrCustomMode: (tabBar.currentIndex === 1) || (tabBar.currentIndex === 2)
|
||||
property bool errorMode: (tabBar.currentIndex === 1) ?
|
||||
advancedNetworkRoutingPage.errorMode :
|
||||
(tabBar.currentIndex === 2) ?
|
||||
customNetworkRoutingPage.errorMode: false
|
||||
property bool interactive: true
|
||||
|
||||
signal networkChanged(int chainId)
|
||||
signal reCalculateSuggestedRoute(var disabledChainIds)
|
||||
signal reCalculateSuggestedRoute()
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
@ -46,9 +49,10 @@ Item {
|
|||
StatusSwitchTabButton {
|
||||
text: qsTr("Advanced")
|
||||
}
|
||||
StatusSwitchTabButton {
|
||||
text: qsTr("Custom")
|
||||
}
|
||||
// To-do Implementaion is not ready yet
|
||||
// StatusSwitchTabButton {
|
||||
// text: qsTr("Custom")
|
||||
// }
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
|
@ -71,12 +75,11 @@ Item {
|
|||
anchors.left: parent.left
|
||||
anchors.margins: Style.current.padding
|
||||
width: stackLayout.width - Style.current.bigPadding
|
||||
selectedNetwork: root.selectedNetwork
|
||||
suggestedRoutes: root.suggestedRoutes
|
||||
bestRoutes: root.bestRoutes
|
||||
amountToSend: root.amountToSend
|
||||
onNetworkChanged: {
|
||||
root.selectedNetwork = network
|
||||
root.networkChanged(network.chainId)
|
||||
isLoading: root.isLoading
|
||||
weiToEth: function(wei) {
|
||||
return "%1 %2".arg(LocaleUtils.numberToLocaleString(parseFloat(store.getWei2Eth(wei)))).arg(selectedAsset.symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,14 +94,17 @@ Item {
|
|||
anchors.left: parent.left
|
||||
anchors.margins: Style.current.padding
|
||||
store: root.store
|
||||
assets: root.assets
|
||||
selectedNetwork: root.selectedNetwork
|
||||
selectedAccount: root.selectedAccount
|
||||
amountToSend: root.amountToSend
|
||||
requiredGasInEth: root.requiredGasInEth
|
||||
selectedAsset: root.selectedAsset
|
||||
suggestedRoutes: root.suggestedRoutes
|
||||
onReCalculateSuggestedRoute: root.reCalculateSuggestedRoute(disabledChainIds)
|
||||
onReCalculateSuggestedRoute: root.reCalculateSuggestedRoute()
|
||||
bestRoutes: root.bestRoutes
|
||||
isLoading: root.isLoading
|
||||
interactive: root.interactive
|
||||
weiToEth: function(wei) {
|
||||
return parseFloat(store.getWei2Eth(wei))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,14 +119,17 @@ Item {
|
|||
anchors.margins: Style.current.padding
|
||||
customMode: true
|
||||
store: root.store
|
||||
assets: root.assets
|
||||
selectedNetwork: root.selectedNetwork
|
||||
selectedAccount: root.selectedAccount
|
||||
amountToSend: root.amountToSend
|
||||
requiredGasInEth: root.requiredGasInEth
|
||||
selectedAsset: root.selectedAsset
|
||||
suggestedRoutes: root.suggestedRoutes
|
||||
onReCalculateSuggestedRoute: root.reCalculateSuggestedRoute(disabledChainIds)
|
||||
onReCalculateSuggestedRoute: root.reCalculateSuggestedRoute()
|
||||
bestRoutes: root.bestRoutes
|
||||
isLoading: root.isLoading
|
||||
interactive: root.interactive
|
||||
weiToEth: function(wei) {
|
||||
return parseFloat(store.getWei2Eth(wei))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,25 +12,21 @@ import StatusQ.Core.Theme 0.1
|
|||
import "../controls"
|
||||
|
||||
ColumnLayout {
|
||||
id: networksAdvancedCustomView
|
||||
id: root
|
||||
|
||||
property var store
|
||||
property var assets
|
||||
property var selectedNetwork: ""
|
||||
property var selectedAccount
|
||||
property double amountToSend: 0
|
||||
property double requiredGasInEth: 0
|
||||
property bool customMode: false
|
||||
property var selectedAsset
|
||||
property var suggestedRoutes
|
||||
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
|
||||
|
||||
signal reCalculateSuggestedRoute(var disabledChainIds)
|
||||
|
||||
onSelectedNetworkChanged: {
|
||||
networksLoader.active = false
|
||||
networksLoader.active = true
|
||||
}
|
||||
signal reCalculateSuggestedRoute()
|
||||
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
|
@ -69,24 +65,32 @@ ColumnLayout {
|
|||
text: qsTr("The networks where the receipient will receive tokens. Amounts calculated automatically for the lowest cost.")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
BalanceExceeded {
|
||||
id: balanceExceeded
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: Style.current.bigPadding
|
||||
transferPossible: root.store.disabledChainIdsToList.length > 0 || root.store.disabledChainIdsFromList.length > 0 ? true : root.bestRoutes ? root.bestRoutes.length > 0 : false
|
||||
amountToSend: root.amountToSend
|
||||
isLoading: root.isLoading
|
||||
}
|
||||
Loader {
|
||||
id: networksLoader
|
||||
Layout.topMargin: Style.current.padding
|
||||
active: false
|
||||
active: !balanceExceeded.visible
|
||||
visible: active
|
||||
sourceComponent: NetworkCardsComponent {
|
||||
store: networksAdvancedCustomView.store
|
||||
selectedNetwork: networksAdvancedCustomView.selectedNetwork
|
||||
selectedAccount: networksAdvancedCustomView.selectedAccount
|
||||
allNetworks: networksAdvancedCustomView.store.allNetworks
|
||||
amountToSend: networksAdvancedCustomView.amountToSend
|
||||
customMode: networksAdvancedCustomView.customMode
|
||||
requiredGasInEth: networksAdvancedCustomView.requiredGasInEth
|
||||
assets: networksAdvancedCustomView.assets
|
||||
selectedAsset: networksAdvancedCustomView.selectedAsset
|
||||
locale: networksAdvancedCustomView.store.locale
|
||||
suggestedRoutes: networksAdvancedCustomView.suggestedRoutes
|
||||
onReCalculateSuggestedRoute: networksAdvancedCustomView.reCalculateSuggestedRoute(disabled)
|
||||
store: root.store
|
||||
selectedAccount: root.selectedAccount
|
||||
allNetworks: root.store.allNetworks
|
||||
amountToSend: root.amountToSend
|
||||
customMode: root.customMode
|
||||
requiredGasInEth: root.requiredGasInEth
|
||||
selectedAsset: root.selectedAsset
|
||||
onReCalculateSuggestedRoute: root.reCalculateSuggestedRoute()
|
||||
bestRoutes: root.bestRoutes
|
||||
weiToEth: root.weiToEth
|
||||
interactive: root.interactive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,13 +13,12 @@ import StatusQ.Core.Theme 0.1
|
|||
import "../controls"
|
||||
|
||||
RowLayout {
|
||||
id: networksSimpleRoutingView
|
||||
id: root
|
||||
|
||||
property var selectedNetwork
|
||||
property var suggestedRoutes
|
||||
property var bestRoutes
|
||||
property double amountToSend: 0
|
||||
|
||||
signal networkChanged(var network)
|
||||
property bool isLoading: false
|
||||
property var weiToEth: function(wei) {}
|
||||
|
||||
spacing: 10
|
||||
|
||||
|
@ -30,7 +29,7 @@ RowLayout {
|
|||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.preferredWidth: networksSimpleRoutingView.width
|
||||
Layout.preferredWidth: root.width
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: 410
|
||||
font.pixelSize: 15
|
||||
|
@ -43,16 +42,16 @@ RowLayout {
|
|||
Layout.maximumWidth: 410
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
text: qsTr("Choose a network to use for the transaction")
|
||||
text: qsTr("The networks where the receipient will receive tokens. Amounts calculated automatically for the lowest cost.")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
BalanceExceeded {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: Style.current.bigPadding
|
||||
visible: !transferPossible
|
||||
transferPossible: networksSimpleRoutingView.suggestedRoutes ? networksSimpleRoutingView.suggestedRoutes.length > 0 : false
|
||||
amountToSend: networksSimpleRoutingView.amountToSend
|
||||
transferPossible: root.bestRoutes !== undefined ? root.bestRoutes.length > 0 : true
|
||||
amountToSend: root.amountToSend
|
||||
isLoading: root.isLoading
|
||||
}
|
||||
ScrollView {
|
||||
Layout.fillWidth: true
|
||||
|
@ -63,30 +62,28 @@ RowLayout {
|
|||
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
||||
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
|
||||
clip: true
|
||||
visible: networksSimpleRoutingView.suggestedRoutes ? networksSimpleRoutingView.suggestedRoutes.length > 0 : false
|
||||
visible: !root.isLoading ? root.bestRoutes !== undefined ? root.bestRoutes.length > 0 : true : false
|
||||
Row {
|
||||
id: row
|
||||
spacing: Style.current.padding
|
||||
Repeater {
|
||||
id: repeater
|
||||
objectName: "networksList"
|
||||
model: networksSimpleRoutingView.suggestedRoutes
|
||||
model: root.bestRoutes
|
||||
StatusListItem {
|
||||
id: item
|
||||
objectName: modelData.chainName
|
||||
objectName: modelData.toNetwork.chainName
|
||||
leftPadding: 5
|
||||
rightPadding: 5
|
||||
implicitWidth: 126
|
||||
title: modelData.chainName
|
||||
subTitle: ""
|
||||
implicitWidth: 150
|
||||
title: modelData.toNetwork.chainName
|
||||
subTitle: root.weiToEth(modelData.amountIn)
|
||||
statusListItemSubTitle.color: Theme.palette.primaryColor1
|
||||
asset.width: 32
|
||||
asset.height: 32
|
||||
asset.name: Style.png("networks/" + modelData.chainName.toLowerCase())
|
||||
asset.name: Style.svg("tiny/" + modelData.toNetwork.iconUrl)
|
||||
asset.isImage: true
|
||||
color: "transparent"
|
||||
border.color: Style.current.primary
|
||||
border.width: networksSimpleRoutingView.selectedNetwork !== undefined ? networksSimpleRoutingView.selectedNetwork.chainId === modelData.chainId ? 1 : 0 : 0
|
||||
onClicked: networksSimpleRoutingView.networkChanged(modelData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,17 +13,12 @@ import StatusQ.Core.Theme 0.1
|
|||
Rectangle {
|
||||
id: footer
|
||||
|
||||
property string maxFiatFees: ""
|
||||
property int estimatedTxTimeFlag: Constants.transactionEstimatedTime.unknown
|
||||
property string maxFiatFees: "..."
|
||||
property alias selectedTimeEstimate: estimatedTime.text
|
||||
property bool pending: true
|
||||
property bool isLastGroup: false
|
||||
|
||||
signal nextButtonClicked()
|
||||
|
||||
onEstimatedTxTimeFlagChanged: {
|
||||
estimatedTime.text = Utils.getLabelForEstimatedTxTime(estimatedTxTimeFlag)
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
height: 82
|
||||
radius: 8
|
||||
|
@ -85,7 +80,6 @@ Rectangle {
|
|||
}
|
||||
|
||||
StatusFlatButton {
|
||||
icon.name: isLastGroup ? "" : "password"
|
||||
text: qsTr("Send")
|
||||
objectName: "sendModalFooterSendButton"
|
||||
size: StatusBaseButton.Size.Large
|
||||
|
|
|
@ -153,7 +153,7 @@ Item {
|
|||
objectName: model.name
|
||||
height: visible ? 64 : 0
|
||||
title: !!model.name ? model.name : ""
|
||||
subTitle: Utils.toLocaleString(model.currencyBalance.toFixed(2), store.locale, {"model.currency": true}) + " " + store.currentCurrency.toUpperCase()
|
||||
subTitle: "%1 %2".arg(LocaleUtils.numberToLocaleString(model.currencyBalance)).arg(store.currentCurrency.toUpperCase())
|
||||
asset.emoji: !!model.emoji ? model.emoji: ""
|
||||
asset.color: model.color
|
||||
asset.name: !model.emoji ? "filled-account": ""
|
||||
|
|
|
@ -430,14 +430,6 @@ QtObject {
|
|||
readonly property int success: 1
|
||||
}
|
||||
|
||||
readonly property QtObject transactionEstimatedTime: QtObject {
|
||||
readonly property int unknown: 0
|
||||
readonly property int lessThanOneMin: 1
|
||||
readonly property int lessThanThreeMins: 2
|
||||
readonly property int lessThanFiveMins: 3
|
||||
readonly property int moreThanFiveMins: 4
|
||||
}
|
||||
|
||||
readonly property QtObject translationsState: QtObject {
|
||||
readonly property int alpha: 0
|
||||
readonly property int beta: 1
|
||||
|
@ -669,4 +661,12 @@ QtObject {
|
|||
Failure = 0,
|
||||
Success = 1
|
||||
}
|
||||
|
||||
enum SendType {
|
||||
Transfer,
|
||||
ENSRegister,
|
||||
ENSRelease,
|
||||
ENSSetPubKey,
|
||||
StickersBuy
|
||||
}
|
||||
}
|
||||
|
|
|
@ -527,24 +527,6 @@ QtObject {
|
|||
|
||||
/* Validation section end */
|
||||
|
||||
function getLabelForEstimatedTxTime(estimatedFlag) {
|
||||
if (estimatedFlag === Constants.transactionEstimatedTime.unknown) {
|
||||
return qsTr("Unknown")
|
||||
}
|
||||
|
||||
if (estimatedFlag === Constants.transactionEstimatedTime.lessThanOneMin) {
|
||||
return qsTr("< 1 min")
|
||||
}
|
||||
if (estimatedFlag === Constants.transactionEstimatedTime.lessThanThreeMins) {
|
||||
return qsTr("< 3 mins")
|
||||
}
|
||||
if (estimatedFlag === Constants.transactionEstimatedTime.lessThanFiveMins) {
|
||||
return qsTr("< 5 mins")
|
||||
}
|
||||
|
||||
return qsTr("> 5 mins")
|
||||
}
|
||||
|
||||
function getContactDetailsAsJson(publicKey, getVerificationRequest=true) {
|
||||
let jsonObj = mainModuleInst.getContactDetailsAsJson(publicKey, getVerificationRequest)
|
||||
try {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7eb66d09e7ff1ad3bac24d7049681f7fbb6b7905
|
||||
Subproject commit 993c236c04517deb636e6551dfd553f427ffcce7
|
Loading…
Reference in New Issue