mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-21 11:08:55 +00:00
chore(wallet) remove transactions module
Bump Status GO to support session based activity requests Transaction module was replaced by activity module, this change removes the old code. Details: - Remove transaction.Item and use the DTO directly - Replace the still using missing functionality - Remove old way of fetching transactions in response to the history event - Use activity filter to provide history for "recents" in Send. Closes #11339
This commit is contained in:
parent
515028222e
commit
bf4af3d7d4
@ -1,4 +1,4 @@
|
||||
import json
|
||||
import json, options
|
||||
|
||||
import base
|
||||
import signal_type
|
||||
@ -13,19 +13,24 @@ type WalletSignal* = ref object of Signal
|
||||
at*: int
|
||||
chainID*: int
|
||||
message*: string
|
||||
requestId*: Option[int]
|
||||
|
||||
proc fromEvent*(T: type WalletSignal, jsonSignal: JsonNode): WalletSignal =
|
||||
result = WalletSignal()
|
||||
result.signalType = SignalType.Wallet
|
||||
result.content = $jsonSignal
|
||||
if jsonSignal["event"].kind != JNull:
|
||||
result.eventType = jsonSignal["event"]["type"].getStr
|
||||
result.blockNumber = jsonSignal["event"]{"blockNumber"}.getInt
|
||||
result.erc20 = jsonSignal["event"]{"erc20"}.getBool
|
||||
let event = jsonSignal["event"]
|
||||
if event.kind != JNull:
|
||||
result.eventType = event["type"].getStr
|
||||
result.blockNumber = event{"blockNumber"}.getInt
|
||||
result.erc20 = event{"erc20"}.getBool
|
||||
result.accounts = @[]
|
||||
if jsonSignal["event"]["accounts"].kind != JNull:
|
||||
for account in jsonSignal["event"]["accounts"]:
|
||||
if event["accounts"].kind != JNull:
|
||||
for account in event["accounts"]:
|
||||
result.accounts.add(account.getStr)
|
||||
result.at = jsonSignal["event"]{"at"}.getInt
|
||||
result.chainID = jsonSignal["event"]{"chainID"}.getInt
|
||||
result.message = jsonSignal["event"]{"message"}.getStr
|
||||
result.at = event{"at"}.getInt
|
||||
result.chainID = event{"chainID"}.getInt
|
||||
result.message = event{"message"}.getStr
|
||||
const requestIdName = "requestId"
|
||||
if event.contains(requestIdName):
|
||||
result.requestId = some(event[requestIdName].getInt())
|
||||
|
@ -10,9 +10,7 @@ import status
|
||||
import web3/conversions
|
||||
|
||||
import app/core/eventemitter
|
||||
|
||||
import ../transactions/item
|
||||
import ../transactions/module as transactions_module
|
||||
import app/core/signals/types
|
||||
|
||||
import backend/activity as backend_activity
|
||||
import backend/backend as backend
|
||||
@ -22,6 +20,11 @@ import app_service/service/currency/service as currency_service
|
||||
import app_service/service/transaction/service as transaction_service
|
||||
import app_service/service/token/service as token_service
|
||||
|
||||
import app/modules/shared/wallet_utils
|
||||
import app/modules/shared_models/currency_amount
|
||||
|
||||
import app_service/service/transaction/dto
|
||||
|
||||
proc toRef*[T](obj: T): ref T =
|
||||
new(result)
|
||||
result[] = obj
|
||||
@ -35,7 +38,6 @@ QtObject:
|
||||
Controller* = ref object of QObject
|
||||
model: Model
|
||||
recipientsModel: RecipientsModel
|
||||
transactionsModule: transactions_module.AccessInterface
|
||||
currentActivityFilter: backend_activity.ActivityFilter
|
||||
currencyService: currency_service.Service
|
||||
tokenService: token_service.Service
|
||||
@ -50,6 +52,8 @@ QtObject:
|
||||
# call updateAssetsIdentities after updating chainIds
|
||||
chainIds: seq[int]
|
||||
|
||||
requestId: int32
|
||||
|
||||
proc setup(self: Controller) =
|
||||
self.QObject.setup
|
||||
|
||||
@ -75,20 +79,30 @@ QtObject:
|
||||
result.outSymbol = item.fromAsset
|
||||
result.outAmount = self.currencyService.parseCurrencyValue(result.outSymbol, metadata.amountOut)
|
||||
|
||||
proc buildTransactionExtraData(self: Controller, metadata: backend_activity.ActivityEntry, item: ref Item): ExtraData =
|
||||
proc buildTransactionExtraData(self: Controller, metadata: backend_activity.ActivityEntry, item: ref TransactionDto): ExtraData =
|
||||
# TODO: Use symbols from backendEntry when they're available
|
||||
result.inSymbol = item[].getSymbol()
|
||||
result.inSymbol = item[].symbol
|
||||
result.inAmount = self.currencyService.parseCurrencyValue(result.inSymbol, metadata.amountIn)
|
||||
result.outSymbol = item[].getSymbol()
|
||||
result.outSymbol = item[].symbol
|
||||
result.outAmount = self.currencyService.parseCurrencyValue(result.outSymbol, metadata.amountOut)
|
||||
|
||||
proc getResolvedSymbol(self: Controller, transaction: TransactionDto): string =
|
||||
if transaction.symbol != "":
|
||||
result = transaction.symbol
|
||||
else:
|
||||
let contractSymbol = self.tokenService.findTokenSymbolByAddress(transaction.contract)
|
||||
if contractSymbol != "":
|
||||
result = contractSymbol
|
||||
else:
|
||||
result = "ETH"
|
||||
|
||||
proc backendToPresentation(self: Controller, backendEntities: seq[backend_activity.ActivityEntry]): seq[entry.ActivityEntry] =
|
||||
var multiTransactionsIds: seq[int] = @[]
|
||||
var transactionIdentities: seq[backend.TransactionIdentity] = @[]
|
||||
var pendingTransactionIdentities: seq[backend.TransactionIdentity] = @[]
|
||||
|
||||
# Extract metadata required to fetch details
|
||||
# TODO: temporary here to show the working API. Details for each entry will be done as required
|
||||
# TODO: see #11598. Temporary here to show the working API. Details for each entry will be done as required
|
||||
# on a detail request from UI after metadata is extended to include the required info
|
||||
for backendEntry in backendEntities:
|
||||
case backendEntry.payloadType:
|
||||
@ -105,7 +119,7 @@ QtObject:
|
||||
for mt in mts:
|
||||
multiTransactions[mt.id] = mt
|
||||
|
||||
var transactions = initTable[TransactionIdentity, ref Item]()
|
||||
var transactions = initTable[TransactionIdentity, ref TransactionDto]()
|
||||
if len(transactionIdentities) > 0:
|
||||
let response = backend.getTransfersForIdentities(transactionIdentities)
|
||||
let res = response.result
|
||||
@ -113,11 +127,10 @@ QtObject:
|
||||
error "failed fetching transaction details; err: ", response.error, ", kind: ", res.kind, ", res.len: ", res.len
|
||||
|
||||
let transactionsDtos = res.getElems().map(x => x.toTransactionDto())
|
||||
let trItems = self.transactionsModule.transactionsToItems(transactionsDtos, @[])
|
||||
for item in trItems:
|
||||
transactions[TransactionIdentity(chainId: item.getChainId(), hash: item.getId(), address: item.getAddress())] = toRef(item)
|
||||
for dto in transactionsDtos:
|
||||
transactions[TransactionIdentity(chainId: dto.chainId, hash: dto.id, address: dto.address)] = toRef(dto)
|
||||
|
||||
var pendingTransactions = initTable[TransactionIdentity, ref Item]()
|
||||
var pendingTransactions = initTable[TransactionIdentity, ref TransactionDto]()
|
||||
if len(pendingTransactionIdentities) > 0:
|
||||
let response = backend.getPendingTransactionsForIdentities(pendingTransactionIdentities)
|
||||
let res = response.result
|
||||
@ -125,12 +138,16 @@ QtObject:
|
||||
error "failed fetching pending transactions details; err: ", response.error, ", kind: ", res.kind, ", res.len: ", res.len
|
||||
|
||||
let pendingTransactionsDtos = res.getElems().map(x => x.toPendingTransactionDto())
|
||||
let trItems = self.transactionsModule.transactionsToItems(pendingTransactionsDtos, @[])
|
||||
for item in trItems:
|
||||
pendingTransactions[TransactionIdentity(chainId: item.getChainId(), hash: item.getId(), address: item.getAddress())] = toRef(item)
|
||||
for dto in pendingTransactionsDtos:
|
||||
pendingTransactions[TransactionIdentity(chainId: dto.chainId, hash: dto.id, address: dto.address)] = toRef(dto)
|
||||
|
||||
# Merge detailed transaction info in order
|
||||
result = newSeqOfCap[entry.ActivityEntry](multiTransactions.len + transactions.len + pendingTransactions.len)
|
||||
|
||||
let amountToCurrencyConvertor = proc(amount: UInt256, symbol: string): CurrencyAmount =
|
||||
return currencyAmountToItem(self.currencyService.parseCurrencyValue(symbol, amount),
|
||||
self.currencyService.getCurrencyFormat(symbol))
|
||||
|
||||
var mtIndex = 0
|
||||
var tIndex = 0
|
||||
var ptIndex = 0
|
||||
@ -141,7 +158,7 @@ QtObject:
|
||||
if multiTransactions.hasKey(id):
|
||||
let mt = multiTransactions[id]
|
||||
let extraData = self.buildMultiTransactionExtraData(backendEntry, mt)
|
||||
result.add(entry.newMultiTransactionActivityEntry(mt, backendEntry, extraData))
|
||||
result.add(entry.newMultiTransactionActivityEntry(mt, backendEntry, extraData, amountToCurrencyConvertor))
|
||||
else:
|
||||
error "failed to find multi transaction with id: ", id
|
||||
mtIndex += 1
|
||||
@ -149,8 +166,9 @@ QtObject:
|
||||
let identity = transactionIdentities[tIndex]
|
||||
if transactions.hasKey(identity):
|
||||
let tr = transactions[identity]
|
||||
tr.symbol = self.getResolvedSymbol(tr[])
|
||||
let extraData = self.buildTransactionExtraData(backendEntry, tr)
|
||||
result.add(entry.newTransactionActivityEntry(tr, backendEntry, self.addresses, extraData))
|
||||
result.add(entry.newTransactionActivityEntry(tr, backendEntry, self.addresses, extraData, amountToCurrencyConvertor))
|
||||
else:
|
||||
error "failed to find transaction with identity: ", identity
|
||||
tIndex += 1
|
||||
@ -158,8 +176,9 @@ QtObject:
|
||||
let identity = pendingTransactionIdentities[ptIndex]
|
||||
if pendingTransactions.hasKey(identity):
|
||||
let tr = pendingTransactions[identity]
|
||||
tr.symbol = self.getResolvedSymbol(tr[])
|
||||
let extraData = self.buildTransactionExtraData(backendEntry, tr)
|
||||
result.add(entry.newTransactionActivityEntry(tr, backendEntry, self.addresses, extraData))
|
||||
result.add(entry.newTransactionActivityEntry(tr, backendEntry, self.addresses, extraData, amountToCurrencyConvertor))
|
||||
else:
|
||||
error "failed to find pending transaction with identity: ", identity
|
||||
ptIndex += 1
|
||||
@ -189,7 +208,7 @@ QtObject:
|
||||
self.eventsHandler.updateSubscribedChainIDs(self.chainIds)
|
||||
self.status.setNewDataAvailable(false)
|
||||
|
||||
let response = backend_activity.filterActivityAsync(self.addresses, seq[backend_activity.ChainId](self.chainIds), self.currentActivityFilter, 0, FETCH_BATCH_COUNT_DEFAULT)
|
||||
let response = backend_activity.filterActivityAsync(self.requestId, 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.status.setLoadingData(false)
|
||||
@ -198,7 +217,7 @@ QtObject:
|
||||
proc loadMoreItems(self: Controller) {.slot.} =
|
||||
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)
|
||||
let response = backend_activity.filterActivityAsync(self.requestId, self.addresses, seq[backend_activity.ChainId](self.chainIds), self.currentActivityFilter, self.model.getCount(), FETCH_BATCH_COUNT_DEFAULT)
|
||||
if response.error != nil:
|
||||
self.status.setLoadingData(false)
|
||||
error "error fetching activity entries: ", response.error
|
||||
@ -224,7 +243,7 @@ QtObject:
|
||||
proc updateStartTimestamp*(self: Controller) {.slot.} =
|
||||
self.status.setLoadingStartTimestamp(true)
|
||||
|
||||
let resJson = backend_activity.getOldestActivityTimestampAsync(self.addresses)
|
||||
let resJson = backend_activity.getOldestActivityTimestampAsync(self.requestId, self.addresses)
|
||||
if resJson.error != nil:
|
||||
self.status.setLoadingStartTimestamp(false)
|
||||
error "error requesting oldest activity timestamp: ", resJson.error
|
||||
@ -261,19 +280,19 @@ QtObject:
|
||||
self.status.setNewDataAvailable(true)
|
||||
)
|
||||
|
||||
proc newController*(transactionsModule: transactions_module.AccessInterface,
|
||||
proc newController*(requestId: int32,
|
||||
currencyService: currency_service.Service,
|
||||
tokenService: token_service.Service,
|
||||
events: EventEmitter): Controller =
|
||||
new(result, delete)
|
||||
|
||||
result.requestId = requestId
|
||||
result.model = newModel()
|
||||
result.recipientsModel = newRecipientsModel()
|
||||
result.transactionsModule = transactionsModule
|
||||
result.tokenService = tokenService
|
||||
result.currentActivityFilter = backend_activity.getIncludeAllActivityFilter()
|
||||
|
||||
result.eventsHandler = newEventsHandler(events)
|
||||
result.eventsHandler = newEventsHandler(result.requestId, events)
|
||||
result.status = newStatus()
|
||||
|
||||
result.currencyService = currencyService
|
||||
@ -345,20 +364,37 @@ QtObject:
|
||||
|
||||
proc setFilterAddresses*(self: Controller, addresses: seq[string]) =
|
||||
self.addresses = addresses
|
||||
self.status.setIsFilterDirty(true)
|
||||
|
||||
self.updateStartTimestamp()
|
||||
|
||||
proc setFilterAddressesJson*(self: Controller, jsonArray: string) {.slot.} =
|
||||
let addressesJson = parseJson(jsonArray)
|
||||
if addressesJson.kind != JArray:
|
||||
error "invalid array of json strings"
|
||||
return
|
||||
|
||||
var addresses = newSeq[string]()
|
||||
for i in 0 ..< addressesJson.len:
|
||||
if addressesJson[i].kind != JString:
|
||||
error "not string entry in the json adday for index ", i
|
||||
return
|
||||
addresses.add(addressesJson[i].getStr())
|
||||
|
||||
self.setFilterAddresses(addresses)
|
||||
|
||||
proc setFilterToAddresses*(self: Controller, addresses: seq[string]) =
|
||||
self.currentActivityFilter.counterpartyAddresses = addresses
|
||||
|
||||
proc setFilterChains*(self: Controller, chainIds: seq[int]) =
|
||||
self.chainIds = chainIds
|
||||
self.status.setIsFilterDirty(true)
|
||||
|
||||
self.updateAssetsIdentities()
|
||||
|
||||
proc updateRecipientsModel*(self: Controller) {.slot.} =
|
||||
self.status.setLoadingRecipients(true)
|
||||
let res = backend_activity.getRecipientsAsync(0, FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)
|
||||
let res = backend_activity.getRecipientsAsync(self.requestId, 0, FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)
|
||||
if res.error != nil or res.result.kind != JBool:
|
||||
self.status.setLoadingRecipients(false)
|
||||
error "error fetching recipients: ", res.error, "; kind ", res.result.kind
|
||||
@ -370,7 +406,7 @@ QtObject:
|
||||
|
||||
proc loadMoreRecipients(self: Controller) {.slot.} =
|
||||
self.status.setLoadingRecipients(true)
|
||||
let res = backend_activity.getRecipientsAsync(self.recipientsModel.getCount(), FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)
|
||||
let res = backend_activity.getRecipientsAsync(self.requestId, self.recipientsModel.getCount(), FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT)
|
||||
if res.error != nil:
|
||||
self.status.setLoadingRecipients(false)
|
||||
error "error fetching more recipient entries: ", res.error
|
||||
@ -393,5 +429,4 @@ QtObject:
|
||||
if (self.addresses == addresses and self.chainIds == chainIds):
|
||||
return
|
||||
self.setFilterAddresses(addresses)
|
||||
self.setFilterChains(chainIds)
|
||||
self.status.setIsFilterDirty(true)
|
||||
self.setFilterChains(chainIds)
|
@ -1,10 +1,14 @@
|
||||
import NimQml, json, strformat, sequtils, strutils, logging, stint, options
|
||||
import NimQml, json, strformat, sequtils, strutils, logging, stint
|
||||
|
||||
import ../transactions/view
|
||||
import ../transactions/item
|
||||
import ./backend/transactions
|
||||
import backend/transactions
|
||||
import backend/activity as backend
|
||||
import ../../../shared_models/currency_amount
|
||||
import app/modules/shared_models/currency_amount
|
||||
|
||||
import app/global/global_singleton
|
||||
|
||||
import app_service/service/transaction/dto
|
||||
import app_service/service/currency/dto as currency
|
||||
import app_service/service/currency/service
|
||||
|
||||
import web3/ethtypes as eth
|
||||
|
||||
@ -15,13 +19,16 @@ type
|
||||
ExtraData* = object
|
||||
inAmount*: float64
|
||||
outAmount*: float64
|
||||
# TODO: Fields below should come from the metadata
|
||||
# TODO: Fields below should come from the metadata. see #11597
|
||||
inSymbol*: string
|
||||
outSymbol*: string
|
||||
|
||||
AmountToCurrencyConvertor* = proc (amount: UInt256, symbol: string): CurrencyAmount
|
||||
|
||||
# It is used to display an activity history entry in the QML UI
|
||||
#
|
||||
# TODO remove this legacy after the NFT is served async; see #11598
|
||||
# TODO add all required metadata from filtering; see #11597
|
||||
#
|
||||
# Looking into going away from carying the whole detailed data and just keep the required data for the UI
|
||||
# and request the detailed data on demand
|
||||
@ -30,36 +37,59 @@ type
|
||||
QtObject:
|
||||
type
|
||||
ActivityEntry* = ref object of QObject
|
||||
# TODO: these should be removed
|
||||
# TODO: these should be removed; see #11598
|
||||
multi_transaction: MultiTransactionDto
|
||||
transaction: ref Item
|
||||
transaction: ref TransactionDto
|
||||
isPending: bool
|
||||
|
||||
valueConvertor: AmountToCurrencyConvertor
|
||||
metadata: backend.ActivityEntry
|
||||
extradata: ExtraData
|
||||
|
||||
totalFees: CurrencyAmount
|
||||
maxTotalFees: CurrencyAmount
|
||||
amountCurrency: CurrencyAmount
|
||||
noAmount: CurrencyAmount
|
||||
|
||||
proc setup(self: ActivityEntry) =
|
||||
self.QObject.setup
|
||||
|
||||
proc delete*(self: ActivityEntry) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newMultiTransactionActivityEntry*(mt: MultiTransactionDto, metadata: backend.ActivityEntry, extradata: ExtraData): ActivityEntry =
|
||||
|
||||
proc newMultiTransactionActivityEntry*(mt: MultiTransactionDto, metadata: backend.ActivityEntry, extradata: ExtraData, valueConvertor: AmountToCurrencyConvertor): ActivityEntry =
|
||||
new(result, delete)
|
||||
result.multi_transaction = mt
|
||||
result.transaction = nil
|
||||
result.isPending = false
|
||||
result.valueConvertor = valueConvertor
|
||||
result.metadata = metadata
|
||||
result.extradata = extradata
|
||||
result.noAmount = newCurrencyAmount()
|
||||
result.amountCurrency = valueConvertor(
|
||||
if metadata.activityType == backend.ActivityType.Receive: metadata.amountIn else: metadata.amountOut,
|
||||
if metadata.activityType == backend.ActivityType.Receive: mt.toAsset else: mt.fromAsset,
|
||||
)
|
||||
result.setup()
|
||||
|
||||
proc newTransactionActivityEntry*(tr: ref Item, metadata: backend.ActivityEntry, fromAddresses: seq[string], extradata: ExtraData): ActivityEntry =
|
||||
proc newTransactionActivityEntry*(tr: ref TransactionDto, metadata: backend.ActivityEntry, fromAddresses: seq[string], extradata: ExtraData, valueConvertor: AmountToCurrencyConvertor): ActivityEntry =
|
||||
new(result, delete)
|
||||
result.multi_transaction = nil
|
||||
result.transaction = tr
|
||||
result.isPending = metadata.payloadType == backend.PayloadType.PendingTransaction
|
||||
result.valueConvertor = valueConvertor
|
||||
result.metadata = metadata
|
||||
result.extradata = extradata
|
||||
|
||||
result.totalFees = valueConvertor(stint.fromHex(UInt256, tr.totalFees), "Gwei")
|
||||
result.maxTotalFees = valueConvertor(stint.fromHex(UInt256, tr.maxTotalFees), "Gwei")
|
||||
result.amountCurrency = valueConvertor(
|
||||
if metadata.activityType == backend.ActivityType.Receive: metadata.amountIn else: metadata.amountOut,
|
||||
tr.symbol
|
||||
)
|
||||
result.noAmount = newCurrencyAmount()
|
||||
|
||||
result.setup()
|
||||
|
||||
proc isMultiTransaction*(self: ActivityEntry): bool {.slot.} =
|
||||
@ -89,11 +119,6 @@ QtObject:
|
||||
raise newException(Defect, "ActivityEntry is not a MultiTransaction")
|
||||
return self.multi_transaction
|
||||
|
||||
proc getTransaction*(self: ActivityEntry, pending: bool): ref Item =
|
||||
if self.isMultiTransaction() or self.isPending != pending:
|
||||
raise newException(Defect, "ActivityEntry is not a " & (if pending: "pending" else: "") & " Transaction")
|
||||
return self.transaction
|
||||
|
||||
proc getSender*(self: ActivityEntry): string {.slot.} =
|
||||
return if self.metadata.sender.isSome(): "0x" & self.metadata.sender.unsafeGet().toHex() else: ""
|
||||
|
||||
@ -153,24 +178,20 @@ QtObject:
|
||||
proc getIsNFT*(self: ActivityEntry): bool {.slot.} =
|
||||
return self.metadata.transferType.isSome() and self.metadata.transferType.unsafeGet() == TransferType.Erc721
|
||||
|
||||
QtProperty[int] isNFT:
|
||||
QtProperty[bool] isNFT:
|
||||
read = getIsNFT
|
||||
|
||||
proc getNFTName*(self: ActivityEntry): string {.slot.} =
|
||||
if self.transaction == nil:
|
||||
error "getNFTName: ActivityEntry is not an transaction.Item"
|
||||
return ""
|
||||
return self.transaction[].getNFTName()
|
||||
# TODO: complete this async #11597
|
||||
return ""
|
||||
|
||||
# TODO: lazy load this in activity history service. See #11597
|
||||
QtProperty[string] nftName:
|
||||
read = getNFTName
|
||||
|
||||
proc getNFTImageURL*(self: ActivityEntry): string {.slot.} =
|
||||
if self.transaction == nil:
|
||||
error "getNFTImageURL: ActivityEntry is not an transaction.Item"
|
||||
return ""
|
||||
return self.transaction[].getNFTImageURL()
|
||||
# TODO: complete this async #11597
|
||||
return ""
|
||||
|
||||
# TODO: lazy load this in activity history service. See #11597
|
||||
QtProperty[string] nftImageURL:
|
||||
@ -178,9 +199,9 @@ QtObject:
|
||||
|
||||
proc getTotalFees*(self: ActivityEntry): QVariant {.slot.} =
|
||||
if self.transaction == nil:
|
||||
error "getTotalFees: ActivityEntry is not an transaction.Item"
|
||||
return newQVariant(newCurrencyAmount())
|
||||
return newQVariant(self.transaction[].getTotalFees())
|
||||
error "getTotalFees: ActivityEntry is not an transaction entry"
|
||||
return newQVariant(self.noAmount)
|
||||
return newQVariant(self.totalFees)
|
||||
|
||||
# TODO: lazy load this in activity history service. See #11597
|
||||
QtProperty[QVariant] totalFees:
|
||||
@ -188,9 +209,9 @@ QtObject:
|
||||
|
||||
proc getMaxTotalFees*(self: ActivityEntry): QVariant {.slot.} =
|
||||
if self.transaction == nil:
|
||||
error "getMaxTotalFees: ActivityEntry is not an transaction.Item"
|
||||
return newQVariant(newCurrencyAmount())
|
||||
return newQVariant(self.transaction[].getMaxTotalFees())
|
||||
error "getMaxTotalFees: ActivityEntry is not an transaction entry"
|
||||
return newQVariant(self.noAmount)
|
||||
return newQVariant(self.maxTotalFees)
|
||||
|
||||
# TODO: used only in details, move it to a entry_details.nim. See #11598
|
||||
QtProperty[QVariant] maxTotalFees:
|
||||
@ -198,9 +219,9 @@ QtObject:
|
||||
|
||||
proc getInput*(self: ActivityEntry): string {.slot.} =
|
||||
if self.transaction == nil:
|
||||
error "getInput: ActivityEntry is not an transaction.Item"
|
||||
error "getInput: ActivityEntry is not an transactio entry"
|
||||
return ""
|
||||
return self.transaction[].getInput()
|
||||
return self.transaction[].input
|
||||
|
||||
# TODO: used only in details, move it to a entry_details.nim. See #11598
|
||||
QtProperty[string] input:
|
||||
@ -214,9 +235,9 @@ QtObject:
|
||||
|
||||
proc getType*(self: ActivityEntry): string {.slot.} =
|
||||
if self.transaction == nil:
|
||||
error "getType: ActivityEntry is not an transaction.Item"
|
||||
error "getType: ActivityEntry is not an transaction entry"
|
||||
return ""
|
||||
return self.transaction[].getType()
|
||||
return self.transaction[].typeValue
|
||||
|
||||
# TODO: used only in details, move it to a entry_details.nim. See #11598
|
||||
QtProperty[string] type:
|
||||
@ -230,9 +251,9 @@ QtObject:
|
||||
|
||||
proc getTxHash*(self: ActivityEntry): string {.slot.} =
|
||||
if self.transaction == nil:
|
||||
error "getTxHash: ActivityEntry is not an transaction.Item"
|
||||
error "getTxHash: ActivityEntry is not an transaction entry"
|
||||
return ""
|
||||
return self.transaction[].getTxHash()
|
||||
return self.transaction[].txHash
|
||||
|
||||
# TODO: used only in details, move it to a entry_details.nim. See #11598
|
||||
QtProperty[string] txHash:
|
||||
@ -253,18 +274,18 @@ QtObject:
|
||||
# TODO: used only in details, move it to a entry_details.nim. See #11598
|
||||
proc getNonce*(self: ActivityEntry): string {.slot.} =
|
||||
if self.transaction == nil:
|
||||
error "getNonce: ActivityEntry is not an transaction.Item"
|
||||
error "getNonce: ActivityEntry is not an transaction entry"
|
||||
return ""
|
||||
return $self.transaction[].getNonce()
|
||||
return $self.transaction[].nonce
|
||||
|
||||
QtProperty[string] nonce:
|
||||
read = getNonce
|
||||
|
||||
proc getBlockNumber*(self: ActivityEntry): string {.slot.} =
|
||||
if self.transaction == nil:
|
||||
error "getBlockNumber: ActivityEntry is not an transaction.Item"
|
||||
error "getBlockNumber: ActivityEntry is not an transaction entry"
|
||||
return ""
|
||||
return $self.transaction[].getBlockNumber()
|
||||
return $self.transaction[].blockNumber
|
||||
|
||||
# TODO: used only in details, move it to a entry_details.nim. See #11598
|
||||
QtProperty[string] blockNumber:
|
||||
@ -289,3 +310,9 @@ QtObject:
|
||||
|
||||
QtProperty[float] amount:
|
||||
read = getAmount
|
||||
|
||||
proc getAmountCurrency*(self: ActivityEntry): QVariant {.slot.} =
|
||||
return newQVariant(self.amountCurrency)
|
||||
|
||||
QtProperty[QVariant] amountCurrency:
|
||||
read = getAmountCurrency
|
||||
|
@ -1,11 +1,7 @@
|
||||
import NimQml, logging, std/json, sequtils, strutils
|
||||
import NimQml, logging, std/json, sequtils, strutils, options
|
||||
import tables, stint, sets
|
||||
|
||||
import model
|
||||
import entry
|
||||
import recipients_model
|
||||
|
||||
import web3/conversions
|
||||
|
||||
import app/core/eventemitter
|
||||
import app/core/signals/types
|
||||
@ -30,6 +26,8 @@ QtObject:
|
||||
subscribedChainIDs: HashSet[int]
|
||||
newDataAvailableFn: proc()
|
||||
|
||||
requestId: int
|
||||
|
||||
proc setup(self: EventsHandler) =
|
||||
self.QObject.setup
|
||||
|
||||
@ -51,6 +49,9 @@ QtObject:
|
||||
proc handleApiEvents(self: EventsHandler, e: Args) =
|
||||
var data = WalletSignal(e)
|
||||
|
||||
if data.requestId.isSome and data.requestId.get() != self.requestId:
|
||||
return
|
||||
|
||||
if self.walletEventHandlers.hasKey(data.eventType):
|
||||
let callback = self.walletEventHandlers[data.eventType]
|
||||
callback(data)
|
||||
@ -63,8 +64,6 @@ QtObject:
|
||||
return
|
||||
let callback = self.eventHandlers[data.eventType]
|
||||
callback(responseJson)
|
||||
else:
|
||||
discard
|
||||
|
||||
proc setupWalletEventHandlers(self: EventsHandler) =
|
||||
let newDataAvailableCallback = proc (data: WalletSignal) =
|
||||
@ -100,14 +99,17 @@ QtObject:
|
||||
self.walletEventHandlers[EventPendingTransactionUpdate] = newDataAvailableCallback
|
||||
self.walletEventHandlers[EventMTTransactionUpdate] = newDataAvailableCallback
|
||||
|
||||
proc newEventsHandler*(events: EventEmitter): EventsHandler =
|
||||
proc newEventsHandler*(requestId: int, events: EventEmitter): EventsHandler =
|
||||
new(result, delete)
|
||||
|
||||
result.events = events
|
||||
result.eventHandlers = initTable[string, EventCallbackProc]()
|
||||
|
||||
result.subscribedAddresses = initHashSet[string]()
|
||||
result.subscribedChainIDs = initHashSet[int]()
|
||||
|
||||
result.requestId = requestId
|
||||
|
||||
result.setup()
|
||||
|
||||
result.setupWalletEventHandlers()
|
||||
|
@ -2,10 +2,7 @@ import NimQml, Tables, strutils, strformat, sequtils, logging
|
||||
|
||||
import ./entry
|
||||
|
||||
# TODO - DEV: remove these imports and associated code after all the metadata is returned by the filter API
|
||||
import app_service/service/transaction/dto
|
||||
import app/modules/shared_models/currency_amount
|
||||
import ../transactions/item as transaction
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
|
@ -1,4 +1,4 @@
|
||||
import NimQml, Tables, strutils, strformat, sequtils, logging
|
||||
import NimQml, Tables, strutils, sequtils, logging
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
|
@ -1,7 +1,5 @@
|
||||
import NimQml, std/json, sequtils, strutils, times
|
||||
import tables, stint, sets, atomics
|
||||
|
||||
import web3/conversions
|
||||
import stint, atomics
|
||||
|
||||
import app/core/signals/types
|
||||
|
||||
@ -119,6 +117,9 @@ QtObject:
|
||||
proc isFilterDirtyChanged*(self: Status) {.signal.}
|
||||
|
||||
proc setIsFilterDirty*(self: Status, value: bool) =
|
||||
if self.isFilterDirty == value:
|
||||
return
|
||||
|
||||
self.isFilterDirty = value
|
||||
self.isFilterDirtyChanged()
|
||||
|
||||
|
@ -89,4 +89,13 @@ method destroyAddAccountPopup*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getNetworkLayer*(self: AccessInterface, chainId: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getChainIdForChat*(self: AccessInterface): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getLatestBlockNumber*(self: AccessInterface, chainId: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method fetchDecodedTxData*(self: AccessInterface, txHash: string, data: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
@ -7,7 +7,6 @@ import ../io_interface as delegate_interface
|
||||
import ./accounts/module as accounts_module
|
||||
import ./all_tokens/module as all_tokens_module
|
||||
import ./assets/module as assets_module
|
||||
import ./transactions/module as transactions_module
|
||||
import ./saved_addresses/module as saved_addresses_module
|
||||
import ./buy_sell_crypto/module as buy_sell_crypto_module
|
||||
import ./networks/module as networks_module
|
||||
@ -39,6 +38,10 @@ logScope:
|
||||
export io_interface
|
||||
|
||||
type
|
||||
ActivityID = enum
|
||||
History
|
||||
Temporary
|
||||
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
delegate: delegate_interface.AccessInterface
|
||||
events: EventEmitter
|
||||
@ -51,13 +54,13 @@ type
|
||||
allTokensModule: all_tokens_module.AccessInterface
|
||||
assetsModule: assets_module.AccessInterface
|
||||
sendModule: send_module.AccessInterface
|
||||
transactionsModule: transactions_module.AccessInterface
|
||||
savedAddressesModule: saved_addresses_module.AccessInterface
|
||||
buySellCryptoModule: buy_sell_crypto_module.AccessInterface
|
||||
addAccountModule: add_account_module.AccessInterface
|
||||
overviewModule: overview_module.AccessInterface
|
||||
networksModule: networks_module.AccessInterface
|
||||
networksService: network_service.Service
|
||||
transactionService: transaction_service.Service
|
||||
keycardService: keycard_service.Service
|
||||
accountsService: accounts_service.Service
|
||||
walletAccountService: wallet_account_service.Service
|
||||
@ -65,6 +68,8 @@ type
|
||||
activityController: activityc.Controller
|
||||
collectiblesController: collectiblesc.Controller
|
||||
collectibleDetailsController: collectible_detailsc.Controller
|
||||
# instance to be used in temporary, short-lived, workflows (e.g. send popup)
|
||||
tmpActivityController: activityc.Controller
|
||||
|
||||
proc newModule*(
|
||||
delegate: delegate_interface.AccessInterface,
|
||||
@ -93,32 +98,33 @@ proc newModule*(
|
||||
result.accountsModule = accounts_module.newModule(result, events, walletAccountService, networkService, currencyService)
|
||||
result.allTokensModule = all_tokens_module.newModule(result, events, tokenService, walletAccountService)
|
||||
result.assetsModule = assets_module.newModule(result, events, walletAccountService, networkService, tokenService, currencyService)
|
||||
result.transactionsModule = transactions_module.newModule(result, events, transactionService, walletAccountService, networkService, currencyService)
|
||||
result.sendModule = send_module.newModule(result, events, walletAccountService, networkService, currencyService, transactionService)
|
||||
result.savedAddressesModule = saved_addresses_module.newModule(result, events, savedAddressService)
|
||||
result.buySellCryptoModule = buy_sell_crypto_module.newModule(result, events, transactionService)
|
||||
result.overviewModule = overview_module.newModule(result, events, walletAccountService, currencyService)
|
||||
result.networksModule = networks_module.newModule(result, events, networkService, walletAccountService, settingsService)
|
||||
result.networksService = networkService
|
||||
result.activityController = activityc.newController(result.transactionsModule, currencyService, tokenService, events)
|
||||
|
||||
result.transactionService = transactionService
|
||||
result.activityController = activityc.newController(int32(ActivityID.History), currencyService, tokenService, events)
|
||||
result.tmpActivityController = activityc.newController(int32(ActivityID.Temporary), currencyService, tokenService, events)
|
||||
result.collectiblesController = collectiblesc.newController(events)
|
||||
result.collectibleDetailsController = collectible_detailsc.newController(networkService, events)
|
||||
result.filter = initFilter(result.controller)
|
||||
|
||||
result.view = newView(result, result.activityController, result.collectiblesController, result.collectibleDetailsController)
|
||||
|
||||
result.view = newView(result, result.activityController, result.tmpActivityController, result.collectiblesController, result.collectibleDetailsController)
|
||||
|
||||
method delete*(self: Module) =
|
||||
self.accountsModule.delete
|
||||
self.allTokensModule.delete
|
||||
self.assetsModule.delete
|
||||
self.transactionsModule.delete
|
||||
self.savedAddressesModule.delete
|
||||
self.buySellCryptoModule.delete
|
||||
self.sendModule.delete
|
||||
self.controller.delete
|
||||
self.view.delete
|
||||
self.activityController.delete
|
||||
self.tmpActivityController.delete
|
||||
self.collectiblesController.delete
|
||||
self.collectibleDetailsController.delete
|
||||
|
||||
@ -145,7 +151,6 @@ method notifyFilterChanged(self: Module) =
|
||||
let includeWatchOnly = self.controller.isIncludeWatchOnlyAccount()
|
||||
self.overviewModule.filterChanged(self.filter.addresses, self.filter.chainIds, includeWatchOnly, self.filter.allAddresses)
|
||||
self.assetsModule.filterChanged(self.filter.addresses, self.filter.chainIds)
|
||||
self.transactionsModule.filterChanged(self.filter.addresses, self.filter.chainIds)
|
||||
self.accountsModule.filterChanged(self.filter.addresses, self.filter.chainIds)
|
||||
self.sendModule.filterChanged(self.filter.addresses, self.filter.chainIds)
|
||||
self.activityController.globalFilterChanged(self.filter.addresses, self.filter.chainIds)
|
||||
@ -211,13 +216,17 @@ method load*(self: Module) =
|
||||
self.filter.includeWatchOnlyToggled()
|
||||
self.notifyFilterChanged()
|
||||
self.setTotalCurrencyBalance()
|
||||
self.events.on(SIGNAL_HISTORY_NON_ARCHIVAL_NODE) do (e:Args):
|
||||
self.view.setIsNonArchivalNode(true)
|
||||
self.events.on(SIGNAL_TRANSACTION_DECODED) do(e: Args):
|
||||
let args = TransactionDecodedArgs(e)
|
||||
self.view.txDecoded(args.txHash, args.dataDecoded)
|
||||
|
||||
self.controller.init()
|
||||
self.view.load()
|
||||
self.accountsModule.load()
|
||||
self.allTokensModule.load()
|
||||
self.assetsModule.load()
|
||||
self.transactionsModule.load()
|
||||
self.savedAddressesModule.load()
|
||||
self.buySellCryptoModule.load()
|
||||
self.overviewModule.load()
|
||||
@ -237,9 +246,6 @@ proc checkIfModuleDidLoad(self: Module) =
|
||||
if(not self.assetsModule.isLoaded()):
|
||||
return
|
||||
|
||||
if(not self.transactionsModule.isLoaded()):
|
||||
return
|
||||
|
||||
if(not self.savedAddressesModule.isLoaded()):
|
||||
return
|
||||
|
||||
@ -326,4 +332,13 @@ method onAddAccountModuleLoaded*(self: Module) =
|
||||
self.view.emitDisplayAddAccountPopup()
|
||||
|
||||
method getNetworkLayer*(self: Module, chainId: int): string =
|
||||
return self.networksModule.getNetworkLayer(chainId)
|
||||
return self.networksModule.getNetworkLayer(chainId)
|
||||
|
||||
method getChainIdForChat*(self: Module): int =
|
||||
return self.networksService.getNetworkForChat().chainId
|
||||
|
||||
method getLatestBlockNumber*(self: Module, chainId: int): string =
|
||||
return self.transactionService.getLatestBlockNumber(chainId)
|
||||
|
||||
method fetchDecodedTxData*(self: Module, txHash: string, data: string) =
|
||||
self.transactionService.fetchDecodedTxData(txHash, data)
|
||||
|
@ -1,128 +0,0 @@
|
||||
import NimQml, json, json_serialization, stint, tables, sugar, sequtils
|
||||
import io_interface
|
||||
import ../../../../../app_service/service/transaction/service as transaction_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/currency/service as currency_service
|
||||
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||
|
||||
import ../../../../core/[main]
|
||||
import ../../../../core/tasks/[qt, threadpool]
|
||||
import ./backend/transactions
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
delegate: io_interface.AccessInterface
|
||||
events: EventEmitter
|
||||
transactionService: transaction_service.Service
|
||||
networkService: network_service.Service
|
||||
walletAccountService: wallet_account_service.Service
|
||||
currencyService: currency_service.Service
|
||||
|
||||
# Forward declaration
|
||||
proc loadTransactions*(self: Controller, address: string, toBlock: Uint256, limit: int = 20, loadMore: bool = false)
|
||||
proc getWalletAccounts*(self: Controller): seq[WalletAccountDto]
|
||||
|
||||
proc newController*(
|
||||
delegate: io_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
transactionService: transaction_service.Service,
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
networkService: network_service.Service,
|
||||
currencyService: currency_service.Service,
|
||||
): Controller =
|
||||
result = Controller()
|
||||
result.events = events
|
||||
result.delegate = delegate
|
||||
result.transactionService = transactionService
|
||||
result.walletAccountService = walletAccountService
|
||||
result.networkService = networkService
|
||||
result.currencyService = currencyService
|
||||
|
||||
proc delete*(self: Controller) =
|
||||
discard
|
||||
|
||||
proc init*(self: Controller) =
|
||||
self.events.on(SIGNAL_TRANSACTION_SENT) do(e:Args):
|
||||
self.delegate.transactionWasSent(TransactionSentArgs(e).result)
|
||||
|
||||
self.events.on(SIGNAL_HISTORY_FETCHING) do (e:Args):
|
||||
let args = HistoryArgs(e)
|
||||
self.delegate.setHistoryFetchState(args.addresses, isFetching = true)
|
||||
|
||||
self.events.on(SIGNAL_HISTORY_READY) do (e:Args):
|
||||
let args = HistoryArgs(e)
|
||||
self.delegate.setHistoryFetchState(args.addresses, isFetching = true)
|
||||
|
||||
self.events.on(SIGNAL_HISTORY_NON_ARCHIVAL_NODE) do (e:Args):
|
||||
let accounts = self.getWalletAccounts()
|
||||
let addresses = accounts.map(account => account.address)
|
||||
self.delegate.setHistoryFetchState(addresses, isFetching = false)
|
||||
self.delegate.setIsNonArchivalNode(true)
|
||||
|
||||
self.events.on(SIGNAL_HISTORY_ERROR) do (e:Args):
|
||||
let accounts = self.getWalletAccounts()
|
||||
let addresses = accounts.map(account => account.address)
|
||||
self.delegate.setHistoryFetchState(addresses, isFetching = false, hasMore = false)
|
||||
|
||||
self.events.on(SIGNAL_TRANSACTIONS_LOADED) do(e:Args):
|
||||
let args = TransactionsLoadedArgs(e)
|
||||
self.delegate.setHistoryFetchState(@[args.address], isFetching = false)
|
||||
self.delegate.setTrxHistoryResult(args.transactions, args.collectibles, args.address, args.wasFetchMore)
|
||||
|
||||
self.events.on(SIGNAL_TRANSACTION_LOADING_COMPLETED_FOR_ALL_NETWORKS) do(e:Args):
|
||||
let args = TransactionsLoadedArgs(e)
|
||||
self.delegate.setHistoryFetchState(args.address, args.allTxLoaded, isFetching = false)
|
||||
|
||||
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e:Args):
|
||||
self.delegate.refreshTransactions()
|
||||
|
||||
self.events.on(SIGNAL_CURRENCY_FORMATS_UPDATED) do(e:Args):
|
||||
# TODO: Rebuild Transaction items
|
||||
discard
|
||||
|
||||
self.events.on(SIGNAL_TRANSACTION_DECODED) do(e: Args):
|
||||
let args = TransactionDecodedArgs(e)
|
||||
self.delegate.txDecoded(args.txHash, args.dataDecoded)
|
||||
|
||||
proc watchPendingTransactions*(self: Controller): seq[TransactionDto] =
|
||||
return self.transactionService.watchPendingTransactions()
|
||||
|
||||
proc getPendingTransactions*(self: Controller): seq[TransactionDto] =
|
||||
return self.transactionService.getPendingTransactions()
|
||||
|
||||
proc getWalletAccounts*(self: Controller): seq[WalletAccountDto] =
|
||||
self.walletAccountService.getWalletAccounts()
|
||||
|
||||
proc getWalletAccountByAddress*(self: Controller, address: string): WalletAccountDto =
|
||||
return self.walletAccountService.getAccountByAddress(address)
|
||||
|
||||
proc loadTransactions*(self: Controller, address: string, toBlock: Uint256, limit: int = 20, loadMore: bool = false) =
|
||||
self.transactionService.loadTransactions(address, toBlock, limit, loadMore)
|
||||
|
||||
proc getAllTransactions*(self: Controller, address: string): seq[TransactionDto] =
|
||||
return self.transactionService.getAllTransactions(address)
|
||||
|
||||
proc getChainIdForChat*(self: Controller): int =
|
||||
return self.networkService.getNetworkForChat().chainId
|
||||
|
||||
proc getChainIdForBrowser*(self: Controller): int =
|
||||
return self.networkService.getNetworkForBrowser().chainId
|
||||
|
||||
proc getLatestBlockNumber*(self: Controller, chainId: int): string =
|
||||
return self.transactionService.getLatestBlockNumber(chainId)
|
||||
|
||||
proc getEnabledChainIds*(self: Controller): seq[int] =
|
||||
return self.networkService.getNetworks().filter(n => n.enabled).map(n => n.chainId)
|
||||
|
||||
proc getCurrencyFormat*(self: Controller, symbol: string): CurrencyFormatDto =
|
||||
return self.currencyService.getCurrencyFormat(symbol)
|
||||
|
||||
proc findTokenSymbolByAddress*(self: Controller, address: string): string =
|
||||
return self.walletAccountService.findTokenSymbolByAddress(address)
|
||||
|
||||
proc getMultiTransactions*(self: Controller, transactionIDs: seq[int]): seq[MultiTransactionDto] =
|
||||
return transaction_service.getMultiTransactions(transactionIDs)
|
||||
|
||||
proc fetchDecodedTxData*(self: Controller, txHash: string, data: string) =
|
||||
self.transactionService.fetchDecodedTxData(txHash, data)
|
@ -1,75 +0,0 @@
|
||||
import ../../../../../app_service/service/wallet_account/dto as WalletDto
|
||||
import ../../../../../app_service/service/transaction/dto
|
||||
export TransactionDto, CollectibleDto
|
||||
|
||||
import ./item
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
## Abstract class for any input/interaction with this module.
|
||||
|
||||
method delete*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method load*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method isLoaded*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method filterChanged*(self: AccessInterface, addresses: seq[string], chainIds: seq[int]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getWalletAccounts*(self: AccessInterface): seq[WalletAccountDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method loadTransactions*(self: AccessInterface, address: string, toBlock: string, limit: int, loadMore: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setTrxHistoryResult*(self: AccessInterface, transactions: seq[TransactionDto], collectibles: seq[CollectibleDto], address: string, wasFetchMore: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setHistoryFetchState*(self: AccessInterface, addresses: seq[string], isFetching: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setHistoryFetchState*(self: AccessInterface, addresses: seq[string], isFetching: bool, hasMore: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setHistoryFetchState*(self: AccessInterface, address: string, allTxLoaded: bool, isFetching: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setIsNonArchivalNode*(self: AccessInterface, isNonArchivalNode: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method transactionWasSent*(self: AccessInterface, result: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getChainIdForChat*(self: AccessInterface): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getChainIdForBrowser*(self: AccessInterface): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method refreshTransactions*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method fetchDecodedTxData*(self: AccessInterface, txHash: string, data: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method txDecoded*(self: AccessInterface, txHash: string, dataDecoded: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
# View Delegate Interface
|
||||
# Delegate for the view must be declared here due to use of QtObject and multi
|
||||
# inheritance, which is not well supported in Nim.
|
||||
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getLatestBlockNumber*(self: AccessInterface, chainId: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method transactionsToItems*(self: AccessInterface, transactions: seq[TransactionDto], collectibles: seq[CollectibleDto]): seq[Item] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getNetworkLayer*(self: AccessInterface, chainId: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
@ -1,299 +0,0 @@
|
||||
import strformat, stint
|
||||
import ../../../shared_models/currency_amount
|
||||
|
||||
type
|
||||
Item* = object
|
||||
id: string
|
||||
txType: string
|
||||
address: string
|
||||
blockNumber: string
|
||||
blockHash: string
|
||||
timestamp: int
|
||||
gasPrice: CurrencyAmount
|
||||
gasLimit: int
|
||||
gasUsed: int
|
||||
nonce: string
|
||||
txStatus: string
|
||||
fro: string
|
||||
to: string
|
||||
contract: string
|
||||
chainId: int
|
||||
maxFeePerGas: CurrencyAmount
|
||||
maxPriorityFeePerGas: CurrencyAmount
|
||||
input: string
|
||||
txHash: string
|
||||
multiTransactionID: int
|
||||
isTimeStamp: bool
|
||||
isNFT: bool
|
||||
baseGasFees: CurrencyAmount
|
||||
totalFees: CurrencyAmount
|
||||
maxTotalFees: CurrencyAmount
|
||||
loadingTransaction: bool
|
||||
# Applies only to isNFT == false
|
||||
value: CurrencyAmount
|
||||
symbol: string
|
||||
# Applies only to isNFT == true
|
||||
tokenID: UInt256
|
||||
nftName: string
|
||||
nftImageUrl: string
|
||||
|
||||
proc initItem*(
|
||||
id: string,
|
||||
txType: string,
|
||||
address: string,
|
||||
blockNumber: string,
|
||||
blockHash: string,
|
||||
timestamp: int,
|
||||
gasPrice: CurrencyAmount,
|
||||
gasLimit: int,
|
||||
gasUsed: int,
|
||||
nonce: string,
|
||||
txStatus: string,
|
||||
value: CurrencyAmount,
|
||||
fro: string,
|
||||
to: string,
|
||||
contract: string,
|
||||
chainId: int,
|
||||
maxFeePerGas: CurrencyAmount,
|
||||
maxPriorityFeePerGas: CurrencyAmount,
|
||||
input: string,
|
||||
txHash: string,
|
||||
multiTransactionID: int,
|
||||
isTimeStamp: bool,
|
||||
baseGasFees: CurrencyAmount,
|
||||
totalFees: CurrencyAmount,
|
||||
maxTotalFees: CurrencyAmount,
|
||||
symbol: string,
|
||||
loadingTransaction: bool = false
|
||||
): Item =
|
||||
result.id = id
|
||||
result.txType = txType
|
||||
result.address = address
|
||||
result.blockNumber = blockNumber
|
||||
result.blockHash = blockHash
|
||||
result.timestamp = timestamp
|
||||
result.gasPrice = gasPrice
|
||||
result.gasLimit = gasLimit
|
||||
result.gasUsed = gasUsed
|
||||
result.nonce = nonce
|
||||
result.txStatus = txStatus
|
||||
result.value = value
|
||||
result.fro = fro
|
||||
result.to = to
|
||||
result.contract = contract
|
||||
result.chainId = chainId
|
||||
result.maxFeePerGas = maxFeePerGas
|
||||
result.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||
result.input = input
|
||||
result.txHash = txHash
|
||||
result.multiTransactionID = multiTransactionID
|
||||
result.isTimeStamp = isTimeStamp
|
||||
result.isNFT = false
|
||||
result.baseGasFees = baseGasFees
|
||||
result.totalFees = totalFees
|
||||
result.maxTotalFees = maxTotalFees
|
||||
result.symbol = symbol
|
||||
result.loadingTransaction = loadingTransaction
|
||||
|
||||
proc initNFTItem*(
|
||||
id: string,
|
||||
txType: string,
|
||||
address: string,
|
||||
blockNumber: string,
|
||||
blockHash: string,
|
||||
timestamp: int,
|
||||
gasPrice: CurrencyAmount,
|
||||
gasLimit: int,
|
||||
gasUsed: int,
|
||||
nonce: string,
|
||||
txStatus: string,
|
||||
fro: string,
|
||||
to: string,
|
||||
contract: string,
|
||||
chainId: int,
|
||||
maxFeePerGas: CurrencyAmount,
|
||||
maxPriorityFeePerGas: CurrencyAmount,
|
||||
input: string,
|
||||
txHash: string,
|
||||
multiTransactionID: int,
|
||||
baseGasFees: CurrencyAmount,
|
||||
totalFees: CurrencyAmount,
|
||||
maxTotalFees: CurrencyAmount,
|
||||
tokenID: UInt256,
|
||||
nftName: string,
|
||||
nftImageUrl: string,
|
||||
loadingTransaction: bool = false
|
||||
): Item =
|
||||
result.id = id
|
||||
result.txType = txType
|
||||
result.address = address
|
||||
result.blockNumber = blockNumber
|
||||
result.blockHash = blockHash
|
||||
result.timestamp = timestamp
|
||||
result.gasPrice = gasPrice
|
||||
result.gasLimit = gasLimit
|
||||
result.gasUsed = gasUsed
|
||||
result.nonce = nonce
|
||||
result.txStatus = txStatus
|
||||
result.value = newCurrencyAmount()
|
||||
result.fro = fro
|
||||
result.to = to
|
||||
result.contract = contract
|
||||
result.chainId = chainId
|
||||
result.maxFeePerGas = maxFeePerGas
|
||||
result.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||
result.input = input
|
||||
result.txHash = txHash
|
||||
result.multiTransactionID = multiTransactionID
|
||||
result.isTimeStamp = false
|
||||
result.isNFT = true
|
||||
result.baseGasFees = baseGasFees
|
||||
result.totalFees = totalFees
|
||||
result.maxTotalFees = maxTotalFees
|
||||
result.loadingTransaction = loadingTransaction
|
||||
result.tokenID = tokenID
|
||||
result.nftName = nftName
|
||||
result.nftImageUrl = nftImageUrl
|
||||
|
||||
proc initLoadingItem*(): Item =
|
||||
result.timestamp = 0
|
||||
result.gasPrice = newCurrencyAmount()
|
||||
result.value = newCurrencyAmount()
|
||||
result.chainId = 0
|
||||
result.maxFeePerGas = newCurrencyAmount()
|
||||
result.maxPriorityFeePerGas = newCurrencyAmount()
|
||||
result.multiTransactionID = 0
|
||||
result.isTimeStamp = false
|
||||
result.baseGasFees = newCurrencyAmount()
|
||||
result.totalFees = newCurrencyAmount()
|
||||
result.maxTotalFees = newCurrencyAmount()
|
||||
result.loadingTransaction = true
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""TransactionsItem(
|
||||
id: {self.id},
|
||||
txType: {self.txType},
|
||||
address: {self.address},
|
||||
blockNumber: {self.blockNumber},
|
||||
blockHash: {self.blockHash},
|
||||
timestamp: {self.timestamp},
|
||||
gasPrice: {self.gasPrice},
|
||||
gasLimit: {self.gasLimit},
|
||||
gasUsed: {self.gasUsed},
|
||||
nonce: {self.nonce},
|
||||
txStatus: {self.txStatus},
|
||||
value: {self.value},
|
||||
fro: {self.fro},
|
||||
to: {self.to},
|
||||
contract: {self.contract},
|
||||
chainId: {self.chainId},
|
||||
maxFeePerGas: {self.maxFeePerGas},
|
||||
maxPriorityFeePerGas: {self.maxPriorityFeePerGas},
|
||||
input: {self.input},
|
||||
txHash: {self.txHash},
|
||||
multiTransactionID: {self.multiTransactionID},
|
||||
isTimeStamp: {self.isTimeStamp},
|
||||
isNFT: {self.isNFT},
|
||||
baseGasFees: {self.baseGasFees},
|
||||
totalFees: {self.totalFees},
|
||||
maxTotalFees: {self.maxTotalFees},
|
||||
symbol: {self.symbol},
|
||||
loadingTransaction: {self.loadingTransaction},
|
||||
tokenID: {self.tokenID},
|
||||
nftName: {self.nftName},
|
||||
nftImageUrl: {self.nftImageUrl},
|
||||
]"""
|
||||
|
||||
proc getId*(self: Item): string =
|
||||
return self.id
|
||||
|
||||
proc getType*(self: Item): string =
|
||||
return self.txType
|
||||
|
||||
proc getAddress*(self: Item): string =
|
||||
return self.address
|
||||
|
||||
proc getBlockNumber*(self: Item): string =
|
||||
return self.blockNumber
|
||||
|
||||
proc getBlockHash*(self: Item): string =
|
||||
return self.blockHash
|
||||
|
||||
proc getTimestamp*(self: Item): int =
|
||||
return self.timestamp
|
||||
|
||||
proc getGasPrice*(self: Item): CurrencyAmount =
|
||||
return self.gasPrice
|
||||
|
||||
proc getGasLimit*(self: Item): int =
|
||||
return self.gasLimit
|
||||
|
||||
proc getGasUsed*(self: Item): int =
|
||||
return self.gasUsed
|
||||
|
||||
proc getNonce*(self: Item): string =
|
||||
return self.nonce
|
||||
|
||||
proc getTxStatus*(self: Item): string =
|
||||
return self.txStatus
|
||||
|
||||
proc getValue*(self: Item): CurrencyAmount =
|
||||
return self.value
|
||||
|
||||
# TODO: fix naming
|
||||
proc getfrom*(self: Item): string =
|
||||
return self.fro
|
||||
|
||||
proc getTo*(self: Item): string =
|
||||
return self.to
|
||||
|
||||
proc getContract*(self: Item): string =
|
||||
return self.contract
|
||||
|
||||
proc getChainId*(self: Item): int =
|
||||
return self.chainId
|
||||
|
||||
proc getMaxFeePerGas*(self: Item): CurrencyAmount =
|
||||
return self.maxFeePerGas
|
||||
|
||||
proc getMaxPriorityFeePerGas*(self: Item): CurrencyAmount =
|
||||
return self.maxPriorityFeePerGas
|
||||
|
||||
proc getInput*(self: Item): string =
|
||||
return self.input
|
||||
|
||||
proc getTxHash*(self: Item): string =
|
||||
return self.txHash
|
||||
|
||||
proc getMultiTransactionID*(self: Item): int =
|
||||
return self.multiTransactionID
|
||||
|
||||
proc getIsTimeStamp*(self: Item): bool =
|
||||
return self.isTimeStamp
|
||||
|
||||
proc getIsNFT*(self: Item): bool =
|
||||
return self.isNFT
|
||||
|
||||
proc getBaseGasFees*(self: Item): CurrencyAmount =
|
||||
return self.baseGasFees
|
||||
|
||||
proc getTotalFees*(self: Item): CurrencyAmount =
|
||||
return self.totalFees
|
||||
|
||||
proc getMaxTotalFees*(self: Item): CurrencyAmount =
|
||||
return self.maxTotalFees
|
||||
|
||||
proc getSymbol*(self: Item): string =
|
||||
return self.symbol
|
||||
|
||||
proc getLoadingTransaction*(self: Item): bool =
|
||||
return self.loadingTransaction
|
||||
|
||||
proc getTokenID*(self: Item): UInt256 =
|
||||
return self.tokenID
|
||||
|
||||
proc getNFTName*(self: Item): string =
|
||||
return self.nftName
|
||||
|
||||
proc getNFTImageURL*(self: Item): string =
|
||||
return self.nftImageUrl
|
@ -1,270 +0,0 @@
|
||||
import NimQml, Tables, strutils, strformat, sequtils, tables, sugar, algorithm, std/[times, os], stint, parseutils
|
||||
|
||||
import ./item
|
||||
import ../../../../../app_service/service/eth/utils as eth_service_utils
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
Id = UserRole + 1,
|
||||
Type
|
||||
Address
|
||||
BlockNumber
|
||||
BlockHash
|
||||
Timestamp
|
||||
GasPrice
|
||||
GasLimit
|
||||
GasUsed
|
||||
Nonce
|
||||
TxStatus
|
||||
From
|
||||
To
|
||||
Contract
|
||||
ChainID
|
||||
MaxFeePerGas
|
||||
MaxPriorityFeePerGas
|
||||
Input
|
||||
TxHash
|
||||
MultiTransactionID
|
||||
IsTimeStamp
|
||||
IsNFT
|
||||
BaseGasFees
|
||||
TotalFees
|
||||
MaxTotalFees
|
||||
LoadingTransaction
|
||||
# Applies only to IsNFT == false
|
||||
Value
|
||||
Symbol
|
||||
# Applies only to IsNFT == true
|
||||
TokenID
|
||||
NFTName
|
||||
NFTImageURL
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Model* = ref object of QAbstractListModel
|
||||
items: seq[Item]
|
||||
hasMore: bool
|
||||
|
||||
proc delete(self: Model) =
|
||||
self.items = @[]
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc setup(self: Model) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc newModel*(): Model =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
result.hasMore = true
|
||||
|
||||
proc `$`*(self: Model): string =
|
||||
for i in 0 ..< self.items.len:
|
||||
result &= fmt"""[{i}]:({$self.items[i]})"""
|
||||
|
||||
proc countChanged(self: Model) {.signal.}
|
||||
|
||||
proc getCount*(self: Model): int {.slot.} =
|
||||
self.items.len
|
||||
|
||||
QtProperty[int] count:
|
||||
read = getCount
|
||||
notify = countChanged
|
||||
|
||||
method rowCount(self: Model, index: QModelIndex = nil): int =
|
||||
return self.items.len
|
||||
|
||||
method roleNames(self: Model): Table[int, string] =
|
||||
{
|
||||
ModelRole.Id.int:"id",
|
||||
ModelRole.Type.int:"type",
|
||||
ModelRole.Address.int:"address",
|
||||
ModelRole.BlockNumber.int:"blockNumber",
|
||||
ModelRole.BlockHash.int:"blockHash",
|
||||
ModelRole.Timestamp.int:"timestamp",
|
||||
ModelRole.GasPrice.int:"gasPrice",
|
||||
ModelRole.GasLimit.int:"gasLimit",
|
||||
ModelRole.GasUsed.int:"gasUsed",
|
||||
ModelRole.Nonce.int:"nonce",
|
||||
ModelRole.TxStatus.int:"txStatus",
|
||||
ModelRole.Value.int:"value",
|
||||
ModelRole.From.int:"from",
|
||||
ModelRole.To.int:"to",
|
||||
ModelRole.Contract.int:"contract",
|
||||
ModelRole.ChainID.int:"chainId",
|
||||
ModelRole.MaxFeePerGas.int:"maxFeePerGas",
|
||||
ModelRole.MaxPriorityFeePerGas.int:"maxPriorityFeePerGas",
|
||||
ModelRole.Input.int:"input",
|
||||
ModelRole.TxHash.int:"txHash",
|
||||
ModelRole.MultiTransactionID.int:"multiTransactionID",
|
||||
ModelRole.IsTimeStamp.int: "isTimeStamp",
|
||||
ModelRole.IsNFT.int: "isNFT",
|
||||
ModelRole.BaseGasFees.int: "baseGasFees",
|
||||
ModelRole.TotalFees.int: "totalFees",
|
||||
ModelRole.MaxTotalFees.int: "maxTotalFees",
|
||||
ModelRole.Symbol.int: "symbol",
|
||||
ModelRole.LoadingTransaction.int: "loadingTransaction",
|
||||
ModelRole.TokenID.int: "tokenID",
|
||||
ModelRole.NFTName.int: "nftName",
|
||||
ModelRole.NFTImageURL.int: "nftImageUrl"
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
if (not index.isValid):
|
||||
return
|
||||
|
||||
if (index.row < 0 or index.row >= self.items.len):
|
||||
return
|
||||
|
||||
let item = self.items[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
|
||||
case enumRole:
|
||||
of ModelRole.Id:
|
||||
result = newQVariant(item.getId())
|
||||
of ModelRole.Type:
|
||||
result = newQVariant(item.getType())
|
||||
of ModelRole.Address:
|
||||
result = newQVariant(item.getAddress())
|
||||
of ModelRole.BlockNumber:
|
||||
result = newQVariant(item.getBlockNumber())
|
||||
of ModelRole.BlockHash:
|
||||
result = newQVariant(item.getBlockHash())
|
||||
of ModelRole.Timestamp:
|
||||
result = newQVariant(item.getTimestamp())
|
||||
of ModelRole.GasPrice:
|
||||
result = newQVariant(item.getGasPrice())
|
||||
of ModelRole.GasLimit:
|
||||
result = newQVariant(item.getGasLimit())
|
||||
of ModelRole.GasUsed:
|
||||
result = newQVariant(item.getGasUsed())
|
||||
of ModelRole.Nonce:
|
||||
result = newQVariant(item.getNonce())
|
||||
of ModelRole.TxStatus:
|
||||
result = newQVariant(item.getTxStatus())
|
||||
of ModelRole.Value:
|
||||
result = newQVariant(item.getValue())
|
||||
of ModelRole.From:
|
||||
result = newQVariant(item.getFrom())
|
||||
of ModelRole.To:
|
||||
result = newQVariant(item.getTo())
|
||||
of ModelRole.Contract:
|
||||
result = newQVariant(item.getContract())
|
||||
of ModelRole.ChainID:
|
||||
result = newQVariant(item.getChainId())
|
||||
of ModelRole.MaxFeePerGas:
|
||||
result = newQVariant(item.getMaxFeePerGas())
|
||||
of ModelRole.MaxPriorityFeePerGas:
|
||||
result = newQVariant(item.getMaxPriorityFeePerGas())
|
||||
of ModelRole.Input:
|
||||
result = newQVariant(item.getInput())
|
||||
of ModelRole.TxHash:
|
||||
result = newQVariant(item.getTxHash())
|
||||
of ModelRole.MultiTransactionID:
|
||||
result = newQVariant(item.getMultiTransactionID())
|
||||
of ModelRole.IsTimeStamp:
|
||||
result = newQVariant(item.getIsTimeStamp())
|
||||
of ModelRole.IsNFT:
|
||||
result = newQVariant(item.getIsNFT())
|
||||
of ModelRole.BaseGasFees:
|
||||
result = newQVariant(item.getBaseGasFees())
|
||||
of ModelRole.TotalFees:
|
||||
result = newQVariant(item.getTotalFees())
|
||||
of ModelRole.MaxTotalFees:
|
||||
result = newQVariant(item.getMaxTotalFees())
|
||||
of ModelRole.Symbol:
|
||||
result = newQVariant(item.getSymbol())
|
||||
of ModelRole.LoadingTransaction:
|
||||
result = newQVariant(item.getLoadingTransaction())
|
||||
of ModelRole.TokenID:
|
||||
result = newQVariant(item.getTokenID().toString())
|
||||
of ModelRole.NFTName:
|
||||
result = newQVariant(item.getNFTName())
|
||||
of ModelRole.NFTImageURL:
|
||||
result = newQVariant(item.getNFTImageURL())
|
||||
|
||||
proc setItems*(self: Model, items: seq[Item]) =
|
||||
self.beginResetModel()
|
||||
self.items = items
|
||||
self.endResetModel()
|
||||
self.countChanged()
|
||||
|
||||
proc resetItems*(self: Model) =
|
||||
self.beginResetModel()
|
||||
self.items = @[]
|
||||
self.endResetModel()
|
||||
self.countChanged()
|
||||
|
||||
proc getLastTxBlockNumber*(self: Model): string {.slot.} =
|
||||
if (self.items.len == 0):
|
||||
return "0x0"
|
||||
return self.items[^1].getBlockNumber()
|
||||
|
||||
proc hasMoreChanged*(self: Model) {.signal.}
|
||||
|
||||
proc getHasMore*(self: Model): bool {.slot.} =
|
||||
return self.hasMore
|
||||
|
||||
proc setHasMore*(self: Model, hasMore: bool) {.slot.} =
|
||||
self.hasMore = hasMore
|
||||
self.hasMoreChanged()
|
||||
|
||||
QtProperty[bool] hasMore:
|
||||
read = getHasMore
|
||||
write = setHasMore
|
||||
notify = hasMoreChanged
|
||||
|
||||
proc cmpTransactions*(x, y: Item): int =
|
||||
# Sort proc to compare transactions from a single account.
|
||||
# Compares first by block number, then by nonce
|
||||
if x.getBlockNumber().isEmptyOrWhitespace or y.getBlockNumber().isEmptyOrWhitespace :
|
||||
return cmp(x.getTimestamp(), y.getTimestamp())
|
||||
result = cmp(x.getBlockNumber().parseHexInt, y.getBlockNumber().parseHexInt)
|
||||
if result == 0:
|
||||
result = cmp(x.getNonce(), y.getNonce())
|
||||
|
||||
proc addNewTransactions*(self: Model, transactions: seq[Item], wasFetchMore: bool) =
|
||||
if transactions.len == 0:
|
||||
return
|
||||
|
||||
var txs = transactions
|
||||
|
||||
# Reset the model if empty
|
||||
if self.items.len == 0:
|
||||
eth_service_utils.deduplicate(txs, tx => tx.getTxHash())
|
||||
self.setItems(txs)
|
||||
return
|
||||
|
||||
# Concatenate existing and new, filter out duplicates
|
||||
let parentModelIndex = newQModelIndex()
|
||||
defer: parentModelIndex.delete
|
||||
|
||||
var newItems = concat(self.items, txs)
|
||||
eth_service_utils.deduplicate(newItems, tx => tx.getTxHash())
|
||||
|
||||
# Though we claim that we insert rows to preserve listview indices without
|
||||
# model reset, we actually reset the list, but since old items order is not changed
|
||||
# by deduplicate() call, the order is preserved and only new items are added
|
||||
# to the end. For model it looks like we inserted.
|
||||
# Unsorted, sorting is done on UI side
|
||||
self.beginInsertRows(parentModelIndex, self.items.len, newItems.len - 1)
|
||||
self.items = newItems
|
||||
self.endInsertRows()
|
||||
|
||||
self.countChanged()
|
||||
|
||||
proc addPageSizeBuffer*(self: Model, pageSize: int) =
|
||||
if pageSize > 0:
|
||||
self.beginInsertRows(newQModelIndex(), self.items.len, self.items.len + pageSize - 1)
|
||||
for i in 0 ..< pageSize:
|
||||
self.items.add(initLoadingItem())
|
||||
self.endInsertRows()
|
||||
self.countChanged()
|
||||
|
||||
proc removePageSizeBuffer*(self: Model) =
|
||||
for i in 0 ..< self.items.len:
|
||||
if self.items[i].getLoadingTransaction():
|
||||
self.beginRemoveRows(newQModelIndex(), i, self.items.len-1)
|
||||
self.items.delete(i, self.items.len-1)
|
||||
self.endRemoveRows()
|
||||
self.countChanged()
|
||||
return
|
@ -1,142 +0,0 @@
|
||||
import NimQml, stint, json, sequtils, sugar
|
||||
|
||||
import ./io_interface, ./view, ./controller, ./item, ./utils, ./multi_transaction_item
|
||||
import ../io_interface as delegate_interface
|
||||
import ../../../../global/global_singleton
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../../app_service/common/wallet_constants
|
||||
import ../../../../../app_service/service/transaction/service as transaction_service
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
import ../../../../../app_service/service/currency/service as currency_service
|
||||
|
||||
export io_interface
|
||||
|
||||
type
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
delegate: delegate_interface.AccessInterface
|
||||
view: View
|
||||
controller: Controller
|
||||
moduleLoaded: bool
|
||||
|
||||
# Forward declarations
|
||||
method loadTransactions*(self: Module, address: string, toBlock: string = "0x0", limit: int = 20, loadMore: bool = false)
|
||||
|
||||
proc newModule*(
|
||||
delegate: delegate_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
transactionService: transaction_service.Service,
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
networkService: network_service.Service,
|
||||
currencyService: currency_service.Service,
|
||||
): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
result.view = newView(result)
|
||||
result.controller = controller.newController(result, events, transactionService, walletAccountService, networkService, currencyService)
|
||||
result.moduleLoaded = false
|
||||
|
||||
method delete*(self: Module) =
|
||||
self.view.delete
|
||||
self.controller.delete
|
||||
|
||||
method load*(self: Module) =
|
||||
singletonInstance.engine.setRootContextProperty("walletSectionTransactions", newQVariant(self.view))
|
||||
self.controller.init()
|
||||
self.view.load()
|
||||
|
||||
method isLoaded*(self: Module): bool =
|
||||
return self.moduleLoaded
|
||||
|
||||
proc getResolvedSymbol*(self: Module, transaction: TransactionDto): string =
|
||||
if transaction.symbol != "":
|
||||
result = transaction.symbol
|
||||
else:
|
||||
let contractSymbol = self.controller.findTokenSymbolByAddress(transaction.contract)
|
||||
if contractSymbol != "":
|
||||
result = contractSymbol
|
||||
elif transaction.typeValue == "erc20":
|
||||
result = ""
|
||||
else:
|
||||
result = "ETH"
|
||||
|
||||
method transactionsToItems*(self: Module, transactions: seq[TransactionDto], collectibles: seq[CollectibleDto]): seq[Item] =
|
||||
let gweiFormat = self.controller.getCurrencyFormat("Gwei")
|
||||
let ethFormat = self.controller.getCurrencyFormat("ETH")
|
||||
|
||||
transactions.map(t => (block:
|
||||
let resolvedSymbol = self.getResolvedSymbol(t)
|
||||
return transactionToItem(t, resolvedSymbol, self.controller.getCurrencyFormat(resolvedSymbol), ethFormat, gweiFormat)
|
||||
))
|
||||
|
||||
proc setPendingTx(self: Module) =
|
||||
self.view.setPendingTx(self.transactionsToItems(self.controller.watchPendingTransactions(), @[]))
|
||||
|
||||
method setEnabledChainIds*(self: Module) =
|
||||
let enabledChainIds = self.controller.getEnabledChainIds()
|
||||
self.view.setEnabledChainIds(enabledChainIds)
|
||||
|
||||
method refreshTransactions*(self: Module) =
|
||||
self.setEnabledChainIds()
|
||||
self.view.resetTrxHistory()
|
||||
self.view.setPendingTx(self.transactionsToItems(self.controller.getPendingTransactions(), @[]))
|
||||
for account in self.controller.getWalletAccounts():
|
||||
let transactions = self.controller.getAllTransactions(account.address)
|
||||
self.view.setTrxHistoryResult(self.transactionsToItems(transactions, @[]), account.address, wasFetchMore=false)
|
||||
|
||||
method viewDidLoad*(self: Module) =
|
||||
let accounts = self.controller.getWalletAccounts()
|
||||
|
||||
self.moduleLoaded = true
|
||||
self.delegate.transactionsModuleDidLoad()
|
||||
self.setEnabledChainIds()
|
||||
self.setPendingTx()
|
||||
|
||||
method filterChanged*(self: Module, addresses: seq[string], chainIds: seq[int]) =
|
||||
let walletAccount = self.controller.getWalletAccountByAddress(addresses[0])
|
||||
self.view.switchAccount(walletAccount)
|
||||
|
||||
method loadTransactions*(self: Module, address: string, toBlock: string = "0x0", limit: int = 20, loadMore: bool = false) =
|
||||
let toBlockParsed = stint.fromHex(Uint256, toBlock)
|
||||
let txLimit = if toBlock == "0x0":
|
||||
limit
|
||||
else:
|
||||
limit + 1
|
||||
|
||||
self.controller.loadTransactions(address, toBlockParsed, txLimit, loadMore)
|
||||
|
||||
method setTrxHistoryResult*(self: Module, transactions: seq[TransactionDto], collectibles: seq[CollectibleDto], address: string, wasFetchMore: bool) =
|
||||
self.view.setTrxHistoryResult(self.transactionsToItems(transactions, collectibles), address, wasFetchMore)
|
||||
|
||||
method setHistoryFetchState*(self: Module, addresses: seq[string], isFetching: bool) =
|
||||
self.view.setHistoryFetchStateForAccounts(addresses, isFetching)
|
||||
|
||||
method setHistoryFetchState*(self: Module, addresses: seq[string], isFetching: bool, hasMore: bool) =
|
||||
self.view.setHistoryFetchStateForAccounts(addresses, isFetching, hasMore)
|
||||
|
||||
method setHistoryFetchState*(self: Module, address: string, allTxLoaded: bool, isFetching: bool) =
|
||||
self.view.setHistoryFetchState(address, allTxLoaded, isFetching)
|
||||
|
||||
method setIsNonArchivalNode*(self: Module, isNonArchivalNode: bool) =
|
||||
self.view.setIsNonArchivalNode(isNonArchivalNode)
|
||||
|
||||
method getChainIdForChat*(self: Module): int =
|
||||
return self.controller.getChainIdForChat()
|
||||
|
||||
method getChainIdForBrowser*(self: Module): int =
|
||||
return self.controller.getChainIdForBrowser()
|
||||
|
||||
method getLatestBlockNumber*(self: Module, chainId: int): string =
|
||||
return self.controller.getLatestBlockNumber(chainId)
|
||||
|
||||
method transactionWasSent*(self: Module, result: string) =
|
||||
self.view.setPendingTx(self.transactionsToItems(self.controller.getPendingTransactions(), @[]))
|
||||
|
||||
method fetchDecodedTxData*(self: Module, txHash: string, data: string) =
|
||||
self.controller.fetchDecodedTxData(txHash, data)
|
||||
|
||||
method txDecoded*(self: Module, txHash: string, dataDecoded: string) =
|
||||
self.view.txDecoded(txHash, dataDecoded)
|
||||
|
||||
method getNetworkLayer*(self: Module, chainId: int): string =
|
||||
return self.delegate.getNetworkLayer(chainId)
|
@ -1,66 +0,0 @@
|
||||
import strutils, stint
|
||||
import ../../../../global/global_singleton
|
||||
|
||||
import ../../../../../app_service/service/transaction/dto
|
||||
import ../../../../../app_service/service/currency/dto as currency_dto
|
||||
import ../../../shared/wallet_utils
|
||||
import ../../../shared_models/currency_amount
|
||||
|
||||
import ./item
|
||||
import ./multi_transaction_item
|
||||
|
||||
import ./backend/transactions
|
||||
|
||||
proc hex2GweiCurrencyAmount(hexValueStr: string, gweiFormat: CurrencyFormatDto): CurrencyAmount =
|
||||
let value = parseFloat(singletonInstance.utils.hex2Gwei(hexValueStr))
|
||||
return currencyAmountToItem(value, gweiFormat)
|
||||
|
||||
proc hex2EthCurrencyAmount(hexValueStr: string, ethFormat: CurrencyFormatDto): CurrencyAmount =
|
||||
let value = parseFloat(singletonInstance.utils.hex2Eth(hexValueStr))
|
||||
return currencyAmountToItem(value, ethFormat)
|
||||
|
||||
proc hex2TokenCurrencyAmount(hexValueStr: string, tokenFormat: CurrencyFormatDto): CurrencyAmount =
|
||||
let value = parseFloat(singletonInstance.utils.hex2Eth(hexValueStr))
|
||||
return currencyAmountToItem(value, tokenFormat)
|
||||
|
||||
proc transactionToItem*(t: TransactionDto, resolvedSymbol: string, tokenFormat: CurrencyFormatDto, ethFormat: CurrencyFormatDto, gweiFormat: CurrencyFormatDto): Item =
|
||||
return initItem(
|
||||
t.id,
|
||||
t.typeValue,
|
||||
t.address,
|
||||
t.blockNumber,
|
||||
t.blockHash,
|
||||
toInt(t.timestamp),
|
||||
hex2EthCurrencyAmount(t.gasPrice, ethFormat),
|
||||
parseInt(singletonInstance.utils.hex2Dec(t.gasLimit)),
|
||||
parseInt(singletonInstance.utils.hex2Dec(t.gasUsed)),
|
||||
t.nonce,
|
||||
t.txStatus,
|
||||
hex2TokenCurrencyAmount(t.value, tokenFormat),
|
||||
t.fromAddress,
|
||||
t.to,
|
||||
t.contract,
|
||||
t.chainId,
|
||||
hex2GweiCurrencyAmount(t.maxFeePerGas, gweiFormat),
|
||||
hex2GweiCurrencyAmount(t.maxPriorityFeePerGas, gweiFormat),
|
||||
t.input,
|
||||
t.txHash,
|
||||
t.multiTransactionID,
|
||||
false,
|
||||
hex2GweiCurrencyAmount(t.baseGasFees, gweiFormat),
|
||||
hex2GweiCurrencyAmount(t.totalFees, gweiFormat),
|
||||
hex2GweiCurrencyAmount(t.maxTotalFees, gweiFormat),
|
||||
resolvedSymbol
|
||||
)
|
||||
|
||||
proc multiTransactionToItem*(t: MultiTransactionDto): MultiTransactionItem =
|
||||
return initMultiTransactionItem(
|
||||
t.id,
|
||||
t.timestamp,
|
||||
t.fromAddress,
|
||||
t.toAddress,
|
||||
t.fromAsset,
|
||||
t.toAsset,
|
||||
t.fromAmount,
|
||||
t.multiTxType
|
||||
)
|
@ -1,200 +0,0 @@
|
||||
import NimQml, tables, stint, json, strformat, sequtils, strutils, sugar, times, math
|
||||
|
||||
import ./item
|
||||
import ./model
|
||||
import ./io_interface
|
||||
|
||||
import ../../../../global/global_singleton
|
||||
|
||||
import ../../../../../app_service/common/conversion as common_conversion
|
||||
import ../../../../../app_service/service/wallet_account/dto
|
||||
|
||||
type
|
||||
LatestBlockData* = ref object of RootObj
|
||||
blockNumber*: int
|
||||
datetime*: DateTime
|
||||
isLayer1*: bool
|
||||
|
||||
QtObject:
|
||||
type
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
models: Table[string, Model]
|
||||
model: Model
|
||||
modelVariant: QVariant
|
||||
fetchingHistoryState: Table[string, bool]
|
||||
enabledChainIds: seq[int]
|
||||
isNonArchivalNode: bool
|
||||
tempAddress: string
|
||||
latestBlockNumbers: Table[int, LatestBlockData]
|
||||
|
||||
proc delete*(self: View) =
|
||||
self.model.delete
|
||||
self.modelVariant.delete
|
||||
self.QObject.delete
|
||||
|
||||
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||
new(result, delete)
|
||||
result.QObject.setup
|
||||
result.delegate = delegate
|
||||
result.model = newModel()
|
||||
result.modelVariant = newQVariant(result.model)
|
||||
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
||||
proc modelChanged*(self: View) {.signal.}
|
||||
|
||||
proc getModel(self: View): QVariant {.slot.} =
|
||||
return self.modelVariant
|
||||
|
||||
QtProperty[QVariant] model:
|
||||
read = getModel
|
||||
notify = modelChanged
|
||||
|
||||
proc setItems*(self: View, items: seq[Item]) =
|
||||
self.model.setItems(items)
|
||||
|
||||
proc historyWasFetched*(self: View) {.signal.}
|
||||
|
||||
proc loadingTrxHistoryChanged*(self: View, isLoading: bool, address: string) {.signal.}
|
||||
|
||||
proc setHistoryFetchState*(self: View, address: string, allTxLoaded: bool, isFetching: bool) =
|
||||
if self.models.hasKey(address):
|
||||
if not isFetching:
|
||||
self.models[address].removePageSizeBuffer()
|
||||
elif isFetching and self.models[address].getCount() == 0:
|
||||
self.models[address].addPageSizeBuffer(20)
|
||||
self.models[address].setHasMore(not allTxLoaded)
|
||||
self.fetchingHistoryState[address] = isFetching
|
||||
self.loadingTrxHistoryChanged(isFetching, address)
|
||||
|
||||
proc isFetchingHistory*(self: View, address: string): bool {.slot.} =
|
||||
if self.fetchingHistoryState.hasKey(address):
|
||||
return self.fetchingHistoryState[address]
|
||||
return true
|
||||
|
||||
proc isHistoryFetched*(self: View, address: string): bool {.slot.} =
|
||||
return self.model.getCount() > 0
|
||||
|
||||
proc loadTransactionsForAccount*(self: View, address: string, toBlock: string = "0x0", limit: int = 20, loadMore: bool = false) {.slot.} =
|
||||
if self.models.hasKey(address):
|
||||
self.setHistoryFetchState(address, allTxLoaded=not self.models[address].getHasMore(), isFetching=true)
|
||||
self.models[address].addPageSizeBuffer(limit)
|
||||
self.delegate.loadTransactions(address, toBlock, limit, loadMore)
|
||||
|
||||
proc resetTrxHistory*(self: View) =
|
||||
for address in self.models.keys:
|
||||
self.models[address].resetItems()
|
||||
|
||||
proc setTrxHistoryResult*(self: View, transactions: seq[Item], address: string, wasFetchMore: bool) =
|
||||
var toAddTransactions: seq[Item] = @[]
|
||||
for tx in transactions:
|
||||
if not self.enabledChainIds.contains(tx.getChainId()):
|
||||
continue
|
||||
|
||||
toAddTransactions.add(tx)
|
||||
|
||||
if not self.models.hasKey(address):
|
||||
self.models[address] = newModel()
|
||||
|
||||
self.models[address].removePageSizeBuffer()
|
||||
self.models[address].addNewTransactions(toAddTransactions, wasFetchMore)
|
||||
if self.fetchingHistoryState.hasKey(address) and self.fetchingHistoryState[address] and wasFetchMore:
|
||||
self.models[address].addPageSizeBuffer(toAddTransactions.len)
|
||||
|
||||
proc setHistoryFetchStateForAccounts*(self: View, addresses: seq[string], isFetching: bool) =
|
||||
for address in addresses:
|
||||
if self.models.hasKey(address):
|
||||
self.setHistoryFetchState(address, allTxLoaded = not self.models[address].getHasMore(), isFetching)
|
||||
else:
|
||||
self.setHistoryFetchState(address, allTxLoaded = false, isFetching)
|
||||
|
||||
proc setHistoryFetchStateForAccounts*(self: View, addresses: seq[string], isFetching: bool, hasMore: bool) =
|
||||
for address in addresses:
|
||||
self.setHistoryFetchState(address, allTxLoaded = not hasMore, isFetching)
|
||||
|
||||
proc setModel*(self: View, address: string) {.slot.} =
|
||||
if not self.models.hasKey(address):
|
||||
self.models[address] = newModel()
|
||||
|
||||
self.model = self.models[address]
|
||||
self.modelVariant = newQVariant(self.model)
|
||||
self.modelChanged()
|
||||
|
||||
proc switchAccount*(self: View, walletAccount: WalletAccountDto) =
|
||||
self.setModel(walletAccount.address)
|
||||
|
||||
proc getIsNonArchivalNode(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.isNonArchivalNode)
|
||||
|
||||
proc setEnabledChainIds*(self: View, chainIds: seq[int]) =
|
||||
self.enabledChainIds = chainIds
|
||||
|
||||
proc isNonArchivalNodeChanged(self: View) {.signal.}
|
||||
|
||||
proc setIsNonArchivalNode*(self: View, isNonArchivalNode: bool) =
|
||||
self.isNonArchivalNode = isNonArchivalNode
|
||||
self.isNonArchivalNodeChanged()
|
||||
|
||||
QtProperty[QVariant] isNonArchivalNode:
|
||||
read = getIsNonArchivalNode
|
||||
notify = isNonArchivalNodeChanged
|
||||
|
||||
proc getChainIdForChat*(self: View): int {.slot.} =
|
||||
return self.delegate.getChainIdForChat()
|
||||
|
||||
proc getChainIdForBrowser*(self: View): int {.slot.} =
|
||||
return self.delegate.getChainIdForBrowser()
|
||||
|
||||
proc getLatestBlockNumber*(self: View, chainId: int): int {.slot.} =
|
||||
if self.latestBlockNumbers.hasKey(chainId):
|
||||
let blockData = self.latestBlockNumbers[chainId]
|
||||
let timeDiff = (now() - blockData.datetime)
|
||||
var multiplier = -1.0
|
||||
if blockData.isLayer1:
|
||||
multiplier = 0.083 # 1 every 12 seconds
|
||||
else:
|
||||
case chainId:
|
||||
of 10: # Optimism
|
||||
multiplier = 0.5 # 1 every 2 second
|
||||
of 42161: # Arbitrum
|
||||
multiplier = 3.96 # around 4 every 1 second
|
||||
else:
|
||||
multiplier = -1.0
|
||||
if multiplier >= 0.0 and timeDiff < initDuration(minutes = 10):
|
||||
let blockNumDiff = inSeconds(timeDiff).float64 * multiplier
|
||||
return (blockData.blockNumber + (int)round(blockNumDiff))
|
||||
|
||||
let latestBlockNumber = self.delegate.getLatestBlockNumber(chainId)
|
||||
let latestBlockNumberNumber = parseInt(singletonInstance.utils.hex2Dec(latestBlockNumber))
|
||||
self.latestBlockNumbers[chainId] = LatestBlockData(
|
||||
blockNumber: latestBlockNumberNumber,
|
||||
datetime: now(),
|
||||
isLayer1: self.delegate.getNetworkLayer(chainId) == "1"
|
||||
)
|
||||
return latestBlockNumberNumber
|
||||
|
||||
proc setPendingTx*(self: View, pendingTx: seq[Item]) =
|
||||
for tx in pendingTx:
|
||||
if not self.enabledChainIds.contains(tx.getChainId()):
|
||||
continue
|
||||
|
||||
let fromAddress = tx.getfrom()
|
||||
if not self.models.hasKey(fromAddress):
|
||||
self.models[fromAddress] = newModel()
|
||||
self.models[fromAddress].addNewTransactions(@[tx], wasFetchMore=false)
|
||||
|
||||
proc prepareTransactionsForAddress*(self: View, address: string) {.slot.} =
|
||||
self.tempAddress = address
|
||||
|
||||
proc getTransactions*(self: View): QVariant {.slot.} =
|
||||
if self.models.hasKey(self.tempAddress):
|
||||
return newQVariant(self.models[self.tempAddress])
|
||||
else:
|
||||
return newQVariant()
|
||||
|
||||
proc fetchDecodedTxData*(self: View, txHash: string, data: string) {.slot.} =
|
||||
self.delegate.fetchDecodedTxData(txHash, data)
|
||||
|
||||
proc txDecoded*(self: View, txHash: string, dataDecoded: string) {.signal.}
|
@ -16,8 +16,10 @@ QtObject:
|
||||
tmpAmount: float # shouldn't be used anywhere except in prepare*/getPrepared* procs
|
||||
tmpSymbol: string # shouldn't be used anywhere except in prepare*/getPrepared* procs
|
||||
activityController: activityc.Controller
|
||||
tmpActivityController: activityc.Controller
|
||||
collectiblesController: collectiblesc.Controller
|
||||
collectibleDetailsController: collectible_detailsc.Controller
|
||||
isNonArchivalNode: bool
|
||||
|
||||
proc setup(self: View) =
|
||||
self.QObject.setup
|
||||
@ -25,10 +27,11 @@ QtObject:
|
||||
proc delete*(self: View) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newView*(delegate: io_interface.AccessInterface, activityController: activityc.Controller, collectiblesController: collectiblesc.Controller, collectibleDetailsController: collectible_detailsc.Controller): View =
|
||||
proc newView*(delegate: io_interface.AccessInterface, activityController: activityc.Controller, tmpActivityController: activityc.Controller, collectiblesController: collectiblesc.Controller, collectibleDetailsController: collectible_detailsc.Controller): View =
|
||||
new(result, delete)
|
||||
result.delegate = delegate
|
||||
result.activityController = activityController
|
||||
result.tmpActivityController = tmpActivityController
|
||||
result.collectiblesController = collectiblesController
|
||||
result.collectibleDetailsController = collectibleDetailsController
|
||||
result.setup()
|
||||
@ -135,3 +138,32 @@ QtObject:
|
||||
return newQVariant(self.collectibleDetailsController)
|
||||
QtProperty[QVariant] collectibleDetailsController:
|
||||
read = getCollectibleDetailsController
|
||||
|
||||
proc getTmpActivityController(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.tmpActivityController)
|
||||
QtProperty[QVariant] tmpActivityController:
|
||||
read = getTmpActivityController
|
||||
|
||||
proc getChainIdForChat*(self: View): int {.slot.} =
|
||||
return self.delegate.getChainIdForChat()
|
||||
|
||||
proc getLatestBlockNumber*(self: View, chainId: int): string {.slot.} =
|
||||
return self.delegate.getLatestBlockNumber(chainId)
|
||||
|
||||
proc fetchDecodedTxData*(self: View, txHash: string, data: string) =
|
||||
self.delegate.fetchDecodedTxData(txHash, data)
|
||||
|
||||
proc getIsNonArchivalNode(self: View): bool {.slot.} =
|
||||
return self.isNonArchivalNode
|
||||
|
||||
proc isNonArchivalNodeChanged(self: View) {.signal.}
|
||||
|
||||
proc setIsNonArchivalNode*(self: View, isNonArchivalNode: bool) =
|
||||
self.isNonArchivalNode = isNonArchivalNode
|
||||
self.isNonArchivalNodeChanged()
|
||||
|
||||
QtProperty[bool] isNonArchivalNode:
|
||||
read = getIsNonArchivalNode
|
||||
notify = isNonArchivalNodeChanged
|
||||
|
||||
proc txDecoded*(self: View, txHash: string, dataDecoded: string) {.signal.}
|
||||
|
@ -49,7 +49,7 @@ QtObject:
|
||||
result.threadpool = threadpool
|
||||
result.tokenService = tokenService
|
||||
result.settingsService = settingsService
|
||||
|
||||
|
||||
proc init*(self: Service) =
|
||||
self.events.on(SignalType.Wallet.event) do(e:Args):
|
||||
var data = WalletSignal(e)
|
||||
|
@ -12,51 +12,6 @@ proc sortAsc[T](t1, t2: T): int =
|
||||
elif (t1.fromNetwork.chainId < t2.fromNetwork.chainId): return -1
|
||||
else: return 0
|
||||
|
||||
type
|
||||
LoadTransactionsTaskArg* = ref object of QObjectTaskArg
|
||||
chainId: int
|
||||
address: string
|
||||
toBlock: Uint256
|
||||
limit: int
|
||||
collectiblesLimit: int
|
||||
loadMore: bool
|
||||
allTxLoaded: bool
|
||||
|
||||
const loadTransactionsTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[LoadTransactionsTaskArg](argEncoded)
|
||||
let output = %* {
|
||||
"address": arg.address,
|
||||
"chainId": arg.chainId,
|
||||
"history": "",
|
||||
"collectibles": "",
|
||||
"loadMore": arg.loadMore,
|
||||
"allTxLoaded": ""
|
||||
}
|
||||
try:
|
||||
let limitAsHex = "0x" & eth_utils.stripLeadingZeros(arg.limit.toHex)
|
||||
let response = transactions.getTransfersByAddress(arg.chainId, arg.address, arg.toBlock, limitAsHex, arg.loadMore).result
|
||||
output["history"] = response
|
||||
output["allTxLoaded"] = %(response.getElems().len < arg.limit)
|
||||
|
||||
# Fetch collectibles for transactions
|
||||
var uniqueIds: seq[collectibles.CollectibleUniqueID] = @[]
|
||||
for txJson in response.getElems():
|
||||
let tx = txJson.toTransactionDto()
|
||||
if tx.typeValue == ERC721_TRANSACTION_TYPE:
|
||||
let nftId = collectibles.CollectibleUniqueID(
|
||||
chainID: arg.chainId,
|
||||
contractAddress: tx.contract,
|
||||
tokenID: tx.tokenId
|
||||
)
|
||||
if not uniqueIds.any(x => (x == nftId)):
|
||||
uniqueIds.add(nftId)
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error loadTransactionsTask: ", errDesription
|
||||
|
||||
arg.finish(output)
|
||||
|
||||
|
||||
type
|
||||
GetSuggestedRoutesTaskArg* = ref object of QObjectTaskArg
|
||||
account: string
|
||||
|
@ -24,11 +24,6 @@ type
|
||||
proc event*(self:PendingTransactionTypeDto):string =
|
||||
result = "transaction:" & $self
|
||||
|
||||
# Deprecated type, to be removed along with transaction service/module
|
||||
type
|
||||
CollectibleDto* = ref object of RootObj
|
||||
dummy: string
|
||||
|
||||
type
|
||||
TransactionDto* = ref object of RootObj
|
||||
id*: string
|
||||
|
@ -37,13 +37,8 @@ include ../../common/json_utils
|
||||
const collectiblesLimit = 200
|
||||
|
||||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_TRANSACTIONS_LOADED* = "transactionsLoaded"
|
||||
const SIGNAL_TRANSACTION_SENT* = "transactionSent"
|
||||
const SIGNAL_SUGGESTED_ROUTES_READY* = "suggestedRoutesReady"
|
||||
const SIGNAL_TRANSACTION_LOADING_COMPLETED_FOR_ALL_NETWORKS* = "transactionsLoadingCompleteForAllNetworks"
|
||||
# TODO: soon to be removed with old transactions module
|
||||
const SIGNAL_HISTORY_FETCHING* = "historyFetching"
|
||||
const SIGNAL_HISTORY_READY* = "historyReady"
|
||||
const SIGNAL_HISTORY_NON_ARCHIVAL_NODE* = "historyNonArchivalNode"
|
||||
const SIGNAL_HISTORY_ERROR* = "historyError"
|
||||
const SIGNAL_CRYPTO_SERVICES_READY* = "cryptoServicesReady"
|
||||
@ -75,20 +70,6 @@ proc `$`*(self: TransactionMinedArgs): string =
|
||||
data: {self.data},
|
||||
]"""
|
||||
|
||||
|
||||
type
|
||||
HistoryArgs* = ref object of Args
|
||||
addresses*: seq[string]
|
||||
|
||||
type
|
||||
TransactionsLoadedArgs* = ref object of Args
|
||||
transactions*: seq[TransactionDto]
|
||||
collectibles*: seq[CollectibleDto]
|
||||
address*: string
|
||||
wasFetchMore*: bool
|
||||
allTxLoaded*: bool
|
||||
tempLoadingTx*: int
|
||||
|
||||
type
|
||||
TransactionSentArgs* = ref object of Args
|
||||
result*: string
|
||||
@ -112,12 +93,6 @@ QtObject:
|
||||
networkService: network_service.Service
|
||||
settingsService: settings_service.Service
|
||||
tokenService: token_service.Service
|
||||
txCounter: Table[string, seq[int]]
|
||||
allTxLoaded: Table[string, bool]
|
||||
allTransactions: Table[string, Table[string, TransactionDto]]
|
||||
|
||||
# Forward declaration
|
||||
proc loadTransactions*(self: Service, address: string, toBlock: Uint256, limit: int = 20, loadMore: bool = false)
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.QObject.delete
|
||||
@ -136,18 +111,11 @@ QtObject:
|
||||
result.networkService = networkService
|
||||
result.settingsService = settingsService
|
||||
result.tokenService = tokenService
|
||||
result.txCounter = initTable[string, seq[int]]()
|
||||
result.allTxLoaded = initTable[string, bool]()
|
||||
result.allTransactions = initTable[string, Table[string, TransactionDto]]()
|
||||
|
||||
proc init*(self: Service) =
|
||||
self.events.on(SignalType.Wallet.event) do(e:Args):
|
||||
var data = WalletSignal(e)
|
||||
case data.eventType:
|
||||
of transactions.EventRecentHistoryReady:
|
||||
for account in data.accounts:
|
||||
self.loadTransactions(account, stint.fromHex(Uint256, "0x0"))
|
||||
self.events.emit(SIGNAL_HISTORY_READY, HistoryArgs(addresses: data.accounts))
|
||||
of transactions.EventNonArchivalNodeDetected:
|
||||
self.events.emit(SIGNAL_HISTORY_NON_ARCHIVAL_NODE, Args())
|
||||
of transactions.EventFetchingHistoryError:
|
||||
@ -170,12 +138,6 @@ QtObject:
|
||||
let allPendingTransactions = self.getPendingTransactions()
|
||||
return allPendingTransactions.filter(x => x.typeValue == $transactionType)
|
||||
|
||||
proc getAllTransactions*(self: Service, address: string): seq[TransactionDto] =
|
||||
if not self.allTransactions.hasKey(address):
|
||||
return @[]
|
||||
|
||||
return toSeq(self.allTransactions[address].values)
|
||||
|
||||
proc watchTransactionResult*(self: Service, watchTxResult: string) {.slot.} =
|
||||
let watchTxResult = parseJson(watchTxResult)
|
||||
let success = watchTxResult["isSuccessfull"].getBool
|
||||
@ -237,65 +199,6 @@ QtObject:
|
||||
self.watchTransaction(tx.txHash, tx.fromAddress, tx.to, tx.typeValue, tx.input, tx.chainId, track = false)
|
||||
return pendingTransactions
|
||||
|
||||
proc onTransactionsLoaded*(self: Service, historyJSON: string) {.slot.} =
|
||||
let historyData = parseJson(historyJSON)
|
||||
let address = historyData["address"].getStr
|
||||
let chainID = historyData["chainId"].getInt
|
||||
let wasFetchMore = historyData["loadMore"].getBool
|
||||
let allTxLoaded = historyData["allTxLoaded"].getBool
|
||||
var transactions: seq[TransactionDto] = @[]
|
||||
var collectibles: seq[CollectibleDto] = @[]
|
||||
|
||||
for tx in historyData["history"].getElems():
|
||||
let dto = tx.toTransactionDto()
|
||||
self.allTransactions.mgetOrPut(address, initTable[string, TransactionDto]())[dto.txHash] = dto
|
||||
transactions.add(dto)
|
||||
|
||||
if self.allTxLoaded.hasKey(address):
|
||||
self.allTxLoaded[address] = self.allTxLoaded[address] and allTxLoaded
|
||||
else:
|
||||
self.allTxLoaded[address] = allTxLoaded
|
||||
|
||||
# emit event
|
||||
self.events.emit(SIGNAL_TRANSACTIONS_LOADED, TransactionsLoadedArgs(
|
||||
transactions: transactions,
|
||||
collectibles: collectibles,
|
||||
address: address,
|
||||
wasFetchMore: wasFetchMore
|
||||
))
|
||||
|
||||
# when requests for all networks are completed then set loading state as completed
|
||||
if self.txCounter.hasKey(address) and self.allTxLoaded.hasKey(address) :
|
||||
var chainIDs = self.txCounter[address]
|
||||
chainIDs.del(chainIDs.find(chainID))
|
||||
self.txCounter[address] = chainIDs
|
||||
if self.txCounter[address].len == 0:
|
||||
self.txCounter.del(address)
|
||||
self.events.emit(SIGNAL_TRANSACTION_LOADING_COMPLETED_FOR_ALL_NETWORKS, TransactionsLoadedArgs(address: address, allTxLoaded: self.allTxLoaded[address]))
|
||||
|
||||
proc loadTransactions*(self: Service, address: string, toBlock: Uint256, limit: int = 20, loadMore: bool = false) =
|
||||
let networks = self.networkService.getNetworks()
|
||||
self.allTxLoaded.del(address)
|
||||
|
||||
if not self.txCounter.hasKey(address):
|
||||
var networkChains: seq[int] = @[]
|
||||
self.txCounter[address] = networkChains
|
||||
for network in networks:
|
||||
networkChains.add(network.chainId)
|
||||
let arg = LoadTransactionsTaskArg(
|
||||
address: address,
|
||||
tptr: cast[ByteAddress](loadTransactionsTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onTransactionsLoaded",
|
||||
toBlock: toBlock,
|
||||
limit: limit,
|
||||
collectiblesLimit: collectiblesLimit,
|
||||
loadMore: loadMore,
|
||||
chainId: network.chainId,
|
||||
)
|
||||
self.txCounter[address] = networkChains
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc createApprovalPath*(self: Service, route: TransactionPathDto, from_addr: string, toAddress: Address, gasFees: string): TransactionBridgeDto =
|
||||
var txData = TransactionDataDto()
|
||||
let approve = Approve(
|
||||
|
@ -358,6 +358,7 @@ proc fromJson*(e: JsonNode, T: typedesc[FilterResponse]): FilterResponse {.inlin
|
||||
)
|
||||
|
||||
rpc(filterActivityAsync, "wallet"):
|
||||
requestId: int32
|
||||
addresses: seq[string]
|
||||
chainIds: seq[ChainId]
|
||||
filter: ActivityFilter
|
||||
@ -388,6 +389,7 @@ proc fromJson*(e: JsonNode, T: typedesc[GetRecipientsResponse]): GetRecipientsRe
|
||||
)
|
||||
|
||||
rpc(getRecipientsAsync, "wallet"):
|
||||
requestId: int32
|
||||
offset: int
|
||||
limit: int
|
||||
|
||||
@ -403,4 +405,5 @@ proc fromJson*(e: JsonNode, T: typedesc[GetOldestTimestampResponse]): GetOldestT
|
||||
)
|
||||
|
||||
rpc(getOldestActivityTimestampAsync, "wallet"):
|
||||
requestId: int32
|
||||
addresses: seq[string]
|
||||
|
@ -38,7 +38,6 @@ SplitView {
|
||||
RootStore.getGasEthValue = (gasAmount, gasPrice) => { return (gasAmount * Math.pow(10, -9)).toPrecision(5) }
|
||||
RootStore.getNetworkLayer = (chainId) => { return 1 }
|
||||
RootStore.currentCurrency = "USD"
|
||||
RootStore.history = historyMockup
|
||||
|
||||
root.rootStoreReady = true
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ QtObject {
|
||||
|
||||
function switchAccountByAddress(address) {
|
||||
browserSectionCurrentAccount.switchAccountByAddress(address)
|
||||
walletSectionTransactions.setModel(address)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -384,6 +384,14 @@ QtObject {
|
||||
communitiesModuleInst.requestToJoinCommunityWithAuthenticationWithSharedAddresses(communityId, ensName, JSON.stringify(addressesToShare), airdropAddress)
|
||||
}
|
||||
|
||||
function getChainIdForChat() {
|
||||
return walletSection.getChainIdForChat()
|
||||
}
|
||||
|
||||
function getLatestBlockNumber(chainId) {
|
||||
return walletSection.getChainIdForSend(chainId)
|
||||
}
|
||||
|
||||
function userCanJoin(id) {
|
||||
return communitiesModuleInst.userCanJoin(id)
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ QtObject {
|
||||
property var walletSectionInst: walletSection
|
||||
property var totalCurrencyBalance: walletSection.totalCurrencyBalance
|
||||
property var activityController: walletSection.activityController
|
||||
property var tmpActivityController: walletSection.tmpActivityController
|
||||
property string signingPhrase: walletSection.signingPhrase
|
||||
property string mnemonicBackedUp: walletSection.isMnemonicBackedUp
|
||||
|
||||
@ -143,7 +144,7 @@ QtObject {
|
||||
}
|
||||
|
||||
function getLatestBlockNumber(chainId) {
|
||||
return walletSectionTransactions.getLatestBlockNumber(chainId)
|
||||
return walletSection.getLatestBlockNumber(chainId)
|
||||
}
|
||||
|
||||
function setFilterAddress(address) {
|
||||
|
@ -33,10 +33,10 @@ Item {
|
||||
|
||||
onTransactionChanged: {
|
||||
d.decodedInputData = ""
|
||||
if (!transaction || !transaction.input || !RootStore.history)
|
||||
if (!transaction || !transaction.input)
|
||||
return
|
||||
d.loadingInputDate = true
|
||||
RootStore.history.fetchDecodedTxData(transaction.txHash, transaction.input)
|
||||
walletSection.fetchDecodedTxData(transaction.txHash, transaction.input)
|
||||
}
|
||||
|
||||
QtObject {
|
||||
@ -92,7 +92,7 @@ Item {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: RootStore.history
|
||||
target: RootStore.walletSectionInst
|
||||
function onTxDecoded(txHash: string, dataDecoded: string) {
|
||||
if (!root.isTransactionValid || txHash !== root.transaction.txHash)
|
||||
return
|
||||
|
@ -169,14 +169,6 @@ QtObject {
|
||||
return walletSectionSendInst.getEstimatedTime(chainId, maxFeePerGas)
|
||||
}
|
||||
|
||||
function getChainIdForChat() {
|
||||
return walletSectionTransactions.getChainIdForChat()
|
||||
}
|
||||
|
||||
function getChainIdForBrowser() {
|
||||
return walletSectionTransactions.getChainIdForBrowser()
|
||||
}
|
||||
|
||||
function hex2Eth(value) {
|
||||
return globalUtils.hex2Eth(value)
|
||||
}
|
||||
|
@ -5,10 +5,6 @@ import utils 1.0
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
// property var utilsModelInst: !!utilsModel ? utilsModel : null
|
||||
// property var chatsModelInst: !!chatsModel ?chatsModel : null
|
||||
// property var walletModelInst: !!walletModel ? walletModel : null
|
||||
// property var profileModelInst: !!profileModel ? profileModel : null
|
||||
|
||||
property var profileSectionModuleInst: profileSectionModule
|
||||
property var privacyModule: profileSectionModuleInst.privacyModule
|
||||
@ -25,29 +21,20 @@ QtObject {
|
||||
property bool isTenorWarningAccepted: !!accountSensitiveSettings ? accountSensitiveSettings.isTenorWarningAccepted : false
|
||||
property bool displayChatImages: !!accountSensitiveSettings ? accountSensitiveSettings.displayChatImages : false
|
||||
|
||||
// property string signingPhrase: !!walletModelInst ? walletModelInst.utilsView.signingPhrase : ""
|
||||
// property string gasPrice: !!walletModelInst ? walletModelInst.gasView.gasPrice : "0"
|
||||
// property string gasEthValue: !!walletModelInst ? walletModelInst.gasView.getGasEthValue : "0"
|
||||
|
||||
property CurrenciesStore currencyStore: CurrenciesStore {}
|
||||
property string currentCurrency: Global.appIsReady? walletSection.currentCurrency : ""
|
||||
// property string defaultCurrency: !!walletModelInst ? walletModelInst.balanceView.defaultCurrency : "0"
|
||||
// property string fiatValue: !!walletModelInst ? walletModelInst.balanceView.getFiatValue : "0"
|
||||
// property string cryptoValue: !!walletModelInst ? walletModelInst.balanceView.getCryptoValue : "0"
|
||||
property string currentCurrency: Global.appIsReady? walletSectionInst.currentCurrency : ""
|
||||
|
||||
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.status.loadingData
|
||||
readonly property bool newDataAvailable: Global.appIsReady && walletSection.activityController.status.newDataAvailable
|
||||
readonly property var transactionActivityStatus: Global.appIsReady ? walletSection.activityController.status : null
|
||||
readonly property var transactionActivityStatus: Global.appIsReady ? walletSectionInst.activityController.status : null
|
||||
|
||||
property var historyTransactions: Global.appIsReady? walletSectionInst.activityController.model : null
|
||||
readonly property bool loadingHistoryTransactions: Global.appIsReady && walletSectionInst.activityController.status.loadingData
|
||||
readonly property bool newDataAvailable: Global.appIsReady && walletSectionInst.activityController.status.newDataAvailable
|
||||
property bool isNonArchivalNode: Global.appIsReady && walletSectionInst.isNonArchivalNode
|
||||
|
||||
property bool isNonArchivalNode: history ? history.isNonArchivalNode
|
||||
: false
|
||||
property var marketValueStore: TokenMarketValuesStore{}
|
||||
|
||||
function resetFilter() {
|
||||
walletSection.activityController.updateFilter()
|
||||
walletSectionInst.activityController.updateFilter()
|
||||
}
|
||||
|
||||
function getNetworkColor(chainId) {
|
||||
@ -185,12 +172,12 @@ QtObject {
|
||||
|| !RootStore.historyTransactions.hasMore
|
||||
|| loadingHistoryTransactions)
|
||||
return
|
||||
walletSection.activityController.loadMoreItems()
|
||||
walletSectionInst.activityController.loadMoreItems()
|
||||
}
|
||||
|
||||
function updateTransactionFilter() {
|
||||
if (transactionActivityStatus.isFilterDirty)
|
||||
walletSection.activityController.updateFilter()
|
||||
walletSectionInst.activityController.updateFilter()
|
||||
}
|
||||
|
||||
function hex2Eth(value) {
|
||||
|
@ -14,16 +14,18 @@ QtObject {
|
||||
property var contactStore: profileSectionStore.contactsStore
|
||||
|
||||
property var mainModuleInst: mainModule
|
||||
property var walletSectionTransactionsInst: walletSectionTransactions
|
||||
property var walletSectionSendInst: walletSectionSend
|
||||
property var walletSectionInst: walletSection
|
||||
|
||||
property string currentCurrency: walletSection.currentCurrency
|
||||
property var tmpActivityController: walletSectionInst.tmpActivityController
|
||||
|
||||
property string currentCurrency: walletSectionInst.currentCurrency
|
||||
property var allNetworks: networksModule.all
|
||||
property var overview: walletSectionOverview
|
||||
property var accounts: walletSectionSendInst.accounts
|
||||
property var senderAccounts: walletSectionSendInst.senderAccounts
|
||||
property var selectedSenderAccount: walletSectionSendInst.selectedSenderAccount
|
||||
property string signingPhrase: walletSection.signingPhrase
|
||||
property string signingPhrase: walletSectionInst.signingPhrase
|
||||
property var savedAddressesModel: SortFilterProxyModel {
|
||||
sourceModel: walletSectionSavedAddresses.model
|
||||
filters: [
|
||||
@ -86,14 +88,6 @@ QtObject {
|
||||
return walletSectionSendInst.getEstimatedTime(chainId, maxFeePerGas)
|
||||
}
|
||||
|
||||
function getChainIdForChat() {
|
||||
return walletSectionTransactions.getChainIdForChat()
|
||||
}
|
||||
|
||||
function getChainIdForBrowser() {
|
||||
return walletSectionTransactions.getChainIdForBrowser()
|
||||
}
|
||||
|
||||
function suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, sendType, lockedInAmounts) {
|
||||
walletSectionSendInst.suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, sendType, JSON.stringify(lockedInAmounts))
|
||||
}
|
||||
@ -288,14 +282,6 @@ QtObject {
|
||||
return {}
|
||||
}
|
||||
|
||||
function prepareTransactionsForAddress(address) {
|
||||
walletSectionTransactions.prepareTransactionsForAddress(address)
|
||||
}
|
||||
|
||||
function getTransactions() {
|
||||
return walletSectionTransactions.getTransactions()
|
||||
}
|
||||
|
||||
function getAllNetworksSupportedPrefix() {
|
||||
return networksModule.getAllNetworksSupportedPrefix()
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ Loader {
|
||||
break
|
||||
}
|
||||
case TabAddressSelectorView.Type.RecentsAddress: {
|
||||
let isIncoming = root.selectedRecipient.to === root.selectedRecipient.address
|
||||
root.addressText = isIncoming ? root.selectedRecipient.from : root.selectedRecipient.to
|
||||
let isIncoming = root.selectedRecipient.txType === Constants.TransactionType.Receive
|
||||
root.addressText = isIncoming ? root.selectedRecipient.sender : root.selectedRecipient.recipient
|
||||
root.item.input.text = root.addressText
|
||||
return
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import "../panels"
|
||||
import "../controls"
|
||||
import "../views"
|
||||
@ -118,7 +120,7 @@ Item {
|
||||
Rectangle {
|
||||
id: myAccountsRect
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.maximumHeight : myAccounts.height
|
||||
Layout.maximumHeight: myAccounts.height
|
||||
color: Theme.palette.indirectColor1
|
||||
radius: 8
|
||||
|
||||
@ -147,11 +149,34 @@ Item {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: recentsRect
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.maximumHeight : recents.height
|
||||
color: Theme.palette.indirectColor1
|
||||
radius: 8
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
updateRecentsActivity()
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onSelectedAccountChanged() {
|
||||
if (visible) {
|
||||
recentsRect.updateRecentsActivity()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateRecentsActivity() {
|
||||
if(root.selectedAccount) {
|
||||
root.store.tmpActivityController.setFilterAddressesJson(JSON.stringify([root.selectedAccount.address]))
|
||||
}
|
||||
root.store.tmpActivityController.updateFilter()
|
||||
}
|
||||
|
||||
StatusListView {
|
||||
id: recents
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
@ -172,44 +197,38 @@ Item {
|
||||
|
||||
delegate: StatusListItem {
|
||||
id: listItem
|
||||
property bool isIncoming: root.selectedAccount ? to === root.selectedAccount.address : false
|
||||
|
||||
property var entry: activityEntry
|
||||
property bool isIncoming: entry.txType === Constants.TransactionType.Receive
|
||||
|
||||
implicitWidth: ListView.view.width
|
||||
height: visible ? 64 : 0
|
||||
title: loading ? Constants.dummyText : isIncoming ? StatusQUtils.Utils.elideText(from,6,4) : StatusQUtils.Utils.elideText(to,6,4)
|
||||
subTitle: LocaleUtils.getTimeDifference(new Date(parseInt(timestamp) * 1000), new Date())
|
||||
title: isIncoming ? StatusQUtils.Utils.elideText(entry.sender,6,4) : StatusQUtils.Utils.elideText(entry.recipient,6,4)
|
||||
subTitle: LocaleUtils.getTimeDifference(new Date(parseInt(entry.timestamp) * 1000), new Date())
|
||||
statusListItemTitle.elide: Text.ElideMiddle
|
||||
statusListItemTitle.wrapMode: Text.NoWrap
|
||||
radius: 0
|
||||
color: sensor.containsMouse || highlighted ? Theme.palette.baseColor2 : "transparent"
|
||||
statusListItemComponentsSlot.spacing: 5
|
||||
loading: loadingTransaction
|
||||
components: [
|
||||
StatusIcon {
|
||||
id: transferIcon
|
||||
height: 15
|
||||
width: 15
|
||||
color: isIncoming ? Style.current.success : Style.current.danger
|
||||
icon: isIncoming ? "arrow-down" : "arrow-up"
|
||||
color: listItem.isIncoming ? Style.current.success : Style.current.danger
|
||||
icon: listItem.isIncoming ? "arrow-down" : "arrow-up"
|
||||
rotation: 45
|
||||
visible: !listItem.loading
|
||||
},
|
||||
StatusTextWithLoadingState {
|
||||
id: contactsLabel
|
||||
loading: listItem.loading
|
||||
font.pixelSize: 15
|
||||
customColor: Theme.palette.directColor1
|
||||
text: loading ? Constants.dummyText : LocaleUtils.currencyAmountToLocaleString(value)
|
||||
text: LocaleUtils.currencyAmountToLocaleString(entry.amountCurrency)
|
||||
}
|
||||
]
|
||||
onClicked: recipientSelected(model, TabAddressSelectorView.Type.RecentsAddress)
|
||||
onClicked: recipientSelected(entry, TabAddressSelectorView.Type.RecentsAddress)
|
||||
}
|
||||
|
||||
model: {
|
||||
if(root.selectedAccount) {
|
||||
root.store.prepareTransactionsForAddress(root.selectedAccount.address)
|
||||
return root.store.getTransactions()
|
||||
}
|
||||
}
|
||||
model: root.store.tmpActivityController.model
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ Item {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
property var store
|
||||
property var store // Expected ui/app/AppLayouts/Chat/stores/RootStore.qml
|
||||
property var contactsStore
|
||||
|
||||
property var token
|
||||
|
@ -16,7 +16,7 @@ Item {
|
||||
width: rectangleBubble.width
|
||||
height: rectangleBubble.height
|
||||
|
||||
property var store
|
||||
property var store // expected ui/app/AppLayouts/Chat/stores/RootStore.qml
|
||||
property var contactsStore
|
||||
|
||||
property var transactionParams
|
||||
|
2
vendor/status-go
vendored
2
vendor/status-go
vendored
@ -1 +1 @@
|
||||
Subproject commit cbb845b574fca248307778d960c993a73df78b98
|
||||
Subproject commit eb8d74e1aed94930241c9fb466805b09bd45810d
|
Loading…
x
Reference in New Issue
Block a user