feat(@wallet): multi transaction simple view

This commit is contained in:
Anthony Laibe 2022-05-19 10:53:57 +02:00 committed by Anthony Laibe
parent 17cbd4512d
commit 00ed4f9c44
86 changed files with 1038 additions and 975 deletions

View File

@ -143,7 +143,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.tokenService = token_service.newService(
statusFoundation.events, statusFoundation.threadpool, result.networkService
)
result.collectibleService = collectible_service.newService(result.settingsService)
result.collectibleService = collectible_service.newService(result.networkService)
result.walletAccountService = wallet_account_service.newService(
statusFoundation.events, statusFoundation.threadpool, result.settingsService, result.accountsService,
result.tokenService, result.networkService,

View File

@ -1,4 +1,4 @@
import NimQml, Tables
import NimQml, Tables, sequtils
import ../../../../global/global_singleton
import ../../../../core/eventemitter
@ -41,7 +41,16 @@ method delete*(self: Module) =
proc setAssets(self: Module, tokens: seq[WalletTokenDto]) =
var items: seq[Item]
for t in tokens:
let item = token_item.initItem(t.name, t.symbol, t.totalBalance.balance, t.address, t.totalBalance.currencyBalance)
let item = token_item.initItem(
t.name,
t.symbol,
t.totalBalance.balance,
t.totalBalance.currencyBalance,
t.enabledNetworkBalance.balance,
t.enabledNetworkBalance.currencybalance,
t.visible,
toSeq(t.balancesPerChain.values),
)
items.add(item)
self.view.getAssetsModel().setItems(items)

View File

@ -152,9 +152,10 @@ proc newModule*[T](
result.profileSectionModule = profile_section_module.newModule(
result, events, accountsService, settingsService, stickersService,
profileService, contactsService, aboutService, languageService, privacyService, nodeConfigurationService,
devicesService, mailserversService, chatService, ensService, walletAccountService, generalService, communityService
devicesService, mailserversService, chatService, ensService, walletAccountService, generalService, communityService,
networkService,
)
result.stickersModule = stickers_module.newModule(result, events, stickersService, settingsService, walletAccountService)
result.stickersModule = stickers_module.newModule(result, events, stickersService, settingsService, walletAccountService, networkService)
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
messageService, chatService)
result.communitiesModule = communities_module.newModule(result, events, communityService, contactsService)

View File

@ -53,6 +53,9 @@ method getCurrentNetworkName*(self: AccessInterface): string {.base.} =
method getCurrentNetworkId*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method getCurrentChainId*(self: AccessInterface): int {.base.} =
raise newException(ValueError, "No implementation available")
method setCurrentNetwork*(self: AccessInterface, network: string) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -63,6 +63,9 @@ method getCurrentNetworkName*(self: Module): string =
method getCurrentNetworkId*(self: Module): string =
return self.controller.getCurrentNetworkDetails().id
method getCurrentChainId*(self: Module): int =
return self.controller.getCurrentNetworkDetails().config.NetworkId
method setCurrentNetwork*(self: Module, network: string) =
self.controller.changeCurrentNetworkTo(network)

View File

@ -44,6 +44,12 @@ QtObject:
read = getCurrentNetworkId
notify = currentNetworkChanged
proc getCurrentChainId*(self: View): int {.slot.} =
return self.delegate.getCurrentChainId()
QtProperty[int] currentChainId:
read = getCurrentChainId
notify = currentNetworkChanged
proc fleetChanged*(self: View) {.signal.}
proc getFleet*(self: View): string {.slot.} =
return self.delegate.getFleet()

View File

@ -5,6 +5,7 @@ import ../../../../global/global_singleton
import ../../../../core/eventemitter
import ../../../../../app_service/service/settings/service as settings_service
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
@ -17,17 +18,21 @@ type
events: EventEmitter
settingsService: settings_service.Service
ensService: ens_service.Service
networkService: network_service.Service
walletAccountService: wallet_account_service.Service
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter,
proc newController*(
delegate: io_interface.AccessInterface, events: EventEmitter,
settingsService: settings_service.Service, ensService: ens_service.Service,
walletAccountService: wallet_account_service.Service): Controller =
walletAccountService: wallet_account_service.Service, networkService: network_service.Service,
): Controller =
result = Controller()
result.delegate = delegate
result.events = events
result.settingsService = settingsService
result.ensService = ensService
result.walletAccountService = walletAccountService
result.networkService = networkService
proc delete*(self: Controller) =
discard
@ -41,10 +46,6 @@ proc init*(self: Controller) =
let args = EnsUsernameDetailsArgs(e)
self.delegate.onDetailsForEnsUsername(args.ensUsername, args.address, args.pubkey, args.isStatus, args.expirationTime)
self.events.on(SIGNAL_GAS_PRICE_FETCHED) do(e:Args):
let args = GasPriceArgs(e)
self.delegate.gasPriceFetched(args.gasPrice)
self.events.on(SIGNAL_ENS_TRANSACTION_CONFIRMED) do(e:Args):
let args = EnsTransactionArgs(e)
self.delegate.ensTransactionConfirmed(args.transactionType, args.ensUsername, args.transactionHash)
@ -65,15 +66,12 @@ proc getAllMyEnsUsernames*(self: Controller, includePendingEnsUsernames: bool):
proc fetchDetailsForEnsUsername*(self: Controller, ensUsername: string) =
self.ensService.fetchDetailsForEnsUsername(ensUsername)
proc fetchGasPrice*(self: Controller) =
self.ensService.fetchGasPrice()
proc setPubKeyGasEstimate*(self: Controller, ensUsername: string, address: string): int =
return self.ensService.setPubKeyGasEstimate(ensUsername, address)
proc setPubKey*(self: Controller, ensUsername: string, address: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string =
return self.ensService.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string =
return self.ensService.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
proc getCurrentNetworkDetails*(self: Controller): Network =
return self.settingsService.getCurrentNetworkDetails()
@ -107,8 +105,8 @@ proc registerEnsGasEstimate*(self: Controller, ensUsername: string, address: str
return self.ensService.registerEnsGasEstimate(ensUsername, address)
proc registerEns*(self: Controller, ensUsername: string, address: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string =
return self.ensService.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string =
return self.ensService.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
proc getSNTBalance*(self: Controller): string =
return self.ensService.getSNTBalance()
@ -131,3 +129,6 @@ proc getStatusToken*(self: Controller): string =
"address": token.addressAsString()
}
return $jsonObj
proc getChainIdForEns*(self: Controller): int =
return self.networkService.getNetworkForEns().chainId

View File

@ -22,9 +22,6 @@ method onDetailsForEnsUsername*(self: AccessInterface, ensUsername: string, addr
isStatus: bool, expirationTime: int) {.base.} =
raise newException(ValueError, "No implementation available")
method gasPriceFetched*(self: AccessInterface, gasPrice: string) {.base.} =
raise newException(ValueError, "No implementation available")
method ensTransactionConfirmed*(self: AccessInterface, trxType: string, ensUsername: string, transactionHash: string)
{.base.} =
raise newException(ValueError, "No implementation available")
@ -45,14 +42,11 @@ method numOfPendingEnsUsernames*(self: AccessInterface): int {.base.} =
method fetchDetailsForEnsUsername*(self: AccessInterface, ensUsername: string) {.base.} =
raise newException(ValueError, "No implementation available")
method fetchGasPrice*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
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): string {.base.} =
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.base.} =
raise newException(ValueError, "No implementation available")
method releaseEnsEstimate*(self: AccessInterface, ensUsername: string, address: string): int {.base.} =
@ -72,7 +66,7 @@ method registerEnsGasEstimate*(self: AccessInterface, ensUsername: string, addre
raise newException(ValueError, "No implementation available")
method registerEns*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.base.} =
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.base.} =
raise newException(ValueError, "No implementation available")
method getSNTBalance*(self: AccessInterface): string {.base.} =
@ -94,5 +88,8 @@ method getGasEthValue*(self: AccessInterface, gweiValue: string, gasLimit: strin
method getStatusToken*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method getChainIdForEns*(self: AccessInterface): int {.base.} =
raise newException(ValueError, "No implementation available")
method setPrefferedEnsUsername*(self: AccessInterface, ensUsername: string) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -8,6 +8,7 @@ import ../../../../core/eventemitter
import ../../../../../app_service/common/conversion as service_conversion
import ../../../../../app_service/service/settings/service as settings_service
import ../../../../../app_service/service/ens/service as ens_service
import ../../../../../app_service/service/network/service as network_service
import ../../../../../app_service/service/ens/utils as ens_utils
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
@ -26,14 +27,17 @@ type
controller: Controller
moduleLoaded: bool
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter,
proc newModule*(
delegate: delegate_interface.AccessInterface, events: EventEmitter,
settingsService: settings_service.Service, ensService: ens_service.Service,
walletAccountService: wallet_account_service.Service): Module =
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.view = view.newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, settingsService, ensService, walletAccountService)
result.controller = controller.newController(result, events, settingsService, ensService, walletAccountService, networkService)
result.moduleLoaded = false
method delete*(self: Module) =
@ -53,7 +57,6 @@ method isLoaded*(self: Module): bool =
return self.moduleLoaded
method viewDidLoad*(self: Module) =
self.fetchGasPrice()
# add registered ens usernames
let registeredEnsUsernames = self.controller.getAllMyEnsUsernames(includePendingEnsUsernames = false)
for u in registeredEnsUsernames:
@ -85,18 +88,12 @@ method onDetailsForEnsUsername*(self: Module, ensUsername: string, address: stri
expirationTime: int) =
self.view.setDetailsForEnsUsername(ensUsername, address, pubkey, isStatus, expirationTime)
method fetchGasPrice*(self: Module) =
self.controller.fetchGasPrice()
method gasPriceFetched*(self: Module, gasPrice: string) =
self.view.setGasPrice(gasPrice)
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): string =
let response = self.controller.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string =
let response = self.controller.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
if(response.len == 0):
info "expected response is empty", methodName="setPubKey"
return
@ -182,8 +179,8 @@ method registerEnsGasEstimate*(self: Module, ensUsername: string, address: strin
return self.controller.registerEnsGasEstimate(ensUsername, address)
method registerEns*(self: Module, ensUsername: string, address: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string =
let response = self.controller.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string =
let response = self.controller.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
let responseObj = response.parseJson
if (responseObj.kind != JObject):
@ -238,5 +235,8 @@ method getGasEthValue*(self: Module, gweiValue: string, gasLimit: string): strin
method getStatusToken*(self: Module): string =
return self.controller.getStatusToken()
method getChainIdForEns*(self: Module): int =
return self.controller.getChainIdForEns()
method setPrefferedEnsUsername*(self: Module, ensUsername: string) =
self.controller.setPreferredName(ensUsername)

View File

@ -11,7 +11,6 @@ QtObject:
modelVariant: QVariant
etherscanLink: string
signingPhrase: string
gasPrice: string
proc delete*(self: View) =
self.model.delete
@ -24,7 +23,6 @@ QtObject:
result.model = newModel()
result.modelVariant = newQVariant(result.model)
result.delegate = delegate
result.gasPrice = "0"
proc load*(self: View, link: string, signingPhrase: string) =
self.etherscanLink = link
@ -66,9 +64,6 @@ QtObject:
self.loading(false)
self.detailsObtained(ensUsername, address, pubkey, isStatus, expirationTime)
proc fetchGasPrice*(self: View) {.slot.} =
self.delegate.fetchGasPrice()
proc transactionWasSent(self: View, txResult: string) {.signal.}
proc emitTransactionWasSentSignal*(self: View, txResult: string) =
self.transactionWasSent(txResult)
@ -77,8 +72,8 @@ QtObject:
return self.delegate.setPubKeyGasEstimate(ensUsername, address)
proc setPubKey*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.slot.} =
return self.delegate.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.slot.} =
return self.delegate.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
proc getEtherscanLink*(self: View): string {.slot.} =
return self.etherscanLink
@ -86,17 +81,6 @@ QtObject:
proc getSigningPhrase*(self: View): string {.slot.} =
return self.signingPhrase
proc gasPriceChanged(self: View) {.signal.}
proc getGasPrice(self: View): string {.slot.} =
return self.gasPrice
QtProperty[string] gasPrice:
read = getGasPrice
notify = gasPriceChanged
proc setGasPrice*(self: View, gasPrice: string) = # this is not a slot
self.gasPrice = gasPrice
self.gasPriceChanged()
proc usernameConfirmed(self: View, username: string) {.signal.}
proc emitUsernameConfirmedSignal*(self: View, ensUsername: string) =
self.usernameConfirmed(ensUsername)
@ -124,8 +108,8 @@ QtObject:
return self.delegate.registerEnsGasEstimate(ensUsername, address)
proc registerEns*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.slot.} =
return self.delegate.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): string {.slot.} =
return self.delegate.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
proc getSNTBalance*(self: View): string {.slot.} =
return self.delegate.getSNTBalance()
@ -145,5 +129,8 @@ QtObject:
proc getStatusToken*(self: View): string {.slot.} =
return self.delegate.getStatusToken()
proc getChainIdForEns*(self: View): int {.slot.} =
return self.delegate.getChainIdForEns()
proc setPrefferedEnsUsername*(self: View, ensUsername: string) {.slot.} =
self.delegate.setPrefferedEnsUsername(ensUsername)

View File

@ -16,6 +16,7 @@ import ../../../../app_service/service/mailservers/service as mailservers_servic
import ../../../../app_service/service/chat/service as chat_service
import ../../../../app_service/service/stickers/service as stickersService
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/general/service as general_service
import ../../../../app_service/service/community/service as community_service
@ -72,7 +73,8 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
ensService: ens_service.Service,
walletAccountService: wallet_account_service.Service,
generalService: general_service.Service,
communityService: community_service.Service
communityService: community_service.Service,
networkService: network_service.Service,
): Module =
result = Module()
result.delegate = delegate
@ -91,7 +93,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
result.syncModule = sync_module.newModule(result, events, settingsService, mailserversService)
result.notificationsModule = notifications_module.newModule(result, events, settingsService, chatService, contactsService)
result.ensUsernamesModule = ens_usernames_module.newModule(
result, events, settingsService, ensService, walletAccountService
result, events, settingsService, ensService, walletAccountService, networkService
)
result.communitiesModule = communities_module.newModule(result, communityService)

View File

@ -7,6 +7,7 @@ import ../../../../app_service/service/node/service as node_service
import ../../../../app_service/service/stickers/service as stickers_service
import ../../../../app_service/service/token/service
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
@ -17,6 +18,7 @@ type
events: EventEmitter
stickerService: stickers_service.Service
settingsService: settings_service.Service
networkService: network_service.Service
walletAccountService: wallet_account_service.Service
disconnected: bool
@ -29,13 +31,15 @@ proc newController*(
events: EventEmitter,
stickerService: stickers_service.Service,
settingsService: settings_service.Service,
walletAccountService: wallet_account_service.Service
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
): Controller =
result = Controller()
result.delegate = delegate
result.events = events
result.stickerService = stickerService
result.settingsService = settingsService
result.networkService = networkService
result.walletAccountService = walletAccountService
result.disconnected = false
@ -76,10 +80,6 @@ proc init*(self: Controller) =
self.events.on(SIGNAL_ALL_STICKER_PACKS_LOADED) do(e: Args):
self.delegate.allPacksLoaded()
self.events.on(SIGNAL_GAS_PRICE_FETCHED) do(e:Args):
let args = GasPriceArgs(e)
self.delegate.gasPriceFetched(args.gasPrice)
self.events.on(SIGNAL_STICKER_GAS_ESTIMATED) do(e: Args):
let args = StickerGasEstimatedArgs(e)
self.delegate.gasEstimateReturned(args.estimate, args.uuid)
@ -92,8 +92,8 @@ proc init*(self: Controller) =
let args = StickerTransactionArgs(e)
self.delegate.stickerTransactionReverted(args.transactionType, args.packID, args.transactionHash, args.revertReason)
proc buy*(self: Controller, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): tuple[response: string, success: bool] =
self.stickerService.buy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, 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)
proc estimate*(self: Controller, packId: string, address: string, price: string, uuid: string) =
self.stickerService.estimate(packId, address, price, uuid)
@ -148,6 +148,9 @@ proc getCurrentCurrency*(self: Controller): string =
proc getPrice*(self: Controller, crypto: string, fiat: string): float64 =
return self.walletAccountService.getPrice(crypto, fiat)
proc getChainIdForStickers*(self: Controller): int =
return self.networkService.getNetworkForStickers().chainId
proc getStatusToken*(self: Controller): string =
let token = self.stickerService.getStatusToken()
@ -156,7 +159,4 @@ proc getStatusToken*(self: Controller): string =
"symbol": token.symbol,
"address": token.addressAsString()
}
return $jsonObj
proc fetchGasPrice*(self: Controller) =
self.stickerService.fetchGasPrice()
return $jsonObj

View File

