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/devices/service as devices_service
|
||||||
import ../../app_service/service/mailservers/service as mailservers_service
|
import ../../app_service/service/mailservers/service as mailservers_service
|
||||||
import ../../app_service/service/gif/service as gif_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/startup/module as startup_module
|
||||||
import ../modules/main/module as main_module
|
import ../modules/main/module as main_module
|
||||||
@ -82,6 +83,7 @@ type
|
|||||||
mailserversService: mailservers_service.Service
|
mailserversService: mailservers_service.Service
|
||||||
nodeService: node_service.Service
|
nodeService: node_service.Service
|
||||||
gifService: gif_service.Service
|
gifService: gif_service.Service
|
||||||
|
ensService: ens_service.Service
|
||||||
|
|
||||||
# Modules
|
# Modules
|
||||||
startupModule: startup_module.AccessInterface
|
startupModule: startup_module.AccessInterface
|
||||||
@ -168,6 +170,9 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
|||||||
result.nodeService = node_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
result.nodeService = node_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
||||||
result.settingsService)
|
result.settingsService)
|
||||||
result.gifService = gif_service.newService(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
|
# Modules
|
||||||
result.startupModule = startup_module.newModule[AppController](
|
result.startupModule = startup_module.newModule[AppController](
|
||||||
@ -206,6 +211,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
|||||||
result.mailserversService,
|
result.mailserversService,
|
||||||
result.nodeService,
|
result.nodeService,
|
||||||
result.gifService,
|
result.gifService,
|
||||||
|
result.ensService
|
||||||
)
|
)
|
||||||
|
|
||||||
# Do connections
|
# Do connections
|
||||||
@ -252,6 +258,7 @@ proc delete*(self: AppController) =
|
|||||||
self.privacyService.delete
|
self.privacyService.delete
|
||||||
self.profileService.delete
|
self.profileService.delete
|
||||||
self.generalService.delete
|
self.generalService.delete
|
||||||
|
self.ensService.delete
|
||||||
|
|
||||||
proc startupDidLoad*(self: AppController) =
|
proc startupDidLoad*(self: AppController) =
|
||||||
singletonInstance.engine.setRootContextProperty("localAppSettings", self.localAppSettingsVariant)
|
singletonInstance.engine.setRootContextProperty("localAppSettings", self.localAppSettingsVariant)
|
||||||
@ -294,6 +301,7 @@ proc load(self: AppController) =
|
|||||||
self.aboutService.init()
|
self.aboutService.init()
|
||||||
self.devicesService.init()
|
self.devicesService.init()
|
||||||
self.mailserversService.init()
|
self.mailserversService.init()
|
||||||
|
self.ensService.init()
|
||||||
|
|
||||||
let pubKey = self.settingsService.getPublicKey()
|
let pubKey = self.settingsService.getPublicKey()
|
||||||
singletonInstance.localAccountSensitiveSettings.setFileName(pubKey)
|
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/devices/service as devices_service
|
||||||
import ../../../app_service/service/mailservers/service as mailservers_service
|
import ../../../app_service/service/mailservers/service as mailservers_service
|
||||||
import ../../../app_service/service/gif/service as gif_service
|
import ../../../app_service/service/gif/service as gif_service
|
||||||
|
import ../../../app_service/service/ens/service as ens_service
|
||||||
|
|
||||||
|
|
||||||
import ../../core/eventemitter
|
import ../../core/eventemitter
|
||||||
@ -96,6 +97,7 @@ proc newModule*[T](
|
|||||||
mailserversService: mailservers_service.Service,
|
mailserversService: mailservers_service.Service,
|
||||||
nodeService: node_service.Service,
|
nodeService: node_service.Service,
|
||||||
gifService: gif_service.Service,
|
gifService: gif_service.Service,
|
||||||
|
ensService: ens_service.Service
|
||||||
): Module[T] =
|
): Module[T] =
|
||||||
result = Module[T]()
|
result = Module[T]()
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
@ -128,7 +130,7 @@ proc newModule*[T](
|
|||||||
dappPermissionsService, providerService)
|
dappPermissionsService, providerService)
|
||||||
result.profileSectionModule = profile_section_module.newModule(result, events, accountsService, settingsService,
|
result.profileSectionModule = profile_section_module.newModule(result, events, accountsService, settingsService,
|
||||||
profileService, contactsService, aboutService, languageService, privacyService, nodeConfigurationService,
|
profileService, contactsService, aboutService, languageService, privacyService, nodeConfigurationService,
|
||||||
devicesService, mailserversService, chatService)
|
devicesService, mailserversService, chatService, ensService, walletAccountService)
|
||||||
result.stickersModule = stickers_module.newModule(result, events, stickersService)
|
result.stickersModule = stickers_module.newModule(result, events, stickersService)
|
||||||
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
|
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
|
||||||
messageService)
|
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.} =
|
method getNotificationsModule*(self: AccessInterface): QVariant {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
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
|
type
|
||||||
## Abstract class (concept) which must be implemented by object/s used in this
|
## Abstract class (concept) which must be implemented by object/s used in this
|
||||||
## module.
|
## 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/devices/service as devices_service
|
||||||
import ../../../../app_service/service/mailservers/service as mailservers_service
|
import ../../../../app_service/service/mailservers/service as mailservers_service
|
||||||
import ../../../../app_service/service/chat/service as chat_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 ./profile/module as profile_module
|
||||||
import ./contacts/module as contacts_module
|
import ./contacts/module as contacts_module
|
||||||
@ -23,6 +25,7 @@ import ./advanced/module as advanced_module
|
|||||||
import ./devices/module as devices_module
|
import ./devices/module as devices_module
|
||||||
import ./sync/module as sync_module
|
import ./sync/module as sync_module
|
||||||
import ./notifications/module as notifications_module
|
import ./notifications/module as notifications_module
|
||||||
|
import ./ens_usernames/module as ens_usernames_module
|
||||||
|
|
||||||
export io_interface
|
export io_interface
|
||||||
|
|
||||||
@ -43,6 +46,7 @@ type
|
|||||||
devicesModule: devices_module.AccessInterface
|
devicesModule: devices_module.AccessInterface
|
||||||
syncModule: sync_module.AccessInterface
|
syncModule: sync_module.AccessInterface
|
||||||
notificationsModule: notifications_module.AccessInterface
|
notificationsModule: notifications_module.AccessInterface
|
||||||
|
ensUsernamesModule: ens_usernames_module.AccessInterface
|
||||||
|
|
||||||
proc newModule*[T](delegate: T,
|
proc newModule*[T](delegate: T,
|
||||||
events: EventEmitter,
|
events: EventEmitter,
|
||||||
@ -56,7 +60,9 @@ proc newModule*[T](delegate: T,
|
|||||||
nodeConfigurationService: node_configuration_service.ServiceInterface,
|
nodeConfigurationService: node_configuration_service.ServiceInterface,
|
||||||
devicesService: devices_service.Service,
|
devicesService: devices_service.Service,
|
||||||
mailserversService: mailservers_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] =
|
Module[T] =
|
||||||
result = Module[T]()
|
result = Module[T]()
|
||||||
@ -75,6 +81,8 @@ proc newModule*[T](delegate: T,
|
|||||||
result.devicesModule = devices_module.newModule(result, events, settingsService, devicesService)
|
result.devicesModule = devices_module.newModule(result, events, settingsService, devicesService)
|
||||||
result.syncModule = sync_module.newModule(result, events, settingsService, mailserversService)
|
result.syncModule = sync_module.newModule(result, events, settingsService, mailserversService)
|
||||||
result.notificationsModule = notifications_module.newModule(result, events, chatService)
|
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)
|
singletonInstance.engine.setRootContextProperty("profileSectionModule", result.viewVariant)
|
||||||
|
|
||||||
@ -103,6 +111,7 @@ method load*[T](self: Module[T]) =
|
|||||||
self.devicesModule.load()
|
self.devicesModule.load()
|
||||||
self.syncModule.load()
|
self.syncModule.load()
|
||||||
self.notificationsModule.load()
|
self.notificationsModule.load()
|
||||||
|
self.ensUsernamesModule.load()
|
||||||
|
|
||||||
method isLoaded*[T](self: Module[T]): bool =
|
method isLoaded*[T](self: Module[T]): bool =
|
||||||
return self.moduleLoaded
|
return self.moduleLoaded
|
||||||
@ -135,6 +144,9 @@ proc checkIfModuleDidLoad[T](self: Module[T]) =
|
|||||||
if(not self.notificationsModule.isLoaded()):
|
if(not self.notificationsModule.isLoaded()):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if(not self.ensUsernamesModule.isLoaded()):
|
||||||
|
return
|
||||||
|
|
||||||
self.moduleLoaded = true
|
self.moduleLoaded = true
|
||||||
self.delegate.profileSectionDidLoad()
|
self.delegate.profileSectionDidLoad()
|
||||||
|
|
||||||
@ -191,3 +203,9 @@ method notificationsModuleDidLoad*[T](self: Module[T]) =
|
|||||||
|
|
||||||
method getNotificationsModule*[T](self: Module[T]): QVariant =
|
method getNotificationsModule*[T](self: Module[T]): QVariant =
|
||||||
self.notificationsModule.getModuleAsVariant()
|
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()
|
return self.delegate.getPrivacyModule()
|
||||||
QtProperty[QVariant] privacyModule:
|
QtProperty[QVariant] privacyModule:
|
||||||
read = getPrivacyModule
|
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 Tables, json, chronicles, strutils
|
||||||
import algorithm, strformat, sets, options
|
import algorithm, strformat, sets, options, sequtils
|
||||||
import chronicles, libp2p/[multihash, multicodec, cid]
|
import chronicles, libp2p/[multihash, multicodec, cid]
|
||||||
import nimcrypto, stint
|
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
|
import status/statusgo_backend_new/eth as status_eth
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "ens-utils"
|
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
|
type
|
||||||
ENSType* {.pure.} = enum
|
ENSType* {.pure.} = enum
|
||||||
@ -21,9 +41,9 @@ proc addDomain(username: string): string =
|
|||||||
if username.endsWith(".eth"):
|
if username.endsWith(".eth"):
|
||||||
return username
|
return username
|
||||||
else:
|
else:
|
||||||
return username & domain
|
return username & STATUS_DOMAIN
|
||||||
|
|
||||||
proc namehash(ensName:string): string =
|
proc namehash*(ensName:string): string =
|
||||||
let name = ensName.toLower()
|
let name = ensName.toLower()
|
||||||
var node:array[32, byte]
|
var node:array[32, byte]
|
||||||
|
|
||||||
@ -38,20 +58,17 @@ proc namehash(ensName:string): string =
|
|||||||
|
|
||||||
result = "0x" & node.toHex()
|
result = "0x" & node.toHex()
|
||||||
|
|
||||||
const registry* = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
|
proc resolver*(usernameHash: string): string =
|
||||||
const resolver_signature = "0x0178b8bf"
|
|
||||||
proc resolver(usernameHash: string): string =
|
|
||||||
let payload = %* [{
|
let payload = %* [{
|
||||||
"to": registry,
|
"to": ENS_REGISTRY,
|
||||||
"from": "0x0000000000000000000000000000000000000000",
|
"from": "0x0000000000000000000000000000000000000000",
|
||||||
"data": fmt"{resolver_signature}{userNameHash}"
|
"data": fmt"{RESOLVER_SIGNATURE}{userNameHash}"
|
||||||
}, "latest"]
|
}, "latest"]
|
||||||
|
|
||||||
var resolverAddr = status_eth.doEthCall(payload).result.getStr()
|
var resolverAddr = status_eth.doEthCall(payload).result.getStr()
|
||||||
resolverAddr.removePrefix("0x000000000000000000000000")
|
resolverAddr.removePrefix("0x000000000000000000000000")
|
||||||
result = "0x" & resolverAddr
|
result = "0x" & resolverAddr
|
||||||
|
|
||||||
const contenthash_signature = "0xbc1c58d1" # contenthash(bytes32)
|
|
||||||
proc contenthash(ensAddr: string): string =
|
proc contenthash(ensAddr: string): string =
|
||||||
var ensHash = namehash(ensAddr)
|
var ensHash = namehash(ensAddr)
|
||||||
ensHash.removePrefix("0x")
|
ensHash.removePrefix("0x")
|
||||||
@ -59,7 +76,7 @@ proc contenthash(ensAddr: string): string =
|
|||||||
let payload = %* [{
|
let payload = %* [{
|
||||||
"to": ensResolver,
|
"to": ensResolver,
|
||||||
"from": "0x0000000000000000000000000000000000000000",
|
"from": "0x0000000000000000000000000000000000000000",
|
||||||
"data": fmt"{contenthash_signature}{ensHash}"
|
"data": fmt"{CONTENTHASH_SIGNATURE}{ensHash}"
|
||||||
}, "latest"]
|
}, "latest"]
|
||||||
|
|
||||||
let bytesResponse = status_eth.doEthCall(payload).result.getStr()
|
let bytesResponse = status_eth.doEthCall(payload).result.getStr()
|
||||||
@ -120,7 +137,6 @@ proc decodeENSContentHash*(value: string): tuple[ensType: ENSType, output: strin
|
|||||||
|
|
||||||
return (ENSType.UNKNOWN, "")
|
return (ENSType.UNKNOWN, "")
|
||||||
|
|
||||||
const pubkey_signature = "0xc8690233" # pubkey(bytes32 node)
|
|
||||||
proc pubkey*(username: string): string =
|
proc pubkey*(username: string): string =
|
||||||
var userNameHash = namehash(addDomain(username))
|
var userNameHash = namehash(addDomain(username))
|
||||||
userNameHash.removePrefix("0x")
|
userNameHash.removePrefix("0x")
|
||||||
@ -128,7 +144,7 @@ proc pubkey*(username: string): string =
|
|||||||
let payload = %* [{
|
let payload = %* [{
|
||||||
"to": ensResolver,
|
"to": ensResolver,
|
||||||
"from": "0x0000000000000000000000000000000000000000",
|
"from": "0x0000000000000000000000000000000000000000",
|
||||||
"data": fmt"{pubkey_signature}{userNameHash}"
|
"data": fmt"{PUBKEY_SIGNATURE}{userNameHash}"
|
||||||
}, "latest"]
|
}, "latest"]
|
||||||
let response = status_eth.doEthCall(payload)
|
let response = status_eth.doEthCall(payload)
|
||||||
# TODO: error handling
|
# TODO: error handling
|
||||||
@ -139,7 +155,6 @@ proc pubkey*(username: string): string =
|
|||||||
pubkey.removePrefix("0x")
|
pubkey.removePrefix("0x")
|
||||||
result = "0x04" & pubkey
|
result = "0x04" & pubkey
|
||||||
|
|
||||||
const address_signature = "0x3b3b57de" # addr(bytes32 node)
|
|
||||||
proc address*(username: string): string =
|
proc address*(username: string): string =
|
||||||
var userNameHash = namehash(addDomain(username))
|
var userNameHash = namehash(addDomain(username))
|
||||||
userNameHash.removePrefix("0x")
|
userNameHash.removePrefix("0x")
|
||||||
@ -147,7 +162,7 @@ proc address*(username: string): string =
|
|||||||
let payload = %* [{
|
let payload = %* [{
|
||||||
"to": ensResolver,
|
"to": ensResolver,
|
||||||
"from": "0x0000000000000000000000000000000000000000",
|
"from": "0x0000000000000000000000000000000000000000",
|
||||||
"data": fmt"{address_signature}{userNameHash}"
|
"data": fmt"{ADDRESS_SIGNATURE}{userNameHash}"
|
||||||
}, "latest"]
|
}, "latest"]
|
||||||
let response = status_eth.doEthCall(payload)
|
let response = status_eth.doEthCall(payload)
|
||||||
# TODO: error handling
|
# TODO: error handling
|
||||||
@ -155,3 +170,86 @@ proc address*(username: string): string =
|
|||||||
if address == "0x0000000000000000000000000000000000000000000000000000000000000000":
|
if address == "0x0000000000000000000000000000000000000000000000000000000000000000":
|
||||||
return ""
|
return ""
|
||||||
result = "0x" & address.substr(26)
|
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
|
import status/statusgo_backend_new/eth as status_eth
|
||||||
|
|
||||||
|
export method_dto
|
||||||
|
|
||||||
include ../../../common/json_utils
|
include ../../../common/json_utils
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -2,14 +2,6 @@ import strutils, json
|
|||||||
import web3/ethtypes, web3/conversions, options, stint
|
import web3/ethtypes, web3/conversions, options, stint
|
||||||
import ../utils
|
import ../utils
|
||||||
|
|
||||||
type
|
|
||||||
PendingTransactionTypeDto* {.pure.} = enum
|
|
||||||
RegisterENS = "RegisterENS",
|
|
||||||
SetPubKey = "SetPubKey",
|
|
||||||
ReleaseENS = "ReleaseENS",
|
|
||||||
BuyStickerPack = "BuyStickerPack"
|
|
||||||
WalletTransfer = "WalletTransfer"
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TransactionDataDto* = object
|
TransactionDataDto* = object
|
||||||
source*: Address # the address the transaction is send from.
|
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 status/statusgo_backend_new/eth
|
||||||
|
|
||||||
import utils
|
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
|
import ./service_interface
|
||||||
|
|
||||||
export service_interface
|
export service_interface
|
||||||
export coder
|
|
||||||
export edn_dto
|
|
||||||
export contract
|
|
||||||
export method_dto
|
|
||||||
export transaction
|
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "eth-service"
|
topics = "eth-service"
|
||||||
@ -34,12 +23,12 @@ proc newService*(): Service =
|
|||||||
result.contracts = @[]
|
result.contracts = @[]
|
||||||
|
|
||||||
# Forward declaration
|
# Forward declaration
|
||||||
method initContracts(self: Service)
|
proc initContracts(self: Service)
|
||||||
|
|
||||||
method init*(self: Service) =
|
method init*(self: Service) =
|
||||||
self.initContracts()
|
self.initContracts()
|
||||||
|
|
||||||
method initContracts(self: Service) =
|
proc initContracts(self: Service) =
|
||||||
self.contracts = @[
|
self.contracts = @[
|
||||||
# Mainnet contracts
|
# Mainnet contracts
|
||||||
newErc20Contract("Status Network Token", Mainnet, parseAddress("0x744d70fdbe2ba4cf95131626614a1763df805b9e"), "SNT", 18, true),
|
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),
|
newErc20Contract("Orchid", Mainnet, parseAddress("0x4575f41308EC1483f3d399aa9a2826d74Da13Deb"), "OXT", 18, false),
|
||||||
]
|
]
|
||||||
|
|
||||||
method allContracts(self: Service): seq[ContractDto] =
|
proc allContracts(self: Service): seq[ContractDto] =
|
||||||
result = self.contracts
|
result = self.contracts
|
||||||
|
|
||||||
method findByAddress*(self: Service, contracts: seq[Erc20ContractDto], address: Address): Erc20ContractDto =
|
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 =
|
method findErc721Contract*(self: Service, chainId: int, name: string): Erc721ContractDto =
|
||||||
let found = self.allErc721ContractsByChainId(chainId).filter(contract => contract.name.toLower == name.toLower)
|
let found = self.allErc721ContractsByChainId(chainId).filter(contract => contract.name.toLower == name.toLower)
|
||||||
result = if found.len > 0: found[0] else: nil
|
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
|
type
|
||||||
ServiceInterface* {.pure inheritable.} = ref object of RootObj
|
ServiceInterface* {.pure inheritable.} = ref object of RootObj
|
||||||
@ -8,3 +22,32 @@ method delete*(self: ServiceInterface) {.base.} =
|
|||||||
|
|
||||||
method init*(self: ServiceInterface) {.base.} =
|
method init*(self: ServiceInterface) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
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
|
import stint
|
||||||
from times import getTime, toUnix, nanosecond
|
from times import getTime, toUnix, nanosecond
|
||||||
import signing_phrases
|
import signing_phrases
|
||||||
from web3 import Address, fromHex
|
|
||||||
import web3/ethhexstrings
|
import web3/ethhexstrings
|
||||||
|
|
||||||
|
import ../../common/conversion as common_conversion
|
||||||
|
|
||||||
|
export common_conversion
|
||||||
|
|
||||||
proc decodeContentHash*(value: string): string =
|
proc decodeContentHash*(value: string): string =
|
||||||
if value == "":
|
if value == "":
|
||||||
return ""
|
return ""
|
||||||
@ -104,46 +107,6 @@ proc toStUInt*[bits: static[int]](flt: float, T: typedesc[StUint[bits]]): T =
|
|||||||
else:
|
else:
|
||||||
result = parse("0", StUint[bits])
|
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 =
|
proc first*(jArray: JsonNode, fieldName, id: string): JsonNode =
|
||||||
if jArray == nil:
|
if jArray == nil:
|
||||||
return 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]
|
result = results[0]
|
||||||
found = true
|
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) =
|
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(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")
|
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 status/statusgo_backend_new/network as status_network
|
||||||
import ./service_interface
|
import ./service_interface
|
||||||
import ./dto
|
|
||||||
import ./types
|
|
||||||
|
|
||||||
export service_interface
|
export service_interface
|
||||||
export dto, types
|
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "network-service"
|
topics = "network-service"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import dto, types
|
import dto, types
|
||||||
|
|
||||||
export dto
|
export dto, types
|
||||||
|
|
||||||
type
|
type
|
||||||
ServiceInterface* {.pure inheritable.} = ref object of RootObj
|
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/stickers as status_stickers
|
||||||
import status/statusgo_backend_new/chat as status_chat
|
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/response_type
|
||||||
import status/statusgo_backend_new/eth
|
import status/statusgo_backend_new/eth
|
||||||
import ./dto/stickers
|
import ./dto/stickers
|
||||||
|
import ../ens/utils as ens_utils
|
||||||
import ../eth/service as eth_service
|
import ../eth/service as eth_service
|
||||||
import ../settings/service as settings_service
|
import ../settings/service as settings_service
|
||||||
import ../wallet_account/service as wallet_account_service
|
import ../wallet_account/service as wallet_account_service
|
||||||
@ -126,7 +126,7 @@ QtObject:
|
|||||||
buyToken = BuyToken(packId: packId, address: address, price: price)
|
buyToken = BuyToken(packId: packId, address: address, price: price)
|
||||||
buyTxAbiEncoded = stickerMktContract.methods["buyToken"].encodeAbi(buyToken)
|
buyTxAbiEncoded = stickerMktContract.methods["buyToken"].encodeAbi(buyToken)
|
||||||
approveAndCall = ApproveAndCall[100](to: stickerMktContract.address, value: price, data: DynamicBytes[100].fromHex(buyTxAbiEncoded))
|
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 =
|
proc buyPack*(self: Service, packId: int, address, price, gas, gasPrice: string, isEIP1559Enabled: bool, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, success: var bool): string =
|
||||||
var
|
var
|
||||||
@ -147,11 +147,11 @@ QtObject:
|
|||||||
|
|
||||||
result = sntContract.methods["approveAndCall"].send(tx, approveAndCall, password, success)
|
result = sntContract.methods["approveAndCall"].send(tx, approveAndCall, password, success)
|
||||||
if success:
|
if success:
|
||||||
discard transactions.trackPendingTransaction(
|
self.transactionService.trackPendingTransaction(
|
||||||
result,
|
result,
|
||||||
address,
|
address,
|
||||||
$sntContract.address,
|
$sntContract.address,
|
||||||
transactions.PendingTransactionType.BuyStickerPack,
|
$PendingTransactionTypeDto.BuyStickerPack,
|
||||||
$packId
|
$packId
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ QtObject:
|
|||||||
var pendingStickerPacks = initHashSet[int]()
|
var pendingStickerPacks = initHashSet[int]()
|
||||||
if (pendingTransactions != ""):
|
if (pendingTransactions != ""):
|
||||||
for trx in pendingTransactions.parseJson{"result"}.getElems():
|
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)
|
pendingStickerPacks.incl(trx["additionalData"].getStr.parseInt)
|
||||||
|
|
||||||
for stickerPack in availableStickers:
|
for stickerPack in availableStickers:
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# include strformat, json
|
# include strformat, json
|
||||||
include ../../common/json_utils
|
include ../../common/json_utils
|
||||||
include ../../../app/core/tasks/common
|
|
||||||
import ../eth/dto/contract
|
import ../eth/dto/contract
|
||||||
import ../eth/utils
|
import ../eth/utils
|
||||||
|
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
include ../../common/json_utils
|
|
||||||
include ../../../app/core/tasks/common
|
|
||||||
import strutils
|
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
# Async load transactions
|
# Async load transactions
|
||||||
#################################################
|
#################################################
|
||||||
|
@ -1,6 +1,17 @@
|
|||||||
import json, strutils, stint
|
import json, strutils, stint
|
||||||
include ../../common/json_utils
|
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
|
type
|
||||||
TransactionDto* = ref object of RootObj
|
TransactionDto* = ref object of RootObj
|
||||||
id*: string
|
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/transactions as transactions
|
||||||
import status/statusgo_backend_new/wallet as status_wallet
|
import status/statusgo_backend_new/wallet as status_wallet
|
||||||
|
|
||||||
import ../../../app/core/[main]
|
import ../../../app/core/[main]
|
||||||
import ../../../app/core/tasks/[qt, threadpool]
|
import ../../../app/core/tasks/[qt, threadpool]
|
||||||
import ../wallet_account/service as wallet_account_service
|
import ../wallet_account/service as wallet_account_service
|
||||||
import ./service_interface, ./dto
|
import ./dto as transaction_dto
|
||||||
import ../eth/utils as eth_utils
|
import ../eth/utils as eth_utils
|
||||||
|
|
||||||
export service_interface
|
export transaction_dto
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "transaction-service"
|
topics = "transaction-service"
|
||||||
|
|
||||||
include async_tasks
|
include async_tasks
|
||||||
|
include ../../common/json_utils
|
||||||
|
|
||||||
# Signals which may be emitted by this service:
|
# Signals which may be emitted by this service:
|
||||||
const SIGNAL_TRANSACTIONS_LOADED* = "transactionsLoaded"
|
const SIGNAL_TRANSACTIONS_LOADED* = "transactionsLoaded"
|
||||||
|
|
||||||
|
type
|
||||||
|
TransactionMinedArgs* = ref object of Args
|
||||||
|
data*: string
|
||||||
|
transactionHash*: string
|
||||||
|
success*: bool
|
||||||
|
revertReason*: string
|
||||||
|
|
||||||
type
|
type
|
||||||
TransactionsLoadedArgs* = ref object of Args
|
TransactionsLoadedArgs* = ref object of Args
|
||||||
transactions*: seq[TransactionDto]
|
transactions*: seq[TransactionDto]
|
||||||
@ -63,6 +71,14 @@ QtObject:
|
|||||||
error "error: ", errDesription
|
error "error: ", errDesription
|
||||||
return
|
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] =
|
proc getTransfersByAddress*(self: Service, address: string, toBlock: Uint256, limit: int, loadMore: bool = false): seq[TransactionDto] =
|
||||||
try:
|
try:
|
||||||
let limitAsHex = "0x" & eth_utils.stripLeadingZeros(limit.toHex)
|
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] =
|
method fetchPrices(self: Service): Table[string, float64] =
|
||||||
let currency = self.settingsService.getCurrency()
|
let currency = self.settingsService.getCurrency()
|
||||||
var prices = {"ETH": fetchPrice("ETH", currency)}.toTable
|
var prices = {"ETH": fetchPrice("ETH", currency)}.toTable
|
||||||
@ -193,6 +196,8 @@ method getWalletAccounts*(self: Service): seq[WalletAccountDto] =
|
|||||||
return toSeq(self.accounts.values)
|
return toSeq(self.accounts.values)
|
||||||
|
|
||||||
method getWalletAccount*(self: Service, accountIndex: int): WalletAccountDto =
|
method getWalletAccount*(self: Service, accountIndex: int): WalletAccountDto =
|
||||||
|
if(accountIndex < 0 or accountIndex >= self.getWalletAccounts().len):
|
||||||
|
return
|
||||||
return self.getWalletAccounts()[accountIndex]
|
return self.getWalletAccounts()[accountIndex]
|
||||||
|
|
||||||
method getCurrencyBalance*(self: Service): float64 =
|
method getCurrencyBalance*(self: Service): float64 =
|
||||||
|
@ -47,3 +47,6 @@ method updateWalletAccount*(self: ServiceInterface, address: string, accountName
|
|||||||
|
|
||||||
method toggleTokenVisible*(self: ServiceInterface, symbol: string) {.base.} =
|
method toggleTokenVisible*(self: ServiceInterface, symbol: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
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.top: separator.bottom
|
||||||
anchors.topMargin: 10
|
anchors.topMargin: 10
|
||||||
width: stack.width
|
width: stack.width
|
||||||
isContact: root.isContact
|
|
||||||
onSelectedRecipientChanged: {
|
onSelectedRecipientChanged: {
|
||||||
addressRequiredValidator.address = root.isRequested ? selectFromAccount.selectedAccount.address : selectRecipient.selectedRecipient.address
|
addressRequiredValidator.address = root.isRequested ? selectFromAccount.selectedAccount.address : selectRecipient.selectedRecipient.address
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,7 @@ StatusAppTwoPanelLayout {
|
|||||||
|
|
||||||
EnsView {
|
EnsView {
|
||||||
id: ensContainer
|
id: ensContainer
|
||||||
store: profileView.store
|
ensUsernamesStore: profileView.store.ensUsernamesStore
|
||||||
messageStore: profileView.globalStore.messageStore
|
|
||||||
contactsStore: profileView.store.contactsStore
|
contactsStore: profileView.store.contactsStore
|
||||||
profileContentWidth: _internal.profileContentWidth
|
profileContentWidth: _internal.profileContentWidth
|
||||||
}
|
}
|
||||||
|
@ -15,24 +15,23 @@ ModalPopup {
|
|||||||
//% "Primary username"
|
//% "Primary username"
|
||||||
title: qsTrId("ens-primary-username")
|
title: qsTrId("ens-primary-username")
|
||||||
|
|
||||||
|
property var ensUsernamesStore
|
||||||
property string newUsername: ""
|
property string newUsername: ""
|
||||||
|
|
||||||
onOpened: {
|
onOpened: {
|
||||||
for(var i in ensNames.contentItem.children){
|
for(var i in ensNames.contentItem.children){
|
||||||
// Not Refactored Yet
|
ensNames.contentItem.children[i].checked = ensNames.contentItem.children[i].text === popup.ensUsernamesStore.preferredUsername
|
||||||
// ensNames.contentItem.children[i].checked = ensNames.contentItem.children[i].text === profileModel.ens.preferredUsername
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: lbl1
|
id: lbl1
|
||||||
// Not Refactored Yet
|
text: popup.ensUsernamesStore.preferredUsername ?
|
||||||
// text: profileModel.ens.preferredUsername ?
|
//% "Your messages are displayed to others with this username:"
|
||||||
// //% "Your messages are displayed to others with this username:"
|
qsTrId("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."
|
||||||
// //% "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-")
|
||||||
// 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
|
font.pixelSize: 15
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@ -42,8 +41,7 @@ ModalPopup {
|
|||||||
id: lbl2
|
id: lbl2
|
||||||
anchors.top: lbl1.bottom
|
anchors.top: lbl1.bottom
|
||||||
anchors.topMargin: Style.current.padding
|
anchors.topMargin: Style.current.padding
|
||||||
// Not Refactored Yet
|
text: popup.ensUsernamesStore.preferredUsername
|
||||||
// text: profileModel.ens.preferredUsername
|
|
||||||
font.pixelSize: 17
|
font.pixelSize: 17
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
}
|
}
|
||||||
@ -60,16 +58,14 @@ ModalPopup {
|
|||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
// Not Refactored Yet
|
model: root.ensUsernamesStore.ensUsernamesModel
|
||||||
// model: profileModel.ens
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
clip: true
|
clip: true
|
||||||
id: ensNames
|
id: ensNames
|
||||||
delegate: RadioDelegate {
|
delegate: RadioDelegate {
|
||||||
id: radioDelegate
|
id: radioDelegate
|
||||||
text: username
|
text: ensUsername
|
||||||
// Not Refactored Yet
|
checked: popup.ensUsernamesStore.preferredUsername === ensUsername
|
||||||
// checked: profileModel.ens.preferredUsername === username
|
|
||||||
|
|
||||||
contentItem: StyledText {
|
contentItem: StyledText {
|
||||||
color: Style.current.textColor
|
color: Style.current.textColor
|
||||||
@ -82,7 +78,7 @@ ModalPopup {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
parent.checked = true
|
parent.checked = true
|
||||||
newUsername = username;
|
newUsername = ensUsername;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,8 +86,7 @@ ModalPopup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onNewUsernameChanged: {
|
onNewUsernameChanged: {
|
||||||
// Not Refactored Yet
|
btnSelectPreferred.state = newUsername === popup.ensUsernamesStore.preferredUsername ? "inactive" : "active"
|
||||||
// btnSelectPreferred.state = newUsername === profileModel.ens.preferredUsername ? "inactive" : "active"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
footer: Item {
|
footer: Item {
|
||||||
@ -135,10 +130,9 @@ ModalPopup {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked : {
|
onClicked : {
|
||||||
if(btnSelectPreferred.state === "active"){
|
if(btnSelectPreferred.state === "active"){
|
||||||
// Not Refactored Yet
|
popup.ensUsernamesStore.setPrefferedEnsUsername(newUsername);
|
||||||
// profileModel.ens.preferredUsername = newUsername;
|
newUsername = "";
|
||||||
// newUsername = "";
|
popup.close();
|
||||||
// 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
|
privacyModule: profileSectionModuleInst.privacyModule
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not Refactored Yet
|
property EnsUsernamesStore ensUsernamesStore: EnsUsernamesStore {
|
||||||
// property var chatsModelInst: chatsModel
|
ensUsernamesModule: profileSectionModuleInst.ensUsernamesModule
|
||||||
// Not Refactored Yet
|
}
|
||||||
// property var utilsModelInst: utilsModel
|
|
||||||
// Not Refactored Yet
|
|
||||||
// property var walletModelInst: walletModel
|
|
||||||
// Not Refactored Yet
|
|
||||||
// property var nodeModelInst: nodeModel
|
|
||||||
|
|
||||||
// Not Refactored Yet
|
|
||||||
// property var ens: profileModelInst.ens
|
|
||||||
property var dappList: dappPermissionsModule.dapps
|
property var dappList: dappPermissionsModule.dapps
|
||||||
property var permissionList: dappPermissionsModule.permissions
|
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 profile_id: 0
|
||||||
property int contacts_id: 1
|
property int contacts_id: 1
|
||||||
@ -188,90 +170,6 @@ QtObject {
|
|||||||
dappPermissionsModule.fetchDapps()
|
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() {
|
function getCurrentVersion() {
|
||||||
return aboutModuleInst.getCurrentVersion()
|
return aboutModuleInst.getCurrentVersion()
|
||||||
}
|
}
|
||||||
@ -283,24 +181,4 @@ QtObject {
|
|||||||
function checkForUpdates() {
|
function checkForUpdates() {
|
||||||
aboutModuleInst.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 {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
property var store
|
property var ensUsernamesStore
|
||||||
property var contactsStore
|
property var contactsStore
|
||||||
property string username: ""
|
property string username: ""
|
||||||
property string walletAddress: "-"
|
property string walletAddress: "-"
|
||||||
@ -50,15 +50,17 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: root.store.ens
|
target: root.ensUsernamesStore.ensUsernamesModule
|
||||||
onDetailsObtained: {
|
onDetailsObtained: {
|
||||||
if(username != ensName) return;
|
if(username != ensName)
|
||||||
|
return;
|
||||||
walletAddressLbl.subTitle = address;
|
walletAddressLbl.subTitle = address;
|
||||||
keyLbl.subTitle = pubkey.substring(0, 20) + "..." + pubkey.substring(pubkey.length - 20);
|
keyLbl.subTitle = pubkey.substring(0, 20) + "..." + pubkey.substring(pubkey.length - 20);
|
||||||
walletAddressLbl.visible = true;
|
walletAddressLbl.visible = true;
|
||||||
keyLbl.visible = true;
|
keyLbl.visible = true;
|
||||||
releaseBtn.visible = isStatus
|
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()
|
expiration = new Date(expirationTime * 1000).getTime()
|
||||||
}
|
}
|
||||||
onLoading: {
|
onLoading: {
|
||||||
@ -80,7 +82,7 @@ Item {
|
|||||||
icon.name: "copy"
|
icon.name: "copy"
|
||||||
tooltip.text: qsTr("Copied to clipboard!")
|
tooltip.text: qsTr("Copied to clipboard!")
|
||||||
iconButton.onClicked: {
|
iconButton.onClicked: {
|
||||||
root.store.copyToClipboard(subTitle)
|
root.ensUsernamesStore.copyToClipboard(subTitle)
|
||||||
tooltip.visible = !tooltip.visible
|
tooltip.visible = !tooltip.visible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +95,7 @@ Item {
|
|||||||
icon.name: "copy"
|
icon.name: "copy"
|
||||||
tooltip.text: qsTr("Copied to clipboard!")
|
tooltip.text: qsTr("Copied to clipboard!")
|
||||||
iconButton.onClicked: {
|
iconButton.onClicked: {
|
||||||
root.store.copyToClipboard(subTitle)
|
root.ensUsernamesStore.copyToClipboard(subTitle)
|
||||||
tooltip.visible = !tooltip.visible
|
tooltip.visible = !tooltip.visible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,9 +103,10 @@ Item {
|
|||||||
Component {
|
Component {
|
||||||
id: transactionDialogComponent
|
id: transactionDialogComponent
|
||||||
StatusETHTransactionModal {
|
StatusETHTransactionModal {
|
||||||
|
ensUsernamesStore: root.ensUsernamesStore
|
||||||
contactsStore: root.contactsStore
|
contactsStore: root.contactsStore
|
||||||
onOpened: {
|
onOpened: {
|
||||||
root.store.getGasPricePredictions()
|
root.ensUsernamesStore.fetchGasPrice()
|
||||||
}
|
}
|
||||||
title: qsTr("Connect username with your pubkey")
|
title: qsTr("Connect username with your pubkey")
|
||||||
onClosed: {
|
onClosed: {
|
||||||
@ -111,10 +114,10 @@ Item {
|
|||||||
}
|
}
|
||||||
estimateGasFunction: function(selectedAccount) {
|
estimateGasFunction: function(selectedAccount) {
|
||||||
if (username === "" || !selectedAccount) return 100000;
|
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) {
|
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password) {
|
||||||
return root.store.releaseEns(username,
|
return root.ensUsernamesStore.releaseEns(username,
|
||||||
selectedAddress,
|
selectedAddress,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
gasPrice,
|
gasPrice,
|
||||||
|
@ -20,7 +20,8 @@ Item {
|
|||||||
signal addBtnClicked()
|
signal addBtnClicked()
|
||||||
signal selectEns(string username)
|
signal selectEns(string username)
|
||||||
|
|
||||||
property var store
|
property var ensUsernamesStore
|
||||||
|
|
||||||
property int profileContentWidth
|
property int profileContentWidth
|
||||||
|
|
||||||
// Defaults to show message
|
// Defaults to show message
|
||||||
@ -34,13 +35,11 @@ Item {
|
|||||||
property string authorPrevMsg: "1"
|
property string authorPrevMsg: "1"
|
||||||
property bool isText: true
|
property bool isText: true
|
||||||
property var clickMessage: function(){}
|
property var clickMessage: function(){}
|
||||||
property string identicon: store.identicon
|
|
||||||
//property string identicon: userProfile.icon
|
|
||||||
property int timestamp: 1577872140
|
|
||||||
property var messageStore
|
|
||||||
|
|
||||||
function shouldDisplayExampleMessage(){
|
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
|
anchors.fill: parent
|
||||||
|
|
||||||
@ -94,7 +93,7 @@ Item {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: selectEns(model.username)
|
onClicked: selectEns(model.ensUsername)
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@ -117,8 +116,8 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
sourceComponent: model.username.endsWith(".stateofus.eth") ? statusENS : normalENS
|
sourceComponent: model.ensUsername.endsWith(".stateofus.eth") ? statusENS : normalENS
|
||||||
property string username: model.username
|
property string username: model.ensUsername
|
||||||
property bool isPending: model.isPending
|
property bool isPending: model.isPending
|
||||||
active: true
|
active: true
|
||||||
anchors.left: circle.right
|
anchors.left: circle.right
|
||||||
@ -129,6 +128,7 @@ Item {
|
|||||||
|
|
||||||
ENSPopup {
|
ENSPopup {
|
||||||
id: ensPopup
|
id: ensPopup
|
||||||
|
ensUsernamesStore: root.ensUsernamesStore
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
@ -209,7 +209,7 @@ Item {
|
|||||||
ListView {
|
ListView {
|
||||||
id: lvEns
|
id: lvEns
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
model: root.store.ens
|
model: root.ensUsernamesStore.ensUsernamesModel
|
||||||
spacing: 10
|
spacing: 10
|
||||||
clip: true
|
clip: true
|
||||||
delegate: ensDelegate
|
delegate: ensDelegate
|
||||||
@ -225,7 +225,8 @@ Item {
|
|||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
id: chatSettingsLabel
|
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"
|
//% "Chat settings"
|
||||||
text: qsTrId("chat-settings")
|
text: qsTrId("chat-settings")
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@ -258,7 +259,7 @@ Item {
|
|||||||
id: usernameLabel2
|
id: usernameLabel2
|
||||||
visible: chatSettingsLabel.visible
|
visible: chatSettingsLabel.visible
|
||||||
//% "None selected"
|
//% "None selected"
|
||||||
text: root.store.preferredUsername || qsTrId("none-selected")
|
text: root.ensUsernamesStore.preferredUsername || qsTrId("none-selected")
|
||||||
anchors.left: usernameLabel.right
|
anchors.left: usernameLabel.right
|
||||||
anchors.leftMargin: Style.current.padding
|
anchors.leftMargin: Style.current.padding
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
@ -284,10 +285,10 @@ Item {
|
|||||||
anchors.leftMargin: Style.current.padding
|
anchors.leftMargin: Style.current.padding
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 20
|
anchors.topMargin: 20
|
||||||
// isCurrentUser: root.isCurrentUser
|
|
||||||
// profileImage: root.messageStore.profileImageSource
|
icon: root.ensUsernamesStore.icon
|
||||||
// isMessage: root.messageStore.isMessage
|
isIdenticon: root.ensUsernamesStore.isIdenticon
|
||||||
// identiconImageSource: root.messageStore.identicon
|
|
||||||
onClickMessage: {
|
onClickMessage: {
|
||||||
root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply);
|
root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply);
|
||||||
}
|
}
|
||||||
@ -295,19 +296,14 @@ Item {
|
|||||||
|
|
||||||
UsernameLabel {
|
UsernameLabel {
|
||||||
id: chatName
|
id: chatName
|
||||||
label.text: "@" + (root.store.preferredUsername.replace(".stateofus.eth", ""))
|
|
||||||
label.color: Style.current.blue
|
|
||||||
anchors.leftMargin: 20
|
anchors.leftMargin: 20
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 0
|
anchors.topMargin: 0
|
||||||
anchors.left: chatImage.right
|
anchors.left: chatImage.right
|
||||||
// isCurrentUser: root.messageStore.isCurrentUser
|
|
||||||
// userName: root.messageStore.userName
|
displayName: "@" + (root.ensUsernamesStore.preferredUsername.replace(".stateofus.eth", ""))
|
||||||
// localName: root.messageStore.localName
|
localName: ""
|
||||||
// displayUserName: root.messageStore.displayUserName
|
amISender: true
|
||||||
onClickMessage: {
|
|
||||||
root.parent.clickMessage(true, false, false, null, false, false, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@ -343,8 +339,8 @@ Item {
|
|||||||
anchors.bottomMargin: Style.current.padding
|
anchors.bottomMargin: Style.current.padding
|
||||||
anchors.right: chatBox.right
|
anchors.right: chatBox.right
|
||||||
anchors.rightMargin: Style.current.padding
|
anchors.rightMargin: Style.current.padding
|
||||||
//timestamp: root.timestamp
|
timestamp: new Date().getTime()
|
||||||
visible: root.messageStore.isMessage
|
visible: true
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
@ -360,10 +356,7 @@ Item {
|
|||||||
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: root.store.ens
|
target: root.ensUsernamesStore.ensUsernamesModule
|
||||||
onPreferredUsernameChanged: {
|
|
||||||
messagesShownAs.visible = shouldDisplayExampleMessage()
|
|
||||||
}
|
|
||||||
onUsernameConfirmed: {
|
onUsernameConfirmed: {
|
||||||
messagesShownAs.visible = shouldDisplayExampleMessage()
|
messagesShownAs.visible = shouldDisplayExampleMessage()
|
||||||
chatSettingsLabel.visible = true
|
chatSettingsLabel.visible = true
|
||||||
|
@ -15,7 +15,7 @@ import shared.controls 1.0
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var store
|
property var ensUsernamesStore
|
||||||
property var contactsStore
|
property var contactsStore
|
||||||
property int profileContentWidth
|
property int profileContentWidth
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ Item {
|
|||||||
property string ensStatus: ""
|
property string ensStatus: ""
|
||||||
|
|
||||||
property var validateENS: Backpressure.debounce(root, 500, function (ensName, isStatus){
|
property var validateENS: Backpressure.debounce(root, 500, function (ensName, isStatus){
|
||||||
store.validateEns(ensName, isStatus)
|
root.ensUsernamesStore.checkEnsUsernameAvailability(ensName, isStatus)
|
||||||
});
|
});
|
||||||
|
|
||||||
function validate(ensUsername) {
|
function validate(ensUsername) {
|
||||||
@ -61,9 +61,10 @@ Item {
|
|||||||
Component {
|
Component {
|
||||||
id: transactionDialogComponent
|
id: transactionDialogComponent
|
||||||
StatusETHTransactionModal {
|
StatusETHTransactionModal {
|
||||||
|
ensUsernamesStore: root.ensUsernamesStore
|
||||||
contactsStore: root.contactsStore
|
contactsStore: root.contactsStore
|
||||||
onOpened: {
|
onOpened: {
|
||||||
root.store.getGasPrice()
|
root.ensUsernamesStore.fetchGasPrice()
|
||||||
}
|
}
|
||||||
title: qsTr("Connect username with your pubkey")
|
title: qsTr("Connect username with your pubkey")
|
||||||
onClosed: {
|
onClosed: {
|
||||||
@ -71,13 +72,15 @@ Item {
|
|||||||
}
|
}
|
||||||
estimateGasFunction: function(selectedAccount) {
|
estimateGasFunction: function(selectedAccount) {
|
||||||
if (ensUsername.text === "" || !selectedAccount) return 80000;
|
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) {
|
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,
|
selectedAddress,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
gasPrice,
|
gasPrice,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
password)
|
password)
|
||||||
}
|
}
|
||||||
onSuccess: function(){
|
onSuccess: function(){
|
||||||
@ -148,25 +151,25 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: mainModule
|
target: root.ensUsernamesStore.ensUsernamesModule
|
||||||
onResolvedENS: {
|
onUsernameAvailabilityChecked: {
|
||||||
if(!validate(ensUsername.text)) return;
|
if(!validate(ensUsername.text)) return;
|
||||||
valid = false;
|
valid = false;
|
||||||
loading = false;
|
loading = false;
|
||||||
ensStatus = ensResult;
|
ensStatus = availabilityStatus;
|
||||||
switch(ensResult){
|
switch(availabilityStatus){
|
||||||
case "available":
|
case "available":
|
||||||
case "owned":
|
case "owned":
|
||||||
case "connected":
|
case "connected":
|
||||||
case "connected-different-key":
|
case "connected-different-key":
|
||||||
valid = true;
|
valid = true;
|
||||||
validationMessage = Constants.ensState[ensResult]
|
validationMessage = Constants.ensState[availabilityStatus]
|
||||||
break;
|
break;
|
||||||
case "taken":
|
case "taken":
|
||||||
validationMessage = Constants.ensState[!isStatus ? 'taken-custom' : 'taken']
|
validationMessage = Constants.ensState[!isStatus ? 'taken-custom' : 'taken']
|
||||||
break;
|
break;
|
||||||
case "already-connected":
|
case "already-connected":
|
||||||
validationMessage = Constants.ensState[ensResult]
|
validationMessage = Constants.ensState[availabilityStatus]
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,7 +192,7 @@ Item {
|
|||||||
if(!valid) return;
|
if(!valid) return;
|
||||||
|
|
||||||
if(ensStatus === Constants.ens_connected){
|
if(ensStatus === Constants.ens_connected){
|
||||||
root.store.ensConnectOwnedUsername(ensUsername.text, isStatus);
|
root.ensUsernamesStore.ensConnectOwnedUsername(ensUsername.text, isStatus);
|
||||||
continueClicked(ensStatus, ensUsername.text)
|
continueClicked(ensStatus, ensUsername.text)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,10 @@ import StatusQ.Components 0.1
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
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 backBtnClicked();
|
||||||
signal usernameRegistered(userName: string);
|
signal usernameRegistered(userName: string);
|
||||||
@ -45,14 +45,16 @@ Item {
|
|||||||
this.active = false // kill an opened instance
|
this.active = false // kill an opened instance
|
||||||
}
|
}
|
||||||
sourceComponent: StatusSNTTransactionModal {
|
sourceComponent: StatusSNTTransactionModal {
|
||||||
|
store: root.ensUsernamesStore
|
||||||
|
contactsStore: root.contactsStore
|
||||||
assetPrice: "10"
|
assetPrice: "10"
|
||||||
contractAddress: root.store.ensRegisterAddress
|
contractAddress: root.ensUsernamesStore.getEnsRegisteredAddress()
|
||||||
estimateGasFunction: function(selectedAccount, uuid) {
|
estimateGasFunction: function(selectedAccount, uuid) {
|
||||||
if (username === "" || !selectedAccount) return 380000;
|
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) {
|
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password) {
|
||||||
return root.store.registerEns(
|
return root.ensUsernamesStore.registerEns(
|
||||||
username,
|
username,
|
||||||
selectedAddress,
|
selectedAddress,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
@ -165,7 +167,7 @@ Item {
|
|||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
//% "%1 (Status UsernameRegistrar)."
|
//% "%1 (Status UsernameRegistrar)."
|
||||||
text: qsTrId("-1--status-usernameregistrar--").arg(root.store.getEnsUsernameRegistrar())
|
text: qsTrId("-1--status-usernameregistrar--").arg(root.ensUsernamesStore.getEnsRegisteredAddress())
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@ -175,7 +177,9 @@ Item {
|
|||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
//% "<a href='%1%2'>Look up on Etherscan</a>"
|
//% "<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.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
onLinkActivated: Global.openLink(link)
|
onLinkActivated: Global.openLink(link)
|
||||||
@ -189,7 +193,7 @@ Item {
|
|||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
//% "%1 (ENS Registry)."
|
//% "%1 (ENS Registry)."
|
||||||
text: qsTrId("-1--ens-registry--").arg(root.ensRegistry)
|
text: qsTrId("-1--ens-registry--").arg(root.ensUsernamesStore.getEnsRegistry())
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@ -199,7 +203,9 @@ Item {
|
|||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
//% "<a href='%1%2'>Look up on Etherscan</a>"
|
//% "<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.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
onLinkActivated: Global.openLink(link)
|
onLinkActivated: Global.openLink(link)
|
||||||
@ -270,11 +276,11 @@ Item {
|
|||||||
id: walletAddressLbl
|
id: walletAddressLbl
|
||||||
//% "Wallet address"
|
//% "Wallet address"
|
||||||
title: qsTrId("wallet-address")
|
title: qsTrId("wallet-address")
|
||||||
subTitle: root.store.getWalletDefaultAddress()
|
subTitle: root.ensUsernamesStore.getWalletDefaultAddress()
|
||||||
tooltip.text: qsTr("Copied to clipboard!")
|
tooltip.text: qsTr("Copied to clipboard!")
|
||||||
icon.name: "copy"
|
icon.name: "copy"
|
||||||
iconButton.onClicked: {
|
iconButton.onClicked: {
|
||||||
root.store.copyToClipboard(subTitle)
|
root.ensUsernamesStore.copyToClipboard(subTitle)
|
||||||
tooltip.visible = !tooltip.visible
|
tooltip.visible = !tooltip.visible
|
||||||
}
|
}
|
||||||
anchors.top: ensUsername.bottom
|
anchors.top: ensUsername.bottom
|
||||||
@ -286,13 +292,13 @@ Item {
|
|||||||
//% "Key"
|
//% "Key"
|
||||||
title: qsTrId("key")
|
title: qsTrId("key")
|
||||||
subTitle: {
|
subTitle: {
|
||||||
let pubKey = root.store.pubKey;
|
let pubKey = root.ensUsernamesStore.pubkey;
|
||||||
return pubKey.substring(0, 20) + "..." + pubKey.substring(pubKey.length - 20);
|
return pubKey.substring(0, 20) + "..." + pubKey.substring(pubKey.length - 20);
|
||||||
}
|
}
|
||||||
tooltip.text: qsTr("Copied to clipboard!")
|
tooltip.text: qsTr("Copied to clipboard!")
|
||||||
icon.name: "copy"
|
icon.name: "copy"
|
||||||
iconButton.onClicked: {
|
iconButton.onClicked: {
|
||||||
root.store.copyToClipboard(root.store.pubKey)
|
root.ensUsernamesStore.copyToClipboard(root.ensUsernamesStore.pubkey)
|
||||||
tooltip.visible = !tooltip.visible
|
tooltip.visible = !tooltip.visible
|
||||||
}
|
}
|
||||||
anchors.top: walletAddressLbl.bottom
|
anchors.top: walletAddressLbl.bottom
|
||||||
@ -345,7 +351,7 @@ Item {
|
|||||||
id: image1
|
id: image1
|
||||||
height: 50
|
height: 50
|
||||||
width: height
|
width: height
|
||||||
source: Style.svg("status-logo")
|
source: Style.png("tokens/SNT")
|
||||||
sourceSize: Qt.size(width, height)
|
sourceSize: Qt.size(width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,12 +384,12 @@ Item {
|
|||||||
anchors.bottomMargin: Style.current.padding
|
anchors.bottomMargin: Style.current.padding
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Style.current.padding
|
anchors.rightMargin: Style.current.padding
|
||||||
text: parseFloat(root.store.getSntBalance()) < 10 ?
|
text: parseFloat(root.ensUsernamesStore.getSntBalance()) < 10 ?
|
||||||
//% "Not enough SNT"
|
//% "Not enough SNT"
|
||||||
qsTrId("not-enough-snt") :
|
qsTrId("not-enough-snt") :
|
||||||
//% "Register"
|
//% "Register"
|
||||||
qsTrId("ens-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()
|
onClicked: localAccountSensitiveSettings.isWalletEnabled ? transactionDialog.open() : confirmationPopup.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,10 +11,10 @@ import "../stores"
|
|||||||
Item {
|
Item {
|
||||||
id: ensView
|
id: ensView
|
||||||
|
|
||||||
property var store
|
property EnsUsernamesStore ensUsernamesStore
|
||||||
|
|
||||||
property var contactsStore
|
property var contactsStore
|
||||||
|
|
||||||
property var messageStore
|
|
||||||
property int profileContentWidth
|
property int profileContentWidth
|
||||||
property bool showSearchScreen: false
|
property bool showSearchScreen: false
|
||||||
property string addedUsername: ""
|
property string addedUsername: ""
|
||||||
@ -29,7 +29,7 @@ Item {
|
|||||||
signal goToList();
|
signal goToList();
|
||||||
|
|
||||||
function goToStart(){
|
function goToStart(){
|
||||||
if(ensView.store.ens.rowCount() > 0 && Global.networkGuarded){
|
if(ensView.ensUsernamesStore.ensUsernamesModel.count > 0 && Global.networkGuarded){
|
||||||
goToList();
|
goToList();
|
||||||
} else {
|
} else {
|
||||||
goToWelcome();
|
goToWelcome();
|
||||||
@ -213,7 +213,7 @@ Item {
|
|||||||
Component {
|
Component {
|
||||||
id: welcome
|
id: welcome
|
||||||
EnsWelcomeView {
|
EnsWelcomeView {
|
||||||
username: ensView.store.username
|
username: ensView.ensUsernamesStore.username
|
||||||
onStartBtnClicked: next(null)
|
onStartBtnClicked: next(null)
|
||||||
profileContentWidth: ensView.profileContentWidth
|
profileContentWidth: ensView.profileContentWidth
|
||||||
}
|
}
|
||||||
@ -222,7 +222,7 @@ Item {
|
|||||||
Component {
|
Component {
|
||||||
id: search
|
id: search
|
||||||
EnsSearchView {
|
EnsSearchView {
|
||||||
store: ensView.store
|
ensUsernamesStore: ensView.ensUsernamesStore
|
||||||
contactsStore: ensView.contactsStore
|
contactsStore: ensView.contactsStore
|
||||||
profileContentWidth: ensView.profileContentWidth
|
profileContentWidth: ensView.profileContentWidth
|
||||||
onContinueClicked: {
|
onContinueClicked: {
|
||||||
@ -243,7 +243,8 @@ Item {
|
|||||||
Component {
|
Component {
|
||||||
id: termsAndConditions
|
id: termsAndConditions
|
||||||
EnsTermsAndConditionsView {
|
EnsTermsAndConditionsView {
|
||||||
store: ensView.store
|
ensUsernamesStore: ensView.ensUsernamesStore
|
||||||
|
contactsStore: ensView.contactsStore
|
||||||
username: selectedUsername
|
username: selectedUsername
|
||||||
onBackBtnClicked: back();
|
onBackBtnClicked: back();
|
||||||
onUsernameRegistered: done(userName);
|
onUsernameRegistered: done(userName);
|
||||||
@ -284,12 +285,12 @@ Item {
|
|||||||
Component {
|
Component {
|
||||||
id: list
|
id: list
|
||||||
EnsListView {
|
EnsListView {
|
||||||
store: ensView.store
|
ensUsernamesStore: ensView.ensUsernamesStore
|
||||||
messageStore: ensView.messageStore
|
|
||||||
profileContentWidth: ensView.profileContentWidth
|
profileContentWidth: ensView.profileContentWidth
|
||||||
onAddBtnClicked: next("search")
|
onAddBtnClicked: next("search")
|
||||||
onSelectEns: {
|
onSelectEns: {
|
||||||
ensView.store.ensDetails(username)
|
ensView.ensUsernamesStore.ensDetails(username)
|
||||||
selectedUsername = username;
|
selectedUsername = username;
|
||||||
next("details")
|
next("details")
|
||||||
}
|
}
|
||||||
@ -299,7 +300,7 @@ Item {
|
|||||||
Component {
|
Component {
|
||||||
id: details
|
id: details
|
||||||
EnsDetailsView {
|
EnsDetailsView {
|
||||||
store: ensView.store
|
ensUsernamesStore: ensView.ensUsernamesStore
|
||||||
contactsStore: ensView.contactsStore
|
contactsStore: ensView.contactsStore
|
||||||
username: selectedUsername
|
username: selectedUsername
|
||||||
onBackBtnClicked: back();
|
onBackBtnClicked: back();
|
||||||
@ -318,14 +319,14 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: ensView.store.ens
|
target: ensView.ensUsernamesStore.ensUsernamesModule
|
||||||
onTransactionWasSent: {
|
onTransactionWasSent: {
|
||||||
//% "Transaction pending..."
|
//% "Transaction pending..."
|
||||||
Global.toastMessage.title = qsTrId("ens-transaction-pending")
|
Global.toastMessage.title = qsTrId("ens-transaction-pending")
|
||||||
Global.toastMessage.source = Style.svg("loading")
|
Global.toastMessage.source = Style.svg("loading")
|
||||||
Global.toastMessage.iconColor = Style.current.primary
|
Global.toastMessage.iconColor = Style.current.primary
|
||||||
Global.toastMessage.iconRotates = true
|
Global.toastMessage.iconRotates = true
|
||||||
Global.toastMessage.link = `${root.store.etherscanLink}/${txResult}`
|
Global.toastMessage.link = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txResult}`
|
||||||
Global.toastMessage.open()
|
Global.toastMessage.open()
|
||||||
}
|
}
|
||||||
onTransactionCompleted: {
|
onTransactionCompleted: {
|
||||||
@ -355,7 +356,7 @@ Item {
|
|||||||
Global.toastMessage.source = Style.svg("block-icon")
|
Global.toastMessage.source = Style.svg("block-icon")
|
||||||
Global.toastMessage.iconColor = Style.current.danger
|
Global.toastMessage.iconColor = Style.current.danger
|
||||||
}
|
}
|
||||||
Global.toastMessage.link = `${root.store.etherscanLink}/${txHash}`
|
Global.toastMessage.link = `${ensView.ensUsernamesStore.getEtherscanLink()}/${txHash}`
|
||||||
Global.toastMessage.open()
|
Global.toastMessage.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,17 +37,16 @@ Item {
|
|||||||
function resolveEns() {
|
function resolveEns() {
|
||||||
if (selectedContact.ensVerified) {
|
if (selectedContact.ensVerified) {
|
||||||
root.isResolvedAddress = false
|
root.isResolvedAddress = false
|
||||||
ensResolver.resolveEns(selectedContact.name)
|
ensResolver.resolveEns(selectedContact.alias)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should be removed most likely.
|
Component.onCompleted: {
|
||||||
// onContactsChanged: {
|
if (root.readOnly) {
|
||||||
// if (root.readOnly) {
|
return
|
||||||
// return
|
}
|
||||||
// }
|
root.selectedContact = { alias: selectAContact }
|
||||||
// root.selectedContact = { name: selectAContact }
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
onSelectedContactChanged: validate()
|
onSelectedContactChanged: validate()
|
||||||
|
|
||||||
@ -55,8 +54,8 @@ Item {
|
|||||||
if (!selectedContact) {
|
if (!selectedContact) {
|
||||||
return root.isValid
|
return root.isValid
|
||||||
}
|
}
|
||||||
let isValidAddress = Utils.isValidAddress(selectedContact.address)
|
let isValidAddress = Utils.isValidAddress(selectedContact.publicKey)
|
||||||
let isDefaultValue = selectedContact.name === selectAContact
|
let isDefaultValue = selectedContact.alias === selectAContact
|
||||||
let isValid = (selectedContact.ensVerified && isValidAddress) || isPending || isValidAddress
|
let isValid = (selectedContact.ensVerified && isValidAddress) || isPending || isValidAddress
|
||||||
select.validationError = ""
|
select.validationError = ""
|
||||||
if (!isValid && !isDefaultValue &&
|
if (!isValid && !isDefaultValue &&
|
||||||
@ -76,7 +75,7 @@ Item {
|
|||||||
visible: root.readOnly
|
visible: root.readOnly
|
||||||
width: parent.width
|
width: parent.width
|
||||||
//% "No contact selected"
|
//% "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.leftPadding: 14
|
||||||
textField.topPadding: 18
|
textField.topPadding: 18
|
||||||
textField.bottomPadding: 18
|
textField.bottomPadding: 18
|
||||||
@ -103,15 +102,15 @@ Item {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 14
|
anchors.leftMargin: 14
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
image.width: (!!selectedContact && !!selectedContact.identicon) ? 32 : 0
|
image.width: (!!selectedContact && !!selectedContact.displayIcon) ? 32 : 0
|
||||||
image.height: 32
|
image.height: 32
|
||||||
image.source: (!!selectedContact && !!selectedContact.identicon) ? selectedContact.identicon : ""
|
image.source: (!!selectedContact && !!selectedContact.displayIcon) ? selectedContact.displayIcon : ""
|
||||||
image.isIdenticon: true
|
image.isIdenticon: (!!selectedContact && !!selectedContact.isDisplayIconIdenticon) ? selectedContact.isDisplayIconIdenticon : true
|
||||||
active: !!selectedContact && !!selectedContact.identicon
|
active: !!selectedContact && !!selectedContact.displayIcon
|
||||||
}
|
}
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
id: selectedTextField
|
id: selectedTextField
|
||||||
text: !!selectedContact ? selectedContact.name : ""
|
text: !!selectedContact ? selectedContact.alias : ""
|
||||||
anchors.left: iconImg.right
|
anchors.left: iconImg.right
|
||||||
anchors.leftMargin: 4
|
anchors.leftMargin: 4
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
@ -148,12 +147,12 @@ Item {
|
|||||||
onResolved: {
|
onResolved: {
|
||||||
root.isResolvedAddress = true
|
root.isResolvedAddress = true
|
||||||
var selectedContact = root.selectedContact
|
var selectedContact = root.selectedContact
|
||||||
selectedContact.address = resolvedAddress
|
selectedContact.publicKey = resolvedAddress
|
||||||
root.selectedContact = selectedContact
|
root.selectedContact = selectedContact
|
||||||
}
|
}
|
||||||
onIsPendingChanged: {
|
onIsPendingChanged: {
|
||||||
if (isPending) {
|
if (isPending) {
|
||||||
root.selectedContact.address = ""
|
root.selectedContact.publicKey = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,6 +164,8 @@ Item {
|
|||||||
property bool isFirstItem: index === 0
|
property bool isFirstItem: index === 0
|
||||||
property bool isLastItem: index === root.contactsStore.myContactsModel.count - 1
|
property bool isLastItem: index === root.contactsStore.myContactsModel.count - 1
|
||||||
|
|
||||||
|
property var currentContact: Utils.getContactDetailsAsJson(pubKey)
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: visible ? 72 : 0
|
height: visible ? 72 : 0
|
||||||
StatusSmartIdenticon {
|
StatusSmartIdenticon {
|
||||||
@ -172,8 +173,8 @@ Item {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: Style.current.padding
|
anchors.leftMargin: Style.current.padding
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
image.source: identicon
|
image.source: currentContact.displayIcon
|
||||||
image.isIdenticon: true
|
image.isIdenticon: currentContact.isDisplayIconIdenticon
|
||||||
}
|
}
|
||||||
Column {
|
Column {
|
||||||
anchors.left: iconImg.right
|
anchors.left: iconImg.right
|
||||||
@ -181,7 +182,7 @@ Item {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: name
|
text: currentContact.alias
|
||||||
font.pixelSize: 15
|
font.pixelSize: 15
|
||||||
color: Theme.palette.directColor1
|
color: Theme.palette.directColor1
|
||||||
height: 22
|
height: 22
|
||||||
@ -189,14 +190,14 @@ Item {
|
|||||||
|
|
||||||
Row {
|
Row {
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: alias + " • "
|
text: currentContact.name + " • "
|
||||||
visible: ensVerified
|
visible: currentContact.ensVerified
|
||||||
color: Theme.palette.baseColor1
|
color: Theme.palette.baseColor1
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
height: 16
|
height: 16
|
||||||
}
|
}
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: address
|
text: currentContact.publicKey
|
||||||
width: 85
|
width: 85
|
||||||
elide: Text.ElideMiddle
|
elide: Text.ElideMiddle
|
||||||
color: Theme.palette.baseColor1
|
color: Theme.palette.baseColor1
|
||||||
@ -212,7 +213,7 @@ Item {
|
|||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
anchors.fill: itemContainer
|
anchors.fill: itemContainer
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.selectedContact = { address, name, alias, isContact, identicon, ensVerified }
|
root.selectedContact = itemContainer.currentContact
|
||||||
resolveEns()
|
resolveEns()
|
||||||
select.selectMenu.close()
|
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")
|
text: qsTrId("optimal")
|
||||||
price: {
|
price: {
|
||||||
if (!eip1599Enabled) {
|
if (!eip1599Enabled) {
|
||||||
const price = gasPrice
|
|
||||||
// Setting the gas price field here because the binding didn't work
|
// Setting the gas price field here because the binding didn't work
|
||||||
inputGasPrice.text = price
|
inputGasPrice.text = root.gasPrice
|
||||||
return price
|
return root.gasPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
return formatDec(suggestedFees.maxFeePerGasM, 6)
|
return formatDec(suggestedFees.maxFeePerGasM, 6)
|
||||||
@ -284,7 +283,7 @@ Item {
|
|||||||
inputPerGasTipLimit.text = formatDec(suggestedFees.maxPriorityFeePerGas, 2);
|
inputPerGasTipLimit.text = formatDec(suggestedFees.maxPriorityFeePerGas, 2);
|
||||||
inputGasPrice.text = formatDec(suggestedFees.maxFeePerGasM, 2);
|
inputGasPrice.text = formatDec(suggestedFees.maxFeePerGasM, 2);
|
||||||
} else {
|
} else {
|
||||||
inputGasPrice.text = price
|
inputGasPrice.text = root.gasPrice
|
||||||
}
|
}
|
||||||
root.updateGasEthValue()
|
root.updateGasEthValue()
|
||||||
root.checkLimits()
|
root.checkLimits()
|
||||||
|
@ -16,7 +16,6 @@ Item {
|
|||||||
property var contactsStore
|
property var contactsStore
|
||||||
|
|
||||||
property var accounts
|
property var accounts
|
||||||
property int currentIndex
|
|
||||||
property int inputWidth: 272
|
property int inputWidth: 272
|
||||||
property int sourceSelectWidth: 136
|
property int sourceSelectWidth: 136
|
||||||
property alias label: txtLabel.text
|
property alias label: txtLabel.text
|
||||||
@ -24,7 +23,6 @@ Item {
|
|||||||
property alias additionalInfo: txtAddlInfo.text
|
property alias additionalInfo: txtAddlInfo.text
|
||||||
property var selectedRecipient
|
property var selectedRecipient
|
||||||
property bool readOnly: false
|
property bool readOnly: false
|
||||||
property bool isContact: false
|
|
||||||
height: inpAddress.height + txtLabel.height
|
height: inpAddress.height + txtLabel.height
|
||||||
//% "Invalid ethereum address"
|
//% "Invalid ethereum address"
|
||||||
readonly property string addressValidationError: qsTrId("invalid-ethereum-address")
|
readonly property string addressValidationError: qsTrId("invalid-ethereum-address")
|
||||||
@ -149,6 +147,9 @@ Item {
|
|||||||
|
|
||||||
AddressInput {
|
AddressInput {
|
||||||
id: inpAddress
|
id: inpAddress
|
||||||
|
|
||||||
|
contactsStore: root.contactsStore
|
||||||
|
|
||||||
width: root.inputWidth
|
width: root.inputWidth
|
||||||
input.label: ""
|
input.label: ""
|
||||||
input.readOnly: root.readOnly
|
input.readOnly: root.readOnly
|
||||||
@ -175,7 +176,6 @@ Item {
|
|||||||
width: root.inputWidth
|
width: root.inputWidth
|
||||||
dropdownWidth: parent.width
|
dropdownWidth: parent.width
|
||||||
readOnly: root.readOnly
|
readOnly: root.readOnly
|
||||||
isContact: root.isContact
|
|
||||||
Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width
|
Layout.preferredWidth: selAddressSource.visible ? root.inputWidth : parent.width
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.alignment: Qt.AlignTop
|
||||||
Layout.fillWidth: true
|
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) {
|
if (!gasLimit) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return formatDec(parseFloat(getGasEthValue(price, gasLimit)), 6)
|
return formatDec(parseFloat(getGasEthValue(gasRectangle.price, gasLimit)), 6)
|
||||||
}
|
}
|
||||||
property double fiatValue: getFiatValue(ethValue, "ETH", defaultCurrency)
|
property double fiatValue: getFiatValue(ethValue, "ETH", defaultCurrency)
|
||||||
signal checked()
|
signal checked()
|
||||||
|
@ -12,6 +12,7 @@ Item {
|
|||||||
width: chatName.width + (ensOrAlias.visible ? ensOrAlias.width + ensOrAlias.anchors.leftMargin : 0)
|
width: chatName.width + (ensOrAlias.visible ? ensOrAlias.width + ensOrAlias.anchors.leftMargin : 0)
|
||||||
property alias label: chatName
|
property alias label: chatName
|
||||||
|
|
||||||
|
property var messageContextMenu
|
||||||
property string displayName
|
property string displayName
|
||||||
property string localName
|
property string localName
|
||||||
property bool amISender
|
property bool amISender
|
||||||
@ -40,11 +41,11 @@ Item {
|
|||||||
root.isHovered = false
|
root.isHovered = false
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!!messageContextMenu) {
|
if (!!root.messageContextMenu) {
|
||||||
// Set parent, X & Y positions for the messageContextMenu
|
// Set parent, X & Y positions for the messageContextMenu
|
||||||
messageContextMenu.parent = root
|
root.messageContextMenu.parent = root
|
||||||
messageContextMenu.setXPosition = function() { return 0}
|
root.messageContextMenu.setXPosition = function() { return 0}
|
||||||
messageContextMenu.setYPosition = function() { return root.height + 4}
|
root.messageContextMenu.setYPosition = function() { return root.height + 4}
|
||||||
}
|
}
|
||||||
root.clickMessage(true);
|
root.clickMessage(true);
|
||||||
}
|
}
|
||||||
|
@ -114,13 +114,11 @@ ModalPopup {
|
|||||||
id: selectRecipient
|
id: selectRecipient
|
||||||
accounts: root.store.accounts
|
accounts: root.store.accounts
|
||||||
contactsStore: root.contactsStore
|
contactsStore: root.contactsStore
|
||||||
currentIndex: index
|
|
||||||
//% "Recipient"
|
//% "Recipient"
|
||||||
label: qsTrId("recipient")
|
label: qsTrId("recipient")
|
||||||
anchors.top: separator.bottom
|
anchors.top: separator.bottom
|
||||||
anchors.topMargin: 10
|
anchors.topMargin: 10
|
||||||
width: stack.width
|
width: stack.width
|
||||||
isContact: root.isContact
|
|
||||||
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,6 @@ StatusModal {
|
|||||||
// accounts: root.store.walletModelInst.accountsView.accounts
|
// accounts: root.store.walletModelInst.accountsView.accounts
|
||||||
contactsStore: root.contactsStore
|
contactsStore: root.contactsStore
|
||||||
selectedRecipient: root.selectedRecipient
|
selectedRecipient: root.selectedRecipient
|
||||||
currentIndex: index
|
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import shared.controls 1.0
|
|||||||
ModalPopup {
|
ModalPopup {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property var ensUsernamesStore
|
||||||
property var contactsStore
|
property var contactsStore
|
||||||
|
|
||||||
readonly property var asset: {"name": "Ethereum", "symbol": "ETH"}
|
readonly property var asset: {"name": "Ethereum", "symbol": "ETH"}
|
||||||
@ -26,42 +27,36 @@ ModalPopup {
|
|||||||
property var onSendTransaction: (function(userAddress, gasLimit, gasPrice, password){ return ""; })
|
property var onSendTransaction: (function(userAddress, gasLimit, gasPrice, password){ return ""; })
|
||||||
property var onSuccess: (function(){})
|
property var onSuccess: (function(){})
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
// Not Refactored Yet
|
|
||||||
// RootStore.walletModelInst.gasView.getGasPricePredictions()
|
|
||||||
}
|
|
||||||
|
|
||||||
height: 540
|
height: 540
|
||||||
|
|
||||||
function sendTransaction() {
|
function sendTransaction() {
|
||||||
// Not Refactored Yet
|
try {
|
||||||
// try {
|
let responseStr = root.ensUsernamesStore.setPubKey(root.ensUsername,
|
||||||
// let responseStr = RootStore.profileModelInst.ens.setPubKey(root.ensUsername,
|
selectFromAccount.selectedAccount.address,
|
||||||
// selectFromAccount.selectedAccount.address,
|
gasSelector.selectedGasLimit,
|
||||||
// gasSelector.selectedGasLimit,
|
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
|
||||||
// gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
|
gasSelector.selectedTipLimit,
|
||||||
// gasSelector.selectedTipLimit,
|
gasSelector.selectedOverallLimit,
|
||||||
// gasSelector.selectedOverallLimit,
|
transactionSigner.enteredPassword)
|
||||||
// transactionSigner.enteredPassword)
|
let response = JSON.parse(responseStr)
|
||||||
// let response = JSON.parse(responseStr)
|
|
||||||
|
|
||||||
// if (!response.success) {
|
if (!response.success) {
|
||||||
// if (Utils.isInvalidPasswordMessage(response.result)){
|
if (Utils.isInvalidPasswordMessage(response.result)){
|
||||||
// //% "Wrong password"
|
//% "Wrong password"
|
||||||
// transactionSigner.validationError = qsTrId("wrong-password")
|
transactionSigner.validationError = qsTrId("wrong-password")
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
// sendingError.text = response.result
|
sendingError.text = response.result
|
||||||
// return sendingError.open()
|
return sendingError.open()
|
||||||
// }
|
}
|
||||||
|
|
||||||
// onSuccess();
|
onSuccess();
|
||||||
// root.close();
|
root.close();
|
||||||
// } catch (e) {
|
} catch (e) {
|
||||||
// console.error('Error sending the transaction', e)
|
console.error('Error sending the transaction', e)
|
||||||
// sendingError.text = "Error sending the transaction: " + e.message;
|
sendingError.text = "Error sending the transaction: " + e.message;
|
||||||
// return sendingError.open()
|
return sendingError.open()
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property MessageDialog sendingError: MessageDialog {
|
property MessageDialog sendingError: MessageDialog {
|
||||||
@ -98,8 +93,7 @@ ModalPopup {
|
|||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
// Not Refactored Yet
|
currency: root.ensUsernamesStore.getCurrentCurrency()
|
||||||
// currency: RootStore.defaultCurrency
|
|
||||||
width: stack.width
|
width: stack.width
|
||||||
//% "Choose account"
|
//% "Choose account"
|
||||||
label: qsTrId("choose-account")
|
label: qsTrId("choose-account")
|
||||||
@ -110,12 +104,10 @@ ModalPopup {
|
|||||||
RecipientSelector {
|
RecipientSelector {
|
||||||
id: selectRecipient
|
id: selectRecipient
|
||||||
visible: false
|
visible: false
|
||||||
// Not Refactored Yet
|
accounts: root.ensUsernamesStore.walletAccounts
|
||||||
// accounts: RootStore.walletModelInst.accountsView.accounts
|
|
||||||
contactsStore: root.contactsStore
|
contactsStore: root.contactsStore
|
||||||
selectedRecipient: { "address": RootStore.utilsModelInst.ensRegisterAddress, "type": RecipientSelector.Type.Address }
|
selectedRecipient: { "address": root.ensUsernamesStore.getEnsRegisteredAddress(), "type": RecipientSelector.Type.Address }
|
||||||
readOnly: true
|
readOnly: true
|
||||||
currentIndex: index
|
|
||||||
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
||||||
}
|
}
|
||||||
GasSelector {
|
GasSelector {
|
||||||
@ -123,11 +115,10 @@ ModalPopup {
|
|||||||
visible: true
|
visible: true
|
||||||
anchors.top: selectFromAccount.bottom
|
anchors.top: selectFromAccount.bottom
|
||||||
anchors.topMargin: Style.current.padding
|
anchors.topMargin: Style.current.padding
|
||||||
// Not Refactored Yet
|
gasPrice: parseFloat(root.ensUsernamesStore.gasPrice)
|
||||||
// gasPrice: parseFloat(RootStore.gasPrice)
|
getGasEthValue: root.ensUsernamesStore.getGasEthValue
|
||||||
// getGasEthValue: RootStore.gasEthValue
|
getFiatValue: root.ensUsernamesStore.getFiatValue
|
||||||
// getFiatValue: RootStore.fiatValue
|
defaultCurrency: root.ensUsernamesStore.getCurrentCurrency()
|
||||||
// defaultCurrency: RootStore.defaultCurrency
|
|
||||||
|
|
||||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||||
let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount);
|
let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount);
|
||||||
@ -161,12 +152,11 @@ ModalPopup {
|
|||||||
}
|
}
|
||||||
toAccount: selectRecipient.selectedRecipient
|
toAccount: selectRecipient.selectedRecipient
|
||||||
asset: root.asset
|
asset: root.asset
|
||||||
// Not Refactored Yet
|
currency: root.ensUsernamesStore.getCurrentCurrency()
|
||||||
// currency: RootStore.defaultCurrency
|
amount: {
|
||||||
// amount: {
|
const fiatValue = root.ensUsernamesStore.getFiatValue(0, root.asset.symbol, currency)
|
||||||
// const fiatValue = RootStore.walletModelInst.balanceView.getFiatValue(0, root.asset.symbol, currency)
|
return { "value": 0, "fiatValue": fiatValue }
|
||||||
// return { "value": 0, "fiatValue": fiatValue }
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TransactionFormGroup {
|
TransactionFormGroup {
|
||||||
@ -178,8 +168,7 @@ ModalPopup {
|
|||||||
TransactionSigner {
|
TransactionSigner {
|
||||||
id: transactionSigner
|
id: transactionSigner
|
||||||
width: stack.width
|
width: stack.width
|
||||||
// Not Refactored Yet
|
signingPhrase: root.ensUsernamesStore.getSigningPhrase()
|
||||||
// signingPhrase: RootStore.walletModelInst.utilsView.signingPhrase
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@ import shared.controls 1.0
|
|||||||
ModalPopup {
|
ModalPopup {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property var store
|
||||||
property var contactsStore
|
property var contactsStore
|
||||||
|
|
||||||
// Not Refactored Yet
|
readonly property var asset: JSON.parse(root.store.getStatusToken())
|
||||||
// readonly property var asset: "" //JSON.parse(RootStore.walletModelInst.tokensView.getStatusToken())
|
|
||||||
property string assetPrice
|
property string assetPrice
|
||||||
property string contractAddress
|
property string contractAddress
|
||||||
property var estimateGasFunction: (function(userAddress, uuid) { return 0; })
|
property var estimateGasFunction: (function(userAddress, uuid) { return 0; })
|
||||||
@ -26,8 +26,7 @@ ModalPopup {
|
|||||||
property var onSuccess: (function(){})
|
property var onSuccess: (function(){})
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
// Not Refactored Yet
|
root.store.fetchGasPrice()
|
||||||
// RootStore.walletModelInst.gasView.getGasPrice()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
height: 540
|
height: 540
|
||||||
@ -114,23 +113,20 @@ ModalPopup {
|
|||||||
RecipientSelector {
|
RecipientSelector {
|
||||||
id: selectRecipient
|
id: selectRecipient
|
||||||
visible: false
|
visible: false
|
||||||
// Not Refactored Yet
|
accounts: root.store.walletAccounts
|
||||||
// accounts: RootStore.walletModelInst.accountsView.accounts
|
|
||||||
contactsStore: root.contactsStore
|
contactsStore: root.contactsStore
|
||||||
selectedRecipient: { "address": contractAddress, "type": RecipientSelector.Type.Address }
|
selectedRecipient: { "address": contractAddress, "type": RecipientSelector.Type.Address }
|
||||||
readOnly: true
|
readOnly: true
|
||||||
currentIndex: index
|
|
||||||
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
|
||||||
}
|
}
|
||||||
GasSelector {
|
GasSelector {
|
||||||
id: gasSelector
|
id: gasSelector
|
||||||
anchors.top: selectFromAccount.bottom
|
anchors.top: selectFromAccount.bottom
|
||||||
anchors.topMargin: Style.current.padding
|
anchors.topMargin: Style.current.padding
|
||||||
// Not Refactored Yet
|
gasPrice: parseFloat(root.store.gasPrice)
|
||||||
// gasPrice: parseFloat(RootStore.gasPrice)
|
getGasEthValue: root.store.getGasEthValue
|
||||||
// getGasEthValue: RootStore.gasEthValue
|
getFiatValue: root.store.getFiatValue
|
||||||
// getFiatValue: RootStore.fiatValue
|
defaultCurrency: root.store.getCurrentCurrency()
|
||||||
defaultCurrency: RootStore.currentCurrency
|
|
||||||
width: stack.width
|
width: stack.width
|
||||||
|
|
||||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||||
@ -166,11 +162,11 @@ ModalPopup {
|
|||||||
}
|
}
|
||||||
toAccount: selectRecipient.selectedRecipient
|
toAccount: selectRecipient.selectedRecipient
|
||||||
asset: root.asset
|
asset: root.asset
|
||||||
currency: RootStore.walletSectionInst.currentCurrency
|
amount: {
|
||||||
// amount: {
|
const fiatValue = root.store.getFiatValue(root.assetPrice || 0, root.asset.symbol, currency)
|
||||||
// const fiatValue = RootStore.walletModelInst.balanceView.getFiatValue(root.assetPrice || 0, root.asset.symbol, currency)
|
return { "value": root.assetPrice, "fiatValue": fiatValue }
|
||||||
// return { "value": root.assetPrice, "fiatValue": fiatValue }
|
}
|
||||||
// }
|
currency: root.store.getCurrentCurrency()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TransactionFormGroup {
|
TransactionFormGroup {
|
||||||
@ -183,8 +179,7 @@ ModalPopup {
|
|||||||
TransactionSigner {
|
TransactionSigner {
|
||||||
id: transactionSigner
|
id: transactionSigner
|
||||||
width: stack.width
|
width: stack.width
|
||||||
// Not Refactored Yet
|
signingPhrase: root.store.getSigningPhrase()
|
||||||
// signingPhrase: RootStore.walletModelInst.utilsView.signingPhrase
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,6 +313,7 @@ Item {
|
|||||||
anchors.leftMargin: chatHorizontalPadding
|
anchors.leftMargin: chatHorizontalPadding
|
||||||
anchors.top: chatImage.top
|
anchors.top: chatImage.top
|
||||||
anchors.left: chatImage.right
|
anchors.left: chatImage.right
|
||||||
|
messageContextMenu: root.messageContextMenu
|
||||||
displayName: senderDisplayName
|
displayName: senderDisplayName
|
||||||
localName: senderLocalName
|
localName: senderLocalName
|
||||||
amISender: amISender
|
amISender: amISender
|
||||||
|
Loading…
x
Reference in New Issue
Block a user