fix(@wallet): Fix event for transaction

This commit is contained in:
Anthony Laibe 2023-01-25 13:56:19 +01:00 committed by Anthony Laibe
parent 64d6c484b2
commit 7744d20eb5
9 changed files with 137 additions and 158 deletions

View File

@ -44,29 +44,25 @@ proc delete*(self: Controller) =
discard
proc init*(self: Controller) =
self.events.on(SignalType.Wallet.event) do(e:Args):
var data = WalletSignal(e)
case data.eventType:
of "new-transfers":
for account in data.accounts:
# TODO find a way to use data.blockNumber
self.loadTransactions(account, stint.fromHex(Uint256, "0x0"))
of "recent-history-fetching":
self.delegate.setHistoryFetchState(data.accounts, isFetching = true)
of "recent-history-ready":
for account in data.accounts:
self.loadTransactions(account, stint.fromHex(Uint256, "0x0"))
self.delegate.setHistoryFetchState(data.accounts, isFetching = false)
of "non-archival-node-detected":
let accounts = self.getWalletAccounts()
let addresses = accounts.map(account => account.address)
self.delegate.setHistoryFetchState(addresses, isFetching = false)
self.delegate.setIsNonArchivalNode(true)
of "fetching-history-error":
let accounts = self.getWalletAccounts()
let addresses = accounts.map(account => account.address)
self.delegate.setHistoryFetchState(addresses, isFetching = false)
self.events.on(SIGNAL_HISTORY_FETCHING) do (e:Args):
let args = HistoryArgs(e)
self.delegate.setHistoryFetchState(args.addresses, isFetching = true)
self.events.on(SIGNAL_HISTORY_READY) do (e:Args):
let args = HistoryArgs(e)
self.delegate.setHistoryFetchState(args.addresses, isFetching = false)
self.events.on(SIGNAL_HISTORY_NON_ARCHIVAL_NODE) do (e:Args):
let accounts = self.getWalletAccounts()
let addresses = accounts.map(account => account.address)
self.delegate.setHistoryFetchState(addresses, isFetching = false)
self.delegate.setIsNonArchivalNode(true)
self.events.on(SIGNAL_HISTORY_ERROR) do (e:Args):
let accounts = self.getWalletAccounts()
let addresses = accounts.map(account => account.address)
self.delegate.setHistoryFetchState(addresses, isFetching = false)
self.events.on(SIGNAL_TRANSACTIONS_LOADED) do(e:Args):
let args = TransactionsLoadedArgs(e)
self.delegate.setTrxHistoryResult(args.transactions, args.address, args.wasFetchMore)
@ -83,15 +79,15 @@ proc init*(self: Controller) =
self.events.on(SIGNAL_SUGGESTED_ROUTES_READY) do(e:Args):
self.delegate.suggestedRoutesReady(SuggestedRoutesArgs(e).suggestedRoutes)
self.events.on(SIGNAL_PENDING_TX_COMPLETED) do(e:Args):
self.walletAccountService.checkRecentHistory()
self.events.on(SIGNAL_TRANSACTION_LOADING_COMPLETED_FOR_ALL_NETWORKS) do(e:Args):
let args = TransactionsLoadedArgs(e)
self.delegate.setHistoryFetchState(args.address, isFetching = false)
proc checkPendingTransactions*(self: Controller): seq[TransactionDto] =
return self.transactionService.checkPendingTransactions()
proc watchPendingTransactions*(self: Controller): seq[TransactionDto] =
return self.transactionService.watchPendingTransactions()
proc getPendingTransactions*(self: Controller): seq[TransactionDto] =
return self.transactionService.getPendingTransactions()
proc getWalletAccounts*(self: Controller): seq[WalletAccountDto] =
self.walletAccountService.getWalletAccounts()

View File

@ -80,7 +80,7 @@ proc transactionsToItems(self: Module, transactions: seq[TransactionDto]) : seq[
))
proc setPendingTx(self: Module) =
self.view.setPendingTx(self.transactionsToItems(self.controller.checkPendingTransactions()))
self.view.setPendingTx(self.transactionsToItems(self.controller.watchPendingTransactions()))
method viewDidLoad*(self: Module) =
let accounts = self.getWalletAccounts()
@ -168,7 +168,7 @@ method onUserAuthenticated*(self: Module, password: string) =
method transactionWasSent*(self: Module, result: string) =
self.view.transactionWasSent(result)
self.setPendingTx()
self.view.setPendingTx(self.transactionsToItems(self.controller.getPendingTransactions()))
method suggestedFees*(self: Module, chainId: int): string =
return self.controller.suggestedFees(chainId)

