Skip to content

Commit

Permalink
feat(activity): WIP
Browse files Browse the repository at this point in the history
Prototype of displaying dynamic activity filter updates
  • Loading branch information
stefandunca committed Feb 7, 2024
1 parent ae16bd8 commit 9426e90
Show file tree
Hide file tree
Showing 12 changed files with 470 additions and 103 deletions.
58 changes: 50 additions & 8 deletions src/app/modules/main/wallet_section/activity/controller.nim
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ QtObject:
# call updateAssetsIdentities after updating chainIds
chainIds: seq[int]

# TODO #12120: refactor to sessionId and use the eventsHandler's sessionId
requestId: int32

collectiblesToTokenConverter: CollectiblesToTokenConverter
Expand Down Expand Up @@ -100,7 +101,7 @@ QtObject:
if metadata.symbolOut.isSome() or metadata.amountOut > 0:
result.outAmount = self.currencyService.parseCurrencyValue(metadata.symbolOut.get(""), metadata.amountOut)

proc backendToPresentation(self: Controller, backendEntities: seq[backend_activity.ActivityEntry]): seq[entry.ActivityEntry] =
proc backendToPresentation(self: Controller, backendEntities: seq[backend_activity.ActivityEntry], highlight: bool): seq[entry.ActivityEntry] =
let amountToCurrencyConvertor = proc(amount: UInt256, symbol: string): CurrencyAmount =
return currencyAmountToItem(self.currencyService.parseCurrencyValue(symbol, amount),
self.currencyService.getCurrencyFormat(symbol))
Expand All @@ -112,7 +113,7 @@ QtObject:
ae = entry.newMultiTransactionActivityEntry(backendEntry, extraData, amountToCurrencyConvertor)
of SimpleTransaction, PendingTransaction:
let extraData = self.buildTransactionExtraData(backendEntry)
ae = entry.newTransactionActivityEntry(backendEntry, self.addresses, extraData, amountToCurrencyConvertor)
ae = entry.newTransactionActivityEntry(backendEntry, self.addresses, extraData, amountToCurrencyConvertor, highlight)
result.add(ae)

proc fetchTxDetails*(self: Controller, entryIndex: int) {.slot.} =
Expand Down Expand Up @@ -151,14 +152,14 @@ QtObject:
error "error fetching activity entries: ", res.errorCode
return

let entries = self.backendToPresentation(res.activities)
let entries = self.backendToPresentation(res.activities, false)

self.model.setEntries(entries, res.offset, res.hasMore)

if len(entries) > 0:
self.eventsHandler.updateRelevantTimestamp(entries[len(entries) - 1].getTimestamp())

proc updateFilter*(self: Controller) {.slot.} =
proc startFilterSession*(self: Controller) {.slot.} =
self.status.setLoadingData(true)
self.status.setIsFilterDirty(false)

Expand All @@ -168,12 +169,38 @@ QtObject:
self.eventsHandler.updateSubscribedChainIDs(self.chainIds)
self.status.setNewDataAvailable(false)

let response = backend_activity.filterActivityAsync(self.requestId, self.addresses, self.allAddressesSelected, seq[backend_activity.ChainId](self.chainIds), self.currentActivityFilter, 0, FETCH_BATCH_COUNT_DEFAULT)
if response.error != nil:
error "error fetching activity entries: ", response.error
let (sessionId, ok) = backend_activity.newActivityFilterSession(self.addresses, self.allAddressesSelected, seq[backend_activity.ChainId](self.chainIds), self.currentActivityFilter, FETCH_BATCH_COUNT_DEFAULT)
echo "@dd sessionId: ", sessionId, " ok: ", ok
if not ok:
self.status.setLoadingData(false)
return

self.eventsHandler.setSessionId(sessionId)
self.requestId = sessionId.int32

# TODO #12120: deprecated, replace with [start|stop]FilterSession
proc updateFilter*(self: Controller) {.slot.} =
if self.requestId >= 0:
let res = backend_activity.stopActivityFilterSession(self.requestId)
if res.error != nil:
error "error stopping the previous session of activity fitlering: ", res.error

