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 entry
|
||||
import recipients_model
|
||||
|
||||
import ../transactions/item
|
||||
import ../transactions/module as transactions_module
|
||||
|
@ -21,11 +22,13 @@ proc toRef*[T](obj: T): ref T =
|
|||
result[] = obj
|
||||
|
||||
const FETCH_BATCH_COUNT_DEFAULT = 10
|
||||
const FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT = 2000
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Controller* = ref object of QObject
|
||||
model: Model
|
||||
recipientsModel: RecipientsModel
|
||||
transactionsModule: transactions_module.AccessInterface
|
||||
currentActivityFilter: backend_activity.ActivityFilter
|
||||
|
||||
|
@ -50,6 +53,12 @@ QtObject:
|
|||
QtProperty[QVariant] model:
|
||||
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] =
|
||||
var multiTransactionsIds: seq[int] = @[]
|
||||
var transactionIdentities: seq[backend.TransactionIdentity] = @[]
|
||||
|
@ -186,6 +195,7 @@ QtObject:
|
|||
proc newController*(transactionsModule: transactions_module.AccessInterface, events: EventEmitter): Controller =
|
||||
new(result, delete)
|
||||
result.model = newModel()
|
||||
result.recipientsModel = newRecipientsModel()
|
||||
result.transactionsModule = transactionsModule
|
||||
result.currentActivityFilter = backend_activity.getIncludeAllActivityFilter()
|
||||
result.events = events
|
||||
|
@ -256,10 +266,10 @@ QtObject:
|
|||
addresses[i] = addressesJson[i].getStr()
|
||||
|
||||
self.addresses = addresses
|
||||
|
||||
|
||||
proc setFilterAddresses*(self: Controller, addresses: seq[string]) =
|
||||
self.addresses = addresses
|
||||
|
||||
|
||||
proc setFilterToAddresses*(self: Controller, addresses: seq[string]) =
|
||||
self.currentActivityFilter.counterpartyAddresses = addresses
|
||||
|
||||
|
@ -291,4 +301,22 @@ QtObject:
|
|||
|
||||
QtProperty[int] errorCode:
|
||||
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,
|
||||
ErrorCodeFilterFailed
|
||||
|
||||
# Mirrors services/wallet/activity/service.go FilterResponse
|
||||
FilterResponse* = object
|
||||
activities*: seq[ActivityEntry]
|
||||
offset*: int
|
||||
|
@ -209,5 +210,14 @@ rpc(filterActivityAsync, "wallet"):
|
|||
addresses: seq[string]
|
||||
chainIds: seq[int]
|
||||
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
|
||||
limit: int
|
|
@ -33,6 +33,8 @@ Control {
|
|||
color: "white"
|
||||
}
|
||||
|
||||
Component.onCompleted: controller.updateRecipientsModel()
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
|
@ -68,17 +70,6 @@ Control {
|
|||
}
|
||||
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
|
||||
var addresses = addressesInput.text.split(',')
|
||||
if(addresses.length == 1 && addresses[0].trim() == "") {
|
||||
|
@ -219,13 +210,17 @@ Control {
|
|||
delegate: ItemOnOffDelegate {}
|
||||
}
|
||||
|
||||
Label { text: qsTr("To addresses") }
|
||||
TextField {
|
||||
id: toAddressesInput
|
||||
ComboBox {
|
||||
id: toAddressesComboBox
|
||||
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 {
|
||||
|
@ -305,6 +300,8 @@ Control {
|
|||
}
|
||||
|
||||
component ItemOnOffDelegate: Item {
|
||||
property string textRole: "text"
|
||||
|
||||
width: parent ? parent.width : 0
|
||||
height: itemLayout.implicitHeight
|
||||
|
||||
|
@ -315,7 +312,7 @@ Control {
|
|||
anchors.fill: parent
|
||||
|
||||
CheckBox { checked: entry.checked; onCheckedChanged: entry.checked = checked }
|
||||
Label { text: entry.text }
|
||||
Label { text: entry[textRole] }
|
||||
RowLayout {}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue