feat(Wallet): AssetsViewAdaptor added for preparing data for AssetsView
This commit is contained in:
parent
4f24ee0422
commit
b12caa3f9a
|
@ -0,0 +1,275 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import StatusQ.Models 0.1
|
||||||
|
|
||||||
|
import Storybook 1.0
|
||||||
|
|
||||||
|
import utils 1.0
|
||||||
|
import shared.views 1.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: listModel
|
||||||
|
|
||||||
|
readonly property var data: [
|
||||||
|
{
|
||||||
|
tokensKey: "key_ETH",
|
||||||
|
name: "Ether",
|
||||||
|
symbol: "ETH",
|
||||||
|
balances: [
|
||||||
|
{
|
||||||
|
chainId: "chain_id_1",
|
||||||
|
balance: "186316672770338050",
|
||||||
|
account: "account_1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chainId: "chain_id_1",
|
||||||
|
balance: "386318672772348050",
|
||||||
|
account: "account_2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chainId: "chain_id_2",
|
||||||
|
balance: "186311232772348990",
|
||||||
|
account: "account_1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chainId: "chain_id_2",
|
||||||
|
balance: "986317232772348990",
|
||||||
|
account: "account_1",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
decimals: 18,
|
||||||
|
communityId: "",
|
||||||
|
communityName: "",
|
||||||
|
communityImage: Qt.resolvedUrl(""),
|
||||||
|
marketDetails: {
|
||||||
|
changePct24hour: -2.1232,
|
||||||
|
currencyPrice: {
|
||||||
|
amount: 3423.23898
|
||||||
|
}
|
||||||
|
},
|
||||||
|
detailsLoading: false,
|
||||||
|
image: Qt.resolvedUrl("")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tokensKey: "key_SNT",
|
||||||
|
name: "Status",
|
||||||
|
symbol: "SNT",
|
||||||
|
balances: [
|
||||||
|
{
|
||||||
|
chainId: "chain_id_1",
|
||||||
|
balance: "386316672770338850",
|
||||||
|
account: "account_1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chainId: "chain_id_1",
|
||||||
|
balance: "377778672772348050",
|
||||||
|
account: "account_2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chainId: "chain_id_2",
|
||||||
|
balance: "146311232772348990",
|
||||||
|
account: "account_1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chainId: "chain_id_3",
|
||||||
|
balance: "86317232772348990",
|
||||||
|
account: "account_1",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
decimals: 18,
|
||||||
|
communityId: "",
|
||||||
|
communityName: "",
|
||||||
|
communityImage: Qt.resolvedUrl(""),
|
||||||
|
marketDetails: {
|
||||||
|
changePct24hour: 9.232,
|
||||||
|
currencyPrice: {
|
||||||
|
amount: 33.23898
|
||||||
|
}
|
||||||
|
},
|
||||||
|
detailsLoading: false,
|
||||||
|
image: Qt.resolvedUrl("")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tokensKey: "key_MYASST",
|
||||||
|
name: "Community Asset",
|
||||||
|
symbol: "MYASST",
|
||||||
|
balances: [
|
||||||
|
{
|
||||||
|
chainId: "chain_id_1",
|
||||||
|
balance: "23234",
|
||||||
|
account: "account_1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chainId: "chain_id_1",
|
||||||
|
balance: "63234",
|
||||||
|
account: "account_2",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
decimals: 3,
|
||||||
|
communityId: "0x033f36ccb",
|
||||||
|
communityName: "My Community",
|
||||||
|
communityImage: Constants.tokenIcon("DAI", false),
|
||||||
|
marketDetails: {
|
||||||
|
changePct24hour: 0,
|
||||||
|
currencyPrice: {
|
||||||
|
amount: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
detailsLoading: false,
|
||||||
|
image: Constants.tokenIcon("ZRX", false)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
append(data)
|
||||||
|
|
||||||
|
const chains = new Set()
|
||||||
|
const accounts = new Set()
|
||||||
|
|
||||||
|
data.forEach(e => e.balances.forEach(
|
||||||
|
e => { chains.add(e.chainId);
|
||||||
|
accounts.add(e.account)}))
|
||||||
|
|
||||||
|
chainsSelector.model = [...chains.values()]
|
||||||
|
chainsDownSelector.model = [...chains.values()]
|
||||||
|
accountsSelector.model = [...accounts.values()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
marketValueThreshold: minimumBalanceSlider.value
|
||||||
|
|
||||||
|
chainsError: chains => {
|
||||||
|
const chainsDown = chainsDownSelector.selection
|
||||||
|
const downForToken = chains.filter(value => chainsDown.includes(value))
|
||||||
|
|
||||||
|
if (downForToken.length)
|
||||||
|
return "Chains down: " + JSON.stringify(downForToken)
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
tokensModel: listModel
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Label { text: "CHAINS:" }
|
||||||
|
|
||||||
|
CheckBoxFlowSelector {
|
||||||
|
id: chainsSelector
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
initialSelection: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Label { text: "CHAINS DOWN:" }
|
||||||
|
|
||||||
|
CheckBoxFlowSelector {
|
||||||
|
id: chainsDownSelector
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Label { text: "ACCOUNTS:" }
|
||||||
|
|
||||||
|
CheckBoxFlowSelector {
|
||||||
|
id: accountsSelector
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
initialSelection: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Label { text: "MINIMUM BALANCE:" }
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Slider {
|
||||||
|
id: minimumBalanceSlider
|
||||||
|
|
||||||
|
from: 0.1
|
||||||
|
to: 100
|
||||||
|
|
||||||
|
value: 10
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: minimumBalanceSlider.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
GenericListView {
|
||||||
|
label: "Input model"
|
||||||
|
|
||||||
|
model: listModel
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
skipEmptyRoles: true
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericListView {
|
||||||
|
label: "Adapter's output model"
|
||||||
|
|
||||||
|
model: adaptor.model
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
roles:
|
||||||
|
["key", "symbol", "name", "icon", "error", "balance", "balanceText",
|
||||||
|
"marketDetailsAvailable", "marketDetailsLoading",
|
||||||
|
"marketPrice", "marketChangePct24hour", "communityId",
|
||||||
|
"communityName", "communityIcon", "position", "canBeHidden"]
|
||||||
|
|
||||||
|
skipEmptyRoles: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// category: Adaptors
|
|
@ -95,6 +95,8 @@ QtObject {
|
||||||
/* This model joins the "Tokens by symbol model combined with Community details"
|
/* This model joins the "Tokens by symbol model combined with Community details"
|
||||||
and "Grouped Account Assets Model" by tokenskey */
|
and "Grouped Account Assets Model" by tokenskey */
|
||||||
property LeftJoinModel groupedAccountAssetsModel: LeftJoinModel {
|
property LeftJoinModel groupedAccountAssetsModel: LeftJoinModel {
|
||||||
|
objectName: "groupedAccountAssetsModel"
|
||||||
|
|
||||||
leftModel: root.baseGroupedAccountAssetModel
|
leftModel: root.baseGroupedAccountAssetModel
|
||||||
rightModel: _jointTokensBySymbolModel
|
rightModel: _jointTokensBySymbolModel
|
||||||
joinRole: "tokensKey"
|
joinRole: "tokensKey"
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
import QtQml 2.15
|
||||||
|
|
||||||
|
import StatusQ 0.1
|
||||||
|
import StatusQ.Models 0.1
|
||||||
|
import StatusQ.Core.Utils 0.1
|
||||||
|
|
||||||
|
import utils 1.0
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
Tokens related part:
|
||||||
|
|
||||||
|
tokensKey [string] - unique identifier of a token, e.g "0x3234235"
|
||||||
|
symbol [string] - token's symbol e.g. "ETH" or "SNT"
|
||||||
|
name [string] - token's name e.g. "Ether" or "Dai"
|
||||||
|
image [url] - token's icon for custom tokens
|
||||||
|
decimals [int] - number of decimal places, e.g. 18 for ETH
|
||||||
|
balances [model] - submodel of balances per chain/account
|
||||||
|
chainId [string] - unique identifier of a chain
|
||||||
|
account [string] - unique identifier of an account
|
||||||
|
balance [string] - balance in basic unit as big integer string
|
||||||
|
marketDetails [object] - object holding market details
|
||||||
|
changePct24hour [double] - percentage change of fiat price in last day
|
||||||
|
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
|
||||||
|
|
||||||
|
Community related part (relevant for community minted assets, empty otherwise):
|
||||||
|
|
||||||
|
communityId [string] - unique identifier of a community, e.g. "0x6734235"
|
||||||
|
communityName [string] - name of a community e.g. "Crypto Kitties"
|
||||||
|
communityImage [url] - community's icon url
|
||||||
|
**/
|
||||||
|
property var tokensModel
|
||||||
|
|
||||||
|
// function formatting tokens balance expressed in a commonly used units,
|
||||||
|
// e.g. 1.2 for 1.2 ETH, according to rules specific for given symbol
|
||||||
|
property var formatBalance:
|
||||||
|
(balance, symbol) => `${balance.toLocaleString(Qt.locale())} ${symbol}`
|
||||||
|
|
||||||
|
// function providing error message per token depending on used chains,
|
||||||
|
// should return empty string if no error found
|
||||||
|
property var chainsError: chains => ""
|
||||||
|
|
||||||
|
// list of chain identifiers used for balance calculation
|
||||||
|
property var chains: []
|
||||||
|
|
||||||
|
// list of accounts used for balance calculation
|
||||||
|
property var accounts: []
|
||||||
|
|
||||||
|
// threshold below which the token is omitted from the output model
|
||||||
|
property double marketValueThreshold
|
||||||
|
|
||||||
|
/**
|
||||||
|
Model structure:
|
||||||
|
|
||||||
|
All roles from the source model are passed directly to the output model,
|
||||||
|
additionally:
|
||||||
|
|
||||||
|
key [string] - renamed from tokensKey
|
||||||
|
icon [url] - from image or fetched by symbol for well-known tokens
|
||||||
|
balance [double] - tokens balance is the commonly used unit, e.g. 1.2 for 1.2 ETH,
|
||||||
|
computed from balances according to provided criteria
|
||||||
|
balanceText [string] - formatted and localized balance
|
||||||
|
error [string] - error message related to balance
|
||||||
|
|
||||||
|
marketDetailsAvailable [bool] - specifies if market datails are available for given token
|
||||||
|
marketDetailsLoading [bool] - specifies if market datails are available for given token
|
||||||
|
marketPrice [double] - specifies market price in currently used currency
|
||||||
|
marketChangePct24hour [double] - percentage price change in last 24 hours, e.g. 0.5 for 0.5% of price change
|
||||||
|
|
||||||
|
position [int] - if custom order available, display position fetched from ManageTokensController
|
||||||
|
canBeHidden [bool] - specifies if given token can be hidden (e.g. ETH should be always visible)
|
||||||
|
|
||||||
|
communityIcon [url] - renamed from communityImage
|
||||||
|
**/
|
||||||
|
readonly property alias model: sfpm
|
||||||
|
|
||||||
|
ObjectProxyModel {
|
||||||
|
id: proxyModel
|
||||||
|
|
||||||
|
sourceModel: root.tokensModel ?? null
|
||||||
|
|
||||||
|
delegate: QObject {
|
||||||
|
readonly property var rootModel: model
|
||||||
|
readonly property bool hasCommunityId: !!model.communityId
|
||||||
|
readonly property var marketDetails: model.marketDetails
|
||||||
|
|
||||||
|
// Read-only roles exposed to the model:
|
||||||
|
|
||||||
|
readonly property string key: model.tokensKey
|
||||||
|
|
||||||
|
readonly property string error:
|
||||||
|
root.chainsError(chainsAggregator.uniqueChains)
|
||||||
|
|
||||||
|
readonly property double balance:
|
||||||
|
AmountsArithmetic.toNumber(totalBalanceAggregator.value, model.decimals)
|
||||||
|
readonly property string balanceText: root.formatBalance(balance, model.symbol)
|
||||||
|
|
||||||
|
readonly property bool marketDetailsAvailable: !hasCommunityId
|
||||||
|
readonly property bool marketDetailsLoading: model.detailsLoading
|
||||||
|
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))
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (hasCommunityId)
|
||||||
|
return true
|
||||||
|
|
||||||
|
return balance * marketPrice >= root.marketValueThreshold
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property url icon:
|
||||||
|
!!model.image ? model.image
|
||||||
|
: Constants.tokenIcon(model.symbol, false)
|
||||||
|
|
||||||
|
readonly property url communityIcon: model.communityImage ?? ""
|
||||||
|
|
||||||
|
readonly property bool canBeHidden: model.symbol !== Constants.ethToken
|
||||||
|
|
||||||
|
SortFilterProxyModel {
|
||||||
|
id: filteredBalances
|
||||||
|
|
||||||
|
sourceModel: rootModel.balances
|
||||||
|
|
||||||
|
filters: [
|
||||||
|
FastExpressionFilter {
|
||||||
|
expression: root.chains.includes(model.chainId)
|
||||||
|
expectedRoles: ["chainId"]
|
||||||
|
},
|
||||||
|
FastExpressionFilter {
|
||||||
|
expression: root.accounts.includes(model.account)
|
||||||
|
expectedRoles: ["account"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionAggregator {
|
||||||
|
id: totalBalanceAggregator
|
||||||
|
|
||||||
|
model: filteredBalances
|
||||||
|
initialValue: "0"
|
||||||
|
roleName: "balance"
|
||||||
|
|
||||||
|
aggregateFunction: (aggr, value) => AmountsArithmetic.sum(
|
||||||
|
AmountsArithmetic.fromString(aggr),
|
||||||
|
AmountsArithmetic.fromString(value)).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionAggregator {
|
||||||
|
id: chainsAggregator
|
||||||
|
|
||||||
|
readonly property var uniqueChains: [...new Set(value).values()]
|
||||||
|
|
||||||
|
model: filteredBalances
|
||||||
|
initialValue: []
|
||||||
|
roleName: "chainId"
|
||||||
|
|
||||||
|
aggregateFunction: (aggr, value) => [...aggr, value]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedRoles:
|
||||||
|
["tokensKey", "symbol", "image", "balances", "decimals",
|
||||||
|
"detailsLoading", "marketDetails", "communityId", "communityImage"]
|
||||||
|
exposedRoles:
|
||||||
|
["key", "error", "balance", "balanceText", "position", "icon",
|
||||||
|
"visible", "canBeHidden", "marketDetailsAvailable", "marketDetailsLoading",
|
||||||
|
"marketPrice", "marketChangePct24hour", "communityIcon"]
|
||||||
|
}
|
||||||
|
|
||||||
|
SortFilterProxyModel {
|
||||||
|
id: sfpm
|
||||||
|
|
||||||
|
sourceModel: proxyModel
|
||||||
|
|
||||||
|
filters: ValueFilter {
|
||||||
|
roleName: "visible"
|
||||||
|
value: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
AssetContextMenu 1.0 AssetContextMenu.qml
|
AssetContextMenu 1.0 AssetContextMenu.qml
|
||||||
AssetsView 1.0 AssetsView.qml
|
AssetsView 1.0 AssetsView.qml
|
||||||
|
AssetsViewAdaptor 1.0 AssetsViewAdaptor.qml
|
||||||
AssetsViewNew 1.0 AssetsViewNew.qml
|
AssetsViewNew 1.0 AssetsViewNew.qml
|
||||||
ConfirmHideAssetPopup 1.0 ConfirmHideAssetPopup.qml
|
ConfirmHideAssetPopup 1.0 ConfirmHideAssetPopup.qml
|
||||||
ConfirmHideCommunityAssetsPopup 1.0 ConfirmHideCommunityAssetsPopup.qml
|
ConfirmHideCommunityAssetsPopup 1.0 ConfirmHideCommunityAssetsPopup.qml
|
||||||
|
|
Loading…
Reference in New Issue