self.startFilterSession()
# self.status.setLoadingData(true)
# self.status.setIsFilterDirty(false)

# self.model.resetModel(@[])

# self.eventsHandler.updateSubscribedAddresses(self.addresses)
# self.eventsHandler.updateSubscribedChainIDs(self.chainIds)
# self.status.setNewDataAvailable(false)

# let response = backend_activity.filterActivityAsync(self.requestId, self.addresses, self.allAddressesSelected, 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.status.setLoadingData(false)
# return

proc loadMoreItems(self: Controller) {.slot.} =
self.status.setLoadingData(true)

Expand Down Expand Up @@ -241,6 +268,20 @@ QtObject:
self.model.updateEntries(entries)
)

self.eventsHandler.onFilteringSessionUpdated(proc (jn: JsonNode) =
echo "@dd onFilteringSessionUpdated: ", pretty(jn)
if jn.kind != JObject:
error "expected an object"

let res = fromJson(jn, backend_activity.SessionUpdate)

echo "@dd onFilteringSessionUpdated newEntries: ", res.newEntries.len

let entries = self.backendToPresentation(res.newEntries, true)

self.model.updateEntries(entries)
)

self.eventsHandler.onGetRecipientsDone(proc (jsonObj: JsonNode) =
defer: self.status.setLoadingRecipients(false)
let res = fromJson(jsonObj, backend_activity.GetRecipientsResponse)
Expand Down Expand Up @@ -282,14 +323,15 @@ QtObject:
self.status.setNewDataAvailable(true)
)

# TODO #12120: no need for hardcoded requestId with sessions
proc newController*(requestId: int32,
currencyService: currency_service.Service,
tokenService: token_service.Service,
events: EventEmitter,
collectiblesConverter: CollectiblesToTokenConverter): Controller =
new(result, delete)

result.requestId = requestId
result.requestId = -1 #requestId
result.model = newModel()
result.recipientsModel = newRecipientsModel()
result.collectiblesModel = newCollectiblesModel()
Expand Down
20 changes: 19 additions & 1 deletion src/app/modules/main/wallet_section/activity/entry.nim
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ QtObject:
nftName: string
nftImageURL: string

# true for entries that were changed/added in the current session
highlight: bool

proc setup(self: ActivityEntry) =
self.QObject.setup

Expand All @@ -54,7 +57,7 @@ QtObject:
)
result.setup()

proc newTransactionActivityEntry*(metadata: backend.ActivityEntry, fromAddresses: seq[string], extradata: ExtraData, valueConvertor: AmountToCurrencyConvertor): ActivityEntry =
proc newTransactionActivityEntry*(metadata: backend.ActivityEntry, fromAddresses: seq[string], extradata: ExtraData, valueConvertor: AmountToCurrencyConvertor, highlight: bool): ActivityEntry =
new(result, delete)
result.valueConvertor = valueConvertor
result.metadata = metadata
Expand All @@ -65,6 +68,7 @@ QtObject:
if result.isInTransactionType(): metadata.symbolIn.get("") else: metadata.symbolOut.get(""),
)
result.noAmount = newCurrencyAmount()
result.highlight = highlight

result.setup()

Expand Down Expand Up @@ -273,3 +277,17 @@ QtObject:

QtProperty[QVariant] amountCurrency:
read = getAmountCurrency

proc highlightChanged*(self: ActivityEntry) {.signal.}

proc getHighlight*(self: ActivityEntry): bool {.slot.} =
return self.highlight

proc doneHighlighting*(self: ActivityEntry) {.slot.} =
if self.highlight:
self.highlight = false
self.highlightChanged()

QtProperty[bool] highlight:
read = getHighlight
notify = highlightChanged
15 changes: 13 additions & 2 deletions src/app/modules/main/wallet_section/activity/events_handler.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ QtObject:
walletEventHandlers: Table[string, WalletEventCallbackProc]

