parent
1e972950e6
commit
ba5e259296
|
@ -27,11 +27,14 @@ proc init*(self: Controller) =
|
||||||
|
|
||||||
self.events.on(SIGNAL_SAVED_ADDRESS_UPDATED) do(e:Args):
|
self.events.on(SIGNAL_SAVED_ADDRESS_UPDATED) do(e:Args):
|
||||||
let args = SavedAddressArgs(e)
|
let args = SavedAddressArgs(e)
|
||||||
self.delegate.savedAddressUpdated(args.name, args.address, args.ens, args.errorMsg)
|
self.delegate.savedAddressUpdated(args.name, args.address, args.errorMsg)
|
||||||
|
|
||||||
self.events.on(SIGNAL_SAVED_ADDRESS_DELETED) do(e:Args):
|
self.events.on(SIGNAL_SAVED_ADDRESS_DELETED) do(e:Args):
|
||||||
let args = SavedAddressArgs(e)
|
let args = SavedAddressArgs(e)
|
||||||
self.delegate.savedAddressDeleted(args.address, args.ens, args.errorMsg)
|
self.delegate.savedAddressDeleted(args.address, args.errorMsg)
|
||||||
|
|
||||||
|
proc areTestNetworksEnabled*(self: Controller): bool =
|
||||||
|
return self.savedAddressService.areTestNetworksEnabled()
|
||||||
|
|
||||||
proc getSavedAddresses*(self: Controller): seq[saved_address_service.SavedAddressDto] =
|
proc getSavedAddresses*(self: Controller): seq[saved_address_service.SavedAddressDto] =
|
||||||
return self.savedAddressService.getSavedAddresses()
|
return self.savedAddressService.getSavedAddresses()
|
||||||
|
@ -40,5 +43,5 @@ proc createOrUpdateSavedAddress*(self: Controller, name: string, address: string
|
||||||
chainShortNames: string) =
|
chainShortNames: string) =
|
||||||
self.savedAddressService.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames)
|
self.savedAddressService.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames)
|
||||||
|
|
||||||
proc deleteSavedAddress*(self: Controller, address: string, ens: string) =
|
proc deleteSavedAddress*(self: Controller, address: string) =
|
||||||
self.savedAddressService.deleteSavedAddress(address, ens)
|
self.savedAddressService.deleteSavedAddress(address)
|
||||||
|
|
|
@ -21,13 +21,13 @@ method createOrUpdateSavedAddress*(self: AccessInterface, name: string, address:
|
||||||
chainShortNames: string) {.base.} =
|
chainShortNames: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method deleteSavedAddress*(self: AccessInterface, address: string, ens: string) {.base.} =
|
method deleteSavedAddress*(self: AccessInterface, address: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method savedAddressUpdated*(self: AccessInterface, name: string, address: string, ens: string, errorMsg: string) {.base.} =
|
method savedAddressUpdated*(self: AccessInterface, name: string, address: string, errorMsg: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method savedAddressDeleted*(self: AccessInterface, address: string, ens: string, errorMsg: string) {.base.} =
|
method savedAddressDeleted*(self: AccessInterface, address: string, errorMsg: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method savedAddressNameExists*(self: AccessInterface, name: string): bool {.base.} =
|
method savedAddressNameExists*(self: AccessInterface, name: string): bool {.base.} =
|
||||||
|
|
|
@ -102,25 +102,17 @@ QtObject:
|
||||||
for item in items:
|
for item in items:
|
||||||
self.itemChanged(item.getAddress())
|
self.itemChanged(item.getAddress())
|
||||||
|
|
||||||
proc getItemByAddress*(self: Model, address: string): Item =
|
proc getItemByAddress*(self: Model, address: string, isTest: bool): Item =
|
||||||
if address.len == 0 or address == ZERO_ADDRESS:
|
if address.len == 0 or address == ZERO_ADDRESS:
|
||||||
return
|
return
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
if cmpIgnoreCase(item.getAddress(), address) == 0:
|
if cmpIgnoreCase(item.getAddress(), address) == 0 and
|
||||||
|
(item.getIsTest() == isTest):
|
||||||
return item
|
return item
|
||||||
|
|
||||||
proc getItemByEnsOrAddress*(self: Model, addrOrEns: string): Item =
|
proc nameExists*(self: Model, name: string, isTest: bool): bool =
|
||||||
if addrOrEns.len == 0:
|
|
||||||
return
|
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
if item.getEns().len > 0:
|
if item.getName() == name and
|
||||||
if item.getEns() == addrOrEns:
|
(item.getIsTest() == isTest):
|
||||||
return item
|
|
||||||
if addrOrEns != ZERO_ADDRESS and cmpIgnoreCase(item.getAddress(), addrOrEns) == 0:
|
|
||||||
return item
|
|
||||||
|
|
||||||
proc nameExists*(self: Model, name: string): bool =
|
|
||||||
for item in self.items:
|
|
||||||
if item.getName() == name:
|
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
|
@ -61,28 +61,24 @@ method createOrUpdateSavedAddress*(self: Module, name: string, address: string,
|
||||||
chainShortNames: string) =
|
chainShortNames: string) =
|
||||||
self.controller.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames)
|
self.controller.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames)
|
||||||
|
|
||||||
method deleteSavedAddress*(self: Module, address: string, ens: string) =
|
method deleteSavedAddress*(self: Module, address: string) =
|
||||||
self.controller.deleteSavedAddress(address, ens)
|
self.controller.deleteSavedAddress(address)
|
||||||
|
|
||||||
method savedAddressUpdated*(self: Module, name: string, address: string, ens: string, errorMsg: string) =
|
method savedAddressUpdated*(self: Module, name: string, address: string, errorMsg: string) =
|
||||||
var item = self.view.getModel().getItemByEnsOrAddress(address)
|
let item = self.view.getModel().getItemByAddress(address, self.controller.areTestNetworksEnabled())
|
||||||
if item.isEmpty():
|
|
||||||
item = self.view.getModel().getItemByEnsOrAddress(ens)
|
|
||||||
self.loadSavedAddresses()
|
self.loadSavedAddresses()
|
||||||
self.view.savedAddressAddedOrUpdated(item.isEmpty(), name, address, ens, errorMsg)
|
self.view.savedAddressAddedOrUpdated(item.isEmpty(), name, address, errorMsg)
|
||||||
|
|
||||||
method savedAddressDeleted*(self: Module, address: string, ens: string, errorMsg: string) =
|
method savedAddressDeleted*(self: Module, address: string, errorMsg: string) =
|
||||||
var item = self.view.getModel().getItemByEnsOrAddress(address)
|
let item = self.view.getModel().getItemByAddress(address, self.controller.areTestNetworksEnabled())
|
||||||
if item.isEmpty():
|
|
||||||
item = self.view.getModel().getItemByEnsOrAddress(ens)
|
|
||||||
self.loadSavedAddresses()
|
self.loadSavedAddresses()
|
||||||
self.view.savedAddressDeleted(item.getName(), address, ens, errorMsg)
|
self.view.savedAddressDeleted(item.getName(), address, errorMsg)
|
||||||
|
|
||||||
method savedAddressNameExists*(self: Module, name: string): bool =
|
method savedAddressNameExists*(self: Module, name: string): bool =
|
||||||
return self.view.getModel().nameExists(name)
|
return self.view.getModel().nameExists(name, self.controller.areTestNetworksEnabled())
|
||||||
|
|
||||||
method getSavedAddressAsJson*(self: Module, address: string): string =
|
method getSavedAddressAsJson*(self: Module, address: string): string =
|
||||||
let item = self.view.getModel().getItemByAddress(address)
|
let item = self.view.getModel().getItemByAddress(address, self.controller.areTestNetworksEnabled())
|
||||||
let jsonObj = %* {
|
let jsonObj = %* {
|
||||||
"name": item.getName(),
|
"name": item.getName(),
|
||||||
"address": item.getAddress(),
|
"address": item.getAddress(),
|
||||||
|
|
|
@ -40,16 +40,16 @@ QtObject:
|
||||||
proc setItems*(self: View, items: seq[Item]) =
|
proc setItems*(self: View, items: seq[Item]) =
|
||||||
self.model.setItems(items)
|
self.model.setItems(items)
|
||||||
|
|
||||||
proc savedAddressAddedOrUpdated*(self: View, added: bool, name: string, address: string, ens: string, errorMsg: string) {.signal.}
|
proc savedAddressAddedOrUpdated*(self: View, added: bool, name: string, address: string, errorMsg: string) {.signal.}
|
||||||
|
|
||||||
proc createOrUpdateSavedAddress*(self: View, name: string, address: string, ens: string, colorId: string,
|
proc createOrUpdateSavedAddress*(self: View, name: string, address: string, ens: string, colorId: string,
|
||||||
chainShortNames: string) {.slot.} =
|
chainShortNames: string) {.slot.} =
|
||||||
self.delegate.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames)
|
self.delegate.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames)
|
||||||
|
|
||||||
proc savedAddressDeleted*(self: View, name: string, address: string, ens: string, errorMsg: string) {.signal.}
|
proc savedAddressDeleted*(self: View, name: string, address: string, errorMsg: string) {.signal.}
|
||||||
|
|
||||||
proc deleteSavedAddress*(self: View, address: string, ens: string) {.slot.} =
|
proc deleteSavedAddress*(self: View, address: string) {.slot.} =
|
||||||
self.delegate.deleteSavedAddress(address, ens)
|
self.delegate.deleteSavedAddress(address)
|
||||||
|
|
||||||
proc savedAddressNameExists*(self: View, name: string): bool {.slot.} =
|
proc savedAddressNameExists*(self: View, name: string): bool {.slot.} =
|
||||||
return self.delegate.savedAddressNameExists(name)
|
return self.delegate.savedAddressNameExists(name)
|
||||||
|
|
|
@ -4,7 +4,10 @@ include app/core/tasks/common
|
||||||
import backend/backend
|
import backend/backend
|
||||||
|
|
||||||
type
|
type
|
||||||
SavedAddressTaskArg = ref object of QObjectTaskArg
|
SavedAddressesTaskArg = ref object of QObjectTaskArg
|
||||||
|
chainId*: int
|
||||||
|
|
||||||
|
SavedAddressTaskArg = ref object of SavedAddressesTaskArg
|
||||||
name: string
|
name: string
|
||||||
address: string
|
address: string
|
||||||
colorId: string
|
colorId: string
|
||||||
|
@ -12,6 +15,54 @@ type
|
||||||
ens: string
|
ens: string
|
||||||
isTestAddress: bool
|
isTestAddress: bool
|
||||||
|
|
||||||
|
UpdateCriteria {.pure.} = enum
|
||||||
|
AlwaysUpdate
|
||||||
|
OnlyIfDifferent
|
||||||
|
|
||||||
|
proc isValidChainId(chainId: int): bool =
|
||||||
|
return chainId == Mainnet or chainId == Goerli or chainId == Sepolia
|
||||||
|
|
||||||
|
proc checkForEnsNameAndUpdate(chainId: int, savedAddress: var SavedAddressDto, updateCriteria: UpdateCriteria): RpcResponse[JsonNode] {.raises: [RpcException].} =
|
||||||
|
if savedAddress.isTest and chainId == Mainnet or
|
||||||
|
not savedAddress.isTest and chainId != Mainnet:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
let ensResponse = backend.getName(chainId, savedAddress.address)
|
||||||
|
if updateCriteria == UpdateCriteria.OnlyIfDifferent and savedAddress.ens == ensResponse.result.getStr():
|
||||||
|
return
|
||||||
|
savedAddress.ens = ensResponse.result.getStr()
|
||||||
|
except:
|
||||||
|
savedAddress.ens = ""
|
||||||
|
return backend.upsertSavedAddress(savedAddress)
|
||||||
|
except Exception as e:
|
||||||
|
raise newException(RpcException, e.msg)
|
||||||
|
|
||||||
|
const fetchSavedAddressesAndResolveEnsNamesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
|
let arg = decode[SavedAddressesTaskArg](argEncoded)
|
||||||
|
var response = %* {
|
||||||
|
"response": [],
|
||||||
|
"error": "",
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
if not isValidChainId(arg.chainId):
|
||||||
|
raise newException(CatchableError, "invalid chainId: " & $arg.chainId)
|
||||||
|
let rpcResponse = backend.getSavedAddresses()
|
||||||
|
if not rpcResponse.error.isNil:
|
||||||
|
raise newException(CatchableError, rpcResponse.error.message)
|
||||||
|
for saJson in rpcResponse.result.getElems():
|
||||||
|
if saJson.kind != JObject or not saJson.hasKey("address"):
|
||||||
|
continue
|
||||||
|
var savedAddress = saJson.toSavedAddressDto()
|
||||||
|
try:
|
||||||
|
discard checkForEnsNameAndUpdate(arg.chainId, savedAddress, UpdateCriteria.OnlyIfDifferent)
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
response["response"].add(savedAddress.toJsonNode())
|
||||||
|
except Exception as e:
|
||||||
|
response["error"] = %* e.msg
|
||||||
|
arg.finish(response)
|
||||||
|
|
||||||
const upsertSavedAddressTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
const upsertSavedAddressTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
let arg = decode[SavedAddressTaskArg](argEncoded)
|
let arg = decode[SavedAddressTaskArg](argEncoded)
|
||||||
var response = %* {
|
var response = %* {
|
||||||
|
@ -22,14 +73,16 @@ const upsertSavedAddressTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.
|
||||||
"error": "",
|
"error": "",
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
let rpcResponse = backend.upsertSavedAddress(SavedAddressDto(
|
if not isValidChainId(arg.chainId):
|
||||||
|
raise newException(CatchableError, "invalid chainId: " & $arg.chainId)
|
||||||
|
var savedAddress = SavedAddressDto(
|
||||||
name: arg.name,
|
name: arg.name,
|
||||||
address: arg.address,
|
address: arg.address,
|
||||||
colorId: arg.colorId,
|
colorId: arg.colorId,
|
||||||
chainShortNames: arg.chainShortNames,
|
chainShortNames: arg.chainShortNames,
|
||||||
ens: arg.ens,
|
ens: arg.ens,
|
||||||
isTest: arg.isTestAddress)
|
isTest: arg.isTestAddress)
|
||||||
)
|
let rpcResponse = checkForEnsNameAndUpdate(arg.chainId, savedAddress, UpdateCriteria.AlwaysUpdate)
|
||||||
if not rpcResponse.error.isNil:
|
if not rpcResponse.error.isNil:
|
||||||
raise newException(CatchableError, rpcResponse.error.message)
|
raise newException(CatchableError, rpcResponse.error.message)
|
||||||
response["response"] = %* "ok"
|
response["response"] = %* "ok"
|
||||||
|
@ -42,11 +95,10 @@ const deleteSavedAddressTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.
|
||||||
var response = %* {
|
var response = %* {
|
||||||
"response": "",
|
"response": "",
|
||||||
"address": %* arg.address,
|
"address": %* arg.address,
|
||||||
"ens": %* arg.ens,
|
|
||||||
"error": "",
|
"error": "",
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
let rpcResponse = backend.deleteSavedAddress(arg.address, arg.ens, arg.isTestAddress)
|
let rpcResponse = backend.deleteSavedAddress(arg.address, arg.isTestAddress)
|
||||||
if not rpcResponse.error.isNil:
|
if not rpcResponse.error.isNil:
|
||||||
raise newException(CatchableError, rpcResponse.error.message)
|
raise newException(CatchableError, rpcResponse.error.message)
|
||||||
response["response"] = %* "ok"
|
response["response"] = %* "ok"
|
||||||
|
|
|
@ -22,3 +22,14 @@ proc toSavedAddressDto*(jsonObj: JsonNode): SavedAddressDto =
|
||||||
discard jsonObj.getProp("chainShortNames", result.chainShortNames)
|
discard jsonObj.getProp("chainShortNames", result.chainShortNames)
|
||||||
discard jsonObj.getProp("isTest", result.isTest)
|
discard jsonObj.getProp("isTest", result.isTest)
|
||||||
discard jsonObj.getProp("createdAt", result.createdAt)
|
discard jsonObj.getProp("createdAt", result.createdAt)
|
||||||
|
|
||||||
|
proc toJsonNode*(self: SavedAddressDto): JsonNode =
|
||||||
|
result = %* {
|
||||||
|
"name": self.name,
|
||||||
|
"address": self.address,
|
||||||
|
"ens": self.ens,
|
||||||
|
"colorId": self.colorId,
|
||||||
|
"chainShortNames": self.chainShortNames,
|
||||||
|
"isTest": self.isTest,
|
||||||
|
"createdAt": self.createdAt,
|
||||||
|
}
|
|
@ -26,7 +26,6 @@ type
|
||||||
SavedAddressArgs* = ref object of Args
|
SavedAddressArgs* = ref object of Args
|
||||||
name*: string
|
name*: string
|
||||||
address*: string
|
address*: string
|
||||||
ens*: string
|
|
||||||
errorMsg*: string
|
errorMsg*: string
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
|
@ -49,57 +48,74 @@ QtObject:
|
||||||
result.networkService = networkService
|
result.networkService = networkService
|
||||||
result.settingsService = settingsService
|
result.settingsService = settingsService
|
||||||
|
|
||||||
proc fetchAddresses(self: Service) =
|
## Forward declaration
|
||||||
try:
|
proc fetchSavedAddressesAndResolveEnsNames(self: Service)
|
||||||
let response = backend.getSavedAddresses()
|
proc updateAddresses(self: Service, signal: string, arg: Args)
|
||||||
self.savedAddresses = map(
|
|
||||||
response.result.getElems(),
|
|
||||||
proc(x: JsonNode): SavedAddressDto = toSavedAddressDto(x)
|
|
||||||
)
|
|
||||||
let chainId = self.networkService.getAppNetwork().chainId
|
|
||||||
for savedAddress in self.savedAddresses:
|
|
||||||
if savedAddress.ens != "":
|
|
||||||
try:
|
|
||||||
let nameResponse = backend.getName(chainId, savedAddress.address)
|
|
||||||
savedAddress.ens = nameResponse.result.getStr
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
error "error: ", procName="fetchAddress", errName = e.name, errDesription = e.msg
|
|
||||||
|
|
||||||
proc updateAddresses(self: Service) =
|
|
||||||
self.fetchAddresses()
|
|
||||||
self.events.emit(SIGNAL_SAVED_ADDRESSES_UPDATED, Args())
|
|
||||||
|
|
||||||
proc init*(self: Service) =
|
proc init*(self: Service) =
|
||||||
# Subscribe to sync events and check for changes
|
|
||||||
self.events.on(SignalType.Message.event) do(e:Args):
|
self.events.on(SignalType.Message.event) do(e:Args):
|
||||||
var data = MessageSignal(e)
|
var data = MessageSignal(e)
|
||||||
if(len(data.savedAddresses) > 0):
|
if(len(data.savedAddresses) > 0):
|
||||||
self.updateAddresses()
|
self.updateAddresses(SIGNAL_SAVED_ADDRESSES_UPDATED, Args())
|
||||||
|
|
||||||
self.fetchAddresses()
|
self.fetchSavedAddressesAndResolveEnsNames()
|
||||||
|
|
||||||
|
proc areTestNetworksEnabled*(self: Service): bool =
|
||||||
|
return self.settingsService.areTestNetworksEnabled()
|
||||||
|
|
||||||
|
proc getAddresses(self: Service): seq[SavedAddressDto] =
|
||||||
|
try:
|
||||||
|
let response = backend.getSavedAddresses()
|
||||||
|
return map(response.result.getElems(), proc(x: JsonNode): SavedAddressDto = toSavedAddressDto(x))
|
||||||
|
except Exception as e:
|
||||||
|
error "error: ", procName="fetchAddress", errName = e.name, errDesription = e.msg
|
||||||
|
|
||||||
proc getSavedAddresses*(self: Service): seq[SavedAddressDto] =
|
proc getSavedAddresses*(self: Service): seq[SavedAddressDto] =
|
||||||
return self.savedAddresses
|
return self.savedAddresses
|
||||||
|
|
||||||
|
proc updateAddresses(self: Service, signal: string, arg: Args) =
|
||||||
|
self.savedAddresses = self.getAddresses()
|
||||||
|
self.events.emit(signal, arg)
|
||||||
|
|
||||||
|
proc fetchSavedAddressesAndResolveEnsNames(self: Service) =
|
||||||
|
let arg = SavedAddressTaskArg(
|
||||||
|
chainId: self.networkService.getAppNetwork().chainId,
|
||||||
|
tptr: cast[ByteAddress](fetchSavedAddressesAndResolveEnsNamesTask),
|
||||||
|
vptr: cast[ByteAddress](self.vptr),
|
||||||
|
slot: "onSavedAddressesFetched",
|
||||||
|
)
|
||||||
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
|
proc onSavedAddressesFetched(self: Service, rpcResponse: string) {.slot.} =
|
||||||
|
try:
|
||||||
|
let rpcResponseObj = rpcResponse.parseJson
|
||||||
|
if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "":
|
||||||
|
raise newException(CatchableError, rpcResponseObj{"error"}.getStr)
|
||||||
|
if rpcResponseObj{"response"}.kind != JArray:
|
||||||
|
raise newException(CatchableError, "invalid response")
|
||||||
|
|
||||||
|
self.savedAddresses = map(rpcResponseObj{"response"}.getElems(), proc(x: JsonNode): SavedAddressDto = toSavedAddressDto(x))
|
||||||
|
except Exception as e:
|
||||||
|
error "onSavedAddressesFetched", msg = e.msg
|
||||||
|
self.events.emit(SIGNAL_SAVED_ADDRESSES_UPDATED, Args())
|
||||||
|
|
||||||
proc createOrUpdateSavedAddress*(self: Service, name: string, address: string, ens: string, colorId: string,
|
proc createOrUpdateSavedAddress*(self: Service, name: string, address: string, ens: string, colorId: string,
|
||||||
chainShortNames: string) =
|
chainShortNames: string) =
|
||||||
let arg = SavedAddressTaskArg(
|
let arg = SavedAddressTaskArg(
|
||||||
|
chainId: self.networkService.getAppNetwork().chainId,
|
||||||
name: name,
|
name: name,
|
||||||
address: address,
|
address: address,
|
||||||
ens: ens,
|
ens: ens,
|
||||||
colorId: colorId,
|
colorId: colorId,
|
||||||
chainShortNames: chainShortNames,
|
chainShortNames: chainShortNames,
|
||||||
isTestAddress: self.settingsService.areTestNetworksEnabled(),
|
isTestAddress: self.areTestNetworksEnabled(),
|
||||||
tptr: cast[ByteAddress](upsertSavedAddressTask),
|
tptr: cast[ByteAddress](upsertSavedAddressTask),
|
||||||
vptr: cast[ByteAddress](self.vptr),
|
vptr: cast[ByteAddress](self.vptr),
|
||||||
slot: "onSavedAddressCreatedOrUpdated",
|
slot: "onSavedAddressCreatedOrUpdated",
|
||||||
)
|
)
|
||||||
self.threadpool.start(arg)
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
proc onSavedAddressCreatedOrUpdated*(self: Service, rpcResponse: string) {.slot.} =
|
proc onSavedAddressCreatedOrUpdated(self: Service, rpcResponse: string) {.slot.} =
|
||||||
var arg = SavedAddressArgs()
|
var arg = SavedAddressArgs()
|
||||||
try:
|
try:
|
||||||
let rpcResponseObj = rpcResponse.parseJson
|
let rpcResponseObj = rpcResponse.parseJson
|
||||||
|
@ -110,25 +126,22 @@ QtObject:
|
||||||
|
|
||||||
arg.name = rpcResponseObj{"name"}.getStr
|
arg.name = rpcResponseObj{"name"}.getStr
|
||||||
arg.address = rpcResponseObj{"address"}.getStr
|
arg.address = rpcResponseObj{"address"}.getStr
|
||||||
arg.ens = rpcResponseObj{"ens"}.getStr
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "onSavedAddressCreatedOrUpdated", msg = e.msg
|
error "onSavedAddressCreatedOrUpdated", msg = e.msg
|
||||||
arg.errorMsg = e.msg
|
arg.errorMsg = e.msg
|
||||||
self.fetchAddresses()
|
self.updateAddresses(SIGNAL_SAVED_ADDRESS_UPDATED, arg)
|
||||||
self.events.emit(SIGNAL_SAVED_ADDRESS_UPDATED, arg)
|
|
||||||
|
|
||||||
proc deleteSavedAddress*(self: Service, address: string, ens: string) =
|
proc deleteSavedAddress*(self: Service, address: string) =
|
||||||
let arg = SavedAddressTaskArg(
|
let arg = SavedAddressTaskArg(
|
||||||
address: address,
|
address: address,
|
||||||
ens: ens,
|
isTestAddress: self.areTestNetworksEnabled(),
|
||||||
isTestAddress: self.settingsService.areTestNetworksEnabled(),
|
|
||||||
tptr: cast[ByteAddress](deleteSavedAddressTask),
|
tptr: cast[ByteAddress](deleteSavedAddressTask),
|
||||||
vptr: cast[ByteAddress](self.vptr),
|
vptr: cast[ByteAddress](self.vptr),
|
||||||
slot: "onDeleteSavedAddress",
|
slot: "onDeleteSavedAddress",
|
||||||
)
|
)
|
||||||
self.threadpool.start(arg)
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
proc onDeleteSavedAddress*(self: Service, rpcResponse: string) {.slot.} =
|
proc onDeleteSavedAddress(self: Service, rpcResponse: string) {.slot.} =
|
||||||
var arg = SavedAddressArgs()
|
var arg = SavedAddressArgs()
|
||||||
try:
|
try:
|
||||||
let rpcResponseObj = rpcResponse.parseJson
|
let rpcResponseObj = rpcResponse.parseJson
|
||||||
|
@ -138,9 +151,7 @@ QtObject:
|
||||||
raise newException(CatchableError, "invalid response")
|
raise newException(CatchableError, "invalid response")
|
||||||
|
|
||||||
arg.address = rpcResponseObj{"address"}.getStr
|
arg.address = rpcResponseObj{"address"}.getStr
|
||||||
arg.ens = rpcResponseObj{"ens"}.getStr
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "onDeleteSavedAddress", msg = e.msg
|
error "onDeleteSavedAddress", msg = e.msg
|
||||||
arg.errorMsg = e.msg
|
arg.errorMsg = e.msg
|
||||||
self.fetchAddresses()
|
self.updateAddresses(SIGNAL_SAVED_ADDRESS_DELETED, arg)
|
||||||
self.events.emit(SIGNAL_SAVED_ADDRESS_DELETED, arg)
|
|
|
@ -91,10 +91,9 @@ rpc(upsertSavedAddress, "wakuext"):
|
||||||
|
|
||||||
rpc(deleteSavedAddress, "wakuext"):
|
rpc(deleteSavedAddress, "wakuext"):
|
||||||
address: string
|
address: string
|
||||||
ens: string
|
|
||||||
isTest: bool
|
isTest: bool
|
||||||
|
|
||||||
rpc(getSavedAddresses, "wallet"):
|
rpc(getSavedAddresses, "wakuext"):
|
||||||
discard
|
discard
|
||||||
|
|
||||||
rpc(checkConnected, "wallet"):
|
rpc(checkConnected, "wallet"):
|
||||||
|
|
|
@ -108,3 +108,7 @@ class BaseElement:
|
||||||
|
|
||||||
def wait_until_hidden(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC):
|
def wait_until_hidden(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC):
|
||||||
assert squish.waitFor(lambda: not self.is_visible, timeout_msec), f'Object {self} is not hidden'
|
assert squish.waitFor(lambda: not self.is_visible, timeout_msec), f'Object {self} is not hidden'
|
||||||
|
|
||||||
|
def wait_until_enabled(self, timeout_msec: int = configs.squish.UI_LOAD_TIMEOUT_MSEC):
|
||||||
|
assert squish.waitFor(lambda: self.is_enabled, timeout_msec), f'Object {self} is not enabled'
|
||||||
|
return self
|
||||||
|
|
|
@ -62,7 +62,7 @@ class AddSavedAddressPopup(SavedAddressPopup):
|
||||||
self.verify_ethereum_mainnet_network_tag_present()
|
self.verify_ethereum_mainnet_network_tag_present()
|
||||||
self.verify_otimism_mainnet_network_tag_present()
|
self.verify_otimism_mainnet_network_tag_present()
|
||||||
self.verify_arbitrum_mainnet_network_tag_present(),
|
self.verify_arbitrum_mainnet_network_tag_present(),
|
||||||
self._save_add_address_button.click()
|
self._save_add_address_button.wait_until_enabled().click()
|
||||||
self.wait_until_hidden()
|
self.wait_until_hidden()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ StatusListItem {
|
||||||
radius: 8
|
radius: 8
|
||||||
icon.name: "more"
|
icon.name: "more"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
menu.openMenu(this, x - menu.width - statusListItemComponentsSlot.spacing, y + height + Style.current.halfPadding,
|
menu.openMenu(this, x + width - menu.width - statusListItemComponentsSlot.spacing, y + height + Style.current.halfPadding,
|
||||||
{
|
{
|
||||||
name: root.name,
|
name: root.name,
|
||||||
address: root.address,
|
address: root.address,
|
||||||
|
|
|
@ -98,6 +98,13 @@ StatusDialog {
|
||||||
readonly property var chainPrefixRegexPattern: /[^:]+\:?|:/g
|
readonly property var chainPrefixRegexPattern: /[^:]+\:?|:/g
|
||||||
readonly property bool addressInputIsENS: !!d.ens
|
readonly property bool addressInputIsENS: !!d.ens
|
||||||
|
|
||||||
|
property bool addressAlreadyAdded: false
|
||||||
|
function checkIfAddressIsAlreadyAddded(address) {
|
||||||
|
let details = RootStore.getSavedAddress(address)
|
||||||
|
d.addressAlreadyAdded = !!details.address
|
||||||
|
return !d.addressAlreadyAdded
|
||||||
|
}
|
||||||
|
|
||||||
/// Ensures that the \c root.address and \c root.chainShortNames are not reset when the initial text is set
|
/// Ensures that the \c root.address and \c root.chainShortNames are not reset when the initial text is set
|
||||||
property bool initialized: false
|
property bool initialized: false
|
||||||
|
|
||||||
|
@ -121,6 +128,13 @@ StatusDialog {
|
||||||
RootStore.createOrUpdateSavedAddress(d.name, d.address, d.ens, d.colorId, d.chainShortNames)
|
RootStore.createOrUpdateSavedAddress(d.name, d.address, d.ens, d.colorId, d.chainShortNames)
|
||||||
root.close()
|
root.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property bool resolvingEnsName: false
|
||||||
|
readonly property string uuid: Utils.uuid()
|
||||||
|
readonly property var validateEnsAsync: Backpressure.debounce(root, 500, function (value) {
|
||||||
|
var name = value.startsWith("@") ? value.substring(1) : value
|
||||||
|
mainModule.resolveENS(name, d.uuid)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
@ -182,13 +196,61 @@ StatusDialog {
|
||||||
validators: [
|
validators: [
|
||||||
StatusMinLengthValidator {
|
StatusMinLengthValidator {
|
||||||
minLength: 1
|
minLength: 1
|
||||||
errorMessage: qsTr("Address must not be blank")
|
errorMessage: qsTr("Please enter an ethereum address")
|
||||||
},
|
},
|
||||||
StatusValidator {
|
StatusValidator {
|
||||||
errorMessage: addressInput.plainText ? qsTr("Please enter a valid address or ENS name.") : ""
|
errorMessage: d.addressAlreadyAdded? qsTr("This address is already saved") : qsTr("Ethereum address invalid")
|
||||||
validate: function (t) {
|
validate: function (value) {
|
||||||
return t !== Constants.zeroAddress && (Utils.isValidAddressWithChainPrefix(t) || Utils.isValidEns(t))
|
if (value !== Constants.zeroAddress) {
|
||||||
? true : { actual: t }
|
if (Utils.isValidEns(value)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (Utils.isValidAddressWithChainPrefix(value)) {
|
||||||
|
if (d.editMode) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const prefixAndAddress = Utils.splitToChainPrefixAndAddress(value)
|
||||||
|
return d.checkIfAddressIsAlreadyAddded(prefixAndAddress.address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
asyncValidators: [
|
||||||
|
StatusAsyncValidator {
|
||||||
|
id: resolvingEnsName
|
||||||
|
name: "resolving-ens-name"
|
||||||
|
errorMessage: d.addressAlreadyAdded? qsTr("This address is already saved") : qsTr("Ethereum address invalid")
|
||||||
|
asyncOperation: (value) => {
|
||||||
|
if (!Utils.isValidEns(value)) {
|
||||||
|
resolvingEnsName.asyncComplete("not-ens")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.resolvingEnsName = true
|
||||||
|
d.validateEnsAsync(value)
|
||||||
|
}
|
||||||
|
validate: (value) => {
|
||||||
|
if (d.editMode || value === "not-ens") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (!!value) {
|
||||||
|
return d.checkIfAddressIsAlreadyAddded(value)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: mainModule
|
||||||
|
function onResolvedENS(resolvedPubKey: string, resolvedAddress: string, uuid: string) {
|
||||||
|
if (uuid !== d.uuid) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.resolvingEnsName = false
|
||||||
|
d.address = resolvedAddress
|
||||||
|
resolvingEnsName.asyncComplete(resolvedAddress)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -207,6 +269,7 @@ StatusDialog {
|
||||||
if (skipTextUpdate || !d.initialized)
|
if (skipTextUpdate || !d.initialized)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
d.addressAlreadyAdded = false
|
||||||
plainText = input.edit.getText(0, text.length)
|
plainText = input.edit.getText(0, text.length)
|
||||||
|
|
||||||
if (input.edit.previousText != plainText) {
|
if (input.edit.previousText != plainText) {
|
||||||
|
@ -228,11 +291,13 @@ StatusDialog {
|
||||||
|
|
||||||
// Update root values
|
// Update root values
|
||||||
if (Utils.isLikelyEnsName(plainText)) {
|
if (Utils.isLikelyEnsName(plainText)) {
|
||||||
|
d.resolvingEnsName = true
|
||||||
d.ens = plainText
|
d.ens = plainText
|
||||||
d.address = Constants.zeroAddress
|
d.address = Constants.zeroAddress
|
||||||
d.chainShortNames = ""
|
d.chainShortNames = ""
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
d.resolvingEnsName = false
|
||||||
d.ens = ""
|
d.ens = ""
|
||||||
d.address = prefixAndAddress.address
|
d.address = prefixAndAddress.address
|
||||||
d.chainShortNames = prefixAndAddress.prefix
|
d.chainShortNames = prefixAndAddress.prefix
|
||||||
|
@ -409,7 +474,8 @@ StatusDialog {
|
||||||
rightButtons: ObjectModel {
|
rightButtons: ObjectModel {
|
||||||
StatusButton {
|
StatusButton {
|
||||||
text: d.editMode? qsTr("Save") : qsTr("Add address")
|
text: d.editMode? qsTr("Save") : qsTr("Add address")
|
||||||
enabled: d.valid && d.dirty
|
enabled: d.valid && d.dirty && !d.resolvingEnsName
|
||||||
|
loading: d.resolvingEnsName
|
||||||
onClicked: {
|
onClicked: {
|
||||||
d.submit()
|
d.submit()
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ StatusDialog {
|
||||||
property string colorId
|
property string colorId
|
||||||
property string chainShortNames
|
property string chainShortNames
|
||||||
|
|
||||||
signal removeSavedAddress(string address, string ens)
|
signal removeSavedAddress(string address)
|
||||||
|
|
||||||
width: 521
|
width: 521
|
||||||
focus: visible
|
focus: visible
|
||||||
|
@ -36,7 +36,7 @@ StatusDialog {
|
||||||
readonly property real lineHeight: 1.2
|
readonly property real lineHeight: 1.2
|
||||||
|
|
||||||
function confirm() {
|
function confirm() {
|
||||||
root.removeSavedAddress(root.address, root.ens)
|
root.removeSavedAddress(root.address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ QtObject {
|
||||||
readonly property bool showAllAccounts: !root.showSavedAddresses && !root.selectedAddress
|
readonly property bool showAllAccounts: !root.showSavedAddresses && !root.selectedAddress
|
||||||
|
|
||||||
property var lastCreatedSavedAddress
|
property var lastCreatedSavedAddress
|
||||||
property var lastDeletedSavedAddress
|
|
||||||
property bool addingSavedAddress: false
|
property bool addingSavedAddress: false
|
||||||
property bool deletingSavedAddress: false
|
property bool deletingSavedAddress: false
|
||||||
|
|
||||||
|
@ -354,9 +353,9 @@ QtObject {
|
||||||
walletSectionSavedAddresses.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames)
|
walletSectionSavedAddresses.createOrUpdateSavedAddress(name, address, ens, colorId, chainShortNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteSavedAddress(address, ens) {
|
function deleteSavedAddress(address) {
|
||||||
root.deletingSavedAddress = true
|
root.deletingSavedAddress = true
|
||||||
walletSectionSavedAddresses.deleteSavedAddress(address, ens)
|
walletSectionSavedAddresses.deleteSavedAddress(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
function savedAddressNameExists(name) {
|
function savedAddressNameExists(name) {
|
||||||
|
|
|
@ -99,8 +99,7 @@ ColumnLayout {
|
||||||
State {
|
State {
|
||||||
name: "highlighted"
|
name: "highlighted"
|
||||||
when: RootStore.lastCreatedSavedAddress ? (!RootStore.lastCreatedSavedAddress.error &&
|
when: RootStore.lastCreatedSavedAddress ? (!RootStore.lastCreatedSavedAddress.error &&
|
||||||
RootStore.lastCreatedSavedAddress.address.toLowerCase() === address.toLowerCase() &&
|
RootStore.lastCreatedSavedAddress.address.toLowerCase() === address.toLowerCase()) : false
|
||||||
RootStore.lastCreatedSavedAddress.ens === ens) : false
|
|
||||||
PropertyChanges { target: savedAddressDelegate; color: Theme.palette.baseColor2 }
|
PropertyChanges { target: savedAddressDelegate; color: Theme.palette.baseColor2 }
|
||||||
StateChangeScript {
|
StateChangeScript {
|
||||||
script: Qt.callLater(d.reset)
|
script: Qt.callLater(d.reset)
|
||||||
|
|
|
@ -1715,9 +1715,9 @@ Item {
|
||||||
Connections {
|
Connections {
|
||||||
target: WalletStore.RootStore.walletSectionSavedAddressesInst
|
target: WalletStore.RootStore.walletSectionSavedAddressesInst
|
||||||
|
|
||||||
function onSavedAddressAddedOrUpdated(added: bool, name: string, address: string, ens: string, errorMsg: string) {
|
function onSavedAddressAddedOrUpdated(added: bool, name: string, address: string, errorMsg: string) {
|
||||||
WalletStore.RootStore.addingSavedAddress = false
|
WalletStore.RootStore.addingSavedAddress = false
|
||||||
WalletStore.RootStore.lastCreatedSavedAddress = { address: address, ens: ens, error: errorMsg }
|
WalletStore.RootStore.lastCreatedSavedAddress = { address: address, error: errorMsg }
|
||||||
|
|
||||||
if (!!errorMsg) {
|
if (!!errorMsg) {
|
||||||
let mode = qsTr("adding")
|
let mode = qsTr("adding")
|
||||||
|
@ -1783,7 +1783,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemoveSavedAddress: {
|
onRemoveSavedAddress: {
|
||||||
WalletStore.RootStore.deleteSavedAddress(address, ens)
|
WalletStore.RootStore.deleteSavedAddress(address)
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1791,9 +1791,8 @@ Item {
|
||||||
Connections {
|
Connections {
|
||||||
target: WalletStore.RootStore.walletSectionSavedAddressesInst
|
target: WalletStore.RootStore.walletSectionSavedAddressesInst
|
||||||
|
|
||||||
function onSavedAddressDeleted(name: string, address: string, ens: string, errorMsg: string) {
|
function onSavedAddressDeleted(name: string, address: string, errorMsg: string) {
|
||||||
WalletStore.RootStore.deletingSavedAddress = false
|
WalletStore.RootStore.deletingSavedAddress = false
|
||||||
WalletStore.RootStore.lastDeletedSavedAddress = { address: address, ens: ens, error: errorMsg }
|
|
||||||
|
|
||||||
if (!!errorMsg) {
|
if (!!errorMsg) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue