mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-16 16:47:24 +00:00
feat(wallet) add recipients API and integrate with filter
Bumps status-go to include the new API. Add a new RecipientsModel to the activity controller. Extends the activity Controller with API to access and manage data in the RecipientsModel. Resolving addresses to names remains to be implemented. Updates #10025
This commit is contained in:
parent
fecf58102c
commit
2dd51e4584
@ -3,6 +3,7 @@ import tables
|
|||||||
|
|
||||||
import model
|
import model
|
||||||
import entry
|
import entry
|
||||||
|
import recipients_model
|
||||||
|
|
||||||
import ../transactions/item
|
import ../transactions/item
|
||||||
import ../transactions/module as transactions_module
|
import ../transactions/module as transactions_module
|
||||||
@ -21,11 +22,13 @@ proc toRef*[T](obj: T): ref T =
|
|||||||
result[] = obj
|
result[] = obj
|
||||||
|
|
||||||
const FETCH_BATCH_COUNT_DEFAULT = 10
|
const FETCH_BATCH_COUNT_DEFAULT = 10
|
||||||
|
const FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT = 2000
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type
|
type
|
||||||
Controller* = ref object of QObject
|
Controller* = ref object of QObject
|
||||||
model: Model
|
model: Model
|
||||||
|
recipientsModel: RecipientsModel
|
||||||
transactionsModule: transactions_module.AccessInterface
|
transactionsModule: transactions_module.AccessInterface
|
||||||
currentActivityFilter: backend_activity.ActivityFilter
|
currentActivityFilter: backend_activity.ActivityFilter
|
||||||
|
|
||||||
@ -50,6 +53,12 @@ QtObject:
|
|||||||
QtProperty[QVariant] model:
|
QtProperty[QVariant] model:
|
||||||
read = getModel
|
read = getModel
|
||||||
|
|
||||||
|
proc getRecipientsModel*(self: Controller): QVariant {.slot.} =
|
||||||
|
return newQVariant(self.recipientsModel)
|
||||||
|
|
||||||
|
QtProperty[QVariant] recipientsModel:
|
||||||
|
read = getRecipientsModel
|
||||||
|
|
||||||
proc backendToPresentation(self: Controller, backendEntities: seq[backend_activity.ActivityEntry]): seq[entry.ActivityEntry] =
|
proc backendToPresentation(self: Controller, backendEntities: seq[backend_activity.ActivityEntry]): seq[entry.ActivityEntry] =
|
||||||
var multiTransactionsIds: seq[int] = @[]
|
var multiTransactionsIds: seq[int] = @[]
|
||||||
var transactionIdentities: seq[backend.TransactionIdentity] = @[]
|
var transactionIdentities: seq[backend.TransactionIdentity] = @[]
|
||||||
@ -186,6 +195,7 @@ QtObject:
|
|||||||
proc newController*(transactionsModule: transactions_module.AccessInterface, events: EventEmitter): Controller =
|
proc newController*(transactionsModule: transactions_module.AccessInterface, events: EventEmitter): Controller =
|
||||||
new(result, delete)
|
new(result, delete)
|
||||||
result.model = newModel()
|
result.model = newModel()
|
||||||
|
result.recipientsModel = newRecipientsModel()
|
||||||
result.transactionsModule = transactionsModule
|
result.transactionsModule = transactionsModule
|
||||||
result.currentActivityFilter = backend_activity.getIncludeAllActivityFilter()
|
result.currentActivityFilter = backend_activity.getIncludeAllActivityFilter()
|
||||||
result.events = events
|
result.events = events
|
||||||
@ -256,10 +266,10 @@ QtObject:
|
|||||||
addresses[i] = addressesJson[i].getStr()
|
addresses[i] = addressesJson[i].getStr()
|
||||||
|
|
||||||
self.addresses = addresses
|
self.addresses = addresses
|
||||||
|
|
||||||
proc setFilterAddresses*(self: Controller, addresses: seq[string]) =
|
proc setFilterAddresses*(self: Controller, addresses: seq[string]) =
|
||||||
self.addresses = addresses
|
self.addresses = addresses
|
||||||
|
|
||||||
proc setFilterToAddresses*(self: Controller, addresses: seq[string]) =
|
proc setFilterToAddresses*(self: Controller, addresses: seq[string]) =
|
||||||
self.currentActivityFilter.counterpartyAddresses = addresses
|
self.currentActivityFilter.counterpartyAddresses = addresses
|
||||||
|
|
||||||
@ -291,4 +301,22 @@ QtObject:
|
|||||||
|
|
||||||
QtProperty[int] errorCode:
|
QtProperty[int] errorCode:
|
||||||
read = getErrorCode
|
read = getErrorCode
|
||||||
notify = errorCodeChanged
|
notify = errorCodeChanged
|
||||||
|
|
||||||
|
proc updateRecipientsModel*(self: Controller) {.slot.} =
|
||||||
|
let response = backend_activity.getAllRecipients(0, FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)
|
||||||
|
if response.error != nil:
|
||||||
|
error "error fetching recipients: ", response.error
|
||||||
|
return
|
||||||
|
|
||||||
|
let result = json.to(response.result, backend_activity.GetAllRecipientsResponse)
|
||||||
|
self.recipientsModel.addAddresses(result.addresses, 0, result.hasMore)
|
||||||
|
|
||||||
|
proc loadMoreRecipients(self: Controller) {.slot.} =
|
||||||
|
let response = backend_activity.getAllRecipients(self.recipientsModel.getCount(), FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)
|
||||||
|
if response.error != nil:
|
||||||
|
error "error fetching more recipient entries: ", response.error
|
||||||
|
return
|
||||||
|
|
||||||
|
let result = json.to(response.result, backend_activity.GetAllRecipientsResponse)
|
||||||
|
self.recipientsModel.addAddresses(result.addresses, self.recipientsModel.getCount(), result.hasMore)
|
@ -0,0 +1,95 @@
|
|||||||
|
import NimQml, Tables, strutils, strformat, sequtils, logging
|
||||||
|
|
||||||
|
type
|
||||||
|
ModelRole {.pure.} = enum
|
||||||
|
AddressRole = UserRole + 1
|
||||||
|
HasNameRole
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type
|
||||||
|
RecipientsModel* = ref object of QAbstractListModel
|
||||||
|
addresses*: seq[string]
|
||||||
|
# TODO: store resolved names here along addresses
|
||||||
|
hasMore: bool
|
||||||
|
|
||||||
|
proc delete(self: RecipientsModel) =
|
||||||
|
self.QAbstractListModel.delete
|
||||||
|
|
||||||
|
proc setup(self: RecipientsModel) =
|
||||||
|
self.QAbstractListModel.setup
|
||||||
|
|
||||||
|
proc newRecipientsModel*(): RecipientsModel =
|
||||||
|
new(result, delete)
|
||||||
|
|
||||||
|
result.addresses = @[]
|
||||||
|
# TODO: init data storage for the resolved names
|
||||||
|
|
||||||
|
result.setup
|
||||||
|
|
||||||
|
proc countChanged(self: RecipientsModel) {.signal.}
|
||||||
|
|
||||||
|
proc getCount*(self: RecipientsModel): int {.slot.} =
|
||||||
|
self.addresses.len
|
||||||
|
|
||||||
|
QtProperty[int] count:
|
||||||
|
read = getCount
|
||||||
|
notify = countChanged
|
||||||
|
|
||||||
|
method rowCount(self: RecipientsModel, index: QModelIndex = nil): int =
|
||||||
|
return self.addresses.len
|
||||||
|
|
||||||
|
method roleNames(self: RecipientsModel): Table[int, string] =
|
||||||
|
{
|
||||||
|
ModelRole.AddressRole.int:"address",
|
||||||
|
ModelRole.HasNameRole.int:"hasName"
|
||||||
|
}.toTable
|
||||||
|
|
||||||
|
method data(self: RecipientsModel, index: QModelIndex, role: int): QVariant =
|
||||||
|
if (not index.isValid):
|
||||||
|
return
|
||||||
|
|
||||||
|
if (index.row < 0 or index.row >= self.addresses.len):
|
||||||
|
return
|
||||||
|
|
||||||
|
let address = self.addresses[index.row]
|
||||||
|
let enumRole = role.ModelRole
|
||||||
|
|
||||||
|
case enumRole:
|
||||||
|
of ModelRole.AddressRole:
|
||||||
|
result = newQVariant(address)
|
||||||
|
of ModelRole.HasNameRole:
|
||||||
|
# TODO: check the resolved names storage
|
||||||
|
result = newQVariant(false)
|
||||||
|
|
||||||
|
proc hasMoreChanged*(self: RecipientsModel) {.signal.}
|
||||||
|
|
||||||
|
proc setHasMore(self: RecipientsModel, hasMore: bool) {.slot.} =
|
||||||
|
self.hasMore = hasMore
|
||||||
|
self.hasMoreChanged()
|
||||||
|
|
||||||
|
proc addAddresses*(self: RecipientsModel, newAddresses: seq[string], offset: int, hasMore: bool) =
|
||||||
|
if offset == 0:
|
||||||
|
self.beginResetModel()
|
||||||
|
self.addresses = newAddresses
|
||||||
|
self.endResetModel()
|
||||||
|
else:
|
||||||
|
let parentModelIndex = newQModelIndex()
|
||||||
|
defer: parentModelIndex.delete
|
||||||
|
|
||||||
|
if offset != self.addresses.len:
|
||||||
|
error "offset != self.addresses.len"
|
||||||
|
return
|
||||||
|
self.beginInsertRows(parentModelIndex, self.addresses.len, self.addresses.len + newAddresses.len - 1)
|
||||||
|
self.addresses.add(newAddresses)
|
||||||
|
self.endInsertRows()
|
||||||
|
|
||||||
|
self.countChanged()
|
||||||
|
self.setHasMore(hasMore)
|
||||||
|
|
||||||
|
proc getHasMore*(self: RecipientsModel): bool {.slot.} =
|
||||||
|
return self.hasMore
|
||||||
|
|
||||||
|
QtProperty[bool] hasMore:
|
||||||
|
read = getHasMore
|
||||||
|
notify = hasMoreChanged
|
||||||
|
|
@ -155,6 +155,7 @@ type
|
|||||||
ErrorCodeFilterCanceled,
|
ErrorCodeFilterCanceled,
|
||||||
ErrorCodeFilterFailed
|
ErrorCodeFilterFailed
|
||||||
|
|
||||||
|
# Mirrors services/wallet/activity/service.go FilterResponse
|
||||||
FilterResponse* = object
|
FilterResponse* = object
|
||||||
activities*: seq[ActivityEntry]
|
activities*: seq[ActivityEntry]
|
||||||
offset*: int
|
offset*: int
|
||||||
@ -209,5 +210,14 @@ rpc(filterActivityAsync, "wallet"):
|
|||||||
addresses: seq[string]
|
addresses: seq[string]
|
||||||
chainIds: seq[int]
|
chainIds: seq[int]
|
||||||
filter: ActivityFilter
|
filter: ActivityFilter
|
||||||
|
offset: int
|
||||||
|
limit: int
|
||||||
|
|
||||||
|
# see services/wallet/api.go GetAllRecipientsResponse
|
||||||
|
type GetAllRecipientsResponse* = object
|
||||||
|
addresses*: seq[string]
|
||||||
|
hasMore*: bool
|
||||||
|
|
||||||
|
rpc(getAllRecipients, "wallet"):
|
||||||
offset: int
|
offset: int
|
||||||
limit: int
|
limit: int
|
@ -33,6 +33,8 @@ Control {
|
|||||||
color: "white"
|
color: "white"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: controller.updateRecipientsModel()
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
|
|
||||||
@ -68,17 +70,6 @@ Control {
|
|||||||
}
|
}
|
||||||
controller.setFilterStatus(JSON.stringify(statuses))
|
controller.setFilterStatus(JSON.stringify(statuses))
|
||||||
|
|
||||||
// Counterparty addresses
|
|
||||||
var addresses = toAddressesInput.text.split(',')
|
|
||||||
if(addresses.length == 1 && addresses[0].trim() == "") {
|
|
||||||
addresses = []
|
|
||||||
} else {
|
|
||||||
for (var i = 0; i < addresses.length; i++) {
|
|
||||||
addresses[i] = padHexAddress(addresses[i].trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
controller.setFilterToAddresses(JSON.stringify(addresses))
|
|
||||||
|
|
||||||
// Involved addresses
|
// Involved addresses
|
||||||
var addresses = addressesInput.text.split(',')
|
var addresses = addressesInput.text.split(',')
|
||||||
if(addresses.length == 1 && addresses[0].trim() == "") {
|
if(addresses.length == 1 && addresses[0].trim() == "") {
|
||||||
@ -219,13 +210,17 @@ Control {
|
|||||||
delegate: ItemOnOffDelegate {}
|
delegate: ItemOnOffDelegate {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label { text: qsTr("To addresses") }
|
ComboBox {
|
||||||
TextField {
|
id: toAddressesComboBox
|
||||||
id: toAddressesInput
|
model: controller.recipientsModel
|
||||||
|
|
||||||
Layout.fillWidth: true
|
displayText: qsTr("Select TO") + (controller.recipientsModel.hasMore ? qsTr(" ...") : "")
|
||||||
|
|
||||||
placeholderText: qsTr("0x1234, 0x5678, ...")
|
currentIndex: -1
|
||||||
|
|
||||||
|
delegate: ItemOnOffDelegate {
|
||||||
|
textRole: "address"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
@ -305,6 +300,8 @@ Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
component ItemOnOffDelegate: Item {
|
component ItemOnOffDelegate: Item {
|
||||||
|
property string textRole: "text"
|
||||||
|
|
||||||
width: parent ? parent.width : 0
|
width: parent ? parent.width : 0
|
||||||
height: itemLayout.implicitHeight
|
height: itemLayout.implicitHeight
|
||||||
|
|
||||||
@ -315,7 +312,7 @@ Control {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
CheckBox { checked: entry.checked; onCheckedChanged: entry.checked = checked }
|
CheckBox { checked: entry.checked; onCheckedChanged: entry.checked = checked }
|
||||||
Label { text: entry.text }
|
Label { text: entry[textRole] }
|
||||||
RowLayout {}
|
RowLayout {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user