# Ignore events older than this relevantTimestamp
# TODO #12120: remove this after dropping individual events and only using incremental updates events
relevantTimestamp: int
subscribedAddresses: HashSet[string]
subscribedChainIDs: HashSet[int]
newDataAvailableFn: proc()

# TODO #12120: Optional[int], getter and setter
requestId: int

proc setup(self: EventsHandler) =
Expand All @@ -34,12 +36,17 @@ QtObject:
proc delete*(self: EventsHandler) =
self.QObject.delete

# TODO #12120: replace with session update event
proc onFilteringDone*(self: EventsHandler, handler: EventCallbackProc) =
self.eventHandlers[backend_activity.eventActivityFilteringDone] = handler

# TODO #12120: replace with session update event
proc onFilteringUpdateDone*(self: EventsHandler, handler: EventCallbackProc) =
self.eventHandlers[backend_activity.eventActivityFilteringUpdate] = handler

proc onFilteringSessionUpdated*(self: EventsHandler, handler: EventCallbackProc) =
self.eventHandlers[backend_activity.eventActivitySessionUpdated] = handler

proc onGetRecipientsDone*(self: EventsHandler, handler: EventCallbackProc) =
self.eventHandlers[backend_activity.eventActivityGetRecipientsDone] = handler

Expand Down Expand Up @@ -98,9 +105,10 @@ QtObject:

# TODO #12120: Replace these specific events with incremental updates events
self.walletEventHandlers[EventNewTransfers] = newDataAvailableCallback
self.walletEventHandlers[EventPendingTransactionUpdate] = newDataAvailableCallback
# self.walletEventHandlers[EventPendingTransactionUpdate] = newDataAvailableCallback
self.walletEventHandlers[EventMTTransactionUpdate] = newDataAvailableCallback

# TODO #12120: no need for hardcoded requestId with sessions
proc newEventsHandler*(requestId: int, events: EventEmitter): EventsHandler =
new(result, delete)

Expand All @@ -110,7 +118,7 @@ QtObject:
result.subscribedAddresses = initHashSet[string]()
result.subscribedChainIDs = initHashSet[int]()

result.requestId = requestId
result.requestId = -1 # requestId

result.setup()

Expand All @@ -134,3 +142,6 @@ QtObject:
self.subscribedChainIDs.clear()
for chainID in chainIDs:
self.subscribedChainIDs.incl(chainID)

proc setSessionId*(self: EventsHandler, sessionId: int) =
self.requestId = sessionId
12 changes: 12 additions & 0 deletions src/app/modules/main/wallet_section/activity/model.nim
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,18 @@ QtObject:
self.countChanged()
self.setHasMore(hasMore)

# TODO #12120: add indexes
proc updateEntries*(self: Model, newEntries: seq[entry.ActivityEntry]) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete

self.beginInsertRows(parentModelIndex, 0, newEntries.len - 1)
self.entries = newEntries & self.entries
self.endInsertRows()

self.countChanged()
# hasMore flag should not be change by updates

proc sameIdentity(e: entry.ActivityEntry, d: backend.Data): bool =
let m = e.getMetadata()
if m.getPayloadType() != d.payloadType:
Expand Down
65 changes: 61 additions & 4 deletions src/backend/activity.nim
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const eventActivityGetOldestTimestampDone*: string = "wallet-activity-get-oldest
const eventActivityFetchTransactionDetails*: string = "wallet-activity-fetch-transaction-details-result"
const eventActivityGetCollectiblesDone*: string = "wallet-activity-get-collectibles"

const eventActivitySessionUpdated*: string = "wallet-activity-session-updated"

type
Period* = object
startTimestamp*: int
Expand Down Expand Up @@ -74,6 +76,17 @@ proc fromJson[T](jsonObj: JsonNode, TT: typedesc[Option[T]]): Option[T] =
else:
return none(T)

