diff --git a/ui/app/AppLayouts/Profile/ProfileLayout.qml b/ui/app/AppLayouts/Profile/ProfileLayout.qml index f9873bd769..4b30835be4 100644 --- a/ui/app/AppLayouts/Profile/ProfileLayout.qml +++ b/ui/app/AppLayouts/Profile/ProfileLayout.qml @@ -9,6 +9,7 @@ import shared.stores 1.0 as SharedStores import shared.popups.keycard 1.0 import AppLayouts.Wallet.controls 1.0 +import AppLayouts.Wallet.stores 1.0 import "stores" import "popups" @@ -28,6 +29,7 @@ StatusSectionLayout { property var systemPalette property var emojiPopup property var networkConnectionStore + required property TokensStore tokensStore backButtonName: root.store.backButtonName notificationCount: activityCenterStore.unreadNotificationsCount @@ -181,6 +183,7 @@ StatusSectionLayout { implicitHeight: parent.height rootStore: root.store walletStore: root.store.walletStore + tokensStore: root.tokensStore emojiPopup: root.emojiPopup sectionTitle: root.store.getNameForSubsection(Constants.settingsSubsection.wallet) contentWidth: d.contentWidth diff --git a/ui/app/AppLayouts/Profile/views/WalletView.qml b/ui/app/AppLayouts/Profile/views/WalletView.qml index a5f21c236a..79c56b5e82 100644 --- a/ui/app/AppLayouts/Profile/views/WalletView.qml +++ b/ui/app/AppLayouts/Profile/views/WalletView.qml @@ -19,6 +19,7 @@ import "../popups" import "../panels" import AppLayouts.Profile.views.wallet 1.0 +import AppLayouts.Wallet.stores 1.0 SettingsContentBase { id: root @@ -26,6 +27,7 @@ SettingsContentBase { property var emojiPopup property var rootStore property var walletStore + required property TokensStore tokensStore readonly property int mainViewIndex: 0; readonly property int networksViewIndex: 1; @@ -220,8 +222,8 @@ SettingsContentBase { Layout.leftMargin: Style.current.padding Layout.rightMargin: Style.current.padding - sourcesOfTokensModel: undefined//tokensStore.sourcesOfTokensModel - tokensListModel: undefined//tokensStore.flatTokensModel + sourcesOfTokensModel: tokensStore.sourcesOfTokensModel + tokensListModel: tokensStore.extendedFlatTokensModel } DappPermissionsView { diff --git a/ui/app/AppLayouts/Wallet/stores/RootStore.qml b/ui/app/AppLayouts/Wallet/stores/RootStore.qml index a4ffd0b2fd..5b9fa8358d 100644 --- a/ui/app/AppLayouts/Wallet/stores/RootStore.qml +++ b/ui/app/AppLayouts/Wallet/stores/RootStore.qml @@ -11,6 +11,8 @@ import StatusQ.Core.Utils 0.1 as SQUtils QtObject { id: root + readonly property TokensStore tokensStore: TokensStore {} + readonly property string defaultSelectedKeyUid: userProfile.keyUid readonly property bool defaultSelectedKeyUidMigratedToKeycard: userProfile.isKeycardUser diff --git a/ui/app/AppLayouts/Wallet/stores/TokensStore.qml b/ui/app/AppLayouts/Wallet/stores/TokensStore.qml new file mode 100644 index 0000000000..fc3a966c40 --- /dev/null +++ b/ui/app/AppLayouts/Wallet/stores/TokensStore.qml @@ -0,0 +1,94 @@ +import QtQuick 2.15 + +import SortFilterProxyModel 0.2 +import StatusQ 0.1 + +import utils 1.0 + +QtObject { + id: root + + /* PRIVATE: Modules used to get data from backend */ + readonly property var _walletModule: walletSectionNewModule + readonly property var _networksModule: networksModule + + /* This contains the different sources for the tokens list + ex. uniswap list, status tokens list */ + readonly property var sourcesOfTokensModel: SortFilterProxyModel { + sourceModel: root._walletModule.sourcesOfTokensModel + proxyRoles: ExpressionRole { + function sourceImage(sourceKey) { + return Constants.getSupportedTokenSourceImage(sourceKey) + } + name: "image" + expression: sourceImage(model.key) + } + } + + /* This list contains the complete list of tokens with separate + entry per token which has a unique [address + network] pair */ + readonly property var flatTokensModel: root._walletModule.flatTokensModel + + /* PRIVATE: This model just combines tokens and network information in one */ + readonly property LeftJoinModel _joinFlatTokensModel : LeftJoinModel { + leftModel: root.flatTokensModel + rightModel: root._networksModule.all + + joinRole: "chainId" + } + + /* This list contains the complete list of tokens with separate + entry per token which has a unique [address + network] pair including extended information + about the specific network per entry */ + readonly property var extendedFlatTokensModel: SortFilterProxyModel { + sourceModel: root._joinFlatTokensModel + + proxyRoles: [ + ExpressionRole { + name: "explorerUrl" + expression: { return model.blockExplorerURL + "/" + model.address } // TO REVIEW the correct composition!! + }, + ExpressionRole { + function tokenIcon(symbol) { + return Constants.tokenIcon(symbol) + } + name: "image" + expression: tokenIcon(model.symbol) + }, + ExpressionRole { + name: "jsArraySources" + expression: model.sources.split(";") + } + ] + } + + /* This list contains list of tokens grouped by symbol + EXCEPTION: We may have different entries for the same symbol in case + of symbol clash when minting community tokens, so in case of community tokens + there will be one entry per address + network pair */ + // TODO in #12513 + readonly property var tokensBySymbolModel: SortFilterProxyModel { + sourceModel: root._walletModule.tokensBySymbolModel + proxyRoles: [ + ExpressionRole { + function tokenIcon(symbol) { + return Constants.tokenIcon(symbol) + } + name: "iconSource" + expression: tokenIcon(model.symbol) + }, + // TODO: Review if it can be removed + ExpressionRole { + name: "shortName" + expression: model.symbol + }, + ExpressionRole { + function getCategory(index) { + return 0 + } + name: "category" + expression: getCategory(model.communityId) + } + ] + } +} diff --git a/ui/app/AppLayouts/Wallet/stores/qmldir b/ui/app/AppLayouts/Wallet/stores/qmldir index 1e5e73ec8f..9a623711b9 100644 --- a/ui/app/AppLayouts/Wallet/stores/qmldir +++ b/ui/app/AppLayouts/Wallet/stores/qmldir @@ -1,3 +1,4 @@ singleton RootStore 1.0 RootStore.qml ActivityFiltersStore 1.0 ActivityFiltersStore.qml CollectiblesStore 1.0 CollectiblesStore.qml +TokensStore 1.0 TokensStore.qml diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index a6a6795f8e..fa49773c92 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -39,6 +39,7 @@ import AppLayouts.Browser.stores 1.0 as BrowserStores import AppLayouts.stores 1.0 import AppLayouts.Chat.stores 1.0 as ChatStores import AppLayouts.Communities.stores 1.0 +import AppLayouts.Wallet.stores 1.0 as WalletStore import mainui.activitycenter.stores 1.0 import mainui.activitycenter.popups 1.0 @@ -64,6 +65,8 @@ Item { property NetworkConnectionStore networkConnectionStore: NetworkConnectionStore {} property CommunityTokensStore communityTokensStore: CommunityTokensStore {} property CommunitiesStore communitiesStore: CommunitiesStore {} + readonly property WalletStore.TokensStore tokensStore: WalletStore.RootStore.tokensStore + // set from main.qml property var sysPalette @@ -1238,6 +1241,7 @@ Item { systemPalette: appMain.sysPalette emojiPopup: statusEmojiPopup.item networkConnectionStore: appMain.networkConnectionStore + tokensStore: appMain.tokensStore } } diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index d343ddb06c..fa723ec169 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -787,6 +787,12 @@ QtObject { readonly property int actionSyncDevice: 3 } + readonly property QtObject supportedTokenSources: QtObject { + readonly property string uniswap: "uniswap" + readonly property string status: "status" + readonly property string custom: "custom" + } + enum LocalPairingState { Idle = 0, Transferring = 1, @@ -1140,6 +1146,18 @@ QtObject { return url.indexOf("DEFAULT-TOKEN") !== -1 } + function getSupportedTokenSourceImage(key, useDefault=true) { + if (key === supportedTokenSources.uniswap) + return Style.png("tokens/UNI") + + if (key === supportedTokenSources.status) + return Style.png("tokens/SNT") + + if (useDefault) + return Style.png("tokens/DEFAULT-TOKEN") + return "" + } + // Message outgoing status readonly property string sending: "sending" readonly property string sent: "sent"