diff --git a/src/app/chat/core.nim b/src/app/chat/core.nim index b0bf9c09fb..1f2d62ff09 100644 --- a/src/app/chat/core.nim +++ b/src/app/chat/core.nim @@ -5,7 +5,7 @@ import ../../status/messages as messages_model import ../../status/signals/types import ../../status/libstatus/types as status_types import ../../status/libstatus/settings as status_settings -import ../../status/[chat, contacts, status] +import ../../status/[chat, contacts, status, wallet] import view, views/channels_list, views/message_list logScope: diff --git a/src/app/chat/event_handling.nim b/src/app/chat/event_handling.nim index 5a1fe6cdf2..d58aa800b6 100644 --- a/src/app/chat/event_handling.nim +++ b/src/app/chat/event_handling.nim @@ -1,4 +1,4 @@ -import sugar, sequtils, times +import sugar, sequtils, times, strutils proc handleChatEvents(self: ChatController) = # Display already saved messages @@ -75,6 +75,10 @@ proc handleChatEvents(self: ChatController) = self.status.events.on("chat:connected") do(e: Args): self.view.setConnected(true) + self.status.events.on(PendingTransactionType.BuyingStickerPack.event) do(e: Args): + var data = TransactionMinedArgs(e).data + self.view.installStickerPack(data.parseInt) + proc handleMailserverEvents(self: ChatController) = self.status.events.on("mailserverTopics") do(e: Args): var topics = TopicArgs(e).topics diff --git a/src/app/chat/view.nim b/src/app/chat/view.nim index 7ef507818a..cdc563f158 100644 --- a/src/app/chat/view.nim +++ b/src/app/chat/view.nim @@ -12,6 +12,7 @@ import ../../status/libstatus/stickers as status_stickers import ../../status/contacts as status_contacts import ../../status/ens as status_ens import ../../status/chat/[chat, message] +import ../../status/wallet import ../../status/libstatus/types import ../../status/profile/profile import eth/common/eth_types @@ -115,6 +116,9 @@ QtObject: try: let response = self.status.stickers.buyPack(packId, address, price, gas, gasPrice, password) result = $(%* { "result": %response }) + # TODO: + # check if response["error"] is not null and handle the error + self.status.wallet.trackPendingTransaction(address, response, PendingTransactionType.BuyingStickerPack, $packId) except RpcException as e: result = $(%* { "error": %* { "message": %e.msg }}) diff --git a/src/app/wallet/core.nim b/src/app/wallet/core.nim index 3a01b76fc0..2616aecbf3 100644 --- a/src/app/wallet/core.nim +++ b/src/app/wallet/core.nim @@ -51,6 +51,7 @@ proc init*(self: WalletController) = of "newblock": for acc in data.accounts: self.status.wallet.updateAccount(acc) + self.status.wallet.checkPendingTransactions(acc, data.blockNumber) # TODO: show notification of "recent-history-fetching": self.view.setHistoryFetchState(data.accounts, true) diff --git a/src/status/libstatus/wallet.nim b/src/status/libstatus/wallet.nim index cfcea6aad7..8013d12cea 100644 --- a/src/status/libstatus/wallet.nim +++ b/src/status/libstatus/wallet.nim @@ -31,6 +31,9 @@ proc getWalletAccounts*(): seq[WalletAccount] = let msg = getCurrentExceptionMsg() error "Failed getting wallet accounts", msg +proc getTransactionReceipt*(transactionHash: string): string = + result = callPrivateRPC("eth_getTransactionReceipt", %* [transactionHash]) + proc getTransfersByAddress*(address: string): seq[types.Transaction] = try: let response = getBlockByNumber("latest") diff --git a/src/status/wallet.nim b/src/status/wallet.nim index ba215a94f2..55ffccadd4 100644 --- a/src/status/wallet.nim +++ b/src/status/wallet.nim @@ -2,6 +2,7 @@ import eventemitter, json, strformat, strutils, chronicles, sequtils, httpclient import json_serialization, stint from eth/common/utils import parseAddress from eth/common/eth_types import EthAddress +from libstatus/core import getBlockByNumber import libstatus/accounts as status_accounts import libstatus/tokens as status_tokens import libstatus/settings as status_settings @@ -18,12 +19,31 @@ export Transaction logScope: topics = "wallet-model" +type PendingTransactionType* {.pure.} = enum + RegisterENS = "RegisterENS", + ReleaseENS = "ReleaseENS", + BuyingStickerPack = "BuyingStickerPack" + +proc event*(self:PendingTransactionType):string = + result = "transaction:" & $self + +type PendingTransaction* = object + transactionHash*: string + blockNumber*: int + trxType*: PendingTransactionType + data*: string + mined: bool + +type TransactionMinedArgs* = ref object of Args + data*: string + type WalletModel* = ref object - events*: EventEmitter - accounts*: seq[WalletAccount] - defaultCurrency*: string - tokens*: JsonNode - totalBalance*: float + events*: EventEmitter + accounts*: seq[WalletAccount] + defaultCurrency*: string + tokens*: JsonNode + totalBalance*: float + pendingTransactions: Table[string, seq[PendingTransaction]] proc getDefaultCurrency*(self: WalletModel): string proc calculateTotalFiatBalance*(self: WalletModel) @@ -32,6 +52,7 @@ proc newWalletModel*(events: EventEmitter): WalletModel = result = WalletModel() result.accounts = @[] result.tokens = %* [] + result.pendingTransactions = initTable[string, seq[PendingTransaction]]() result.events = events result.defaultCurrency = "" result.totalBalance = 0.0 @@ -68,6 +89,36 @@ proc estimateGas*(self: WalletModel, source, to, value: string): int = except RpcException as e: raise +proc trackPendingTransaction*(self: WalletModel, address: string, trxHash: string, trxType: PendingTransactionType, data: string) = + let latestBlock = getBlockByNumber("latest").parseJson()["result"].getInt + + if not self.pendingTransactions.hasKey(address): + self.pendingTransactions[address] = @[] + + self.pendingTransactions[address].add PendingTransaction( + transactionHash: trxHash, + trxType: trxType, + blockNumber: latestBlock, + data: data, + mined: false + ) + +proc getTransactionReceipt*(self: WalletModel, transactionHash: string): JsonNode = + result = status_wallet.getTransactionReceipt(transactionHash).parseJSON()["result"] + +proc checkPendingTransactions*(self: WalletModel, address: string, blockNumber: int) = + if not self.pendingTransactions.hasKey(address): return + for trx in self.pendingTransactions[address].mitems: + if trx.mined: continue + + let transactionReceipt = self.getTransactionReceipt(trx.transactionHash) + if transactionReceipt.kind != JNull: + trx.mined = true + if transactionReceipt{"status"}.getStr == "0x1": # mined successfully + self.events.emit(trx.trxType.event, TransactionMinedArgs(data: trx.data)) + else: + discard # TODO: what should we do if the transaction reverted? + proc estimateTokenGas*(self: WalletModel, source, to, assetAddress, value: string): int = var transfer: Transfer