proc fromJson[T](jsonObj: JsonNode, TT: typedesc[seq[T]]): seq[T] =
if jsonObj.kind != JArray:
error "Expected array, got: ", jsonObj.kind
return @[]

result = newSeq[T](jsonObj.len)
for i, elem in jsonObj.getElems():
result[i] = fromJson(elem, T)

return result

proc `%`*(at: ActivityType): JsonNode {.inline.} =
return newJInt(ord(at))

Expand Down Expand Up @@ -241,8 +254,6 @@ proc `$`*(pt: ProtocolType): string {.inline.} =
return "Hop"
of Uniswap:
return "Uniswap"
else:
return ""

# Mirrors status-go/services/wallet/activity/activity.go TransferType
type
Expand Down Expand Up @@ -319,13 +330,20 @@ type
ErrorCodeTaskCanceled,
ErrorCodeFailed

# TODO #12120: Replace it with SessionUpdate
# Mirrors services/wallet/activity/service.go FilterResponse
FilterResponse* = object
activities*: seq[ActivityEntry]
offset*: int
hasMore*: bool
errorCode*: ErrorCode

# Mirrors services/wallet/activity/session.go SessionUpdate
SessionUpdate* = object
newEntries*: seq[ActivityEntry]
removed*: seq[Data]
updated*: seq[Data]

proc getPayloadType*(ae: ActivityEntry): PayloadType =
return ae.payloadType

Expand Down Expand Up @@ -423,8 +441,8 @@ proc fromJson*(e: JsonNode, T: typedesc[ActivityEntry]): ActivityEntry {.inline.
activityType: data.activityType.get(),
activityStatus: data.activityStatus.get(),
timestamp: data.timestamp.get(),
amountOut: data.amountOut.get(),
amountIn: data.amountIn.get(),
amountOut: if data.amountOut.isSome: data.amountOut.get() else: 0.u256,
amountIn: if data.amountIn.isSome: data.amountIn.get() else: 0.u256,
tokenOut: data.tokenOut,
tokenIn: data.tokenIn,
symbolOut: data.symbolOut,
Expand Down Expand Up @@ -478,6 +496,19 @@ proc fromJson*(e: JsonNode, T: typedesc[FilterResponse]): FilterResponse {.inlin
errorCode: ErrorCode(e["errorCode"].getInt())
)

proc fromJson*(e: JsonNode, T: typedesc[SessionUpdate]): SessionUpdate {.inline.} =
var newEntries: seq[ActivityEntry]
if e.hasKey("newEntries"):
let jsonEntries = e["newEntries"]
if jsonEntries.kind == JNull:
newEntries = @[]
elif jsonEntries.kind == JArray:
newEntries = fromJson(jsonEntries, seq[ActivityEntry])

result = T(
newEntries: newEntries
)

rpc(filterActivityAsync, "wallet"):
requestId: int32
addresses: seq[string]
Expand All @@ -487,6 +518,32 @@ rpc(filterActivityAsync, "wallet"):
offset: int
limit: int

rpc(startActivityFilterSession, "wallet"):
addresses: seq[string]
allAddresses: bool
chainIds: seq[ChainId]
filter: ActivityFilter
count: int

rpc(stopActivityFilterSession, "wallet"):
sessionId: int

# returns (sessionId, success)
proc newActivityFilterSession*(
addresses: seq[string],
allAddresses: bool,
chainIds: seq[ChainId],
filter: ActivityFilter,
count: int,
): (int, bool) {.inline.} =
let res = startActivityFilterSession(addresses, allAddresses, chainIds, filter, count)
if res.error != nil:
error "error starting a new session of activity fitlering: ", res.error
return (-1, false)
var test: json.JsonNode
test = res.result
return (test.getInt(), true)

# see services/wallet/activity/service.go GetRecipientsResponse
type GetRecipientsResponse* = object
addresses*: seq[string]
Expand Down
Loading

0 comments on commit 9426e90

Please sign in to comment.