fix(@desktop/wallet): Creating the UI flow needed to select params for making a purchase via Mercuryo

This commit is contained in:
Khushboo Mehta 2024-08-06 18:04:22 +02:00 committed by Anthony Laibe
parent d6ecc24562
commit 6aeb4671cb
29 changed files with 901 additions and 157 deletions

View File

@ -1,16 +1,54 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import Storybook 1.0 import Storybook 1.0
import Models 1.0 import Models 1.0
import AppLayouts.Wallet.popups 1.0 import StatusQ.Core.Backpressure 0.1
import AppLayouts.Wallet.popups.buy 1.0
import AppLayouts.Wallet.stores 1.0
import shared.stores 1.0
SplitView { SplitView {
id: root id: root
orientation: Qt.Horizontal orientation: Qt.Horizontal
QtObject {
id: d
property string uuid
property var debounceFetchProviderUrl: Backpressure.debounce(root, 500, function() {
d.buyCryptoStore.providerUrlReady(d.uuid, "xxxx")
})
property var debounceFetchProvidersList: Backpressure.debounce(root, 500, function() {
d.buyCryptoStore.areProvidersLoading = false
})
readonly property var buyCryptoStore: BuyCryptoStore {
readonly property var providersModel: OnRampProvidersModel{}
property bool areProvidersLoading
signal providerUrlReady(string uuid , string url)
function fetchProviders() {
console.warn("fetchProviders called >>")
areProvidersLoading = true
d.debounceFetchProvidersList()
}
function fetchProviderUrl(uuid, providerID,
isRecurrent, accountAddress = "",
chainID = 0, symbol = "") {
console.warn("fetchProviderUrl called >> uuid: ", uuid, "providerID: ",providerID
, "isRecurrent: ", isRecurrent, "accountAddress: ", accountAddress,
"chainID: ", chainID, "symbol: ", symbol)
d.uuid = uuid
d.debounceFetchProviderUrl()
}
}
}
PopupBackground { PopupBackground {
id: popupBg id: popupBg
@ -28,8 +66,34 @@ SplitView {
BuyCryptoModal { BuyCryptoModal {
id: buySellModal id: buySellModal
anchors.centerIn: parent
visible: true visible: true
onRampProvidersModel: OnRampProvidersModel{} modal: false
closePolicy: Popup.CloseOnEscape
buyCryptoAdaptor: BuyCryptoModalAdaptor {
buyCryptoStore: d.buyCryptoStore
readonly property var currencyStore: CurrenciesStore {}
readonly property var assetsStore: WalletAssetsStore {
id: thisWalletAssetStore
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel {}
}
readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {}
assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel
}
buyCryptoFormData: buySellModal.buyCryptoInputParamsForm
walletAccountsModel: WalletAccountsModel{}
networksModel: NetworksModel.flatNetworks
areTestNetworksEnabled: true
groupedAccountAssetsModel: assetsStore.groupedAccountAssetsModel
plainTokensBySymbolModel: assetsStore.walletTokensStore.plainTokensBySymbolModel
currentCurrency: currencyStore.currentCurrency
}
buyCryptoInputParamsForm: BuyCryptoParamsForm{
selectedWalletAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
selectedNetworkChainId: 11155111
selectedTokenKey: "ETH"
}
} }
} }
} }

View File

@ -5,36 +5,91 @@ import SortFilterProxyModel 0.2
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as SQUtils import StatusQ.Core.Utils 0.1 as SQUtils
import StatusQ.Core.Backpressure 0.1
import Models 1.0 import Models 1.0
import utils 1.0 import utils 1.0
import AppLayouts.Wallet.popups 1.0 import AppLayouts.Wallet.popups.buy 1.0
import AppLayouts.Wallet.stores 1.0
import shared.stores 1.0
Item { Item {
id: root id: root
width: 600 width: 600
height: 800 height: 800
OnRampProvidersModel{ QtObject {
id: _onRampProvidersModel id: d
} property string uuid
property var debounceFetchProviderUrl: Backpressure.debounce(root, 500, function() {
d.buyCryptoStore.providerUrlReady(d.uuid, "xxxx")
})
property var debounceFetchProvidersList: Backpressure.debounce(root, 500, function() {
d.buyCryptoStore.areProvidersLoading = false
})
readonly property var buyCryptoStore: BuyCryptoStore {
readonly property var providersModel: d.onRampProvidersModel
property bool areProvidersLoading
signal providerUrlReady(string uuid , string url)
SortFilterProxyModel { function fetchProviders() {
id: recurrentOnRampProvidersModel console.warn("fetchProviders called >>")
sourceModel: _onRampProvidersModel areProvidersLoading = true
filters: ValueFilter { d.debounceFetchProvidersList()
roleName: "recurrentSiteUrl" }
value: ""
inverted: true function fetchProviderUrl(uuid, providerID,
isRecurrent, accountAddress = "",
chainID = 0, symbol = "") {
console.warn("fetchProviderUrl called >> uuid: ", uuid, "providerID: ",providerID
, "isRecurrent: ", isRecurrent, "accountAddress: ", accountAddress,
"chainID: ", chainID, "symbol: ", symbol)
d.uuid = uuid
d.debounceFetchProviderUrl()
}
}
readonly property var onRampProvidersModel: OnRampProvidersModel{}
readonly property var recurrentOnRampProvidersModel: SortFilterProxyModel {
sourceModel: d.onRampProvidersModel
filters: ValueFilter {
roleName: "supportsRecurrentPurchase"
value: true
}
} }
} }
Component { Component {
id: componentUnderTest id: componentUnderTest
BuyCryptoModal { BuyCryptoModal {
onRampProvidersModel: _onRampProvidersModel id: buySellModal
onClosed: destroy() buyCryptoAdaptor: BuyCryptoModalAdaptor {
buyCryptoStore: d.buyCryptoStore
readonly property var currencyStore: CurrenciesStore {}
readonly property var assetsStore: WalletAssetsStore {
id: thisWalletAssetStore
walletTokensStore: TokensStore {
plainTokensBySymbolModel: TokensBySymbolModel {}
}
readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {}
assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel
}
buyCryptoFormData: buySellModal.buyCryptoInputParamsForm
walletAccountsModel: WalletAccountsModel{}
networksModel: NetworksModel.flatNetworks
areTestNetworksEnabled: true
groupedAccountAssetsModel: assetsStore.groupedAccountAssetsModel
plainTokensBySymbolModel: assetsStore.walletTokensStore.plainTokensBySymbolModel
currentCurrency: currencyStore.currentCurrency
}
buyCryptoInputParamsForm: BuyCryptoParamsForm{
selectedWalletAddress: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
selectedNetworkChainId: 11155111
selectedTokenKey: "ETH"
}
} }
} }
@ -73,15 +128,17 @@ Item {
verify(!!feesText) verify(!!feesText)
compare(feesText.text, modelToCompareAgainst.get(i).fees) compare(feesText.text, modelToCompareAgainst.get(i).fees)
/* TODO: fix when writing more tests for this functionality
const externalLinkIcon = findChild(delegateUnderTest, "externalLinkIcon") const externalLinkIcon = findChild(delegateUnderTest, "externalLinkIcon")
verify(!!externalLinkIcon) verify(!!externalLinkIcon)
compare(externalLinkIcon.icon, "tiny/external") compare(externalLinkIcon.icon, "tiny/external")
compare(externalLinkIcon.color, Theme.palette.baseColor1) compare(externalLinkIcon.color, Theme.palette.baseColor1) */
// Hover over the item and check hovered state // Hover over the item and check hovered state
mouseMove(delegateUnderTest, delegateUnderTest.width/2, delegateUnderTest.height/2) mouseMove(delegateUnderTest, delegateUnderTest.width/2, delegateUnderTest.height/2)
verify(delegateUnderTest.sensor.containsMouse) verify(delegateUnderTest.sensor.containsMouse)
compare(externalLinkIcon.color, Theme.palette.directColor1) /* TODO: fix when writing more tests for this functionality
compare(externalLinkIcon.color, Theme.palette.directColor1) */
verify(delegateUnderTest.color, Theme.palette.baseColor2) verify(delegateUnderTest.color, Theme.palette.baseColor2)
} }
} }
@ -99,11 +156,11 @@ Item {
launchPopup() launchPopup()
// check if footer has Done button and action on button clicked // check if footer has Done button and action on button clicked
const footer = findChild(controlUnderTest, "footer") compare(controlUnderTest.rightButtons.length, 2)
verify(!!footer) verify(!controlUnderTest.rightButtons[0].visible)
compare(footer.rightButtons.count, 1) verify(controlUnderTest.rightButtons[1].visible)
compare(footer.rightButtons.get(0).text, qsTr("Done")) compare(controlUnderTest.rightButtons[1].text, qsTr("Done"))
mouseClick(footer.rightButtons.get(0)) mouseClick(controlUnderTest.rightButtons[1])
// popup should be closed // popup should be closed
verify(!controlUnderTest.opened) verify(!controlUnderTest.opened)
@ -140,6 +197,7 @@ Item {
} }
function test_modalContent_OneTime_tab() { function test_modalContent_OneTime_tab() {
notificationSpy.clear()
// Launch modal // Launch modal
launchPopup() launchPopup()
@ -152,14 +210,16 @@ Item {
waitForRendering(providersList) waitForRendering(providersList)
verify(!!providersList) verify(!!providersList)
tryCompare(controlUnderTest.buyCryptoAdaptor.buyCryptoStore, "areProvidersLoading", false)
mouseClick(tabBar.itemAt(0)) mouseClick(tabBar.itemAt(0))
compare(tabBar.currentIndex, 0) compare(tabBar.currentIndex, 0)
// verify that 3 items are listed // verify that 4 items are listed
compare(providersList.count, 3) compare(providersList.count, 4)
// check if delegate contents are as expected // check if delegate contents are as expected
testDelegateItems(providersList, _onRampProvidersModel) testDelegateItems(providersList, d.onRampProvidersModel)
let delegateUnderTest = providersList.itemAtIndex(0) let delegateUnderTest = providersList.itemAtIndex(0)
verify(!!delegateUnderTest) verify(!!delegateUnderTest)
@ -168,8 +228,8 @@ Item {
tryCompare(notificationSpy, "count", 0) tryCompare(notificationSpy, "count", 0)
mouseClick(delegateUnderTest) mouseClick(delegateUnderTest)
tryCompare(notificationSpy, "count", 1) tryCompare(notificationSpy, "count", 1)
compare(notificationSpy.signalArguments[0][0], _onRampProvidersModel.get(0).siteUrl) compare(notificationSpy.signalArguments[0][0], "xxxx")
compare(notificationSpy.signalArguments[0][1], _onRampProvidersModel.get(0).hostname) compare(notificationSpy.signalArguments[0][1], d.onRampProvidersModel.get(0).hostname)
notificationSpy.clear() notificationSpy.clear()
// popup should be closed // popup should be closed
@ -177,6 +237,7 @@ Item {
} }
function test_modalContent_recurrent_tab() { function test_modalContent_recurrent_tab() {
notificationSpy.clear()
// Launch modal // Launch modal
launchPopup() launchPopup()
@ -186,9 +247,9 @@ Item {
// find providers list // find providers list
const providersList = findChild(controlUnderTest, "providersList") const providersList = findChild(controlUnderTest, "providersList")
waitForRendering(providersList)
verify(!!providersList) verify(!!providersList)
tryCompare(controlUnderTest.buyCryptoAdaptor.buyCryptoStore, "areProvidersLoading", false)
// check data in "Recurrent" tab -------------------------------------------------------- // check data in "Recurrent" tab --------------------------------------------------------
mouseClick(tabBar.itemAt(1)) mouseClick(tabBar.itemAt(1))
@ -200,7 +261,7 @@ Item {
compare(providersList.count, 1) compare(providersList.count, 1)
// check if delegate contents are as expected // check if delegate contents are as expected
testDelegateItems(providersList, recurrentOnRampProvidersModel) testDelegateItems(providersList, d.recurrentOnRampProvidersModel)
let delegateUnderTest = providersList.itemAtIndex(0) let delegateUnderTest = providersList.itemAtIndex(0)
verify(!!delegateUnderTest) verify(!!delegateUnderTest)
@ -209,13 +270,9 @@ Item {
tryCompare(notificationSpy, "count", 0) tryCompare(notificationSpy, "count", 0)
verify(controlUnderTest.opened) verify(controlUnderTest.opened)
mouseClick(delegateUnderTest) mouseClick(delegateUnderTest)
tryCompare(notificationSpy, "count", 1) tryCompare(notificationSpy, "count", 0)
compare(notificationSpy.signalArguments[0][0], recurrentOnRampProvidersModel.get(0).recurrentSiteUrl)
compare(notificationSpy.signalArguments[0][1], recurrentOnRampProvidersModel.get(0).hostname)
notificationSpy.clear() notificationSpy.clear()
//TODO: add more test logic here for second page of selecting params
// popup should be closed
verify(!controlUnderTest.opened)
} }
} }
} }

View File

@ -87,5 +87,6 @@ QtObject {
readonly property string latamex: Style.png("onRampProviders/latamex") readonly property string latamex: Style.png("onRampProviders/latamex")
readonly property string moonPay: Style.png("onRampProviders/moonPay") readonly property string moonPay: Style.png("onRampProviders/moonPay")
readonly property string ramp: Style.png("onRampProviders/ramp") readonly property string ramp: Style.png("onRampProviders/ramp")
readonly property string mercuryo: Style.png("onRampProviders/mercuryo")
} }
} }

View File

@ -3,31 +3,56 @@ import QtQuick 2.15
ListModel { ListModel {
readonly property var data: [ readonly property var data: [
{ {
id: "1",
name: "Ramp", name: "Ramp",
description: "Global crypto to fiat flow", description: "Global crypto to fiat flow",
fees: "0.49% - 2.9%", fees: "0.49% - 2.9%",
logoUrl: ModelsData.onRampProviderImages.ramp, logoUrl: ModelsData.onRampProviderImages.ramp,
siteUrl: "https://ramp.network/buy?hostApiKey=zrtf9u2uqebeyzcs37fu5857tktr3eg9w5tffove&swapAsset=DAI,ETH,USDC,USDT",
hostname: "ramp.network", hostname: "ramp.network",
recurrentSiteUrl: "" supportsSinglePurchase: true,
supportsRecurrentPurchase: false,
supportedAssets:[],
urlsNeedParameters: false
}, },
{ {
id: "2",
name: "MoonPay", name: "MoonPay",
description: "The new standard for fiat to crypto", description: "The new standard for fiat to crypto",
fees: "1% - 4.5%", fees: "1% - 4.5%",
logoUrl: ModelsData.onRampProviderImages.moonPay, logoUrl: ModelsData.onRampProviderImages.moonPay,
siteUrl: "https://buy.moonpay.com/?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR",
hostname: "moonpay.com", hostname: "moonpay.com",
recurrentSiteUrl: "https://buy.moonpay.com/?apiKey=pk_live_ABCCQPA5qqDu0unEwHJyAYQyeIqFGR", supportsSinglePurchase: true,
supportsRecurrentPurchase: false,
supportedAssets:[],
urlsNeedParameters: false
}, },
{ {
id: "3",
name: "Latamex", name: "Latamex",
description: "Easily buy crypto in Argentina, Mexico, and Brazil", description: "Easily buy crypto in Argentina, Mexico, and Brazil",
fees: "1% - 1.7%", fees: "1% - 1.7%",
logoUrl: ModelsData.onRampProviderImages.latamex, logoUrl: ModelsData.onRampProviderImages.latamex,
siteUrl: "https://latamex.com/",
hostname: "latamex.com", hostname: "latamex.com",
recurrentSiteUrl: "", supportsSinglePurchase: true,
supportsRecurrentPurchase: false,
supportedAssets:[],
urlsNeedParameters: false
},
{
id: "4",
name: "Mercuryo",
description: "Mercuryo buy crypto in Argentina, Mexico, and Brazil",
fees: "1% - 1.7%",
logoUrl: ModelsData.onRampProviderImages.mercuryo,
hostname: "mercuryo.com",
supportsSinglePurchase: true,
supportsRecurrentPurchase: true,
supportedAssets:[
{ key: "111551110x0000000000000000000000000000000000000000", chainId: 11155111, address: "0x0000000000000000000000000000000000000000"},
{ key: "4200x0000000000000000000000000000000000000000", chainId: 420, address: "0x0000000000000000000000000000000000000000"},
{ key: "4200xf2edf1c091f683e3fb452497d9a98a49cba84669", chainId: 420, address: "0xf2edf1c091f683e3fb452497d9a98a49cba84669"},
],
urlsNeedParameters: true
} }
] ]

View File

@ -82,7 +82,7 @@ ListModel {
{ chainId: 42161, address: "0xda10009cbd5d07dd0cecc66161fc93d7c9000da1"}, { chainId: 42161, address: "0xda10009cbd5d07dd0cecc66161fc93d7c9000da1"},
{ chainId: 5, address: "0xf2edf1c091f683e3fb452497d9a98a49cba84666"}, { chainId: 5, address: "0xf2edf1c091f683e3fb452497d9a98a49cba84666"},
{ chainId: 11155111, address: "0xda10009cbd5d07dd0cecc66161fc93d7c9000da1"}, { chainId: 11155111, address: "0xda10009cbd5d07dd0cecc66161fc93d7c9000da1"},
{ chainId: 420, address: "0xf2edf1c091f683e3fb452497d9a98a49cba84666"}, { chainId: 420, address: "0xf2edf1c091f683e3fb452497d9a98a49cba84669"},
{ chainId: 421613, address: "0xf2edf1c091f683e3fb452497d9a98a49cba84666"}, { chainId: 421613, address: "0xf2edf1c091f683e3fb452497d9a98a49cba84666"},
], ],
decimals: 18, decimals: 18,

View File

@ -0,0 +1,4 @@
import QtQuick 2.15
QtObject {
}

View File

@ -4,3 +4,4 @@ singleton RootStore 1.0 RootStore.qml
SwapStore 1.0 SwapStore.qml SwapStore 1.0 SwapStore.qml
TokensStore 1.0 TokensStore.qml TokensStore 1.0 TokensStore.qml
WalletAssetsStore 1.0 WalletAssetsStore.qml WalletAssetsStore 1.0 WalletAssetsStore.qml
BuyCryptoStore 1.0 BuyCryptoStore.qml

View File

@ -17,6 +17,7 @@ import "views"
import "stores" import "stores"
import "controls" import "controls"
import "popups/swap" import "popups/swap"
import "popups/buy"
Item { Item {
id: root id: root
@ -142,6 +143,10 @@ Item {
selectedAccountAddress: RootStore.selectedAddress selectedAccountAddress: RootStore.selectedAddress
} }
property BuyCryptoParamsForm buyFormData: BuyCryptoParamsForm {
selectedWalletAddress: RootStore.selectedAddress
}
function displayAllAddresses() { function displayAllAddresses() {
RootStore.showSavedAddresses = false RootStore.showSavedAddresses = false
RootStore.selectedAddress = "" RootStore.selectedAddress = ""
@ -165,6 +170,12 @@ Item {
rightPanelStackView.currentItem.resetView() rightPanelStackView.currentItem.resetView()
} }
} }
function getSelectedOrFirstNonWatchedAddress() {
return !!RootStore.selectedAddress ?
RootStore.selectedAddress :
StatusQUtils.ModelUtils.get(RootStore.nonWatchAccounts, 0, "address")
}
} }
SignPhraseModal { SignPhraseModal {
@ -212,9 +223,7 @@ Item {
hasFloatingButtons: true hasFloatingButtons: true
}) })
onLaunchSwapModal: { onLaunchSwapModal: {
d.swapFormData.selectedAccountAddress = !!RootStore.selectedAddress ? d.swapFormData.selectedAccountAddress = d.getSelectedOrFirstNonWatchedAddress()
RootStore.selectedAddress :
StatusQUtils.ModelUtils.get(RootStore.nonWatchAccounts,0, "address")
d.swapFormData.selectedNetworkChainId = StatusQUtils.ModelUtils.getByKey(RootStore.filteredFlatModel, "layer", 1, "chainId") d.swapFormData.selectedNetworkChainId = StatusQUtils.ModelUtils.getByKey(RootStore.filteredFlatModel, "layer", 1, "chainId")
d.swapFormData.fromTokensKey = tokensKey d.swapFormData.fromTokensKey = tokensKey
d.swapFormData.defaultToTokenKey = RootStore.areTestNetworksEnabled ? Constants.swap.testStatusTokenKey : Constants.swap.mainnetStatusTokenKey d.swapFormData.defaultToTokenKey = RootStore.areTestNetworksEnabled ? Constants.swap.testStatusTokenKey : Constants.swap.mainnetStatusTokenKey
@ -336,9 +345,7 @@ Item {
} }
onLaunchSwapModal: { onLaunchSwapModal: {
d.swapFormData.fromTokensKey = "" d.swapFormData.fromTokensKey = ""
d.swapFormData.selectedAccountAddress = !!RootStore.selectedAddress ? d.swapFormData.selectedAccountAddress = d.getSelectedOrFirstNonWatchedAddress()
RootStore.selectedAddress :
StatusQUtils.ModelUtils.get(RootStore.nonWatchAccounts,0, "address")
d.swapFormData.selectedNetworkChainId = StatusQUtils.ModelUtils.getByKey(RootStore.filteredFlatModel, "layer", 1, "chainId") d.swapFormData.selectedNetworkChainId = StatusQUtils.ModelUtils.getByKey(RootStore.filteredFlatModel, "layer", 1, "chainId")
if(!!walletStore.currentViewedHoldingTokensKey && walletStore.currentViewedHoldingType === Constants.TokenType.ERC20) { if(!!walletStore.currentViewedHoldingTokensKey && walletStore.currentViewedHoldingType === Constants.TokenType.ERC20) {
d.swapFormData.fromTokensKey = walletStore.currentViewedHoldingTokensKey d.swapFormData.fromTokensKey = walletStore.currentViewedHoldingTokensKey
@ -346,6 +353,15 @@ Item {
d.swapFormData.defaultToTokenKey = RootStore.areTestNetworksEnabled ? Constants.swap.testStatusTokenKey : Constants.swap.mainnetStatusTokenKey d.swapFormData.defaultToTokenKey = RootStore.areTestNetworksEnabled ? Constants.swap.testStatusTokenKey : Constants.swap.mainnetStatusTokenKey
Global.openSwapModalRequested(d.swapFormData) Global.openSwapModalRequested(d.swapFormData)
} }
onLaunchBuyCryptoModal: {
d.buyFormData.selectedWalletAddress = d.getSelectedOrFirstNonWatchedAddress()
d.buyFormData.selectedNetworkChainId = StatusQUtils.ModelUtils.getByKey(RootStore.filteredFlatModel, "layer", 1, "chainId")
d.buyFormData.selectedTokenKey = Constants.ethToken
if(!!walletStore.currentViewedHoldingTokensKey && walletStore.currentViewedHoldingType === Constants.TokenType.ERC20) {
d.buyFormData.selectedTokenKey = walletStore.currentViewedHoldingTokensKey
}
Global.openBuyCryptoModalRequested(d.buyFormData)
}
ModelEntry { ModelEntry {
id: selectedCommunityForCollectible id: selectedCommunityForCollectible

View File

@ -175,8 +175,7 @@ QObject {
readonly property string favoritesSectionId: "section_zzz" readonly property string favoritesSectionId: "section_zzz"
} }
RolesRenamingModel { readonly property RolesRenamingModel renamedTokensBySymbolModel: RolesRenamingModel {
id: renamedTokensBySymbolModel
sourceModel: root.plainTokensBySymbolModel || null sourceModel: root.plainTokensBySymbolModel || null
mapping: [ mapping: [
RoleRename { RoleRename {
@ -191,7 +190,7 @@ QObject {
propagateResets: true propagateResets: true
sources: [ sources: [
SourceModel { SourceModel {
model: renamedTokensBySymbolModel model: root.renamedTokensBySymbolModel
markerRoleValue: "plain_tokens_model" markerRoleValue: "plain_tokens_model"
}, },
SourceModel { SourceModel {

View File

@ -0,0 +1,48 @@
import QtQuick 2.15
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import utils 1.0
StatusListItem {
id: root
required property string name
required property string description
required property string logoUrl
required property string fees
required property bool urlsNeedParameters
property bool isUrlLoading: false
title: root.name
subTitle: root.description
asset.name: root.logoUrl
asset.isImage: true
statusListItemSubTitle.maximumLineCount: 1
statusListItemComponentsSlot.spacing: 8
components: [
StatusTextWithLoadingState {
objectName: "feesText"
text: root.loading ? Constants.dummyText: root.fees
customColor: Theme.palette.baseColor1
lineHeight: 24
lineHeightMode: Text.FixedHeight
verticalAlignment: Text.AlignVCenter
loading: root.loading
},
StatusIcon {
objectName: "externalLinkIcon"
icon: root.urlsNeedParameters ? "chevron-down": "tiny/external"
rotation: root.urlsNeedParameters ? 270: 0
color: sensor.containsMouse ? Theme.palette.directColor1: Theme.palette.baseColor1
visible: !root.loading && !root.isUrlLoading
},
StatusLoadingIndicator {
visible: root.isUrlLoading
}
]
}

View File

@ -0,0 +1,18 @@
import QtQuick 2.15
import utils 1.0
BuyCryptoProvidersDelegate {
name: Constants.dummyText
description: Constants.dummyText
logoUrl: Constants.dummyText
urlsNeedParameters: false
fees: Constants.dummyText
statusListItemSubTitle.loading: true
statusListItemTitle.loading: true
statusListItemIcon.loading: true
loading: true
enabled: false
}

View File

@ -21,3 +21,5 @@ SwapExchangeButton 1.0 SwapExchangeButton.qml
TokenSelector 1.0 TokenSelector.qml TokenSelector 1.0 TokenSelector.qml
TokenSelectorNew 1.0 TokenSelectorNew.qml TokenSelectorNew 1.0 TokenSelectorNew.qml
SwapProvidersTermsAndConditionsText 1.0 SwapProvidersTermsAndConditionsText.qml SwapProvidersTermsAndConditionsText 1.0 SwapProvidersTermsAndConditionsText.qml
BuyCryptoProvidersDelegate 1.0 BuyCryptoProvidersDelegate.qml
BuyCryptoProvidersLoadingDelegate 1.0 BuyCryptoProvidersLoadingDelegate.qml

View File

@ -0,0 +1,86 @@
import QtQuick 2.15
import QtQuick.Layouts 1.0
import QtQml.Models 2.15
import SortFilterProxyModel 0.2
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import AppLayouts.Wallet.controls 1.0
ColumnLayout {
id: root
// required properties
required property bool providersLoading
// expected model structure:
// id, name, description, fees, logoUrl, hostname, supportsSinglePurchase, supportsRecurrentPurchase, supportedAssets, urlsNeedParameters
required property var providersModel
required property bool isUrlBeingFetched
required property string selectedProviderId
// exposed api
property alias currentTabIndex: tabBar.currentIndex
signal providerSelected(string id)
QtObject {
id: d
readonly property int loadingItemsCount: 5
}
spacing: 20
StatusSwitchTabBar {
id: tabBar
objectName: "tabBar"
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
StatusSwitchTabButton {
text: qsTr("One time")
}
StatusSwitchTabButton {
text: qsTr("Recurrent")
}
}
StatusListView {
objectName: "providersList"
Layout.fillWidth: true
Layout.fillHeight: true
DelegateModel {
id: regularModel
model: SortFilterProxyModel {
sourceModel: root.providersModel
filters: ValueFilter {
enabled: tabBar.currentIndex
roleName: "supportsRecurrentPurchase"
value: true
}
}
delegate: BuyCryptoProvidersDelegate {
required property var model
width: ListView.view.width
name: model.name
description: model.description
logoUrl: model.logoUrl
fees: model.fees
urlsNeedParameters: model.urlsNeedParameters
isUrlLoading: root.isUrlBeingFetched && root.selectedProviderId === model.id
onClicked: root.providerSelected(model.id)
}
}
DelegateModel {
id: loadingModel
model: d.loadingItemsCount
delegate: BuyCryptoProvidersLoadingDelegate {
required property var model
width: ListView.view.width
}
}
model: root.providersLoading ? loadingModel : regularModel
}
}

View File

@ -0,0 +1,148 @@
import QtQuick 2.14
import QtQuick.Layouts 1.0
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import StatusQ.Components 0.1
import StatusQ.Components.private 0.1
import AppLayouts.Wallet.controls 1.0
import utils 1.0
ColumnLayout {
id: root
// required properties
required property var adaptor
required property var selectedProvider
required property string selectedTokenKey
required property int selectedNetworkChainId
required property var filteredFlatNetworksModel
// exposed api
property alias searchString: holdingSelector.searchString
signal networkSelected(int chainId)
signal tokenSelected(string tokensKey)
QtObject {
id: d
function updateTokenSelector() {
if(!!root.selectedTokenKey && root.selectedNetworkChainId !== -1) {
holdingSelector.selectToken(root.selectedTokenKey)
}
}
}
onSelectedTokenKeyChanged: d.updateTokenSelector()
onSelectedNetworkChainIdChanged: d.updateTokenSelector()
spacing: 20
StatusListItem {
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft
leftPadding: 0
rightPadding: 0
title: qsTr("Buy via %1").arg(!!root.selectedProvider ? root.selectedProvider.name: "")
subTitle: qsTr("Select which network and asset")
statusListItemTitle.color: Theme.palette.directColor1
asset.name: !!root.selectedProvider ? root.selectedProvider.logoUrl: ""
asset.isImage: true
color: Theme.palette.transparent
enabled: false
}
StatusMenuSeparator {
Layout.fillWidth: true
}
ColumnLayout {
Layout.fillWidth: true
spacing: 8
StatusBaseText {
text: qsTr("Select network")
color: Theme.palette.directColor1
font.pixelSize: 15
lineHeight: 22
lineHeightMode: Text.FixedHeight
verticalAlignment: Text.AlignVCenter
}
NetworkFilter {
objectName: "networkFilter"
Layout.fillWidth: true
control.popup.width: parent.width
multiSelection: false
showSelectionIndicator: false
flatNetworks: root.filteredFlatNetworksModel
selection: [root.selectedNetworkChainId]
onSelectionChanged: root.networkSelected(selection[0])
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 8
StatusBaseText {
text: qsTr("Select asset")
color: Theme.palette.directColor1
font.pixelSize: 15
lineHeight: 22
lineHeightMode: Text.FixedHeight
verticalAlignment: Text.AlignVCenter
}
TokenSelector {
id: holdingSelector
Layout.fillWidth: true
model: root.adaptor.outputAssetsModel
popup.width: parent.width
contentItem: Loader {
height: 40 // by design
sourceComponent: !!holdingSelector.currentTokensKey ? selectedTokenCmp : nothingSelectedCmp
}
background: StatusComboboxBackground {
border.width: 1
color: Theme.palette.transparent
}
onTokenSelected: root.tokenSelected(tokensKey)
Component.onCompleted: holdingSelector.selectToken(root.selectedTokenKey)
}
}
Component {
id: nothingSelectedCmp
StatusBaseText {
objectName: "tokenSelectorContentItemText"
font.pixelSize: Style.current.additionalTextSize
font.weight: Font.Medium
color: Theme.palette.primaryColor1
text: qsTr("Select asset")
}
}
Component {
id: selectedTokenCmp
RowLayout {
spacing: Style.current.halfPadding
StatusRoundedImage {
objectName: "tokenSelectorIcon"
Layout.preferredWidth: 20
Layout.preferredHeight: 20
image.source: ModelUtils.getByKey(holdingSelector.model, "tokensKey", holdingSelector.currentTokensKey, "iconSource")
}
StatusBaseText {
objectName: "tokenSelectorContentItemText"
font.pixelSize: 15
color: Theme.palette.directColor1
text: ModelUtils.getByKey(holdingSelector.model, "tokensKey", holdingSelector.currentTokensKey, "name")
}
StatusBaseText {
Layout.fillWidth: true
objectName: "tokenSelectorContentItemText"
font.pixelSize: 15
color: Theme.palette.baseColor1
text: ModelUtils.getByKey(holdingSelector.model, "tokensKey", holdingSelector.currentTokensKey, "symbol")
}
}
}
}

View File

@ -33,6 +33,7 @@ Rectangle {
signal launchSendModal(string fromAddress) signal launchSendModal(string fromAddress)
signal launchBridgeModal() signal launchBridgeModal()
signal launchSwapModal() signal launchSwapModal()
signal launchBuyCryptoModal()
color: Theme.palette.statusAppLayout.rightPanelBackgroundColor color: Theme.palette.statusAppLayout.rightPanelBackgroundColor
@ -146,7 +147,7 @@ Rectangle {
visible: d.buyActionAvailable visible: d.buyActionAvailable
icon.name: "token" icon.name: "token"
text: qsTr("Buy") text: qsTr("Buy")
onClicked: Global.openBuyCryptoModalRequested() onClicked: root.launchBuyCryptoModal()
} }
StatusFlatButton { StatusFlatButton {

View File

@ -10,3 +10,5 @@ TokenSelectorPanel 1.0 TokenSelectorPanel.qml
WalletHeader 1.0 WalletHeader.qml WalletHeader 1.0 WalletHeader.qml
WalletNftPreview 1.0 WalletNftPreview.qml WalletNftPreview 1.0 WalletNftPreview.qml
WalletTxProgressBlock 1.0 WalletTxProgressBlock.qml WalletTxProgressBlock 1.0 WalletTxProgressBlock.qml
BuyCryptoProvidersListPanel 1.0 BuyCryptoProvidersListPanel.qml
SelectParamsForBuyCryptoPanel 1.0 SelectParamsForBuyCryptoPanel.qml

View File

@ -1,97 +0,0 @@
import QtQuick 2.14
import QtQuick.Layouts 1.0
import QtQml.Models 2.14
import SortFilterProxyModel 0.2
import StatusQ.Popups.Dialog 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ 0.1
import utils 1.0
StatusDialog {
id: root
required property var onRampProvidersModel
padding: Style.current.xlPadding
implicitWidth: 560
implicitHeight: 436
title: qsTr("Buy assets")
ColumnLayout {
anchors.fill: parent
spacing: 20
StatusSwitchTabBar {
id: tabBar
objectName: "tabBar"
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
StatusSwitchTabButton {
text: qsTr("One time")
}
StatusSwitchTabButton {
text: qsTr("Recurrent")
}
}
StatusListView {
id: providersList
objectName: "providersList"
Layout.fillWidth: true
Layout.fillHeight: true
model: SortFilterProxyModel {
sourceModel: !!root.onRampProvidersModel ? root.onRampProvidersModel : null
filters: ValueFilter {
enabled: tabBar.currentIndex
roleName: "recurrentSiteUrl"
value: ""
inverted: true
}
}
delegate: StatusListItem {
width: ListView.view.width
title: name
subTitle: description
asset.name: logoUrl
asset.isImage: true
statusListItemSubTitle.maximumLineCount: 1
statusListItemComponentsSlot.spacing: 8
components: [
StatusBaseText {
objectName: "feesText"
text: fees
color: Theme.palette.baseColor1
lineHeight: 24
lineHeightMode: Text.FixedHeight
verticalAlignment: Text.AlignVCenter
},
StatusIcon {
objectName: "externalLinkIcon"
icon: "tiny/external"
color: sensor.containsMouse ? Theme.palette.directColor1: Theme.palette.baseColor1
}
]
onClicked: {
let url = tabBar.currentIndex ? recurrentSiteUrl : siteUrl
Global.openLinkWithConfirmation(url, hostname)
root.close()
}
}
}
}
footer: StatusDialogFooter {
objectName: "footer"
rightButtons: ObjectModel {
StatusButton {
text: qsTr("Done")
onClicked: root.close()
}
}
}
}

View File

@ -0,0 +1,143 @@
import QtQuick 2.14
import QtQuick.Layouts 1.0
import QtQml.Models 2.14
import SortFilterProxyModel 0.2
import StatusQ.Popups 0.1
import StatusQ.Popups.Dialog 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ 0.1
import utils 1.0
import AppLayouts.Wallet.controls 1.0
import AppLayouts.Wallet.adaptors 1.0
import AppLayouts.Wallet.panels 1.0
StatusStackModal {
id: root
required property BuyCryptoParamsForm buyCryptoInputParamsForm
required property BuyCryptoModalAdaptor buyCryptoAdaptor
QtObject {
id: d
readonly property var buyButton: StatusButton {
height: root.finishButton.height
visible: !!root.replaceItem
borderColor: "transparent"
text: qsTr("Buy via %1").arg(!!root.buyCryptoAdaptor.selectedProvider ? root.buyCryptoAdaptor.selectedProvider.name: "")
loading: root.buyCryptoAdaptor.urlIsBeingFetched
onClicked: {
if(!!root.buyCryptoAdaptor.selectedProvider && !!root.buyCryptoAdaptor.selectedToken) {
root.buyCryptoAdaptor.fetchProviderUrl(
root.buyCryptoInputParamsForm.selectedProviderId,
buyCryptoProvidersListPanel.currentTabIndex,
root.buyCryptoInputParamsForm.selectedWalletAddress,
root.buyCryptoInputParamsForm.selectedNetworkChainId,
root.buyCryptoAdaptor.selectedToken.symbol
)
}
}
enabled: root.buyCryptoInputParamsForm.filledCorrectly
}
}
width: 560
height: 515
padding: Style.current.xlPadding
stackTitle: qsTr("Buy assets for %1").arg(!!buyCryptoAdaptor.selectedAccount ? buyCryptoAdaptor.selectedAccount.name: "")
rightButtons: [d.buyButton, finishButton]
finishButton: StatusButton {
text: qsTr("Done")
onClicked: root.close()
}
Connections {
target: root.buyCryptoAdaptor
function onProviderUrlReady(url) {
if (!!root.buyCryptoAdaptor.selectedProvider && !!url)
Global.openLinkWithConfirmation(url, root.buyCryptoAdaptor.selectedProvider.hostname)
root.close()
}
}
onOpened: root.buyCryptoAdaptor.fetchProviders()
onClosed: {
// reset the view
root.replaceItem = undefined
buyCryptoProvidersListPanel.currentTabIndex = 0
root.buyCryptoAdaptor.reset()
root.buyCryptoInputParamsForm.resetFormData()
}
stackItems: [
BuyCryptoProvidersListPanel {
id: buyCryptoProvidersListPanel
providersLoading: root.buyCryptoAdaptor.providersLoading
providersModel: root.buyCryptoAdaptor.providersModel
selectedProviderId: root.buyCryptoInputParamsForm.selectedProviderId
isUrlBeingFetched: root.buyCryptoAdaptor.urlIsBeingFetched
onProviderSelected: {
root.buyCryptoInputParamsForm.selectedProviderId = id
if(!!root.buyCryptoAdaptor.selectedProvider) {
if(root.buyCryptoAdaptor.selectedProvider.urlsNeedParameters) {
root.replace(selectParamsPanel)
} else {
root.buyCryptoAdaptor.fetchProviderUrl(root.buyCryptoAdaptor.selectedProvider.id, currentTabIndex)
}
}
}
}
]
Component {
id: selectParamsPanel
SelectParamsForBuyCryptoPanel {
id: selectParamsPanelInst
adaptor: TokenSelectorViewAdaptor {
/* TODO these should be hadbled and perhaps improved under
https://github.com/status-im/status-desktop/issues/16025 */
assetsModel: SortFilterProxyModel {
sourceModel: root.buyCryptoAdaptor.groupedAccountAssetsModelWithKey
filters: FastExpressionFilter {
expression: model.addressPerChain.rowCount() > 0
expectedRoles: ["addressPerChain"]
}
}
plainTokensBySymbolModel: SortFilterProxyModel {
sourceModel: root.buyCryptoAdaptor.plainTokensBySymbolModelWithKey
filters: FastExpressionFilter {
expression: model.addressPerChain.rowCount() > 0
expectedRoles: ["addressPerChain"]
}
}
flatNetworksModel: root.buyCryptoAdaptor.networksModel
currentCurrency: root.buyCryptoAdaptor.currentCurrency
showAllTokens: true
enabledChainIds: root.buyCryptoInputParamsForm.selectedNetworkChainId !== -1 ? [root.buyCryptoInputParamsForm.selectedNetworkChainId] : []
accountAddress: root.buyCryptoInputParamsForm.selectedWalletAddress
searchString: selectParamsPanelInst.searchString
}
selectedProvider: root.buyCryptoAdaptor.selectedProvider
selectedTokenKey: root.buyCryptoInputParamsForm.selectedTokenKey
selectedNetworkChainId: root.buyCryptoInputParamsForm.selectedNetworkChainId
filteredFlatNetworksModel: root.buyCryptoAdaptor.filteredFlatNetworksModel
onNetworkSelected: {
if (root.buyCryptoInputParamsForm.selectedNetworkChainId !== chainId) {
root.buyCryptoInputParamsForm.selectedNetworkChainId = chainId
}
}
onTokenSelected: {
if (root.buyCryptoInputParamsForm.selectedTokenKey !== tokensKey) {
root.buyCryptoInputParamsForm.selectedTokenKey = tokensKey
}
}
}
}
}

View File

@ -0,0 +1,146 @@
import QtQml 2.15
import SortFilterProxyModel 0.2
import StatusQ 0.1
import StatusQ.Core.Utils 0.1
import utils 1.0
import shared.stores 1.0
import AppLayouts.Wallet 1.0
import AppLayouts.Wallet.stores 1.0 as WalletStore
QObject {
id: root
required property WalletStore.BuyCryptoStore buyCryptoStore
required property BuyCryptoParamsForm buyCryptoFormData
required property var walletAccountsModel
required property var networksModel
required property bool areTestNetworksEnabled
required property var groupedAccountAssetsModel
required property var plainTokensBySymbolModel
required property string currentCurrency
QtObject {
id: d
property string uuid
property bool urlIsBeingFetched
readonly property var selectedProviderSupportedArray: !!selectedProvider && !!selectedProvider.supportedAssets ? ModelUtils.modelToFlatArray(selectedProvider.supportedAssets, "key"): null
}
signal providerUrlReady(string url)
readonly property bool providersLoading: root.buyCryptoStore.areProvidersLoading
readonly property var providersModel: root.buyCryptoStore.providersModel
readonly property bool urlIsBeingFetched: d.urlIsBeingFetched
readonly property var selectedAccount: selectedAccountEntry.item
readonly property var selectedToken: selectedTokenEntry.item
readonly property var selectedProvider: selectedProviderEntry.item
readonly property SortFilterProxyModel filteredFlatNetworksModel: SortFilterProxyModel {
sourceModel: root.networksModel
filters: ValueFilter { roleName: "isTest"; value: root.areTestNetworksEnabled }
}
/* TODO evaluate if this is still needed after
https://github.com/status-im/status-desktop/issues/16025 */
readonly property ObjectProxyModel plainTokensBySymbolModelWithKey: ObjectProxyModel {
sourceModel: root.plainTokensBySymbolModel
delegate: SortFilterProxyModel {
id: delegateRoot
readonly property var addressPerChain: this
sourceModel: model.addressPerChain
proxyRoles: JoinRole {
name: "key"
roleNames: ["chainId", "address"]
separator: ""
}
filters: FastExpressionFilter {
expression: !!d.selectedProviderSupportedArray ? d.selectedProviderSupportedArray.includes(model.key) : true
expectedRoles: ["key"]
}
}
exposedRoles: ["addressPerChain"]
expectedRoles: ["addressPerChain"]
}
/* TODO evaluate if this is still needed after
https://github.com/status-im/status-desktop/issues/16025 */
readonly property ObjectProxyModel groupedAccountAssetsModelWithKey: ObjectProxyModel {
sourceModel: root.groupedAccountAssetsModel
delegate: SortFilterProxyModel {
id: delegateRoot1
readonly property var addressPerChain: this
sourceModel: model.addressPerChain
proxyRoles: JoinRole {
name: "key"
roleNames: ["chainId", "address"]
separator: ""
}
filters: FastExpressionFilter {
expression: !!d.selectedProviderSupportedArray ? d.selectedProviderSupportedArray.includes(model.key) : true
expectedRoles: ["key"]
}
}
exposedRoles: ["addressPerChain"]
expectedRoles: ["addressPerChain"]
}
function reset() {
d.uuid = ""
d.urlIsBeingFetched = false
}
function fetchProviders() {
root.buyCryptoStore.fetchProviders()
}
function fetchProviderUrl(
providerID,
isRecurrent,
accountAddress = "",
chainID = 0,
symbol = "") {
// Identify new search with a different uuid
d.uuid = Utils.uuid()
d.urlIsBeingFetched = true
buyCryptoStore.fetchProviderUrl(d.uuid, providerID, isRecurrent,
accountAddress, chainID,symbol)
}
Connections {
target: root.buyCryptoStore
function onProviderUrlReady(uuid, url) {
if(uuid === d.uuid) {
d.urlIsBeingFetched = false
root.providerUrlReady(url)
}
}
}
ModelEntry {
id: selectedAccountEntry
sourceModel: root.walletAccountsModel
key: "address"
value: root.buyCryptoFormData.selectedWalletAddress
}
ModelEntry {
id: selectedTokenEntry
sourceModel: root.plainTokensBySymbolModel
key: "key"
value: root.buyCryptoFormData.selectedTokenKey
}
ModelEntry {
id: selectedProviderEntry
sourceModel: root.providersModel
key: "id"
value: root.buyCryptoFormData.selectedProviderId
}
}

View File

@ -0,0 +1,19 @@
import QtQml 2.15
QtObject {
id: root
property string selectedWalletAddress: ""
property int selectedNetworkChainId: -1
property string selectedTokenKey: ""
property string selectedProviderId: ""
readonly property bool filledCorrectly: !!selectedWalletAddress && !!selectedTokenKey && selectedNetworkChainId !== -1
function resetFormData() {
selectedWalletAddress = ""
selectedNetworkChainId = -1
selectedTokenKey = ""
selectedProviderId = ""
}
}

View File

@ -0,0 +1,3 @@
BuyCryptoModal 1.0 BuyCryptoModal.qml
BuyCryptoModalAdaptor 1.0 BuyCryptoModalAdaptor.qml
BuyCryptoParamsForm 1.0 BuyCryptoParamsForm.qml

View File

@ -6,5 +6,4 @@ ReceiveModal 1.0 ReceiveModal.qml
AddEditSavedAddressPopup 1.0 AddEditSavedAddressPopup.qml AddEditSavedAddressPopup 1.0 AddEditSavedAddressPopup.qml
RemoveSavedAddressPopup 1.0 RemoveSavedAddressPopup.qml RemoveSavedAddressPopup 1.0 RemoveSavedAddressPopup.qml
SavedAddressActivityPopup 1.0 SavedAddressActivityPopup.qml SavedAddressActivityPopup 1.0 SavedAddressActivityPopup.qml
BuyCryptoModal 1.0 BuyCryptoModal.qml
SignTransactionModalBase 1.0 SignTransactionModalBase.qml SignTransactionModalBase 1.0 SignTransactionModalBase.qml

View File

@ -16,6 +16,7 @@ import shared.controls 1.0
import AppLayouts.Wallet.controls 1.0 import AppLayouts.Wallet.controls 1.0
import AppLayouts.Wallet.panels 1.0 import AppLayouts.Wallet.panels 1.0
import AppLayouts.Wallet.popups.buy 1.0
StatusDialog { StatusDialog {
id: root id: root
@ -61,6 +62,12 @@ StatusDialog {
} }
readonly property bool isError: root.swapAdaptor.errorMessage !== "" readonly property bool isError: root.swapAdaptor.errorMessage !== ""
readonly property BuyCryptoParamsForm buyFormData: BuyCryptoParamsForm {
selectedWalletAddress: root.swapInputParamsForm.selectedAccountAddress
selectedNetworkChainId: root.swapInputParamsForm.selectedNetworkChainId
selectedTokenKey: root.swapInputParamsForm.fromTokensKey
}
} }
Connections { Connections {
@ -314,7 +321,13 @@ StatusDialog {
text: root.swapAdaptor.errorMessage text: root.swapAdaptor.errorMessage
buttonText: root.swapAdaptor.isTokenBalanceInsufficient ? qsTr("Buy crypto") : qsTr("Buy ETH") buttonText: root.swapAdaptor.isTokenBalanceInsufficient ? qsTr("Buy crypto") : qsTr("Buy ETH")
buttonVisible: visible && (root.swapAdaptor.isTokenBalanceInsufficient || root.swapAdaptor.isEthBalanceInsufficient) buttonVisible: visible && (root.swapAdaptor.isTokenBalanceInsufficient || root.swapAdaptor.isEthBalanceInsufficient)
onButtonClicked: Global.openBuyCryptoModalRequested() onButtonClicked: {
// value dont update correctly if not done from here
d.buyFormData.selectedWalletAddress = root.swapInputParamsForm.selectedAccountAddress
d.buyFormData.selectedNetworkChainId = root.swapInputParamsForm.selectedNetworkChainId
d.buyFormData.selectedTokenKey =root.swapInputParamsForm.fromTokensKey
Global.openBuyCryptoModalRequested(d.buyFormData)
}
} }
} }
} }

View File

@ -0,0 +1,35 @@
import QtQuick 2.15
QtObject {
id: root
readonly property var providersModel: walletSectionBuySellCrypto.model
readonly property bool areProvidersLoading: walletSectionBuySellCrypto.isFetching
signal providerUrlReady(string uuid , string url)
function fetchProviders() {
walletSectionBuySellCrypto.fetchProviders()
}
function fetchProviderUrl(
uuid,
providerID,
isRecurrent,
selectedWalletAddress = "",
chainID = 0,
symbol = "") {
walletSectionBuySellCrypto.fetchProviderUrl(
uuid,
providerID,
isRecurrent,
selectedWalletAddress,
chainID,
symbol
)
}
Component.onCompleted: {
walletSectionBuySellCrypto.providerUrlReady.connect(root.providerUrlReady)
}
}

View File

@ -172,8 +172,6 @@ QtObject {
d.initChainColors(flatNetworks) d.initChainColors(flatNetworks)
} }
property var cryptoRampServicesModel: walletSectionBuySellCrypto.model
function resetCurrentViewedHolding(type) { function resetCurrentViewedHolding(type) {
currentViewedHoldingTokensKey = "" currentViewedHoldingTokensKey = ""
currentViewedHoldingID = "" currentViewedHoldingID = ""

View File

@ -4,3 +4,4 @@ CollectiblesStore 1.0 CollectiblesStore.qml
TokensStore 1.0 TokensStore.qml TokensStore 1.0 TokensStore.qml
WalletAssetsStore 1.0 WalletAssetsStore.qml WalletAssetsStore 1.0 WalletAssetsStore.qml
SwapStore 1.0 SwapStore.qml SwapStore 1.0 SwapStore.qml
BuyCryptoStore 1.0 BuyCryptoStore.qml

View File

@ -16,6 +16,7 @@ import AppLayouts.Profile.popups 1.0
import AppLayouts.Communities.popups 1.0 import AppLayouts.Communities.popups 1.0
import AppLayouts.Communities.helpers 1.0 import AppLayouts.Communities.helpers 1.0
import AppLayouts.Wallet.popups.swap 1.0 import AppLayouts.Wallet.popups.swap 1.0
import AppLayouts.Wallet.popups.buy 1.0
import AppLayouts.Wallet.popups 1.0 import AppLayouts.Wallet.popups 1.0
import AppLayouts.Wallet.stores 1.0 as WalletStore import AppLayouts.Wallet.stores 1.0 as WalletStore
@ -397,8 +398,10 @@ QtObject {
openPopup(swapModal, {swapInputParamsForm: parameters}) openPopup(swapModal, {swapInputParamsForm: parameters})
} }
function openBuyCryptoModal() { function openBuyCryptoModal(parameters) {
openPopup(buyCryptoModal) openPopup(buyCryptoModal, {
buyCryptoInputParamsForm: parameters
})
} }
readonly property list<Component> _components: [ readonly property list<Component> _components: [
@ -1254,7 +1257,16 @@ QtObject {
Component { Component {
id: buyCryptoModal id: buyCryptoModal
BuyCryptoModal { BuyCryptoModal {
onRampProvidersModel: WalletStore.RootStore.cryptoRampServicesModel buyCryptoAdaptor: BuyCryptoModalAdaptor {
buyCryptoStore: WalletStore.BuyCryptoStore {}
buyCryptoFormData: buyCryptoInputParamsForm
walletAccountsModel: root.rootStore.accounts
networksModel: root.rootStore.profileSectionStore.walletStore.flatNetworks
areTestNetworksEnabled: root.rootStore.profileSectionStore.walletStore.areTestNetworksEnabled
groupedAccountAssetsModel: root.walletAssetsStore.groupedAccountAssetsModel
plainTokensBySymbolModel: root.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel
currentCurrency: root.currencyStore.currentCurrency
}
onClosed: destroy() onClosed: destroy()
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -107,7 +107,7 @@ QtObject {
signal openSwapModalRequested(var formDataParams) signal openSwapModalRequested(var formDataParams)
// BuyCrypto // BuyCrypto
signal openBuyCryptoModalRequested() signal openBuyCryptoModalRequested(var formDataParams)
// Metrics // Metrics
signal openMetricsEnablePopupRequested(string placement, var cb) signal openMetricsEnablePopupRequested(string placement, var cb)