feature(wallet): Token preferences in assets model (#15706)
This commit is contained in:
parent
7d49b6bd9c
commit
047f558cd1
|
@ -1,5 +1,3 @@
|
|||
import json
|
||||
|
||||
import ./io_interface
|
||||
|
||||
import app/core/eventemitter
|
||||
|
@ -111,11 +109,11 @@ proc getCommunityTokenDescription*(self: Controller, chainId: int, address: stri
|
|||
proc updateTokenPreferences*(self: Controller, tokenPreferencesJson: string) =
|
||||
self.tokenService.updateTokenPreferences(tokenPreferencesJson)
|
||||
|
||||
proc getTokenPreferences*(self: Controller, symbol: string): TokenPreferencesItem =
|
||||
return self.tokenService.getTokenPreferences(symbol)
|
||||
|
||||
proc getTokenPreferencesJson*(self: Controller): string =
|
||||
let data = self.tokenService.getTokenPreferences()
|
||||
if data.isNil:
|
||||
return "[]"
|
||||
return $data
|
||||
return self.tokenService.getTokenPreferencesJson()
|
||||
|
||||
proc getTokenGroupByCommunity*(self: Controller): bool =
|
||||
return self.settingsService.tokenGroupByCommunity()
|
||||
|
|
|
@ -31,6 +31,8 @@ type
|
|||
MarketDetails
|
||||
DetailsLoading
|
||||
MarketDetailsLoading
|
||||
Visible
|
||||
Position
|
||||
|
||||
QtObject:
|
||||
type FlatTokensModel* = ref object of QAbstractListModel
|
||||
|
@ -81,7 +83,9 @@ QtObject:
|
|||
ModelRole.WebsiteUrl.int:"websiteUrl",
|
||||
ModelRole.MarketDetails.int:"marketDetails",
|
||||
ModelRole.DetailsLoading.int:"detailsLoading",
|
||||
ModelRole.MarketDetailsLoading.int:"marketDetailsLoading"
|
||||
ModelRole.MarketDetailsLoading.int:"marketDetailsLoading",
|
||||
ModelRole.Visible.int:"visible",
|
||||
ModelRole.Position.int:"position"
|
||||
}.toTable
|
||||
|
||||
method data(self: FlatTokensModel, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -129,6 +133,10 @@ QtObject:
|
|||
result = newQVariant(self.delegate.getTokensDetailsLoading())
|
||||
of ModelRole.MarketDetailsLoading:
|
||||
result = newQVariant(self.delegate.getTokensMarketValuesLoading())
|
||||
of ModelRole.Visible:
|
||||
result = newQVariant(self.delegate.getTokenPreferences(item.symbol).visible)
|
||||
of ModelRole.Position:
|
||||
result = newQVariant(self.delegate.getTokenPreferences(item.symbol).position)
|
||||
|
||||
proc modelsUpdated*(self: FlatTokensModel) =
|
||||
self.beginResetModel()
|
||||
|
@ -170,3 +178,11 @@ QtObject:
|
|||
proc currencyFormatsUpdated*(self: FlatTokensModel) =
|
||||
for marketDetails in self.tokenMarketDetails:
|
||||
marketDetails.updateCurrencyFormat()
|
||||
|
||||
proc tokenPreferencesUpdated*(self: FlatTokensModel) =
|
||||
if self.delegate.getFlatTokensList().len > 0:
|
||||
let index = self.createIndex(0, 0, nil)
|
||||
let lastindex = self.createIndex(self.delegate.getFlatTokensList().len-1, 0, nil)
|
||||
defer: index.delete
|
||||
defer: lastindex.delete
|
||||
self.dataChanged(index, lastindex, @[ModelRole.Visible.int, ModelRole.Position.int])
|
|
@ -10,6 +10,7 @@ type
|
|||
FlatTokenModelDataSource* = tuple[
|
||||
getFlatTokensList: proc(): var seq[TokenItem],
|
||||
getTokenDetails: proc(symbol: string): TokenDetailsItem,
|
||||
getTokenPreferences: proc(symbol: string): TokenPreferencesItem,
|
||||
getCommunityTokenDescription: proc(chainId: int, address: string): string,
|
||||
getTokensDetailsLoading: proc(): bool,
|
||||
getTokensMarketValuesLoading: proc(): bool,
|
||||
|
@ -18,6 +19,7 @@ type
|
|||
TokenBySymbolModelDataSource* = tuple[
|
||||
getTokenBySymbolList: proc(): var seq[TokenBySymbolItem],
|
||||
getTokenDetails: proc(symbol: string): TokenDetailsItem,
|
||||
getTokenPreferences: proc(symbol: string): TokenPreferencesItem,
|
||||
getCommunityTokenDescription: proc(addressPerChain: seq[AddressPerChain]): string,
|
||||
getTokensDetailsLoading: proc(): bool,
|
||||
getTokensMarketValuesLoading: proc(): bool,
|
||||
|
|
|
@ -70,8 +70,7 @@ method load*(self: Module) =
|
|||
self.events.on(SIGNAL_TOKENS_PRICES_UPDATED) do(e: Args):
|
||||
self.view.tokensMarketValuesUpdated()
|
||||
self.events.on(SIGNAL_TOKEN_PREFERENCES_UPDATED) do(e: Args):
|
||||
let args = ResultArgs(e)
|
||||
self.view.tokenPreferencesUpdated(args.success)
|
||||
self.view.tokenPreferencesUpdated()
|
||||
self.events.on(SIGNAL_COMMUNITY_TOKENS_DETAILS_LOADED) do(e: Args):
|
||||
self.view.tokensDetailsUpdated()
|
||||
|
||||
|
@ -116,6 +115,7 @@ method getFlatTokenModelDataSource*(self: Module): FlatTokenModelDataSource =
|
|||
return (
|
||||
getFlatTokensList: proc(): var seq[TokenItem] = self.controller.getFlatTokensList(),
|
||||
getTokenDetails: proc(symbol: string): TokenDetailsItem = self.controller.getTokenDetails(symbol),
|
||||
getTokenPreferences: proc(symbol: string): TokenPreferencesItem = self.controller.getTokenPreferences(symbol),
|
||||
getCommunityTokenDescription: proc(chainId: int, address: string): string = self.controller.getCommunityTokenDescription(chainId, address),
|
||||
getTokensDetailsLoading: proc(): bool = self.controller.getTokensDetailsLoading(),
|
||||
getTokensMarketValuesLoading: proc(): bool = self.controller.getTokensMarketValuesLoading()
|
||||
|
@ -125,6 +125,7 @@ method getTokenBySymbolModelDataSource*(self: Module): TokenBySymbolModelDataSou
|
|||
return (
|
||||
getTokenBySymbolList: proc(): var seq[TokenBySymbolItem] = self.controller.getTokenBySymbolList(),
|
||||
getTokenDetails: proc(symbol: string): TokenDetailsItem = self.controller.getTokenDetails(symbol),
|
||||
getTokenPreferences: proc(symbol: string): TokenPreferencesItem = self.controller.getTokenPreferences(symbol),
|
||||
getCommunityTokenDescription: proc(addressPerChain: seq[AddressPerChain]): string = self.controller.getCommunityTokenDescription(addressPerChain),
|
||||
getTokensDetailsLoading: proc(): bool = self.controller.getTokensDetailsLoading(),
|
||||
getTokensMarketValuesLoading: proc(): bool = self.controller.getTokensMarketValuesLoading()
|
||||
|
|
|
@ -30,6 +30,8 @@ type
|
|||
MarketDetails
|
||||
DetailsLoading
|
||||
MarketDetailsLoading
|
||||
Visible
|
||||
Position
|
||||
|
||||
QtObject:
|
||||
type TokensBySymbolModel* = ref object of QAbstractListModel
|
||||
|
@ -84,6 +86,8 @@ QtObject:
|
|||
ModelRole.MarketDetails.int:"marketDetails",
|
||||
ModelRole.DetailsLoading.int:"detailsLoading",
|
||||
ModelRole.MarketDetailsLoading.int:"marketDetailsLoading",
|
||||
ModelRole.Visible.int:"visible",
|
||||
ModelRole.Position.int:"position"
|
||||
}.toTable
|
||||
|
||||
method data(self: TokensBySymbolModel, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -130,6 +134,10 @@ QtObject:
|
|||
result = newQVariant(self.delegate.getTokensDetailsLoading())
|
||||
of ModelRole.MarketDetailsLoading:
|
||||
result = newQVariant(self.delegate.getTokensMarketValuesLoading())
|
||||
of ModelRole.Visible:
|
||||
result = newQVariant(self.delegate.getTokenPreferences(item.symbol).visible)
|
||||
of ModelRole.Position:
|
||||
result = newQVariant(self.delegate.getTokenPreferences(item.symbol).position)
|
||||
|
||||
proc modelsUpdated*(self: TokensBySymbolModel) =
|
||||
self.beginResetModel()
|
||||
|
@ -179,3 +187,11 @@ QtObject:
|
|||
proc currencyFormatsUpdated*(self: TokensBySymbolModel) =
|
||||
for marketDetails in self.tokenMarketDetails:
|
||||
marketDetails.updateCurrencyFormat()
|
||||
|
||||
proc tokenPreferencesUpdated*(self: TokensBySymbolModel) =
|
||||
if self.delegate.getTokenBySymbolList().len > 0:
|
||||
let index = self.createIndex(0, 0, nil)
|
||||
let lastindex = self.createIndex(self.delegate.getTokenBySymbolList().len-1, 0, nil)
|
||||
defer: index.delete
|
||||
defer: lastindex.delete
|
||||
self.dataChanged(index, lastindex, @[ModelRole.Visible.int, ModelRole.Position.int])
|
|
@ -141,7 +141,9 @@ QtObject:
|
|||
self.flatTokensModel.currencyFormatsUpdated()
|
||||
self.tokensBySymbolModel.currencyFormatsUpdated()
|
||||
|
||||
proc tokenPreferencesUpdated*(self: View, result: bool) {.signal.}
|
||||
proc tokenPreferencesUpdated*(self: View) =
|
||||
self.flatTokensModel.tokenPreferencesUpdated()
|
||||
self.tokensBySymbolModel.tokenPreferencesUpdated()
|
||||
|
||||
proc updateTokenPreferences*(self: View, tokenPreferencesJson: string) {.slot.} =
|
||||
self.delegate.updateTokenPreferences(tokenPreferencesJson)
|
||||
|
|
|
@ -60,6 +60,8 @@ QtObject:
|
|||
tokenDetailsTable: Table[string, TokenDetailsItem]
|
||||
tokenMarketValuesTable: Table[string, TokenMarketValuesItem]
|
||||
tokenPriceTable: Table[string, float64]
|
||||
tokenPreferencesTable: Table[string, TokenPreferencesItem]
|
||||
tokenPreferencesJson: string
|
||||
tokensDetailsLoading: bool
|
||||
tokensPricesLoading: bool
|
||||
tokensMarketDetailsLoading: bool
|
||||
|
@ -69,6 +71,7 @@ QtObject:
|
|||
|
||||
proc getCurrency*(self: Service): string
|
||||
proc rebuildMarketData*(self: Service)
|
||||
proc fetchTokenPreferences(self: Service)
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.QObject.delete
|
||||
|
@ -92,6 +95,7 @@ QtObject:
|
|||
result.tokenDetailsTable = initTable[string, TokenDetailsItem]()
|
||||
result.tokenMarketValuesTable = initTable[string, TokenMarketValuesItem]()
|
||||
result.tokenPriceTable = initTable[string, float64]()
|
||||
result.tokenPreferencesTable = initTable[string, TokenPreferencesItem]()
|
||||
result.tokensDetailsLoading = true
|
||||
result.tokensPricesLoading = true
|
||||
result.tokensMarketDetailsLoading = true
|
||||
|
@ -261,7 +265,9 @@ QtObject:
|
|||
# Callback to process the response of getSupportedTokensList call
|
||||
proc supportedTokensListRetrieved(self: Service, response: string) {.slot.} =
|
||||
# this is emited so that the models can know that the seq it depends on has been updated
|
||||
defer: self.events.emit(SIGNAL_TOKENS_LIST_UPDATED, Args())
|
||||
defer:
|
||||
self.fetchTokenPreferences()
|
||||
self.events.emit(SIGNAL_TOKENS_LIST_UPDATED, Args())
|
||||
try:
|
||||
let parsedJson = response.parseJson
|
||||
var errorString: string
|
||||
|
@ -506,30 +512,57 @@ QtObject:
|
|||
self.threadpool.start(arg)
|
||||
|
||||
# Token Management
|
||||
proc getTokenPreferences*(self: Service): JsonNode =
|
||||
proc fetchTokenPreferences(self: Service) =
|
||||
# this is emited so that the models can notify about token preferences being available
|
||||
defer: self.events.emit(SIGNAL_TOKEN_PREFERENCES_UPDATED, Args())
|
||||
self.tokenPreferencesJson = "[]"
|
||||
try:
|
||||
let response = backend.getTokenPreferences()
|
||||
if not response.error.isNil:
|
||||
error "status-go error", procName="getTokenPreferences", errCode=response.error.code, errDesription=response.error.message
|
||||
error "status-go error", procName="fetchTokenPreferences", errCode=response.error.code, errDesription=response.error.message
|
||||
return
|
||||
return response.result
|
||||
|
||||
if response.result.isNil or response.result.kind != JArray:
|
||||
return
|
||||
|
||||
self.tokenPreferencesJson = $response.result
|
||||
for preferences in response.result:
|
||||
let dto = Json.decode($preferences, TokenPreferencesDto, allowUnknownFields = true)
|
||||
self.tokenPreferencesTable[dto.key] = TokenPreferencesItem(
|
||||
key: dto.key,
|
||||
position: dto.position,
|
||||
groupPosition: dto.groupPosition,
|
||||
visible: dto.visible,
|
||||
communityId: dto.communityId)
|
||||
except Exception as e:
|
||||
error "error: ", procName="getTokenPreferences", errName=e.name, errDesription=e.msg
|
||||
error "error: ", procName="fetchTokenPreferences", errName=e.name, errDesription=e.msg
|
||||
|
||||
proc getTokenPreferences*(self: Service, symbol: string): TokenPreferencesItem =
|
||||
if not self.tokenPreferencesTable.hasKey(symbol):
|
||||
return TokenPreferencesItem(
|
||||
key: symbol,
|
||||
position: high(int),
|
||||
groupPosition: high(int),
|
||||
visible: true,
|
||||
communityId: ""
|
||||
)
|
||||
return self.tokenPreferencesTable[symbol]
|
||||
|
||||
proc getTokenPreferencesJson*(self: Service): string =
|
||||
if len(self.tokenPreferencesJson) == 0:
|
||||
self.fetchTokenPreferences()
|
||||
return self.tokenPreferencesJson
|
||||
|
||||
proc updateTokenPreferences*(self: Service, tokenPreferencesJson: string) =
|
||||
var updated = false
|
||||
try:
|
||||
let preferencesJson = parseJson(tokenPreferencesJson)
|
||||
var tokenPreferences: seq[TokenPreferences]
|
||||
var tokenPreferences: seq[TokenPreferencesDto]
|
||||
if preferencesJson.kind == JArray:
|
||||
for preferences in preferencesJson:
|
||||
add(tokenPreferences, fromJson(preferences, TokenPreferences))
|
||||
|
||||
add(tokenPreferences, Json.decode($preferences, TokenPreferencesDto, allowUnknownFields = false))
|
||||
let response = backend.updateTokenPreferences(tokenPreferences)
|
||||
if not response.error.isNil:
|
||||
raise newException(CatchableError, response.error.message)
|
||||
updated = true
|
||||
self.fetchTokenPreferences()
|
||||
except Exception as e:
|
||||
error "error: ", procName="updateTokenPreferences", errName=e.name, errDesription=e.msg
|
||||
|
||||
self.events.emit(SIGNAL_TOKEN_PREFERENCES_UPDATED, ResultArgs(success: updated))
|
||||
|
|
|
@ -89,6 +89,23 @@ proc `$`*(self: TokenDetailsItem): string =
|
|||
assetWebsiteUrl: {self.assetWebsiteUrl}
|
||||
]"""
|
||||
|
||||
type
|
||||
TokenPreferencesItem* = ref object of RootObj
|
||||
key*: string
|
||||
position*: int
|
||||
groupPosition*: int
|
||||
visible*: bool
|
||||
communityId*: string
|
||||
|
||||
proc `$`*(self: TokenPreferencesItem): string =
|
||||
result = fmt"""TokenPreferencesItem[
|
||||
key: {self.key},
|
||||
position: {self.position},
|
||||
groupPosition: {self.groupPosition},
|
||||
visible: {self.visible},
|
||||
communityId: {self.communityId}
|
||||
]"""
|
||||
|
||||
type
|
||||
TokenMarketValuesItem* = object
|
||||
marketCap*: float64
|
||||
|
|
|
@ -56,21 +56,13 @@ type
|
|||
activityTypes* {.serializedFieldName("activityTypes").}: seq[int]
|
||||
readType* {.serializedFieldName("readType").}: int
|
||||
|
||||
TokenPreferences* = ref object of RootObj
|
||||
TokenPreferencesDto* = ref object of RootObj
|
||||
key* {.serializedFieldName("key").}: string
|
||||
position* {.serializedFieldName("position").}: int
|
||||
groupPosition* {.serializedFieldName("groupPosition").}: int
|
||||
visible* {.serializedFieldName("visible").}: bool
|
||||
communityId* {.serializedFieldName("communityId").}: string
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[TokenPreferences]): TokenPreferences {.inline.} =
|
||||
result = TokenPreferences()
|
||||
discard t.getProp("key", result.key)
|
||||
discard t.getProp("position", result.position)
|
||||
discard t.getProp("groupPosition", result.groupPosition)
|
||||
discard t.getProp("visible", result.visible)
|
||||
discard t.getProp("communityId", result.communityId)
|
||||
|
||||
rpc(clientVersion, "web3"):
|
||||
discard
|
||||
|
||||
|
@ -285,7 +277,7 @@ rpc(moveWalletAccount, "accounts"):
|
|||
toPosition: int
|
||||
|
||||
rpc(updateTokenPreferences, "accounts"):
|
||||
preferences: seq[TokenPreferences]
|
||||
preferences: seq[TokenPreferencesDto]
|
||||
|
||||
rpc(getTokenPreferences, "accounts"):
|
||||
discard
|
||||
|
|
|
@ -53,7 +53,9 @@ Item {
|
|||
}
|
||||
},
|
||||
detailsLoading: false,
|
||||
image: Qt.resolvedUrl("")
|
||||
image: Qt.resolvedUrl(""),
|
||||
position: 1,
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
tokensKey: "key_SNT",
|
||||
|
@ -92,7 +94,9 @@ Item {
|
|||
}
|
||||
},
|
||||
detailsLoading: false,
|
||||
image: Qt.resolvedUrl("")
|
||||
image: Qt.resolvedUrl(""),
|
||||
position: 2,
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
tokensKey: "key_MYASST",
|
||||
|
@ -121,7 +125,9 @@ Item {
|
|||
}
|
||||
},
|
||||
detailsLoading: false,
|
||||
image: Constants.tokenIcon("ZRX", false)
|
||||
image: Constants.tokenIcon("ZRX", false),
|
||||
position: 5,
|
||||
visible: true
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -141,42 +147,9 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
ManageTokensController {
|
||||
id: manageTokensController
|
||||
|
||||
sourceModel: listModel
|
||||
serializeAsCollectibles: false
|
||||
|
||||
onRequestLoadSettings: {
|
||||
loadingStarted()
|
||||
|
||||
const jsonData = [
|
||||
{
|
||||
"key": "ETH",
|
||||
"position": 1,
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"key": "SNT",
|
||||
"position": 2,
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"key": "MYASST",
|
||||
"position": 5,
|
||||
"visible": true
|
||||
}
|
||||
]
|
||||
|
||||
loadingFinished(JSON.stringify(jsonData))
|
||||
}
|
||||
}
|
||||
|
||||
AssetsViewAdaptor {
|
||||
id: adaptor
|
||||
|
||||
controller: manageTokensController
|
||||
|
||||
chains: chainsSelector.selection
|
||||
accounts: accountsSelector.selection
|
||||
|
||||
|
|
|
@ -174,7 +174,6 @@ RightTabBaseView {
|
|||
}
|
||||
|
||||
tokensModel: RootStore.walletAssetsStore.groupedAccountAssetsModel
|
||||
controller: RootStore.walletAssetsStore.assetsController
|
||||
|
||||
formatBalance: (balance, symbol) => {
|
||||
return LocaleUtils.currencyAmountToLocaleString(
|
||||
|
|
|
@ -12,10 +12,6 @@ import SortFilterProxyModel 0.2
|
|||
QObject {
|
||||
id: root
|
||||
|
||||
// Controller providing information about visibility and order defined
|
||||
// by a user (token management)
|
||||
required property ManageTokensController controller
|
||||
|
||||
/**
|
||||
Expected model structure:
|
||||
|
||||
|
@ -35,6 +31,8 @@ QObject {
|
|||
currencyPrice [object] - object holding fiat price details
|
||||
amount [double] - fiat prace of 1 logical unit of cryptocurrency
|
||||
detailsLoading [bool] - indicatator if market details are ready to use
|
||||
position [int] - custom order position
|
||||
visible [bool] - token management visiblity flag
|
||||
|
||||
Community related part (relevant for community minted assets, empty otherwise):
|
||||
|
||||
|
@ -115,15 +113,8 @@ QObject {
|
|||
readonly property real marketPrice: marketDetails.currencyPrice.amount ?? 0
|
||||
readonly property real marketChangePct24hour: marketDetails.changePct24hour ?? 0
|
||||
|
||||
readonly property int position: {
|
||||
controller.revision
|
||||
return controller.order(model.symbol)
|
||||
}
|
||||
|
||||
readonly property bool visible: {
|
||||
root.controller.revision
|
||||
|
||||
if (!root.controller.filterAcceptsSymbol(model.symbol))
|
||||
if (!model.visible)
|
||||
return false
|
||||
|
||||
if (hasCommunityId)
|
||||
|
@ -184,9 +175,10 @@ QObject {
|
|||
|
||||
expectedRoles:
|
||||
["tokensKey", "symbol", "image", "balances", "decimals",
|
||||
"detailsLoading", "marketDetails", "communityId", "communityImage"]
|
||||
"detailsLoading", "marketDetails", "communityId", "communityImage",
|
||||
"position", "visible"]
|
||||
exposedRoles:
|
||||
["key", "error", "balance", "balanceText", "position", "icon",
|
||||
["key", "error", "balance", "balanceText", "icon",
|
||||
"visible", "canBeHidden", "marketDetailsAvailable", "marketDetailsLoading",
|
||||
"marketPrice", "marketChangePct24hour", "communityIcon"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue