feat(@desktop/wallet): Move the Account Selector logic to show selected token balance on a sepcific network to a dedicated WalletAccountsSelectorAdaptor

fixes #16705
This commit is contained in:
Khushboo Mehta 2024-11-28 12:42:31 +01:00 committed by Khushboo-dev-cpp
parent 37a06fc3be
commit 0d4d1b0ba7
12 changed files with 906 additions and 202 deletions

View File

@ -7,48 +7,205 @@ import Models 1.0
import SortFilterProxyModel 0.2
import shared.controls 1.0
import shared.stores 1.0
Item {
import AppLayouts.Wallet.stores 1.0
import AppLayouts.Wallet.adaptors 1.0
import utils 1.0
SplitView {
id: root
ColumnLayout {
spacing: 16
anchors.centerIn: parent
implicitWidth: 150
orientation: Qt.Vertical
QtObject {
id: d
WalletAccountsModel {
id: accountsModel
readonly property var flatNetworks: NetworksModel.flatNetworks
readonly property var assetsStore: WalletAssetsStore {
id: thisWalletAssetStore
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel {}
}
readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {}
assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel
}
Label {
text: "Default style"
font.bold: true
Layout.fillWidth: true
readonly property var currencyStore: CurrenciesStore{}
readonly property var nonWatchWalletAcounts: SortFilterProxyModel {
sourceModel: walletAccountsModel
filters: ValueFilter { roleName: "canSend"; value: true }
}
AccountSelector {
id: accountSelector
Layout.fillWidth: true
model: WalletAccountsModel {}
onCurrentAccountAddressChanged: {
accountSelector2.selectedAddress = currentAccountAddress
readonly property var filteredFlatNetworksModel: SortFilterProxyModel {
sourceModel: d.flatNetworks
filters: ValueFilter { roleName: "isTest"; value: true }
}
}
ListModel {
id: walletAccountsModel
readonly property var data: [
{
name: "helloworld",
address: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
emoji: "😋",
colorId: Constants.walletAccountColors.primary,
walletType: "",
canSend: true,
position: 0,
currencyBalance: ({amount: 1.25,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: true
},
{
name: "Hot wallet (generated)",
emoji: "🚗",
colorId: Constants.walletAccountColors.army,
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
walletType: Constants.generatedWalletType,
canSend: true,
position: 3,
currencyBalance: ({amount: 10,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
},
{
name: "Family (seed)",
emoji: "🎨",
colorId: Constants.walletAccountColors.magenta,
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8882",
walletType: Constants.seedWalletType,
canSend: true,
position: 1,
currencyBalance: ({amount: 110.05,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
},
{
name: "Tag Heuer (watch)",
emoji: "⌚",
colorId: Constants.walletAccountColors.copper,
color: "#CB6256",
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8883",
walletType: Constants.watchWalletType,
canSend: false,
position: 2,
currencyBalance: ({amount: 3,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
},
{
name: "Fab (key)",
emoji: "🔑",
colorId: Constants.walletAccountColors.camel,
color: "#C78F67",
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8884",
walletType: Constants.keyWalletType,
canSend: true,
position: 4,
currencyBalance: ({amount: 999,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
}
]
Component.onCompleted: append(data)
}
WalletAccountsSelectorAdaptor {
id: walletAccountsSelectorAdaptor
accounts: walletAccountsModel
assetsModel: d.assetsStore.groupedAccountAssetsModel
tokensBySymbolModel: d.assetsStore.walletTokensStore.plainTokensBySymbolModel
filteredFlatNetworksModel: d.filteredFlatNetworksModel
selectedTokenKey: selectedTokenComboBox.currentValue
selectedNetworkChainId: networksComboBox.currentValue
fnFormatCurrencyAmountFromBigInt: function(balance, symbol, decimals, options = null) {
return d.currencyStore.formatCurrencyAmountFromBigInt(balance, symbol, decimals, options)
}
}
Item {
SplitView.preferredWidth: 150
SplitView.fillHeight: true
ColumnLayout {
spacing: 16
width: 150
WalletAccountsModel {
id: accountsModel
}
Label {
text: "Default style"
font.bold: true
Layout.fillWidth: true
}
AccountSelector {
id: accountSelector
Layout.fillWidth: true
model: WalletAccountsModel {}
onCurrentAccountAddressChanged: {
accountSelector2.selectedAddress = currentAccountAddress
}
}
Label {
text: "Header style"
font.bold: true
Layout.fillWidth: true
}
AccountSelectorHeader {
id: accountSelector2
model: walletAccountsSelectorAdaptor.processedWalletAccounts
onCurrentAccountAddressChanged: {
accountSelector.selectedAddress = currentAccountAddress
}
}
}
Label {
text: "Header style"
font.bold: true
Layout.fillWidth: true
}
AccountSelectorHeader {
id: accountSelector2
model: accountSelector.model
onCurrentAccountAddressChanged: {
accountSelector.selectedAddress = currentAccountAddress
}
Item {
SplitView.preferredWidth: 300
SplitView.preferredHeight: childrenRect.height
ColumnLayout {
Label { text: "Selected Token" }
ComboBox {
id: selectedTokenComboBox
textRole: "name"
valueRole: "key"
model: d.assetsStore.walletTokensStore.plainTokensBySymbolModel
currentIndex: -1
}
Label { text: "Selected Network" }
ComboBox {
id: networksComboBox
textRole: "chainName"
valueRole: "chainId"
model: d.filteredFlatNetworksModel
currentIndex: -1
}
}
}
}
}
// category: Components

View File

@ -1,11 +1,12 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import SortFilterProxyModel 0.2
import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Core.Backpressure 0.1
import Models 1.0
@ -32,6 +33,10 @@ SplitView {
readonly property WalletAssetsStore walletAssetStore: WalletAssetsStore {
assetsWithFilteredBalances: groupedAccountsAssetsModel
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel{}
getDisplayAssetsBelowBalanceThresholdDisplayAmount: () => 0
}
}
readonly property var walletAccountsModel: WalletAccountsModel{}
@ -67,6 +72,14 @@ SplitView {
simpleSend.estimatedFiatFees = "1.45 EUR"
simpleSend.estimatedCryptoFees = "0.0007 ETH"
})
function formatCurrencyAmount(amount, symbol, options = null, locale = null) {
if (isNaN(amount)) {
return "N/A"
}
var currencyAmount = d.getCurrencyAmount(amount, symbol)
return LocaleUtils.currencyAmountToLocaleString(currencyAmount, options, locale)
}
}
PopupBackground {
@ -96,7 +109,7 @@ SplitView {
interactive: interactiveCheckbox.checked
accountsModel: d.walletAccountsModel
accountsModel: accountsSelectorAdaptor.processedWalletAccounts
assetsModel: assetsSelectorViewAdaptor.outputAssetsModel
collectiblesModel: collectiblesSelectionAdaptor.model
networksModel: d.filteredNetworksModel
@ -105,13 +118,7 @@ SplitView {
recentRecipientsModel: WalletTransactionsModel{}
currentCurrency: "USD"
fnFormatCurrencyAmount: function(amount, symbol, options = null, locale = null) {
if (isNaN(amount)) {
return "N/A"
}
var currencyAmount = d.getCurrencyAmount(amount, symbol)
return LocaleUtils.currencyAmountToLocaleString(currencyAmount, options, locale)
}
fnFormatCurrencyAmount: d.formatCurrencyAmount
fnResolveENS: Backpressure.debounce(root, 500, function (ensName, uuid) {
if (!!ensName && ensName.endsWith(".eth")) {
@ -146,6 +153,24 @@ SplitView {
}
}
WalletAccountsSelectorAdaptor {
id: accountsSelectorAdaptor
accounts: d.walletAccountsModel
assetsModel: GroupedAccountsAssetsModel {}
tokensBySymbolModel: d.walletAssetStore.walletTokensStore.plainTokensBySymbolModel
filteredFlatNetworksModel: d.filteredNetworksModel
selectedTokenKey: simpleSend.selectedTokenKey
selectedNetworkChainId: simpleSend.selectedChainId
fnFormatCurrencyAmountFromBigInt: function(balance, symbol, decimals, options = null) {
let bigIntBalance = AmountsArithmetic.fromString(balance)
let decimalBalance = AmountsArithmetic.toNumber(bigIntBalance, decimals)
return d.formatCurrencyAmount(decimalBalance, symbol, options)
}
}
TokenSelectorViewAdaptor {
id: assetsSelectorViewAdaptor

View File

@ -0,0 +1,187 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import SortFilterProxyModel 0.2
import AppLayouts.Wallet.stores 1.0
import AppLayouts.Wallet.adaptors 1.0
import Storybook 1.0
import Models 1.0
import shared.stores 1.0
import utils 1.0
Item {
id: root
ListModel {
id: walletAccountsModel
readonly property var data: [
{
name: "helloworld",
address: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
emoji: "😋",
colorId: Constants.walletAccountColors.primary,
walletType: "",
canSend: true,
position: 0,
currencyBalance: ({amount: 1.25,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: true
},
{
name: "Hot wallet (generated)",
emoji: "🚗",
colorId: Constants.walletAccountColors.army,
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
walletType: Constants.generatedWalletType,
canSend: true,
position: 3,
currencyBalance: ({amount: 10,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
},
{
name: "Family (seed)",
emoji: "🎨",
colorId: Constants.walletAccountColors.magenta,
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8882",
walletType: Constants.seedWalletType,
canSend: true,
position: 1,
currencyBalance: ({amount: 110.05,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
},
{
name: "Tag Heuer (watch)",
emoji: "⌚",
colorId: Constants.walletAccountColors.copper,
color: "#CB6256",
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8883",
walletType: Constants.watchWalletType,
canSend: false,
position: 2,
currencyBalance: ({amount: 3,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
},
{
name: "Fab (key)",
emoji: "🔑",
colorId: Constants.walletAccountColors.camel,
color: "#C78F67",
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8884",
walletType: Constants.keyWalletType,
canSend: true,
position: 4,
currencyBalance: ({amount: 999,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
}
]
Component.onCompleted: append(data)
}
QtObject {
id: d
readonly property var assetsStore: WalletAssetsStore {
id: thisWalletAssetStore
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel {}
}
readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {}
assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel
}
readonly property var currencyStore: CurrenciesStore{}
}
WalletAccountsSelectorAdaptor {
id: adaptor
accounts: walletAccountsModel
assetsModel: d.assetsStore.groupedAccountAssetsModel
tokensBySymbolModel: d.assetsStore.walletTokensStore.plainTokensBySymbolModel
filteredFlatNetworksModel: SortFilterProxyModel {
sourceModel: NetworksModel.flatNetworks
filters: ValueFilter { roleName: "isTest"; value: true }
}
fnFormatCurrencyAmountFromBigInt: function(balance, symbol, decimals, options = null) {
return d.currencyStore.formatCurrencyAmountFromBigInt(balance, symbol, decimals, options)
}
selectedTokenKey: selectedTokenComboBox.currentValue
selectedNetworkChainId: networksComboBox.currentValue
}
ColumnLayout {
anchors.fill: parent
Label { text: "Selected Token" }
ComboBox {
id: selectedTokenComboBox
textRole: "name"
valueRole: "key"
model: d.assetsStore.walletTokensStore.plainTokensBySymbolModel
currentIndex: 0
onCountChanged: currentIndex = 0
}
Label { text: "Selected Network" }
ComboBox {
id: networksComboBox
textRole: "chainName"
valueRole: "chainId"
model: adaptor.filteredFlatNetworksModel
currentIndex: 0
onCountChanged: currentIndex = 0
}
RowLayout {
GenericListView {
label: "Input Accounts model"
model: walletAccountsModel
Layout.fillWidth: true
Layout.fillHeight: true
roles: ["name", "address", "currencyBalance", "position", "canSend"]
skipEmptyRoles: true
}
GenericListView {
label: "Adapter's output model"
model: adaptor.processedWalletAccounts
Layout.fillWidth: true
Layout.fillHeight: true
roles: ["name", "address", "currencyBalance", "position", "canSend", "accountBalance", "currencyBalanceDouble"]
skipEmptyRoles: true
insetComponent: Label {
text: "balance " + (model ? model.accountBalance.formattedBalance: "")
}
}
}
}
}
// category: Adaptors

View File

@ -171,26 +171,28 @@ Item {
function test_floating_header_default_account() {
verify(!!controlUnderTest)
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
/* using a for loop set different accounts as default index and
check if the correct values are displayed in the floating header*/
for (let i = 0; i< swapAdaptor.nonWatchAccounts.count; i++) {
const nonWatchAccount = swapAdaptor.nonWatchAccounts.get(i)
root.swapFormData.selectedAccountAddress = nonWatchAccount.address
for (let i = 0; i< walletAccounts.count; i++) {
const accountToTest = walletAccounts.get(i)
root.swapFormData.selectedAccountAddress = accountToTest.address
// Launch popup
launchAndVerfyModal()
const floatingHeaderBackground = findChild(controlUnderTest, "headerBackground")
verify(!!floatingHeaderBackground)
compare(floatingHeaderBackground.color.toString().toUpperCase(), Utils.getColorForId(nonWatchAccount.colorId).toString().toUpperCase())
compare(floatingHeaderBackground.color.toString().toUpperCase(), Utils.getColorForId(accountToTest.colorId).toString().toUpperCase())
const headerContentItemText = findChild(controlUnderTest, "textContent")
verify(!!headerContentItemText)
compare(headerContentItemText.text, nonWatchAccount.name)
compare(headerContentItemText.text, accountToTest.name)
const headerContentItemEmoji = findChild(controlUnderTest, "assetContent")
verify(!!headerContentItemEmoji)
compare(headerContentItemEmoji.asset.emoji, nonWatchAccount.emoji)
compare(headerContentItemEmoji.asset.emoji, accountToTest.emoji)
}
closeAndVerfyModal()
}
@ -228,6 +230,7 @@ Item {
launchAndVerfyModal()
const accountsModalHeader = getAndVerifyAccountsModalHeader()
launchAccountSelectionPopup(accountsModalHeader)
let walletAccounts = accountsModalHeader.model
const comboBoxList = findChild(controlUnderTest, "accountSelectorList")
verify(!!comboBoxList)
@ -235,7 +238,7 @@ Item {
for(let i =0; i< comboBoxList.model.count; i++) {
let delegateUnderTest = comboBoxList.itemAtIndex(i)
let accountToBeTested = swapAdaptor.nonWatchAccounts.get(i)
let accountToBeTested = walletAccounts.get(i)
let elidedAddress = SQUtils.Utils.elideAndFormatWalletAddress(accountToBeTested.address)
compare(delegateUnderTest.title, accountToBeTested.name)
compare(delegateUnderTest.subTitle, elidedAddress)
@ -302,7 +305,6 @@ Item {
for(let i =0; i< comboBoxList.model.count; i++) {
let delegateUnderTest = comboBoxList.itemAtIndex(i)
verify(!!delegateUnderTest.model.fromToken)
verify(!!delegateUnderTest.model.accountBalance)
compare(delegateUnderTest.inlineTagModel, 1)
@ -315,9 +317,9 @@ Item {
compare(inlineTagDelegate_0.asset.color.toString().toUpperCase(), delegateUnderTest.model.accountBalance.chainColor.toString().toUpperCase())
compare(inlineTagDelegate_0.titleText.color, balance === "0" ? Theme.palette.baseColor1 : Theme.palette.directColor1)
let bigIntBalance = SQUtils.AmountsArithmetic.toNumber(balance, delegateUnderTest.model.fromToken.decimals)
compare(inlineTagDelegate_0.title, balance === "0" ? "0 %1".arg(delegateUnderTest.model.fromToken.symbol)
: root.swapAdaptor.formatCurrencyAmount(bigIntBalance, delegateUnderTest.model.fromToken.symbol))
let bigIntBalance = SQUtils.AmountsArithmetic.toNumber(balance, controlUnderTest.swapAdaptor.fromToken.decimals)
compare(inlineTagDelegate_0.title, balance === "0" ? "0 %1".arg(controlUnderTest.swapAdaptor.fromToken.symbol)
: root.swapAdaptor.currencyStore.formatCurrencyAmount(bigIntBalance, controlUnderTest.swapAdaptor.fromToken.symbol))
}
closeAndVerfyModal()
@ -327,13 +329,16 @@ Item {
// Launch popup
launchAndVerfyModal()
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
const payPanel = findChild(controlUnderTest, "payPanel")
verify(!!payPanel)
const amountToSendInput = findChild(payPanel, "amountToSendInput")
verify(!!amountToSendInput)
verify(amountToSendInput.cursorVisible)
for(let i =0; i< swapAdaptor.nonWatchAccounts.count; i++) {
for(let i =0; i< walletAccounts.count; i++) {
// launch account selection dropdown
const accountsModalHeader = getAndVerifyAccountsModalHeader()
launchAccountSelectionPopup(accountsModalHeader)
@ -348,20 +353,20 @@ Item {
verify(accountsModalHeader.control.popup.closed)
// The input params form's slected Index should be updated as per this selection
compare(root.swapFormData.selectedAccountAddress, swapAdaptor.nonWatchAccounts.get(i).address)
compare(root.swapFormData.selectedAccountAddress, walletAccounts.get(i).address)
// The comboBox item should reflect chosen account
const floatingHeaderBackground = findChild(accountsModalHeader, "headerBackground")
verify(!!floatingHeaderBackground)
compare(floatingHeaderBackground.color.toString().toUpperCase(), swapAdaptor.nonWatchAccounts.get(i).color.toString().toUpperCase())
compare(floatingHeaderBackground.color.toString().toUpperCase(), walletAccounts.get(i).color.toString().toUpperCase())
const headerContentItemText = findChild(accountsModalHeader, "textContent")
verify(!!headerContentItemText)
compare(headerContentItemText.text, swapAdaptor.nonWatchAccounts.get(i).name)
compare(headerContentItemText.text, walletAccounts.get(i).name)
const headerContentItemEmoji = findChild(accountsModalHeader, "assetContent")
verify(!!headerContentItemEmoji)
compare(headerContentItemEmoji.asset.emoji, swapAdaptor.nonWatchAccounts.get(i).emoji)
compare(headerContentItemEmoji.asset.emoji, walletAccounts.get(i).emoji)
waitForRendering(amountToSendInput)
@ -477,7 +482,7 @@ Item {
verify(!!fromToken)
let bigIntBalance = SQUtils.AmountsArithmetic.toNumber(accountBalance.balance, fromToken.decimals)
compare(inlineTagDelegate_0.title, bigIntBalance === 0 ? "0 %1".arg(fromToken.symbol)
: root.swapAdaptor.formatCurrencyAmount(bigIntBalance, fromToken.symbol))
: root.swapAdaptor.currencyStore.formatCurrencyAmount(bigIntBalance, fromToken.symbol))
}
// close account selection dropdown
accountsModalHeader.control.popup.close()
@ -918,7 +923,11 @@ Item {
// try setting value before popup is launched and check values
let valueToExchange = 0.001
let valueToExchangeString = valueToExchange.toString()
root.swapFormData.selectedAccountAddress = swapAdaptor.nonWatchAccounts.get(0).address
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
root.swapFormData.selectedAccountAddress = walletAccounts.get(0).address
root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId
root.swapFormData.fromTokensKey = "ETH"
root.swapFormData.fromTokenAmount = valueToExchangeString
@ -968,11 +977,14 @@ Item {
}
function test_modal_pay_input_wrong_value_1() {
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
let invalidValues = ["ABC", "0.0.010201", "12PASA", "100,9.01"]
for (let i =0; i<invalidValues.length; i++) {
let invalidValue = invalidValues[i]
// try setting value before popup is launched and check values
root.swapFormData.selectedAccountAddress = swapAdaptor.nonWatchAccounts.get(0).address
root.swapFormData.selectedAccountAddress = walletAccounts.get(0).address
root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId
root.swapFormData.fromTokensKey =
root.swapFormData.fromTokenAmount = invalidValue
@ -1013,10 +1025,13 @@ Item {
}
function test_modal_pay_input_wrong_value_2() {
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
// try setting value before popup is launched and check values
let valueToExchange = 100
let valueToExchangeString = valueToExchange.toString()
root.swapFormData.selectedAccountAddress = swapAdaptor.nonWatchAccounts.get(0).address
root.swapFormData.selectedAccountAddress = walletAccounts.get(0).address
root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId
root.swapFormData.fromTokensKey = "ETH"
root.swapFormData.fromTokenAmount = valueToExchangeString
@ -1103,10 +1118,13 @@ Item {
}
function test_modal_receive_input_presetValues() {
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
let valueToReceive = 0.001
let valueToReceiveString = valueToReceive.toString()
// try setting value before popup is launched and check values
root.swapFormData.selectedAccountAddress = swapAdaptor.nonWatchAccounts.get(0).address
root.swapFormData.selectedAccountAddress = walletAccounts.get(0).address
root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId
root.swapFormData.toTokenKey = "STT"
root.swapFormData.toTokenAmount = valueToReceiveString
@ -1164,12 +1182,15 @@ Item {
root.swapFormData.fromTokenAmount = valueToExchangeString
root.swapFormData.toTokenKey = "STT"
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
formValuesChanged.wait()
// Launch popup
launchAndVerfyModal()
// The default is the first account. Setting the second account to test switching accounts
root.swapFormData.selectedAccountAddress = swapAdaptor.nonWatchAccounts.get(1).address
root.swapFormData.selectedAccountAddress = walletAccounts.get(1).address
waitForItemPolished(controlUnderTest.contentItem)
@ -1215,13 +1236,17 @@ Item {
function test_modal_max_button_click_with_no_preset_pay_value() {
// Launch popup
launchAndVerfyModal()
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
// The default is the first account. Setting the second account to test switching accounts
root.swapFormData.selectedAccountAddress = swapAdaptor.nonWatchAccounts.get(1).address
root.swapFormData.selectedAccountAddress = walletAccounts.get(1).address
formValuesChanged.clear()
// try setting value before popup is launched and check values
root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId
root.swapFormData.selectedAccountAddress = swapAdaptor.nonWatchAccounts.get(0).address
root.swapFormData.selectedAccountAddress = walletAccounts.get(0).address
root.swapFormData.fromTokensKey = "ETH"
root.swapFormData.toTokenKey = "STT"
@ -1266,6 +1291,10 @@ Item {
}
function test_modal_pay_input_switching_accounts() {
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
// test with pay value being set and not set
let payValuesToTestWith = ["", "0.2"]
@ -1275,7 +1304,7 @@ Item {
// Asset chosen but no pay value set state -------------------------------------------------------------------------------
root.swapFormData.fromTokenAmount = valueToExchangeString
root.swapFormData.selectedAccountAddress = swapAdaptor.nonWatchAccounts.get(0).address
root.swapFormData.selectedAccountAddress = walletAccounts.get(0).address
root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId
root.swapFormData.fromTokensKey = "ETH"
@ -1292,8 +1321,8 @@ Item {
const errorTag = findChild(controlUnderTest, "errorTag")
verify(!!errorTag)
for (let i=0; i< root.swapAdaptor.nonWatchAccounts.count; i++) {
root.swapFormData.selectedAccountAddress = root.swapAdaptor.nonWatchAccounts.get(i).address
for (let i=0; i< walletAccounts.count; i++) {
root.swapFormData.selectedAccountAddress = walletAccounts.get(i).address
waitForItemPolished(controlUnderTest.contentItem)
@ -1382,11 +1411,14 @@ Item {
const receiveBottomItemText = findChild(receivePanel, "bottomItemText")
verify(!!receiveBottomItemText)
const accountsModalHeader = getAndVerifyAccountsModalHeader()
let walletAccounts = accountsModalHeader.model
root.swapAdaptor.reset()
// set network and address by default same
root.swapFormData.selectedNetworkChainId = root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId
root.swapFormData.selectedAccountAddress = root.swapAdaptor.nonWatchAccounts.get(0).address
root.swapFormData.selectedAccountAddress = walletAccounts.get(0).address
root.swapFormData.fromTokensKey = data.fromToken
root.swapFormData.fromTokenAmount = data.fromTokenAmount
root.swapFormData.toTokenKey = data.toToken

View File

@ -0,0 +1,208 @@
import QtQuick 2.15
import QtTest 1.15
import SortFilterProxyModel 0.2
import StatusQ 0.1
import StatusQ.Core.Utils 0.1
import AppLayouts.Wallet.stores 1.0
import AppLayouts.Wallet.adaptors 1.0
import Models 1.0
import shared.stores 1.0
import utils 1.0
Item {
id: root
width: 600
height: 400
ListModel {
id: walletAccountsModel
readonly property var data: [
{
name: "helloworld",
address: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240",
emoji: "😋",
colorId: Constants.walletAccountColors.primary,
walletType: "",
canSend: true,
position: 0,
currencyBalance: ({amount: 1.25,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: true
},
{
name: "Hot wallet (generated)",
emoji: "🚗",
colorId: Constants.walletAccountColors.army,
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881",
walletType: Constants.generatedWalletType,
canSend: true,
position: 3,
currencyBalance: ({amount: 10,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
},
{
name: "Family (seed)",
emoji: "🎨",
colorId: Constants.walletAccountColors.magenta,
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8882",
walletType: Constants.seedWalletType,
canSend: true,
position: 1,
currencyBalance: ({amount: 110.05,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
},
{
name: "Tag Heuer (watch)",
emoji: "⌚",
colorId: Constants.walletAccountColors.copper,
color: "#CB6256",
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8883",
walletType: Constants.watchWalletType,
canSend: false,
position: 2,
currencyBalance: ({amount: 3,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
},
{
name: "Fab (key)",
emoji: "🔑",
colorId: Constants.walletAccountColors.camel,
color: "#C78F67",
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8884",
walletType: Constants.keyWalletType,
canSend: true,
position: 4,
currencyBalance: ({amount: 999,
symbol: "USD",
displayDecimals: 2,
stripTrailingZeroes: false}),
migratedToKeycard: false
}
]
Component.onCompleted: append(data)
}
QtObject {
id: d
readonly property var flatNetworks: NetworksModel.flatNetworks
readonly property var assetsStore: WalletAssetsStore {
id: thisWalletAssetStore
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel {}
}
readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {}
assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel
}
readonly property var currencyStore: CurrenciesStore{}
readonly property var nonWatchWalletAcounts: SortFilterProxyModel {
sourceModel: walletAccountsModel
filters: ValueFilter { roleName: "canSend"; value: true }
}
readonly property var filteredFlatNetworksModel: SortFilterProxyModel {
sourceModel: d.flatNetworks
filters: ValueFilter { roleName: "isTest"; value: true }
}
readonly property ObjectProxyModel filteredBalancesModel: ObjectProxyModel {
sourceModel: d.assetsStore.groupedAccountAssetsModel
delegate: SortFilterProxyModel {
readonly property var balances: this
sourceModel: LeftJoinModel {
leftModel: model.balances
rightModel: d.filteredFlatNetworksModel
joinRole: "chainId"
}
filters: ValueFilter {
roleName: "chainId"
value: d.selectedNetworkChainId
}
}
expectedRoles: "balances"
exposedRoles: "balances"
}
property string selectedTokenKey: "ETH"
property int selectedNetworkChainId: 11155111
}
Component {
id: componentUnderTest
WalletAccountsSelectorAdaptor {
accounts: walletAccountsModel
assetsModel: d.assetsStore.groupedAccountAssetsModel
tokensBySymbolModel: d.assetsStore.walletTokensStore.plainTokensBySymbolModel
filteredFlatNetworksModel: d.filteredFlatNetworksModel
selectedTokenKey: d.selectedTokenKey
selectedNetworkChainId: d.selectedNetworkChainId
fnFormatCurrencyAmountFromBigInt: function(balance, symbol, decimals, options = null) {
return d.currencyStore.formatCurrencyAmountFromBigInt(balance, symbol, decimals, options)
}
}
}
property WalletAccountsSelectorAdaptor controlUnderTest: null
TestCase {
name: "WalletAccountsSelectorAdaptor"
when: windowShown
function init() {
controlUnderTest = createTemporaryObject(componentUnderTest, root)
}
function test_no_watchOnly_account() {
verify(!!controlUnderTest)
compare(controlUnderTest.processedWalletAccounts.count, d.nonWatchWalletAcounts.count)
}
function test_accountBalance_data() {
return [
{selectedTokenKey: "ETH", chainId: 11155111},
{selectedTokenKey: "STT", chainId: 11155111},
{selectedTokenKey: "ETH", chainId: 11155420},
{selectedTokenKey: "STT", chainId: 11155420}
]
}
function test_accountBalance(data) {
verify(!!controlUnderTest)
d.selectedTokenKey = data.selectedTokenKey
d.selectedNetworkChainId = data.chainId
let processedAccounts = controlUnderTest.processedWalletAccounts
for (let i = 0; i < processedAccounts.count; i++) {
let accountAddress = processedAccounts.get(i).address
let selectedTokenBalancesModel = ModelUtils.getByKey(d.filteredBalancesModel, "tokensKey", d.selectedTokenKey).balances
let tokenBalanceForSelectedAccount = ModelUtils.getByKey(selectedTokenBalancesModel, "account", accountAddress) ?? 0
let tokenBalanceForAccount = !!tokenBalanceForSelectedAccount ? tokenBalanceForSelectedAccount.balance: "0"
compare(tokenBalanceForAccount, processedAccounts.get(i).accountBalance.balance)
}
}
}
}

View File

@ -0,0 +1,152 @@
import QtQuick 2.15
import SortFilterProxyModel 0.2
import StatusQ 0.1
import StatusQ.Core.Utils 0.1
/**
Transforms and prepares the wallet accounts model to display
selected token on selected network
When no token or network is selected, only currency balance for account is shown.
*/
QObject {
id: root
// input api
/** Expected accounts model structure:
- name: name of the account
- address: address of the account,
- colorId: color id for the account,
- canSend: can send from acount ,
- position: position set by user in settings,
- currencyBalance: total currency balance in CurrencyAmount type,
- migratedToKeycard: if account is migrated to keycard.
*/
required property var accounts
/** Expected assets model structure:
- tokensKey: string -> unique string ID of the token (asset); e.g. "ETH" or contract address
- name: string -> user visible token name (e.g. "Ethereum")
- symbol: string -> user visible token symbol (e.g. "ETH")
- decimals: int -> number of decimal places
- communityId: string -> optional; ID of the community this token belongs to, if any
- marketDetails: var -> object containing props like `currencyPrice` for the computed values below
- balances: submodel -> [ chainId:int, account:string, balance:BigIntString, iconUrl:string ]
*/
required property var assetsModel
/** Expected token by symbol model structure:
- key: id for the token,
- name: name of the token,
- symbol: symbol of the token,
- decimals: decimals for the token
*/
required property var tokensBySymbolModel
/** Expected networks model structure:
- chainId: chain Id for network,
- chainName: name of network,
- iconUrl: icon representing the network,
*/
required property var filteredFlatNetworksModel
/** selectedTokenKey:
the selected token key
*/
required property string selectedTokenKey
/** selectedNetworkChainId:
the selected network chainId
*/
required property int selectedNetworkChainId
/** function to calculate token balance from BigInt:
the selected network chainId
*/
required property var fnFormatCurrencyAmountFromBigInt
/** output model
Computed processedWalletAccounts model addon values:
- accountBalance: balance of selected token on selected network along with network information
- filters out account that cant be used to send
*/
readonly property var processedWalletAccounts: SortFilterProxyModel {
sourceModel: root.accounts
delayed: true // Delayed to allow `processAccountBalance` dependencies to be resolved
filters: ValueFilter {
roleName: "canSend"
value: true
}
sorters: [
RoleSorter { roleName: "currencyBalanceDouble"; sortOrder: Qt.DescendingOrder },
RoleSorter { roleName: "position"; sortOrder: Qt.AscendingOrder }
]
proxyRoles: [
FastExpressionRole {
name: "accountBalance"
expression: {
// dependencies
root.selectedTokenKey
root.selectedNetworkChainId
return d.processAccountBalance(model.address)
}
expectedRoles: ["address"]
},
FastExpressionRole {
name: "currencyBalanceDouble"
expression: model.currencyBalance.amount
expectedRoles: ["currencyBalance"]
}
]
}
QtObject {
id: d
readonly property ObjectProxyModel filteredBalancesModel: ObjectProxyModel {
sourceModel: root.assetsModel
delegate: SortFilterProxyModel {
readonly property var balances: this
sourceModel: LeftJoinModel {
leftModel: model.balances
rightModel: root.filteredFlatNetworksModel
joinRole: "chainId"
}
filters: ValueFilter {
roleName: "chainId"
value: root.selectedNetworkChainId
}
}
expectedRoles: "balances"
exposedRoles: "balances"
}
function processAccountBalance(address) {
let selectedToken = ModelUtils.getByKey(root.tokensBySymbolModel, "key", root.selectedTokenKey)
if (!selectedToken) {
return null
}
let network = ModelUtils.getByKey(root.filteredFlatNetworksModel, "chainId", root.selectedNetworkChainId)
if (!network) {
return null
}
let balancesModel = ModelUtils.getByKey(filteredBalancesModel, "tokensKey", root.selectedTokenKey, "balances")
let accountBalance = ModelUtils.getByKey(balancesModel, "account", address)
if(accountBalance && accountBalance.balance !== "0") {
accountBalance.formattedBalance = root.fnFormatCurrencyAmountFromBigInt(accountBalance.balance, selectedToken.symbol, selectedToken.decimals)
return accountBalance
}
return {
balance: "0",
iconUrl: network.iconUrl,
chainColor: network.chainColor,
formattedBalance: "0 %1".arg(selectedToken.symbol)
}
}
}
}

View File

@ -1,2 +1,3 @@
CollectiblesSelectionAdaptor 1.0 CollectiblesSelectionAdaptor.qml
TokenSelectorViewAdaptor 1.0 TokenSelectorViewAdaptor.qml
WalletAccountsSelectorAdaptor 1.0 WalletAccountsSelectorAdaptor.qml

View File

@ -23,9 +23,6 @@ StatusDialog {
id: root
/**
TODO: use the newly defined WalletAccountsSelectorAdaptor
in https://github.com/status-im/status-desktop/pull/16834
This will also remove watch only accounts from the list
Expected model structure:
- name: name of account
- address: wallet address

View File

@ -1,9 +1,11 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQml.Models 2.15
import SortFilterProxyModel 0.2
import utils 1.0
import StatusQ 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Backpressure 0.1
@ -18,6 +20,7 @@ import shared.panels 1.0
import AppLayouts.Wallet.controls 1.0
import AppLayouts.Wallet.panels 1.0
import AppLayouts.Wallet.popups.buy 1.0
import AppLayouts.Wallet.adaptors 1.0
StatusDialog {
id: root
@ -58,11 +61,37 @@ StatusDialog {
selectedTokenKey: root.swapInputParamsForm.fromTokensKey
}
readonly property WalletAccountsSelectorAdaptor accountsSelectorAdaptor : WalletAccountsSelectorAdaptor {
accounts: root.swapAdaptor.swapStore.accounts
assetsModel: root.swapAdaptor.walletAssetsStore.baseGroupedAccountAssetModel
tokensBySymbolModel: root.swapAdaptor.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel
filteredFlatNetworksModel: SortFilterProxyModel {
sourceModel: root.swapAdaptor.swapStore.flatNetworks
filters: ValueFilter { roleName: "isTest"; value: root.swapAdaptor.swapStore.areTestNetworksEnabled }
}
selectedTokenKey: root.swapInputParamsForm.fromTokensKey
selectedNetworkChainId: root.swapInputParamsForm.selectedNetworkChainId
fnFormatCurrencyAmountFromBigInt: function(balance, symbol, decimals, options = null) {
return root.swapAdaptor.currencyStore.formatCurrencyAmountFromBigInt(balance, symbol, decimals, options)
}
}
readonly property var selectedAccount: selectedAccountEntry.item
function addMetricsEvent(subEventName) {
Global.addCentralizedMetricIfEnabled("swap", {subEvent: subEventName})
}
}
ModelEntry {
id: selectedAccountEntry
sourceModel: d.accountsSelectorAdaptor.processedWalletAccounts
key: "address"
value: root.swapInputParamsForm.selectedAccountAddress
}
Connections {
target: root.swapInputParamsForm
function onFormValuesChanged() {
@ -109,7 +138,7 @@ StatusDialog {
AccountSelectorHeader {
id: selector
control.popup.width: 512
model: root.swapAdaptor.nonWatchAccounts
model: d.accountsSelectorAdaptor.processedWalletAccounts
selectedAddress: root.swapInputParamsForm.selectedAccountAddress
onCurrentAccountAddressChanged: {
if (currentAccountAddress !== "" && currentAccountAddress !== root.swapInputParamsForm.selectedAccountAddress) {
@ -409,7 +438,7 @@ StatusDialog {
objectName: "signButton"
readonly property string fromTokenSymbol: !!root.swapAdaptor.fromToken ? root.swapAdaptor.fromToken.symbol ?? "" : ""
loadingWithText: root.swapAdaptor.approvalPending
icon.name: root.swapAdaptor.selectedAccount.migratedToKeycard ? Constants.authenticationIconByType[Constants.LoginType.Keycard]
icon.name: d.selectedAccount.migratedToKeycard ? Constants.authenticationIconByType[Constants.LoginType.Keycard]
: Constants.authenticationIconByType[root.loginType]
text: {
if(root.swapAdaptor.validSwapProposalReceived) {
@ -461,7 +490,7 @@ StatusDialog {
formatBigNumber: (number, symbol, noSymbolOption) => root.swapAdaptor.currencyStore.formatBigNumber(number, symbol, noSymbolOption)
loginType: root.swapAdaptor.selectedAccount.migratedToKeycard ? Constants.LoginType.Keycard : root.loginType
loginType: d.selectedAccount.migratedToKeycard ? Constants.LoginType.Keycard : root.loginType
feesLoading: root.swapAdaptor.swapProposalLoading
fromTokenSymbol: root.swapAdaptor.fromToken.symbol
@ -470,11 +499,11 @@ StatusDialog {
"chainId", root.swapInputParamsForm.selectedNetworkChainId,
"address")
accountName: root.swapAdaptor.selectedAccount.name
accountAddress: root.swapAdaptor.selectedAccount.address
accountEmoji: root.swapAdaptor.selectedAccount.emoji
accountColor: Utils.getColorForId(root.swapAdaptor.selectedAccount.colorId)
accountBalanceFormatted: root.swapAdaptor.selectedAccount.accountBalance.formattedBalance
accountName: d.selectedAccount.name
accountAddress: d.selectedAccount.address
accountEmoji: d.selectedAccount.emoji
accountColor: Utils.getColorForId(d.selectedAccount.colorId)
accountBalanceFormatted: d.selectedAccount.accountBalance.formattedBalance
networkShortName: networkFilter.singleSelectionItemData.shortName
networkName: networkFilter.singleSelectionItemData.chainName
@ -513,7 +542,7 @@ StatusDialog {
formatBigNumber: (number, symbol, noSymbolOption) => root.swapAdaptor.currencyStore.formatBigNumber(number, symbol, noSymbolOption)
loginType: root.swapAdaptor.selectedAccount.migratedToKeycard ? Constants.LoginType.Keycard : root.loginType
loginType: d.selectedAccount.migratedToKeycard ? Constants.LoginType.Keycard : root.loginType
feesLoading: root.swapAdaptor.swapProposalLoading
fromTokenSymbol: root.swapAdaptor.fromToken.symbol
@ -528,10 +557,10 @@ StatusDialog {
"chainId", root.swapInputParamsForm.selectedNetworkChainId,
"address")
accountName: root.swapAdaptor.selectedAccount.name
accountAddress: root.swapAdaptor.selectedAccount.address
accountEmoji: root.swapAdaptor.selectedAccount.emoji
accountColor: Utils.getColorForId(root.swapAdaptor.selectedAccount.colorId)
accountName: d.selectedAccount.name
accountAddress: d.selectedAccount.address
accountEmoji: d.selectedAccount.emoji
accountColor: Utils.getColorForId(d.selectedAccount.colorId)
networkShortName: networkFilter.singleSelectionItemData.shortName
networkName: networkFilter.singleSelectionItemData.chainName

View File

@ -33,51 +33,9 @@ QObject {
// To expose the selected from and to Token from the SwapModal
readonly property var fromToken: fromTokenEntry.item
readonly property var toToken: toTokenEntry.item
readonly property var selectedAccount: selectedAccountEntry.item
readonly property string uuid: d.uuid
// TO REVIEW: Handle this in a separate `WalletAccountsAdaptor.qml` file.
// Probably this data transformation should live there since they have common base.
readonly property var nonWatchAccounts: SortFilterProxyModel {
sourceModel: root.swapStore.accounts
delayed: true // Delayed to allow `processAccountBalance` dependencies to be resolved
filters: ValueFilter {
roleName: "canSend"
value: true
}
sorters: [
RoleSorter { roleName: "currencyBalanceDouble"; sortOrder: Qt.DescendingOrder },
RoleSorter { roleName: "position"; sortOrder: Qt.AscendingOrder }
]
proxyRoles: [
FastExpressionRole {
name: "accountBalance"
expression: {
// dependencies
root.swapFormData.fromTokensKey
root.fromToken
root.fromToken.symbol
root.fromToken.decimals
root.swapFormData.selectedNetworkChainId
root.swapFormData.fromTokensKey
return d.processAccountBalance(model.address)
}
expectedRoles: ["address"]
},
FastExpressionRole {
name: "currencyBalanceDouble"
expression: model.currencyBalance.amount
expectedRoles: ["currencyBalance"]
},
FastExpressionRole {
name: "fromToken"
expression: root.fromToken
}
]
}
readonly property SortFilterProxyModel filteredFlatNetworksModel: SortFilterProxyModel {
sourceModel: root.swapStore.flatNetworks
filters: ValueFilter { roleName: "isTest"; value: root.swapStore.areTestNetworksEnabled }
@ -94,55 +52,6 @@ QObject {
// storing txHash to verify against tx completed event
property string txHash
readonly property ObjectProxyModel filteredBalancesModel: ObjectProxyModel {
sourceModel: root.walletAssetsStore.baseGroupedAccountAssetModel
delegate: SortFilterProxyModel {
readonly property var balances: this
sourceModel: LeftJoinModel {
leftModel: model.balances
rightModel: root.swapStore.flatNetworks
joinRole: "chainId"
}
filters: ValueFilter {
roleName: "chainId"
value: root.swapFormData.selectedNetworkChainId
}
}
expectedRoles: "balances"
exposedRoles: "balances"
}
function processAccountBalance(address) {
if (!root.swapFormData.fromTokensKey || !root.fromToken) {
return null
}
let network = ModelUtils.getByKey(root.filteredFlatNetworksModel, "chainId", root.swapFormData.selectedNetworkChainId)
if (!network) {
return null
}
let balancesModel = ModelUtils.getByKey(filteredBalancesModel, "tokensKey", root.swapFormData.fromTokensKey, "balances")
let accountBalance = ModelUtils.getByKey(balancesModel, "account", address)
if(accountBalance && accountBalance.balance !== "0") {
accountBalance.formattedBalance = root.formatCurrencyAmountFromBigInt(accountBalance.balance, root.fromToken.symbol, root.fromToken.decimals)
return accountBalance
}
return {
balance: "0",
iconUrl: network.iconUrl,
chainColor: network.chainColor,
formattedBalance: "0 %1".arg(root.fromToken.symbol)
}
}
// Properties to handle error states
readonly property bool isRouteEthBalanceInsufficient: root.validSwapProposalReceived && root.swapOutputData.errCode === Constants.routerErrorCodes.router.errNotEnoughNativeBalance
@ -209,13 +118,6 @@ QObject {
value: root.swapFormData.toTokenKey
}
ModelEntry {
id: selectedAccountEntry
sourceModel: root.nonWatchAccounts
key: "address"
value: root.swapFormData.selectedAccountAddress
}
Connections {
target: root.swapStore
function onSuggestedRoutesReady(txRoutes, errCode, errDescription) {
@ -284,14 +186,6 @@ QObject {
d.txHash = ""
}
function formatCurrencyAmount(balance, symbol, options = null, locale = null) {
return root.currencyStore.formatCurrencyAmount(balance, symbol, options, locale)
}
function formatCurrencyAmountFromBigInt(balance, symbol, decimals, options = null) {
return root.currencyStore.formatCurrencyAmountFromBigInt(balance, symbol, decimals, options)
}
function getDisabledChainIds(enabledChainId) {
let disabledChainIds = []
let chainIds = ModelUtils.modelToFlatArray(root.filteredFlatNetworksModel, "chainId")

View File

@ -668,21 +668,22 @@ Item {
flatNetworksModel: WalletStores.RootStore.flatNetworks
areTestNetworksEnabled: WalletStores.RootStore.areTestNetworksEnabled
groupedAccountAssetsModel: appMain.walletAssetsStore.groupedAccountAssetsModel
currentCurrency: appMain.currencyStore.currentCurrency
plainTokensBySymbolModel: appMain.tokensStore.plainTokensBySymbolModel
showCommunityAssetsInSend: appMain.tokensStore.showCommunityAssetsInSend
collectiblesBySymbolModel: WalletStores.RootStore.collectiblesStore.jointCollectiblesBySymbolModel
tokenBySymbolModel: appMain.tokensStore.plainTokensBySymbolModel
fnFormatCurrencyAmount: function(amount, symbol, options = null, locale = null) {
return appMain.currencyStore.formatCurrencyAmount(amount, symbol)
}
savedAddressesModel: WalletStores.RootStore.savedAddresses
recentRecipientsModel: appMain.transactionStore.tempActivityController1Model
currentCurrency: appMain.currencyStore.currentCurrency
fnFormatCurrencyAmount: appMain.currencyStore.formatCurrencyAmount
fnFormatCurrencyAmountFromBigInt: appMain.currencyStore.formatCurrencyAmountFromBigInt
// TODO remove this call to mainModule under #16919
fnResolveENS: function(ensName, uuid) {
mainModule.resolveENS(name, uuid)
}
savedAddressesModel: WalletStores.RootStore.savedAddresses
recentRecipientsModel: appMain.transactionStore.tempActivityController1Model
Component.onCompleted: {
// It's requested from many nested places, so as a workaround we use
// Global to shorten the path via global signal.

View File

@ -41,8 +41,6 @@ QtObject {
/** For simple send modal flows, decoupling from transaction store **/
/** curently selected fiat currency symbol **/
required property string currentCurrency
/** Expected model structure:
- name: name of account
- address: wallet address
@ -62,6 +60,13 @@ QtObject {
- balances: submodel[ chainId:int, account:string, balance:BigIntString, iconUrl:string ]
**/
required property var groupedAccountAssetsModel
/** Expected token by symbol model structure:
- key: id for the token,
- name: name of the token,
- symbol: symbol of the token,
- decimals: decimals for the token
*/
required property var plainTokensBySymbolModel
/** Expected model structure:
- symbol [string] - unique identifier of a collectible
- collectionUid [string] - unique identifier of a collection
@ -96,8 +101,6 @@ QtObject {
/** whether community tokens are shown in send modal
based on a global setting **/
required property bool showCommunityAssetsInSend
/** required function to format currency amount to locale string **/
required property var fnFormatCurrencyAmount
required property var savedAddressesModel
required property var recentRecipientsModel
@ -107,6 +110,13 @@ QtObject {
/** required signal to receive resolved ens name address **/
signal ensNameResolved(string resolvedPubKey, string resolvedAddress, string uuid)
/** curently selected fiat currency symbol **/
required property string currentCurrency
/** required function to format currency amount to locale string **/
required property var fnFormatCurrencyAmount
/** required function to format to currency amount from big int **/
required property var fnFormatCurrencyAmountFromBigInt
function openSend(params = {}) {
// TODO remove once simple send is feature complete
let sendModalCmp = root.simpleSendEnabled ? simpleSendModalComponent: sendModalComponent
@ -243,14 +253,13 @@ QtObject {
SimpleSendModal {
id: simpleSendModal
/** TODO: use the newly defined WalletAccountsSelectorAdaptor
in https://github.com/status-im/status-desktop/pull/16834 **/
accountsModel: root.walletAccountsModel
accountsModel: backendHandler.accountsSelectorAdaptor.processedWalletAccounts
assetsModel: backendHandler.assetsSelectorViewAdaptor.outputAssetsModel
collectiblesModel: backendHandler.collectiblesSelectionAdaptor.model
networksModel: backendHandler.filteredFlatNetworksModel
savedAddressesModel: root.savedAddressesModel
recentRecipientsModel: root.recentRecipientsModel
currentCurrency: root.currentCurrency
fnFormatCurrencyAmount: root.fnFormatCurrencyAmount
fnResolveENS: root.fnResolveENS
@ -315,6 +324,18 @@ QtObject {
close()
}
readonly property var accountsSelectorAdaptor: WalletAccountsSelectorAdaptor {
accounts: root.walletAccountsModel
assetsModel: root.groupedAccountAssetsModel
tokensBySymbolModel: root.plainTokensBySymbolModel
filteredFlatNetworksModel: backendHandler.filteredFlatNetworksModel
selectedTokenKey: simpleSendModal.selectedTokenKey
selectedNetworkChainId: simpleSendModal.selectedChainId
fnFormatCurrencyAmountFromBigInt: root.fnFormatCurrencyAmountFromBigInt
}
readonly property var assetsSelectorViewAdaptor: TokenSelectorViewAdaptor {
// TODO: remove all store dependecies and add specific properties to the handler instead
assetsModel: root.groupedAccountAssetsModel