mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-24 20:48:50 +00:00
refactor(@desktop/settings-ens-usernames): ens usernames module added and corresponding ui updated
This commit is contained in:
parent
bd2bb8952a
commit
69fc5bec5e
@ -30,6 +30,7 @@ import ../../app_service/service/saved_address/service as saved_address_service
|
||||
import ../../app_service/service/devices/service as devices_service
|
||||
import ../../app_service/service/mailservers/service as mailservers_service
|
||||
import ../../app_service/service/gif/service as gif_service
|
||||
import ../../app_service/service/ens/service as ens_service
|
||||
|
||||
import ../modules/startup/module as startup_module
|
||||
import ../modules/main/module as main_module
|
||||
@ -82,6 +83,7 @@ type
|
||||
mailserversService: mailservers_service.Service
|
||||
nodeService: node_service.Service
|
||||
gifService: gif_service.Service
|
||||
ensService: ens_service.Service
|
||||
|
||||
# Modules
|
||||
startupModule: startup_module.AccessInterface
|
||||
@ -168,6 +170,9 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
||||
result.nodeService = node_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
||||
result.settingsService)
|
||||
result.gifService = gif_service.newService(result.settingsService)
|
||||
result.ensService = ens_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
||||
result.settingsService, result.walletAccountService, result.transactionService, result.ethService,
|
||||
result.networkService, result.tokenService)
|
||||
|
||||
# Modules
|
||||
result.startupModule = startup_module.newModule[AppController](
|
||||
@ -206,6 +211,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
||||
result.mailserversService,
|
||||
result.nodeService,
|
||||
result.gifService,
|
||||
result.ensService
|
||||
)
|
||||
|
||||
# Do connections
|
||||
@ -252,6 +258,7 @@ proc delete*(self: AppController) =
|
||||
self.privacyService.delete
|
||||
self.profileService.delete
|
||||
self.generalService.delete
|
||||
self.ensService.delete
|
||||
|
||||
proc startupDidLoad*(self: AppController) =
|
||||
singletonInstance.engine.setRootContextProperty("localAppSettings", self.localAppSettingsVariant)
|
||||
@ -294,6 +301,7 @@ proc load(self: AppController) =
|
||||
self.aboutService.init()
|
||||
self.devicesService.init()
|
||||
self.mailserversService.init()
|
||||
self.ensService.init()
|
||||
|
||||
let pubKey = self.settingsService.getPublicKey()
|
||||
singletonInstance.localAccountSensitiveSettings.setFileName(pubKey)
|
||||
|
@ -43,6 +43,7 @@ import ../../../app_service/service/node_configuration/service_interface as node
|
||||
import ../../../app_service/service/devices/service as devices_service
|
||||
import ../../../app_service/service/mailservers/service as mailservers_service
|
||||
import ../../../app_service/service/gif/service as gif_service
|
||||
import ../../../app_service/service/ens/service as ens_service
|
||||
|
||||
|
||||
import ../../core/eventemitter
|
||||
@ -96,6 +97,7 @@ proc newModule*[T](
|
||||
mailserversService: mailservers_service.Service,
|
||||
nodeService: node_service.Service,
|
||||
gifService: gif_service.Service,
|
||||
ensService: ens_service.Service
|
||||
): Module[T] =
|
||||
result = Module[T]()
|
||||
result.delegate = delegate
|
||||
@ -128,7 +130,7 @@ proc newModule*[T](
|
||||
dappPermissionsService, providerService)
|
||||
result.profileSectionModule = profile_section_module.newModule(result, events, accountsService, settingsService,
|
||||
profileService, contactsService, aboutService, languageService, privacyService, nodeConfigurationService,
|
||||
devicesService, mailserversService, chatService)
|
||||
devicesService, mailserversService, chatService, ensService, walletAccountService)
|
||||
result.stickersModule = stickers_module.newModule(result, events, stickersService)
|
||||
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
|
||||
messageService)
|
||||
|
@ -0,0 +1,129 @@
|
||||
import Tables, chronicles
|
||||
import controller_interface
|
||||
import io_interface
|
||||
|
||||
import ../../../../global/global_singleton
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../../app_service/service/settings/service_interface as settings_service
|
||||
import ../../../../../app_service/service/ens/service as ens_service
|
||||
import ../../../../../app_service/service/wallet_account/service_interface as wallet_account_service
|
||||
|
||||
export controller_interface
|
||||
|
||||
logScope:
|
||||
topics = "profile-section-ens-usernames-module-controller"
|
||||
|
||||
type
|
||||
Controller* = ref object of controller_interface.AccessInterface
|
||||
delegate: io_interface.AccessInterface
|
||||
events: EventEmitter
|
||||
settingsService: settings_service.ServiceInterface
|
||||
ensService: ens_service.Service
|
||||
walletAccountService: wallet_account_service.ServiceInterface
|
||||
|
||||
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter,
|
||||
settingsService: settings_service.ServiceInterface, ensService: ens_service.Service,
|
||||
walletAccountService: wallet_account_service.ServiceInterface): Controller =
|
||||
result = Controller()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.settingsService = settingsService
|
||||
result.ensService = ensService
|
||||
result.walletAccountService = walletAccountService
|
||||
|
||||
method delete*(self: Controller) =
|
||||
discard
|
||||
|
||||
method init*(self: Controller) =
|
||||
self.events.on(SIGNAL_ENS_USERNAME_AVAILABILITY_CHECKED) do(e:Args):
|
||||
let args = EnsUsernameAvailabilityArgs(e)
|
||||
self.delegate.ensUsernameAvailabilityChecked(args.availabilityStatus)
|
||||
|
||||
self.events.on(SIGNAL_ENS_USERNAME_DETAILS_FETCHED) do(e:Args):
|
||||
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)
|
||||
|
||||
self.events.on(SIGNAL_ENS_TRANSACTION_REVERTED) do(e:Args):
|
||||
let args = EnsTransactionArgs(e)
|
||||
self.delegate.ensTransactionReverted(args.transactionType, args.ensUsername, args.transactionHash, args.revertReason)
|
||||
|
||||
method checkEnsUsernameAvailability*(self: Controller, desiredEnsUsername: string, statusDomain: bool) =
|
||||
self.ensService.checkEnsUsernameAvailability(desiredEnsUsername, statusDomain)
|
||||
|
||||
method getMyPendingEnsUsernames*(self: Controller): seq[string] =
|
||||
return self.ensService.getMyPendingEnsUsernames()
|
||||
|
||||
method getAllMyEnsUsernames*(self: Controller, includePendingEnsUsernames: bool): seq[string] =
|
||||
return self.ensService.getAllMyEnsUsernames(includePendingEnsUsernames)
|
||||
|
||||
method fetchDetailsForEnsUsername*(self: Controller, ensUsername: string) =
|
||||
self.ensService.fetchDetailsForEnsUsername(ensUsername)
|
||||
|
||||
method fetchGasPrice*(self: Controller) =
|
||||
self.ensService.fetchGasPrice()
|
||||
|
||||
method setPubKeyGasEstimate*(self: Controller, ensUsername: string, address: string): int =
|
||||
return self.ensService.setPubKeyGasEstimate(ensUsername, address)
|
||||
|
||||
method 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)
|
||||
|
||||
method getCurrentNetworkDetails*(self: Controller): Network =
|
||||
return self.settingsService.getCurrentNetworkDetails()
|
||||
|
||||
method getSigningPhrase*(self: Controller): string =
|
||||
return self.settingsService.getSigningPhrase()
|
||||
|
||||
method saveNewEnsUsername*(self: Controller, ensUsername: string): bool =
|
||||
return self.settingsService.saveNewEnsUsername(ensUsername)
|
||||
|
||||
method getPreferredEnsUsername*(self: Controller): string =
|
||||
return self.settingsService.getPreferredName()
|
||||
|
||||
method releaseEnsEstimate*(self: Controller, ensUsername: string, address: string): int =
|
||||
return self.ensService.releaseEnsEstimate(ensUsername, address)
|
||||
|
||||
method release*(self: Controller, ensUsername: string, address: string, gas: string, gasPrice: string, password: string):
|
||||
string =
|
||||
return self.ensService.release(ensUsername, address, gas, gasPrice, password)
|
||||
|
||||
method setPreferredName*(self: Controller, preferredName: string) =
|
||||
if(self.settingsService.savePreferredName(preferredName)):
|
||||
singletonInstance.userProfile.setPreferredName(preferredName)
|
||||
else:
|
||||
info "an error occurred saving prefered ens username", methodName="setPreferredName"
|
||||
|
||||
method getEnsRegisteredAddress*(self: Controller): string =
|
||||
return self.ensService.getEnsRegisteredAddress()
|
||||
|
||||
method registerEnsGasEstimate*(self: Controller, ensUsername: string, address: string): int =
|
||||
return self.ensService.registerEnsGasEstimate(ensUsername, address)
|
||||
|
||||
method 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)
|
||||
|
||||
method getSNTBalance*(self: Controller): string =
|
||||
return self.ensService.getSNTBalance()
|
||||
|
||||
method getWalletDefaultAddress*(self: Controller): string =
|
||||
return self.walletAccountService.getWalletAccount(0).address
|
||||
|
||||
method getCurrentCurrency*(self: Controller): string =
|
||||
return self.settingsService.getCurrency()
|
||||
|
||||
method getPrice*(self: Controller, crypto: string, fiat: string): float64 =
|
||||
return self.walletAccountService.getPrice(crypto, fiat)
|
||||
|
||||
method getStatusToken*(self: Controller): string =
|
||||
return self.ensService.getStatusToken()
|
||||
|
@ -0,0 +1,80 @@
|
||||
import ../../../../../app_service/service/settings/dto/settings as settings_dto
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
## Abstract class for any input/interaction with this module.
|
||||
|
||||
method delete*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method init*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method checkEnsUsernameAvailability*(self: AccessInterface, desiredEnsUsername: string, statusDomain: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getMyPendingEnsUsernames*(self: AccessInterface): seq[string] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getAllMyEnsUsernames*(self: AccessInterface, includePendingEnsUsernames: bool): seq[string] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
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.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getCurrentNetworkDetails*(self: AccessInterface): Network {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getSigningPhrase*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method saveNewEnsUsername*(self: AccessInterface, ensUsername: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getPreferredEnsUsername*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method releaseEnsEstimate*(self: AccessInterface, ensUsername: string, address: string): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method release*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
password: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setPreferredName*(self: AccessInterface, preferredName: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getEnsRegisteredAddress*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method registerEnsGasEstimate*(self: AccessInterface, ensUsername: string, address: string): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method registerEns*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getSNTBalance*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getWalletDefaultAddress*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getCurrentCurrency*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getPrice*(self: AccessInterface, crypto: string, fiat: string): float64 {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getStatusToken*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
@ -0,0 +1,61 @@
|
||||
import NimQml, Tables, strformat
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
Id = UserRole + 1
|
||||
Name
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Model* = ref object of QAbstractListModel
|
||||
items: seq[tuple[id: string, name: string]]
|
||||
|
||||
proc delete*(self: Model) =
|
||||
self.items = @[]
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc setup(self: Model) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc newModel*(): Model =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
|
||||
proc `$`*(self: Model): string =
|
||||
for i in 0 ..< self.items.len:
|
||||
result &= fmt"""
|
||||
[{i}]:(id: {self.items[i].id}, name: {self.items[i].name})
|
||||
"""
|
||||
|
||||
method rowCount(self: Model, index: QModelIndex = nil): int =
|
||||
return self.items.len
|
||||
|
||||
method roleNames(self: Model): Table[int, string] =
|
||||
{
|
||||
ModelRole.Id.int:"id",
|
||||
ModelRole.Name.int:"name",
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, 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.Id:
|
||||
result = newQVariant(item.id)
|
||||
of ModelRole.Name:
|
||||
result = newQVariant(item.name)
|
||||
|
||||
proc add*(self: Model, id: string, name: string) =
|
||||
let parentModelIndex = newQModelIndex()
|
||||
defer: parentModelIndex.delete
|
||||
|
||||
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
|
||||
self.items.add((id: id, name: name))
|
||||
self.endInsertRows()
|
@ -0,0 +1,11 @@
|
||||
# Defines how parent module accesses this module
|
||||
include ./private_interfaces/module_base_interface
|
||||
include ./private_interfaces/module_access_interface
|
||||
|
||||
# Defines how this module view communicates with this module
|
||||
include ./private_interfaces/module_view_delegate_interface
|
||||
|
||||
# Defines how this controller communicates with this module
|
||||
include ./private_interfaces/module_controller_delegate_interface
|
||||
|
||||
# Defines how submodules of this module communicate with this module
|
102
src/app/modules/main/profile_section/ens_usernames/model.nim
Normal file
102
src/app/modules/main/profile_section/ens_usernames/model.nim
Normal file
@ -0,0 +1,102 @@
|
||||
import NimQml, Tables
|
||||
|
||||
type Item* = object
|
||||
ensUsername*: string
|
||||
isPending*: bool
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
EnsUsername = UserRole + 1
|
||||
IsPending
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Model* = ref object of QAbstractListModel
|
||||
items: seq[Item]
|
||||
|
||||
proc delete(self: Model) =
|
||||
self.items = @[]
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc setup(self: Model) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc newModel*(): Model =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
|
||||
proc countChanged(self: Model) {.signal.}
|
||||
proc getCount(self: Model): int {.slot.} =
|
||||
self.items.len
|
||||
QtProperty[int] count:
|
||||
read = getCount
|
||||
notify = countChanged
|
||||
|
||||
method rowCount(self: Model, index: QModelIndex = nil): int =
|
||||
return self.items.len
|
||||
|
||||
method roleNames(self: Model): Table[int, string] =
|
||||
{
|
||||
ModelRole.EnsUsername.int:"ensUsername",
|
||||
ModelRole.IsPending.int:"isPending"
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, 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.EnsUsername:
|
||||
result = newQVariant(item.ensUsername)
|
||||
of ModelRole.IsPending:
|
||||
result = newQVariant(item.isPending)
|
||||
|
||||
proc findIndexForItemWithEnsUsername(self: Model, ensUsername: string): int =
|
||||
for i in 0 ..< self.items.len:
|
||||
if(self.items[i].ensUsername == ensUsername):
|
||||
return i
|
||||
return -1
|
||||
|
||||
proc containsEnsUsername*(self: Model, ensUsername: string): bool =
|
||||
return self.findIndexForItemWithEnsUsername(ensUsername) != -1
|
||||
|
||||
proc addItem*(self: Model, item: Item) =
|
||||
if(self.containsEnsUsername(item.ensUsername)):
|
||||
return
|
||||
|
||||
let parentModelIndex = newQModelIndex()
|
||||
defer: parentModelIndex.delete
|
||||
|
||||
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
|
||||
self.items.add(item)
|
||||
self.endInsertRows()
|
||||
self.countChanged()
|
||||
|
||||
proc removeItemByEnsUsername*(self: Model, ensUsername: string) =
|
||||
let index = self.findIndexForItemWithEnsUsername(ensUsername)
|
||||
if(index == -1):
|
||||
return
|
||||
|
||||
let parentModelIndex = newQModelIndex()
|
||||
defer: parentModelIndex.delete
|
||||
|
||||
self.beginRemoveRows(parentModelIndex, index, index)
|
||||
self.items.delete(index)
|
||||
self.endRemoveRows()
|
||||
self.countChanged()
|
||||
|
||||
proc updatePendingStatus*(self: Model, ensUsername: string, pendingStatus: bool) =
|
||||
let ind = self.findIndexForItemWithEnsUsername(ensUsername)
|
||||
if(ind == -1):
|
||||
return
|
||||
|
||||
self.items[ind].isPending = pendingStatus
|
||||
|
||||
let index = self.createIndex(ind, 0, nil)
|
||||
self.dataChanged(index, index, @[ModelRole.IsPending.int])
|
242
src/app/modules/main/profile_section/ens_usernames/module.nim
Normal file
242
src/app/modules/main/profile_section/ens_usernames/module.nim
Normal file
@ -0,0 +1,242 @@
|
||||
import NimQml, json, stint, strutils, strformat, parseutils, chronicles
|
||||
|
||||
import io_interface
|
||||
import ../io_interface as delegate_interface
|
||||
import view, controller, model
|
||||
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../../app_service/common/conversion as service_conversion
|
||||
import ../../../../../app_service/service/settings/service_interface as settings_service
|
||||
import ../../../../../app_service/service/ens/service as ens_service
|
||||
import ../../../../../app_service/service/ens/utils as ens_utils
|
||||
import ../../../../../app_service/service/wallet_account/service_interface as wallet_account_service
|
||||
|
||||
export io_interface
|
||||
|
||||
logScope:
|
||||
topics = "profile-section-ens-usernames-module"
|
||||
|
||||
include ../../../../../app_service/common/json_utils
|
||||
|
||||
type
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
delegate: delegate_interface.AccessInterface
|
||||
view: View
|
||||
viewVariant: QVariant
|
||||
controller: controller.AccessInterface
|
||||
moduleLoaded: bool
|
||||
|
||||
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter,
|
||||
settingsService: settings_service.ServiceInterface, ensService: ens_service.Service,
|
||||
walletAccountService: wallet_account_service.ServiceInterface): 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.moduleLoaded = false
|
||||
|
||||
method delete*(self: Module) =
|
||||
self.view.delete
|
||||
self.viewVariant.delete
|
||||
self.controller.delete
|
||||
|
||||
method load*(self: Module) =
|
||||
self.controller.init()
|
||||
|
||||
let signingPhrase = self.controller.getSigningPhrase()
|
||||
let network = self.controller.getCurrentNetworkDetails()
|
||||
var link = network.etherscanLink.replace("/address", "/tx")
|
||||
self.view.load(link, signingPhrase)
|
||||
|
||||
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:
|
||||
self.view.model().addItem(Item(ensUsername: u, isPending: false))
|
||||
# add pending ens usernames
|
||||
let pendingEnsUsernames = self.controller.getMyPendingEnsUsernames()
|
||||
for u in pendingEnsUsernames:
|
||||
self.view.model().addItem(Item(ensUsername: u, isPending: true))
|
||||
|
||||
self.moduleLoaded = true
|
||||
self.delegate.ensUsernamesModuleDidLoad()
|
||||
|
||||
method getModuleAsVariant*(self: Module): QVariant =
|
||||
return self.viewVariant
|
||||
|
||||
method checkEnsUsernameAvailability*(self: Module, desiredEnsUsername: string, statusDomain: bool) =
|
||||
self.controller.checkEnsUsernameAvailability(desiredEnsUsername, statusDomain)
|
||||
|
||||
method ensUsernameAvailabilityChecked*(self: Module, availabilityStatus: string) =
|
||||
self.view.sendUsernameAvailabilityCheckedSignal(availabilityStatus)
|
||||
|
||||
method numOfPendingEnsUsernames*(self: Module): int =
|
||||
return self.controller.getMyPendingEnsUsernames().len
|
||||
|
||||
method fetchDetailsForEnsUsername*(self: Module, ensUsername: string) =
|
||||
self.controller.fetchDetailsForEnsUsername(ensUsername)
|
||||
|
||||
method onDetailsForEnsUsername*(self: Module, ensUsername: string, address: string, pubkey: string, isStatus: bool,
|
||||
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)
|
||||
if(response.len == 0):
|
||||
info "expected response is empty", methodName="setPubKey"
|
||||
return
|
||||
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind != JObject):
|
||||
info "expected response is not a json object", methodName="setPubKey"
|
||||
return
|
||||
|
||||
var success: bool
|
||||
if(not responseObj.getProp("success", success) or not success):
|
||||
info "remote call is not executed with success", methodName="setPubKey"
|
||||
return
|
||||
|
||||
var respResult: string
|
||||
if(responseObj.getProp("result", respResult)):
|
||||
self.view.model().addItem(Item(ensUsername: ensUsername, isPending: true))
|
||||
self.view.emitTransactionWasSentSignal(respResult)
|
||||
|
||||
return response
|
||||
|
||||
method releaseEnsEstimate*(self: Module, ensUsername: string, address: string): int =
|
||||
return self.controller.releaseEnsEstimate(ensUsername, address)
|
||||
|
||||
method release*(self: Module, ensUsername: string, address: string, gas: string, gasPrice: string, password: string): string =
|
||||
let response = self.controller.release(ensUsername, address, gas, gasPrice, password)
|
||||
if(response.len == 0):
|
||||
info "expected response is empty", methodName="release"
|
||||
return
|
||||
|
||||
let responseObj = response.parseJson
|
||||
if(responseObj.kind != JObject):
|
||||
info "expected response is not a json object", methodName="release"
|
||||
return
|
||||
|
||||
var success: bool
|
||||
if(not responseObj.getProp("success", success) or not success):
|
||||
info "remote call is not executed with success", methodName="release"
|
||||
return
|
||||
|
||||
var result: string
|
||||
if(responseObj.getProp("result", result)):
|
||||
self.controller.setPreferredName("")
|
||||
self.view.model().removeItemByEnsUsername(ensUsername)
|
||||
self.view.emitTransactionWasSentSignal(result)
|
||||
|
||||
return response
|
||||
|
||||
proc formatUsername(self: Module, ensUsername: string, isStatus: bool): string =
|
||||
result = ensUsername
|
||||
if isStatus:
|
||||
result = ensUsername & ens_utils.STATUS_DOMAIN
|
||||
|
||||
method connectOwnedUsername*(self: Module, ensUsername: string, isStatus: bool) =
|
||||
var ensUsername = self.formatUsername(ensUsername, isStatus)
|
||||
if(not self.controller.saveNewEnsUsername(ensUsername)):
|
||||
info "an error occurred saving ens username", methodName="connectOwnedUsername"
|
||||
return
|
||||
|
||||
self.controller.setPreferredName(ensUsername)
|
||||
self.view.model().addItem(Item(ensUsername: ensUsername, isPending: false))
|
||||
|
||||
method ensTransactionConfirmed*(self: Module, trxType: string, ensUsername: string, transactionHash: string) =
|
||||
if(not self.controller.saveNewEnsUsername(ensUsername)):
|
||||
info "an error occurred saving ens username", methodName="ensTransactionConfirmed"
|
||||
return
|
||||
|
||||
if(self.view.model().containsEnsUsername(ensUsername)):
|
||||
self.view.model().updatePendingStatus(ensUsername, false)
|
||||
else:
|
||||
self.view.model().addItem(Item(ensUsername: ensUsername, isPending: false))
|
||||
self.view.emitTransactionCompletedSignal(true, transactionHash, ensUsername, trxType, "")
|
||||
|
||||
method ensTransactionReverted*(self: Module, trxType: string, ensUsername: string, transactionHash: string,
|
||||
revertReason: string) =
|
||||
self.view.model().removeItemByEnsUsername(ensUsername)
|
||||
self.view.emitTransactionCompletedSignal(false, transactionHash, ensUsername, trxType, revertReason)
|
||||
|
||||
method getEnsRegisteredAddress*(self: Module): string =
|
||||
return self.controller.getEnsRegisteredAddress()
|
||||
|
||||
method registerEnsGasEstimate*(self: Module, ensUsername: string, address: string): int =
|
||||
return self.controller.registerEnsGasEstimate(ensUsername, address)
|
||||
|
||||
method registerEns*(self: Module, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string =
|
||||
let response = self.controller.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
|
||||
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind != JObject):
|
||||
info "expected response is not a json object", methodName="registerEns"
|
||||
return
|
||||
|
||||
var respResult: string
|
||||
if(responseObj.getProp("result", respResult)):
|
||||
self.view.model().addItem(Item(ensUsername: ensUsername, isPending: true))
|
||||
self.view.emitTransactionWasSentSignal(respResult)
|
||||
|
||||
return response
|
||||
|
||||
method getSNTBalance*(self: Module): string =
|
||||
return self.controller.getSNTBalance()
|
||||
|
||||
method getWalletDefaultAddress*(self: Module): string =
|
||||
return self.controller.getWalletDefaultAddress()
|
||||
|
||||
method getCurrentCurrency*(self: Module): string =
|
||||
return self.controller.getCurrentCurrency()
|
||||
|
||||
method getFiatValue*(self: Module, cryptoBalance: string, cryptoSymbol: string, fiatSymbol: string): string =
|
||||
if (cryptoBalance == "" or cryptoSymbol == "" or fiatSymbol == ""):
|
||||
return "0.00"
|
||||
|
||||
let price = self.controller.getPrice(cryptoSymbol, fiatSymbol)
|
||||
let value = parseFloat(cryptoBalance) * price
|
||||
return fmt"{value:.2f}"
|
||||
|
||||
method getGasEthValue*(self: Module, gweiValue: string, gasLimit: string): string {.slot.} =
|
||||
var gasLimitInt:int
|
||||
|
||||
if(gasLimit.parseInt(gasLimitInt) == 0):
|
||||
info "an error occurred parsing gas limit", methodName="getGasEthValue"
|
||||
return ""
|
||||
|
||||
# The following check prevents app crash, cause we're trying to promote
|
||||
# gasLimitInt to unsigned 256 int, and this number must be a positive number,
|
||||
# because of overflow.
|
||||
var gwei = gweiValue.parseFloat()
|
||||
if (gwei < 0):
|
||||
gwei = 0
|
||||
|
||||
if (gasLimitInt < 0):
|
||||
gasLimitInt = 0
|
||||
|
||||
let weiValue = service_conversion.gwei2Wei(gwei) * gasLimitInt.u256
|
||||
let ethValue = service_conversion.wei2Eth(weiValue)
|
||||
return fmt"{ethValue}"
|
||||
|
||||
method getStatusToken*(self: Module): string =
|
||||
return self.controller.getStatusToken()
|
||||
|
||||
method setPrefferedEnsUsername*(self: Module, ensUsername: string) =
|
||||
self.controller.setPreferredName(ensUsername)
|
@ -0,0 +1,13 @@
|
||||
import NimQml
|
||||
|
||||
method delete*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method load*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method isLoaded*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
@ -0,0 +1,5 @@
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
|
||||
# Since nim doesn't support using concepts in second level nested types we
|
||||
# define delegate interfaces within access interface.
|
@ -0,0 +1,17 @@
|
||||
method ensUsernameAvailabilityChecked*(self: AccessInterface, availabilityStatus: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onDetailsForEnsUsername*(self: AccessInterface, ensUsername: string, address: string, pubkey: string,
|
||||
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")
|
||||
|
||||
method ensTransactionReverted*(self: AccessInterface, trxType: string, ensUsername: string, transactionHash: string,
|
||||
revertReason: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
@ -0,0 +1,63 @@
|
||||
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method checkEnsUsernameAvailability*(self: AccessInterface, desiredEnsUsername: string, statusDomain: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method numOfPendingEnsUsernames*(self: AccessInterface): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
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.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method releaseEnsEstimate*(self: AccessInterface, ensUsername: string, address: string): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method release*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
password: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method connectOwnedUsername*(self: AccessInterface, ensUsername: string, isStatus: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getEnsRegisteredAddress*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method registerEnsGasEstimate*(self: AccessInterface, ensUsername: string, address: string): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method registerEns*(self: AccessInterface, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getSNTBalance*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getWalletDefaultAddress*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getCurrentCurrency*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getFiatValue*(self: AccessInterface, cryptoBalance: string, cryptoSymbol: string, fiatSymbol: string): string
|
||||
{.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getGasEthValue*(self: AccessInterface, gweiValue: string, gasLimit: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getStatusToken*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setPrefferedEnsUsername*(self: AccessInterface, ensUsername: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
149
src/app/modules/main/profile_section/ens_usernames/view.nim
Normal file
149
src/app/modules/main/profile_section/ens_usernames/view.nim
Normal file
@ -0,0 +1,149 @@
|
||||
import NimQml
|
||||
import io_interface
|
||||
import model
|
||||
from ../../../../../app_service/service/ens/utils import ENS_REGISTRY
|
||||
|
||||
QtObject:
|
||||
type
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
model: Model
|
||||
modelVariant: QVariant
|
||||
etherscanLink: string
|
||||
signingPhrase: string
|
||||
gasPrice: string
|
||||
|
||||
proc delete*(self: View) =
|
||||
self.model.delete
|
||||
self.modelVariant.delete
|
||||
self.QObject.delete
|
||||
|
||||
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||
new(result, delete)
|
||||
result.QObject.setup
|
||||
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
|
||||
self.signingPhrase = ""
|
||||
self.delegate.viewDidLoad()
|
||||
|
||||
proc model*(self: View): Model =
|
||||
return self.model
|
||||
|
||||
proc modelChanged*(self: View) {.signal.}
|
||||
proc getModel(self: View): QVariant {.slot.} =
|
||||
return self.modelVariant
|
||||
QtProperty[QVariant] model:
|
||||
read = getModel
|
||||
notify = modelChanged
|
||||
|
||||
proc getEnsRegistry(self: View): string {.slot.} =
|
||||
return ENS_REGISTRY
|
||||
|
||||
proc usernameAvailabilityChecked(self: View, availabilityStatus: string) {.signal.}
|
||||
proc sendUsernameAvailabilityCheckedSignal*(self: View, availabilityStatus: string) =
|
||||
self.usernameAvailabilityChecked(availabilityStatus)
|
||||
|
||||
proc checkEnsUsernameAvailability*(self: View, desiredEnsUsername: string, statusDomain: bool) {.slot.} =
|
||||
self.delegate.checkEnsUsernameAvailability(desiredEnsUsername, statusDomain)
|
||||
|
||||
proc numOfPendingEnsUsernames*(self: View): int {.slot.} =
|
||||
return self.delegate.numOfPendingEnsUsernames()
|
||||
|
||||
proc loading(self: View, isLoading: bool) {.signal.}
|
||||
proc detailsObtained(self: View, ensName: string, address: string, pubkey: string, isStatus: bool, expirationTime: int) {.signal.}
|
||||
|
||||
proc fetchDetailsForEnsUsername*(self: View, ensUsername: string) {.slot.} =
|
||||
self.loading(true)
|
||||
self.delegate.fetchDetailsForEnsUsername(ensUsername)
|
||||
|
||||
proc setDetailsForEnsUsername*(self: View, ensUsername: string, address: string, pubkey: string, isStatus: bool,
|
||||
expirationTime: int) =
|
||||
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)
|
||||
|
||||
proc setPubKeyGasEstimate*(self: View, ensUsername: string, address: string): int {.slot.} =
|
||||
return self.delegate.setPubKeyGasEstimate(ensUsername, address)
|
||||
|
||||
proc setPubKey*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.slot.} =
|
||||
return self.delegate.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
|
||||
|
||||
proc getEtherscanLink*(self: View): string {.slot.} =
|
||||
return self.etherscanLink
|
||||
|
||||
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)
|
||||
|
||||
proc transactionCompleted(self: View, success: bool, txHash: string, username: string, trxType: string,
|
||||
revertReason: string) {.signal.}
|
||||
proc emitTransactionCompletedSignal*(self: View, success: bool, txHash: string, username: string, trxType: string,
|
||||
revertReason: string) =
|
||||
self.transactionCompleted(success, txHash, username, trxType, revertReason)
|
||||
|
||||
proc releaseEnsEstimate*(self: View, ensUsername: string, address: string): int {.slot.} =
|
||||
return self.delegate.releaseEnsEstimate(ensUsername, address)
|
||||
|
||||
proc release*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string, password: string):
|
||||
string {.slot.} =
|
||||
return self.delegate.release(ensUsername, address, gas, gasPrice, password)
|
||||
|
||||
proc connectOwnedUsername*(self: View, ensUsername: string, isStatus: bool) {.slot.} =
|
||||
self.delegate.connectOwnedUsername(ensUsername, isStatus)
|
||||
|
||||
proc getEnsRegisteredAddress*(self: View): string {.slot.} =
|
||||
return self.delegate.getEnsRegisteredAddress()
|
||||
|
||||
proc registerEnsGasEstimate*(self: View, ensUsername: string, address: string): int {.slot.} =
|
||||
return self.delegate.registerEnsGasEstimate(ensUsername, address)
|
||||
|
||||
proc registerEns*(self: View, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.slot.} =
|
||||
return self.delegate.registerEns(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
|
||||
|
||||
proc getSNTBalance*(self: View): string {.slot.} =
|
||||
return self.delegate.getSNTBalance()
|
||||
|
||||
proc getWalletDefaultAddress*(self: View): string {.slot.} =
|
||||
return self.delegate.getWalletDefaultAddress()
|
||||
|
||||
proc getCurrentCurrency*(self: View): string {.slot.} =
|
||||
return self.delegate.getCurrentCurrency()
|
||||
|
||||
proc getFiatValue*(self: View, cryptoBalance: string, cryptoSymbol: string, fiatSymbol: string): string {.slot.} =
|
||||
return self.delegate.getFiatValue(cryptoBalance, cryptoSymbol, fiatSymbol)
|
||||
|
||||
proc getGasEthValue*(self: View, gweiValue: string, gasLimit: string): string {.slot.} =
|
||||
return self.delegate.getGasEthValue(gweiValue, gasLimit)
|
||||
|
||||
proc getStatusToken*(self: View): string {.slot.} =
|
||||
return self.delegate.getStatusToken()
|
||||
|
||||
proc setPrefferedEnsUsername*(self: View, ensUsername: string) {.slot.} =
|
||||
self.delegate.setPrefferedEnsUsername(ensUsername)
|
@ -74,6 +74,13 @@ method notificationsModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||
method getNotificationsModule*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method ensUsernamesModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getEnsUsernamesModule*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
||||
type
|
||||
## Abstract class (concept) which must be implemented by object/s used in this
|
||||
## module.
|
||||
|
@ -13,6 +13,8 @@ import ../../../../app_service/service/node_configuration/service_interface as n
|
||||
import ../../../../app_service/service/devices/service as devices_service
|
||||
import ../../../../app_service/service/mailservers/service as mailservers_service
|
||||
import ../../../../app_service/service/chat/service as chat_service
|
||||
import ../../../../app_service/service/ens/service as ens_service
|
||||
import ../../../../app_service/service/wallet_account/service_interface as wallet_account_service
|
||||
|
||||
import ./profile/module as profile_module
|
||||
import ./contacts/module as contacts_module
|
||||
@ -23,6 +25,7 @@ import ./advanced/module as advanced_module
|
||||
import ./devices/module as devices_module
|
||||
import ./sync/module as sync_module
|
||||
import ./notifications/module as notifications_module
|
||||
import ./ens_usernames/module as ens_usernames_module
|
||||
|
||||
export io_interface
|
||||
|
||||
@ -43,6 +46,7 @@ type
|
||||
devicesModule: devices_module.AccessInterface
|
||||
syncModule: sync_module.AccessInterface
|
||||
notificationsModule: notifications_module.AccessInterface
|
||||
ensUsernamesModule: ens_usernames_module.AccessInterface
|
||||
|
||||
proc newModule*[T](delegate: T,
|
||||
events: EventEmitter,
|
||||
@ -56,7 +60,9 @@ proc newModule*[T](delegate: T,
|
||||
nodeConfigurationService: node_configuration_service.ServiceInterface,
|
||||
devicesService: devices_service.Service,
|
||||
mailserversService: mailservers_service.Service,
|
||||
chatService: chat_service.Service
|
||||
chatService: chat_service.Service,
|
||||
ensService: ens_service.Service,
|
||||
walletAccountService: wallet_account_service.ServiceInterface
|
||||
):
|
||||
Module[T] =
|
||||
result = Module[T]()
|
||||
@ -75,6 +81,8 @@ proc newModule*[T](delegate: T,
|
||||
result.devicesModule = devices_module.newModule(result, events, settingsService, devicesService)
|
||||
result.syncModule = sync_module.newModule(result, events, settingsService, mailserversService)
|
||||
result.notificationsModule = notifications_module.newModule(result, events, chatService)
|
||||
result.ensUsernamesModule = ens_usernames_module.newModule(result, events, settingsService, ensService,
|
||||
walletAccountService)
|
||||
|
||||
singletonInstance.engine.setRootContextProperty("profileSectionModule", result.viewVariant)
|
||||
|
||||
@ -103,6 +111,7 @@ method load*[T](self: Module[T]) =
|
||||
self.devicesModule.load()
|
||||
self.syncModule.load()
|
||||
self.notificationsModule.load()
|
||||
self.ensUsernamesModule.load()
|
||||
|
||||
method isLoaded*[T](self: Module[T]): bool =
|
||||
return self.moduleLoaded
|
||||
@ -135,6 +144,9 @@ proc checkIfModuleDidLoad[T](self: Module[T]) =
|
||||
if(not self.notificationsModule.isLoaded()):
|
||||
return
|
||||
|
||||
if(not self.ensUsernamesModule.isLoaded()):
|
||||
return
|
||||
|
||||
self.moduleLoaded = true
|
||||
self.delegate.profileSectionDidLoad()
|
||||
|
||||
@ -191,3 +203,9 @@ method notificationsModuleDidLoad*[T](self: Module[T]) =
|
||||
|
||||
method getNotificationsModule*[T](self: Module[T]): QVariant =
|
||||
self.notificationsModule.getModuleAsVariant()
|
||||
|
||||
method ensUsernamesModuleDidLoad*[T](self: Module[T]) =
|
||||
self.checkIfModuleDidLoad()
|
||||
|
||||
method getEnsUsernamesModule*[T](self: Module[T]): QVariant =
|
||||
self.ensUsernamesModule.getModuleAsVariant()
|
@ -60,3 +60,8 @@ QtObject:
|
||||
return self.delegate.getPrivacyModule()
|
||||
QtProperty[QVariant] privacyModule:
|
||||
read = getPrivacyModule
|
||||
|
||||
proc getEnsUsernamesModule(self: View): QVariant {.slot.} =
|
||||
return self.delegate.getEnsUsernamesModule()
|
||||
QtProperty[QVariant] ensUsernamesModule:
|
||||
read = getEnsUsernamesModule
|
60
src/app_service/common/conversion.nim
Normal file
60
src/app_service/common/conversion.nim
Normal file
@ -0,0 +1,60 @@
|
||||
import strutils, strformat, stint, chronicles
|
||||
from web3 import Address, fromHex
|
||||
|
||||
proc parseAddress*(strAddress: string): Address =
|
||||
fromHex(Address, strAddress)
|
||||
|
||||
proc isAddress*(strAddress: string): bool =
|
||||
try:
|
||||
discard parseAddress(strAddress)
|
||||
except:
|
||||
return false
|
||||
return true
|
||||
|
||||
proc toStUInt*[bits: static[int]](flt: float, T: typedesc[StUint[bits]]): T =
|
||||
var stringValue = fmt"{flt:<.0f}"
|
||||
stringValue.removeSuffix('.')
|
||||
if (flt >= 0):
|
||||
result = parse($stringValue, StUint[bits])
|
||||
else:
|
||||
result = parse("0", StUint[bits])
|
||||
|
||||
proc toUInt256*(flt: float): UInt256 =
|
||||
toStUInt(flt, StUInt[256])
|
||||
|
||||
proc toUInt64*(flt: float): StUInt[64] =
|
||||
toStUInt(flt, StUInt[64])
|
||||
|
||||
proc eth2Wei*(eth: float, decimals: int = 18): UInt256 =
|
||||
let weiValue = eth * parseFloat(alignLeft("1", decimals + 1, '0'))
|
||||
weiValue.toUInt256
|
||||
|
||||
proc gwei2Wei*(gwei: float): UInt256 =
|
||||
eth2Wei(gwei, 9)
|
||||
|
||||
proc wei2Eth*(input: Stuint[256], decimals: int = 18): string =
|
||||
var one_eth = u256(10).pow(decimals) # fromHex(Stuint[256], "DE0B6B3A7640000")
|
||||
|
||||
var (eth, remainder) = divmod(input, one_eth)
|
||||
let leading_zeros = "0".repeat(($one_eth).len - ($remainder).len - 1)
|
||||
|
||||
fmt"{eth}.{leading_zeros}{remainder}"
|
||||
|
||||
proc wei2Eth*(input: string, decimals: int): string =
|
||||
try:
|
||||
var input256: Stuint[256]
|
||||
if input.contains("e+"): # we have a js string BN, ie 1e+21
|
||||
let
|
||||
inputSplit = input.split("e+")
|
||||
whole = inputSplit[0].u256
|
||||
remainder = u256(10).pow(inputSplit[1].parseInt)
|
||||
input256 = whole * remainder
|
||||
else:
|
||||
input256 = input.u256
|
||||
result = wei2Eth(input256, decimals)
|
||||
except Exception as e:
|
||||
error "Error parsing this wei value", input, msg=e.msg
|
||||
result = "0"
|
||||
|
||||
proc wei2Gwei*(input: string): string =
|
||||
result = wei2Eth(input, 9)
|
81
src/app_service/service/ens/async_tasks.nim
Normal file
81
src/app_service/service/ens/async_tasks.nim
Normal file
@ -0,0 +1,81 @@
|
||||
#################################################
|
||||
# Async check for ens username availability
|
||||
#################################################
|
||||
|
||||
type
|
||||
CheckEnsAvailabilityTaskArg = ref object of QObjectTaskArg
|
||||
ensUsername*: string
|
||||
isStatus*: bool
|
||||
myPublicKey*: string
|
||||
myWalletAddress*: string
|
||||
|
||||
const checkEnsAvailabilityTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[CheckEnsAvailabilityTaskArg](argEncoded)
|
||||
|
||||
var desiredEnsUsername = arg.ensUsername & (if(arg.isStatus): ens_utils.STATUS_DOMAIN else: "")
|
||||
|
||||
var availability = ""
|
||||
let ownerAddr = ens_utils.owner(desiredEnsUsername)
|
||||
if ownerAddr == "" and arg.isStatus:
|
||||
availability = ENS_AVAILABILITY_STATUS_AVAILABLE
|
||||
else:
|
||||
let ensPubkey = ens_utils.pubkey(arg.ensUsername)
|
||||
if ownerAddr != "":
|
||||
if ensPubkey == "" and ownerAddr == arg.myWalletAddress:
|
||||
availability = ENS_AVAILABILITY_STATUS_OWNED # "Continuing will connect this username with your chat key."
|
||||
elif ensPubkey == arg.myPublicKey:
|
||||
availability = ENS_AVAILABILITY_STATUS_CONNECTED
|
||||
elif ownerAddr == arg.myWalletAddress:
|
||||
availability = ENS_AVAILABILITY_STATUS_CONNECTED_DIFFERENT_KEY # "Continuing will require a transaction to connect the username with your current chat key.",
|
||||
else:
|
||||
availability = ENS_AVAILABILITY_STATUS_TAKEN
|
||||
else:
|
||||
availability = ENS_AVAILABILITY_STATUS_TAKEN
|
||||
|
||||
let responseJson = %*{
|
||||
"availability": availability
|
||||
}
|
||||
arg.finish(responseJson)
|
||||
|
||||
#################################################
|
||||
# Async load ens username details
|
||||
#################################################
|
||||
|
||||
type
|
||||
EnsUsernamDetailsTaskArg = ref object of QObjectTaskArg
|
||||
ensUsername*: string
|
||||
isStatus*: bool
|
||||
toAddress*: Address
|
||||
data: string
|
||||
|
||||
const ensUsernameDetailsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[EnsUsernamDetailsTaskArg](argEncoded)
|
||||
|
||||
let address = ens_utils.address(arg.ensUsername)
|
||||
let pubkey = ens_utils.pubkey(arg.ensUsername)
|
||||
|
||||
var expirationTime = 0
|
||||
if arg.isStatus:
|
||||
expirationTime = ens_utils.getExpirationTime(arg.toAddress, arg.data)
|
||||
|
||||
let responseJson = %* {
|
||||
"ensUsername": arg.ensUsername,
|
||||
"address": address,
|
||||
"pubkey": pubkey,
|
||||
"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)
|
486
src/app_service/service/ens/service.nim
Normal file
486
src/app_service/service/ens/service.nim
Normal file
@ -0,0 +1,486 @@
|
||||
import NimQml, Tables, sets, json, sequtils, strutils, strformat, chronicles
|
||||
import web3/conversions
|
||||
import web3/[conversions, ethtypes], stint
|
||||
import web3/ethtypes
|
||||
|
||||
import ../../../app/core/eventemitter
|
||||
import ../../../app/core/tasks/[qt, threadpool]
|
||||
|
||||
import status/statusgo_backend_new/eth as status_eth
|
||||
|
||||
import ../../common/conversion as common_conversion
|
||||
import utils as ens_utils
|
||||
import ../settings/service_interface as settings_service
|
||||
import ../wallet_account/service_interface as wallet_account_service
|
||||
import ../transaction/service as transaction_service
|
||||
import ../eth/service_interface as eth_service
|
||||
import ../network/service_interface as network_service
|
||||
import ../token/service as token_service
|
||||
|
||||
|
||||
logScope:
|
||||
topics = "ens-service"
|
||||
|
||||
|
||||
const ENS_AVAILABILITY_STATUS_ALREADY_CONNECTED = "already-connected"
|
||||
const ENS_AVAILABILITY_STATUS_AVAILABLE = "available"
|
||||
const ENS_AVAILABILITY_STATUS_OWNED = "owned"
|
||||
const ENS_AVAILABILITY_STATUS_CONNECTED = "connected"
|
||||
const ENS_AVAILABILITY_STATUS_CONNECTED_DIFFERENT_KEY = "connected-different-key"
|
||||
const ENS_AVAILABILITY_STATUS_TAKEN = "taken"
|
||||
|
||||
include ../../common/json_utils
|
||||
include async_tasks
|
||||
|
||||
type
|
||||
EnsUsernameAvailabilityArgs* = ref object of Args
|
||||
availabilityStatus*: string
|
||||
|
||||
EnsUsernameDetailsArgs* = ref object of Args
|
||||
ensUsername*: string
|
||||
address*: string
|
||||
pubkey*: string
|
||||
isStatus*: bool
|
||||
expirationTime*: int
|
||||
|
||||
GasPriceArgs* = ref object of Args
|
||||
gasPrice*: string
|
||||
|
||||
EnsTransactionArgs* = ref object of Args
|
||||
transactionHash*: string
|
||||
ensUsername*: string
|
||||
transactionType*: string
|
||||
revertReason*: string
|
||||
|
||||
# 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* = "gasPriceFetched"
|
||||
const SIGNAL_ENS_TRANSACTION_CONFIRMED* = "ensTransactionConfirmed"
|
||||
const SIGNAL_ENS_TRANSACTION_REVERTED* = "ensTransactionReverted"
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Service* = ref object of QObject
|
||||
events: EventEmitter
|
||||
threadpool: ThreadPool
|
||||
pendingEnsUsernames*: HashSet[string]
|
||||
settingsService: settings_service.ServiceInterface
|
||||
walletAccountService: wallet_account_service.ServiceInterface
|
||||
transactionService: transaction_service.Service
|
||||
ethService: eth_service.ServiceInterface
|
||||
networkService: network_service.ServiceInterface
|
||||
tokenService: token_service.Service
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newService*(
|
||||
events: EventEmitter,
|
||||
threadpool: ThreadPool,
|
||||
settingsService: settings_service.ServiceInterface,
|
||||
walletAccountService: wallet_account_service.ServiceInterface,
|
||||
transactionService: transaction_service.Service,
|
||||
ethService: eth_service.ServiceInterface,
|
||||
networkService: network_service.ServiceInterface,
|
||||
tokenService: token_service.Service
|
||||
): Service =
|
||||
new(result, delete)
|
||||
result.QObject.setup
|
||||
result.events = events
|
||||
result.threadpool = threadpool
|
||||
result.settingsService = settingsService
|
||||
result.walletAccountService = walletAccountService
|
||||
result.transactionService = transactionService
|
||||
result.ethService = ethService
|
||||
result.networkService = networkService
|
||||
result.tokenService = tokenService
|
||||
|
||||
proc confirmTransaction(self: Service, trxType: string, ensUsername: string, transactionHash: string) =
|
||||
self.pendingEnsUsernames.excl(ensUsername)
|
||||
let data = EnsTransactionArgs(transactionHash: transactionHash, ensUsername: ensUsername, transactionType: $trxType)
|
||||
self.events.emit(SIGNAL_ENS_TRANSACTION_CONFIRMED, data)
|
||||
|
||||
proc revertTransaction(self: Service, trxType: string, ensUsername: string, transactionHash: string,
|
||||
revertReason: string) =
|
||||
self.pendingEnsUsernames.excl(ensUsername)
|
||||
let data = EnsTransactionArgs(transactionHash: transactionHash, ensUsername: ensUsername, transactionType: $trxType,
|
||||
revertReason: revertReason)
|
||||
self.events.emit(SIGNAL_ENS_TRANSACTION_REVERTED, data)
|
||||
|
||||
proc doConnect(self: Service) =
|
||||
self.events.on(PendingTransactionTypeDto.RegisterENS.event) do(e: Args):
|
||||
var receivedData = TransactionMinedArgs(e)
|
||||
if receivedData.success:
|
||||
self.confirmTransaction($PendingTransactionTypeDto.RegisterENS, receivedData.data, receivedData.transactionHash)
|
||||
else:
|
||||
self.revertTransaction($PendingTransactionTypeDto.RegisterENS, receivedData.data, receivedData.transactionHash,
|
||||
receivedData.revertReason)
|
||||
|
||||
self.events.on(PendingTransactionTypeDto.SetPubKey.event) do(e: Args):
|
||||
var receivedData = TransactionMinedArgs(e)
|
||||
if receivedData.success:
|
||||
self.confirmTransaction($PendingTransactionTypeDto.SetPubKey, receivedData.data, receivedData.transactionHash)
|
||||
else:
|
||||
self.revertTransaction($PendingTransactionTypeDto.SetPubKey, receivedData.data, receivedData.transactionHash,
|
||||
receivedData.revertReason)
|
||||
|
||||
proc init*(self: Service) =
|
||||
self.doConnect()
|
||||
|
||||
# Response of `transactionService.getPendingTransactions()` should be appropriate DTO, that's not added at the moment
|
||||
# but once we add it, need to update this block here, since we won't need to parse json manually here.
|
||||
let pendingTransactions = self.transactionService.getPendingTransactions()
|
||||
var pendingStickerPacks = initHashSet[int]()
|
||||
if (pendingTransactions.len > 0):
|
||||
for trx in pendingTransactions.parseJson{"result"}.getElems():
|
||||
let transactionType = trx["type"].getStr
|
||||
if transactionType == $PendingTransactionTypeDto.RegisterENS or
|
||||
transactionType == $PendingTransactionTypeDto.SetPubKey:
|
||||
self.pendingEnsUsernames.incl trx["additionalData"].getStr
|
||||
|
||||
proc getMyPendingEnsUsernames*(self: Service): seq[string] =
|
||||
for i in self.pendingEnsUsernames.items:
|
||||
result.add(i)
|
||||
|
||||
proc getAllMyEnsUsernames*(self: Service, includePending: bool): seq[string] =
|
||||
result = self.settingsService.getEnsUsernames()
|
||||
if(includePending):
|
||||
result.add(self.getMyPendingEnsUsernames())
|
||||
|
||||
proc onEnsUsernameAvailabilityChecked*(self: Service, response: string) {.slot.} =
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind != JObject):
|
||||
info "expected response is not a json object", methodName="onEnsUsernameAvailabilityChecked"
|
||||
# notify view, this is important
|
||||
self.events.emit(SIGNAL_ENS_USERNAME_AVAILABILITY_CHECKED, EnsUsernameAvailabilityArgs())
|
||||
return
|
||||
|
||||
var availablilityStatus: string
|
||||
discard responseObj.getProp("availability", availablilityStatus)
|
||||
let data = EnsUsernameAvailabilityArgs(availabilityStatus: availablilityStatus)
|
||||
self.events.emit(SIGNAL_ENS_USERNAME_AVAILABILITY_CHECKED, data)
|
||||
|
||||
proc formatUsername(self: Service, username: string, isStatus: bool): string =
|
||||
result = username
|
||||
if isStatus:
|
||||
result = result & ens_utils.STATUS_DOMAIN
|
||||
|
||||
proc checkEnsUsernameAvailability*(self: Service, ensUsername: string, isStatus: bool) =
|
||||
let registeredEnsUsernames = self.getAllMyEnsUsernames(true)
|
||||
var desiredEnsUsername = self.formatUsername(ensUsername, isStatus)
|
||||
var availability = ""
|
||||
if registeredEnsUsernames.filter(proc(x: string):bool = x == desiredEnsUsername).len > 0:
|
||||
let data = EnsUsernameAvailabilityArgs(availabilityStatus: ENS_AVAILABILITY_STATUS_ALREADY_CONNECTED)
|
||||
self.events.emit(SIGNAL_ENS_USERNAME_AVAILABILITY_CHECKED, data)
|
||||
else:
|
||||
let arg = CheckEnsAvailabilityTaskArg(
|
||||
tptr: cast[ByteAddress](checkEnsAvailabilityTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onEnsUsernameAvailabilityChecked",
|
||||
ensUsername: ensUsername,
|
||||
isStatus: isStatus,
|
||||
myPublicKey: self.settingsService.getPublicKey(),
|
||||
myWalletAddress: self.walletAccountService.getWalletAccount(0).address
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc onEnsUsernameDetailsFetched*(self: Service, response: string) {.slot.} =
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind != JObject):
|
||||
info "expected response is not a json object", methodName="onEnsUsernameDetailsFetched"
|
||||
# notify view, this is important
|
||||
self.events.emit(SIGNAL_ENS_USERNAME_DETAILS_FETCHED, EnsUsernameDetailsArgs())
|
||||
return
|
||||
|
||||
var data = EnsUsernameDetailsArgs()
|
||||
discard responseObj.getProp("ensUsername", data.ensUsername)
|
||||
discard responseObj.getProp("address", data.address)
|
||||
discard responseObj.getProp("pubkey", data.pubkey)
|
||||
discard responseObj.getProp("isStatus", data.isStatus)
|
||||
discard responseObj.getProp("expirationTime", data.expirationTime)
|
||||
|
||||
self.events.emit(SIGNAL_ENS_USERNAME_DETAILS_FETCHED, data)
|
||||
|
||||
proc sntSymbol(networkType: NetworkType): string =
|
||||
if networkType == NetworkType.Mainnet:
|
||||
return "SNT"
|
||||
else:
|
||||
return "STT"
|
||||
|
||||
proc getCurrentNetworkContractForName(self: Service, name: string): ContractDto =
|
||||
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
|
||||
let networkDto = self.networkService.getNetwork(networkType)
|
||||
return self.ethService.findContract(networkDto.chainId, name)
|
||||
|
||||
proc getCurrentNetworkErc20ContractForSymbol(self: Service, symbol: string = ""): Erc20ContractDto =
|
||||
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
|
||||
let networkDto = self.networkService.getNetwork(networkType)
|
||||
return self.ethService.findErc20Contract(networkDto.chainId, if symbol.len > 0: symbol else: networkType.sntSymbol())
|
||||
|
||||
proc fetchDetailsForEnsUsername*(self: Service, ensUsername: string) =
|
||||
var contractDto = self.getCurrentNetworkContractForName("ens-usernames")
|
||||
|
||||
var data: string
|
||||
var isStatus = false
|
||||
if ensUsername.endsWith(ens_utils.STATUS_DOMAIN):
|
||||
let onlyUsername = ensUsername.replace(ens_utils.STATUS_DOMAIN, "")
|
||||
let label = fromHex(FixedBytes[32], label(onlyUsername))
|
||||
let expTime = ExpirationTime(label: label)
|
||||
isStatus = true
|
||||
data = contractDto.methods["getExpirationTime"].encodeAbi(expTime)
|
||||
|
||||
let arg = EnsUsernamDetailsTaskArg(
|
||||
tptr: cast[ByteAddress](ensUsernameDetailsTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onEnsUsernameDetailsFetched",
|
||||
ensUsername: ensUsername,
|
||||
isStatus: isStatus,
|
||||
toAddress: contractDto.address,
|
||||
data: data
|
||||
)
|
||||
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", methodName="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", methodName="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 myPublicKey = self.settingsService.getPublicKey()
|
||||
var hash = namehash(ensUsername)
|
||||
hash.removePrefix("0x")
|
||||
|
||||
let label = fromHex(FixedBytes[32], "0x" & hash)
|
||||
let coordinates = self.extractCoordinates(myPublicKey)
|
||||
let x = fromHex(FixedBytes[32], coordinates.x)
|
||||
let y = fromHex(FixedBytes[32], coordinates.y)
|
||||
|
||||
let contractDto = self.getCurrentNetworkContractForName("ens-resolver")
|
||||
|
||||
let setPubkey = SetPubkey(label: label, x: x, y: y)
|
||||
let resolverAddress = resolver(hash)
|
||||
|
||||
var tx = buildTokenTransaction(parseAddress(address), parseAddress(resolverAddress), "", "")
|
||||
var success = false
|
||||
|
||||
let response = contractDto.methods["setPubkey"].estimateGas(tx, setPubkey, success)
|
||||
if(success):
|
||||
result = fromHex[int](response)
|
||||
else:
|
||||
result = 80000
|
||||
except RpcException as e:
|
||||
result = 80000
|
||||
error "error occurred", methodName="setPubKeyGasEstimate"
|
||||
|
||||
proc setPubKey*(self: Service, ensUsername: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string =
|
||||
try:
|
||||
let eip1559Enabled = self.settingsService.isEIP1559Enabled()
|
||||
let myPublicKey = self.settingsService.getPublicKey()
|
||||
|
||||
var hash = namehash(ensUsername)
|
||||
hash.removePrefix("0x")
|
||||
|
||||
let label = fromHex(FixedBytes[32], "0x" & hash)
|
||||
let coordinates = self.extractCoordinates(myPublicKey)
|
||||
let x = fromHex(FixedBytes[32], coordinates.x)
|
||||
let y = fromHex(FixedBytes[32], coordinates.y)
|
||||
|
||||
let contractDto = self.getCurrentNetworkContractForName("ens-resolver")
|
||||
|
||||
let setPubkey = SetPubkey(label: label, x: x, y: y)
|
||||
let resolverAddress = resolver(hash)
|
||||
|
||||
var tx = buildTokenTransaction(parseAddress(address), parseAddress(resolverAddress), gas, gasPrice,
|
||||
eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
|
||||
var success = false
|
||||
|
||||
let response = contractDto.methods["setPubkey"].send(tx, setPubkey, password, success)
|
||||
result = $(%* { "result": %response, "success": %success })
|
||||
|
||||
if success:
|
||||
self.transactionService.trackPendingTransaction(response, address, resolverAddress,
|
||||
$PendingTransactionTypeDto.SetPubKey, ensUsername)
|
||||
self.pendingEnsUsernames.incl(ensUsername)
|
||||
|
||||
except RpcException as e:
|
||||
error "error occurred", methodName="setPubKey"
|
||||
|
||||
proc releaseEnsEstimate*(self: Service, ensUsername: string, address: string): int =
|
||||
try:
|
||||
let label = fromHex(FixedBytes[32], label(ensUsername))
|
||||
|
||||
let contractDto = self.getCurrentNetworkContractForName("ens-resolver")
|
||||
|
||||
let release = Release(label: label)
|
||||
|
||||
var tx = buildTokenTransaction(parseAddress(address), contractDto.address, "", "")
|
||||
var success = false
|
||||
|
||||
let response = contractDto.methods["release"].estimateGas(tx, release, success)
|
||||
|
||||
if(success):
|
||||
result = fromHex[int](response)
|
||||
else:
|
||||
result = 100000
|
||||
|
||||
except RpcException as e:
|
||||
result = 100000
|
||||
error "error occurred", methodName="releaseEnsEstimate"
|
||||
|
||||
|
||||
proc release*(self: Service, ensUsername: string, address: string, gas: string, gasPrice: string, password: string):
|
||||
string =
|
||||
try:
|
||||
let label = fromHex(FixedBytes[32], label(ensUsername))
|
||||
|
||||
let contractDto = self.getCurrentNetworkContractForName("ens-usernames")
|
||||
|
||||
let release = Release(label: label)
|
||||
|
||||
var tx = buildTokenTransaction(parseAddress(address), contractDto.address, "", "")
|
||||
var success = false
|
||||
|
||||
let response = contractDto.methods["release"].send(tx, release, password, success)
|
||||
result = $(%* { "result": %response, "success": %success })
|
||||
|
||||
if(success):
|
||||
self.transactionService.trackPendingTransaction(response, address, $contractDto.address,
|
||||
$PendingTransactionTypeDto.ReleaseENS, ensUsername)
|
||||
self.pendingEnsUsernames.excl(ensUsername)
|
||||
|
||||
except RpcException as e:
|
||||
error "error occurred", methodName="release"
|
||||
|
||||
proc getEnsRegisteredAddress*(self: Service): string =
|
||||
let contractDto = self.getCurrentNetworkContractForName("ens-usernames")
|
||||
if contractDto != nil:
|
||||
return $contractDto.address
|
||||
|
||||
proc registerENSGasEstimate*(self: Service, ensUsername: string, address: string): int =
|
||||
try:
|
||||
let myPublicKey = self.settingsService.getPublicKey()
|
||||
let coordinates = self.extractCoordinates(myPublicKey)
|
||||
let x = fromHex(FixedBytes[32], coordinates.x)
|
||||
let y = fromHex(FixedBytes[32], coordinates.y)
|
||||
|
||||
let contractDto = self.getCurrentNetworkContractForName("ens-usernames")
|
||||
let sntContract = self.getCurrentNetworkErc20ContractForSymbol()
|
||||
|
||||
let price = getPrice(contractDto)
|
||||
let label = fromHex(FixedBytes[32], label(ensUsername))
|
||||
|
||||
let register = Register(label: label, account: parseAddress(address), x: x, y: y)
|
||||
let registerAbiEncoded = contractDto.methods["register"].encodeAbi(register)
|
||||
let approveAndCallObj = ApproveAndCall[132](to: contractDto.address, value: price,
|
||||
data: DynamicBytes[132].fromHex(registerAbiEncoded))
|
||||
let approveAndCallAbiEncoded = sntContract.methods["approveAndCall"].encodeAbi(approveAndCallObj)
|
||||
|
||||
var tx = buildTokenTransaction(parseAddress(address), sntContract.address, "", "")
|
||||
var success = false
|
||||
|
||||
let response = sntContract.methods["approveAndCall"].estimateGas(tx, approveAndCallObj, success)
|
||||
|
||||
if(success):
|
||||
result = fromHex[int](response)
|
||||
else:
|
||||
result = 380000
|
||||
|
||||
except RpcException as e:
|
||||
error "error occurred", methodName="registerENSGasEstimate"
|
||||
|
||||
proc registerEns*(self: Service, username: string, address: string, gas: string, gasPrice: string,
|
||||
maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string =
|
||||
try:
|
||||
let myPublicKey = self.settingsService.getPublicKey()
|
||||
let coordinates = self.extractCoordinates(myPublicKey)
|
||||
let x = fromHex(FixedBytes[32], coordinates.x)
|
||||
let y = fromHex(FixedBytes[32], coordinates.y)
|
||||
|
||||
let contractDto = self.getCurrentNetworkContractForName("ens-usernames")
|
||||
let sntContract = self.getCurrentNetworkErc20ContractForSymbol()
|
||||
|
||||
let price = getPrice(contractDto)
|
||||
let label = fromHex(FixedBytes[32], label(username))
|
||||
let eip1559Enabled = self.settingsService.isEIP1559Enabled()
|
||||
|
||||
let register = Register(label: label, account: parseAddress(address), x: x, y: y)
|
||||
let registerAbiEncoded = contractDto.methods["register"].encodeAbi(register)
|
||||
let approveAndCallObj = ApproveAndCall[132](to: contractDto.address, value: price,
|
||||
data: DynamicBytes[132].fromHex(registerAbiEncoded))
|
||||
|
||||
var tx = buildTokenTransaction(parseAddress(address), sntContract.address, gas, gasPrice, eip1559Enabled,
|
||||
maxPriorityFeePerGas, maxFeePerGas)
|
||||
var success = false
|
||||
|
||||
let response = sntContract.methods["approveAndCall"].send(tx, approveAndCallObj, password, success)
|
||||
result = $(%* { "result": %response, "success": %success })
|
||||
if success:
|
||||
var ensUsername = self.formatUsername(username, true)
|
||||
self.transactionService.trackPendingTransaction(response, address, $sntContract.address,
|
||||
$PendingTransactionTypeDto.RegisterENS, ensUsername)
|
||||
self.pendingEnsUsernames.incl(ensUsername)
|
||||
|
||||
except RpcException as e:
|
||||
error "error occurred", methodName="registerEns"
|
||||
|
||||
proc getSNTBalance*(self: Service): string =
|
||||
let address = self.walletAccountService.getWalletAccount(0).address
|
||||
let sntContract = self.getCurrentNetworkErc20ContractForSymbol()
|
||||
|
||||
var postfixedAccount: string = address
|
||||
postfixedAccount.removePrefix("0x")
|
||||
let payload = %* [{
|
||||
"to": $sntContract.address,
|
||||
"from": address,
|
||||
"data": fmt"0x70a08231000000000000000000000000{postfixedAccount}"
|
||||
}, "latest"]
|
||||
let response = status_eth.doEthCall(payload)
|
||||
let balance = response.result.getStr
|
||||
|
||||
var decimals = 18
|
||||
|
||||
let allTokens = self.tokenService.getTokens()
|
||||
for t in allTokens:
|
||||
if(t.address == sntContract.address):
|
||||
decimals = t.decimals
|
||||
break
|
||||
|
||||
result = ens_utils.hex2Token(balance, decimals)
|
||||
|
||||
proc getStatusToken*(self: Service): string =
|
||||
let sntContract = self.getCurrentNetworkErc20ContractForSymbol()
|
||||
let jsonObj = %* {
|
||||
"name": sntContract.name,
|
||||
"symbol": sntContract.symbol,
|
||||
"address": sntContract.address
|
||||
}
|
||||
return $jsonObj
|
@ -1,14 +1,34 @@
|
||||
import Tables, json, chronicles, strutils
|
||||
import algorithm, strformat, sets, options
|
||||
import algorithm, strformat, sets, options, sequtils
|
||||
import chronicles, libp2p/[multihash, multicodec, cid]
|
||||
import nimcrypto, stint
|
||||
include ../../common/json_utils
|
||||
import web3/conversions
|
||||
import ../../common/conversion as common_conversion
|
||||
import ../eth/dto/transaction as eth_transaction_dto
|
||||
import ../eth/dto/coder as eth_coder_dto
|
||||
import ../eth/dto/contract as eth_contract_dto
|
||||
import status/statusgo_backend_new/eth as status_eth
|
||||
|
||||
logScope:
|
||||
topics = "ens-utils"
|
||||
|
||||
const domain* = ".stateofus.eth"
|
||||
include ../../common/json_utils
|
||||
|
||||
const STATUS_DOMAIN* = ".stateofus.eth"
|
||||
const ENS_REGISTRY* = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
|
||||
const RESOLVER_SIGNATURE* = "0x0178b8bf"
|
||||
const CONTENTHASH_SIGNATURE* = "0xbc1c58d1" # contenthash(bytes32)
|
||||
const PUBKEY_SIGNATURE* = "0xc8690233" # pubkey(bytes32 node)
|
||||
const ADDRESS_SIGNATURE* = "0x3b3b57de" # addr(bytes32 node)
|
||||
const OWNER_SIGNATURE* = "0x02571be3" # owner(bytes32 node)
|
||||
|
||||
export STATUS_DOMAIN
|
||||
export ENS_REGISTRY
|
||||
export RESOLVER_SIGNATURE
|
||||
export CONTENTHASH_SIGNATURE
|
||||
export PUBKEY_SIGNATURE
|
||||
export ADDRESS_SIGNATURE
|
||||
export OWNER_SIGNATURE
|
||||
|
||||
type
|
||||
ENSType* {.pure.} = enum
|
||||
@ -21,9 +41,9 @@ proc addDomain(username: string): string =
|
||||
if username.endsWith(".eth"):
|
||||
return username
|
||||
else:
|
||||
return username & domain
|
||||
return username & STATUS_DOMAIN
|
||||
|
||||
proc namehash(ensName:string): string =
|
||||
proc namehash*(ensName:string): string =
|
||||
let name = ensName.toLower()
|
||||
var node:array[32, byte]
|
||||
|
||||
@ -38,20 +58,17 @@ proc namehash(ensName:string): string =
|
||||
|
||||
result = "0x" & node.toHex()
|
||||
|
||||
const registry* = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
|
||||
const resolver_signature = "0x0178b8bf"
|
||||
proc resolver(usernameHash: string): string =
|
||||
proc resolver*(usernameHash: string): string =
|
||||
let payload = %* [{
|
||||
"to": registry,
|
||||
"to": ENS_REGISTRY,
|
||||
"from": "0x0000000000000000000000000000000000000000",
|
||||
"data": fmt"{resolver_signature}{userNameHash}"
|
||||
"data": fmt"{RESOLVER_SIGNATURE}{userNameHash}"
|
||||
}, "latest"]
|
||||
|
||||
var resolverAddr = status_eth.doEthCall(payload).result.getStr()
|
||||
resolverAddr.removePrefix("0x000000000000000000000000")
|
||||
result = "0x" & resolverAddr
|
||||
|
||||
const contenthash_signature = "0xbc1c58d1" # contenthash(bytes32)
|
||||
proc contenthash(ensAddr: string): string =
|
||||
var ensHash = namehash(ensAddr)
|
||||
ensHash.removePrefix("0x")
|
||||
@ -59,7 +76,7 @@ proc contenthash(ensAddr: string): string =
|
||||
let payload = %* [{
|
||||
"to": ensResolver,
|
||||
"from": "0x0000000000000000000000000000000000000000",
|
||||
"data": fmt"{contenthash_signature}{ensHash}"
|
||||
"data": fmt"{CONTENTHASH_SIGNATURE}{ensHash}"
|
||||
}, "latest"]
|
||||
|
||||
let bytesResponse = status_eth.doEthCall(payload).result.getStr()
|
||||
@ -120,7 +137,6 @@ proc decodeENSContentHash*(value: string): tuple[ensType: ENSType, output: strin
|
||||
|
||||
return (ENSType.UNKNOWN, "")
|
||||
|
||||
const pubkey_signature = "0xc8690233" # pubkey(bytes32 node)
|
||||
proc pubkey*(username: string): string =
|
||||
var userNameHash = namehash(addDomain(username))
|
||||
userNameHash.removePrefix("0x")
|
||||
@ -128,7 +144,7 @@ proc pubkey*(username: string): string =
|
||||
let payload = %* [{
|
||||
"to": ensResolver,
|
||||
"from": "0x0000000000000000000000000000000000000000",
|
||||
"data": fmt"{pubkey_signature}{userNameHash}"
|
||||
"data": fmt"{PUBKEY_SIGNATURE}{userNameHash}"
|
||||
}, "latest"]
|
||||
let response = status_eth.doEthCall(payload)
|
||||
# TODO: error handling
|
||||
@ -139,7 +155,6 @@ proc pubkey*(username: string): string =
|
||||
pubkey.removePrefix("0x")
|
||||
result = "0x04" & pubkey
|
||||
|
||||
const address_signature = "0x3b3b57de" # addr(bytes32 node)
|
||||
proc address*(username: string): string =
|
||||
var userNameHash = namehash(addDomain(username))
|
||||
userNameHash.removePrefix("0x")
|
||||
@ -147,7 +162,7 @@ proc address*(username: string): string =
|
||||
let payload = %* [{
|
||||
"to": ensResolver,
|
||||
"from": "0x0000000000000000000000000000000000000000",
|
||||
"data": fmt"{address_signature}{userNameHash}"
|
||||
"data": fmt"{ADDRESS_SIGNATURE}{userNameHash}"
|
||||
}, "latest"]
|
||||
let response = status_eth.doEthCall(payload)
|
||||
# TODO: error handling
|
||||
@ -155,3 +170,86 @@ proc address*(username: string): string =
|
||||
if address == "0x0000000000000000000000000000000000000000000000000000000000000000":
|
||||
return ""
|
||||
result = "0x" & address.substr(26)
|
||||
|
||||
proc owner*(username: string): string =
|
||||
var userNameHash = namehash(addDomain(username))
|
||||
userNameHash.removePrefix("0x")
|
||||
let payload = %* [{
|
||||
"to": ENS_REGISTRY,
|
||||
"from": "0x0000000000000000000000000000000000000000",
|
||||
"data": fmt"{OWNER_SIGNATURE}{userNameHash}"
|
||||
}, "latest"]
|
||||
let response = status_eth.doEthCall(payload)
|
||||
# TODO: error handling
|
||||
let ownerAddr = response.result.getStr()
|
||||
if ownerAddr == "0x0000000000000000000000000000000000000000000000000000000000000000":
|
||||
return ""
|
||||
result = "0x" & ownerAddr.substr(26)
|
||||
|
||||
proc buildTransaction*(source: Address, value: Uint256, gas = "", gasPrice = "", isEIP1559Enabled = false,
|
||||
maxPriorityFeePerGas = "", maxFeePerGas = "", data = ""): TransactionDataDto =
|
||||
result = TransactionDataDto(
|
||||
source: source,
|
||||
value: value.some,
|
||||
gas: (if gas.isEmptyOrWhitespace: Quantity.none else: Quantity(cast[uint64](parseFloat(gas).toUInt64)).some),
|
||||
gasPrice: (if gasPrice.isEmptyOrWhitespace: int.none else: gwei2Wei(parseFloat(gasPrice)).truncate(int).some),
|
||||
data: data
|
||||
)
|
||||
if isEIP1559Enabled:
|
||||
result.txType = "0x02"
|
||||
result.maxPriorityFeePerGas = if maxFeePerGas.isEmptyOrWhitespace: Uint256.none else: gwei2Wei(parseFloat(maxPriorityFeePerGas)).some
|
||||
result.maxFeePerGas = (if maxFeePerGas.isEmptyOrWhitespace: Uint256.none else: gwei2Wei(parseFloat(maxFeePerGas)).some)
|
||||
else:
|
||||
result.txType = "0x00"
|
||||
|
||||
proc buildTokenTransaction*(source, contractAddress: Address, gas = "", gasPrice = "", isEIP1559Enabled = false,
|
||||
maxPriorityFeePerGas = "", maxFeePerGas = ""): TransactionDataDto =
|
||||
result = buildTransaction(source, 0.u256, gas, gasPrice, isEIP1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
|
||||
result.to = contractAddress.some
|
||||
|
||||
proc label*(username:string): string =
|
||||
var node:array[32, byte] = keccak_256.digest(username.toLower()).data
|
||||
result = "0x" & node.toHex()
|
||||
|
||||
proc getExpirationTime*(toAddress: Address, data: string): int =
|
||||
try:
|
||||
var tx = buildTransaction(parseAddress("0x0000000000000000000000000000000000000000"), 0.u256)
|
||||
tx.to = toAddress.some
|
||||
tx.data = data
|
||||
|
||||
let payload = %*[%tx, "latest"]
|
||||
let response = status_eth.doEthCall(payload)
|
||||
result = fromHex[int](response.result.getStr)
|
||||
except RpcException as e:
|
||||
error "Error obtaining expiration time", err=e.msg
|
||||
|
||||
proc getPrice*(ensUsernamesContract: ContractDto): Stuint[256] =
|
||||
try:
|
||||
let payload = %* [{
|
||||
"to": $ensUsernamesContract.address,
|
||||
"data": ensUsernamesContract.methods["getPrice"].encodeAbi()
|
||||
}, "latest"]
|
||||
|
||||
let response = status_eth.doEthCall(payload)
|
||||
if not response.error.isNil:
|
||||
error "Error getting ens username price, ", errDescription=response.error.message
|
||||
if response.result.getStr == "0x":
|
||||
error "Error getting ens username price: 0x"
|
||||
|
||||
result = fromHex(Stuint[256], response.result.getStr)
|
||||
except RpcException as e:
|
||||
error "Error obtaining expiration time", err=e.msg
|
||||
|
||||
proc hex2Token*(input: string, decimals: int): string =
|
||||
var value = fromHex(Stuint[256], input)
|
||||
|
||||
if decimals == 0:
|
||||
return fmt"{value}"
|
||||
|
||||
var p = u256(10).pow(decimals)
|
||||
var i = value.div(p)
|
||||
var r = value.mod(p)
|
||||
var leading_zeros = "0".repeat(decimals - ($r).len)
|
||||
var d = fmt"{leading_zeros}{$r}"
|
||||
result = $i
|
||||
if(r > 0): result = fmt"{result}.{d}"
|
@ -9,6 +9,8 @@ import ./method_dto
|
||||
|
||||
import status/statusgo_backend_new/eth as status_eth
|
||||
|
||||
export method_dto
|
||||
|
||||
include ../../../common/json_utils
|
||||
|
||||
type
|
||||
|
@ -2,14 +2,6 @@ import strutils, json
|
||||
import web3/ethtypes, web3/conversions, options, stint
|
||||
import ../utils
|
||||
|
||||
type
|
||||
PendingTransactionTypeDto* {.pure.} = enum
|
||||
RegisterENS = "RegisterENS",
|
||||
SetPubKey = "SetPubKey",
|
||||
ReleaseENS = "ReleaseENS",
|
||||
BuyStickerPack = "BuyStickerPack"
|
||||
WalletTransfer = "WalletTransfer"
|
||||
|
||||
type
|
||||
TransactionDataDto* = object
|
||||
source*: Address # the address the transaction is send from.
|
||||
|
@ -4,20 +4,9 @@ import web3/ethtypes, json_serialization, chronicles, tables
|
||||
import status/statusgo_backend_new/eth
|
||||
|
||||
import utils
|
||||
import ./dto/contract
|
||||
import ./dto/method_dto
|
||||
import ./dto/network
|
||||
import ./dto/coder
|
||||
import ./dto/edn_dto
|
||||
import ./dto/transaction
|
||||
import ./service_interface
|
||||
|
||||
export service_interface
|
||||
export coder
|
||||
export edn_dto
|
||||
export contract
|
||||
export method_dto
|
||||
export transaction
|
||||
|
||||
logScope:
|
||||
topics = "eth-service"
|
||||
@ -34,12 +23,12 @@ proc newService*(): Service =
|
||||
result.contracts = @[]
|
||||
|
||||
# Forward declaration
|
||||
method initContracts(self: Service)
|
||||
proc initContracts(self: Service)
|
||||
|
||||
method init*(self: Service) =
|
||||
self.initContracts()
|
||||
|
||||
method initContracts(self: Service) =
|
||||
proc initContracts(self: Service) =
|
||||
self.contracts = @[
|
||||
# Mainnet contracts
|
||||
newErc20Contract("Status Network Token", Mainnet, parseAddress("0x744d70fdbe2ba4cf95131626614a1763df805b9e"), "SNT", 18, true),
|
||||
@ -221,7 +210,7 @@ method initContracts(self: Service) =
|
||||
newErc20Contract("Orchid", Mainnet, parseAddress("0x4575f41308EC1483f3d399aa9a2826d74Da13Deb"), "OXT", 18, false),
|
||||
]
|
||||
|
||||
method allContracts(self: Service): seq[ContractDto] =
|
||||
proc allContracts(self: Service): seq[ContractDto] =
|
||||
result = self.contracts
|
||||
|
||||
method findByAddress*(self: Service, contracts: seq[Erc20ContractDto], address: Address): Erc20ContractDto =
|
||||
@ -254,22 +243,3 @@ method allErc721ContractsByChainId*(self: Service, chainId: int): seq[Erc721Cont
|
||||
method findErc721Contract*(self: Service, chainId: int, name: string): Erc721ContractDto =
|
||||
let found = self.allErc721ContractsByChainId(chainId).filter(contract => contract.name.toLower == name.toLower)
|
||||
result = if found.len > 0: found[0] else: nil
|
||||
|
||||
method buildTransaction*(self: Service, source: Address, value: Uint256, gas = "", gasPrice = "", isEIP1559Enabled = false, maxPriorityFeePerGas = "", maxFeePerGas = "", data = ""): TransactionDataDto =
|
||||
result = TransactionDataDto(
|
||||
source: source,
|
||||
value: value.some,
|
||||
gas: (if gas.isEmptyOrWhitespace: Quantity.none else: Quantity(cast[uint64](parseFloat(gas).toUInt64)).some),
|
||||
gasPrice: (if gasPrice.isEmptyOrWhitespace: int.none else: gwei2Wei(parseFloat(gasPrice)).truncate(int).some),
|
||||
data: data
|
||||
)
|
||||
if isEIP1559Enabled:
|
||||
result.txType = "0x02"
|
||||
result.maxPriorityFeePerGas = if maxFeePerGas.isEmptyOrWhitespace: Uint256.none else: gwei2Wei(parseFloat(maxPriorityFeePerGas)).some
|
||||
result.maxFeePerGas = (if maxFeePerGas.isEmptyOrWhitespace: Uint256.none else: gwei2Wei(parseFloat(maxFeePerGas)).some)
|
||||
else:
|
||||
result.txType = "0x00"
|
||||
|
||||
method buildTokenTransaction*(self: Service, source, contractAddress: Address, gas = "", gasPrice = "", isEIP1559Enabled = false, maxPriorityFeePerGas = "", maxFeePerGas = ""): TransactionDataDto =
|
||||
result = self.buildTransaction(source, 0.u256, gas, gasPrice, isEIP1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
|
||||
result.to = contractAddress.some
|
||||
|
@ -1,3 +1,17 @@
|
||||
import web3/ethtypes
|
||||
import ./dto/contract
|
||||
import ./dto/method_dto
|
||||
import ./dto/network
|
||||
import ./dto/coder
|
||||
import ./dto/edn_dto
|
||||
import ./dto/transaction
|
||||
|
||||
export contract
|
||||
export method_dto
|
||||
export network
|
||||
export coder
|
||||
export edn_dto
|
||||
export transaction
|
||||
|
||||
type
|
||||
ServiceInterface* {.pure inheritable.} = ref object of RootObj
|
||||
@ -8,3 +22,32 @@ method delete*(self: ServiceInterface) {.base.} =
|
||||
|
||||
method init*(self: ServiceInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method findByAddress*(self: ServiceInterface, contracts: seq[Erc20ContractDto], address: Address): Erc20ContractDto
|
||||
{.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method findBySymbol*(self: ServiceInterface, contracts: seq[Erc20ContractDto], symbol: string): Erc20ContractDto
|
||||
{.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method findContract*(self: ServiceInterface, chainId: int, name: string): ContractDto {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method allErc20Contracts*(self: ServiceInterface): seq[Erc20ContractDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method allErc20ContractsByChainId*(self: ServiceInterface, chainId: int): seq[Erc20ContractDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method findErc20Contract*(self: ServiceInterface, chainId: int, symbol: string): Erc20ContractDto {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method findErc20Contract*(self: ServiceInterface, chainId: int, address: Address): Erc20ContractDto {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method allErc721ContractsByChainId*(self: ServiceInterface, chainId: int): seq[Erc721ContractDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method findErc721Contract*(self: ServiceInterface, chainId: int, name: string): Erc721ContractDto {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
@ -7,9 +7,12 @@ from sugar import `=>`, `->`
|
||||
import stint
|
||||
from times import getTime, toUnix, nanosecond
|
||||
import signing_phrases
|
||||
from web3 import Address, fromHex
|
||||
import web3/ethhexstrings
|
||||
|
||||
import ../../common/conversion as common_conversion
|
||||
|
||||
export common_conversion
|
||||
|
||||
proc decodeContentHash*(value: string): string =
|
||||
if value == "":
|
||||
return ""
|
||||
@ -104,46 +107,6 @@ proc toStUInt*[bits: static[int]](flt: float, T: typedesc[StUint[bits]]): T =
|
||||
else:
|
||||
result = parse("0", StUint[bits])
|
||||
|
||||
proc toUInt256*(flt: float): UInt256 =
|
||||
toStUInt(flt, StUInt[256])
|
||||
|
||||
proc toUInt64*(flt: float): StUInt[64] =
|
||||
toStUInt(flt, StUInt[64])
|
||||
|
||||
proc eth2Wei*(eth: float, decimals: int = 18): UInt256 =
|
||||
let weiValue = eth * parseFloat(alignLeft("1", decimals + 1, '0'))
|
||||
weiValue.toUInt256
|
||||
|
||||
proc gwei2Wei*(gwei: float): UInt256 =
|
||||
eth2Wei(gwei, 9)
|
||||
|
||||
proc wei2Eth*(input: Stuint[256], decimals: int = 18): string =
|
||||
var one_eth = u256(10).pow(decimals) # fromHex(Stuint[256], "DE0B6B3A7640000")
|
||||
|
||||
var (eth, remainder) = divmod(input, one_eth)
|
||||
let leading_zeros = "0".repeat(($one_eth).len - ($remainder).len - 1)
|
||||
|
||||
fmt"{eth}.{leading_zeros}{remainder}"
|
||||
|
||||
proc wei2Eth*(input: string, decimals: int): string =
|
||||
try:
|
||||
var input256: Stuint[256]
|
||||
if input.contains("e+"): # we have a js string BN, ie 1e+21
|
||||
let
|
||||
inputSplit = input.split("e+")
|
||||
whole = inputSplit[0].u256
|
||||
remainder = u256(10).pow(inputSplit[1].parseInt)
|
||||
input256 = whole * remainder
|
||||
else:
|
||||
input256 = input.u256
|
||||
result = wei2Eth(input256, decimals)
|
||||
except Exception as e:
|
||||
error "Error parsing this wei value", input, msg=e.msg
|
||||
result = "0"
|
||||
|
||||
proc wei2Gwei*(input: string): string =
|
||||
result = wei2Eth(input, 9)
|
||||
|
||||
proc first*(jArray: JsonNode, fieldName, id: string): JsonNode =
|
||||
if jArray == nil:
|
||||
return nil
|
||||
@ -184,16 +147,6 @@ proc find*[T](s: seq[T], pred: proc(x: T): bool {.closure.}, found: var bool): T
|
||||
result = results[0]
|
||||
found = true
|
||||
|
||||
proc parseAddress*(strAddress: string): Address =
|
||||
fromHex(Address, strAddress)
|
||||
|
||||
proc isAddress*(strAddress: string): bool =
|
||||
try:
|
||||
discard parseAddress(strAddress)
|
||||
except:
|
||||
return false
|
||||
return true
|
||||
|
||||
proc validateTransactionInput*(from_addr, to_addr, assetAddress, value, gas, gasPrice, data: string, isEIP1599Enabled: bool, maxPriorityFeePerGas, maxFeePerGas, uuid: string) =
|
||||
if not isAddress(from_addr): raise newException(ValueError, "from_addr is not a valid ETH address")
|
||||
if not isAddress(to_addr): raise newException(ValueError, "to_addr is not a valid ETH address")
|
||||
|
@ -3,11 +3,9 @@ import options
|
||||
|
||||
import status/statusgo_backend_new/network as status_network
|
||||
import ./service_interface
|
||||
import ./dto
|
||||
import ./types
|
||||
|
||||
export service_interface
|
||||
export dto, types
|
||||
|
||||
|
||||
logScope:
|
||||
topics = "network-service"
|
||||
|
@ -1,6 +1,6 @@
|
||||
import dto, types
|
||||
|
||||
export dto
|
||||
export dto, types
|
||||
|
||||
type
|
||||
ServiceInterface* {.pure inheritable.} = ref object of RootObj
|
||||
|
@ -10,10 +10,10 @@ import json, tables, json_serialization
|
||||
|
||||
import status/statusgo_backend_new/stickers as status_stickers
|
||||
import status/statusgo_backend_new/chat as status_chat
|
||||
import status/statusgo_backend_new/transactions as transactions
|
||||
import status/statusgo_backend_new/response_type
|
||||
import status/statusgo_backend_new/eth
|
||||
import ./dto/stickers
|
||||
import ../ens/utils as ens_utils
|
||||
import ../eth/service as eth_service
|
||||
import ../settings/service as settings_service
|
||||
import ../wallet_account/service as wallet_account_service
|
||||
@ -126,7 +126,7 @@ QtObject:
|
||||
buyToken = BuyToken(packId: packId, address: address, price: price)
|
||||
buyTxAbiEncoded = stickerMktContract.methods["buyToken"].encodeAbi(buyToken)
|
||||
approveAndCall = ApproveAndCall[100](to: stickerMktContract.address, value: price, data: DynamicBytes[100].fromHex(buyTxAbiEncoded))
|
||||
self.eth_service.buildTokenTransaction(address, sntContract.address, gas, gasPrice, isEIP1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
|
||||
ens_utils.buildTokenTransaction(address, sntContract.address, gas, gasPrice, isEIP1559Enabled, maxPriorityFeePerGas, maxFeePerGas)
|
||||
|
||||
proc buyPack*(self: Service, packId: int, address, price, gas, gasPrice: string, isEIP1559Enabled: bool, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, success: var bool): string =
|
||||
var
|
||||
@ -147,11 +147,11 @@ QtObject:
|
||||
|
||||
result = sntContract.methods["approveAndCall"].send(tx, approveAndCall, password, success)
|
||||
if success:
|
||||
discard transactions.trackPendingTransaction(
|
||||
self.transactionService.trackPendingTransaction(
|
||||
result,
|
||||
address,
|
||||
$sntContract.address,
|
||||
transactions.PendingTransactionType.BuyStickerPack,
|
||||
$PendingTransactionTypeDto.BuyStickerPack,
|
||||
$packId
|
||||
)
|
||||
|
||||
@ -254,7 +254,7 @@ QtObject:
|
||||
var pendingStickerPacks = initHashSet[int]()
|
||||
if (pendingTransactions != ""):
|
||||
for trx in pendingTransactions.parseJson{"result"}.getElems():
|
||||
if trx["type"].getStr == $PendingTransactionType.BuyStickerPack:
|
||||
if trx["type"].getStr == $PendingTransactionTypeDto.BuyStickerPack:
|
||||
pendingStickerPacks.incl(trx["additionalData"].getStr.parseInt)
|
||||
|
||||
for stickerPack in availableStickers:
|
||||
|
@ -1,6 +1,5 @@
|
||||
# include strformat, json
|
||||
include ../../common/json_utils
|
||||
include ../../../app/core/tasks/common
|
||||
import ../eth/dto/contract
|
||||
import ../eth/utils
|
||||
|
||||
|
@ -1,7 +1,3 @@
|
||||
include ../../common/json_utils
|
||||
include ../../../app/core/tasks/common
|
||||
import strutils
|
||||
|
||||
#################################################
|
||||
# Async load transactions
|
||||
#################################################
|
||||
|
@ -1,6 +1,17 @@
|
||||
import json, strutils, stint
|
||||
include ../../common/json_utils
|
||||
|
||||
type
|
||||
PendingTransactionTypeDto* {.pure.} = enum
|
||||
RegisterENS = "RegisterENS",
|
||||
SetPubKey = "SetPubKey",
|
||||
ReleaseENS = "ReleaseENS",
|
||||
BuyStickerPack = "BuyStickerPack"
|
||||
WalletTransfer = "WalletTransfer"
|
||||
|
||||
proc event*(self:PendingTransactionTypeDto):string =
|
||||
result = "transaction:" & $self
|
||||
|
||||
type
|
||||
TransactionDto* = ref object of RootObj
|
||||
id*: string
|
||||
|
@ -1,23 +1,31 @@
|
||||
import NimQml, chronicles, sequtils, sugar, stint, json
|
||||
import NimQml, chronicles, sequtils, sugar, stint, strutils, json
|
||||
import status/statusgo_backend_new/transactions as transactions
|
||||
import status/statusgo_backend_new/wallet as status_wallet
|
||||
|
||||
import ../../../app/core/[main]
|
||||
import ../../../app/core/tasks/[qt, threadpool]
|
||||
import ../wallet_account/service as wallet_account_service
|
||||
import ./service_interface, ./dto
|
||||
import ./dto as transaction_dto
|
||||
import ../eth/utils as eth_utils
|
||||
|
||||
export service_interface
|
||||
export transaction_dto
|
||||
|
||||
logScope:
|
||||
topics = "transaction-service"
|
||||
|
||||
include async_tasks
|
||||
include ../../common/json_utils
|
||||
|
||||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_TRANSACTIONS_LOADED* = "transactionsLoaded"
|
||||
|
||||
type
|
||||
TransactionMinedArgs* = ref object of Args
|
||||
data*: string
|
||||
transactionHash*: string
|
||||
success*: bool
|
||||
revertReason*: string
|
||||
|
||||
type
|
||||
TransactionsLoadedArgs* = ref object of Args
|
||||
transactions*: seq[TransactionDto]
|
||||
@ -63,6 +71,14 @@ QtObject:
|
||||
error "error: ", errDesription
|
||||
return
|
||||
|
||||
proc trackPendingTransaction*(self: Service, hash: string, fromAddress: string, toAddress: string, trxType: string,
|
||||
data: string) =
|
||||
try:
|
||||
discard transactions.trackPendingTransaction(hash, fromAddress, toAddress, trxType, data)
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error: ", errDesription
|
||||
|
||||
proc getTransfersByAddress*(self: Service, address: string, toBlock: Uint256, limit: int, loadMore: bool = false): seq[TransactionDto] =
|
||||
try:
|
||||
let limitAsHex = "0x" & eth_utils.stripLeadingZeros(limit.toHex)
|
||||
|
@ -1,22 +0,0 @@
|
||||
import dto, stint
|
||||
|
||||
export dto
|
||||
|
||||
type
|
||||
ServiceInterface* {.pure inheritable.} = ref object of RootObj
|
||||
## Abstract class for this service access.
|
||||
|
||||
method delete*(self: ServiceInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method init*(self: ServiceInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method checkRecentHistory*(self: ServiceInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getTransfersByAddress*(self: ServiceInterface, address: string, toBlock: Uint256, limit: int, loadMore: bool = false): seq[TransactionDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getTransfersByAddressTemp*(self: ServiceInterface, address: string, toBlock: Uint256, limit: int, loadMore: bool = false): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
@ -159,6 +159,9 @@ method buildTokens(
|
||||
)
|
||||
)
|
||||
|
||||
method getPrice*(self: Service, crypto: string, fiat: string): float64 =
|
||||
return fetchPrice(crypto, fiat)
|
||||
|
||||
method fetchPrices(self: Service): Table[string, float64] =
|
||||
let currency = self.settingsService.getCurrency()
|
||||
var prices = {"ETH": fetchPrice("ETH", currency)}.toTable
|
||||
@ -193,6 +196,8 @@ method getWalletAccounts*(self: Service): seq[WalletAccountDto] =
|
||||
return toSeq(self.accounts.values)
|
||||
|
||||
method getWalletAccount*(self: Service, accountIndex: int): WalletAccountDto =
|
||||
if(accountIndex < 0 or accountIndex >= self.getWalletAccounts().len):
|
||||
return
|
||||
return self.getWalletAccounts()[accountIndex]
|
||||
|
||||
method getCurrencyBalance*(self: Service): float64 =
|
||||
|
@ -47,3 +47,6 @@ method updateWalletAccount*(self: ServiceInterface, address: string, accountName
|
||||
|
||||
method toggleTokenVisible*(self: ServiceInterface, symbol: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getPrice*(self: ServiceInterface, crypto: string, fiat: string): float64 {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
@ -101,7 +101,6 @@ StatusModal {
|
||||
anchors.top: separator.bottom
|
||||
anchors.topMargin: 10
|
||||
width: stack.width
|
||||
isContact: root.isContact
|
||||
onSelectedRecipientChanged: {
|
||||
addressRequiredValidator.address = root.isRequested ? selectFromAccount.selectedAccount.address : selectRecipient.selectedRecipient.address
|
||||
}
|
||||
|
@ -56,8 +56,7 @@ StatusAppTwoPanelLayout {
|
||||
|
||||
EnsView {
|
||||
id: ensContainer
|
||||
store: profileView.store
|
||||
messageStore: profileView.globalStore.messageStore
|
||||
ensUsernamesStore: profileView.store.ensUsernamesStore
|
||||
contactsStore: profileView.store.contactsStore
|
||||
profileContentWidth: _internal.profileContentWidth
|
||||
}
|
||||
|
@ -15,24 +15,23 @@ ModalPopup {
|
||||
//% "Primary username"
|
||||
title: qsTrId("ens-primary-username")
|
||||
|
||||
property var ensUsernamesStore
|
||||
property string newUsername: ""
|
||||
|
||||
onOpened: {
|
||||
for(var i in ensNames.contentItem.children){
|
||||
// Not Refactored Yet
|
||||
// ensNames.contentItem.children[i].checked = ensNames.contentItem.children[i].text === profileModel.ens.preferredUsername
|
||||
ensNames.contentItem.children[i].checked = ensNames.contentItem.children[i].text === popup.ensUsernamesStore.preferredUsername
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: lbl1
|
||||
// Not Refactored Yet
|
||||
// text: profileModel.ens.preferredUsername ?
|
||||
// //% "Your messages are displayed to others with this username:"
|
||||
// qsTrId("your-messages-are-displayed-to-others-with-this-username-")
|
||||
// :
|
||||
// //% "Once you select a username, you won’t be able to disable it afterwards. You will only be able choose a different username to display."
|
||||
// qsTrId("once-you-select-a-username--you-won-t-be-able-to-disable-it-afterwards--you-will-only-be-able-choose-a-different-username-to-display-")
|
||||
text: popup.ensUsernamesStore.preferredUsername ?
|
||||
//% "Your messages are displayed to others with this username:"
|
||||
qsTrId("your-messages-are-displayed-to-others-with-this-username-")
|
||||
:
|
||||
//% "Once you select a username, you won’t be able to disable it afterwards. You will only be able choose a different username to display."
|
||||
qsTrId("once-you-select-a-username--you-won-t-be-able-to-disable-it-afterwards--you-will-only-be-able-choose-a-different-username-to-display-")
|
||||
font.pixelSize: 15
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
@ -42,8 +41,7 @@ ModalPopup {
|
||||
id: lbl2
|
||||
anchors.top: lbl1.bottom
|
||||
anchors.topMargin: Style.current.padding
|
||||
// Not Refactored Yet
|
||||
// text: profileModel.ens.preferredUsername
|
||||
text: popup.ensUsernamesStore.preferredUsername
|
||||
font.pixelSize: 17
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
@ -60,16 +58,14 @@ ModalPopup {
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
// Not Refactored Yet
|
||||
// model: profileModel.ens
|
||||
model: root.ensUsernamesStore.ensUsernamesModel
|
||||
spacing: 0
|
||||
clip: true
|
||||
id: ensNames
|
||||
delegate: RadioDelegate {
|
||||
id: radioDelegate
|
||||
text: username
|
||||
// Not Refactored Yet
|
||||
// checked: profileModel.ens.preferredUsername === username
|
||||
text: ensUsername
|
||||
checked: popup.ensUsernamesStore.preferredUsername === ensUsername
|
||||
|
||||
contentItem: StyledText {
|
||||
color: Style.current.textColor
|
||||
@ -82,7 +78,7 @@ ModalPopup {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
parent.checked = true
|
||||
newUsername = username;
|
||||
newUsername = ensUsername;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,8 +86,7 @@ ModalPopup {
|
||||
}
|
||||
|
||||
onNewUsernameChanged: {
|
||||
// Not Refactored Yet
|
||||
// btnSelectPreferred.state = newUsername === profileModel.ens.preferredUsername ? "inactive" : "active"
|
||||
btnSelectPreferred.state = newUsername === popup.ensUsernamesStore.preferredUsername ? "inactive" : "active"
|
||||
}
|
||||
|
||||
footer: Item {
|
||||
@ -135,10 +130,9 @@ ModalPopup {
|
||||
anchors.fill: parent
|
||||
onClicked : {
|
||||
if(btnSelectPreferred.state === "active"){
|
||||
// Not Refactored Yet
|
||||
// profileModel.ens.preferredUsername = newUsername;
|
||||
// newUsername = "";
|
||||
// popup.close();
|
||||
popup.ensUsernamesStore.setPrefferedEnsUsername(newUsername);
|
||||
newUsername = "";
|
||||
popup.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
157
ui/app/AppLayouts/Profile/stores/EnsUsernamesStore.qml
Normal file
157
ui/app/AppLayouts/Profile/stores/EnsUsernamesStore.qml
Normal file
@ -0,0 +1,157 @@
|
||||
import QtQuick 2.13
|
||||
import utils 1.0
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
property var ensUsernamesModule
|
||||
|
||||
property var ensUsernamesModel: root.ensUsernamesModule ? ensUsernamesModule.model : []
|
||||
|
||||
property string pubkey: userProfile.pubKey
|
||||
property string icon: userProfile.icon
|
||||
property bool isIdenticon: userProfile.isIdenticon
|
||||
property string preferredUsername: userProfile.preferredName
|
||||
|
||||
property string username: userProfile.username
|
||||
property string gasPrice: root.ensUsernamesModule ? ensUsernamesModule.gasPrice : "0"
|
||||
|
||||
property var walletAccounts: walletSectionAccounts.model
|
||||
|
||||
function setPrefferedEnsUsername(ensName) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return
|
||||
ensUsernamesModule.setPrefferedEnsUsername(ensName)
|
||||
}
|
||||
|
||||
function checkEnsUsernameAvailability(ensName, isStatus) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return
|
||||
ensUsernamesModule.checkEnsUsernameAvailability(ensName, isStatus)
|
||||
}
|
||||
|
||||
function numOfPendingEnsUsernames() {
|
||||
if(!root.ensUsernamesModule)
|
||||
return 0
|
||||
ensUsernamesModule.numOfPendingEnsUsernames()
|
||||
}
|
||||
|
||||
function ensDetails(ensUsername) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
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) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.setPubKey(ensUsername, address, gas, gasPrice, maxPriorityFeePerGas, maxFeePerGas, password)
|
||||
}
|
||||
|
||||
function getEtherscanLink() {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getEtherscanLink()
|
||||
}
|
||||
|
||||
function getSigningPhrase() {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getSigningPhrase()
|
||||
}
|
||||
|
||||
function copyToClipboard(value) {
|
||||
globalUtils.copyToClipboard(value)
|
||||
}
|
||||
|
||||
function releaseEnsEstimate(ensUsername, address) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.releaseEnsEstimate(ensUsername, address)
|
||||
}
|
||||
|
||||
function releaseEns(ensUsername, address, gasLimit, gasPrice, password) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.releaseEns(ensUsername, address, gasLimit, gasPrice, password)
|
||||
}
|
||||
|
||||
function ensConnectOwnedUsername(name, isStatus) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return
|
||||
ensUsernamesModule.connectOwnedUsername(name, isStatus)
|
||||
}
|
||||
|
||||
function getEnsRegisteredAddress() {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getEnsRegisteredAddress()
|
||||
}
|
||||
|
||||
function registerEnsGasEstimate(ensUsername, address) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return 0
|
||||
return ensUsernamesModule.registerEnsGasEstimate(ensUsername, address)
|
||||
}
|
||||
|
||||
function registerEns(ensUsername, address, gasLimit, tipLimit, overallLimit, gasPrice, password) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.registerEns(ensUsername, address, gasLimit, tipLimit, overallLimit, gasPrice, password)
|
||||
}
|
||||
|
||||
function getEnsRegistry() {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getEnsRegistry()
|
||||
}
|
||||
|
||||
function getSntBalance() {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getSNTBalance()
|
||||
}
|
||||
|
||||
function getWalletDefaultAddress() {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getWalletDefaultAddress()
|
||||
}
|
||||
|
||||
function getCurrentCurrency() {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getCurrentCurrency()
|
||||
}
|
||||
|
||||
function getFiatValue(balance, cryptoSymbo, fiatSymbol) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getFiatValue(balance, cryptoSymbo, fiatSymbol)
|
||||
}
|
||||
|
||||
function getGasEthValue(gweiValue, gasLimit) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getGasEthValue(gweiValue, gasLimit)
|
||||
}
|
||||
|
||||
function getStatusToken() {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getStatusToken()
|
||||
}
|
||||
}
|
||||
|
@ -43,30 +43,12 @@ QtObject {
|
||||
privacyModule: profileSectionModuleInst.privacyModule
|
||||
}
|
||||
|
||||
// Not Refactored Yet
|
||||
// property var chatsModelInst: chatsModel
|
||||
// Not Refactored Yet
|
||||
// property var utilsModelInst: utilsModel
|
||||
// Not Refactored Yet
|
||||
// property var walletModelInst: walletModel
|
||||
// Not Refactored Yet
|
||||
// property var nodeModelInst: nodeModel
|
||||
property EnsUsernamesStore ensUsernamesStore: EnsUsernamesStore {
|
||||
ensUsernamesModule: profileSectionModuleInst.ensUsernamesModule
|
||||
}
|
||||
|
||||
// Not Refactored Yet
|
||||
// property var ens: profileModelInst.ens
|
||||
property var dappList: dappPermissionsModule.dapps
|
||||
property var permissionList: dappPermissionsModule.permissions
|
||||
// Not Refactored Yet
|
||||
// property var mutedChatsContacts: profileModelInst.mutedChats.contacts
|
||||
// property var mutedChats: profileModelInst.mutedChats.chats
|
||||
|
||||
// Not Refactored Yet
|
||||
property string ensRegisterAddress: "" //utilsModelInst.ensRegisterAddress
|
||||
// Not Refactored Yet
|
||||
property string etherscanLink: "" //walletModelInst.utilsView.etherscanLink
|
||||
// Not Refactored Yet
|
||||
// property string preferredUsername: userProfile.preferredName // was: profileModelInst.ens.preferredUsername
|
||||
// property string firstEnsUsername: userProfile.firstEnsName // was: profileModelInst.ens.firstEnsUsername
|
||||
|
||||
property int profile_id: 0
|
||||
property int contacts_id: 1
|
||||
@ -188,90 +170,6 @@ QtObject {
|
||||
dappPermissionsModule.fetchDapps()
|
||||
}
|
||||
|
||||
function ensDetails(username) {
|
||||
// Not Refactored Yet
|
||||
// profileModelInst.ens.details(username)
|
||||
}
|
||||
|
||||
function ensPendingLen() {
|
||||
// Not Refactored Yet
|
||||
// return profileModelInst.ens.pendingLen()
|
||||
}
|
||||
|
||||
function validateEns(ensName, isStatus) {
|
||||
// Not Refactored Yet
|
||||
// profileModelInst.ens.validate(ensName, isStatus)
|
||||
}
|
||||
|
||||
function registerEnsGasEstimate(username, address) {
|
||||
// Not Refactored Yet
|
||||
// return profileModelInst.ens.registerENSGasEstimate(username, address)
|
||||
}
|
||||
|
||||
function registerEns(username, address, gasLimit, tipLimit, overallLimit, gasPrice, password) {
|
||||
// Not Refactored Yet
|
||||
// return profileModelInst.ens.registerENS(username,
|
||||
// address, gasLimit, tipLimit, overallLimit, gasPrice, password)
|
||||
}
|
||||
|
||||
function getEnsUsernameRegistrar() {
|
||||
// Not Refactored Yet
|
||||
// return profileModelInst.ens.getUsernameRegistrar()
|
||||
}
|
||||
|
||||
function getEnsRegistry() {
|
||||
// Not Refactored Yet
|
||||
// return profileModelInst.ens.getENSRegistry()
|
||||
}
|
||||
|
||||
function releaseEnsEstimate(username, address) {
|
||||
// Not Refactored Yet
|
||||
// return profileModelInst.ens.releaseEstimate(username, address)
|
||||
}
|
||||
|
||||
function releaseEns(username, address, gasLimit, gasPrice, password) {
|
||||
// Not Refactored Yet
|
||||
// return profileModelInst.ens.release(username, address, gasLimit, gasPrice, password)
|
||||
}
|
||||
|
||||
function getGasPrice() {
|
||||
// Not Refactored Yet
|
||||
// walletModelInst.gasView.getGasPrice()
|
||||
}
|
||||
|
||||
function getGasPricePredictions() {
|
||||
// Not Refactored Yet
|
||||
// walletModelInst.gasView.getGasPricePredictions()
|
||||
}
|
||||
|
||||
function ensConnectOwnedUsername(name, isStatus) {
|
||||
// Not Refactored Yet
|
||||
// profileModelInst.ens.connectOwnedUsername(name, isStatus)
|
||||
}
|
||||
|
||||
function getWalletDefaultAddress() {
|
||||
// Not Refactored Yet
|
||||
// return walletModelInst.getDefaultAddress()
|
||||
}
|
||||
|
||||
function getSntBalance() {
|
||||
// Not Refactored Yet - This should be fetched from corresponding module, not from the global Utils
|
||||
// return utilsModelInst.getSNTBalance()
|
||||
}
|
||||
|
||||
function getNetworkName() {
|
||||
// Not Refactored Yet
|
||||
// return utilsModelInst.getNetworkName()
|
||||
}
|
||||
|
||||
function setBloomLevel(mode) {
|
||||
nodeModelInst.setBloomLevel(mode)
|
||||
}
|
||||
|
||||
function setWakuV2LightClient(mode) {
|
||||
nodeModelInst.setWakuV2LightClient(mode)
|
||||
}
|
||||
|
||||
function getCurrentVersion() {
|
||||
return aboutModuleInst.getCurrentVersion()
|
||||
}
|
||||
@ -283,24 +181,4 @@ QtObject {
|
||||
function checkForUpdates() {
|
||||
aboutModuleInst.checkForUpdates()
|
||||
}
|
||||
|
||||
function setPubKeyGasEstimate(username, address) {
|
||||
// Not Refactored Yet
|
||||
// return profileModelInst.ens.setPubKeyGasEstimate(username, address)
|
||||
}
|
||||
|
||||
function setPubKey(username, address, gasLimit, gasPrice, password) {
|
||||
// Not Refactored Yet
|
||||
// return profileModelInst.ens.setPubKey(username, address, gasLimit, gasPrice, password)
|
||||
}
|
||||
|
||||
function userNameOrAlias(pk) {
|
||||
// Not Refactored Yet
|
||||
// return chatsModelInst.userNameOrAlias(pk);
|
||||
}
|
||||
|
||||
function generateIdenticon(pk) {
|
||||
// Not Refactored Yet
|
||||
// return utilsModelInst.generateIdenticon(pk);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import shared.status 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var store
|
||||
property var ensUsernamesStore
|
||||
property var contactsStore
|
||||
property string username: ""
|
||||
property string walletAddress: "-"
|
||||
@ -50,15 +50,17 @@ Item {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.store.ens
|
||||
target: root.ensUsernamesStore.ensUsernamesModule
|
||||
onDetailsObtained: {
|
||||
if(username != ensName) return;
|
||||
if(username != ensName)
|
||||
return;
|
||||
walletAddressLbl.subTitle = address;
|
||||
keyLbl.subTitle = pubkey.substring(0, 20) + "..." + pubkey.substring(pubkey.length - 20);
|
||||
walletAddressLbl.visible = true;
|
||||
keyLbl.visible = true;
|
||||
releaseBtn.visible = isStatus
|
||||
releaseBtn.enabled = (Date.now() / 1000) > expirationTime && expirationTime > 0 && root.store.preferredUsername != username
|
||||
releaseBtn.enabled = (Date.now() / 1000) > expirationTime && expirationTime > 0 &&
|
||||
root.ensUsernamesStore.preferredUsername != username
|
||||
expiration = new Date(expirationTime * 1000).getTime()
|
||||
}
|
||||
onLoading: {
|
||||
@ -80,7 +82,7 @@ Item {
|
||||
icon.name: "copy"
|
||||
tooltip.text: qsTr("Copied to clipboard!")
|
||||
iconButton.onClicked: {
|
||||
root.store.copyToClipboard(subTitle)
|
||||
root.ensUsernamesStore.copyToClipboard(subTitle)
|
||||
tooltip.visible = !tooltip.visible
|
||||
}
|
||||
}
|
||||
@ -93,7 +95,7 @@ Item {
|
||||
icon.name: "copy"
|
||||
tooltip.text: qsTr("Copied to clipboard!")
|
||||
iconButton.onClicked: {
|
||||
root.store.copyToClipboard(subTitle)
|
||||
root.ensUsernamesStore.copyToClipboard(subTitle)
|
||||
tooltip.visible = !tooltip.visible
|
||||
}
|
||||
}
|
||||
@ -101,9 +103,10 @@ Item {
|
||||
Component {
|
||||
id: transactionDialogComponent
|
||||
StatusETHTransactionModal {
|
||||
ensUsernamesStore: root.ensUsernamesStore
|
||||
contactsStore: root.contactsStore
|
||||
onOpened: {
|
||||
root.store.getGasPricePredictions()
|
||||
root.ensUsernamesStore.fetchGasPrice()
|
||||
}
|
||||
title: qsTr("Connect username with your pubkey")
|
||||
onClosed: {
|
||||
@ -111,10 +114,10 @@ Item {
|
||||
}
|
||||
estimateGasFunction: function(selectedAccount) {
|
||||
if (username === "" || !selectedAccount) return 100000;
|
||||
return root.store.releaseEnsEstimate(Utils.removeStatusEns(username), selectedAccount.address)
|
||||
return root.ensUsernamesStore.releaseEnsEstimate(Utils.removeStatusEns(username), selectedAccount.address)
|
||||
}
|
||||
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password) {
|
||||
return root.store.releaseEns(username,
|
||||
return root.ensUsernamesStore.releaseEns(username,
|
||||
selectedAddress,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
|
@ -20,7 +20,8 @@ Item {
|
||||
signal addBtnClicked()
|
||||
signal selectEns(string username)
|
||||
|
||||
property var store
|
||||
property var ensUsernamesStore
|
||||
|
||||
property int profileContentWidth
|
||||
|
||||
// Defaults to show message
|
||||
@ -34,13 +35,11 @@ Item {
|
||||
property string authorPrevMsg: "1"
|
||||
property bool isText: true
|
||||
property var clickMessage: function(){}
|
||||
property string identicon: store.identicon
|
||||
//property string identicon: userProfile.icon
|
||||
property int timestamp: 1577872140
|
||||
property var messageStore
|
||||
|
||||
function shouldDisplayExampleMessage(){
|
||||
return store.ens.rowCount() > 0 && store.ensPendingLen() !== store.ens.rowCount() && store.preferredUsername !== ""
|
||||
return root.ensUsernamesStore.ensUsernamesModel.count > 0 &&
|
||||
root.ensUsernamesStore.numOfPendingEnsUsernames() !== root.ensUsernamesStore.ensUsernamesModel &&
|
||||
store.ensUsernamesStore.preferredUsername !== ""
|
||||
}
|
||||
anchors.fill: parent
|
||||
|
||||
@ -94,7 +93,7 @@ Item {
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: selectEns(model.username)
|
||||
onClicked: selectEns(model.ensUsername)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@ -117,8 +116,8 @@ Item {
|
||||
}
|
||||
|
||||
Loader {
|
||||
sourceComponent: model.username.endsWith(".stateofus.eth") ? statusENS : normalENS
|
||||
property string username: model.username
|
||||
sourceComponent: model.ensUsername.endsWith(".stateofus.eth") ? statusENS : normalENS
|
||||
property string username: model.ensUsername
|
||||
property bool isPending: model.isPending
|
||||
active: true
|
||||
anchors.left: circle.right
|
||||
@ -129,6 +128,7 @@ Item {
|
||||
|
||||
ENSPopup {
|
||||
id: ensPopup
|
||||
ensUsernamesStore: root.ensUsernamesStore
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
@ -209,7 +209,7 @@ Item {
|
||||
ListView {
|
||||
id: lvEns
|
||||
anchors.fill: parent
|
||||
model: root.store.ens
|
||||
model: root.ensUsernamesStore.ensUsernamesModel
|
||||
spacing: 10
|
||||
clip: true
|
||||
delegate: ensDelegate
|
||||
@ -225,7 +225,8 @@ Item {
|
||||
|
||||
StatusBaseText {
|
||||
id: chatSettingsLabel
|
||||
visible: root.store.ens.rowCount() > 0 && root.store.ensPendingLen() != root.store.ens.rowCount()
|
||||
visible: root.ensUsernamesStore.ensUsernamesModel.count > 0 &&
|
||||
root.ensUsernamesStore.numOfPendingEnsUsernames() != root.ensUsernamesStore.ensUsernamesModel.count
|
||||
//% "Chat settings"
|
||||
text: qsTrId("chat-settings")
|
||||
anchors.left: parent.left
|
||||
@ -258,7 +259,7 @@ Item {
|
||||
id: usernameLabel2
|
||||
visible: chatSettingsLabel.visible
|
||||
//% "None selected"
|
||||
text: root.store.preferredUsername || qsTrId("none-selected")
|
||||
text: root.ensUsernamesStore.preferredUsername || qsTrId("none-selected")
|
||||
anchors.left: usernameLabel.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
font.pixelSize: 14
|
||||
@ -284,10 +285,10 @@ Item {
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 20
|
||||
// isCurrentUser: root.isCurrentUser
|
||||
// profileImage: root.messageStore.profileImageSource
|
||||
// isMessage: root.messageStore.isMessage
|
||||
// identiconImageSource: root.messageStore.identicon
|
||||
|
||||
icon: root.ensUsernamesStore.icon
|
||||
isIdenticon: root.ensUsernamesStore.isIdenticon
|
||||
|
||||
onClickMessage: {
|
||||
root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply);
|
||||
}
|
||||
@ -295,19 +296,14 @@ Item {
|
||||
|
||||
UsernameLabel {
|
||||
id: chatName
|
||||
label.text: "@" + (root.store.preferredUsername.replace(".stateofus.eth", ""))
|
||||
label.color: Style.current.blue
|
||||
anchors.leftMargin: 20
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
anchors.left: chatImage.right
|
||||
// isCurrentUser: root.messageStore.isCurrentUser
|
||||
// userName: root.messageStore.userName
|
||||
// localName: root.messageStore.localName
|
||||
// displayUserName: root.messageStore.displayUserName
|
||||
onClickMessage: {
|
||||
root.parent.clickMessage(true, false, false, null, false, false, false);
|
||||
}
|
||||
|
||||
displayName: "@" + (root.ensUsernamesStore.preferredUsername.replace(".stateofus.eth", ""))
|
||||
localName: ""
|
||||
amISender: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@ -343,8 +339,8 @@ Item {
|
||||
anchors.bottomMargin: Style.current.padding
|
||||
anchors.right: chatBox.right
|
||||
anchors.rightMargin: Style.current.padding
|
||||
//timestamp: root.timestamp
|
||||
visible: root.messageStore.isMessage
|
||||
timestamp: new Date().getTime()
|
||||
visible: true
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
@ -360,10 +356,7 @@ Item {
|
||||
|
||||
|
||||
Connections {
|
||||
target: root.store.ens
|
||||
onPreferredUsernameChanged: {
|
||||
messagesShownAs.visible = shouldDisplayExampleMessage()
|
||||
}
|
||||
target: root.ensUsernamesStore.ensUsernamesModule
|
||||
onUsernameConfirmed: {
|
||||
messagesShownAs.visible = shouldDisplayExampleMessage()
|
||||
chatSettingsLabel.visible = true
|
||||
|
@ -15,7 +15,7 @@ import shared.controls 1.0
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var store
|
||||
property var ensUsernamesStore
|
||||
property var contactsStore
|
||||
property int profileContentWidth
|
||||
|
||||
@ -30,7 +30,7 @@ Item {
|
||||
property string ensStatus: ""
|
||||
|
||||
property var validateENS: Backpressure.debounce(root, 500, function (ensName, isStatus){
|
||||
store.validateEns(ensName, isStatus)
|
||||
root.ensUsernamesStore.checkEnsUsernameAvailability(ensName, isStatus)
|
||||
});
|
||||
|
||||
function validate(ensUsername) {
|
||||
@ -61,9 +61,10 @@ Item {
|
||||
Component {
|
||||
id: transactionDialogComponent
|
||||
StatusETHTransactionModal {
|
||||
ensUsernamesStore: root.ensUsernamesStore
|
||||
contactsStore: root.contactsStore
|
||||
onOpened: {
|
||||
root.store.getGasPrice()
|
||||
root.ensUsernamesStore.fetchGasPrice()
|
||||
}
|
||||
title: qsTr("Connect username with your pubkey")
|
||||
onClosed: {
|
||||
@ -71,13 +72,15 @@ Item {
|
||||
}
|
||||
estimateGasFunction: function(selectedAccount) {
|
||||
if (ensUsername.text === "" || !selectedAccount) return 80000;
|
||||
return root.store.setPubKeyGasEstimate(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ), selectedAccount.address)
|
||||
return root.ensUsernamesStore.setPubKeyGasEstimate(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ), selectedAccount.address)
|
||||
}
|
||||
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password) {
|
||||
return root.store.setPubKey(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ),
|
||||
return root.ensUsernamesStore.setPubKey(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ),
|
||||
selectedAddress,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
"",
|
||||
"",
|
||||
password)
|
||||
}
|
||||
onSuccess: function(){
|
||||
@ -148,25 +151,25 @@ Item {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: mainModule
|
||||
onResolvedENS: {
|
||||
target: root.ensUsernamesStore.ensUsernamesModule
|
||||
onUsernameAvailabilityChecked: {
|
||||
if(!validate(ensUsername.text)) return;
|
||||
valid = false;
|
||||
loading = false;
|
||||
ensStatus = ensResult;
|
||||
switch(ensResult){
|
||||
ensStatus = availabilityStatus;
|
||||
switch(availabilityStatus){
|
||||
case "available":
|
||||
case "owned":
|
||||
case "connected":
|
||||
case "connected-different-key":
|
||||
valid = true;
|
||||
validationMessage = Constants.ensState[ensResult]
|
||||
validationMessage = Constants.ensState[availabilityStatus]
|
||||
break;
|
||||
case "taken":
|
||||
validationMessage = Constants.ensState[!isStatus ? 'taken-custom' : 'taken']
|
||||
break;
|
||||
case "already-connected":
|
||||
validationMessage = Constants.ensState[ensResult]
|
||||
validationMessage = Constants.ensState[availabilityStatus]
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -189,7 +192,7 @@ Item {
|
||||
if(!valid) return;
|
||||
|
||||
if(ensStatus === Constants.ens_connected){
|
||||
root.store.ensConnectOwnedUsername(ensUsername.text, isStatus);
|
||||
root.ensUsernamesStore.ensConnectOwnedUsername(ensUsername.text, isStatus);
|
||||
continueClicked(ensStatus, ensUsername.text)
|
||||
return;
|
||||
}
|
||||
|
@ -14,10 +14,10 @@ import StatusQ.Components 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var store
|
||||
property string username: ""
|
||||
|
||||
readonly property string ensRegistry: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
|
||||
property var ensUsernamesStore
|
||||
property var contactsStore
|
||||
property string username: ""
|
||||
|
||||
signal backBtnClicked();
|
||||
signal usernameRegistered(userName: string);
|
||||
@ -45,14 +45,16 @@ Item {
|
||||
this.active = false // kill an opened instance
|
||||
}
|
||||
sourceComponent: StatusSNTTransactionModal {
|
||||
store: root.ensUsernamesStore
|
||||
contactsStore: root.contactsStore
|
||||
assetPrice: "10"
|
||||
contractAddress: root.store.ensRegisterAddress
|
||||
contractAddress: root.ensUsernamesStore.getEnsRegisteredAddress()
|
||||
estimateGasFunction: function(selectedAccount, uuid) {
|
||||
if (username === "" || !selectedAccount) return 380000;
|
||||
return root.store.registerEnsGasEstimate(username, selectedAccount.address)
|
||||
return root.ensUsernamesStore.registerEnsGasEstimate(username, selectedAccount.address)
|
||||
}
|
||||
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password) {
|
||||
return root.store.registerEns(
|
||||
return root.ensUsernamesStore.registerEns(
|
||||
username,
|
||||
selectedAddress,
|
||||
gasLimit,
|
||||
@ -165,7 +167,7 @@ Item {
|
||||
|
||||
StatusBaseText {
|
||||
//% "%1 (Status UsernameRegistrar)."
|
||||
text: qsTrId("-1--status-usernameregistrar--").arg(root.store.getEnsUsernameRegistrar())
|
||||
text: qsTrId("-1--status-usernameregistrar--").arg(root.ensUsernamesStore.getEnsRegisteredAddress())
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
@ -175,7 +177,9 @@ Item {
|
||||
|
||||
StatusBaseText {
|
||||
//% "<a href='%1%2'>Look up on Etherscan</a>"
|
||||
text: qsTrId("-a-href---1-2--look-up-on-etherscan--a-").arg(root.store.etherscanLink.replace("/tx", "/address")).arg(root.store.getEnsUsernameRegistrar())
|
||||
text: qsTrId("-a-href---1-2--look-up-on-etherscan--a-")
|
||||
.arg(root.ensUsernamesStore.getEtherscanLink())
|
||||
.arg(root.ensUsernamesStore.getEnsRegisteredAddress())
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
onLinkActivated: Global.openLink(link)
|
||||
@ -189,7 +193,7 @@ Item {
|
||||
|
||||
StatusBaseText {
|
||||
//% "%1 (ENS Registry)."
|
||||
text: qsTrId("-1--ens-registry--").arg(root.ensRegistry)
|
||||
text: qsTrId("-1--ens-registry--").arg(root.ensUsernamesStore.getEnsRegistry())
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
@ -199,7 +203,9 @@ Item {
|
||||
|
||||
StatusBaseText {
|
||||
//% "<a href='%1%2'>Look up on Etherscan</a>"
|
||||
text: qsTrId("-a-href---1-2--look-up-on-etherscan--a-").arg(root.store.etherscanLink.replace("/tx", "/address")).arg(root.ensRegistry)
|
||||
text: qsTrId("-a-href---1-2--look-up-on-etherscan--a-")
|
||||
.arg(root.ensUsernamesStore.getEtherscanLink())
|
||||
.arg(root.ensUsernamesStore.getEnsRegistry())
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
onLinkActivated: Global.openLink(link)
|
||||
@ -270,11 +276,11 @@ Item {
|
||||
id: walletAddressLbl
|
||||
//% "Wallet address"
|
||||
title: qsTrId("wallet-address")
|
||||
subTitle: root.store.getWalletDefaultAddress()
|
||||
subTitle: root.ensUsernamesStore.getWalletDefaultAddress()
|
||||
tooltip.text: qsTr("Copied to clipboard!")
|
||||
icon.name: "copy"
|
||||
iconButton.onClicked: {
|
||||
root.store.copyToClipboard(subTitle)
|
||||
root.ensUsernamesStore.copyToClipboard(subTitle)
|
||||
tooltip.visible = !tooltip.visible
|
||||
}
|
||||
anchors.top: ensUsername.bottom
|
||||
@ -286,13 +292,13 @@ Item {
|
||||
//% "Key"
|
||||
title: qsTrId("key")
|
||||
subTitle: {
|
||||
let pubKey = root.store.pubKey;
|
||||
let pubKey = root.ensUsernamesStore.pubkey;
|
||||
return pubKey.substring(0, 20) + "..." + pubKey.substring(pubKey.length - 20);
|
||||
}
|
||||
tooltip.text: qsTr("Copied to clipboard!")
|
||||
icon.name: "copy"
|
||||
iconButton.onClicked: {
|
||||
root.store.copyToClipboard(root.store.pubKey)
|
||||
root.ensUsernamesStore.copyToClipboard(root.ensUsernamesStore.pubkey)
|
||||
tooltip.visible = !tooltip.visible
|
||||
}
|
||||
anchors.top: walletAddressLbl.bottom
|
||||
@ -345,7 +351,7 @@ Item {
|
||||
id: image1
|
||||
height: 50
|
||||
width: height
|
||||
source: Style.svg("status-logo")
|
||||
source: Style.png("tokens/SNT")
|
||||
sourceSize: Qt.size(width, height)
|
||||
}
|
||||
|
||||
@ -378,12 +384,12 @@ Item {
|
||||
anchors.bottomMargin: Style.current.padding
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.padding
|
||||
text: parseFloat(root.store.getSntBalance()) < 10 ?
|
||||
text: parseFloat(root.ensUsernamesStore.getSntBalance()) < 10 ?
|
||||
//% "Not enough SNT"
|
||||
qsTrId("not-enough-snt") :
|
||||
//% "Register"
|
||||
qsTrId("ens-register")
|
||||
enabled: parseFloat(root.store.getSntBalance()) >= 10 && termsAndConditionsCheckbox.checked
|
||||
enabled: parseFloat(root.ensUsernamesStore.getSntBalance()) >= 10 && termsAndConditionsCheckbox.checked
|
||||
onClicked: localAccountSensitiveSettings.isWalletEnabled ? transactionDialog.open() : confirmationPopup.open()
|
||||
}
|
||||
|
||||
|
@ -11,10 +11,10 @@ import "../stores"
|
||||
Item {
|
||||
id: ensView
|
||||
|
||||
property var store
|
||||
property EnsUsernamesStore ensUsernamesStore
|
||||
|
||||
property var contactsStore
|
||||
|
||||
property var messageStore
|
||||
property int profileContentWidth
|
||||
property bool showSearchScreen: false
|
||||
property string addedUsername: ""
|
||||
@ -29,7 +29,7 @@ Item {
|
||||
signal goToList();
|
||||
|
||||
function goToStart(){
|
||||
if(ensView.store.ens.rowCount() > 0 && Global.networkGuarded){
|
||||
if(ensView.ensUsernamesStore.ensUsernamesModel.count > 0 && Global.networkGuarded){
|
||||
goToList();
|
||||
} else {
|
||||
goToWelcome();
|
||||
@ -213,7 +213,7 @@ Item {
|
||||
Component {
|
||||
id: welcome
|
||||
EnsWelcomeView {
|
||||
username: ensView.store.username
|
||||
username: ensView.ensUsernamesStore.username
|
||||
onStartBtnClicked: next(null)
|
||||
profileContentWidth: ensView.profileContentWidth
|
||||
}
|
||||
@ -222,7 +222,7 @@ Item {
|
||||
Component {
|
||||
id: search
|
||||
EnsSearchView {
|
||||
store: ensView.store
|
||||
ensUsernamesStore: ensView.ensUsernamesStore
|
||||
contactsStore: ensView.contactsStore
|
||||
profileContentWidth: ensView.profileContentWidth
|
||||
onContinueClicked: {
|
||||
@ -243,7 +243,8 @@ Item {
|
||||
Component {
|
||||
id: termsAndConditions
|
||||
EnsTermsAndConditionsView {
|
||||
store: ensView.store
|
||||
ensUsernamesStore: ensView.ensUsernamesStore
|
||||
contactsStore: ensView.contactsStore
|
||||
username: selectedUsername
|
||||
onBackBtnClicked: back();
|
||||
onUsernameRegistered: done(userName);
|
||||
@ -284,12 +285,12 @@ Item {
|
||||
Component {
|
||||
id: list
|
||||
EnsListView {
|
||||
store: ensView.store
|
||||
messageStore: ensView.messageStore
|
||||
ensUsernamesStore: ensView.ensUsernamesStore
|
||||
|
||||
profileContentWidth: ensView.profileContentWidth
|
||||
onAddBtnClicked: next("search")
|
||||
onSelectEns: {
|
||||
ensView.store.ensDetails(username)
|
||||
ensView.ensUsernamesStore.ensDetails(username)
|
||||
selectedUsername = username;
|
||||
next("details")
|
||||
}
|
||||
@ -299,7 +300,7 @@ Item {
|
||||
Component {
|
||||
id: details
|
||||
EnsDetailsView {
|
||||
store: ensView.store
|
||||
ensUsernamesStore: ensView.ensUsernamesStore
|
||||
contactsStore: ensView.contactsStore
|
||||
username: selectedUsername
|
||||
onBackBtnClicked: back();
|
||||
@ -318,14 +319,14 @@ Item {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ensView.store.ens
|
||||
target: ensView.ensUsernamesStore.ensUsernamesModule
|
||||
onTransactionWasSent: {
|
||||
//% "Transaction pending..."
|
||||
Global.toastMessage.title = qsTrId("ens-transaction-pending")
|
||||
Global.toastMessage.source = Style.svg("loading")
|
||||
Global.toastMessage.iconColor = Style.current.primary
|
||||
Global.toastMessage.iconRotates = true
|
||||
Global.toastMessage.link = `${root.store.etherscanLink}/${txResult}`
|
||||
Global.toastMessage.link = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txResult}`
|
||||
Global.toastMessage.open()
|
||||
}
|
||||
onTransactionCompleted: {
|
||||
@ -355,7 +356,7 @@ Item {
|
||||
Global.toastMessage.source = Style.svg("block-icon")
|
||||
Global.toastMessage.iconColor = Style.current.danger
|
||||
}
|
||||
Global.toastMessage.link = `${root.store.etherscanLink}/${txHash}`
|
||||
Global.toastMessage.link = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txHash}`
|
||||
Global.toastMessage.open()
|
||||
}
|
||||
}
|
||||
|
@ -37,17 +37,16 @@ Item {
|
||||
function resolveEns() {
|
||||
if (selectedContact.ensVerified) {
|
||||
root.isResolvedAddress = false
|
||||
ensResolver.resolveEns(selectedContact.name)
|
||||
ensResolver.resolveEns(selectedContact.alias)
|
||||
}
|
||||
}
|
||||
|
||||
// This should be removed most likely.
|
||||
// onContactsChanged: {
|
||||
// if (root.readOnly) {
|
||||
// return
|
||||
// }
|
||||
// root.selectedContact = { name: selectAContact }
|
||||
// }
|
||||
Component.onCompleted: {
|
||||
if (root.readOnly) {
|
||||
return
|
||||
}
|
||||
root.selectedContact = { alias: selectAContact }
|
||||
}
|
||||
|
||||
onSelectedContactChanged: validate()
|
||||
|
||||
@ -55,8 +54,8 @@ Item {
|
||||
if (!selectedContact) {
|
||||
return root.isValid
|
||||
}
|
||||
let isValidAddress = Utils.isValidAddress(selectedContact.address)
|
||||
let isDefaultValue = selectedContact.name === selectAContact
|
||||
let isValidAddress = Utils.isValidAddress(selectedContact.publicKey)
|
||||
let isDefaultValue = selectedContact.alias === selectAContact
|
||||
let isValid = (selectedContact.ensVerified && isValidAddress) || isPending || isValidAddress
|
||||
select.validationError = ""
|
||||
if (!isValid && !isDefaultValue &&
|
||||
@ -76,7 +75,7 @@ Item {
|
||||
visible: root.readOnly
|
||||
width: parent.width
|
||||
//% "No contact selected"
|
||||
text: (root.selectedContact && root.selectedContact.name) ? root.selectedContact.name : qsTrId("no-contact-selected")
|
||||
text: (root.selectedContact && root.selectedContact.alias) ? root.selectedContact.alias : qsTrId("no-contact-selected")
|
||||
textField.leftPadding: 14
|
||||
textField.topPadding: 18
|
||||
textField.bottomPadding: 18
|
||||
@ -103,15 +102,15 @@ Item {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 14
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image.width: (!!selectedContact && !!selectedContact.identicon) ? 32 : 0
|
||||
image.width: (!!selectedContact && !!selectedContact.displayIcon) ? 32 : 0
|
||||
image.height: 32
|
||||
image.source: (!!selectedContact && !!selectedContact.identicon) ? selectedContact.identicon : ""
|
||||
image.isIdenticon: true
|
||||
active: !!selectedContact && !!selectedContact.identicon
|
||||
image.source: (!!selectedContact && !!selectedContact.displayIcon) ? selectedContact.displayIcon : ""
|
||||
image.isIdenticon: (!!selectedContact && !!selectedContact.isDisplayIconIdenticon) ? selectedContact.isDisplayIconIdenticon : true
|
||||
active: !!selectedContact && !!selectedContact.displayIcon
|
||||
}
|
||||
StatusBaseText {
|
||||
id: selectedTextField
|
||||
text: !!selectedContact ? selectedContact.name : ""
|
||||
text: !!selectedContact ? selectedContact.alias : ""
|
||||
anchors.left: iconImg.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@ -148,12 +147,12 @@ Item {
|
||||
onResolved: {
|
||||
root.isResolvedAddress = true
|
||||
var selectedContact = root.selectedContact
|
||||
selectedContact.address = resolvedAddress
|
||||
selectedContact.publicKey = resolvedAddress
|
||||
root.selectedContact = selectedContact
|
||||
}
|
||||
onIsPendingChanged: {
|
||||
if (isPending) {
|
||||
root.selectedContact.address = ""
|
||||
root.selectedContact.publicKey = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,6 +164,8 @@ Item {
|
||||
property bool isFirstItem: index === 0
|
||||
property bool isLastItem: index === root.contactsStore.myContactsModel.count - 1
|
||||
|
||||
property var currentContact: Utils.getContactDetailsAsJson(pubKey)
|
||||
|
||||
width: parent.width
|
||||
height: visible ? 72 : 0
|
||||
StatusSmartIdenticon {
|
||||
@ -172,8 +173,8 @@ Item {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image.source: identicon
|
||||
image.isIdenticon: true
|
||||
image.source: currentContact.displayIcon
|
||||
image.isIdenticon: currentContact.isDisplayIconIdenticon
|
||||
}
|
||||
Column {
|
||||
anchors.left: iconImg.right
|
||||
@ -181,7 +182,7 @@ Item {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StatusBaseText {
|
||||
text: name
|
||||
text: currentContact.alias
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
height: 22
|
||||
@ -189,14 +190,14 @@ Item {
|
||||
|
||||
Row {
|
||||
StatusBaseText {
|
||||
text: alias + " • "
|
||||
visible: ensVerified
|
||||
text: currentContact.name + " • "
|
||||
visible: currentContact.ensVerified
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 12
|
||||
height: 16
|
||||
}
|
||||
StatusBaseText {
|
||||
text: address
|
||||
text: currentContact.publicKey
|
||||
width: 85
|
||||
elide: Text.ElideMiddle
|
||||
color: Theme.palette.baseColor1
|
||||
@ -212,7 +213,7 @@ Item {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: itemContainer
|
||||
onClicked: {
|
||||
root.selectedContact = { address, name, alias, isContact, identicon, ensVerified }
|
||||
root.selectedContact = itemContainer.currentContact
|
||||
resolveEns()
|
||||
select.selectMenu.close()
|
||||
}
|
||||
@ -220,10 +221,3 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*##^##
|
||||
Designer {
|
||||
D{i:0;autoSize:true;height:480;width:640}
|
||||
}
|
||||
##^##*/
|
||||
|
@ -267,10 +267,9 @@ Item {
|
||||
text: qsTrId("optimal")
|
||||
price: {
|
||||
if (!eip1599Enabled) {
|
||||
const price = gasPrice
|
||||
// Setting the gas price field here because the binding didn't work
|
||||
inputGasPrice.text = price
|
||||
return price
|
||||
inputGasPrice.text = root.gasPrice
|
||||
return root.gasPrice
|
||||
}
|
||||
|
||||
return formatDec(suggestedFees.maxFeePerGasM, 6)
|
||||
@ -284,7 +283,7 @@ Item {
|
||||
inputPerGasTipLimit.text = formatDec(suggestedFees.maxPriorityFeePerGas, 2);
|
||||
inputGasPrice.text = formatDec(suggestedFees.maxFeePerGasM, 2);
|
||||
} else {
|
||||
inputGasPrice.text = price
|
||||
inputGasPrice.text = root.gasPrice
|
||||
}
|
||||
root.updateGasEthValue()
|
||||
root.checkLimits()
|
||||
|
@ -16,7 +16,6 @@ Item {
|
||||
property var contactsStore
|
||||
|
||||
property var accounts
|
||||
property int currentIndex
|
||||
property int inputWidth: 272
|
||||
property int sourceSelectWidth: 136
|
||||
property alias label: txtLabel.text
|
||||
@ -24,7 +23,6 @@ Item {
|
||||
property alias additionalInfo: txtAddlInfo.text
|
||||
property var selectedRecipient
|
||||
property bool readOnly: false
|
||||
property bool isContact: false
|
||||
height: inpAddress.height + txtLabel.height
|
||||
//% "Invalid ethereum address"
|
||||
readonly property string addressValidationError: qsTrId("invalid-ethereum-address")
|
||||
@ -149,6 +147,9 @@ Item {
|
||||
|
||||
AddressInput {
|
||||
id: inpAddress
|
||||
|
||||
contactsStore: root.contactsStore
|
||||
|
||||
width: root.inputWidth
|
||||
input.label: ""
|
||||
input.readOnly: root.readOnly
|
||||
@ -175,7 +176,6 @@ Item {
|
||||
width: root.inputWidth
|
||||
dropdownWidth: parent.width
|
||||
readOnly: root.readOnly
|
||||
isContact: root.isContact
|
||||
Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
@ -258,10 +258,3 @@ Item {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*##^##
|
||||
Designer {
|
||||
D{i:0;autoSize:true;height:480;width:640}
|
||||
}
|
||||
##^##*/
|
||||
|
@ -29,7 +29,7 @@ Rectangle {
|
||||
if (!gasLimit) {
|
||||
return 0
|
||||
}
|
||||
return formatDec(parseFloat(getGasEthValue(price, gasLimit)), 6)
|
||||
return formatDec(parseFloat(getGasEthValue(gasRectangle.price, gasLimit)), 6)
|
||||
}
|
||||
property double fiatValue: getFiatValue(ethValue, "ETH", defaultCurrency)
|
||||
signal checked()
|
||||
|
@ -12,6 +12,7 @@ Item {
|
||||
width: chatName.width + (ensOrAlias.visible ? ensOrAlias.width + ensOrAlias.anchors.leftMargin : 0)
|
||||
property alias label: chatName
|
||||
|
||||
property var messageContextMenu
|
||||
property string displayName
|
||||
property string localName
|
||||
property bool amISender
|
||||
@ -40,11 +41,11 @@ Item {
|
||||
root.isHovered = false
|
||||
}
|
||||
onClicked: {
|
||||
if (!!messageContextMenu) {
|
||||
if (!!root.messageContextMenu) {
|
||||
// Set parent, X & Y positions for the messageContextMenu
|
||||
messageContextMenu.parent = root
|
||||
messageContextMenu.setXPosition = function() { return 0}
|
||||
messageContextMenu.setYPosition = function() { return root.height + 4}
|
||||
root.messageContextMenu.parent = root
|
||||
root.messageContextMenu.setXPosition = function() { return 0}
|
||||
root.messageContextMenu.setYPosition = function() { return root.height + 4}
|
||||
}
|
||||
root.clickMessage(true);
|
||||
}
|
||||
|
@ -114,13 +114,11 @@ ModalPopup {
|
||||
id: selectRecipient
|
||||
accounts: root.store.accounts
|
||||
contactsStore: root.contactsStore
|
||||
currentIndex: index
|
||||
//% "Recipient"
|
||||
label: qsTrId("recipient")
|
||||
anchors.top: separator.bottom
|
||||
anchors.topMargin: 10
|
||||
width: stack.width
|
||||
isContact: root.isContact
|
||||
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,6 @@ StatusModal {
|
||||
// accounts: root.store.walletModelInst.accountsView.accounts
|
||||
contactsStore: root.contactsStore
|
||||
selectedRecipient: root.selectedRecipient
|
||||
currentIndex: index
|
||||
readOnly: true
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import shared.controls 1.0
|
||||
ModalPopup {
|
||||
id: root
|
||||
|
||||
property var ensUsernamesStore
|
||||
property var contactsStore
|
||||
|
||||
readonly property var asset: {"name": "Ethereum", "symbol": "ETH"}
|
||||
@ -26,42 +27,36 @@ ModalPopup {
|
||||
property var onSendTransaction: (function(userAddress, gasLimit, gasPrice, password){ return ""; })
|
||||
property var onSuccess: (function(){})
|
||||
|
||||
Component.onCompleted: {
|
||||
// Not Refactored Yet
|
||||
// RootStore.walletModelInst.gasView.getGasPricePredictions()
|
||||
}
|
||||
|
||||
height: 540
|
||||
|
||||
function sendTransaction() {
|
||||
// Not Refactored Yet
|
||||
// try {
|
||||
// let responseStr = RootStore.profileModelInst.ens.setPubKey(root.ensUsername,
|
||||
// selectFromAccount.selectedAccount.address,
|
||||
// gasSelector.selectedGasLimit,
|
||||
// gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
// gasSelector.selectedTipLimit,
|
||||
// gasSelector.selectedOverallLimit,
|
||||
// transactionSigner.enteredPassword)
|
||||
// let response = JSON.parse(responseStr)
|
||||
try {
|
||||
let responseStr = root.ensUsernamesStore.setPubKey(root.ensUsername,
|
||||
selectFromAccount.selectedAccount.address,
|
||||
gasSelector.selectedGasLimit,
|
||||
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
|
||||
gasSelector.selectedTipLimit,
|
||||
gasSelector.selectedOverallLimit,
|
||||
transactionSigner.enteredPassword)
|
||||
let response = JSON.parse(responseStr)
|
||||
|
||||
// if (!response.success) {
|
||||
// if (Utils.isInvalidPasswordMessage(response.result)){
|
||||
// //% "Wrong password"
|
||||
// transactionSigner.validationError = qsTrId("wrong-password")
|
||||
// return
|
||||
// }
|
||||
// sendingError.text = response.result
|
||||
// return sendingError.open()
|
||||
// }
|
||||
if (!response.success) {
|
||||
if (Utils.isInvalidPasswordMessage(response.result)){
|
||||
//% "Wrong password"
|
||||
transactionSigner.validationError = qsTrId("wrong-password")
|
||||
return
|
||||
}
|
||||
sendingError.text = response.result
|
||||
return sendingError.open()
|
||||
}
|
||||
|
||||
// onSuccess();
|
||||
// root.close();
|
||||
// } catch (e) {
|
||||
// console.error('Error sending the transaction', e)
|
||||
// sendingError.text = "Error sending the transaction: " + e.message;
|
||||
// return sendingError.open()
|
||||
// }
|
||||
onSuccess();
|
||||
root.close();
|
||||
} catch (e) {
|
||||
console.error('Error sending the transaction', e)
|
||||
sendingError.text = "Error sending the transaction: " + e.message;
|
||||
return sendingError.open()
|
||||
}
|
||||
}
|
||||
|
||||
property MessageDialog sendingError: MessageDialog {
|
||||
@ -98,8 +93,7 @@ ModalPopup {
|
||||
}
|
||||
return null
|
||||
}
|
||||
// Not Refactored Yet
|
||||
// currency: RootStore.defaultCurrency
|
||||
currency: root.ensUsernamesStore.getCurrentCurrency()
|
||||
width: stack.width
|
||||
//% "Choose account"
|
||||
label: qsTrId("choose-account")
|
||||
@ -110,12 +104,10 @@ ModalPopup {
|
||||
RecipientSelector {
|
||||
id: selectRecipient
|
||||
visible: false
|
||||
// Not Refactored Yet
|
||||
// accounts: RootStore.walletModelInst.accountsView.accounts
|
||||
accounts: root.ensUsernamesStore.walletAccounts
|
||||
contactsStore: root.contactsStore
|
||||
selectedRecipient: { "address": RootStore.utilsModelInst.ensRegisterAddress, "type": RecipientSelector.Type.Address }
|
||||
selectedRecipient: { "address": root.ensUsernamesStore.getEnsRegisteredAddress(), "type": RecipientSelector.Type.Address }
|
||||
readOnly: true
|
||||
currentIndex: index
|
||||
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
||||
}
|
||||
GasSelector {
|
||||
@ -123,11 +115,10 @@ ModalPopup {
|
||||
visible: true
|
||||
anchors.top: selectFromAccount.bottom
|
||||
anchors.topMargin: Style.current.padding
|
||||
// Not Refactored Yet
|
||||
// gasPrice: parseFloat(RootStore.gasPrice)
|
||||
// getGasEthValue: RootStore.gasEthValue
|
||||
// getFiatValue: RootStore.fiatValue
|
||||
// defaultCurrency: RootStore.defaultCurrency
|
||||
gasPrice: parseFloat(root.ensUsernamesStore.gasPrice)
|
||||
getGasEthValue: root.ensUsernamesStore.getGasEthValue
|
||||
getFiatValue: root.ensUsernamesStore.getFiatValue
|
||||
defaultCurrency: root.ensUsernamesStore.getCurrentCurrency()
|
||||
|
||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||
let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount);
|
||||
@ -161,12 +152,11 @@ ModalPopup {
|
||||
}
|
||||
toAccount: selectRecipient.selectedRecipient
|
||||
asset: root.asset
|
||||
// Not Refactored Yet
|
||||
// currency: RootStore.defaultCurrency
|
||||
// amount: {
|
||||
// const fiatValue = RootStore.walletModelInst.balanceView.getFiatValue(0, root.asset.symbol, currency)
|
||||
// return { "value": 0, "fiatValue": fiatValue }
|
||||
// }
|
||||
currency: root.ensUsernamesStore.getCurrentCurrency()
|
||||
amount: {
|
||||
const fiatValue = root.ensUsernamesStore.getFiatValue(0, root.asset.symbol, currency)
|
||||
return { "value": 0, "fiatValue": fiatValue }
|
||||
}
|
||||
}
|
||||
}
|
||||
TransactionFormGroup {
|
||||
@ -178,8 +168,7 @@ ModalPopup {
|
||||
TransactionSigner {
|
||||
id: transactionSigner
|
||||
width: stack.width
|
||||
// Not Refactored Yet
|
||||
// signingPhrase: RootStore.walletModelInst.utilsView.signingPhrase
|
||||
signingPhrase: root.ensUsernamesStore.getSigningPhrase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,10 @@ import shared.controls 1.0
|
||||
ModalPopup {
|
||||
id: root
|
||||
|
||||
property var store
|
||||
property var contactsStore
|
||||
|
||||
// Not Refactored Yet
|
||||
// readonly property var asset: "" //JSON.parse(RootStore.walletModelInst.tokensView.getStatusToken())
|
||||
readonly property var asset: JSON.parse(root.store.getStatusToken())
|
||||
property string assetPrice
|
||||
property string contractAddress
|
||||
property var estimateGasFunction: (function(userAddress, uuid) { return 0; })
|
||||
@ -26,8 +26,7 @@ ModalPopup {
|
||||
property var onSuccess: (function(){})
|
||||
|
||||
Component.onCompleted: {
|
||||
// Not Refactored Yet
|
||||
// RootStore.walletModelInst.gasView.getGasPrice()
|
||||
root.store.fetchGasPrice()
|
||||
}
|
||||
|
||||
height: 540
|
||||
@ -114,23 +113,20 @@ ModalPopup {
|
||||
RecipientSelector {
|
||||
id: selectRecipient
|
||||
visible: false
|
||||
// Not Refactored Yet
|
||||
// accounts: RootStore.walletModelInst.accountsView.accounts
|
||||
accounts: root.store.walletAccounts
|
||||
contactsStore: root.contactsStore
|
||||
selectedRecipient: { "address": contractAddress, "type": RecipientSelector.Type.Address }
|
||||
readOnly: true
|
||||
currentIndex: index
|
||||
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
||||
}
|
||||
GasSelector {
|
||||
id: gasSelector
|
||||
anchors.top: selectFromAccount.bottom
|
||||
anchors.topMargin: Style.current.padding
|
||||
// Not Refactored Yet
|
||||
// gasPrice: parseFloat(RootStore.gasPrice)
|
||||
// getGasEthValue: RootStore.gasEthValue
|
||||
// getFiatValue: RootStore.fiatValue
|
||||
defaultCurrency: RootStore.currentCurrency
|
||||
gasPrice: parseFloat(root.store.gasPrice)
|
||||
getGasEthValue: root.store.getGasEthValue
|
||||
getFiatValue: root.store.getFiatValue
|
||||
defaultCurrency: root.store.getCurrentCurrency()
|
||||
width: stack.width
|
||||
|
||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||
@ -166,11 +162,11 @@ ModalPopup {
|
||||
}
|
||||
toAccount: selectRecipient.selectedRecipient
|
||||
asset: root.asset
|
||||
currency: RootStore.walletSectionInst.currentCurrency
|
||||
// amount: {
|
||||
// const fiatValue = RootStore.walletModelInst.balanceView.getFiatValue(root.assetPrice || 0, root.asset.symbol, currency)
|
||||
// return { "value": root.assetPrice, "fiatValue": fiatValue }
|
||||
// }
|
||||
amount: {
|
||||
const fiatValue = root.store.getFiatValue(root.assetPrice || 0, root.asset.symbol, currency)
|
||||
return { "value": root.assetPrice, "fiatValue": fiatValue }
|
||||
}
|
||||
currency: root.store.getCurrentCurrency()
|
||||
}
|
||||
}
|
||||
TransactionFormGroup {
|
||||
@ -183,8 +179,7 @@ ModalPopup {
|
||||
TransactionSigner {
|
||||
id: transactionSigner
|
||||
width: stack.width
|
||||
// Not Refactored Yet
|
||||
// signingPhrase: RootStore.walletModelInst.utilsView.signingPhrase
|
||||
signingPhrase: root.store.getSigningPhrase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -313,6 +313,7 @@ Item {
|
||||
anchors.leftMargin: chatHorizontalPadding
|
||||
anchors.top: chatImage.top
|
||||
anchors.left: chatImage.right
|
||||
messageContextMenu: root.messageContextMenu
|
||||
displayName: senderDisplayName
|
||||
localName: senderLocalName
|
||||
amISender: amISender
|
||||
|
Loading…
x
Reference in New Issue
Block a user