Make the getENSName calls async (#16099) (#16110)

* wip: make the getENSName calls async

* fix: login to the app takes forever

Resolving ens name sometimes, most likely due to network congestion can be really slow,
that results in slow app loading, especially if user has more accounts, cause the app checks
ens name existence for each account.

This PR does that check in an async way.

Fixes #16086

* chore: async check for ens name existence when adding new accounts

---------

Co-authored-by: Sale Djenic <aleksandardjenic@status.im>
This commit is contained in:
Jonathan Rainville 2024-08-14 16:14:39 -04:00 committed by GitHub
parent 3caeba8783
commit 82d1be9ad8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 68 additions and 13 deletions

View File

@ -257,3 +257,28 @@ proc getTokenBalanceHistoryDataTask*(argEncoded: string) {.gcsafe, nimcall.} =
"error": e.msg,
}
arg.finish(output)
#################################################
# Async get ENS names for account
#################################################
type
FetchENSNamesForAddressesTaskArg = ref object of QObjectTaskArg
chainId: int
addresses: seq[string]
proc fetchENSNamesForAddressesTask*(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[FetchENSNamesForAddressesTaskArg](argEncoded)
var response = %* {
"result": [],
"error": "",
}
try:
var result = newJobject()
for address in arg.addresses:
let name = getEnsName(address, arg.chainId)
result[address] = %name
response["result"] = result
except Exception as e:
response["error"] = %* e.msg
arg.finish(response)

View File

@ -56,6 +56,8 @@ QtObject:
proc handleKeypair(self: Service, keypair: KeypairDto)
proc updateAccountsPositions(self: Service)
proc importPartiallyOperableAccounts(self: Service, keyUid: string, password: string)
proc parseCurrencyValueByTokensKey*(self: Service, tokensKey: string, amountInt: UInt256): float64
proc fetchENSNamesForAddressesAsync(self: Service, addresses: seq[string], chainId: int)
# All slots defined in included files have to be forward declared
proc onAllTokensBuilt*(self: Service, response: string) {.slot.}
proc onDerivedAddressesFetched*(self: Service, jsonString: string) {.slot.}
@ -66,7 +68,7 @@ QtObject:
proc onFetchChainIdForUrl*(self: Service, jsonString: string) {.slot.}
proc onNonProfileKeycardKeypairMigratedToApp*(self: Service, response: string) {.slot.}
proc tokenBalanceHistoryDataResolved*(self: Service, response: string) {.slot.}
proc parseCurrencyValueByTokensKey*(self: Service, tokensKey: string, amountInt: UInt256): float64
proc onENSNamesFetched*(self: Service, response: string) {.slot.}
proc delete*(self: Service) =
self.closingApp = true

View File

@ -136,17 +136,20 @@ proc startWallet(self: Service) =
proc init*(self: Service) =
try:
var addressesToGetENSName: seq[string] = @[]
let chainId = self.networkService.getAppNetwork().chainId
let woAccounts = getWatchOnlyAccountsFromDb()
for acc in woAccounts:
acc.ens = getEnsName(acc.address, chainId)
addressesToGetENSName.add(acc.address)
self.storeWatchOnlyAccount(acc)
let keypairs = getKeypairsFromDb()
for kp in keypairs:
for acc in kp.accounts:
acc.ens = getEnsName(acc.address, chainId)
addressesToGetENSName.add(acc.address)
self.storeKeypair(kp)
self.fetchENSNamesForAddressesAsync(addressesToGetENSName, chainId)
let addresses = self.getWalletAddresses()
self.checkRecentHistory(addresses)
self.startWallet()
@ -195,8 +198,8 @@ proc addNewKeypairsAccountsToLocalStoreAndNotify(self: Service, notify: bool = t
break
if found:
continue
woAccDb.ens = getEnsName(woAccDb.address, chainId)
self.storeWatchOnlyAccount(woAccDb)
self.fetchENSNamesForAddressesAsync(@[woAccDb.address], chainId)
self.buildAllTokens(@[woAccDb.address], store = true)
if notify:
self.events.emit(SIGNAL_WALLET_ACCOUNT_SAVED, AccountArgs(account: woAccDb))
@ -207,9 +210,9 @@ proc addNewKeypairsAccountsToLocalStoreAndNotify(self: Service, notify: bool = t
if localKp.isNil:
self.storeKeypair(kpDb)
let addresses = kpDb.accounts.map(a => a.address)
self.fetchENSNamesForAddressesAsync(addresses, chainId)
self.buildAllTokens(addresses, store = true)
for acc in kpDb.accounts:
acc.ens = getEnsName(acc.address, chainId)
if acc.isChat:
continue
if notify:
@ -223,8 +226,8 @@ proc addNewKeypairsAccountsToLocalStoreAndNotify(self: Service, notify: bool = t
break
if found:
continue
accDb.ens = getEnsName(accDb.address, chainId)
self.storeAccountToKeypair(accDb)
self.fetchENSNamesForAddressesAsync(@[accDb.address], chainId)
if accDb.isChat:
continue
self.buildAllTokens(@[accDb.address], store = true)
@ -279,19 +282,21 @@ proc updateAccountsPositions(self: Service) =
continue
localAcc.position = dbAcc.position
proc updateAccountInLocalStoreAndNotify(self: Service, address, name, colorId, emoji: string, operable: string = "",
positionUpdated: Option[bool] = none(bool), notify: bool = true) =
proc updateAccountInLocalStoreAndNotify(self: Service, address, name, colorId, emoji: string, ensName: string = "",
operable: string = "", positionUpdated: Option[bool] = none(bool), notify: bool = true) =
if address.len > 0:
var account = self.getAccountByAddress(address)
if account.isNil:
return
if name.len > 0 or colorId.len > 0 or emoji.len > 0 or operable.len > 0:
if name.len > 0 or colorId.len > 0 or emoji.len > 0 or operable.len > 0 or ensName.len > 0:
if name.len > 0 and name != account.name:
account.name = name
if colorId.len > 0 and colorId != account.colorId:
account.colorId = colorId
if emoji.len > 0 and emoji != account.emoji:
account.emoji = emoji
if ensName.len > 0 and ensName != account.ens:
account.ens = ensName
if operable.len > 0 and operable != account.operable and
(operable == AccountNonOperable or operable == AccountPartiallyOperable or operable == AccountFullyOperable):
account.operable = operable
@ -445,7 +450,7 @@ proc makePartiallyOperableAccoutsFullyOperable(self: Service, password: string,
return
let affectedAccounts = map(response.result.getElems(), x => x.getStr())
for acc in affectedAccounts:
self.updateAccountInLocalStoreAndNotify(acc, name = "", colorId = "", emoji = "", operable = AccountFullyOperable)
self.updateAccountInLocalStoreAndNotify(acc, name = "", colorId = "", emoji = "", ensName = "", operable = AccountFullyOperable)
except Exception as e:
error "error: ", procName="makeSeedPhraseKeypairFullyOperable", errName=e.name, errDesription=e.msg
@ -464,7 +469,7 @@ proc onNonProfileKeycardKeypairMigratedToApp*(self: Service, response: string) {
else:
kp.keycards = @[]
except Exception as e:
error "error handilng migrated keycard response", errDesription=e.msg
error "error handling migrated keycard response", errDesription=e.msg
self.events.emit(SIGNAL_ALL_KEYCARDS_DELETED, data)
proc migrateNonProfileKeycardKeypairToAppAsync*(self: Service, keyUid, seedPhrase, password: string, doPasswordHashing: bool) =
@ -481,6 +486,29 @@ proc migrateNonProfileKeycardKeypairToAppAsync*(self: Service, keyUid, seedPhras
)
self.threadpool.start(arg)
proc onENSNamesFetched*(self: Service, response: string) {.slot.} =
try:
let responseObj = response.parseJson
if responseObj{"error"}.kind != JNull and responseObj{"error"}.getStr != "":
raise newException(CatchableError, responseObj["error"].getStr)
for address, name in responseObj["result"].pairs:
let ensName = name.getStr
if ensName.len == 0:
continue
self.updateAccountInLocalStoreAndNotify(address, name = "", colorId = "", emoji = "", ensName)
except Exception as e:
error "error getting ENS names for accounts", errDesription=e.msg
proc fetchENSNamesForAddressesAsync(self: Service, addresses: seq[string], chainId: int) =
let arg = FetchENSNamesForAddressesTaskArg(
tptr: fetchENSNamesForAddressesTask,
vptr: cast[ByteAddress](self.vptr),
slot: "onENSNamesFetched",
addresses: addresses,
chainId: chainId
)
self.threadpool.start(arg)
proc getRandomMnemonic*(self: Service): string =
try:
let response = status_go_accounts.getRandomMnemonic()
@ -621,7 +649,7 @@ proc moveAccountFinally*(self: Service, fromPosition: int, toPosition: int) =
updated = true
except Exception as e:
error "error: ", procName="moveAccountFinally", errName=e.name, errDesription=e.msg
self.updateAccountInLocalStoreAndNotify(address = "", name = "", colorId = "", emoji = "", operable = "", some(updated))
self.updateAccountInLocalStoreAndNotify(address = "", name = "", colorId = "", emoji = "", ensName = "", operable = "", some(updated))
proc updateKeypairName*(self: Service, keyUid: string, name: string) =
try:
@ -719,7 +747,7 @@ proc handleWalletAccount(self: Service, account: WalletAccountDto, notify: bool
var localAcc = self.getAccountByAddress(account.address)
if not localAcc.isNil:
self.updateAccountInLocalStoreAndNotify(account.address, account.name, account.colorId, account.emoji,
account.operable, none(bool), notify)
account.ens, account.operable, none(bool), notify)
else:
self.addNewKeypairsAccountsToLocalStoreAndNotify(notify)