View File

@ -132,15 +132,9 @@ QtObject:
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()
if (pendingTransactions.kind == JArray and pendingTransactions.len > 0):
for trx in pendingTransactions.getElems():
let transactionType = trx["type"].getStr
if transactionType == $PendingTransactionTypeDto.RegisterENS or
transactionType == $PendingTransactionTypeDto.SetPubKey:
self.pendingEnsUsernames.incl trx["additionalData"].getStr
for trx in self.transactionService.getPendingTransactions():
if trx.typeValue == $PendingTransactionTypeDto.RegisterENS or trx.typeValue == $PendingTransactionTypeDto.SetPubKey:
self.pendingEnsUsernames.incl trx.additionalData
proc getMyPendingEnsUsernames*(self: Service): seq[string] =
for i in self.pendingEnsUsernames.items:
@ -260,7 +254,7 @@ QtObject:
let hash = resp.result.getStr
let resolverAddress = status_ens.resolver(chainId, ensUsername.addDomain()).result.getStr
self.transactionService.trackPendingTransaction(
self.transactionService.watchTransaction(
hash, $address, resolverAddress,
$PendingTransactionTypeDto.SetPubKey, ensUsername, chainId
)
@ -317,7 +311,7 @@ QtObject:
let hash = resp.result.getStr
let ensUsernamesAddress = self.getEnsRegisteredAddress()
self.transactionService.trackPendingTransaction(
self.transactionService.watchTransaction(
hash, address, ensUsernamesAddress,
$PendingTransactionTypeDto.ReleaseENS, ensUsername, chainId
)
@ -368,7 +362,7 @@ QtObject:
let hash = resp.result.getStr
let sntContract = self.getStatusToken()
let ensUsername = self.formatUsername(username, true)
self.transactionService.trackPendingTransaction(
self.transactionService.watchTransaction(
hash, address, $sntContract.address,
$PendingTransactionTypeDto.RegisterEns, ensUsername,
chainId

View File

@ -211,7 +211,7 @@ QtObject:
let transactionResponse = status_stickers.buy(chainId, %txData, packId, password)
let transactionHash = transactionResponse.result.getStr()
let sntContract = self.getStatusToken()
self.transactionService.trackPendingTransaction(
self.transactionService.watchTransaction(
transactionHash,
address,
$sntContract.address,

View File

@ -85,13 +85,11 @@ QtObject:
if found:
continue
let responseTokens = backend.getTokens(network.chainId)
let default_tokens = map(
responseTokens.result.getElems(),
proc(x: JsonNode): TokenDto = x.toTokenDto(network.enabled, hasIcon=true, isCustom=false)
)
self.tokens[network.chainId] = default_tokens.filter(
proc(x: TokenDto): bool = x.chainId == network.chainId
)

View File

@ -134,21 +134,30 @@ const getSuggestedRoutesTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall
}
arg.finish(output)
type
WatchTransactionTaskArg* = ref object of QObjectTaskArg
hash: string
chainId: int
txHash: string
address: string
trxType: string
const watchTransactionsTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
const watchTransactionTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[WatchTransactionTaskArg](argEncoded)
try:
let output = %*{
"txHash": arg.txHash,
"isSuccessfull": transactions.watchTransaction(arg.chainId, arg.txHash).error.isNil,
"hash": arg.hash,
"address": arg.address,
"chainId": arg.chainId,
"trxType": arg.trxType,
"isSuccessfull": transactions.watchTransaction(arg.chainId, arg.hash).error.isNil,
}
arg.finish(output)
except Exception as e:
let output = %* {
"hash": arg.txHash,
"hash": arg.hash,
"address": arg.address,
"chainId": arg.chainId,
"trxType": arg.trxType,
"isSuccessfull": false
}

View File

@ -125,14 +125,24 @@ proc cmpTransactions*(x, y: TransactionDto): int =
type
SuggestedFeesDto* = ref object
gasPrice*: float
baseFee*: float
maxPriorityFeePerGas*: float
maxFeePerGasL*: float
maxFeePerGasM*: float
maxFeePerGasH*: float
gasPrice*: float64
baseFee*: float64
maxPriorityFeePerGas*: float64
maxFeePerGasL*: float64
maxFeePerGasM*: float64
maxFeePerGasH*: float64
eip1559Enabled*: bool
proc decodeSuggestedFeesDto*(jsonObj: JsonNode): SuggestedFeesDto =
result = SuggestedFeesDto()
result.gasPrice = jsonObj{"gasPrice"}.getFloat
result.baseFee = jsonObj{"baseFee"}.getFloat
result.maxPriorityFeePerGas = jsonObj{"maxPriorityFeePerGas"}.getFloat
result.maxFeePerGasL = jsonObj{"maxFeePerGasL"}.getFloat
result.maxFeePerGasM = jsonObj{"maxFeePerGasM"}.getFloat
result.maxFeePerGasH = jsonObj{"maxFeePerGasH"}.getFloat
result.eip1559Enabled = jsonObj{"eip1559Enabled"}.getbool
proc toSuggestedFeesDto*(jsonObj: JsonNode): SuggestedFeesDto =
result = SuggestedFeesDto()
result.gasPrice = parseFloat(jsonObj["gasPrice"].getStr)
@ -225,7 +235,7 @@ proc convertToTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto =
discard jsonObj.getProp("bridgeName", result.bridgeName)
result.fromNetwork = Json.decode($jsonObj["fromNetwork"], NetworkDto, allowUnknownFields = true)
result.toNetwork = Json.decode($jsonObj["toNetwork"], NetworkDto, allowUnknownFields = true)
result.gasFees = Json.decode($jsonObj["gasFees"], SuggestedFeesDto, allowUnknownFields = true)
result.gasFees = decodeSuggestedFeesDto(jsonObj["gasFees"])
discard jsonObj.getProp("cost", result.cost)
discard jsonObj.getProp("tokenFees", result.tokenFees)
discard jsonObj.getProp("bonderFees", result.bonderFees)

View File

@ -35,8 +35,11 @@ include ../../common/json_utils
const SIGNAL_TRANSACTIONS_LOADED* = "transactionsLoaded"
const SIGNAL_TRANSACTION_SENT* = "transactionSent"
const SIGNAL_SUGGESTED_ROUTES_READY* = "suggestedRoutesReady"
const SIGNAL_PENDING_TX_COMPLETED* = "pendingTransactionCompleted"
const SIGNAL_TRANSACTION_LOADING_COMPLETED_FOR_ALL_NETWORKS* = "transactionsLoadingCompleteForAllNetworks"
const SIGNAL_HISTORY_FETCHING* = "historyFetching"
const SIGNAL_HISTORY_READY* = "historyReady"
const SIGNAL_HISTORY_NON_ARCHIVAL_NODE* = "historyNonArchivalNode"
const SIGNAL_HISTORY_ERROR* = "historyError"
type
EstimatedTime* {.pure.} = enum
@ -54,6 +57,10 @@ type
success*: bool
revertReason*: string
type
HistoryArgs* = ref object of Args
addresses*: seq[string]
type
TransactionsLoadedArgs* = ref object of Args
transactions*: seq[TransactionDto]
@ -82,8 +89,7 @@ QtObject:
txCounter: Table[string, seq[int]]
# Forward declaration
proc checkPendingTransactions*(self: Service): seq[TransactionDto]
proc checkPendingTransactions*(self: Service, address: string)
proc loadTransactions*(self: Service, address: string, toBlock: Uint256, limit: int = 20, loadMore: bool = false)
proc delete*(self: Service) =
self.QObject.delete
@ -91,7 +97,7 @@ QtObject:
proc newService*(
events: EventEmitter,
threadpool: ThreadPool,
networkService: network_service.Service,
networkService: network_service.Service,
settingsService: settings_service.Service,
tokenService: token_service.Service,
): Service =
@ -104,101 +110,80 @@ QtObject:
result.tokenService = tokenService
result.txCounter = initTable[string, seq[int]]()
proc doConnect*(self: Service) =
proc init*(self: Service) =
self.events.on(SignalType.Wallet.event) do(e:Args):
var data = WalletSignal(e)
if(data.eventType == "newblock"):
for acc in data.accounts:
self.checkPendingTransactions(acc)
case data.eventType:
of "recent-history-fetching":
self.events.emit(SIGNAL_HISTORY_FETCHING, HistoryArgs(addresses: data.accounts))
of "recent-history-ready":
for account in data.accounts:
self.loadTransactions(account, stint.fromHex(Uint256, "0x0"))
self.events.emit(SIGNAL_HISTORY_READY, HistoryArgs(addresses: data.accounts))
of "non-archival-node-detected":
self.events.emit(SIGNAL_HISTORY_NON_ARCHIVAL_NODE, Args())
of "fetching-history-error":
self.events.emit(SIGNAL_HISTORY_ERROR, Args())
proc init*(self: Service) =
self.doConnect()
proc watchTransactionResult*(self: Service, watchTxResult: string) {.slot.} =
let watchTxResult = parseJson(watchTxResult)
let txHash = watchTxResult["txHash"].getStr
let success = watchTxResult["isSuccessfull"].getBool
if(success):
self.events.emit(SIGNAL_PENDING_TX_COMPLETED, PendingTxCompletedArgs(txHash: txHash))
proc watchTransaction*(self: Service, chainId: int, transactionHash: string) =
let arg = WatchTransactionTaskArg(
chainId: chainId,
txHash: transactionHash,
tptr: cast[ByteAddress](watchTransactionsTask),
vptr: cast[ByteAddress](self.vptr),
slot: "watchTransactionResult",
)
self.threadpool.start(arg)
proc getTransactionReceipt*(self: Service, chainId: int, transactionHash: string): JsonNode =
try:
let response = transactions.getTransactionReceipt(chainId, transactionHash)
result = response.result
except Exception as e:
let errDescription = e.msg
error "error getting transaction receipt: ", errDescription
proc deletePendingTransaction*(self: Service, chainId: int, transactionHash: string) =
try:
discard transactions.deletePendingTransaction(chainId, transactionHash)
except Exception as e:
let errDescription = e.msg
error "error deleting pending transaction: ", errDescription
proc confirmTransactionStatus(self: Service, pendingTransactions: seq[TransactionDto]) =
for trx in pendingTransactions:
let transactionReceipt = self.getTransactionReceipt(trx.chainId, trx.txHash)
if transactionReceipt != nil and transactionReceipt.kind != JNull:
self.deletePendingTransaction(trx.chainId, trx.txHash)
let ev = TransactionMinedArgs(
data: trx.additionalData,
transactionHash: trx.txHash,
chainId: trx.chainId,
success: transactionReceipt{"status"}.getStr == "0x1",
revertReason: ""
)
self.events.emit(parseEnum[PendingTransactionTypeDto](trx.typeValue).event, ev)
proc getPendingTransactions*(self: Service): JsonNode =
proc getPendingTransactions*(self: Service): seq[TransactionDto] =
try:
let chainIds = self.networkService.getNetworks().map(a => a.chainId)
let response = backend.getPendingTransactionsByChainIDs(chainIds)
return response.result
let response = backend.getPendingTransactionsByChainIDs(chainIds).result
if (response.kind == JArray and response.len > 0):
return response.getElems().map(x => x.toPendingTransactionDto())
return @[]
except Exception as e:
let errDescription = e.msg
error "error: ", errDescription
return
proc getPendingOutboundTransactionsByAddress*(self: Service, address: string): JsonNode =
try:
let chainIds = self.networkService.getNetworks().map(a => a.chainId)
result = transactions.getPendingOutboundTransactionsByAddress(chainIds, address).result
except Exception as e:
let errDescription = e.msg
error "error getting pending txs by address: ", errDescription, address
proc watchTransactionResult*(self: Service, watchTxResult: string) {.slot.} =
let watchTxResult = parseJson(watchTxResult)
let success = watchTxResult["isSuccessfull"].getBool
if(success):
let hash = watchTxResult["hash"].getStr
let chainId = watchTxResult["chainId"].getInt
let address = watchTxResult["address"].getStr
let transactionReceipt = transactions.getTransactionReceipt(chainId, hash).result
if transactionReceipt != nil and transactionReceipt.kind != JNull:
discard transactions.deletePendingTransaction(chainId, hash)
let ev = TransactionMinedArgs(
data: "",
transactionHash: hash,
chainId: chainId,
success: transactionReceipt{"status"}.getStr == "0x1",
revertReason: ""
)
self.events.emit(parseEnum[PendingTransactionTypeDto](watchTxResult["trxType"].getStr).event, ev)
transactions.checkRecentHistory(@[chainId], @[address])
proc checkPendingTransactions*(self: Service): seq[TransactionDto] =
# TODO move this to a thread
proc watchTransaction*(
self: Service, hash: string, fromAddress: string, toAddress: string, trxType: string, data: string, chainId: int, track: bool = true
) =
if track:
try:
discard transactions.trackPendingTransaction(hash, fromAddress, toAddress, trxType, data, chainId)
except Exception as e:
let errDescription = e.msg
error "error: ", errDescription
let arg = WatchTransactionTaskArg(
chainId: chainId,
hash: hash,
address: fromAddress,
trxType: trxType,
tptr: cast[ByteAddress](watchTransactionTask),
vptr: cast[ByteAddress](self.vptr),
slot: "watchTransactionResult",
)
self.threadpool.start(arg)
proc watchPendingTransactions*(self: Service): seq[TransactionDto] =
let pendingTransactions = self.getPendingTransactions()
if (pendingTransactions.kind == JArray and pendingTransactions.len > 0):
let pendingTxs = pendingTransactions.getElems().map(x => x.toPendingTransactionDto())
self.confirmTransactionStatus(pendingTxs)
for tx in pendingTxs:
self.watchTransaction(tx.chainId, tx.txHash)
return pendingTxs
proc checkPendingTransactions*(self: Service, address: string) =
let pendingTxs = self.getPendingOutboundTransactionsByAddress(address).getElems().map(x => x.toPendingTransactionDto())
self.confirmTransactionStatus(pendingTxs)
proc trackPendingTransaction*(self: Service, hash: string, fromAddress: string, toAddress: string, trxType: string,
data: string, chainId: int) =
try:
discard transactions.trackPendingTransaction(hash, fromAddress, toAddress, trxType, data, chainId)
except Exception as e:
let errDescription = e.msg
error "error: ", errDescription
for tx in pendingTransactions:
self.watchTransaction(tx.txHash, tx.fromAddress, tx.to, tx.typeValue, tx.input, tx.chainId, track = false)
return pendingTransactions
proc setTrxHistoryResult*(self: Service, historyJSON: string) {.slot.} =
let historyData = parseJson(historyJSON)
@ -357,11 +342,12 @@ QtObject:
paths,
password,
)
# Watch for this transaction to be completed
if response.result{"hashes"} != nil:
for hash in response.result["hashes"][$chainID]:
let txHash = hash.getStr
self.watchTransaction(chainID, txHash)
self.watchTransaction(txHash, from_addr, to_addr, $PendingTransactionTypeDto.WalletTransfer, "", chainId, track = false)
let output = %* {"result": response.result{"hashes"}, "success":true, "uuid": %uuid }
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
except Exception as e:
@ -408,16 +394,6 @@ QtObject:
error "Error fetching crypto services", message = e.msg
return @[]
proc addToAllTransactionsAndSetNewMinMax(self: Service, myTip: float, numOfTransactionWithTipLessThanMine: var int,
transactions: JsonNode) =
if transactions.kind != JArray:
return
for t in transactions:
let gasPriceUnparsed = $fromHex(Stuint[256], t{"gasPrice"}.getStr)
let gasPrice = parseFloat(wei2gwei(gasPriceUnparsed))
if gasPrice < myTip:
numOfTransactionWithTipLessThanMine.inc
proc getEstimatedTime*(self: Service, chainId: int, maxFeePerGas: string): EstimatedTime =
try:
let response = backend.getTransactionEstimatedTime(chainId, maxFeePerGas.parseFloat).result.getInt

View File

@ -38,10 +38,6 @@ proc deletePendingTransaction*(chainId: int, transactionHash: string): RpcRespon
let payload = %* [chainId, transactionHash]
result = core.callPrivateRPC("wallet_deletePendingTransactionByChainID", payload)
proc getPendingOutboundTransactionsByAddress*(chainIds: seq[int], address: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [chainIds, address]
result = core.callPrivateRPC("wallet_getPendingOutboundTransactionsByAddressAndChainIDs", payload)
proc fetchCryptoServices*(): RpcResponse[JsonNode] {.raises: [Exception].} =
result = core.callPrivateRPC("wallet_getCryptoOnRamps", %* [])