@ -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): tuple[response: string, success: bool] {.base.} =
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.} =
raise newException(ValueError, "No implementation available")
method getInstalledStickerPacks*(self: AccessInterface): Table[string, StickerPackDto] {.base.} =
@ -89,10 +89,7 @@ method getGasEthValue*(self: AccessInterface, gweiValue: string, gasLimit: strin
method getStatusToken*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method fetchGasPrice*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method gasPriceFetched*(self: AccessInterface, gasPrice: string) {.base.} =
method getChainIdForStickers*(self: AccessInterface): int {.base.} =
raise newException(ValueError, "No implementation available")
method stickerTransactionConfirmed*(self: AccessInterface, trxType: string, packID: string, transactionHash: string) {.base.} =

View File

@ -5,6 +5,7 @@ import ../../../global/global_singleton
import ../../../core/eventemitter
import ../../../../app_service/service/stickers/service as stickers_service
import ../../../../app_service/service/settings/service as settings_service
import ../../../../app_service/service/network/service as network_service
import ../../../../app_service/common/conversion as service_conversion
import ../../../../app_service/service/wallet_account/service as wallet_account_service
@ -19,17 +20,18 @@ type
moduleLoaded: bool
proc newModule*(
delegate: delegate_interface.AccessInterface,
events: EventEmitter,
stickersService: stickers_service.Service,
settingsService: settings_Service.Service,
walletAccountService: wallet_account_service.Service
): Module =
delegate: delegate_interface.AccessInterface,
events: EventEmitter,
stickersService: stickers_service.Service,
settingsService: settings_Service.Service,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.view = newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, stickersService, settingsService, walletAccountService)
result.controller = controller.newController(result, events, stickersService, settingsService, walletAccountService, networkService)
result.moduleLoaded = false
singletonInstance.engine.setRootContextProperty("stickersModule", result.viewVariant)
@ -50,8 +52,8 @@ 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): tuple[response: string, success: bool] =
return self.controller.buy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
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 getInstalledStickerPacks*(self: Module): Table[string, StickerPackDto] =
self.controller.getInstalledStickerPacks()
@ -167,11 +169,8 @@ method getGasEthValue*(self: Module, gweiValue: string, gasLimit: string): strin
method getStatusToken*(self: Module): string =
return self.controller.getStatusToken()
method fetchGasPrice*(self: Module) =
self.controller.fetchGasPrice()
method gasPriceFetched*(self: Module, gasPrice: string) =
self.view.setGasPrice(gasPrice)
method getChainIdForStickers*(self: Module): int =
return self.controller.getChainIdForStickers()
method stickerTransactionConfirmed*(self: Module, trxType: string, packID: string, transactionHash: string) =
self.view.stickerPacks.updateStickerPackInList(packID, true, false)

View File

@ -13,7 +13,6 @@ QtObject:
recentStickers*: StickerList
signingPhrase: string
stickersMarketAddress: string
gasPrice: string
proc delete*(self: View) =
self.QObject.delete
@ -28,7 +27,6 @@ QtObject:
proc load*(self: View, signingPhrase: string, stickersMarketAddress: string) =
self.signingPhrase = signingPhrase
self.stickersMarketAddress = stickersMarketAddress
self.gasPrice = "0"
self.delegate.viewDidLoad()
proc addStickerPackToList*(self: View, stickerPack: PackItem, isInstalled, isBought, isPending: bool) =
@ -63,8 +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): string {.slot.} =
let responseTuple = self.delegate.buy(packId, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
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:
@ -139,6 +137,9 @@ QtObject:
proc getSNTBalance*(self: View): string {.slot.} =
return self.delegate.getSNTBalance()
proc getChainIdForStickers*(self: View): int {.slot.} =
return self.delegate.getChainIdForStickers()
proc getWalletDefaultAddress*(self: View): string {.slot.} =
return self.delegate.getWalletDefaultAddress()
@ -154,21 +155,6 @@ QtObject:
proc getStatusToken*(self: View): string {.slot.} =
return self.delegate.getStatusToken()
proc fetchGasPrice*(self: View) {.slot.} =
self.delegate.fetchGasPrice()
proc gasPriceChanged(self: View) {.signal.}
proc getGasPrice(self: View): string {.slot.} =
return self.gasPrice
QtProperty[string] gasPrice:
read = getGasPrice
notify = gasPriceChanged
proc setGasPrice*(self: View, gasPrice: string) = # this is not a slot
self.gasPrice = gasPrice
self.gasPriceChanged()
proc transactionCompleted(self: View, success: bool, txHash: string, packID: string, trxType: string,
revertReason: string) {.signal.}
proc emitTransactionCompletedSignal*(self: View, success: bool, txHash: string, packID: string, trxType: string,

View File

@ -1,4 +1,4 @@
import NimQml, sequtils, sugar
import tables, NimQml, sequtils, sugar
import ./io_interface, ./view, ./item, ./controller
import ../io_interface as delegate_interface
@ -47,8 +47,11 @@ method refreshWalletAccounts*(self: Module) =
t.name,
t.symbol,
t.totalBalance.balance,
t.address,
t.totalBalance.currencyBalance,
t.enabledNetworkBalance.balance,
t.enabledNetworkBalance.currencyBalance,
t.visible,
toSeq(t.balancesPerChain.values),
))
)

View File

@ -43,8 +43,5 @@ proc getCurrencyBalance*(self: Controller): float64 =
proc updateCurrency*(self: Controller, currency: string) =
self.walletAccountService.updateCurrency(currency)
proc isEIP1559Enabled*(self: Controller): bool =
return self.networkService.isEIP1559Enabled()
proc getIndex*(self: Controller, address: string): int =
return self.walletAccountService.getIndex(address)

View File

@ -1,4 +1,4 @@
import NimQml, Tables
import NimQml, Tables, sequtils
import ../../../../global/global_singleton
import ../../../../core/eventemitter
@ -72,9 +72,18 @@ proc setAssetsAndBalance(self: Module, tokens: seq[WalletTokenDto]) =
var totalCurrencyBalanceForAllAssets = 0.0
var items: seq[Item]
for t in tokens:
let item = token_item.initItem(t.name, t.symbol, t.totalBalance.balance, t.address, t.totalBalance.currencyBalance)
let item = token_item.initItem(
t.name,
t.symbol,
t.totalBalance.balance,
t.totalBalance.currencyBalance,
t.enabledNetworkBalance.balance,
t.enabledNetworkBalance.currencybalance,
t.visible,
toSeq(t.balancesPerChain.values),
)
items.add(item)
totalCurrencyBalanceForAllAssets += t.totalBalance.currencyBalance
totalCurrencyBalanceForAllAssets += t.enabledNetworkBalance.currencybalance
self.view.getAssetsModel().setItems(items)
self.view.setCurrencyBalance(totalCurrencyBalanceForAllAssets)

View File

@ -48,8 +48,5 @@ method transactionsModuleDidLoad*(self: AccessInterface) {.base.} =
method savedAddressesModuleDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method isEIP1559Enabled*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method buySellCryptoModuleDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -63,7 +63,7 @@ proc newModule*(
result.allTokensModule = all_tokens_module.newModule(result, events, tokenService, walletAccountService)
result.collectiblesModule = collectibles_module.newModule(result, events, collectibleService, walletAccountService)
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService)
result.transactionsModule = transactions_module.newModule(result, events, transactionService, walletAccountService)
result.transactionsModule = transactions_module.newModule(result, events, transactionService, walletAccountService, networkService)
result.savedAddressesModule = saved_addresses_module.newModule(result, events, savedAddressService)
result.buySellCryptoModule = buy_sell_crypto_module.newModule(result, events, transactionService)
@ -93,9 +93,6 @@ method switchAccountByAddress*(self: Module, address: string) =
method setTotalCurrencyBalance*(self: Module) =
self.view.setTotalCurrencyBalance(self.controller.getCurrencyBalance())
method isEIP1559Enabled*(self: Module): bool =
return self.controller.isEIP1559Enabled()
method load*(self: Module) =
singletonInstance.engine.setRootContextProperty("walletSection", newQVariant(self.view))

View File

@ -1,6 +1,7 @@
import NimQml, json, json_serialization, stint, tables, sugar, sequtils
import io_interface
import ../../../../../app_service/service/transaction/service as transaction_service
import ../../../../../app_service/service/network/service as network_service
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../core/[main]
@ -11,6 +12,7 @@ type
delegate: io_interface.AccessInterface
events: EventEmitter
transactionService: transaction_service.Service
networkService: network_service.Service
walletAccountService: wallet_account_service.Service
# Forward declaration
@ -21,13 +23,15 @@ proc newController*(
delegate: io_interface.AccessInterface,
events: EventEmitter,
transactionService: transaction_service.Service,
walletAccountService: wallet_account_service.Service
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
): Controller =
result = Controller()
result.events = events
result.delegate = delegate
result.transactionService = transactionService
result.walletAccountService = walletAccountService
result.networkService = networkService
proc delete*(self: Controller) =
discard
@ -79,22 +83,26 @@ proc getAccountByAddress*(self: Controller, address: string): WalletAccountDto =
proc loadTransactions*(self: Controller, address: string, toBlock: Uint256, limit: int = 20, loadMore: bool = false) =
self.transactionService.loadTransactions(address, toBlock, limit, loadMore)
proc estimateGas*(self: Controller, from_addr: string, to: string, assetAddress: string, value: string, data: string): string =
result = self.transactionService.estimateGas(from_addr, to, assetAddress, value, data)
proc estimateGas*(self: Controller, from_addr: string, to: string, assetSymbol: string, value: string, data: string): string =
result = self.transactionService.estimateGas(from_addr, to, assetSymbol, value, data)
proc transferEth*(self: Controller, from_addr: string, to_addr: string, value: string,
gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string,
password: string, uuid: string): bool =
result = self.transactionService.transferEth(from_addr, to_addr, value, gas, gasPrice,
maxPriorityFeePerGas, maxFeePerGas, password, uuid)
proc transferTokens*(self: Controller, from_addr: string, to_addr: string, contractAddress: string,
proc transfer*(self: Controller, from_addr: string, to_addr: string, tokenSymbol: string,
value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,maxFeePerGas: string,
password: string, uuid: string
password: string, chainId: string, uuid: string, eip1559Enabled: bool,
): bool =
result = self.transactionService.transferTokens(from_addr, to_addr, contractAddress, value, gas,
gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, uuid)
result = self.transactionService.transfer(from_addr, to_addr, tokenSymbol, value, gas,
gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, chainId, uuid, eip1559Enabled)
proc suggestedFees*(self: Controller): string =
let suggestedFees = self.transactionService.suggestedFees()
return suggestedFees.toJson()
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): string =
let suggestedRoutes = self.transactionService.suggestedRoutes(account, amount, token)
return suggestedRoutes.toJson()
proc getChainIdForChat*(self: Controller): int =
return self.networkService.getNetworkForChat().chainId
proc getChainIdForBrowser*(self: Controller): int =
return self.networkService.getNetworkForBrowser().chainId

View File

@ -40,24 +40,28 @@ method setHistoryFetchState*(self: AccessInterface, addresses: seq[string], isFe
method setIsNonArchivalNode*(self: AccessInterface, isNonArchivalNode: bool) {.base.} =
raise newException(ValueError, "No implementation available")
method estimateGas*(self: AccessInterface, from_addr: string, to: string, assetAddress: string, value: string, data: string): string {.base.} =
method estimateGas*(self: AccessInterface, from_addr: string, to: string, assetSymbol: string, value: string, data: string): string {.base.} =
raise newException(ValueError, "No implementation available")
method transferEth*(self: AccessInterface, from_addr: string, to_addr: string, value: string,
gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string,
password: string, uuid: string): bool {.base.} =
raise newException(ValueError, "No implementation available")
method transferTokens*(self: AccessInterface, from_addr: string, to_addr: string,
contractAddress: string, value: string, gas: string, gasPrice: string,
method transfer*(self: AccessInterface, from_addr: string, to_addr: string,
tokenSymbol: string, value: string, gas: string, gasPrice: string,
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string,
uuid: string): bool {.base.} =
chainId: string, uuid: string, eip1559Enabled: bool): bool {.base.} =
raise newException(ValueError, "No implementation available")
method transactionWasSent*(self: AccessInterface, result: string) {.base.} =
raise newException(ValueError, "No implementation available")
method suggestedFees*(self: AccessInterface): 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): string {.base.} =
raise newException(ValueError, "No implementation available")
method getChainIdForChat*(self: AccessInterface): int =
raise newException(ValueError, "No implementation available")
method getChainIdForBrowser*(self: AccessInterface): int =
raise newException(ValueError, "No implementation available")
# View Delegate Interface

View File

