mirror of
https://github.com/status-im/status-desktop.git
synced 2025-03-04 00:11:12 +00:00
chore(wallet) extract responsibilities from activity.Controller
Extract processing of Events and Status keeping responsibilities from activity.Controller Updates #11233
This commit is contained in:
parent
24cdab41c6
commit
d17f2c70f1
@ -1,18 +1,19 @@
|
||||
import NimQml, logging, std/json, sequtils, sugar, options, strutils, times
|
||||
import tables, stint, sets, atomics
|
||||
import NimQml, logging, std/json, sequtils, sugar, options, strutils
|
||||
import tables, stint, sets
|
||||
|
||||
import model
|
||||
import entry
|
||||
import recipients_model
|
||||
import events_handler
|
||||
import status
|
||||
|
||||
import web3/conversions
|
||||
|
||||
import app/core/eventemitter
|
||||
|
||||
import ../transactions/item
|
||||
import ../transactions/module as transactions_module
|
||||
|
||||
import app/core/eventemitter
|
||||
import app/core/signals/types
|
||||
|
||||
import backend/activity as backend_activity
|
||||
import backend/backend as backend
|
||||
import backend/transactions
|
||||
@ -28,8 +29,6 @@ proc toRef*[T](obj: T): ref T =
|
||||
const FETCH_BATCH_COUNT_DEFAULT = 10
|
||||
const FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT = 2000
|
||||
|
||||
type EventCallbackProc = proc (eventObject: JsonNode)
|
||||
|
||||
# TODO: implement passing of collectibles
|
||||
QtObject:
|
||||
type
|
||||
@ -41,15 +40,8 @@ QtObject:
|
||||
currencyService: currency_service.Service
|
||||
tokenService: token_service.Service
|
||||
|
||||
events: EventEmitter
|
||||
# Event name and handler pairs
|
||||
eventHandlers: Table[string, EventCallbackProc]
|
||||
|
||||
loadingData: Atomic[int]
|
||||
errorCode: backend_activity.ErrorCode
|
||||
|
||||
loadingRecipients: Atomic[int]
|
||||
loadingStartTimestamp: Atomic[int]
|
||||
eventsHandler: EventsHandler
|
||||
status: Status
|
||||
|
||||
# call updateAssetsIdentities after updating filterTokenCodes
|
||||
filterTokenCodes: HashSet[string]
|
||||
@ -58,8 +50,6 @@ QtObject:
|
||||
# call updateAssetsIdentities after updating chainIds
|
||||
chainIds: seq[int]
|
||||
|
||||
startTimestamp: int
|
||||
|
||||
proc setup(self: Controller) =
|
||||
self.QObject.setup
|
||||
|
||||
@ -174,36 +164,12 @@ QtObject:
|
||||
error "failed to find pending transaction with identity: ", identity
|
||||
ptIndex += 1
|
||||
|
||||
proc loadingDataChanged*(self: Controller) {.signal.}
|
||||
|
||||
proc setLoadingData(self: Controller, loadingData: bool) =
|
||||
discard fetchAdd(self.loadingData, if loadingData: 1 else: -1)
|
||||
self.loadingDataChanged()
|
||||
|
||||
proc loadingRecipientsChanged*(self: Controller) {.signal.}
|
||||
|
||||
proc setLoadingRecipients(self: Controller, loadingData: bool) =
|
||||
discard fetchAdd(self.loadingRecipients, if loadingData: 1 else: -1)
|
||||
self.loadingRecipientsChanged()
|
||||
|
||||
proc loadingStartTimestampChanged*(self: Controller) {.signal.}
|
||||
|
||||
proc setLoadingStartTimestamp(self: Controller, loadingData: bool) =
|
||||
discard fetchAdd(self.loadingStartTimestamp, if loadingData: 1 else: -1)
|
||||
self.loadingStartTimestampChanged()
|
||||
|
||||
proc errorCodeChanged*(self: Controller) {.signal.}
|
||||
|
||||
proc setErrorCode(self: Controller, errorCode: int) =
|
||||
self.errorCode = backend_activity.ErrorCode(errorCode)
|
||||
self.errorCodeChanged()
|
||||
|
||||
proc processResponse(self: Controller, response: JsonNode) =
|
||||
defer: self.setLoadingData(false)
|
||||
defer: self.status.setLoadingData(false)
|
||||
|
||||
let res = fromJson(response, backend_activity.FilterResponse)
|
||||
|
||||
defer: self.setErrorCode(res.errorCode.int)
|
||||
defer: self.status.setErrorCode(res.errorCode.int)
|
||||
|
||||
if res.errorCode != ErrorCodeSuccess:
|
||||
error "error fetching activity entries: ", res.errorCode
|
||||
@ -213,21 +179,21 @@ QtObject:
|
||||
self.model.setEntries(entries, res.offset, res.hasMore)
|
||||
|
||||
proc updateFilter*(self: Controller) {.slot.} =
|
||||
self.setLoadingData(true)
|
||||
self.status.setLoadingData(true)
|
||||
self.model.resetModel(@[])
|
||||
|
||||
let response = backend_activity.filterActivityAsync(self.addresses, seq[backend_activity.ChainId](self.chainIds), self.currentActivityFilter, 0, FETCH_BATCH_COUNT_DEFAULT)
|
||||
if response.error != nil:
|
||||
error "error fetching activity entries: ", response.error
|
||||
self.setLoadingData(false)
|
||||
self.status.setLoadingData(false)
|
||||
return
|
||||
|
||||
proc loadMoreItems(self: Controller) {.slot.} =
|
||||
self.setLoadingData(true)
|
||||
self.status.setLoadingData(true)
|
||||
|
||||
let response = backend_activity.filterActivityAsync(self.addresses, seq[backend_activity.ChainId](self.chainIds), self.currentActivityFilter, self.model.getCount(), FETCH_BATCH_COUNT_DEFAULT)
|
||||
if response.error != nil:
|
||||
self.setLoadingData(false)
|
||||
self.status.setLoadingData(false)
|
||||
error "error fetching activity entries: ", response.error
|
||||
return
|
||||
|
||||
@ -246,40 +212,24 @@ QtObject:
|
||||
|
||||
self.currentActivityFilter.types = types
|
||||
|
||||
proc startTimestampChanged*(self: Controller) {.signal.}
|
||||
|
||||
# Call this method on every data update (ideally only if updates are before the last timestamp retrieved)
|
||||
# This depends on self.addresses being set, call on every address change
|
||||
proc updateStartTimestamp*(self: Controller) {.slot.} =
|
||||
self.setLoadingStartTimestamp(true)
|
||||
self.status.setLoadingStartTimestamp(true)
|
||||
|
||||
let resJson = backend_activity.getOldestActivityTimestampAsync(self.addresses)
|
||||
if resJson.error != nil:
|
||||
self.setLoadingStartTimestamp(false)
|
||||
self.status.setLoadingStartTimestamp(false)
|
||||
error "error requesting oldest activity timestamp: ", resJson.error
|
||||
return
|
||||
|
||||
proc handleApiEvents(self: Controller, e: Args) =
|
||||
var data = WalletSignal(e)
|
||||
|
||||
if self.eventHandlers.hasKey(data.eventType):
|
||||
var responseJson: JsonNode
|
||||
responseJson = parseJson(data.message)
|
||||
|
||||
if responseJson.kind != JObject:
|
||||
error "unexpected json type", responseJson.kind
|
||||
return
|
||||
let callback = self.eventHandlers[data.eventType]
|
||||
callback(responseJson)
|
||||
else:
|
||||
discard
|
||||
|
||||
proc setupEventHandlers(self: Controller) =
|
||||
self.eventHandlers[backend_activity.eventActivityFilteringDone] = proc (jsonObj: JsonNode) =
|
||||
self.eventsHandler.onFilteringDone(proc (jsonObj: JsonNode) =
|
||||
self.processResponse(jsonObj)
|
||||
)
|
||||
|
||||
self.eventHandlers[backend_activity.eventActivityGetRecipientsDone] = proc (jsonObj: JsonNode) =
|
||||
defer: self.setLoadingRecipients(false)
|
||||
self.eventsHandler.onGetRecipientsDone(proc (jsonObj: JsonNode) =
|
||||
defer: self.status.setLoadingRecipients(false)
|
||||
let res = fromJson(jsonObj, backend_activity.GetRecipientsResponse)
|
||||
|
||||
if res.errorCode != ErrorCodeSuccess:
|
||||
@ -287,33 +237,35 @@ QtObject:
|
||||
return
|
||||
|
||||
self.recipientsModel.addAddresses(res.addresses, res.offset, res.hasMore)
|
||||
)
|
||||
|
||||
self.eventHandlers[backend_activity.eventActivityGetOldestTimestampDone] = proc (jsonObj: JsonNode) =
|
||||
defer: self.setLoadingStartTimestamp(false)
|
||||
self.eventsHandler.onGetOldestTimestampDone(proc (jsonObj: JsonNode) =
|
||||
defer: self.status.setLoadingStartTimestamp(false)
|
||||
let res = fromJson(jsonObj, backend_activity.GetOldestTimestampResponse)
|
||||
|
||||
if res.errorCode != ErrorCodeSuccess:
|
||||
error "error fetching start timestamp: ", res.errorCode
|
||||
return
|
||||
|
||||
self.startTimestamp = res.timestamp
|
||||
self.startTimestampChanged()
|
||||
self.status.setStartTimestamp(res.timestamp)
|
||||
)
|
||||
|
||||
proc newController*(transactionsModule: transactions_module.AccessInterface,
|
||||
currencyService: currency_service.Service,
|
||||
tokenService: token_service.Service,
|
||||
events: EventEmitter): Controller =
|
||||
new(result, delete)
|
||||
|
||||
result.model = newModel()
|
||||
result.recipientsModel = newRecipientsModel()
|
||||
result.transactionsModule = transactionsModule
|
||||
result.tokenService = tokenService
|
||||
result.currentActivityFilter = backend_activity.getIncludeAllActivityFilter()
|
||||
result.events = events
|
||||
result.eventHandlers = initTable[string, EventCallbackProc]()
|
||||
result.currencyService = currencyService
|
||||
|
||||
result.errorCode = backend_activity.ErrorCode.ErrorCodeSuccess
|
||||
result.eventsHandler = newEventsHandler(events)
|
||||
result.status = newStatus()
|
||||
|
||||
result.currencyService = currencyService
|
||||
|
||||
result.filterTokenCodes = initHashSet[string]()
|
||||
|
||||
@ -323,10 +275,6 @@ QtObject:
|
||||
result.setup()
|
||||
|
||||
result.setupEventHandlers()
|
||||
let controller = result
|
||||
result.events.on(SignalType.Wallet.event, proc(e: Args) =
|
||||
controller.handleApiEvents(e)
|
||||
)
|
||||
|
||||
proc setFilterStatus*(self: Controller, statusesArrayJsonString: string) {.slot.} =
|
||||
let statusesJson = parseJson(statusesArrayJsonString)
|
||||
@ -397,67 +345,35 @@ QtObject:
|
||||
|
||||
self.updateAssetsIdentities()
|
||||
|
||||
proc getLoadingData*(self: Controller): bool {.slot.} =
|
||||
return load(self.loadingData) > 0
|
||||
|
||||
QtProperty[bool] loadingData:
|
||||
read = getLoadingData
|
||||
notify = loadingDataChanged
|
||||
|
||||
proc getErrorCode*(self: Controller): int {.slot.} =
|
||||
return self.errorCode.int
|
||||
|
||||
QtProperty[int] errorCode:
|
||||
read = getErrorCode
|
||||
notify = errorCodeChanged
|
||||
|
||||
proc getLoadingRecipients*(self: Controller): bool {.slot.} =
|
||||
return load(self.loadingRecipients) > 0
|
||||
|
||||
QtProperty[bool] loadingRecipients:
|
||||
read = getLoadingRecipients
|
||||
notify = loadingRecipientsChanged
|
||||
|
||||
proc getLoadingStartTimestamp*(self: Controller): bool {.slot.} =
|
||||
return load(self.loadingStartTimestamp) > 0
|
||||
|
||||
QtProperty[bool] loadingStartTimestamp:
|
||||
read = getLoadingStartTimestamp
|
||||
notify = loadingStartTimestampChanged
|
||||
|
||||
proc updateRecipientsModel*(self: Controller) {.slot.} =
|
||||
self.setLoadingRecipients(true)
|
||||
self.status.setLoadingRecipients(true)
|
||||
let res = backend_activity.getRecipientsAsync(0, FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)
|
||||
if res.error != nil or res.result.kind != JBool:
|
||||
self.setLoadingRecipients(false)
|
||||
self.status.setLoadingRecipients(false)
|
||||
error "error fetching recipients: ", res.error, "; kind ", res.result.kind
|
||||
return
|
||||
|
||||
# If the request was enqueued and already waiting for a response, we don't need to do anything
|
||||
if res.result.getBool():
|
||||
self.setLoadingRecipients(false)
|
||||
self.status.setLoadingRecipients(false)
|
||||
|
||||
proc loadMoreRecipients(self: Controller) {.slot.} =
|
||||
self.setLoadingRecipients(true)
|
||||
self.status.setLoadingRecipients(true)
|
||||
let res = backend_activity.getRecipientsAsync(self.recipientsModel.getCount(), FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)
|
||||
if res.error != nil:
|
||||
self.setLoadingRecipients(false)
|
||||
self.status.setLoadingRecipients(false)
|
||||
error "error fetching more recipient entries: ", res.error
|
||||
return
|
||||
|
||||
# If the request was enqueued and waiting for an answer, we don't need to do anything
|
||||
if res.result.getBool():
|
||||
self.setLoadingRecipients(false)
|
||||
|
||||
proc getStartTimestamp*(self: Controller): int {.slot.} =
|
||||
return if self.startTimestamp > 0:
|
||||
self.startTimestamp
|
||||
else:
|
||||
int(times.parse("2000-01-01", "yyyy-MM-dd").toTime().toUnix())
|
||||
|
||||
QtProperty[int] startTimestamp:
|
||||
read = getStartTimestamp
|
||||
notify = startTimestampChanged
|
||||
self.status.setLoadingRecipients(false)
|
||||
|
||||
proc updateFilterBase(self: Controller) {.slot.} =
|
||||
self.updateStartTimestamp()
|
||||
|
||||
proc getStatus*(self: Controller): QVariant {.slot.} =
|
||||
return newQVariant(self.status)
|
||||
|
||||
QtProperty[QVariant] status:
|
||||
read = getStatus
|
@ -0,0 +1,65 @@
|
||||
import NimQml, logging, std/json, sequtils, strutils
|
||||
import tables, stint, sets
|
||||
|
||||
import model
|
||||
import entry
|
||||
import recipients_model
|
||||
|
||||
import web3/conversions
|
||||
|
||||
import app/core/eventemitter
|
||||
import app/core/signals/types
|
||||
|
||||
import backend/activity as backend_activity
|
||||
|
||||
type EventCallbackProc = proc (eventObject: JsonNode)
|
||||
|
||||
# EventsHandler responsible for catching activity related backend events and reporting them
|
||||
QtObject:
|
||||
type
|
||||
EventsHandler* = ref object of QObject
|
||||
events: EventEmitter
|
||||
# Event name and handler pairs
|
||||
eventHandlers: Table[string, EventCallbackProc]
|
||||
|
||||
proc setup(self: EventsHandler) =
|
||||
self.QObject.setup
|
||||
|
||||
proc delete*(self: EventsHandler) =
|
||||
self.QObject.delete
|
||||
|
||||
proc onFilteringDone*(self: EventsHandler, handler: EventCallbackProc) =
|
||||
self.eventHandlers[backend_activity.eventActivityFilteringDone] = handler
|
||||
|
||||
proc onGetRecipientsDone*(self: EventsHandler, handler: EventCallbackProc) =
|
||||
self.eventHandlers[backend_activity.eventActivityGetRecipientsDone] = handler
|
||||
|
||||
proc onGetOldestTimestampDone*(self: EventsHandler, handler: EventCallbackProc) =
|
||||
self.eventHandlers[backend_activity.eventActivityGetOldestTimestampDone] = handler
|
||||
|
||||
proc handleApiEvents(self: EventsHandler, e: Args) =
|
||||
var data = WalletSignal(e)
|
||||
|
||||
if self.eventHandlers.hasKey(data.eventType):
|
||||
var responseJson: JsonNode
|
||||
responseJson = parseJson(data.message)
|
||||
|
||||
if responseJson.kind != JObject:
|
||||
error "unexpected json type", responseJson.kind
|
||||
return
|
||||
let callback = self.eventHandlers[data.eventType]
|
||||
callback(responseJson)
|
||||
else:
|
||||
discard
|
||||
|
||||
proc newEventsHandler*(events: EventEmitter): EventsHandler =
|
||||
new(result, delete)
|
||||
result.events = events
|
||||
result.eventHandlers = initTable[string, EventCallbackProc]()
|
||||
|
||||
result.setup()
|
||||
|
||||
let eventsHandler = result
|
||||
result.events.on(SignalType.Wallet.event, proc(e: Args) =
|
||||
eventsHandler.handleApiEvents(e)
|
||||
)
|
99
src/app/modules/main/wallet_section/activity/status.nim
Normal file
99
src/app/modules/main/wallet_section/activity/status.nim
Normal file
@ -0,0 +1,99 @@
|
||||
import NimQml, std/json, sequtils, strutils, times
|
||||
import tables, stint, sets, atomics
|
||||
|
||||
import web3/conversions
|
||||
|
||||
import app/core/signals/types
|
||||
|
||||
import backend/activity as backend_activity
|
||||
|
||||
# Status's responsibility is to keep track and report the general state of the backend
|
||||
QtObject:
|
||||
type
|
||||
Status* = ref object of QObject
|
||||
loadingData: Atomic[int]
|
||||
errorCode: backend_activity.ErrorCode
|
||||
|
||||
loadingRecipients: Atomic[int]
|
||||
loadingStartTimestamp: Atomic[int]
|
||||
|
||||
startTimestamp: int
|
||||
|
||||
proc setup(self: Status) =
|
||||
self.QObject.setup
|
||||
|
||||
proc delete*(self: Status) =
|
||||
self.QObject.delete
|
||||
|
||||
proc loadingDataChanged*(self: Status) {.signal.}
|
||||
|
||||
proc setLoadingData*(self: Status, loadingData: bool) =
|
||||
discard fetchAdd(self.loadingData, if loadingData: 1 else: -1)
|
||||
self.loadingDataChanged()
|
||||
|
||||
proc loadingRecipientsChanged*(self: Status) {.signal.}
|
||||
|
||||
proc setLoadingRecipients*(self: Status, loadingData: bool) =
|
||||
discard fetchAdd(self.loadingRecipients, if loadingData: 1 else: -1)
|
||||
self.loadingRecipientsChanged()
|
||||
|
||||
proc loadingStartTimestampChanged*(self: Status) {.signal.}
|
||||
|
||||
proc setLoadingStartTimestamp*(self: Status, loadingData: bool) =
|
||||
discard fetchAdd(self.loadingStartTimestamp, if loadingData: 1 else: -1)
|
||||
self.loadingStartTimestampChanged()
|
||||
|
||||
proc errorCodeChanged*(self: Status) {.signal.}
|
||||
|
||||
proc setErrorCode*(self: Status, errorCode: int) =
|
||||
self.errorCode = backend_activity.ErrorCode(errorCode)
|
||||
self.errorCodeChanged()
|
||||
|
||||
proc newStatus*(): Status =
|
||||
new(result, delete)
|
||||
|
||||
result.errorCode = backend_activity.ErrorCode.ErrorCodeSuccess
|
||||
|
||||
result.setup()
|
||||
|
||||
proc getLoadingData*(self: Status): bool {.slot.} =
|
||||
return load(self.loadingData) > 0
|
||||
|
||||
QtProperty[bool] loadingData:
|
||||
read = getLoadingData
|
||||
notify = loadingDataChanged
|
||||
|
||||
proc getErrorCode*(self: Status): int {.slot.} =
|
||||
return self.errorCode.int
|
||||
|
||||
QtProperty[int] errorCode:
|
||||
read = getErrorCode
|
||||
notify = errorCodeChanged
|
||||
|
||||
proc getLoadingRecipients*(self: Status): bool {.slot.} =
|
||||
return load(self.loadingRecipients) > 0
|
||||
|
||||
QtProperty[bool] loadingRecipients:
|
||||
read = getLoadingRecipients
|
||||
notify = loadingRecipientsChanged
|
||||
|
||||
proc getLoadingStartTimestamp*(self: Status): bool {.slot.} =
|
||||
return load(self.loadingStartTimestamp) > 0
|
||||
|
||||
QtProperty[bool] loadingStartTimestamp:
|
||||
read = getLoadingStartTimestamp
|
||||
notify = loadingStartTimestampChanged
|
||||
|
||||
proc startTimestampChanged*(self: Status) {.signal.}
|
||||
|
||||
proc setStartTimestamp*(self: Status, startTimestamp: int) =
|
||||
self.startTimestamp = startTimestamp
|
||||
self.startTimestampChanged()
|
||||
|
||||
proc getStartTimestamp*(self: Status): int {.slot.} =
|
||||
return if self.startTimestamp > 0: self.startTimestamp
|
||||
else: int(times.parse("2000-01-01", "yyyy-MM-dd").toTime().toUnix())
|
||||
|
||||
QtProperty[int] startTimestamp:
|
||||
read = getStartTimestamp
|
||||
notify = startTimestampChanged
|
@ -21,7 +21,7 @@ QtObject {
|
||||
|
||||
// Time filters
|
||||
property int selectedTime: Constants.TransactionTimePeriod.All
|
||||
property double fromTimestamp: activityController.startTimestamp * 1000
|
||||
property double fromTimestamp: activityController.status.startTimestamp * 1000
|
||||
property double toTimestamp: new Date().valueOf()
|
||||
function setSelectedTimestamp(selcTime) {
|
||||
selectedTime = selcTime
|
||||
@ -137,7 +137,7 @@ QtObject {
|
||||
|
||||
|
||||
property var recentsList: activityController.recipientsModel
|
||||
property bool loadingRecipients: activityController.loadingRecipients
|
||||
property bool loadingRecipients: activityController.status.loadingRecipients
|
||||
property var recentsFilters: []
|
||||
function updateRecipientsModel() {
|
||||
activityController.updateRecipientsModel()
|
||||
@ -202,7 +202,7 @@ QtObject {
|
||||
|
||||
function resetAllFilters() {
|
||||
selectedTime = Constants.TransactionTimePeriod.All
|
||||
fromTimestamp = activityController.startTimestamp * 1000
|
||||
fromTimestamp = activityController.status.startTimestamp * 1000
|
||||
toTimestamp = new Date().valueOf()
|
||||
activityController.setFilterTime(fromTimestamp/1000, toTimestamp/1000)
|
||||
|
||||
|
@ -38,7 +38,7 @@ QtObject {
|
||||
property var history: typeof walletSectionTransactions !== "undefined" ? walletSectionTransactions
|
||||
: null
|
||||
property var historyTransactions: Global.appIsReady? walletSection.activityController.model : null
|
||||
readonly property bool loadingHistoryTransactions: Global.appIsReady && walletSection.activityController.loadingData
|
||||
readonly property bool loadingHistoryTransactions: Global.appIsReady && walletSection.activityController.status.loadingData
|
||||
property bool isNonArchivalNode: history ? history.isNonArchivalNode
|
||||
: false
|
||||
property var marketValueStore: TokenMarketValuesStore{}
|
||||
|
Loading…
x
Reference in New Issue
Block a user