feat(wallet): Introduce simple account transaction list

There's still some things that needs to be done (possibly in future commits):

[ ] Asset icons need to be determined so they can be displayed along the transaction
[ ] Transaction values need to be converted to decimal values
[ ] Date-time formatting
[ ] Grouping of transactions by days
This commit is contained in:
Pascal Precht 2020-06-16 11:46:26 +02:00 committed by Iuri Matias
parent 116b04a9ef
commit 0f7e08075b
8 changed files with 290 additions and 7 deletions

View File

@ -5,6 +5,7 @@ import strutils
import views/asset_list
import views/account_list
import views/account_item
import views/transaction_list
import ../../status/wallet
import ../../status/status
import chronicles
@ -15,6 +16,7 @@ QtObject:
accounts*: AccountList
currentAssetList*: AssetList
currentAccount: AccountItemView
currentTransactions: TransactionList
status: Status
totalFiatBalance: string
@ -30,6 +32,7 @@ QtObject:
result.accounts = newAccountList()
result.currentAccount = newAccountItemView()
result.currentAssetList = newAssetList()
result.currentTransactions = newTransactionList()
result.totalFiatBalance = ""
result.setup
@ -68,6 +71,20 @@ QtObject:
write = setCurrentAssetList
notify = currentAssetListChanged
proc currentTransactionsChanged*(self: WalletView) {.signal.}
proc getCurrentTransactions*(self: WalletView): QVariant {.slot.} =
return newQVariant(self.currentTransactions)
proc setCurrentTransactions*(self: WalletView, transactionList: seq[Transaction]) =
self.currentTransactions.setNewData(transactionList)
self.currentTransactionsChanged()
QtProperty[QVariant] transactions:
read = getCurrentTransactions
write = setCurrentTransactions
notify = currentTransactionsChanged
proc totalFiatBalanceChanged*(self: WalletView) {.signal.}
proc getTotalFiatBalance(self: WalletView): string {.slot.} =
@ -163,3 +180,6 @@ QtObject:
proc addCustomToken*(self: WalletView, address: string, name: string, symbol: string, decimals: string) {.slot.} =
self.status.wallet.toggleAsset(symbol, true, address, name, parseInt(decimals), "")
proc loadTransactionsForAccount*(self: WalletView, address: string) {.slot.} =
self.setCurrentTransactions(self.status.wallet.getTransfersByAddress(address))

View File

@ -0,0 +1,89 @@
import NimQml
import tables
import ../../../status/wallet
type
TransactionRoles {.pure.} = enum
Type = UserRole + 1,
Address = UserRole + 2,
BlockNumber = UserRole + 3,
BlockHash = UserRole + 4,
Timestamp = UserRole + 5,
GasPrice = UserRole + 6,
GasLimit = UserRole + 7,
GasUsed = UserRole + 8,
Nonce = UserRole + 9,
TxStatus = UserRole + 10,
Value = UserRole + 11,
From = UserRole + 12,
To = UserRole + 13
QtObject:
type TransactionList* = ref object of QAbstractListModel
transactions*: seq[Transaction]
proc setup(self: TransactionList) = self.QAbstractListModel.setup
proc delete(self: TransactionList) =
self.QAbstractListModel.delete
self.transactions = @[]
proc newTransactionList*(): TransactionList =
new(result, delete)
result.transactions = @[]
result.setup
method rowCount(self: TransactionList, index: QModelIndex = nil): int =
return self.transactions.len
method data(self: TransactionList, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.transactions.len:
return
let transaction = self.transactions[index.row]
let transactionRole = role.TransactionRoles
case transactionRole:
of TransactionRoles.Type: result = newQVariant(transaction.typeValue)
of TransactionRoles.Address: result = newQVariant(transaction.address)
of TransactionRoles.BlockNumber: result = newQVariant(transaction.blockNumber)
of TransactionRoles.BlockHash: result = newQVariant(transaction.blockHash)
of TransactionRoles.Timestamp: result = newQVariant(transaction.timestamp)
of TransactionRoles.GasPrice: result = newQVariant(transaction.gasPrice)
of TransactionRoles.GasLimit: result = newQVariant(transaction.gasLimit)
of TransactionRoles.GasUsed: result = newQVariant(transaction.gasUsed)
of TransactionRoles.Nonce: result = newQVariant(transaction.nonce)
of TransactionRoles.TxStatus: result = newQVariant(transaction.txStatus)
of TransactionRoles.Value: result = newQVariant(transaction.value)
of TransactionRoles.From: result = newQVariant(transaction.fromAddress)
of TransactionRoles.To: result = newQVariant(transaction.to)
method roleNames(self: TransactionList): Table[int, string] =
{ TransactionRoles.Type.int:"typeValue",
TransactionRoles.Address.int:"address",
TransactionRoles.BlockNumber.int:"blockNumber",
TransactionRoles.BlockHash.int:"blockHash",
TransactionRoles.Timestamp.int:"timestamp",
TransactionRoles.GasPrice.int:"gasPrice",
TransactionRoles.GasLimit.int:"gasLimit",
TransactionRoles.GasUsed.int:"gasUsed",
TransactionRoles.Nonce.int:"nonce",
TransactionRoles.TxStatus.int:"txStatus",
TransactionRoles.Value.int:"value",
TransactionRoles.From.int:"fromAddress",
TransactionRoles.To.int:"to" }.toTable
proc addTransactionToList*(self: TransactionList, transaction: Transaction) =
self.beginInsertRows(newQModelIndex(), self.transactions.len, self.transactions.len)
self.transactions.add(transaction)
self.endInsertRows()
proc setNewData*(self: TransactionList, transactionList: seq[Transaction]) =
self.beginResetModel()
self.transactions = transactionList
self.endResetModel()
proc forceUpdate*(self: TransactionList) =
self.beginResetModel()
self.endResetModel()

View File

@ -35,11 +35,20 @@ proc sendTransaction*(inputJSON: string, password: string): string =
proc startMessenger*() =
discard callPrivateRPC("startMessenger".prefix)
proc addPeer*(peer: string) =
proc addPeer*(peer: string) =
discard callPrivateRPC("admin_addPeer", %* [peer])
proc removePeer*(peer: string) =
proc removePeer*(peer: string) =
discard callPrivateRPC("admin_removePeer", %* [peer])
proc markTrustedPeer*(peer: string) =
proc markTrustedPeer*(peer: string) =
discard callPrivateRPC("markTrustedPeer".prefix(false), %* [peer])
proc getContactByID*(id: string): string =
result = callPrivateRPC("getContactByID".prefix, %* [id])
proc getBlockByNumber*(blockNumber: string): string =
result = callPrivateRPC("eth_getBlockByNumber", %* [blockNumber, false])
proc getTransfersByAddress*(address: string, toBlock: string, limit: string): string =
result = callPrivateRPC("wallet_getTransfersByAddress", %* [address, toBlock, limit])

View File

@ -75,3 +75,20 @@ type AccountArgs* = ref object of Args
type
StatusGoException* = object of Exception
type
Transaction* = ref object
typeValue*: string
address*: string
blockNumber*: string
blockHash*: string
timestamp*: string
gasPrice*: string
gasLimit*: string
gasUsed*: string
nonce*: string
txStatus*: string
value*: string
fromAddress*: string
to*: string

View File

@ -6,6 +6,7 @@ import strformat
import stint
import strutils, sequtils
import chronicles
import types
import ../wallet/account
proc getWalletAccounts*(): seq[WalletAccount] =
@ -32,6 +33,36 @@ proc getWalletAccounts*(): seq[WalletAccount] =
let msg = getCurrentExceptionMsg()
error "Failed getting wallet accounts", msg
proc getTransfersByAddress*(address: string): seq[Transaction] =
try:
let response = status.getBlockByNumber("latest")
let latestBlock = parseJson(response)["result"]
let transactionsResponse = status.getTransfersByAddress(address, latestBlock["number"].getStr, "0x14")
let transactions = parseJson(transactionsResponse)["result"]
var accountTransactions: seq[Transaction] = @[]
for transaction in transactions:
accountTransactions.add(Transaction(
typeValue: transaction["type"].getStr,
address: transaction["address"].getStr,
blockNumber: transaction["blockNumber"].getStr,
timestamp: transaction["timestamp"].getStr,
gasPrice: transaction["gasPrice"].getStr,
gasLimit: transaction["gasLimit"].getStr,
gasUsed: transaction["gasUsed"].getStr,
nonce: transaction["nonce"].getStr,
txStatus: transaction["txStatus"].getStr,
value: transaction["value"].getStr,
fromAddress: transaction["from"].getStr,
to: transaction["to"].getStr
))
result = accountTransactions
except:
let msg = getCurrentExceptionMsg()
error "Failed getting wallet account transactions", msg
proc sendTransaction*(from_address: string, to: string, value: string, password: string): string =
var args = %* {
"value": fmt"0x{toHex(value)}",

View File

@ -4,10 +4,11 @@ import libstatus/tokens as status_tokens
import libstatus/settings as status_settings
import libstatus/wallet as status_wallet
import libstatus/accounts/constants as constants
from libstatus/types import GeneratedAccount, DerivedAccount
from libstatus/types import GeneratedAccount, DerivedAccount, Transaction
import wallet/balance_manager
import wallet/account
export account
export Transaction
type WalletModel* = ref object
events*: EventEmitter
@ -144,3 +145,6 @@ proc toggleAsset*(self: WalletModel, symbol: string, enable: bool, address: stri
account.assetList = self.generateAccountConfiguredAssets(account.address)
updateBalance(account, self.getDefaultCurrency())
self.events.emit("assetChanged", Args())
proc getTransfersByAddress*(self: WalletModel, address: string): seq[Transaction] =
result = status_wallet.getTransfersByAddress(address)

View File

@ -1,8 +1,118 @@
import QtQuick 2.3
import "../../../imports"
Item {
Text {
id: name3
text: "HISTORY"
Component {
id: transactionListItem
Item {
anchors.right: parent.right
anchors.left: parent.left
height: 64
Item {
Rectangle {
id: assetIcon
color: "gray"
width: 40
height: 40
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 12
radius: 50
}
Text {
id: transferIcon
anchors.topMargin: 25
anchors.top: parent.top
anchors.left: assetIcon.right
anchors.leftMargin: 22
height: 15
width: 15
color: to != walletModel.currentAccount.address ? "#4360DF" : "green"
text: to != walletModel.currentAccount.address ? "↑" : "↓"
}
Text {
id: transactionValue
anchors.left: transferIcon.right
anchors.leftMargin: Theme.smallPadding
anchors.top: parent.top
anchors.topMargin: Theme.bigPadding
font.pixelSize: 15
text: value + " TOKEN"
}
}
Item {
anchors.right: timeInfo.left
anchors.top: parent.top
anchors.topMargin: Theme.bigPadding
width: children[0].width + children[1].width
Text {
text: to != walletModel.currentAccount.address ? "To " : "From "
anchors.right: addressValue.left
color: Theme.darkGrey
anchors.top: parent.top
font.pixelSize: 15
font.strikeout: false
}
Text {
id: addressValue
text: to
width: 100
elide: Text.ElideMiddle
anchors.right: parent.right
anchors.top: parent.top
font.pixelSize: 15
}
}
Item {
id: timeInfo
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: Theme.bigPadding
width: children[0].width + children[1].width + children[2].width
Text {
text: "• "
font.weight: Font.Bold
anchors.right: timeIndicator.left
color: Theme.darkGrey
anchors.top: parent.top
font.pixelSize: 15
}
Text {
id: timeIndicator
text: "At "
anchors.right: timeValue.left
color: Theme.darkGrey
anchors.top: parent.top
font.pixelSize: 15
font.strikeout: false
}
Text {
id: timeValue
text: timestamp
anchors.right: parent.right
anchors.top: parent.top
font.pixelSize: 15
}
}
}
}
ListView {
anchors.topMargin: 20
anchors.fill: parent
model: walletModel.transactions
delegate: transactionListItem
}
}

View File

@ -81,6 +81,9 @@ SplitView {
anchors.left: collectiblesBtn.right
anchors.leftMargin: 32
btnText: "History"
onClicked: {
walletModel.loadTransactionsForAccount(walletModel.currentAccount.address)
}
}
}