@ -6,6 +6,7 @@ import ../../../../global/global_singleton
import ../../../../core/eventemitter
import ../../../../../app_service/service/transaction/service as transaction_service
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../app_service/service/network/service as network_service
export io_interface
@ -25,12 +26,13 @@ proc newModule*(
delegate: delegate_interface.AccessInterface,
events: EventEmitter,
transactionService: transaction_service.Service,
walletAccountService: wallet_account_service.Service
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.view = newView(result)
result.controller = controller.newController(result, events, transactionService, walletAccountService)
result.controller = controller.newController(result, events, transactionService, walletAccountService, networkService)
result.moduleLoaded = false
method delete*(self: Module) =
@ -82,26 +84,29 @@ method setTrxHistoryResult*(self: Module, transactions: seq[TransactionDto], add
method setHistoryFetchState*(self: Module, addresses: seq[string], isFetching: bool) =
self.view.setHistoryFetchStateForAccounts(addresses, isFetching)
method estimateGas*(self: Module, from_addr: string, to: string, assetAddress: string, value: string, data: string): string =
result = self.controller.estimateGas(from_addr, to, assetAddress, value, data)
method estimateGas*(self: Module, from_addr: string, to: string, assetSymbol: string, value: string, data: string): string =
result = self.controller.estimateGas(from_addr, to, assetSymbol, value, data)
method setIsNonArchivalNode*(self: Module, isNonArchivalNode: bool) =
self.view.setIsNonArchivalNode(isNonArchivalNode)
method transferEth*(self: Module, from_addr: string, to_addr: string, value: string, gas: string,
gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string,
uuid: string): bool =
result = self.controller.transferEth(from_addr, to_addr, value, gas, gasPrice,
maxPriorityFeePerGas, maxFeePerGas, password, uuid)
method transferTokens*(self: Module, from_addr: string, to_addr: string, contractAddress: string,
method transfer*(self: Module, from_addr: string, to_addr: string, tokenSymbol: string,
value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,
maxFeePerGas: string, password: string, uuid: string): bool =
result = self.controller.transferTokens(from_addr, to_addr, contractAddress, value, gas, gasPrice,
maxPriorityFeePerGas, maxFeePerGas, password, uuid)
maxFeePerGas: string, password: string, chainId: string, uuid: string, eip1559Enabled: bool): bool =
result = self.controller.transfer(from_addr, to_addr, tokenSymbol, value, gas, gasPrice,
maxPriorityFeePerGas, maxFeePerGas, password, chainId, uuid, eip1559Enabled)
method transactionWasSent*(self: Module, result: string) =
self.view.transactionWasSent(result)
method suggestedFees*(self: Module): string =
return self.controller.suggestedFees()
method suggestedFees*(self: Module, chainId: int): string =
return self.controller.suggestedFees(chainId)
method suggestedRoutes*(self: Module, account: string, amount: float64, token: string): string =
return self.controller.suggestedRoutes(account, amount, token)
method getChainIdForChat*(self: Module): int =
return self.controller.getChainIdForChat()
method getChainIdForBrowser*(self: Module): int =
return self.controller.getChainIdForBrowser()

View File

@ -1,4 +1,4 @@
import NimQml, tables, stint, json, strformat, sequtils
import NimQml, tables, stint, json, strformat, sequtils, strutils
import ./item
import ./model
@ -108,25 +108,35 @@ QtObject:
read = getIsNonArchivalNode
notify = isNonArchivalNodeChanged
proc estimateGas*(self: View, from_addr: string, to: string, assetAddress: string, value: string, data: string): string {.slot.} =
result = self.delegate.estimateGas(from_addr, to, assetAddress, value, data)
proc estimateGas*(self: View, from_addr: string, to: string, assetSymbol: string, value: string, data: string): string {.slot.} =
result = self.delegate.estimateGas(from_addr, to, assetSymbol, value, data)
proc transactionSent*(self: View, txResult: string) {.signal.}
proc transactionWasSent*(self: View,txResult: string) {.slot} =
self.transactionSent(txResult)
proc transferEth*(self: View, from_addr: string, to_addr: string, value: string, gas: string,
gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string,
uuid: string): bool {.slot.} =
result = self.delegate.transferEth(from_addr, to_addr, value, gas, gasPrice,
maxPriorityFeePerGas, maxFeePerGas, password, uuid)
proc transferTokens*(self: View, from_addr: string, to_addr: string, contractAddress: string,
proc transfer*(self: View, from_addr: string, to_addr: string, tokenSymbol: string,
value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string,
maxFeePerGas: string, password: string, uuid: string): bool {.slot.} =
result = self.delegate.transferTokens(from_addr, to_addr, contractAddress, value, gas, gasPrice,
maxPriorityFeePerGas, maxFeePerGas, password, uuid)
maxFeePerGas: string, password: string, chainId: string, uuid: string, eip1559Enabled: bool): bool {.slot.} =
result = self.delegate.transfer(from_addr, to_addr, tokenSymbol, value, gas, gasPrice,
maxPriorityFeePerGas, maxFeePerGas, password, chainId, uuid, eip1559Enabled)
proc suggestedFees*(self: View): string {.slot.} =
return self.delegate.suggestedFees()
proc suggestedFees*(self: View, chainId: int): string {.slot.} =
return self.delegate.suggestedFees(chainId)
proc suggestedRoutes*(self: View, account: string, amount: string, token: string): string {.slot.} =
var parsedAmount = 0.0
try:
parsedAmount = parsefloat(amount)
except:
discard
return self.delegate.suggestedRoutes(account, parsedAmount, token)
proc getChainIdForChat*(self: View): int {.slot.} =
return self.delegate.getChainIdForChat()
proc getChainIdForBrowser*(self: View): int {.slot.} =
return self.delegate.getChainIdForBrowser()

View File

@ -74,7 +74,4 @@ QtObject:
self.currentCurrency = currency
self.signingPhrase = signingPhrase
self.isMnemonicBackedUp = mnemonicBackedUp
self.currentCurrencyChanged()
proc isEIP1559Enabled*(self: View): QVariant {.slot.} =
return newQVariant(self.delegate.isEIP1559Enabled())
self.currentCurrencyChanged()

View File

@ -0,0 +1,86 @@
import NimQml, Tables, strutils, strformat
import ../../../app_service/service/wallet_account/dto
type
ModelRole {.pure.} = enum
ChainId = UserRole + 1,
Address
Balance
CurrencyBalance
QtObject:
type
BalanceModel* = ref object of QAbstractListModel
items*: seq[BalanceDto]
proc delete(self: BalanceModel) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: BalanceModel) =
self.QAbstractListModel.setup
proc newModel*(): BalanceModel =
new(result, delete)
result.setup
proc `$`*(self: BalanceModel): string =
for i in 0 ..< self.items.len:
result &= fmt"""[{i}]:({$self.items[i]})"""
proc countChanged(self: BalanceModel) {.signal.}
proc getCount*(self: BalanceModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
method rowCount(self: BalanceModel, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: BalanceModel): Table[int, string] =
{
ModelRole.ChainId.int:"chainId",
ModelRole.Address.int:"address",
ModelRole.Balance.int:"balance",
ModelRole.CurrencyBalance.int:"currencyBalance",
}.toTable
method data(self: BalanceModel, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.ChainId:
result = newQVariant(item.chainId)
of ModelRole.Address:
result = newQVariant(item.address)
of ModelRole.Balance:
result = newQVariant(item.balance)
of ModelRole.CurrencyBalance:
result = newQVariant(item.currencyBalance)
proc rowData(self: BalanceModel, index: int, column: string): string {.slot.} =
if (index >= self.items.len):
return
let item = self.items[index]
case column:
of "chainId": result = $item.chainId
of "address": result = $item.address
of "balance": result = $item.balance
of "currencyBalance": result = $item.currencyBalance
proc setItems*(self: BalanceModel, items: seq[BalanceDto]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()

View File

@ -1,27 +1,47 @@
import strformat
import ../../../app_service/service/wallet_account/dto
import ./balance_model as balance_model
type
Item* = object
name: string
symbol: string
balance: float
address: string
currencyBalance: float
totalBalance: float
totalCurrencyBalance: float
enabledNetworkCurrencyBalance: float
enabledNetworkBalance: float
networkVisible: bool
balances: balance_model.BalanceModel
proc initItem*(name, symbol: string, balance: float, address: string, currencyBalance: float): Item =
proc initItem*(
name, symbol: string,
totalBalance: float,
totalCurrencyBalance: float,
enabledNetworkBalance: float,
enabledNetworkCurrencyBalance: float,
networkVisible: bool,
balances: seq[BalanceDto]
): Item =
result.name = name
result.symbol = symbol
result.balance = balance
result.address = address
result.currencyBalance = currencyBalance
result.totalBalance = totalBalance
result.totalCurrencyBalance = totalCurrencyBalance
result.enabledNetworkBalance = enabledNetworkBalance
result.enabledNetworkCurrencyBalance = enabledNetworkCurrencyBalance
result.networkVisible = networkVisible
result.balances = balance_model.newModel()
result.balances.setItems(balances)
proc `$`*(self: Item): string =
result = fmt"""AllTokensItem(
name: {self.name},
symbol: {self.symbol},
balance: {self.balance},
address: {self.address},
currencyBalance: {self.currencyBalance},
totalBalance: {self.totalBalance},
totalCurrencyBalance: {self.totalCurrencyBalance},
enabledNetworkBalance: {self.enabledNetworkBalance},
enabledNetworkCurrencyBalance: {self.enabledNetworkCurrencyBalance},
networkVisible: {self.networkVisible},
]"""
proc getName*(self: Item): string =
@ -30,11 +50,20 @@ proc getName*(self: Item): string =
proc getSymbol*(self: Item): string =
return self.symbol
proc getBalance*(self: Item): float =
return self.balance
proc getTotalBalance*(self: Item): float =
return self.totalBalance
proc getAddress*(self: Item): string =
return self.address
proc getTotalCurrencyBalance*(self: Item): float =
return self.totalCurrencyBalance
proc getCurrencyBalance*(self: Item): float =
return self.currencyBalance
proc getEnabledNetworkBalance*(self: Item): float =
return self.enabledNetworkBalance
proc getEnabledNetworkCurrencyBalance*(self: Item): float =
return self.enabledNetworkCurrencyBalance
proc getNetworkVisible*(self: Item): bool =
return self.networkVisible
proc getBalances*(self: Item): balance_model.BalanceModel =
return self.balances

View File

@ -6,9 +6,12 @@ type
ModelRole {.pure.} = enum
Name = UserRole + 1,
Symbol
Balance
Address
CurrencyBalance
TotalBalance
TotalCurrencyBalance
EnabledNetworkCurrencyBalance
EnabledNetworkBalance
NetworkVisible
Balances
QtObject:
type
@ -46,9 +49,12 @@ QtObject:
{
ModelRole.Name.int:"name",
ModelRole.Symbol.int:"symbol",
ModelRole.Balance.int:"balance",
ModelRole.Address.int:"address",
ModelRole.CurrencyBalance.int:"currencyBalance",
ModelRole.TotalBalance.int:"totalBalance",
ModelRole.TotalCurrencyBalance.int:"totalCurrencyBalance",
ModelRole.EnabledNetworkCurrencyBalance.int:"enabledNetworkCurrencyBalance",
ModelRole.EnabledNetworkBalance.int:"enabledNetworkBalance",
ModelRole.NetworkVisible.int:"networkVisible",
ModelRole.Balances.int:"balances",
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -66,12 +72,18 @@ QtObject:
result = newQVariant(item.getName())
of ModelRole.Symbol:
result = newQVariant(item.getSymbol())
of ModelRole.Balance:
result = newQVariant(item.getBalance())
of ModelRole.Address:
result = newQVariant(item.getAddress())
of ModelRole.CurrencyBalance:
result = newQVariant(item.getCurrencyBalance())
of ModelRole.TotalBalance:
result = newQVariant(item.getTotalBalance())
of ModelRole.TotalCurrencyBalance:
result = newQVariant(item.getTotalCurrencyBalance())
of ModelRole.EnabledNetworkCurrencyBalance:
result = newQVariant(item.getEnabledNetworkCurrencyBalance())
of ModelRole.EnabledNetworkBalance:
result = newQVariant(item.getEnabledNetworkBalance())
of ModelRole.NetworkVisible:
result = newQVariant(item.getNetworkVisible())
of ModelRole.Balances:
result = newQVariant(item.getBalances())
proc rowData(self: Model, index: int, column: string): string {.slot.} =
if (index >= self.items.len):
@ -80,12 +92,22 @@ QtObject:
case column:
of "name": result = $item.getName()
of "symbol": result = $item.getSymbol()
of "balance": result = $item.getBalance()
of "address": result = $item.getAddress()
of "currencyBalance": result = $item.getCurrencyBalance()
of "totalBalance": result = $item.getTotalBalance()
of "totalCurrencyBalance": result = $item.getTotalCurrencyBalance()
of "enabledNetworkCurrencyBalance": result = $item.getEnabledNetworkCurrencyBalance()
of "enabledNetworkBalance": result = $item.getEnabledNetworkBalance()
of "networkVisible": result = $item.getNetworkVisible()
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
proc hasChain*(self: Model, index: int, chainId: int): bool {.slot.} =
let item = self.items[index]
for balance in item.getBalances().items:
if (balance.chainId == chainId):
return true
return false

View File

@ -134,7 +134,7 @@ let NETWORKS* = %* [
"nativeCurrencyDecimals": 18,
"isTest": true,
"layer": 1,
"enabled": false,
"enabled": true,
},
{
"chainId": 4,

View File

@ -1,7 +1,7 @@
import chronicles, sequtils, json
import dto
import ../settings/service as settings_service
import ../network/service as network_service
import ../../../backend/backend
@ -14,22 +14,22 @@ const limit = 200
type
Service* = ref object of RootObj
settingsService: settings_service.Service
networkService: network_service.Service
proc delete*(self: Service) =
discard
proc newService*(settingsService: settings_service.Service): Service =
proc newService*(networkService: network_service.Service): Service =
result = Service()
result.settingsService = settingsService
result.networkService = networkService
proc init*(self: Service) =
discard
proc getCollections*(self: Service, address: string): seq[CollectionDto] =
try:
let networkId = self.settingsService.getCurrentNetworkId()
let response = backend.getOpenseaCollectionsByOwner(networkId, address)
let chainId = self.networkService.getNetworkForCollectibles().chainId
let response = backend.getOpenseaCollectionsByOwner(chainId, address)
return map(response.result.getElems(), proc(x: JsonNode): CollectionDto = x.toCollectionDto())
except Exception as e:
let errDesription = e.msg
@ -38,8 +38,8 @@ proc getCollections*(self: Service, address: string): seq[CollectionDto] =
proc getCollectibles*(self: Service, address: string, collectionSlug: string): seq[CollectibleDto] =
try:
let networkId = self.settingsService.getCurrentNetworkId()
let response = backend.getOpenseaAssetsByOwnerAndCollection(networkId, address, collectionSlug, limit)
let chainId = self.networkService.getNetworkForCollectibles().chainId
let response = backend.getOpenseaAssetsByOwnerAndCollection(chainId, address, collectionSlug, limit)
return map(response.result.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto())
except Exception as e:
let errDesription = e.msg

View File

@ -65,17 +65,4 @@ const ensUsernameDetailsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.
"isStatus": arg.isStatus,
"expirationTime": expirationTime
}
arg.finish(responseJson)
#################################################
# Async fetch gas price
#################################################
const fetchGasPriceTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[QObjectTaskArg](argEncoded)
let response = status_eth.getGasPrice()
let responseJson = %* {
"gasPrice": response.result.getStr
}
arg.finish(responseJson)
arg.finish(responseJson)

View File

@ -62,7 +62,6 @@ type
# Signals which may be emitted by this service:
const SIGNAL_ENS_USERNAME_AVAILABILITY_CHECKED* = "ensUsernameAvailabilityChecked"
const SIGNAL_ENS_USERNAME_DETAILS_FETCHED* = "ensUsernameDetailsFetched"
const SIGNAL_GAS_PRICE_FETCHED* = "ensGasPriceFetched"
const SIGNAL_ENS_TRANSACTION_CONFIRMED* = "ensTransactionConfirmed"
const SIGNAL_ENS_TRANSACTION_REVERTED* = "ensTransactionReverted"
@ -183,7 +182,7 @@ QtObject:
vptr: cast[ByteAddress](self.vptr),
slot: "onEnsUsernameAvailabilityChecked",
ensUsername: ensUsername,
chainId: self.settingsService.getCurrentNetworkId(),
chainId: self.networkService.getNetworkForEns().chainId,
isStatus: isStatus,
myPublicKey: self.settingsService.getPublicKey(),
myWalletAddress: self.walletAccountService.getWalletAccount(0).address
@ -220,46 +219,18 @@ QtObject:
vptr: cast[ByteAddress](self.vptr),
slot: "onEnsUsernameDetailsFetched",
ensUsername: ensUsername,
chainId: self.settingsService.getCurrentNetworkId(),
chainId: self.networkService.getNetworkForEns().chainId,
isStatus: isStatus
)
self.threadpool.start(arg)
proc onGasPriceFetched*(self: Service, response: string) {.slot.} =
let responseObj = response.parseJson
if (responseObj.kind != JObject):
info "expected response is not a json object", procName="onGasPriceFetched"
# notify view, this is important
self.events.emit(SIGNAL_GAS_PRICE_FETCHED, GasPriceArgs(gasPrice: "0"))
return
var gasPriceHex: string
if(not responseObj.getProp("gasPrice", gasPriceHex)):
info "expected response doesn't contain gas price", procName="onGasPriceFetched"
# notify view, this is important
self.events.emit(SIGNAL_GAS_PRICE_FETCHED, GasPriceArgs(gasPrice: "0"))
return
let gasPrice = $fromHex(Stuint[256], gasPriceHex)
let parsedGasPrice = parseFloat(wei2gwei(gasPrice))
var data = GasPriceArgs(gasPrice: fmt"{parsedGasPrice:.3f}")
self.events.emit(SIGNAL_GAS_PRICE_FETCHED, data)
proc fetchGasPrice*(self: Service) =
let arg = QObjectTaskArg(
tptr: cast[ByteAddress](fetchGasPriceTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onGasPriceFetched"
)
self.threadpool.start(arg)
proc extractCoordinates(self: Service, pubkey: string):tuple[x: string, y:string] =
result = ("0x" & pubkey[4..67], "0x" & pubkey[68..131])
proc setPubKeyGasEstimate*(self: Service, ensUsername: string, address: string): int =
try:
let
chainId = self.settingsService.getCurrentNetworkId()
chainId = self.networkService.getNetworkForEns().chainId
txData = ens_utils.buildTransaction(parseAddress(address), 0.u256)
let resp = status_ens.setPubKeyEstimate(chainId, %txData, ensUsername,
@ -277,12 +248,12 @@ QtObject:
gasPrice: string,
maxPriorityFeePerGas: string,
maxFeePerGas: string,
password: string
password: string,
eip1559Enabled: bool,
): string =
try:
let
chainId = self.settingsService.getCurrentNetworkId()
eip1559Enabled = self.networkService.isEIP1559Enabled()
chainId = self.networkService.getNetworkForEns().chainId
txData = ens_utils.buildTransaction(parseAddress(address), 0.u256, gas, gasPrice,
eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
@ -303,7 +274,7 @@ QtObject:
proc releaseEnsEstimate*(self: Service, ensUsername: string, address: string): int =
try:
let
chainId = self.settingsService.getCurrentNetworkId()
chainId = self.networkService.getNetworkForEns().chainId
txData = ens_utils.buildTransaction(parseAddress(address), 0.u256)
let resp = status_ens.releaseEstimate(chainId, %txData, ensUsername)
@ -313,8 +284,7 @@ QtObject:
result = 100000
proc getEnsRegisteredAddress*(self: Service): string =
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
let networkDto = self.networkService.getNetwork(networkType)
let networkDto = self.networkService.getNetworkForEns()
return status_ens.getRegistrarAddress(networkDto.chainId).result.getStr
@ -328,7 +298,7 @@ QtObject:
): string =
try:
let
chainId = self.settingsService.getCurrentNetworkId()
chainId = self.networkService.getNetworkForEns().chainId
txData = ens_utils.buildTransaction(parseAddress(address), 0.u256, gas, gasPrice)
let resp = status_ens.release(chainId, %txData, password, ensUsername)
@ -347,7 +317,7 @@ QtObject:
proc registerENSGasEstimate*(self: Service, ensUsername: string, address: string): int =
try:
let
chainId = self.settingsService.getCurrentNetworkId()
chainId = self.networkService.getNetworkForEns().chainId
txData = ens_utils.buildTransaction(parseAddress(address), 0.u256)
let resp = status_ens.registerEstimate(chainId, %txData, ensUsername,
@ -358,10 +328,9 @@ QtObject:
error "error occurred", procName="registerENSGasEstimate", msg = e.msg
proc getStatusToken*(self: Service): TokenDto =
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
let networkDto = self.networkService.getNetwork(networkType)
let networkDto = self.networkService.getNetworkForEns()
return self.tokenService.findTokenBySymbol(networkDto, networkType.sntSymbol())
return self.tokenService.findTokenBySymbol(networkDto, networkDto.sntSymbol())
proc registerEns*(
self: Service,
@ -371,14 +340,12 @@ QtObject:
gasPrice: string,
maxPriorityFeePerGas: string,
maxFeePerGas: string,
password: string
password: string,
eip1559Enabled: bool,
): string =
try:
let
networkType = self.settingsService.getCurrentNetwork().toNetworkType()
network = self.networkService.getNetwork(networkType)
chainId = network.chainId
eip1559Enabled = self.networkService.isEIP1559Enabled()
chainId = self.networkService.getNetworkForEns().chainId
txData = ens_utils.buildTransaction(parseAddress(address), 0.u256, gas, gasPrice,
eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
@ -399,15 +366,14 @@ QtObject:
proc getSNTBalance*(self: Service): string =
let token = self.getStatusToken()
let account = self.walletAccountService.getWalletAccount(0).address
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
let network = self.networkService.getNetwork(networkType)
let networkDto = self.networkService.getNetworkForEns()
let balances = status_go_backend.getTokensBalancesForChainIDs(@[network.chainId], @[account], @[token.addressAsString()]).result
let balances = status_go_backend.getTokensBalancesForChainIDs(@[networkDto.chainId], @[account], @[token.addressAsString()]).result
return ens_utils.hex2Token(balances{account}{token.addressAsString()}.getStr, token.decimals)
proc resourceUrl*(self: Service, username: string): (string, string, string) =
try:
let chainId = self.settingsService.getCurrentNetworkId()
let chainId = self.networkService.getNetworkForEns().chainId
let response = status_ens.resourceURL(chainId, username)
return (response.result{"Scheme"}.getStr, response.result{"Host"}.getStr, response.result{"Path"}.getStr)
except Exception as e:

View File

@ -74,12 +74,12 @@ proc encodeAbi*(self: MethodDto, obj: object = RootObj()): string =
result &= encoded.data
result &= data
proc estimateGas*(self: MethodDto, tx: var TransactionDataDto, procDescriptor: object, success: var bool): string =
proc estimateGas*(self: MethodDto, chainId: int, tx: var TransactionDataDto, procDescriptor: object, success: var bool): string =
success = true
tx.data = self.encodeAbi(procDescriptor)
try:
# this call should not be part of this file, we need to move it to appropriate place, or this should not be a DTO class.
let response = status_eth.estimateGas(%*[%tx])
let response = status_eth.estimateGas(chainId, %*[%tx])
result = response.result.getStr # gas estimate in hex
except RpcException as e:
success = false
@ -89,20 +89,20 @@ proc getEstimateGasData*(self: MethodDto, tx: var TransactionDataDto, procDescri
tx.data = self.encodeAbi(procDescriptor)
return %*[%tx]
proc send*(self: MethodDto, tx: var TransactionDataDto, procDescriptor: object, password: string, success: var bool): RpcResponse[JsonNode] =
proc send*(self: MethodDto, chainId: int, tx: var TransactionDataDto, procDescriptor: object, password: string, success: var bool): RpcResponse[JsonNode] =
tx.data = self.encodeAbi(procDescriptor)
# this call should not be part of this file, we need to move it to appropriate place, or this should not be a DTO class.
let response = status_eth.sendTransaction($(%tx), password)
let response = status_eth.sendTransaction(chainId, $(%tx), password)
success = response.error.isNil
return response
proc call[T](self: MethodDto, tx: var TransactionDataDto, procDescriptor: object, success: var bool): T =
proc call[T](self: MethodDto, chainId: int, tx: var TransactionDataDto, procDescriptor: object, success: var bool): T =
success = true
tx.data = self.encodeAbi(procDescriptor)
let response: RpcResponse
try:
# this call should not be part of this file, we need to move it to appropriate place, or this should not be a DTO class.
response = status_eth.doEthCall(tx)
response = status_eth.doEthCall(chainId, tx)
except RpcException as e:
success = false
result = e.msg

View File

@ -305,7 +305,7 @@ QtObject:
proc getTransactionDetails*(self: Service, message: MessageDto): (string, string) =
# TODO(alaibe): handle multi network
let networkDto = self.networkService.getEnabledNetworks()[0]
let networkDto = self.networkService.getNetworks()[0]
let ethereum = newTokenDto("Ethereum", networkDto.chainId, parseAddress(ZERO_ADDRESS), "ETH", 18, true)
let tokenContract = if message.transactionParameters.contract == "" : ethereum else: self.tokenService.findTokenByAddress(networkDto, parseAddress(message.transactionParameters.contract))
let tokenContractStr = if tokenContract == nil: "{}" else: $(Json.encode(tokenContract))

View File

@ -56,18 +56,6 @@ proc getNetworks*(self: Service): seq[NetworkDto] =
if not testNetworksEnabled and not network.isTest:
result.add(network)
proc getEnabledNetworks*(self: Service): seq[NetworkDto] =
if not singletonInstance.localAccountSensitiveSettings.getIsMultiNetworkEnabled():
let currentNetworkType = self.settingsService.getCurrentNetwork().toNetworkType()
for network in self.fetchNetworks():
if currentNetworkType.toChainId() == network.chainId:
return @[network]
let networks = self.getNetworks()
for network in networks:
if network.enabled:
result.add(network)
proc upsertNetwork*(self: Service, network: NetworkDto) =
discard backend.addEthereumChain(backend.Network(
chainId: network.chainId,
@ -107,13 +95,31 @@ proc toggleNetwork*(self: Service, chainId: int) =
network.enabled = not network.enabled
self.upsertNetwork(network)
proc isEIP1559Enabled*(self: Service): bool =
# TODO: Assume multi network is not enabled
# TODO: add block number chain for other chains
let network = self.getEnabledNetworks()[0]
case network.chainId:
of 3: return true
of 4: return true
of 5: return true
of 1: return true
else: return false
proc getNetworkForEns*(self: Service): NetworkDto =
if not singletonInstance.localAccountSensitiveSettings.getIsMultiNetworkEnabled():
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
return self.getNetwork(networkType)
if self.settingsService.areTestNetworksEnabled():
return self.getNetwork(Ropsten)
return self.getNetwork(Mainnet)
proc getNetworkForStickers*(self: Service): NetworkDto =
return self.getNetworkForEns()
proc getNetworkForBrowser*(self: Service): NetworkDto =
return self.getNetworkForEns()
proc getNetworkForChat*(self: Service): NetworkDto =
return self.getNetworkForEns()
proc getNetworkForCollectibles*(self: Service): NetworkDto =
if not singletonInstance.localAccountSensitiveSettings.getIsMultiNetworkEnabled():
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
return self.getNetwork(networkType)
if self.settingsService.areTestNetworksEnabled():
return self.getNetwork(Rinkeby)
return self.getNetwork(Mainnet)

View File

@ -43,10 +43,4 @@ proc toChainId*(self: NetworkType): int =
of NetworkType.Goerli: result = Goerli
of NetworkType.XDai: result = XDai
of NetworkType.Poa: result = 99
of NetworkType.Other: result = -1
proc sntSymbol*(networkType: NetworkType): string =
if networkType == NetworkType.Mainnet:
return "SNT"
else:
return "STT"
of NetworkType.Other: result = -1

View File

@ -25,7 +25,6 @@ logScope:
QtObject:
type Service* = ref object of QObject
settings: SettingsDto
eip1559Enabled*: bool
proc delete*(self: Service) =
self.QObject.delete
@ -33,7 +32,6 @@ QtObject:
proc newService*(): Service =
new(result, delete)
result.QObject.setup
result.eip1559Enabled = false
proc init*(self: Service) =
try:
@ -414,23 +412,6 @@ QtObject:
proc unpinMailserver*(self: Service, fleet: Fleet): bool =
return self.pinMailserver("", fleet)
proc isEIP1559Enabled*(self: Service, blockNumber: int): bool =
let networkId = self.getCurrentNetworkDetails().config.NetworkId
let activationBlock = case networkId:
of 3: 10499401 # Ropsten
of 4: 8897988 # Rinkeby
of 5: 5062605 # Goerli
of 1: 12965000 # Mainnet
else: -1
if activationBlock > -1 and blockNumber >= activationBlock:
result = true
else:
result = false
self.eip1559Enabled = result
proc isEIP1559Enabled*(self: Service): bool =
result = self.eip1559Enabled
proc saveNodeConfiguration*(self: Service, value: JsonNode): bool =
if(self.saveSetting(KEY_NODE_CONFIG, value)):
self.settings.nodeConfig = value

View File

@ -49,16 +49,4 @@ const obtainMarketStickerPacksTask: Task = proc(argEncoded: string) {.gcsafe, ni
var packs: seq[StickerPackDto] = @[]
for packId, stickerPack in marketStickerPacks.pairs:
packs.add(stickerPack)
arg.finish(%*(packs))
#################################################
# Async fetch gas price
#################################################
const fetchGasPriceTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[QObjectTaskArg](argEncoded)
let response = status_eth.getGasPrice()
let responseJson = %* {
"gasPrice": response.result.getStr
}
arg.finish(responseJson)
arg.finish(%*(packs))

View File

@ -56,7 +56,6 @@ const SIGNAL_STICKER_PACK_LOADED* = "stickerPackLoaded"
const SIGNAL_ALL_STICKER_PACKS_LOADED* = "allStickerPacksLoaded"
const SIGNAL_STICKER_GAS_ESTIMATED* = "stickerGasEstimated"
const SIGNAL_INSTALLED_STICKER_PACKS_LOADED* = "installedStickerPacksLoaded"
const SIGNAL_GAS_PRICE_FETCHED* = "stickersGasPriceFetched"
const SIGNAL_STICKER_TRANSACTION_CONFIRMED* = "stickerTransactionConfirmed"
const SIGNAL_STICKER_TRANSACTION_REVERTED* = "stickerTransactionReverted"
@ -113,7 +112,7 @@ QtObject:
proc getStickerMarketAddress*(self: Service): string =
try:
let chainId = self.settingsService.getCurrentNetworkId()
let chainId = self.networkService.getNetworkForStickers().chainId
let response = status_stickers.stickerMarketAddress(chainId)
return response.result.getStr()
except RpcException:
@ -196,16 +195,13 @@ QtObject:
result.gasPrice = (if gasPrice.isEmptyOrWhitespace: int.none else: gwei2Wei(parseFloat(gasPrice)).truncate(int).some)
proc getStatusToken*(self: Service): TokenDto =
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
let networkDto = self.networkService.getNetwork(networkType)
let networkDto = self.networkService.getNetworkForStickers()
return self.tokenService.findTokenBySymbol(networkDto, networkType.sntSymbol())
return self.tokenService.findTokenBySymbol(networkDto, networkDto.sntSymbol())
proc buyPack*(self: Service, packId: string, address, gas, gasPrice: string, eip1559Enabled: bool, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, success: var bool): tuple[txHash: string, error: string] =
let
networkType = self.settingsService.getCurrentNetwork().toNetworkType()
network = self.networkService.getNetwork(networkType)
chainId = network.chainId
chainId = self.networkService.getNetworkForStickers().chainId
txData = buildTransaction(parseAddress(address), gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
try:
@ -230,8 +226,7 @@ QtObject:
except RpcException:
error "Error sending transaction", message = getCurrentExceptionMsg()
proc buy*(self: Service, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): tuple[response: string, success: bool] =
let eip1559Enabled = self.networkService.isEIP1559Enabled()
proc buy*(self: Service, packId: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, eip1559Enabled: bool): tuple[response: string, success: bool] =
try:
status_utils.validateTransactionInput(address, address, "", "0", gas, gasPrice, "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, "ok")
except Exception as e:
@ -264,7 +259,7 @@ QtObject:
))
let chainId = self.settingsService.getCurrentNetworkId()
let chainId = self.networkService.getNetworkForStickers().chainId
let pendingStickerPacksResponse = status_stickers.pending()
for (packID, stickerPackJson) in pendingStickerPacksResponse.result.pairs():
if self.marketStickerPacks.contains(packID): continue
@ -278,7 +273,7 @@ QtObject:
self.events.emit(SIGNAL_ALL_STICKER_PACKS_LOADED, Args())
proc obtainMarketStickerPacks*(self: Service) =
let chainId = self.settingsService.getCurrentNetworkId()
let chainId = self.networkService.getNetworkForStickers().chainId
let arg = ObtainMarketStickerPacksTaskArg(
tptr: cast[ByteAddress](obtainMarketStickerPacksTask),
@ -297,7 +292,7 @@ QtObject:
# definition so we'll need to setup the type, task, and helper outside of body
# passed to `QtObject:`
proc estimate*(self: Service, packId: string, address: string, price: string, uuid: string) =
let chainId = self.settingsService.getCurrentNetworkId()
let chainId = self.networkService.getNetworkForStickers().chainId
let arg = EstimateTaskArg(
tptr: cast[ByteAddress](estimateTask),
@ -339,7 +334,7 @@ QtObject:
return 0
proc installStickerPack*(self: Service, packId: string) =
let chainId = self.settingsService.getCurrentNetworkId()
let chainId = self.networkService.getNetworkForStickers().chainId
if not self.marketStickerPacks.hasKey(packId):
return
let installResponse = status_stickers.install(chainId, packId)
@ -380,36 +375,7 @@ QtObject:
proc getSNTBalance*(self: Service): string =
let token = self.getStatusToken()
let account = self.walletAccountService.getWalletAccount(0).address
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
let network = self.networkService.getNetwork(networkType)
let network = self.networkService.getNetworkForStickers()
let balances = status_go_backend.getTokensBalancesForChainIDs(@[network.chainId], @[account], @[token.addressAsString()]).result
return ens_utils.hex2Token(balances{account}{token.addressAsString()}.getStr, token.decimals)
proc onGasPriceFetched*(self: Service, response: string) {.slot.} =
let responseObj = response.parseJson
if (responseObj.kind != JObject):
info "expected response is not a json object", procName="onGasPriceFetched"
# notify view, this is important
self.events.emit(SIGNAL_GAS_PRICE_FETCHED, GasPriceArgs(gasPrice: "0"))
return
var gasPriceHex: string
if(not responseObj.getProp("gasPrice", gasPriceHex)):
info "expected response doesn't contain gas price", procName="onGasPriceFetched"
# notify view, this is important
self.events.emit(SIGNAL_GAS_PRICE_FETCHED, GasPriceArgs(gasPrice: "0"))
return
let gasPrice = $fromHex(Stuint[256], gasPriceHex)
let parsedGasPrice = parseFloat(wei2gwei(gasPrice))
var data = GasPriceArgs(gasPrice: fmt"{parsedGasPrice:.3f}")
self.events.emit(SIGNAL_GAS_PRICE_FETCHED, data)
proc fetchGasPrice*(self: Service) =
let arg = QObjectTaskArg(
tptr: cast[ByteAddress](fetchGasPriceTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onGasPriceFetched"
)
self.threadpool.start(arg)
return ens_utils.hex2Token(balances{account}{token.addressAsString()}.getStr, token.decimals)

View File

@ -25,11 +25,10 @@ proc newTokenDto*(
name: name, chainId: chainId, address: address, symbol: symbol, decimals: decimals, hasIcon: hasIcon, isCustom: isCustom
)
proc toTokenDto*(jsonObj: JsonNode, activeTokenSymbols: seq[string], hasIcon: bool = false, isCustom: bool = true): TokenDto =
proc toTokenDto*(jsonObj: JsonNode, isVisible: bool, hasIcon: bool = false, isCustom: bool = true): TokenDto =
result = TokenDto()
result.isCustom = isCustom
result.hasIcon = hasIcon
result.isVisible = false
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("chainId", result.chainId)
@ -38,8 +37,7 @@ proc toTokenDto*(jsonObj: JsonNode, activeTokenSymbols: seq[string], hasIcon: bo
discard jsonObj.getProp("decimals", result.decimals)
discard jsonObj.getProp("color", result.color)
if activeTokenSymbols.contains(result.symbol):
result.isVisible = true
result.isVisible = isVisible
proc addressAsString*(self: TokenDto): string =
return $self.address

View File

@ -63,22 +63,20 @@ QtObject:
proc init*(self: Service) =
try:
self.tokens = initTable[NetworkDto, seq[TokenDto]]()
let networks = self.networkService.getEnabledNetworks()
let networks = self.networkService.getNetworks()
let chainIds = networks.map(n => n.chainId)
let visibleTokens = backend.getVisibleTokens(chainIds).result
let responseCustomTokens = backend.getCustomTokens()
for network in networks:
let activeTokenSymbols = visibleTokens[$network.chainId].getElems().map(n => n["symbol"].getStr)
let responseTokens = backend.getTokens(network.chainId)
let default_tokens = map(
responseTokens.result.getElems(),
proc(x: JsonNode): TokenDto = x.toTokenDto(activeTokenSymbols, hasIcon=true, isCustom=false)
proc(x: JsonNode): TokenDto = x.toTokenDto(network.enabled, hasIcon=true, isCustom=false)
)
self.tokens[network] = concat(
default_tokens,
map(responseCustomTokens.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(activeTokenSymbols))
map(responseCustomTokens.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(network.enabled))
).filter(
proc(x: TokenDto): bool = x.chainId == network.chainId
)
@ -106,15 +104,9 @@ QtObject:
if token.address == address:
return token
proc getVisibleTokens*(self: Service): seq[TokenDto] =
for tokens in self.getTokens().values:
for token in tokens:
if token.isVisible:
result.add(token)
proc addCustomToken*(self: Service, chainId: int, address: string, name: string, symbol: string, decimals: int): string =
# TODO(alaile): use chainId rather than first enabled network
let networkWIP = self.networkService.getEnabledNetworks()[0]
let networkWIP = self.networkService.getNetworks()[0]
let foundToken = self.findTokenByAddress(networkWIP, parseAddress(address))
if not foundToken.isNil:

View File

@ -57,6 +57,11 @@ type SuggestedFees = object
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]
QtObject:
type Service* = ref object of QObject
@ -213,56 +218,56 @@ QtObject:
loadMore: loadMore
)
self.threadpool.start(arg)
proc estimateGas*(
self: Service,
from_addr: string,
to: string,
assetAddress: string,
assetSymbol: string,
value: string,
data: string = ""
chainId: string,
data: string = "",
): string {.slot.} =
var response: RpcResponse[JsonNode]
var success: bool
# TODO make this async
if assetAddress != ZERO_ADDRESS and not assetAddress.isEmptyOrWhitespace:
var tx = buildTokenTransaction(
let network = self.networkService.getNetwork(parseInt(chainId))
if network.nativeCurrencySymbol == assetSymbol:
var tx = ens_utils.buildTransaction(
parseAddress(from_addr),
parseAddress(assetAddress)
eth2Wei(parseFloat(value), 18),
data = data
)
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
let network = self.networkService.getNetwork(networkType)
let token = self.tokenService.findTokenByAddress(network, parseAddress(assetAddress))
if token == nil:
raise newException(ValueError, fmt"Could not find ERC-20 contract with address '{assetAddress}' for the current network")
let transfer = Transfer(to: parseAddress(to), value: conversion.eth2Wei(parseFloat(value), token.decimals))
let transferproc = ERC20_procS.toTable["transfer"]
var success: bool
tx.to = parseAddress(to).some
try:
let gas = transferproc.estimateGas(tx, transfer, success)
let res = fromHex[int](gas)
return $(%* { "result": res, "success": success })
response = eth.estimateGas(parseInt(chainId), %*[%tx])
let res = fromHex[int](response.result.getStr)
return $(%* { "result": res, "success": true })
except Exception as e:
error "Error estimating gas", msg = e.msg
return $(%* { "result": "-1", "success": false, "error": { "message": e.msg } })
var tx = ens_utils.buildTransaction(
let token = self.tokenService.findTokenBySymbol(network, assetSymbol)
if token == nil:
raise newException(ValueError, fmt"Could not find ERC-20 contract with symbol '{assetSymbol}' for the current network")
var tx = buildTokenTransaction(
parseAddress(from_addr),
eth2Wei(parseFloat(value), 18),
data = data
token.address,
)
tx.to = parseAddress(to).some
let transfer = Transfer(to: parseAddress(to), value: conversion.eth2Wei(parseFloat(value), token.decimals))
let transferproc = ERC20_procS.toTable["transfer"]
try:
response = eth.estimateGas(%*[%tx])
let res = fromHex[int](response.result.getStr)
let gas = transferproc.estimateGas(parseInt(chainId), tx, transfer, success)
let res = fromHex[int](gas)
return $(%* { "result": res, "success": success })
except Exception as e:
error "Error estimating gas", msg = e.msg
return $(%* { "result": "-1", "success": false })
return $(%* { "result": "-1", "success": false, "error": { "message": e.msg } })
proc transferEth*(
proc transferEth(
self: Service,
from_addr: string,
to_addr: string,
@ -272,10 +277,11 @@ QtObject:
maxPriorityFeePerGas: string,
maxFeePerGas: string,
password: string,
uuid: string
): bool {.slot.} =
chainId: string,
uuid: string,
eip1559Enabled: bool,
): bool {.slot.} =
try:
let eip1559Enabled = self.networkService.isEIP1559Enabled()
eth_utils.validateTransactionInput(from_addr, to_addr, assetAddress = "", value, gas,
gasPrice, data = "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, uuid)
@ -285,8 +291,7 @@ QtObject:
tx.to = parseAddress(to_addr).some
let json: JsonNode = %tx
let response = eth.sendTransaction($json, password)
let response = eth.sendTransaction(parseInt(chainId), $json, password)
let output = %* { "result": response.result.getStr, "success": %(response.error.isNil), "uuid": %uuid }
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
@ -298,34 +303,35 @@ QtObject:
return true
proc transferTokens*(
self: Service,
from_addr: string,
to_addr: string,
assetAddress: string,
value: string,
gas: string,
gasPrice: string,
maxPriorityFeePerGas: string,
maxFeePerGas: string,
password: string,
uuid: string
): bool =
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
try:
let eip1559Enabled = self.networkService.isEIP1559Enabled()
eth_utils.validateTransactionInput(from_addr, to_addr, assetAddress, value, gas,
gasPrice, data = "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, uuid)
let network = self.networkService.getNetwork(parseInt(chainId))
let token = self.tokenService.findTokenBySymbol(network, tokenSymbol)
# TODO move this to another thread
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
let network = self.networkService.getNetwork(networkType)
let token = self.tokenService.findTokenByAddress(network, parseAddress(assetAddress))
var tx = ens_utils.buildTokenTransaction(parseAddress(from_addr), parseAddress(assetAddress),
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 success: bool
let transfer = Transfer(to: parseAddress(to_addr),
value: conversion.eth2Wei(parseFloat(value), token.decimals))
let transferproc = ERC20_procS.toTable["transfer"]
let response = transferproc.send(tx, transfer, password, success)
let response = transferproc.send(parseInt(chainId), tx, transfer, password, success)
let txHash = response.result.getStr
let output = %* { "result": txHash, "success": %success, "uuid": %uuid }
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
@ -337,19 +343,45 @@ QtObject:
return false
return true
proc suggestedFees*(self: Service): SuggestedFees =
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
let network = self.networkService.getNetwork(networkType)
let response = eth.suggestedFees(network.chainId).result
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 =
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)
)
maxFeePerGasH: parseFloat(response{"maxFeePerGasHigh"}.getStr),
eip1559Enabled: response{"eip1559Enabled"}.getbool,
)
proc suggestedRoutes*(self: Service, account: string, amount: float64, token: string): SuggestedRoutes =
let response = eth.suggestedRoutes(account, amount, token)
return SuggestedRoutes(
networks: Json.decode($response.result{"networks"}, seq[NetworkDto])
)
proc fetchCryptoServices*(self: Service): seq[CryptoRampDto] =
try:

View File

@ -98,19 +98,27 @@ type
proc getCustomTokens(): seq[TokenDto] =
try:
let responseCustomTokens = backend.getCustomTokens()
result = map(responseCustomTokens.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(@[]))
result = map(responseCustomTokens.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(true))
except Exception as e:
error "error fetching custom tokens: ", message = e.msg
proc getTokensForChainId(chainId: int): seq[TokenDto] =
proc getTokensForChainId(network: NetworkDto): seq[TokenDto] =
try:
let responseTokens = backend.getTokens(chainId)
let defaultTokens = map(responseTokens.result.getElems(),
proc(x: JsonNode): TokenDto = x.toTokenDto(@[], hasIcon=true, isCustom=false)
)
let responseTokens = backend.getTokens(network.chainId)
let defaultTokens = map(
responseTokens.result.getElems(),
proc(x: JsonNode): TokenDto = x.toTokenDto(network.enabled, hasIcon=true, isCustom=false)
)
result.add(defaultTokens)
except Exception as e:
error "error fetching tokens: ", message = e.msg, chainId=chainId
error "error fetching tokens: ", message = e.msg, chainId=network.chainId
proc isNetworkEnabledForChainId(networks: seq[NetworkDto], chainId: int): bool =
for network in networks:
if network.chainId == chainId:
return network.enabled
return false
proc prepareSymbols(networkSymbols: seq[string], allTokens: seq[TokenDto]): seq[seq[string]] =
# we have to use up to 300 characters in a single request when we're fetching prices
@ -151,6 +159,9 @@ proc fetchNativeChainBalance(chainId: int, nativeCurrencyDecimals: int, accountA
proc fetchPrices(networkSymbols: seq[string], allTokens: seq[TokenDto], currency: string): Table[string, float] =
let allSymbols = prepareSymbols(networkSymbols, allTokens)
for symbols in allSymbols:
if symbols.len == 0:
continue
try:
let response = backend.fetchPrices(symbols, currency)
for (symbol, value) in response.result.pairs:
@ -197,15 +208,13 @@ const prepareTokensTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[BuildTokensTaskArg](argEncoded)
var networkSymbols: seq[string]
var chainIdsFromSettings: seq[int]
var allTokens: seq[TokenDto]
for network in arg.networks:
networkSymbols.add(network.nativeCurrencySymbol)
chainIdsFromSettings.add(network.chainId)
var allTokens: seq[TokenDto]
allTokens.add(getTokensForChainId(network))
allTokens.add(getCustomTokens())
for chainId in chainIdsFromSettings:
allTokens.add(getTokensForChainId(chainId))
allTokens = deduplicate(allTokens)
var prices = fetchPrices(networkSymbols, allTokens, arg.currency)
@ -216,55 +225,80 @@ const prepareTokensTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
var builtTokens: seq[WalletTokenDto]
let groupedNetworks = groupNetworksBySymbol(arg.networks)
var enabledNetworkBalance = BalanceDto(
balance: 0.0,
currencyBalance: 0.0
)
for networkNativeCurrencySymbol, networks in groupedNetworks.pairs:
var balancesPerChain = initTable[int, BalanceDto]()
for network in networks:
let chainBalance = fetchNativeChainBalance(network.chainId, network.nativeCurrencyDecimals, address)
balancesPerChain[network.chainId] = BalanceDto(
balance: chainBalance,
currencyBalance: chainBalance * prices[network.nativeCurrencySymbol]
currencyBalance: chainBalance * prices[network.nativeCurrencySymbol],
chainId: network.chainId,
address: "0x0000000000000000000000000000000000000000"
)
if network.enabled:
enabledNetworkBalance.balance += balancesPerChain[network.chainId].balance
enabledNetworkBalance.currencyBalance += balancesPerChain[network.chainId].currencyBalance
let networkDto = getNetworkByCurrencySymbol(arg.networks, networkNativeCurrencySymbol)
var totalTokenBalance: BalanceDto
totalTokenBalance.balance = toSeq(balancesPerChain.values).map(x => x.balance).foldl(a + b)
totalTokenBalance.currencyBalance = totalTokenBalance.balance * prices[networkDto.nativeCurrencySymbol]
builtTokens.add(WalletTokenDto(
name: networkDto.nativeCurrencyName,
address: "0x0000000000000000000000000000000000000000",
symbol: networkDto.nativeCurrencySymbol,
decimals: networkDto.nativeCurrencyDecimals,
hasIcon: true,
color: "blue",
isCustom: false,
totalBalance: totalTokenBalance,
balancesPerChain: balancesPerChain
enabledNetworkBalance: enabledNetworkBalance,
balancesPerChain: balancesPerChain,
visible: networkDto.enabled,
)
)
let groupedTokens = groupTokensBySymbol(allTokens)
enabledNetworkBalance = BalanceDto(
balance: 0.0,
currencyBalance: 0.0
)
for symbol, tokens in groupedTokens.pairs:
var balancesPerChain = initTable[int, BalanceDto]()
var visible = false
for token in tokens:
let balanceForToken = tokenBalances{address}{token.addressAsString()}.getStr
let chainBalanceForToken = parsefloat(hex2Balance(balanceForToken, token.decimals))
balancesPerChain[token.chainId] = BalanceDto(
balance: chainBalanceForToken,
currencyBalance: chainBalanceForToken * prices[token.symbol]
currencyBalance: chainBalanceForToken * prices[token.symbol],
chainId: token.chainId,
address: $token.address
)
if isNetworkEnabledForChainId(arg.networks, token.chainId):
visible = true
enabledNetworkBalance.balance += balancesPerChain[token.chainId].balance
enabledNetworkBalance.currencyBalance += balancesPerChain[token.chainId].currencyBalance
let tokenDto = getTokenForSymbol(allTokens, symbol)
var totalTokenBalance: BalanceDto
totalTokenBalance.balance = toSeq(balancesPerChain.values).map(x => x.balance).foldl(a + b)
totalTokenBalance.currencyBalance = totalTokenBalance.balance * prices[tokenDto.symbol]
builtTokens.add(WalletTokenDto(
name: tokenDto.name,
address: $tokenDto.address,
symbol: tokenDto.symbol,
decimals: tokenDto.decimals,
hasIcon: tokenDto.hasIcon,
color: tokenDto.color,
isCustom: tokenDto.isCustom,
totalBalance: totalTokenBalance,
balancesPerChain: balancesPerChain
balancesPerChain: balancesPerChain,
enabledNetworkBalance: enabledNetworkBalance,
visible: visible
)
)
@ -272,6 +306,6 @@ const prepareTokensTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
for wtDto in builtTokens:
tokensJarray.add(walletTokenDtoToJson(wtDto))
builtTokensPerAccount[address] = tokensJArray
arg.finish(builtTokensPerAccount)

View File

@ -5,18 +5,21 @@ include ../../common/json_utils
type BalanceDto* = object
balance*: float64
currencyBalance*: float64
address*: string
chainId*: int
type
WalletTokenDto* = object
name*: string
address*: string
symbol*: string
decimals*: int
hasIcon*: bool
color*: string
isCustom*: bool
totalBalance*: BalanceDto
enabledNetworkBalance*: BalanceDto
balancesPerChain*: Table[int, BalanceDto]
visible*: bool
type
WalletAccountDto* = ref object of RootObj
@ -79,20 +82,26 @@ proc toBalanceDto*(jsonObj: JsonNode): BalanceDto =
result = BalanceDto()
discard jsonObj.getProp("balance", result.balance)
discard jsonObj.getProp("currencyBalance", result.currencyBalance)
discard jsonObj.getProp("address", result.address)
discard jsonObj.getProp("chainId", result.chainId)
proc toWalletTokenDto*(jsonObj: JsonNode): WalletTokenDto =
result = WalletTokenDto()
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("address", result.address)
discard jsonObj.getProp("symbol", result.symbol)
discard jsonObj.getProp("decimals", result.decimals)
discard jsonObj.getProp("hasIcon", result.hasIcon)
discard jsonObj.getProp("color", result.color)
discard jsonObj.getProp("isCustom", result.isCustom)
discard jsonObj.getProp("visible", result.visible)
var totalBalanceObj: JsonNode
if(jsonObj.getProp("totalBalance", totalBalanceObj)):
result.totalBalance = toBalanceDto(totalBalanceObj)
var enabledNetworkBalanceObj: JsonNode
if(jsonObj.getProp("enabledNetworkBalance", enabledNetworkBalanceObj)):
result.enabledNetworkBalance = toBalanceDto(enabledNetworkBalanceObj)
var balancesPerChainObj: JsonNode
if(jsonObj.getProp("balancesPerChain", balancesPerChainObj)):
@ -106,12 +115,13 @@ proc walletTokenDtoToJson*(dto: WalletTokenDto): JsonNode =
result = %* {
"name": dto.name,
"address": dto.address,
"symbol": dto.symbol,
"decimals": dto.decimals,
"hasIcon": dto.hasIcon,
"color": dto.color,
"isCustom": dto.isCustom,
"totalBalance": %* dto.totalBalance,
"balancesPerChain": balancesPerChainJsonObj
"enabledNetworkBalance": %* dto.enabledNetworkBalance,
"balancesPerChain": balancesPerChainJsonObj,
"visible": dto.visible
}

View File

@ -394,7 +394,7 @@ QtObject:
slot: "onAllTokensBuilt",
walletAddresses: walletAddresses,
currency: self.settingsService.getCurrency(),
networks: self.networkService.getEnabledNetworks()
networks: self.networkService.getNetworks()
)
self.threadpool.start(arg)

View File

@ -96,9 +96,6 @@ rpc(discoverToken, "wallet"):
rpc(getPendingTransactions, "wallet"):
discard
rpc(getVisibleTokens, "wallet"):
chainIds: seq[int]
rpc(toggleVisibleToken, "wallet"):
chainId: int
address: string

View File

@ -60,11 +60,11 @@ proc signMessage*(rpcParams: string): string =
proc signTypedData*(data: string, address: string, password: string): string =
return $status_go.signTypedData(data, address, password)
proc sendTransaction*(inputJSON: string, password: string): RpcResponse[JsonNode]
proc sendTransaction*(chainId: int, inputJSON: string, password: string): RpcResponse[JsonNode]
{.raises: [RpcException, ValueError, Defect, SerializationError].} =
try:
var hashed_password = "0x" & $keccak_256.digest(password)
let rpcResponseRaw = status_go.sendTransaction(inputJSON, hashed_password)
let rpcResponseRaw = status_go.sendTransactionWithChainId(chainId, inputJSON, hashed_password)
result = Json.decode(rpcResponseRaw, RpcResponse[JsonNode])
except RpcException as e:
error "error sending tx", inputJSON, exception=e.msg

View File

@ -14,22 +14,23 @@ proc getNativeChainBalance*(chainId: int, address: string): RpcResponse[JsonNode
let payload = %* [address, "latest"]
return core.callPrivateRPCWithChainId("eth_getBalance", chainId, payload)
proc sendTransaction*(transactionData: string, password: string): RpcResponse[JsonNode] {.raises: [Exception].} =
core.sendTransaction(transactionData, password)
proc sendTransaction*(chainId: int, transactionData: string, password: string): RpcResponse[JsonNode] {.raises: [Exception].} =
core.sendTransaction(chainId, transactionData, password)
# This is the replacement of the `call` function
proc doEthCall*(payload = %* []): RpcResponse[JsonNode] {.raises: [Exception].} =
core.callPrivateRPC("eth_call", payload)
proc estimateGas*(payload = %* []): RpcResponse[JsonNode] {.raises: [Exception].} =
core.callPrivateRPC("eth_estimateGas", payload)
proc estimateGas*(chainId: int, payload = %* []): RpcResponse[JsonNode] {.raises: [Exception].} =
core.callPrivateRPCWithChainId("eth_estimateGas", chainId, payload)
proc getEthAccounts*(): RpcResponse[JsonNode] {.raises: [Exception].} =
return core.callPrivateRPC("eth_accounts")
proc getGasPrice*(payload = %* []): RpcResponse[JsonNode] {.raises: [Exception].} =
return core.callPrivateRPC("eth_gasPrice", payload)
proc suggestedFees*(chainId: int): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [chainId]
return core.callPrivateRPC("wallet_getSuggestedFees", payload)
return core.callPrivateRPC("wallet_getSuggestedFees", payload)
proc suggestedRoutes*(account: string, amount: float64, token: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [account, amount, token]
return core.callPrivateRPC("wallet_getSuggestedRoutes", payload)

@ -1 +1 @@
Subproject commit 0b855bfb48159850decbed55b3427bd2c3f3ad96
Subproject commit 18d385cf2b5f075b9ba18ce91465ea3847515aa5

View File

@ -59,6 +59,7 @@ Rectangle {
anchors.centerIn: parent
store: browserWindow.globalStore
contactsStore: browserWindow.globalStore.profileSectionStore.contactsStore
chainId: browserWindow.globalStore.getChainIdForBrowser()
}
property Component signMessageModalComponent: SignMessageModal {}
@ -196,7 +197,7 @@ Rectangle {
// TODO: WIP under PR https://github.com/status-im/status-desktop/pull/4274
let url = `${WalletStore.getEtherscanLink()}/${result}`;
Global.displayToastMessage(qsTr("Transaction pending..."),
"",
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,

View File

@ -78,4 +78,5 @@ QtObject {
function copyToClipboard(text) {
globalUtils.copyToClipboard(text)
}
}

View File

@ -20,13 +20,4 @@ QtObject {
walletSectionTransactions.setModel(address)
}
function getGasPrice(){
// Not Refactored Yet
// walletModel.gasView.getGasPrice()
}
function isEIP1559Enabled() {
return walletSection.isEIP1559Enabled()
}
}

View File

@ -94,12 +94,8 @@ QtObject {
// TODO: use bignumber instead of floats
trx.value = RootStore.getEth2Hex(parseFloat(value))
trx.gas = "0x" + parseInt(selectedGasLimit, 10).toString(16)
if (WalletStore.isEIP1559Enabled()) {
trx.maxPriorityFeePerGas = RootStore.getGwei2Hex(parseFloat(selectedTipLimit))
trx.maxFeePerGas = RootStore.getGwei2Hex(parseFloat(selectedOverallLimit))
} else {
trx.gasPrice = RootStore.getGwei2Hex(parseFloat(selectedGasPrice))
}
trx.maxPriorityFeePerGas = RootStore.getGwei2Hex(parseFloat(selectedTipLimit))
trx.maxFeePerGas = RootStore.getGwei2Hex(parseFloat(selectedOverallLimit))
request.payload.password = enteredPassword
request.payload.params[0] = trx
@ -110,7 +106,6 @@ QtObject {
}
sendDialog.open();
WalletStore.getGasPrice()
} else if (requestType === Constants.web3SendAsyncReadOnly && ["eth_sign", "personal_sign", "eth_signTypedData", "eth_signTypedData_v3"].indexOf(request.payload.method) > -1) {
const signDialog = createSignMessageModalComponent(request)
signDialog.web3Response = web3Response

View File

@ -177,7 +177,7 @@ StatusModal {
if (stack.isLastGroup) {
root.sendChatCommand(selectFromAccount.selectedAccount.address,
txtAmount.selectedAmount,
txtAmount.selectedAsset.address,
txtAmount.selectedAsset.symbol,
txtAmount.selectedAsset.decimals)
return root.close()
}

View File

@ -132,8 +132,6 @@ QtObject {
property string channelEmoji: chatCommunitySectionModule && chatCommunitySectionModule.emoji ? chatCommunitySectionModule.emoji : ""
property string gasPrice: profileSectionModule.ensUsernamesModule.gasPrice
property ListModel addToGroupContacts: ListModel {}
property var walletSectionTransactionsInst: walletSectionTransactions
@ -513,18 +511,16 @@ QtObject {
return profileSectionModule.ensUsernamesModule.getGasEthValue(gweiValue, gasLimit)
}
function estimateGas(from_addr, to, assetAddress, value, data) {
return walletSectionTransactions.estimateGas(from_addr, to, assetAddress, value === "" ? "0.00" : value, data)
function estimateGas(from_addr, to, assetSymbol, value, chainId, data) {
return walletSectionTransactions.estimateGas(from_addr, to, assetSymbol, value === "" ? "0.00" : value, chainId, data)
}
function transferEth(from, to, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, uuid) {
return walletSectionTransactions.transferEth(from, to, amount, gasLimit, gasPrice, tipLimit,
overallLimit, password, uuid);
}
function transferTokens(from, to, address, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, uuid) {
return walletSectionTransactions.transferTokens(from, to, address, amount, gasLimit,
gasPrice, tipLimit, overallLimit, password, uuid);
function transfer(from, to, address, tokenSymbol, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, chainId, uuid, eip1559Enabled) {
return walletSectionTransactions.transfer(
from, to, address, tokenSymbol, amount, gasLimit,
gasPrice, tipLimit, overallLimit, password, chainId, uuid,
eip1559Enabled
);
}
function getAccountNameByAddress(address) {
@ -540,15 +536,11 @@ QtObject {
return walletSectionAccounts.getAccountAssetsByAddress()
}
function fetchGasPrice() {
profileSectionModule.ensUsernamesModule.fetchGasPrice()
function suggestedFees(chainId) {
return JSON.parse(walletSectionTransactions.suggestedFees(chainId))
}
function isEIP1559Enabled() {
return walletSection.isEIP1559Enabled()
}
function suggestedFees() {
return JSON.parse(walletSectionTransactions.suggestedFees())
function suggestedRoutes(account, amount, token) {
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token)).networks
}
}

View File

@ -6,16 +6,8 @@ QtObject {
property var stickersModule
property string gasPrice: root.stickersModule ? stickersModule.gasPrice : "0"
property var walletAccounts: walletSectionAccounts.model
function fetchGasPrice() {
if(!root.stickersModule)
return "0"
stickersModule.fetchGasPrice()
}
function getSigningPhrase() {
if(!root.stickersModule)
return ""
@ -70,10 +62,14 @@ QtObject {
return stickersModule.estimate(packId, selectedAccount, price, uuid)
}
function buy(packId, address, price, gasLimit, gasPrice, tipLimit, overallLimit, password) {
function buy(packId, address, price, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
if(!root.stickersModule)
return ""
return stickersModule.buy(packId, address, price, gasLimit, gasPrice, tipLimit, overallLimit, password)
return stickersModule.buy(packId, address, price, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled)
}
function getChainIdForStickers() {
return stickersModule.getChainIdForStickers()
}
}

View File

@ -384,10 +384,6 @@ Item {
anchors.centerIn: parent
store: root.rootStore
contactsStore: root.contactsStore
onOpened: {
// Not Refactored Yet
// root.rootStore.walletModelInst.gasView.getGasPrice()
}
onClosed: {
destroy()
}

View File

@ -9,6 +9,7 @@ QtObject {
// Advanced Module Properties
property string currentNetworkName: advancedModule? advancedModule.currentNetworkName : ""
property string currentNetworkId: advancedModule? advancedModule.currentNetworkId : ""
property string currentChainId: advancedModule? advancedModule.currentChainId : 0
property string fleet: advancedModule? advancedModule.fleet : ""
property string bloomLevel: advancedModule? advancedModule.bloomLevel : ""
property bool wakuV2LightClientEnabled: advancedModule? advancedModule.wakuV2LightClientEnabled : false
@ -40,10 +41,13 @@ QtObject {
function setGlobalNetworkId() {
Global.currentNetworkId = currentNetworkId
Global.currentChainId = currentChainId
}
Component.onCompleted: {
setGlobalNetworkId()
}
onCurrentNetworkIdChanged: {
setGlobalNetworkId()
}

View File

@ -13,7 +13,6 @@ QtObject {
property string preferredUsername: userProfile.preferredName
property string username: userProfile.username
property string gasPrice: root.ensUsernamesModule ? ensUsernamesModule.gasPrice : "0"
property var walletAccounts: walletSectionAccounts.model
@ -41,22 +40,16 @@ QtObject {
ensUsernamesModule.fetchDetailsForEnsUsername(ensUsername)
}
function fetchGasPrice() {
if(!root.ensUsernamesModule)
return "0"
ensUsernamesModule.fetchGasPrice()
}
function setPubKeyGasEstimate(ensUsername, address) {
if(!root.ensUsernamesModule)
return 0
return ensUsernamesModule.setPubKeyGasEstimate(ensUsername, address)
}
function setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password) {
function setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled) {
if(!root.ensUsernamesModule)
return ""
return ensUsernamesModule.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
return ensUsernamesModule.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, eip1559Enabled)
}
function getEtherscanLink() {
@ -105,10 +98,10 @@ QtObject {
return ensUsernamesModule.registerEnsGasEstimate(ensUsername, address)
}
function registerEns(ensUsername, address, gasLimit, gasPrice, tipLimit, overallLimit, password) {
function registerEns(ensUsername, address, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
if(!root.ensUsernamesModule)
return ""
return ensUsernamesModule.registerEns(ensUsername, address, gasLimit, gasPrice, tipLimit, overallLimit, password)
return ensUsernamesModule.registerEns(ensUsername, address, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled)
}
function getEnsRegistry() {
@ -153,12 +146,18 @@ QtObject {
return ensUsernamesModule.getStatusToken()
}
function isEIP1559Enabled() {
return walletSection.isEIP1559Enabled()
function suggestedFees(chainId) {
return JSON.parse(walletSectionTransactions.suggestedFees(chainId))
}
function suggestedFees() {
return JSON.parse(walletSectionTransactions.suggestedFees())
function getChainIdForEns() {
if(!root.ensUsernamesModule)
return ""
return ensUsernamesModule.getChainIdForEns()
}
function suggestedRoutes(account, amount, token) {
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token)).networks
}
}

View File

@ -518,7 +518,7 @@ SettingsContentBase {
anchors.leftMargin: 0
anchors.rightMargin: 0
text: qsTr("Stickers/ENS on ropsten")
visible: root.advancedStore.currentNetworkId === Constants.networkRopsten
visible: !localAccountSensitiveSettings.isMultiNetworkEnabled && root.advancedStore.currentNetworkId === Constants.networkRopsten
isSwitch: true
switchChecked: localAccountSensitiveSettings.stickersEnsRopsten
onClicked: {

View File

@ -106,9 +106,7 @@ Item {
ensUsernamesStore: root.ensUsernamesStore
contactsStore: root.contactsStore
ensUsername: root.username
onOpened: {
root.ensUsernamesStore.fetchGasPrice()
}
chainId: root.ensUsernamesStore.getChainIdForEns()
title: qsTr("Connect username with your pubkey")
onClosed: {
destroy()

View File

@ -63,9 +63,7 @@ Item {
StatusETHTransactionModal {
ensUsernamesStore: root.ensUsernamesStore
contactsStore: root.contactsStore
onOpened: {
root.ensUsernamesStore.fetchGasPrice()
}
chainId: root.ensUsernamesStore.getChainIdForEns()
title: qsTr("Connect username with your pubkey")
onClosed: {
destroy()
@ -74,14 +72,15 @@ Item {
if (ensUsername.text === "" || !selectedAccount) return 80000;
return root.ensUsernamesStore.setPubKeyGasEstimate(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ), selectedAccount.address)
}
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password) {
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password, eip1559Enabled) {
return root.ensUsernamesStore.setPubKey(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ),
selectedAddress,
gasLimit,
gasPrice,
"",
"",
password)
password,
eip1559Enabled)
}
onSuccess: function(){
usernameUpdated(ensUsername.text);

View File

@ -51,12 +51,13 @@ Item {
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)
}
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password) {
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
return root.ensUsernamesStore.registerEns(
username,
selectedAddress,
@ -64,7 +65,8 @@ Item {
gasPrice,
tipLimit,
overallLimit,
password
password,
eip1559Enabled,
)
}
onSuccess: function(){

View File

@ -325,7 +325,7 @@ Item {
onTransactionWasSent: {
let url = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txResult}`;
Global.displayToastMessage(qsTr("Transaction pending..."),
"",
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
@ -364,7 +364,7 @@ Item {
let url = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txHash}`;
Global.displayToastMessage(qsTr("Transaction pending..."),
"",
qsTr("View on etherscan"),
icon,
false,
ephType,

View File

@ -76,11 +76,9 @@ QtObject {
property string currentCurrency: walletSection.currentCurrency
property string signingPhrase: walletSection.signingPhrase
function estimateGas(from_addr, to, assetAddress, value, data) {
return walletSectionTransactions.estimateGas(from_addr, to, assetAddress, value, data)
function estimateGas(from_addr, to, assetSymbol, value, chainId, data) {
return walletSectionTransactions.estimateGas(from_addr, to, assetSymbol, value, chainId, data)
}
// TODO change this to use a better store once it is moved out of the ENS module
property string gasPrice: profileSectionStore.ensUsernamesStore.gasPrice
function getFiatValue(balance, cryptoSymbo, fiatSymbol) {
return profileSectionStore.ensUsernamesStore.getFiatValue(balance, cryptoSymbo, fiatSymbol)
}
@ -88,22 +86,29 @@ QtObject {
return profileSectionStore.ensUsernamesStore.getGasEthValue(gweiValue, gasLimit)
}
function transferEth(from, to, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, uuid) {
return walletSectionTransactions.transferEth(from, to, amount, gasLimit, gasPrice, tipLimit,
overallLimit, password, uuid);
function transfer(from, to, tokenSymbol, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, chainId, uuid, eip1559Enabled) {
return walletSectionTransactions.transfer(
from, to, tokenSymbol, amount, gasLimit,
gasPrice, tipLimit, overallLimit, password, chainId, uuid,
eip1559Enabled
);
}
function transferTokens(from, to, address, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, uuid) {
return walletSectionTransactions.transferTokens(from, to, address, amount, gasLimit,
gasPrice, tipLimit, overallLimit, password, uuid);
function suggestedFees(chainId) {
return JSON.parse(walletSectionTransactions.suggestedFees(chainId))
}
function isEIP1559Enabled() {
return walletSection.isEIP1559Enabled()
function getChainIdForChat() {
return walletSectionTransactions.getChainIdForChat()
}
function suggestedFees() {
return JSON.parse(walletSectionTransactions.suggestedFees())
function getChainIdForBrowser() {
return walletSectionTransactions.getChainIdForBrowser()
}
function suggestedRoutes(account, amount, token) {
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token)).networks
}
function hex2Eth(value) {

View File

@ -852,10 +852,6 @@ Item {
anchors.centerIn: parent
store: appMain.rootStore
contactsStore: appMain.rootStore.profileSectionStore.contactsStore
onOpened: {
// Not Refactored Yet
// walletModel.gasView.getGasPrice()
}
onClosed: {
sendModal.closed()
}

View File

@ -14,7 +14,7 @@ Item {
anchors.right: parent.right
anchors.left: parent.left
visible: balance > 0
visible: networkVisible && enabledNetworkBalance > 0
height: visible ? 40 + 2 * Style.current.padding : 0
@ -52,7 +52,7 @@ Item {
}
StyledText {
id: assetBalance
text: Utils.toLocaleString(balance, locale) + " " + symbol.toUpperCase()
text: Utils.toLocaleString(enabledNetworkBalance, locale) + " " + symbol.toUpperCase()
anchors.top: assetInfoImage.top
anchors.topMargin: 0
anchors.right: parent.right
@ -63,7 +63,7 @@ Item {
StyledText {
id: assetCurrencyBalance
color: Style.current.secondaryText
text: Utils.toLocaleString(currencyBalance.toFixed(2), locale) + " " + assetDelegate.currency.toUpperCase()
text: Utils.toLocaleString(enabledNetworkCurrencyBalance.toFixed(2), locale) + " " + assetDelegate.currency.toUpperCase()
anchors.right: parent.right
anchors.rightMargin: 0
anchors.top: assetBalance.bottom

View File

@ -14,12 +14,10 @@ Item {
height: visible ? Style.current.smallPadding + prioritytext.height +
(advancedMode ? advancedModeItemGroup.height : selectorButtons.height) : 0
property double gasPrice: 0
property bool isEIP1559Enabled: true
property var suggestedFees: ""
property var suggestedFees: ({
eip1559Enabled: true
})
property var getGasGweiValue: function () {}
property var getGasEthValue: function () {}
property var getFiatValue: function () {}
@ -62,8 +60,10 @@ Item {
// causes error on application load without this null check
if (!inputGasPrice || !inputGasLimit) {
return
}
let ethValue = root.getGasEthValue(inputGasPrice.text, inputGasLimit.text)
let fiatValue = root.getFiatValue(ethValue, "ETH", root.defaultCurrency)
selectedGasEthValue = ethValue
selectedGasFiatValue = fiatValue
@ -75,7 +75,7 @@ Item {
function checkLimits(){
if(!isEIP1559Enabled) return;
if(!root.suggestedFees.eip1559Enabled) return;
let inputTipLimit = parseFloat(inputPerGasTipLimit.text || "0.00")
let inputOverallLimit = parseFloat(inputGasPrice.text || "0.00")
@ -105,9 +105,10 @@ Item {
}
Component.onCompleted: {
updateGasEthValue()
checkLimits()
function checkOptimal() {
if (!optimalGasButton.gasRadioBtn.checked) {
optimalGasButton.gasRadioBtn.toggle()
}
}
function validate() {
@ -132,7 +133,7 @@ Item {
inputGasPrice.validationError = root.noInputErrorMessage
}
if (isEIP1559Enabled && noPerGasTip) {
if (root.suggestedFees.eip1559Enabled && noPerGasTip) {
inputPerGasTipLimit.validationError = root.noInputErrorMessage
}
@ -143,7 +144,7 @@ Item {
inputGasPrice.validationError = invalidInputErrorMessage
}
if (isEIP1559Enabled && isNaN(inputPerGasTipLimit.text)) {
if (root.suggestedFees.eip1559Enabled && isNaN(inputPerGasTipLimit.text)) {
inputPerGasTipLimit.validationError = invalidInputErrorMessage
}
@ -158,11 +159,10 @@ Item {
if (inputPrice <= 0.00) {
inputGasPrice.validationError = root.greaterThan0ErrorMessage
}
if (isEIP1559Enabled && inputTipLimit <= 0.00) {
if (root.suggestedFees.eip1559Enabled && inputTipLimit <= 0.00) {
inputPerGasTipLimit.validationError = root.greaterThan0ErrorMessage
}
const isInputValid = inputGasLimit.validationError === "" && inputGasPrice.validationError === "" && (!isEIP1559Enabled || (isEIP1559Enabled && inputPerGasTipLimit.validationError === ""))
const isInputValid = inputGasLimit.validationError === "" && inputGasPrice.validationError === "" && (!root.suggestedFees.eip1559Enabled || (root.suggestedFees.eip1559Enabled && inputPerGasTipLimit.validationError === ""))
return isInputValid
}
@ -171,8 +171,7 @@ Item {
id: prioritytext
anchors.top: parent.top
anchors.left: parent.left
//% "Priority"
text: qsTrId("priority")
text: root.suggestedFees.eip1559Enabled ? qsTr("Priority") : qsTr("Gas Price")
font.weight: Font.Medium
font.pixelSize: 13
color: Style.current.textColor
@ -180,7 +179,7 @@ Item {
StyledText {
id: baseFeeText
visible: isEIP1559Enabled && advancedMode
visible: root.suggestedFees.eip1559Enabled && advancedMode
anchors.top: parent.top
anchors.left: prioritytext.right
anchors.leftMargin: Style.current.smallPadding
@ -194,6 +193,7 @@ Item {
id: buttonAdvanced
anchors.verticalCenter: prioritytext.verticalCenter
anchors.right: parent.right
visible: root.suggestedFees.eip1559Enabled
text: advancedMode ?
//% "Use suggestions"
qsTrId("use-suggestions") :
@ -205,7 +205,7 @@ Item {
Row {
id: selectorButtons
visible: !advancedMode
visible: root.suggestedFees.eip1559Enabled && !advancedMode
anchors.top: prioritytext.bottom
anchors.topMargin: Style.current.halfPadding
spacing: 11
@ -216,10 +216,11 @@ Item {
}
GasSelectorButton {
id: lowGasButton
buttonGroup: gasGroup
text: qsTr("Low")
price: {
if (!isEIP1559Enabled) return gasPrice;
if (!root.suggestedFees.eip1559Enabled) return root.suggestedFees.gasPrice;
return formatDec(root.suggestedFees.maxFeePerGasL, 6)
}
gasLimit: inputGasLimit ? inputGasLimit.text : ""
@ -227,7 +228,7 @@ Item {
getFiatValue: root.getFiatValue
defaultCurrency: root.defaultCurrency
onChecked: {
if (isEIP1559Enabled){
if (root.suggestedFees.eip1559Enabled){
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasL, 2);
} else {
@ -240,14 +241,13 @@ Item {
GasSelectorButton {
id: optimalGasButton
buttonGroup: gasGroup
checkedByDefault: true
//% "Optimal"
text: qsTrId("optimal")
price: {
if (!isEIP1559Enabled) {
if (!root.suggestedFees.eip1559Enabled) {
// Setting the gas price field here because the binding didn't work
inputGasPrice.text = root.gasPrice
return root.gasPrice
inputGasPrice.text = root.suggestedFees.gasPrice
return root.suggestedFees.gasPrice
}
return formatDec(root.suggestedFees.maxFeePerGasM, 6)
@ -257,11 +257,11 @@ Item {
getFiatValue: root.getFiatValue
defaultCurrency: root.defaultCurrency
onChecked: {
if (isEIP1559Enabled){
if (root.suggestedFees.eip1559Enabled){
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasM, 2);
} else {
inputGasPrice.text = root.gasPrice
inputGasPrice.text = root.suggestedFees.gasPrice
}
root.updateGasEthValue()
root.checkLimits()
@ -269,10 +269,11 @@ Item {
}
GasSelectorButton {
id: highGasButton
buttonGroup: gasGroup
text: qsTr("High")
price: {
if (!isEIP1559Enabled) return gasPrice;
if (!root.suggestedFees.eip1559Enabled) return root.suggestedFees.gasPrice;
return formatDec(root.suggestedFees.maxFeePerGasH,6);
}
gasLimit: inputGasLimit ? inputGasLimit.text : ""
@ -280,7 +281,7 @@ Item {
getFiatValue: root.getFiatValue
defaultCurrency: root.defaultCurrency
onChecked: {
if (isEIP1559Enabled){
if (root.suggestedFees.eip1559Enabled){
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasH, 2);
} else {
@ -296,7 +297,7 @@ Item {
id: advancedModeItemGroup
anchors.top: prioritytext.bottom
anchors.topMargin: 14
visible: root.advancedMode
visible: !root.suggestedFees.eip1559Enabled || root.advancedMode
width: parent.width
height: childrenRect.height
@ -309,7 +310,7 @@ Item {
customHeight: 56
anchors.top: parent.top
anchors.left: parent.left
anchors.right: isEIP1559Enabled ? inputPerGasTipLimit.left : inputGasPrice.left
anchors.right: root.suggestedFees.eip1559Enabled ? inputPerGasTipLimit.left : inputGasPrice.left
anchors.rightMargin: Style.current.padding
placeholderText: "21000"
validator: IntValidator{
@ -333,7 +334,7 @@ Item {
anchors.right: inputGasPrice.left
anchors.rightMargin: Style.current.padding
anchors.left: undefined
visible: isEIP1559Enabled
visible: root.suggestedFees.eip1559Enabled
width: 125
customHeight: 56
text: formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
@ -350,7 +351,7 @@ Item {
color: Style.current.secondaryText
//% "Gwei"
text: qsTrId("gwei")
visible: isEIP1559Enabled
visible: root.suggestedFees.eip1559Enabled
anchors.top: parent.top
anchors.topMargin: 42
anchors.right: inputPerGasTipLimit.right
@ -405,6 +406,7 @@ Item {
StyledText {
id: maxPriorityFeeText
anchors.left: parent.left
visible: root.suggestedFees.eip1559Enabled
//% "Maximum priority fee: %1 ETH"
text: {
let v = selectedGasEthValue > 0.00009 ? selectedGasEthValue :
@ -420,6 +422,7 @@ Item {
StyledText {
id: maxPriorityFeeFiatText
text: root.maxFiatFees
visible: root.suggestedFees.eip1559Enabled
anchors.verticalCenter: maxPriorityFeeText.verticalCenter
anchors.left: maxPriorityFeeText.right
anchors.leftMargin: 6
@ -432,6 +435,7 @@ Item {
id: maxPriorityFeeDetailsText
//% "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."
text: qsTrId("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
width: parent.width
anchors.top: maxPriorityFeeText.bottom
anchors.topMargin: Style.current.smallPadding

View File

@ -19,12 +19,14 @@ Column {
property double selectedAmount
property var selectedAsset
property double selectedGasEthValue
property var selectedNetwork
property bool isValid: false
onSelectedAccountChanged: validate()
onSelectedAmountChanged: validate()
onSelectedAssetChanged: validate()
onSelectedGasEthValueChanged: validate()
onSelectedNetworkChanged: validate()
function validate() {
let isValid = true
@ -36,8 +38,10 @@ Column {
if (selectedAsset && selectedAsset.symbol && selectedAsset.symbol.toUpperCase() === "ETH") {
gasTotal += selectedAmount
}
const currAcctGasAsset = Utils.findAssetBySymbol(selectedAccount.assets, "ETH")
if (currAcctGasAsset && currAcctGasAsset.value < gasTotal) {
const chainId = (selectedNetwork && selectedNetwork.chainId) || Global.currentChainId
const currAcctGasAsset = Utils.findAssetByChainAndSymbol(chainId, selectedAccount.assets, "ETH")
if (currAcctGasAsset && currAcctGasAsset.totalBalance < gasTotal) {
isValid = false
}
root.isValid = isValid

View File

@ -20,6 +20,7 @@ Rectangle {
property var getGasEthValue: function () {}
property var getFiatValue: function () {}
property alias gasRadioBtn: gasRadioBtn
function formatDec(num, dec){
return Math.round((num + Number.EPSILON) * Math.pow(10, dec)) / Math.pow(10, dec)

View File

@ -12,6 +12,7 @@ Column {
visible: !isValid
spacing: 5
property int chainId
property var account
property double amount
property var asset
@ -27,7 +28,7 @@ Column {
if (!(account && account.assets && asset && amount >= 0)) {
return root.isValid
}
const currAcctAsset = Utils.findAssetBySymbol(account.assets, asset.symbol)
const currAcctAsset = Utils.findAssetByChainAndSymbol(root.chainId, account.assets, asset.symbol)
if (currAcctAsset && currAcctAsset.value < amount) {
isValid = false

View File

@ -39,32 +39,41 @@ StatusModal {
function sendTransaction() {
stack.currentGroup.isPending = true
let success = false
if(advancedHeader.assetSelector.selectedAsset.address === "" || advancedHeader.assetSelector.selectedAsset.address === Constants.zeroAddress){
success = popup.store.transferEth(
advancedHeader.accountSelector.selectedAccount.address,
advancedHeader.recipientSelector.selectedRecipient.address,
advancedHeader.amountToSendInput.text,
gasSelector.selectedGasLimit,
gasSelector.isEIP1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword,
stack.uuid)
} else {
success = popup.store.transferTokens(
advancedHeader.accountSelector.selectedAccount.address,
advancedHeader.recipientSelector.selectedRecipient.address,
advancedHeader.assetSelector.selectedAsset.address,
advancedHeader.amountToSendInput.text,
gasSelector.selectedGasLimit,
gasSelector.isEIP1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword,
stack.uuid)
}
success = popup.store.transfer(
advancedHeader.accountSelector.selectedAccount.address,
advancedHeader.recipientSelector.selectedRecipient.address,
advancedHeader.assetSelector.selectedAsset.symbol,
advancedHeader.amountToSendInput.text,
gasSelector.selectedGasLimit,
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword,
networkSelector.selectedNetwork.chainId || Global.currentChainId,
stack.uuid,
gasSelector.suggestedFees.eip1559Enabled,
)
}
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
if (!popup.store.isMultiNetworkEnabled) {
return
}
networkSelector.suggestedRoutes = popup.store.suggestedRoutes(
advancedHeader.accountSelector.selectedAccount.address, advancedHeader.amountToSendInput.text, advancedHeader.assetSelector.selectedAsset.symbol
)
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
}
})
width: 556
// To-Do as per design once the account selector become floating the heigth can be as defined in design as 595
height: 670
@ -81,13 +90,22 @@ StatusModal {
advancedHeader.recipientSelector.selectedType = RecipientSelector.Type.Contact
advancedHeader.recipientSelector.readOnly = true
advancedHeader.recipientSelector.selectedRecipient = popup.preSelectedRecipient
}
if(popup.preSelectedAccount) {
advancedHeader.accountSelector.selectedAccount = popup.preSelectedAccount
}
}
if (popup.store.isMultiNetworkEnabled) {
popup.recalculateRoutesAndFees()
} else {
gasSelector.suggestedFees = popup.store.suggestedFees(Global.currentChainId)
gasSelector.checkOptimal()
}
}
advancedHeaderComponent: SendModalHeader {
store: popup.store
contactsStore: popup.contactsStore
@ -95,6 +113,18 @@ StatusModal {
if(popup.contentItem.currentGroup.isValid)
gasSelector.estimateGas()
}
onAssetChanged: function() {
popup.recalculateRoutesAndFees()
}
onSelectedAccountChanged: function() {
popup.recalculateRoutesAndFees()
}
onAmountToSendChanged: function() {
popup.recalculateRoutesAndFees()
}
}
contentItem: TransactionStackView {
@ -115,7 +145,7 @@ StatusModal {
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
contentHeight: addressSelector.height + networkAndFeesSelector.height + gasSelector.height + gasValidator.height
contentHeight: addressSelector.height + networkSelector.height + gasSelector.height + gasValidator.height
clip: true
TabAddressSelectorView {
@ -130,45 +160,45 @@ StatusModal {
}
}
TabNetworkAndFees {
id: networkAndFeesSelector
NetworkSelector {
id: networkSelector
anchors.top: addressSelector.bottom
anchors.right: parent.right
anchors.left: parent.left
visible: popup.store.isMultiNetworkEnabled
onNetworkChanged: function(chainId) {
gasSelector.suggestedFees = popup.store.suggestedFees(chainId)
}
}
GasSelector {
id: gasSelector
anchors.top: networkAndFeesSelector.visible ? networkAndFeesSelector.bottom : addressSelector.bottom
gasPrice: parseFloat(popup.store.gasPrice)
anchors.top: networkSelector.bottom
getGasEthValue: popup.store.getGasEthValue
getFiatValue: popup.store.getFiatValue
defaultCurrency: popup.store.currentCurrency
isEIP1559Enabled: popup.store.isEIP1559Enabled()
suggestedFees: popup.store.suggestedFees()
visible: !popup.store.isMultiNetworkEnabled
width: stack.width
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
if (!(advancedHeader.accountSelector.selectedAccount && advancedHeader.accountSelector.selectedAccount.address &&
advancedHeader.recipientSelector.selectedRecipient && advancedHeader.recipientSelector.selectedRecipient.address &&
advancedHeader.assetSelector.selectedAsset && advancedHeader.assetSelector.selectedAsset.address &&
advancedHeader.amountToSendInput.text)) {
advancedHeader.recipientSelector.selectedRecipient && advancedHeader.recipientSelector.selectedRecipient.address &&
advancedHeader.assetSelector.selectedAsset && advancedHeader.assetSelector.selectedAsset.symbol &&
advancedHeader.amountToSendInput.text)) {
selectedGasLimit = 250000
defaultGasLimit = selectedGasLimit
return
}
let gasEstimate = JSON.parse(popup.store.estimateGas(
advancedHeader.accountSelector.selectedAccount.address,
advancedHeader.recipientSelector.selectedRecipient.address,
advancedHeader.assetSelector.selectedAsset.address,
advancedHeader.amountToSendInput.text,
""))
advancedHeader.accountSelector.selectedAccount.address,
advancedHeader.recipientSelector.selectedRecipient.address,
advancedHeader.assetSelector.selectedAsset.symbol,
advancedHeader.amountToSendInput.text,
networkSelector.selectedNetwork.chainId || Global.currentChainId,
""))
if (!gasEstimate.success) {
//% "Error estimating gas: %1"
console.warn(qsTrId("error-estimating-gas---1").arg(gasEstimate.error.message))
return
@ -178,6 +208,7 @@ StatusModal {
defaultGasLimit = selectedGasLimit
})
}
GasValidator {
id: gasValidator
anchors.top: gasSelector.bottom
@ -186,6 +217,7 @@ StatusModal {
: parseFloat(advancedHeader.amountToSendInput.text)
selectedAsset: advancedHeader.assetSelector.selectedAsset
selectedGasEthValue: gasSelector.selectedGasEthValue
selectedNetwork: networkSelector.selectedNetwork
}
}
}
@ -217,7 +249,7 @@ StatusModal {
return popup.sendTransaction()
}
if(gasSelector.isEIP1559Enabled && popup.contentItem.currentGroup === group1 && gasSelector.advancedMode){
if(gasSelector.suggestedFees.eip1559Enabled && popup.contentItem.currentGroup === group1 && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.suggestedFees.baseFee,
@ -277,7 +309,7 @@ StatusModal {
let url = `${popup.store.getEtherscanLink()}/${response.result}`
Global.displayToastMessage(qsTr("Transaction pending..."),
"",
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,

View File

@ -33,37 +33,27 @@ StatusModal {
property bool isARequest: false
property string msgId: ""
property string trxData: ""
property int chainId
property alias transactionSigner: transactionSigner
property var sendTransaction: function() {
stack.currentGroup.isPending = true
let success = false
if(root.selectedAsset.address === "" || root.selectedAsset.address === Constants.zeroAddress){
success = root.store.transferEth(
selectFromAccount.selectedAccount.address,
selectRecipient.selectedRecipient.address,
root.selectedAmount,
gasSelector.selectedGasLimit,
gasSelector.isEIP1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword,
stack.uuid)
} else {
success = root.store.transferTokens(
selectFromAccount.selectedAccount.address,
selectRecipient.selectedRecipient.address,
root.selectedAsset.address,
root.selectedAmount,
gasSelector.selectedGasLimit,
gasSelector.isEIP1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword,
stack.uuid)
}
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"
@ -85,6 +75,11 @@ StatusModal {
stack.pop(groupPreview, StackView.Immediate)
}
onOpened: {
gasSelector.suggestedFees = root.store.suggestedFees(root.chainId)
gasSelector.checkOptimal()
}
contentItem: Item {
width: root.width
height: childrenRect.height
@ -127,6 +122,7 @@ StatusModal {
//% "Choose account"
label: qsTrId("choose-account")
showBalanceForAssetSymbol: root.selectedAsset.symbol
chainId: root.chainId
minRequiredAssetBalance: parseFloat(root.selectedAmount)
onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
}
@ -152,18 +148,15 @@ StatusModal {
GasSelector {
id: gasSelector
anchors.topMargin: Style.current.padding
gasPrice: parseFloat(root.store.gasPrice)
getGasEthValue: root.store.getGasEthValue
getFiatValue: root.store.getFiatValue
defaultCurrency: root.store.currentCurrency
isEIP1559Enabled: root.store.isEIP1559Enabled()
suggestedFees: root.store.suggestedFees()
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.address &&
root.selectedAsset && root.selectedAsset.symbol &&
root.selectedAmount)) {
selectedGasLimit = 250000
defaultGasLimit = selectedGasLimit
@ -173,9 +166,11 @@ StatusModal {
let gasEstimate = JSON.parse(root.store.estimateGas(
selectFromAccount.selectedAccount.address,
selectRecipient.selectedRecipient.address,
root.selectedAsset.address,
root.selectedAsset.symbol,
root.selectedAmount,
trxData))
root.chainId,
trxData
))
if (!gasEstimate.success) {
let message = qsTr("Error estimating gas: %1").arg(gasEstimate.error.message)
@ -235,6 +230,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
account: selectFromAccount.selectedAccount
amount: !!root.selectedAmount ? parseFloat(root.selectedAmount) : 0.0
chainId: root.chainId
asset: root.selectedAsset
}
GasValidator {
@ -297,13 +293,13 @@ StatusModal {
if (validity.isValid && !validity.isPending) {
if (stack.isLastGroup) {
return root.sendTransaction(gasSelector.selectedGasLimit,
gasSelector.isEIP1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword)
}
if(gasSelector.isEIP1559Enabled && stack.currentGroup === groupSelectGas && gasSelector.advancedMode){
if(gasSelector.suggestedFees.eip1559Enabled && stack.currentGroup === groupSelectGas && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.suggestedFees.baseFee,
@ -366,7 +362,7 @@ StatusModal {
// Refactor this
let url = "" //`${walletModel.utilsView.etherscanLink}/${response.result}`
Global.displayToastMessage(qsTr("Transaction pending..."),
"",
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,

View File

@ -20,6 +20,7 @@ ModalPopup {
property var contactsStore
property string ensUsername
property int chainId
readonly property var asset: {"name": "Ethereum", "symbol": "ETH"}
title: qsTr("Contract interaction")
@ -35,10 +36,11 @@ ModalPopup {
let responseStr = root.ensUsernamesStore.setPubKey(root.ensUsername,
selectFromAccount.selectedAccount.address,
gasSelector.selectedGasLimit,
gasSelector.isEIP1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword)
transactionSigner.enteredPassword,
gasSelector.suggestedFees.eip1559Enabled)
let response = JSON.parse(responseStr)
if (!response.success) {
@ -60,6 +62,11 @@ ModalPopup {
}
}
onOpened: {
gasSelector.suggestedFees = root.ensUsernamesStore.suggestedFees(root.chainId)
gasSelector.checkOptimal()
}
property MessageDialog sendingError: MessageDialog {
id: sendingError
//% "Error sending the transaction"
@ -96,6 +103,7 @@ ModalPopup {
}
currency: root.ensUsernamesStore.getCurrentCurrency()
width: stack.width
chainId: root.chainId
//% "Choose account"
label: qsTrId("choose-account")
showBalanceForAssetSymbol: "ETH"
@ -116,12 +124,9 @@ ModalPopup {
visible: true
anchors.top: selectFromAccount.bottom
anchors.topMargin: Style.current.padding
gasPrice: parseFloat(root.ensUsernamesStore.gasPrice)
getGasEthValue: root.ensUsernamesStore.getGasEthValue
getFiatValue: root.ensUsernamesStore.getFiatValue
defaultCurrency: root.ensUsernamesStore.getCurrentCurrency()
isEIP1559Enabled: root.ensUsernamesStore.isEIP1559Enabled()
suggestedFees: root.ensUsernamesStore.suggestedFees()
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount);
@ -217,7 +222,7 @@ ModalPopup {
return root.sendTransaction()
}
if(gasSelector.isEIP1559Enabled && stack.currentGroup === group3 && gasSelector.advancedMode){
if(gasSelector.suggestedFees.eip1559Enabled && stack.currentGroup === group3 && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.suggestedFees.baseFee,

View File

@ -22,13 +22,13 @@ ModalPopup {
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){ return ""; })
property var onSendTransaction: (function(userAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled){ return ""; })
property var onSuccess: (function(){})
property var asyncGasEstimateTarget
Component.onCompleted: {
root.stickersStore.fetchGasPrice();
gasSelector.estimateGas();
}
@ -56,10 +56,11 @@ ModalPopup {
function sendTransaction() {
let responseStr = onSendTransaction(selectFromAccount.selectedAccount.address,
gasSelector.selectedGasLimit,
gasSelector.isEIP1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword);
transactionSigner.enteredPassword,
gasSelector.suggestedFees.eip1559Enabled);
let response = JSON.parse(responseStr)
if (!response.success) {
@ -76,6 +77,11 @@ ModalPopup {
root.close();
}
onOpened: {
gasSelector.suggestedFees = root.store.suggestedFees(root.chainId)
gasSelector.checkOptimal()
}
TransactionStackView {
id: stack
height: parent.height
@ -111,6 +117,7 @@ ModalPopup {
label: qsTrId("choose-account")
showBalanceForAssetSymbol: root.asset.symbol
minRequiredAssetBalance: root.assetPrice
chainId: root.chainId
onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
}
RecipientSelector {
@ -134,12 +141,9 @@ ModalPopup {
id: gasSelector
anchors.top: selectFromAccount.bottom
anchors.topMargin: Style.current.padding
gasPrice: parseFloat(root.stickersStore.gasPrice)
getGasEthValue: root.stickersStore.getGasEthValue
getFiatValue: root.stickersStore.getFiatValue
defaultCurrency: root.stickersStore.getCurrentCurrency()
isEIP1559Enabled: root.store.isEIP1559Enabled()
suggestedFees: root.store.suggestedFees()
width: stack.width
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
@ -243,7 +247,7 @@ ModalPopup {
return root.sendTransaction()
}
if(gasSelector.isEIP1559Enabled && stack.currentGroup === group2 && gasSelector.advancedMode){
if(gasSelector.suggestedFees.eip1559Enabled && stack.currentGroup === group2 && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.suggestedFees.baseFee,

View File

@ -107,18 +107,20 @@ Item {
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)
}
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password) {
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
return root.store.stickersStore.buy(packId,
selectedAddress,
gasLimit,
gasPrice,
tipLimit,
overallLimit,
password)
password,
eip1559Enabled)
}
onClosed: {
destroy()

View File

@ -68,18 +68,20 @@ ModalPopup {
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)
}
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password) {
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password, eip1559Enabled) {
return root.store.stickersStore.buy(packId,
selectedAddress,
gasLimit,
gasPrice,
tipLimit,
overallLimit,
password)
password,
eip1559Enabled)
}
onClosed: {
destroy()

View File

@ -0,0 +1,130 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtQuick.Dialogs 1.3
import utils 1.0
import shared.stores 1.0
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import "../panels"
import "../controls"
import "../views"
Item {
id: root
height: visible ? stackLayout.height + 2* Style.current.xlPadding : 0
signal networkChanged(int chainId)
property var suggestedRoutes: ""
property var selectedNetwork: ""
StackLayout {
id: stackLayout
anchors.top: parent.top
anchors.topMargin: Style.current.xlPadding
height: simpleLayout.height
width: parent.width
currentIndex: 0
ColumnLayout {
id: simpleLayout
Layout.fillWidth: true
spacing: 24
Rectangle {
id: networksRect
radius: 13
color: Theme.palette.indirectColor1
Layout.fillWidth: true
Layout.preferredHeight: layout.height + 24
ColumnLayout {
id: layout
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 16
spacing: 20
RowLayout {
spacing: 10
StatusRoundIcon {
Layout.alignment: Qt.AlignTop
radius: 8
icon.name: "flash"
}
ColumnLayout {
StatusBaseText {
Layout.maximumWidth: 410
font.pixelSize: 15
font.weight: Font.Medium
color: Theme.palette.directColor1
//% "Networks"
text: qsTr("Networks")
wrapMode: Text.WordWrap
}
StatusBaseText {
Layout.maximumWidth: 410
font.pixelSize: 15
color: Theme.palette.baseColor1
text: qsTr("Choose a network to use for the transaction")
wrapMode: Text.WordWrap
}
}
}
StatusBaseText {
visible: suggestedRoutes.length === 0
font.pixelSize: 15
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: Theme.palette.dangerColor1
text: qsTr("No networks available")
wrapMode: Text.WordWrap
}
Item {
Layout.fillWidth: true
height: 50
ScrollView {
width: parent.width
contentWidth: row.width
contentHeight: row.height + 10
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
ScrollBar.horizontal.policy: ScrollBar.AlwaysOn
clip: true
Row {
id: row
spacing: 16
Repeater {
id: repeater
model: suggestedRoutes
StatusListItem {
id: item
implicitWidth: 126
title: modelData.chainName
subTitle: ""
image.source: Style.png("networks/" + modelData.chainName.toLowerCase())
image.width: 32
image.height: 32
leftPadding: 5
rightPadding: 5
color: "transparent"
border.color: Style.current.primary
border.width: root.selectedNetwork.chainId === modelData.chainId ? 1 : 0
onClicked: {
root.selectedNetwork = modelData
root.networkChanged(modelData.chainId)
}
}
}
}
}
}
}
}
}
}
}

View File

@ -27,9 +27,13 @@ Rectangle {
property var estimateGas: function() {}
property bool isReady: amountToSendInput.valid && !amountToSendInput.pending && recipientSelector.isValid && !recipientSelector.isPending
signal assetChanged()
signal selectedAccountChanged()
signal amountToSendChanged()
QtObject {
id: _internal
property string maxFiatBalance: Utils.stripTrailingZeros(parseFloat(assetSelector.selectedAsset.balance).toFixed(4))
property string maxFiatBalance: Utils.stripTrailingZeros(parseFloat(assetSelector.selectedAsset.totalBalance).toFixed(4))
//% "Please enter a valid amount"
property string sendAmountInputErrorMessage: qsTr("Please enter a valid amount")
//% "Max:"
@ -86,6 +90,7 @@ Rectangle {
}
})
if (isValid) { estimateGas() }
header.selectedAccountChanged()
}
showAccountDetails: false
selectField.select.height: 32
@ -103,7 +108,7 @@ Rectangle {
}
StatusListItemTag {
//% "No balances active"
title: assetSelector.selectedAsset.balance > 0 ? _internal.maxString + (assetSelector.selectedAsset ? _internal.maxFiatBalance : "0.00") : qsTr("No balances active")
title: assetSelector.selectedAsset.totalBalance > 0 ? _internal.maxString + (assetSelector.selectedAsset ? _internal.maxFiatBalance : "0.00") : qsTr("No balances active")
closeButtonVisible: false
titleText.font.pixelSize: 12
height: 22
@ -139,6 +144,7 @@ Rectangle {
txtFiatBalance.text = header.store.getFiatValue(amount, assetSelector.selectedAsset.symbol, header.store.currentCurrency)
}
estimateGas()
header.amountToSendChanged()
}
}
StatusAssetSelector {
@ -161,6 +167,7 @@ Rectangle {
}
txtFiatBalance.text = header.store.getFiatValue(amountToSendInput.text, assetSelector.selectedAsset.symbol, header.store.currentCurrency)
estimateGas()
header.assetChanged()
}
}
}

View File

@ -1,208 +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 shared.stores 1.0
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import "../panels"
import "../controls"
import "../views"
Item {
id: root
height: visible ? stackLayout.height + modeSelectionTabBar.height + 2*Style.current.xlPadding: 0
signal contactSelected(string address, int type)
StatusSwitchTabBar {
id: modeSelectionTabBar
anchors.horizontalCenter: parent.horizontalCenter
StatusSwitchTabButton {
//% "Simple"
text: qsTr("Simple")
}
StatusSwitchTabButton {
//% "Advanced"
text: qsTr("Advanced")
}
StatusSwitchTabButton {
//% "Custom"
text: qsTr("Custom")
}
}
StackLayout {
id: stackLayout
anchors.top: modeSelectionTabBar.bottom
anchors.topMargin: Style.current.xlPadding
height: simpleLayout.height
width: parent.width
currentIndex: modeSelectionTabBar.currentIndex
ColumnLayout {
id: simpleLayout
Layout.fillWidth: true
spacing: 24
// To-do networks depends on multi networks and fee suggestions not available yet
Rectangle {
id: networksRect
radius: 13
color: Theme.palette.indirectColor1
Layout.fillWidth: true
Layout.preferredHeight: layout.height + 24
ColumnLayout {
id: layout
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 16
spacing: 20
RowLayout {
spacing: 10
StatusRoundIcon {
Layout.alignment: Qt.AlignTop
radius: 8
icon.name: "flash"
}
ColumnLayout {
StatusBaseText {
Layout.maximumWidth: 410
font.pixelSize: 15
font.weight: Font.Medium
color: Theme.palette.directColor1
//% "Networks"
text: qsTr("Networks")
wrapMode: Text.WordWrap
}
StatusBaseText {
Layout.maximumWidth: 410
font.pixelSize: 15
color: Theme.palette.baseColor1
//% "The networks where the receipient will receive tokens. Amounts calculated automatically for the lowest cost."
text: qsTr("The networks where the receipient will receive tokens. Amounts calculated automatically for the lowest cost.")
wrapMode: Text.WordWrap
}
}
}
RowLayout {
spacing: 16
Layout.leftMargin: 40
Repeater {
model: 3
StatusListItem {
implicitWidth: 126
title: "PlaceHolder" + index
subTitle: ""
icon.isLetterIdenticon: true
icon.width: 32
icon.height: 32
leftPadding: 0
rightPadding: 0
color: "transparent"
}
}
}
}
}
Rectangle {
id: feesRect
radius: 13
color: Theme.palette.indirectColor1
Layout.fillWidth: true
Layout.preferredHeight: feesLayout.height + 32
RowLayout {
id: feesLayout
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 16
spacing: 10
StatusRoundIcon {
Layout.alignment: Qt.AlignTop
radius: 8
icon.name: "fees"
}
ColumnLayout {
spacing: 12
StatusBaseText {
Layout.maximumWidth: 410
font.pixelSize: 15
font.weight: Font.Medium
color: Theme.palette.directColor1
//% "Fees"
text: qsTr("Fees")
wrapMode: Text.WordWrap
}
RowLayout {
spacing: 16
Repeater {
model: 3
delegate:
RadioDelegate {
id: control
checked: index === 0
contentItem.visible: false
indicator.visible: false
background: Rectangle {
implicitWidth: 128
implicitHeight: 78
radius: 8
color: control.checked ? Theme.palette.indirectColor1: Theme.palette.baseColor4
border.width: control.checked
border.color: Theme.palette.primaryColor2
ColumnLayout {
width: parent.width
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 8
StatusBaseText {
font.pixelSize: 15
color: Theme.palette.baseColor1
//% "Slow"
text: qsTr("Slow")
wrapMode: Text.WordWrap
}
StatusBaseText {
font.pixelSize: 13
color: Theme.palette.baseColor1
text: "0.24 USD"
wrapMode: Text.WordWrap
}
StatusBaseText {
font.pixelSize: 13
color: Theme.palette.baseColor1
text: "~15 minutes"
wrapMode: Text.WordWrap
}
}
}
}
}
}
}
}
}
}
StatusBaseText {
Layout.alignment: Qt.AlignCenter
font.pixelSize: 15
color: Theme.palette.baseColor1
text: "Not Implemented"
}
StatusBaseText {
Layout.alignment: Qt.AlignCenter
font.pixelSize: 15
color: Theme.palette.baseColor1
text: "Not Implemented"
}
}
}

View File

@ -105,7 +105,7 @@ Item {
contactsStore: root.contactsStore
msgId: messageId
isARequest: true
onOpened: root.store.fetchGasPrice()
chainId: root.store.getChainIdForChat()
onClosed: destroy()
onOpenGasEstimateErrorPopup: {
gasEstimateErrorPopup.confirmationText = message + qsTrId("--the-transaction-will-probably-fail-");

View File

@ -244,7 +244,7 @@ Item {
selectedRecipient: root.selectedRecipient
selectedFiatAmount: root.fiatValue
selectedType: RecipientSelector.Type.Contact
onOpened: root.store.fetchGasPrice()
chainId: root.store.getChainIdForChat()
onClosed: destroy()
msgId: messageId
}

View File

@ -16,8 +16,9 @@ QtObject {
property var privacyModuleInst
property bool profilePopupOpened: false
property string currentNetworkId: ""
property bool networkGuarded: root.currentNetworkId === Constants.networkMainnet ||
(root.currentNetworkId === Constants.networkRopsten && localAccountSensitiveSettings.stickersEnsRopsten)
property int currentChainId: 0
property bool networkGuarded: localAccountSensitiveSettings.isMultiNetworkEnabled || (root.currentNetworkId === Constants.networkMainnet ||
(root.currentNetworkId === Constants.networkRopsten && localAccountSensitiveSettings.stickersEnsRopsten))
signal openImagePopup(var image, var contextMenu)
signal openLinkInBrowser(string link)

View File

@ -387,17 +387,17 @@ QtObject {
return qsTrId("-1d").arg(diffDay)
}
function findAssetBySymbol(assets, symbolToFind) {
function findAssetByChainAndSymbol(chainIdToFind, assets, symbolToFind) {
for(var i=0; i<assets.rowCount(); i++) {
const symbol = assets.rowData(i, "symbol")
if (symbol.toLowerCase() === symbolToFind.toLowerCase()) {
if (symbol.toLowerCase() === symbolToFind.toLowerCase() && assets.hasChain(i, parseInt(chainIdToFind))) {
return {
name: assets.rowData(i, "name"),
symbol,
value: assets.rowData(i, "balance"),
fiatBalanceDisplay: assets.rowData(i, "currencyBalance"),
address: assets.rowData(i, "address"),
fiatBalance: assets.rowData(i, "currencyBalance")
totalBalance: assets.rowData(i, "totalBalance"),
totalCurrencyBalance: assets.rowData(i, "totalCurrencyBalance"),
fiatBalance: assets.rowData(i, "totalCurrencyBalance"),
chainId: chainIdToFind,
}
}
}

@ -1 +1 @@
Subproject commit 06d52222add28c4d65e3a8816881f1c843cd0787
Subproject commit 7fa256afd2011f488bfb08bfc660c1499fe1f8d2

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit c3b0582cc93cbfda03623df8b4f6875552335909
Subproject commit 8c0f230644474408962b38f39a84cc4358c8b8c4