From c9641bb0b95300ffa934242cb0a07c0953262b67 Mon Sep 17 00:00:00 2001 From: Khushboo Mehta Date: Mon, 27 May 2024 18:55:43 +0200 Subject: [PATCH] feat(@desktop/wallet): Implementation of One Time & Recurrent tab in Buy Popup fixes #14819 --- storybook/pages/BuyCryptoModalPage.qml | 37 +++++ .../qmlTests/tests/tst_BuyCryptoModal.qml | 146 ++++++++++++++++++ storybook/src/Models/ModelsData.qml | 6 + storybook/src/Models/OnRampProvidersModel.qml | 35 +++++ storybook/src/Models/qmldir | 1 + .../AppLayouts/Wallet/panels/WalletFooter.qml | 9 +- .../Wallet/popups/BuyCryptoModal.qml | 98 ++++++++++++ .../Wallet/popups/CryptoServicesModal.qml | 76 --------- ui/app/AppLayouts/Wallet/popups/qmldir | 1 + ui/app/mainui/Popups.qml | 13 ++ .../assets/png/onRampProviders/latamex.png | Bin 0 -> 7405 bytes .../assets/png/onRampProviders/moonPay.png | Bin 0 -> 13220 bytes .../assets/png/onRampProviders/ramp.png | Bin 0 -> 1845 bytes ui/imports/utils/Global.qml | 3 + 14 files changed, 341 insertions(+), 84 deletions(-) create mode 100644 storybook/pages/BuyCryptoModalPage.qml create mode 100644 storybook/qmlTests/tests/tst_BuyCryptoModal.qml create mode 100644 storybook/src/Models/OnRampProvidersModel.qml create mode 100644 ui/app/AppLayouts/Wallet/popups/BuyCryptoModal.qml delete mode 100644 ui/app/AppLayouts/Wallet/popups/CryptoServicesModal.qml create mode 100644 ui/imports/assets/png/onRampProviders/latamex.png create mode 100644 ui/imports/assets/png/onRampProviders/moonPay.png create mode 100644 ui/imports/assets/png/onRampProviders/ramp.png diff --git a/storybook/pages/BuyCryptoModalPage.qml b/storybook/pages/BuyCryptoModalPage.qml new file mode 100644 index 0000000000..55499ca1b8 --- /dev/null +++ b/storybook/pages/BuyCryptoModalPage.qml @@ -0,0 +1,37 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +import Storybook 1.0 +import Models 1.0 + +import AppLayouts.Wallet.popups 1.0 + +SplitView { + id: root + + orientation: Qt.Horizontal + + PopupBackground { + id: popupBg + + SplitView.fillWidth: true + SplitView.fillHeight: true + + Button { + id: reopenButton + anchors.centerIn: parent + text: "Reopen" + enabled: !buySellModal.visible + + onClicked: buySellModal.open() + } + + BuyCryptoModal { + id: buySellModal + visible: true + onRampProvidersModel: OnRampProvidersModel{} + } + } +} + +// category: Popups diff --git a/storybook/qmlTests/tests/tst_BuyCryptoModal.qml b/storybook/qmlTests/tests/tst_BuyCryptoModal.qml new file mode 100644 index 0000000000..4408d47152 --- /dev/null +++ b/storybook/qmlTests/tests/tst_BuyCryptoModal.qml @@ -0,0 +1,146 @@ +import QtQuick 2.15 +import QtTest 1.15 + +import StatusQ.Core.Theme 0.1 + +import Models 1.0 +import utils 1.0 + +import AppLayouts.Wallet.popups 1.0 + +Item { + id: root + width: 600 + height: 800 + + OnRampProvidersModel{ + id: onRampProvidersModal + } + + Component { + id: componentUnderTest + BuyCryptoModal { + onRampProvidersModel: onRampProvidersModal + onClosed: destroy() + } + } + + SignalSpy { + id: notificationSpy + target: Global + signalName: "openLinkWithConfirmation" + } + + TestCase { + name: "BuyCryptoModal" + when: windowShown + + property BuyCryptoModal controlUnderTest: null + + function init() { + controlUnderTest = createTemporaryObject(componentUnderTest, root) + } + + function launchPopup() { + verify(!!controlUnderTest) + controlUnderTest.open() + verify(!!controlUnderTest.opened) + } + + function test_launchAndCloseModal() { + launchPopup() + + // close popup + controlUnderTest.close() + verify(!controlUnderTest.opened) + } + + function test_ModalFooter() { + // Launch modal + launchPopup() + + // check if footer has Done button and action on button clicked + const footer = findChild(controlUnderTest, "footer") + verify(!!footer) + compare(footer.rightButtons.count, 1) + compare(footer.rightButtons.get(0).text, qsTr("Done")) + mouseClick(footer.rightButtons.get(0), Qt.LeftButton) + + // popup should be closed + verify(!controlUnderTest.opened) + } + + function test_modalContent() { + // Launch modal + launchPopup() + + // find tab bar + const tabBar = findChild(controlUnderTest, "tabBar") + verify(!!tabBar) + + // should have 2 items + compare(tabBar.count, 2) + + // current index set should be to 0 + compare(tabBar.currentIndex, 0) + + // item 0 should have text "One time" + compare(tabBar.itemAt(0).text, qsTr("One time")) + + // item 1 should have text "Recurrent" + compare(tabBar.itemAt(1).text, qsTr("Recurrent")) + + // TODO: this will be implemnted under https://github.com/status-im/status-desktop/issues/14820 + // until then this list will be empty + mouseClick(tabBar.itemAt(1), Qt.LeftButton) + compare(tabBar.currentIndex, 1) + + const providersList = findChild(controlUnderTest, "providersList") + waitForRendering(providersList) + verify(!!providersList) + compare(providersList.count, 0) + + // check data on 1st tab -------------------------------------------------------- + mouseClick(tabBar.itemAt(0), Qt.LeftButton) + compare(tabBar.currentIndex, 0) + + waitForRendering(providersList) + verify(!!providersList) + + // verify that 3 items are listed + compare(providersList.count, 3) + + // check if delegate contents are as expected + for(let i =0; i< providersList.count; i++) { + let delegateUnderTest = providersList.itemAtIndex(i) + verify(!!delegateUnderTest) + + compare(delegateUnderTest.title, onRampProvidersModal.get(i).name) + compare(delegateUnderTest.subTitle, onRampProvidersModal.get(i).description) + compare(delegateUnderTest.asset.name, onRampProvidersModal.get(i).logoUrl) + + const feesText = findChild(delegateUnderTest, "feesText") + verify(!!feesText) + compare(feesText.text, onRampProvidersModal.get(i).fees) + + const externalLinkIcon = findChild(delegateUnderTest, "externalLinkIcon") + verify(!!externalLinkIcon) + compare(externalLinkIcon.icon, "tiny/external") + compare(externalLinkIcon.color, Theme.palette.baseColor1) + + // Hover over the item and check hovered state + mouseMove(delegateUnderTest, delegateUnderTest.width/2, delegateUnderTest.height/2) + verify(delegateUnderTest.sensor.containsMouse) + compare(externalLinkIcon.color, Theme.palette.directColor1) + verify(delegateUnderTest.color, Theme.palette.baseColor2) + } + + // test mouse click + tryCompare(notificationSpy, "count", 0) + mouseClick(providersList.itemAtIndex(0)) + tryCompare(notificationSpy, "count", 1) + compare(notificationSpy.signalArguments[0][0],onRampProvidersModal.get(0).siteUrl) + compare(notificationSpy.signalArguments[0][1],onRampProvidersModal.get(0).hostname) + } + } +} diff --git a/storybook/src/Models/ModelsData.qml b/storybook/src/Models/ModelsData.qml index 0c87b7a33e..c4a93e3776 100644 --- a/storybook/src/Models/ModelsData.qml +++ b/storybook/src/Models/ModelsData.qml @@ -82,4 +82,10 @@ QtObject { readonly property string ownerTokenInfo: "In order to Mint, Import and Airdrop community tokens, you first need to mint your Owner token which will give you permissions to access the token management features for your community." readonly property string airdropInfo: "You can Airdrop tokens to deserving Community members or to give individuals token-based permissions." } + + readonly property QtObject onRampProviderImages: QtObject { + readonly property string latamex: Style.png("onRampProviders/latamex") + readonly property string moonPay: Style.png("onRampProviders/moonPay") + readonly property string ramp: Style.png("onRampProviders/ramp") + } } diff --git a/storybook/src/Models/OnRampProvidersModel.qml b/storybook/src/Models/OnRampProvidersModel.qml new file mode 100644 index 0000000000..5404f0a533 --- /dev/null +++ b/storybook/src/Models/OnRampProvidersModel.qml @@ -0,0 +1,35 @@ +import QtQuick 2.15 + +ListModel { + readonly property var data: [ + { + name: "Ramp", + description: "Global crypto to fiat flow", + fees: "0.49% - 2.9%", + logoUrl: ModelsData.onRampProviderImages.ramp, + siteUrl: "https://ramp.network/buy?hostApiKey=zrtf9u2uqebeyzcs37fu5857tktr3eg9w5tffove&swapAsset=DAI,ETH,USDC,USDT", + hostname: "ramp.network", + recurrentSiteURL: "" + }, + { + name: "MoonPay", + description: "The new standard for fiat to crypto", + fees: "1% - 4.5%", + logoUrl: ModelsData.onRampProviderImages.moonPay, + siteUrl: "https://buy.moonpay.com/?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR", + hostname: "moonpay.com", + recurrentSiteURL: "https://buy.moonpay.com/?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR", + }, + { + name: "Latamex", + description: "Easily buy crypto in Argentina, Mexico, and Brazil", + fees: "1% - 1.7%", + logoUrl: ModelsData.onRampProviderImages.latamex, + siteUrl: "https://latamex.com/", + hostname: "latamex.com", + recurrentSiteURL: "", + } + ] + + Component.onCompleted: append(data) +} diff --git a/storybook/src/Models/qmldir b/storybook/src/Models/qmldir index 062845538f..95f7929692 100644 --- a/storybook/src/Models/qmldir +++ b/storybook/src/Models/qmldir @@ -22,6 +22,7 @@ WalletTransactionsModel 1.0 WalletTransactionsModel.qml GroupedAccountsAssetsModel 1.0 GroupedAccountsAssetsModel.qml TokensBySymbolModel 1.0 TokensBySymbolModel.qml CommunitiesModel 1.0 CommunitiesModel.qml +OnRampProvidersModel 1.0 OnRampProvidersModel.qml singleton ModelsData 1.0 ModelsData.qml singleton NetworksModel 1.0 NetworksModel.qml diff --git a/ui/app/AppLayouts/Wallet/panels/WalletFooter.qml b/ui/app/AppLayouts/Wallet/panels/WalletFooter.qml index 5d150893e8..bfdbb0c721 100644 --- a/ui/app/AppLayouts/Wallet/panels/WalletFooter.qml +++ b/ui/app/AppLayouts/Wallet/panels/WalletFooter.qml @@ -81,9 +81,7 @@ Rectangle { visible: !root.isCommunityOwnershipTransfer && !root.walletStore.showAllAccounts icon.name: "token" text: qsTr("Buy") - onClicked: function () { - Global.openPopup(buySellModal); - } + onClicked: Global.openBuyCryptoModalRequested() } StatusFlatButton { @@ -97,11 +95,6 @@ Rectangle { onClicked: root.launchSwapModal() } } - - Component { - id: buySellModal - CryptoServicesModal {} - } } diff --git a/ui/app/AppLayouts/Wallet/popups/BuyCryptoModal.qml b/ui/app/AppLayouts/Wallet/popups/BuyCryptoModal.qml new file mode 100644 index 0000000000..18eb113f41 --- /dev/null +++ b/ui/app/AppLayouts/Wallet/popups/BuyCryptoModal.qml @@ -0,0 +1,98 @@ +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 + // TODO: this temporary and changed under https://github.com/status-im/status-desktop/issues/14820 + // when recurrentSiteURL is available + filters: ValueFilter { + enabled: tabBar.currentIndex + roleName: "name" + value: "" + } + } + 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() + } + } + } +} diff --git a/ui/app/AppLayouts/Wallet/popups/CryptoServicesModal.qml b/ui/app/AppLayouts/Wallet/popups/CryptoServicesModal.qml deleted file mode 100644 index 872adf0ec0..0000000000 --- a/ui/app/AppLayouts/Wallet/popups/CryptoServicesModal.qml +++ /dev/null @@ -1,76 +0,0 @@ -import QtQuick 2.14 -import QtQuick.Controls 2.14 - -import utils 1.0 -import shared.panels 1.0 - -import StatusQ.Popups 0.1 -import StatusQ.Components 0.1 -import StatusQ.Core.Theme 0.1 -import StatusQ.Core 0.1 - -import "../controls" -import "../stores" - -StatusModal { - id: cryptoServicesPopupRoot - - height: 400 - headerSettings.title: qsTr("Buy crypto") - anchors.centerIn: parent - - Loader { - id: loader - anchors.fill: parent - sourceComponent: servicesComponent - - Component { - id: servicesComponent - Item { - anchors.fill: parent - anchors.topMargin: Style.current.padding - anchors.bottomMargin: Style.current.padding - anchors.leftMargin: Style.current.padding - anchors.rightMargin: Style.current.padding - StyledText { - id: note - anchors.top: parent.top - anchors.horizontalCenter: parent.horizontalCenter - color: Style.current.secondaryText - text: qsTr("Choose a service you'd like to use to buy crypto") - } - - StatusListView { - anchors.top: note.bottom - anchors.bottom: parent.bottom - anchors.topMargin: Style.current.padding - anchors.horizontalCenter: parent.horizontalCenter - width: 394 - model: RootStore.cryptoRampServicesModel - focus: true - spacing: Style.current.padding - - delegate: StatusListItem { - width: parent.width - title: name - subTitle: description - asset.name: logoUrl - asset.isImage: true - label: fees - statusListItemSubTitle.maximumLineCount: 1 - components: [ - StatusIcon { - icon: "next" - color: Theme.palette.baseColor1 - } - ] - onClicked: { - Global.openLink(siteUrl); - cryptoServicesPopupRoot.close(); - } - } - } - } - } - } -} diff --git a/ui/app/AppLayouts/Wallet/popups/qmldir b/ui/app/AppLayouts/Wallet/popups/qmldir index 4aacaa2a38..52552b4151 100644 --- a/ui/app/AppLayouts/Wallet/popups/qmldir +++ b/ui/app/AppLayouts/Wallet/popups/qmldir @@ -6,3 +6,4 @@ ReceiveModal 1.0 ReceiveModal.qml AddEditSavedAddressPopup 1.0 AddEditSavedAddressPopup.qml RemoveSavedAddressPopup 1.0 RemoveSavedAddressPopup.qml SavedAddressActivityPopup 1.0 SavedAddressActivityPopup.qml +BuyCryptoModal 1.0 BuyCryptoModal.qml diff --git a/ui/app/mainui/Popups.qml b/ui/app/mainui/Popups.qml index 37c3d0b915..1736b6aab0 100644 --- a/ui/app/mainui/Popups.qml +++ b/ui/app/mainui/Popups.qml @@ -16,6 +16,7 @@ import AppLayouts.Profile.popups 1.0 import AppLayouts.Communities.popups 1.0 import AppLayouts.Communities.helpers 1.0 import AppLayouts.Wallet.popups.swap 1.0 +import AppLayouts.Wallet.popups 1.0 import AppLayouts.Wallet.stores 1.0 as WalletStore import AppLayouts.Chat.stores 1.0 as ChatStore @@ -91,6 +92,7 @@ QtObject { Global.openConfirmHideCollectiblePopup.connect(openConfirmHideCollectiblePopup) Global.openCommunityMemberMessagesPopupRequested.connect(openCommunityMemberMessagesPopup) Global.openSwapModalRequested.connect(openSwapModal) + Global.openBuyCryptoModalRequested.connect(openBuyCryptoModal) } property var currentPopup @@ -390,6 +392,10 @@ QtObject { openPopup(swapModal, {swapInputParamsForm: parameters}) } + function openBuyCryptoModal() { + openPopup(buyCryptoModal) + } + readonly property list _components: [ Component { id: removeContactConfirmationDialog @@ -1248,6 +1254,13 @@ QtObject { } onClosed: destroy() } + }, + Component { + id: buyCryptoModal + BuyCryptoModal { + onRampProvidersModel: WalletStore.RootStore.cryptoRampServicesModel + onClosed: destroy() + } } ] } diff --git a/ui/imports/assets/png/onRampProviders/latamex.png b/ui/imports/assets/png/onRampProviders/latamex.png new file mode 100644 index 0000000000000000000000000000000000000000..891e1510d6b8e74b9fb269e6e3bdfa5e25798269 GIT binary patch literal 7405 zcmV@?*}- znKLlX0-2BuI0<2iLu}&&vn4SJ0fxocIJUu-Z7r58+1huhyQ}8j_g+<3RaduUNp|MU zv&&Uo%d2`{-Fv@#?|b#E;V)Q@963^G7{*Fn*K0LRTS`lp%a2O$43{9tXNE|al1}uI+OP)*Dg1~{9FcFK#XgiKrEDn-D zkTm*lxskz~KY#ufoZ@oI0Ay*)&dy#>jk^yn(6X|!kdu=`z=g!Nd;*IRqJK5Jk! zW^Y;Qm!`I9OOtzIu^1*MCNMfWD%P&jM8JQWjzYF$jCT!I;S9-gUXT|t!h&A0Nly;Go!6rHRbO#>&ddZ)29rtO9uS=+Sj#+a7?jZ7gB= z`T4XCi{lBpUC-b+UjOg}UfX{h?;YyHi6N3Zi)BxTZb_BphtiyFO{{gbU!KEfo3yQ= zVvdfbi;HmK(sF!kVLr+V=q2e=LK(=Rp&_?a3W=<)uHJ}QDzgIMv17-WJ)clE&IMeS zI37z_c)hU;&%M=#KON}B;AjFmOQK~82@{I~OjkBfcYxF!P@QvN+eS+OtXmR%5=NYN zP6<|hvJ4k2DW&ral1>R^Utgaik+g3M?YnewBmZ=H* zI5ILK0noG!RaI5@W13}J0J6#wNo=OgWh`~9uF+^z9NXV9h;Kam0d_YJ!O}x8ENQD? zgJCyL(*mU`o#c7IbG-zy5O{{F53c%n%P=KtFRshQJ?k2LlK*~zuj zQR$NgP=WV*+N{+L9VI1Y=AwgxwHJfHzgiLm*+eY@T~RlE-u? zvjDGZ%a@>RsA(Z=Xt?Eu`MByc^N<}jgerG+chOpa*hCoDFEHzg~{P9EG|Zf zxV3BC!k0IGfOn4!NY$gas%x?V9?65UdD9?_6v?xXK}(Td;n0ZRUS?;YEz*b;XP4mb z@2Ev-DUn>lKzC1%aLA_v;*~2@1#ZdKUHcqjp~Y~yOvG>)8koR_ zhxg*0caMSH($dlr5n^&%$%oy{p2lR@ObTFod;5Qa*_Ohw!r~$kr*7ZVfv-PzfF2@? zz>9m-6i5OkwlyVr9#vIm3E;J~gyF8sPZ)qteJtgYyVTa*NFAEzh3TdyR6I5YJof!V z*!$;RaYhN*b;A%XS;lS}W&$9GX6)y&t5QrhFN8SRyk2}`^8u1P&GYsR!F2A1dL_>- zEq*BslDrft1-zc}|_CvV$(k^J;>uZ+y(eqYr(Aw$?$C#5hVzD2kyrbK6OP z?wb~XZ1+fdSo+A%%R`m{wDiVs&r|y_I5bXICQ=+)w~E3tWQ?m85q2rblguey9Nn@4 zq!WQ`o5I4Dl4Acc)dpcF;U*=^k$Mkv)1Q&i7#@B207i!C7)fAWUY@9fKzx8yxfUl2 zAYI7d73NYFB^u4c$b^M|+O!|7UE_32mnwi%BX5vTWwDJSX|>;+}F3@KPhx+%cAODoY(kuMBA0_>H& ze&m-QqGy;R1>v0`#m@uMMi`R0L9R#`H~no5?W5$YCLV z(+FU8GpW+FUVU99)_ksBL@CFQ9~Wy9sM~|$=1?H2G9`s5sV?L2=k@_S^73J_3zU{J zwTy)EVbcKCU(tXZ&Maqek_w_(_{R5l$(qs;h89d1!X!{*zk27nII})IQSxaCGmh=Q zZV^8W0@|qq%B%?Bbms-}^757roPS{js^&+9Bn}J=2uw(ox77K%3sO{=Y#)PH%TgE3 z%|U`1@wKOSQ@lZ{X0pmy842T^#zAa*r(L8=GnEU^EX9iY0@#tn$q)u71lC?&g@y%l zGTy_oV%WN+1+6XPUYEy0O5IMR#O8%u!Dk*jDArL*0;{xKEx9-;grfVvV~2SiZx10JJn(4U959>DS55z5L~QVaqLy&ru2wsVoi84{5k%}f}M z!%gQ_m4&c&RW*4o38aBewPzgLUpPwFgk0)sDd~f9c{I;`Y@e}l?=W_~)g|u9$r1sU zuCMp|h8_SZxLyhAM1l+_h9}~9{143{t73;@NMSrbqjBCXgol2002+1tq-`R3u5(Ls zaot75^k9Y){-q7ioC`y^>$b%xDauyPNjeA<_~C!;C3fX=R3cR|v1Z@PCKM#Wvn7#} zv73K(02W=!SSTqh^h=@V32fWPde6OJ+jh3%a9125)0%RG!EY=?snnO>@4{P+y)r%y zD7xr5(s9Syvr(QKm-{kA7-Bo2c zW?EAahGyzX)wR6$Gi(hL`%S#@BC&AXM1&-ev7u7P-LxqH(!pzaEs?hH>fTPYk>hOm zB@dHF7}8GaXz!Z9kDuR1FC*9vs`lbj%S*9jVPujBBaY9ntta*l`yuuf4L|zfe(K^h z)pc4%!f@~Nf+w%(I6Q$P`})KSV4qlFwcZ1uGK}kZoAo_T7jAz0n2bA-o-piY=qXZ| zbcQ$m?if0H$AuaMHdkDz!N}%ZoQ!nb~KX)Kb$x* zjHiFzBEv*Q78wac_RPbdHTOs>?P%ORgxGjO#K$(7*qGS>3iag?16+1CQ>V+g2|EEg z)0EWC5Bu=)+igg%$kL|XbagE%3MB*TO41FY!JF1pqP#R)b)W~A1pRsLnKtU@m=M5t z)H4lXFwh2ESsK{pCwUD^UTo0B&OaT48zXw&l@5SZ#1B?q*7aBS98*45vT-v>NiiUg zKKqgI4Ot4!G*0%MXf|$GRUO{ymdk~8cu|f zi7<4Z&4Z_Xx>$rXQ~R4g7!lZnLNb~mX%s@ID_yQ-@#JJ8Cr5W4>Lbw16v>-zN{Xea zeKJg1YI*;_7`APtq-er)BzHQ5 z;f;inQpoSAX%EHHCaZ8ncma$VW2X~n%lH?A#}C~}57XJ7P!&y`FjA${Eiabv$DZHO zirojgkvf>l5|Z@X^NnckFooK1hUJbg)S$9F3aN0x>dR*JCy(z(PftQgk)DE4@InFs@cDJlPTmKDa2 zf6?MoU`Z~`?L*kK?U)#Rq*LV6P#?nITwEguBWVBvB#_;s_ulTtd;c@2(reNI&KO~2 zAPmi6es33raH;4e9&Z{EuQ9BK;PJpvokxXAG($oP4s{O0=?(-=nlMs8M>4`-$Mg_o zeSf~?fC~l<6fxr8ANfEu)F8HwW}CS0OUvj@2TPq@2Kr-o=E;LjVj~k_*bzoX!a#so zLeic#?e7-pvT#_A`QcHu1fpKUKeD(pg&Nw~7e8fv81l^;cr-sYe({Lm2L7^{PCt2acQ4EmA}DcsMeV zj3pgHLl@U}_m9qqFuaC1APOM2WMV?Y_nz1-BUsVufScepPm%uQICJJw!S=2{0pIyg9P&WJGl;Au#e zWVWw+_s8(syT`HVSNkc}7k_7&4{Fb`cr_C?!zS1*3I#j|C7$ddYJh+I7>ko!$%uOtuwB7)ijiJX>dJ*!(()DIIZNR5C&X}DIZ?95ZH&|u7~q_rp4hA1#g;x z1=R+wzqUabX&}h!)5Q&14iDp{-!#*&Ea;YWZ~WvY!bl%s_-z~9&yof_zowbv(jT>4 zPnD7rN)kqT@J_Z51Gb8JKu@T;G(^G)+;i7b<)Egc4j!d%;nDBzCdtcE=UIV-F=>S1 zYloXK+%`|QyiZ{0c1M-vx>xe~M9I(1o;AYA*y(L4`$THE=Bg^x%*)4Qg?s20)z49k ziBn1#UgDG2Mk1+pnfEvG2KR+BvQ;Iym=(ehFU6gbg2!G8rcg=$2fwV;v zH@oh03n`#aC=Jo4A7KC)3Bz?)=bA_!|1xD}NtQm{d!~lsXgEdkGDjF`2*Yxvq=K%c ze?mkY_ujh%;gH|5q$@g#=mlSYYppUDi5W#0nFzx#I0E2^B{D*u&nJj6n|LcW5fdjB z=S6U`5r*y)b-&u$F9E7CavY(7o35|Kys8}a?TCh{mJ9y65@((j6<;>-RWpk)TxtuS z*1787?ShgV(HUlE*vakd)73|N^dli;pt3MDHNsFtV;^(MWTT`sX@sjPOkA<5#s!{^ zsg~?q9cw;6pX}!ZLcW(foe0A&ZYv_rGrdw+Tpbqm#3#n(`6PUNJr55+JQfoTsXZe{ z1>~4L!f-}O8REPUg>d)&1E=uqWYI|$s<^hH02f|f4&g|+!%NR|PMt7yq}|Kz6By z+~O<|WvOAnyxyhP$-y%G0kildirMje>bMqz&g@Fe=@N!_Sgk=)b1(MJ-nnG#0QgmGgMX!vBgVBlD6+;(G{7&~!K0&lBA zR6NuL=afK>W|EZ}+B6BnW=HPSPH4E|Z^}_$Pid;O{lu0avp4_HjCbBVfnPjv1S33{ zGmR>9?}`!DaP!>_lp)cb>~SW-aNBOU0QVDytxJguW$R*q;`9l_^}y7%Sy_?5jW;f)-(gs3O`nB6N@i?*x`XP-LRZH)cD!)Z z9?E4Dl|j#^$GvV4%lT*M;!P=3{8*&&C3;kdXm1 z@fCkphx{UCb}|r#`^rGVaJCf(&`YUXk&ke0mT;i$PiJlJ5Opg%D0U1D4U6w>uU%QK z-tY7XL-=3Jq;Uu3s#!vyk5QjSR-|{L@Fpr&oq1-@Z%?==gBw0RHsb zR-}_$(Ga?3`9tXzU({YRr zO$d?+EM(}Zj}}+nJ`cG$x@Q!_)CmLPIt}vKx$9u*O_id{cYJKzj)9xplUaCLWJ@6< z&Hm06m(-!U!VrBGQzi_D`3$UDRe_~T%Q0EmyYo1y?r}$2f>KgF$0o4-sY8?2Raswz zWtWkY9=E0(VYt=VmOO@WPPK)zubeCDFCW@FM{*t zG7^S&e;IWYtiHMmIx@K|ruf|I>Hj_?*g0cLiZ7t2OcITWU~L5ptd< z)s7>OFdWu~jG9)gs}t8V9*R7gcm|NP0J33pOCh7S@`7?SERZ=uSXLUsaKB;M#rXN# zYEV)VL2&r*Lz4Ol$JRB?sn4Bp$NAAsrXrUBlfr7#$gPY#;H&gZ?|E0LW5k>-iw*J)86D$|yd! zW*+1)SuKDtc=VPoB(J0JIw>cyY7VBo|U)shgdjb(ogAhx*zIa|ldTNfcaY9;GVLm0MT$SwvGpZxM%lq@U| zvn1Kf>$iPr0p!A8WXK#`1+*iyi3eB)QX43Bx0aNF}ccia=le=@G<7b>Sz*UG*niOX=JwmaU!(+v!h77`p1k z;}<;l;{|BArb4uNC^^H&mUOdwq;;&+HzV)UX5pMU1!8<~KV?Y1`K|ZS)kCNxk|B~~ zPeg_CqZVi`N8A3K%a$%S0T$;5rHcEFx?P`m!)mx1+~A69$SK#xL_$_`&T-r5LzIOjv$jLHbPblI4aF5v(AivL~B|&|+v~WnqzmXt&WZHJg@POwfjLA|`y8L2_ zfHA1fP$ER@5Us=Fw-J~7#3JrzrVxf(B1K*KT z%B;#fy9LMw&6}T(d+%OEs^<;!bPK5=61-A1JENp#C&F-_AIT5nvIlBWSd&fQ8R((5 za+|sBlTFN%5kM})$`8_N7k7L1^!AFIetc;e?z{hNWb=q%?jYABL7e<|7&xVU7=eVL z)LL{f@ckktF8x+5=B+3eS)x8_qnZX~7qRYrli@QdfXvFeuCIl3BE{?$%%kU>SB5Wr zWf2PVvJ`MG=|idnq>C^nBMis6okkxyo@FgLl#Z`a$H`EyM&3w2sFty!x9KZ29?7xF@`E600^r_!?w?ny+P$JU?L0aWi1s z22kv`ylFT?!}8n8u>9s)%J7h{NNn44I;Vc}ffzXXSX=V|p8nAx9Ns%fdA*RZkDBRI zUrV|oeo%BD=x&?lJg}9VYQUSLv|obd>coObm9d*ru`G(qzP1SYbEV1-4-ZNA>~v2) z<}R(RtsCsmKiSb{AbH9a4!7R?T`Q&IThP;HI3!~O;AE@=Y?%`^03HIcAJ#8zZpT@I zX(t7wX~?Uj(Cp57)L%q>CSg+yDdFg9Y-~)_$*u}}8gl$hkN$hnV0vs4&`84w1elMrSiJV!?@bpV~ax)fC(D?}(PlM0+!;)x^d4k7M^ zB+|HjIx6cgvjU)9f+nGr^RLKn@T`Q6@zDu<_7h1=R-W)A{I*oO~if5fV0af1JGS~J_eG=H3a5u?)}NB z;3=Cz>nvJ$AI}t*OvuV&@~{(46Vtz&WK(%Mcpelgr-HZKr;0vq22S-fp3-t!0JMwi zKO)P zbT`l0=llE--|M-aABc;w^FDE(`+mi}=%*U0v{dX=L_|ciYLAq(iHI(}CVWv`27jTS z$bAof5PK-9=}=Hm;AS+ZiHLZK)RYu-d^6W3{429`1LZdNCZ__Y?k&wju7pW-D|!;W zv1p8a_JLAS{MV(hpSc>(!sv8!Yb_#gvIvi`aAp2rvKMBi>iz(`tW1?BM8n$i8D{a4 zC>Nrb0X@}gy-5rh^TnOAZ!k?9I{M?phRZ0m1FMXBbd?6muTA#<|Mb6OCnmE5)sh4m6iF0b7dm7V`UXQt+BW(V zDbcXOo%-_)hYS@hCS?XW8aE2Qd5&GW+N>bWX#1jSDAsG@AP|9lf|Wop`aES)PMD+M zn}z?Vrg5X@n?Fmoxq5DnhHYlUXe1FeE;9YqLNT7E^)Ag(6>8ULpm{zw5Lnqk1U7Dt z?O~brr!d$R#d%c1z)!CU2}H{s#52<|Ndy{)d&YSawT9WMGt$yKuvD#5b zCGufWi#CQ47yKVXd86`*%_?rFg%+zPDPe1QDWqKg9>$uVTH!~_vNXWddSY350yaCz zIbS@e8D~;ti_j_=nT7Am4tkj)uz5naX&!2@ITXRW`2Bnq7Z)MYNKR`6l}A&~*{a>t z>Ec};zvbL9^WghxNfHP&Y@m7oMq@g*#f?E`e77yrsy^5l-Yx>CMaXRT zQSw!)hm&s04sNvU{CF(dC`fVn$#G@fUb$S23r>s4k~YZE(Q!CWSwz3QWj01+ALk}N zb?{d3(}?3C5sJ3EgZ~fZz)IzQ7(W@GQj%bbP3zI(`&1M6zToqv;91KY8$-4yt+?Q> zI+wwnZP|)3ycScq|=>M}+y5nkULf91RlfqFF!+@#aT7L&N54+Q-Mo zNvT=pQRm%^nwiMnt8E)gsDw-^bfsQNpWlJ`v+SjWxo%{fG^Obn8ulcq8%EP#E!w*K zvtO)THijR8HCP`?3{kFSL}fc=LQe1b z0ZTGdjnkpj(pd>hs69Wf#EU1`-N5#7=WnKA?blZ~s-Pt%q8MacC)0Eac%@-3q4{9a zzv|$%CVdDP%0n$_xhWy{J62OZu#57>hp&txTWU!buO;u^O+4NUD0jAtWuvmZ#;x#7IC)#vtsWPzB9JiWv)5+>TWLx#DuX9znX_Y%WqSBM zzXkWJJKxEHi|k3ym6*RBIWLocYKum->nQE^0B0Eslwb$^pS1csj;yUtm5n#U!j^Cz=Q=pXTAPzJOHd$VY(#QpPjs zfT{L{6yvAWPlc0d&@VWPCR{hxgIP;X3<6b!`=o!eng?u++vO-5tu#%pc&b$5c!*=| zZ%DcPskKB$fQM9!HBX32(a=p#^(a-y*9@hSJzlM!3Ob2meRCUZ;cOL#yML#}sBGWw zKCZ50M0m8t=Ps^J67lwq0_V-^GM!UiW2U~BdBcizgar(g`a1HoB5B2aIRX{JA@uim zpMKKW4xB<}3dMx-3MH!(+h;;B;=Ovs`--s~d?a1e$p;aZVU|KCqzO!9Eb-D;skYZ- z2k*N6T|SYU?EUzJA_OWzC9H4mw{q>C$UH@?eXWH@T!1k}u0zHWs-k6^s&4wjOQN}~ z%lPbh4|GwsAJwZ;hEfLz01_x7;qx?`@!eesDfxb*8z^7L8P+3g&bbanh-qZzl`HWq zS4r4ZqK`VNq13vI23m?1%w{UDmySv*+G3o!I*&eBSPVzKRiMOtLJ|`(^Qrr=Og*N8QYYd2dlLI z$QQR+Cky2cmIX;wI9WZ#1}>}XJuITc7EzSxPSw<6ZDC``l5^!}aYt*UwaoCW_GJC` zsmu{K%6hkAJIdU(z8Y<=R^0n{ref$O=>`VZAb7N)qE(9yP(4SEO%}+!Gv9ANlWE_P z!SDpP*cdkWP92a}rh$`aG^vA9Ctja}_pZPb=1jolZ7T2oN7cQ&-j;27$K4!uX@AQx z!A2%G_d2MCM z)>Lj>GSZ8|u!@>AyqM{-tuYi$6-oYfcz8HJFX$@e=`-vFE_x{>clvAHno!K9FI}u^ zgFjN7`0(5U>M`LpcFVM>)~IY&n;e$sAi@6Z*)vqOriO-wrskNVJ`pLCMY*POlIMz&e()}k{@bcFfdr-+%Kzex<3U(Qcd;g3s9Jn*}ZhM9~Zl1K_v zD8!}?5ZG0oiLchy-Xfl9jhkK6?OX9~&kglH=@^xbt_Mk_3aS-ozd?)eg_YyK+wMfl zpUxy*d%RhOKJX?<9AKa+)w-_P_OSZvyka+7M3qf{%Ee*gMFT(t=0Qg`xH=o6T;dyg z`CF=2wb=>_9E^mMk9nHr52uJvR~0 zJa2Z0reBJKzA$KkbnUdz2TT)#9cwjno9POV+L*u)0LCobtkOauNw95$BcjT6qA6KK zKQEWJ?(TIptBgeoTNYv`r9Mk)b;wDPb^W9tUjAZ7{$iH3{Xx1_#h6HHe}nO{42gwB zc=`lg=SK&2DVo?LUB1(HHcL_k07(lS>Rj@zI37~c3_0WERx8n>P0M+@C3*{}1Q#K- zBwo$oKLHjCq`&3ickk8*9Jwp?t#gm}AWbR&JbBlT3f|KX_F5@OHA)GeVOFVTo%nI;dY}q+2pl zDRI5R(T83%PpHeCyEmIq-WF2L+l()iVF*UUjV9NMF`30QYuDzrI`x9kPsN1}3J`e0 ztJE+C&gWo)?=rV#52s(iX1<7;>E zq%tS7drvhPa`}C{_(<0^zMD_5tDe$@4&WN0>10-CW5wi-m-ET@&lIj7wi8Aw80a8dMsClx73;vF&!C@?H zu=zK!zG@nJDlgM|s0c;qLVs!w0I>utkHKITuz)sb{f=HqDwT)PKcCS1X# z0dv^e+A{Sz`)qBorj;b

%!fR;a7HlCOKPLO|S*yydT@f}Kr`fog^d-)|v#uc7@g0kaxgz;(V) zOM2D}ia&IfNqBYp*tVuI=$Dqa`*ip?=>1?~8mfU|gDeLRv6IV-}BmZ1K~l|5p9!+SIuV zlX9yW{axAYgIsmSxzc);e0tmlaoweU>xLI(tW;A~iFU58KfFxGywI@H5yw*yX@` zH>Z8J&+tB8DGEMlp6VgHk3n|9R=u0c@p&EOi6dcDk;n+ks0^s={Rb`l5l^sxo4oLD zXQOUka4wBDe_(O+fy)o?PIxksUH@W)&@)<3!gmU4h=%l&O6rvKApbgkk#d_n1-Y&5 za5mPs-gTk{b%)zVr(^_34PqcfF3t{eGBZt@Ja5KG%}4BvZS zapxc3zuOqRtJZrzBn)9vw z+frhZ6it46Io00P2+I%K)bh7?2YEX?wBNKi^qj8Ci?>rQW`Gpgr?} zs`OuDhU{_z_cJ|ypmx6Bt$G1C*v1J+!Q-eZR#}S_n=iOE5S?qddTY^^=Y2{3>y1k< ziRoUCJgGM6fYFTJ{S+Qjz&*Z97kt`DAM|1pwbTj-bF#W}-B3^KKh$J#yg+4BSliud zQ%AOlgTEewZ&bOXBR?LB_T4~!grxWik$ENgb_j+UG<&bzEXoApOuhXuKh!$8e*vBV zDCFjg)@3}G#HyMi(t#5Ll1`c4V{9!*gdS(ddvz|U>Oh|X=U!M?sImjqEo#hJE6ypHxmJ)LocX`7s6=!ZszYqJ*_1+G4@2^}Kq;wV?_sEpT;Qgg6 zAG0LE@3tO(eof=fR=;(3lj$UBzBqni_v`wLTFNTXEBhxONPcn{1}Xl$aNq$)4hKHU zC1zR|!XRY_OGX^EnC=5WVV8-Fn1k>61$ujXTUlK$yByOtX&K4#G7Y}bdN5g{UlH{0 zQxV97>FErLN?KvJBH@2xD`p?Y3Y79)i;WnULK zQ96cS10$??b4(ZkogwhTf9hm1hFN52?2^aBfrfDbOMCIk2>p7TvNAIjmz}LG&`p*R z@1=5utIaB`)5(l+Yz7-NMZ+H*Knm}Ib@ROf*@l31LrJMC5vttymoD?l=C{{K%vBF$|8<~>5{m605OD5~b;`jGr4bzvg z5<9XRp3(-NF-DfdV~=Gp9qif-u^@G??Ef1nF$WaIul0QKy<0+jJOBnOD-LKF*tan} zT;lcQCGOlj8`A5;Y^{?%Q-P_b-szA$y%JP*BwyO!Qzdjnh~&rl5F^8sGV}Ix5Zx=@ z&1y+cG&I_Pt^udRz~cN`*HPKdLmF=6%#H@D=#_8F=8m|11W0cuYxVi0#g=Ra;?QG1 zhoy!H$(G99W*1!DD>`Wkm!zRzWo8v~>8$&+yMC>p2<7fEw`K{&d|S9J{bmuhe$rOx z0NC?}59dW;`g2gg$I&?^pR28lN?DYUKVjl)qoV8!f>Q2i~LX2a{U`s(+Gs_z;?Y7FKI5l z+70(sv%$JGm3#&gh3us}ckZYq1*|+a?^^We)Eap`Ls8-jDzje6jG<*l;rqL8a;KZ< zaL96IH0>*c2PfP566L-AY8cI1!73Nya!0KY!hdqp<++(;F9ARdr%6^`>v8AANPJH<^Xsc~sSQfC zQ)LZw5QqoSlKbuwzD?f@Re*2GC`6(yW`;QCdO6&>8@aWZkV$ehU@Y!Y)mb=@`C7R! z(Rq*7TMF_lRDb0u$7Toa8**|*xLz%V-ee){yoV;0)3WoaMQhNR z-+)ZOlqU9FBrgpywElhJ(VAOuvyN~T&nRq~qQs)OmQbiKmV(d8aY|43&>oPO@C|vX z$6TI63iNV^yqY)I$-qOesZ|4J19&_DuAbBYnidrh_KKF?u}a|EPK&;IpqIOQ^>Qq~ z24!p^{y0BT?vK61&?Uocg!!&lytFe+iR1NDdoDwNnBz9MCIrk*~^~NzT#tE_tmbf_uu3!3|of( z!SAiNow(L&h#ohoaIrE_?*r8J`OG zASXkPzN!uIFo$QX0NyC7mUM2tG2cYV{CLc3;QNm3U7EQq4A0WL$`_}XXec5y&Ne!I z|EbC!zu`pnbdkC+wPR$uE(aVRiHiIfSjX4 z*j7X5=$&30tjO`6EoJxLhyclCx<9Wzl84bu9(Fe~J$-y;hBEOLH!Pu&jHG?b*Eprd zZK|#HcS)Yl%bT*_7B(@rjO(T=wo%)^mifgz-@z)$RL_m($iD6bxVn}PiR9If$g}j` zPAPN%NOha|_+dQ;U~WA|mjrR@ky-|R@sZ8~{%b~doe58js~ z^Aw{5)ebr22j-tY)i|z(#?GZRGf;JdBRBNF=ENS#YhghPYR*$9{;&=X--0(GBl72Y zA(j@jQ2~Z2{$%4@j%j;tdYD1#w+i<}7k4^=uuG=2Uf0RdR4$W%9$U)2hSB@IdUI^z zM4k+95;`OKfH1LF&=$S-g?;9`me)BtzS&@){m_0tCw*w!CJha-(~IYK;VqUpDUL4M zTZVUU)aP4=T?=-EIth`urFFh>;&E^4M3YCRtl}aUyD#Q9pZq$tToxgQjrEoIzcPJ{{yyNuWDCQ+djt^Q>AT>TOxq9zV@o}l5 zSjzdvj75^5Z~Cx=%gWD!+n>7wQm#gH-kj;!>}7)(TK;ZlbZI}^$4^ziN_-=uSZq-3 zFX{cP2ifAgHJc~q_)8q@^61_!`6xjekG;}!$^s!9ef=5}O2Ox8nmBg|WNWu!*8d_N z%cC3hk(gd~s2U3Gm^(}JWAX_6MNVwixSPGy=z=?0Z+82iyFtuPj&Q%6wsh1LPJIBp zS$Kkth*{$=-T5!tQ%QNN-zo>?PB!_}W_+z_qGW#%DH~M(K70L;?u~$0qm}l2xHixD zkSPW7w`C;KPH_fYHEXtrzZy}g>w;3f;pC8$J_ z?6gw{M;|I*q_yNWhz59X z303EE2h?GJPst2{gMew*}IhBlk^fH+MO9>sXGZjt_gRFU?{)?r8h=LQyyuI zH-^M?G3agml*r1;LSQ`sH!`b!PU#;;|4ITuFS82ElokhmaiIfS1SlZ?Hx8g`S3I2_ z=%-`2{Z|QA4CzxsUHrDNZR#`e1;B4W)sz`DzTZ5~ixMc!OD`OE{4xvt5h&sRw-@@4 z4qIM`=#|0&;^V>qG*;&_N8UZ#(1i@sg~e5FPC@%;;X$Wc7_g4-hL%;p_YDF1ranQT z37k^Rjpn3#rbWPAM#t%e>4i75>4Of@JaPcvh68)ZKRb1)aSmP_Xcx2Q{yX4Rs!OdM zuuj1=O{=Vw3$#1QzgEKwb-`UCt$|Xfhra?n9YYdpNsmQA=&X7B1Hb_ye_+5q1GF_n zqML!h{ysCaJBYYe!_)Kt-~oUQ?3cj1A8O2?8f^^gTyChj4~Sy|R;_tNlGQ;W%U%NV z!_>jBVaqap0xQ8D|LM~wcmf*MeZB+O?E$#mHwi;DMCi(L?p!P409uTW@b@1-xIya& zXdxNgQ7`zp;t5cO>u0M9Z~C`_Y8i#!ZJ%K!rVdQUCK{0W_@>N2`WtOltfj&Aszq1^ zMV%5|(=h;(35J^`wQD^tdE&DDm^%=}Ob2&l2dP7+f5>cfThuM%^Rlb~W2ljpFuF}c zEaNPR0JaU!`DUbksll+b6fOF93#z6ZZ$MUPN@4s0=6TjSb<#@kLIAeSUIKT$)&pEs zu|bci1Dg}jZ-bTSL79X4Nbn(DaD@&)=Bm5YW46XkCUyl*=f1P}-9T;i0y*?_#x1zB z@@4pr`)0OKj5AKfx+m~wCJ5mdR1>z`-R^d83Eeb707 zIc0U|TbK(%F!u zaHgpo-*g_W8890qkN~40ZVik9f`@VD6}nIV(}wU%oIL^wJj?qRr#o2M3Y?6I=n^Ws@FsW5IJD1h|gsq#%JX^DrKLhEum`0|JFKSFOhR@f=Em+jCMHu``09Y zxI>jCu&I^Og(j? z6;J`2K-D6!RiiR1qcxOS&G`J|Ll^*1H|O7#Q(Vq80SyJf$ec^at4Q@uXkUIv6vrRFlCMXKfpRWGAzVPwj3B6daR^Vrpj0mc+$M@>DZ6{kN+`CQ@ z3N%?vlB{jOfyQp$3Z#%+RJs9un?Dj=NGI=ksoI5IR#@mLKQ%|MrH1vb$28#k&V z!edl%byfX>h-bA!>|gxFV)Bg2SV$DuBEA^Wk~%3;415@NU3D@)G5TV(;PHSNC~j=E zL1L-><|lu~H16-|4DNWEs@ixnDXS%Y`0}vPM5R+}cud9~=ybR>Dn8+4s%)C$Ha9~( z2+4x`QE`4k(_DfK$d2C0tbtX#<%Ho%JNt(_fh@xlbZ9ws05H#gUSXDoot0G{ZY>Y) zM8d;s^)kBJOZF0zqCtw+Z1fG_EtXZA@;j=cetj@fS+6(rg1<4KV2H4UkoW-KH{C9K z++G3*OK);U9KBp!=^U>49K|uMHpk@&#pKBjvO*0Y5i_K$CNF@#?kUZMh5?I9imUwW zW@JbK8|P-U#y264b|7p5!P$!QDo`NU=|7-WK)e!`1{O-%oJpstsaav#yzh~7l39*t zOP?JVxgM=-CerGkc}19v0|`c4{)Aomn@pfS1ES8?snhi769~iJmB&cO7YYe%N%h*;zJD}|JOX6%GP+KS7m+HR_J-wzji{fr`*oJayQxHEE zU%vHf59p^>Y$|LK<#?l%FZRQECmZb-gXgP*umy)NMgoVtG&VWF!S|gBr9Vt@1VX4Ear5t~8TyfzyqN@)ye5}MATm#Fb`v$nhR#w1K zAv@FE+)|8^Kxl2Q!Rhv4bj*g|as(+g@EvB?uoB|-UEclLpWYQZFez`K2K_~wSF1r? z&>vuJsQ<4|ad%9inMl>ZpRP84ye;qq7>e1b#dP4R3p9j)_L@H;8^F>8bp~{VZKPJ{ zf~%e)AtPhFtY68v+?a6F?30dSO%{yialsY89t$GSPPu&myo`3x8V0J5$&+|V#QXGg zOQSV$c-NnY7Q5myGBV=gd{ajw6+wH2?_B|}%O`ZHx#H@8B8Ndjn~6ZG5G}NCx#@I0 zg50lMpk~v8sYDCOdD516Wk^uXWDIEUfUEC;D8AL-b;#h~B`)!n)>O@bU_mI7BeFh^ z2-A@R^Tor%gVoe?7@!0joHyvUDrP>>dHO0w=Bob{(=o0(vd)Y`zM}4c-Ke9s-rpR{ zC^NPQyDYC!{q|$s+J*<@&-s*q+pYGaCy26^TD)?fbNeXO#CF|N8W=508w{$PRmeG& z0DyUy&jfk)tuccTQAN>hcU zp#MDlY8ei>jD}z(fP@STK*~~i(5D7muIQ~T~6 z$7CXDg(%SODGwTK=;cpeG@A7OhEOh`xXJX8oS^+-*r%NQ6To2iNxTR9es>vKg8n!$ z+H;xzB8dL82;deySqEk+m5?f+g>c^MjE9o zG>J-wTZTn-GPS(`4Q<4+v~&k-V271bY=CXTK%Vu;=GY?DE%?3k;0{3qbPL2AUjPG; znM47go+Or-7J~1oxIU#pK-HYcZU!K(nJlu)$d(E~xqYr0h>*VrK`tgQoo1 zE^tK&Qh9p%Rm0j5dx=oqO5UGS!-gWc4?DU~_R;8xS#s4+qR+1(lltZ3cHN!`;^wS#uSzrwrmk_OzyBffd1zlT>`S>+?p(fbN2~8`7~(kfwQ^H zc+8?Ji9nB_Lk1yp+*``@0A_FhGwZj4ol%J@R|)MO1@^z*d}~r~Y+w3Rlzp5Ue3Tl= z6VxzBQjEIoUzev9&!vp+%}tqI_Xoow#ev92>bEZ{sE^4C1Rm`>z?5z1A z?X>VM8Bi(Bi==y2OgRc1k;~ zsr_HM;&SJwH4=tj=o*YDR_1x|9gN38$wnWci`6GDgsi$=J{lFZd@mvWq7O;SO=p#G zokQNDPnPE4yIh$B&@Wo)Ejl(Q-h&s5OX|T_PwEcbecds`z}66Lp55!N4$ojS5Kv#Y zV%XtgnCE}<{9 literal 0 HcmV?d00001 diff --git a/ui/imports/assets/png/onRampProviders/ramp.png b/ui/imports/assets/png/onRampProviders/ramp.png new file mode 100644 index 0000000000000000000000000000000000000000..3840202aa2a4abe764e22eaf14cbe40e66e00400 GIT binary patch literal 1845 zcma)-`8(T*7RJ9i+KXUXIya))iz%w3Um7hP%k6NJC^E)Y$|R{JiRq&{V&A5g8`@Mn zf=Fb>h%1(MDo81k)KUbIpsKCb)*4Hs8mZc9X>&9G!Tj(!=e+Ov^*ryP`1*M0=@{z( z0HEi23E>X_8b*Ji^@ZAL@`ZJ(n`V^T_ig~dD}?NaA5?3Ncz+Lfpkc&Bt`??|m;Ap6 zfHX@0$RY#4uG-3427p960C*b)08V890F5md__?ST_kGcUNR>*pwzo}t&A&3rux%c56y!`b&2O)cEzFTy8!k}NjFX8vH!vQ>x%95~ImJrCMBV$X%|vds>j2q0EB5*N zA}pCWw(w?cZ;M#XvhB?nP)_$uy?CQosh3GSipd;t&wZIBw~bpd-;+2|cY%^Vzpcn^ z`-NqU0Ih93nq@;UE3KF@TcrWA} z036)+M7RZ}lq+VUlP6J!Z>{N>c9ZBvUX^|NJ`r^rjMV}x@7x0E-(g*f z6Tt~16(5AflohA%3+JqTA9eh$pdIM3z=U z+=x#^S?Db97IapA8q1VGt{K;ZKCM=Bs8V`OZQ(M_|N&y%N<+mq8R^0o&>r6_tL7 zP>p5ek86+BcLa@=OFNn*it*Gx6Ib-g&y*x-&m$&lwtip``V)9I_6_-177trLL{&xv zpeAefK5;ia4&ke@8SC}p>NuWd$%u%7_JVrDuVLQ}RwwbyOJ+rRXniOIo{HI!*ueQe zF?Y&_k+`K{RUfh$je~Z;`Pi1Bh2$}7&SNA;cWRMCmauex$*rL2PSrdFOKw)Yq=#fO zFE712tGRYO7c&W$eidx7vi6Sy;4pU%8+G>@b-xx^;qX4JHAotnk$}y z7W_w{uAh45-C-)9(!*_^rY~DOMn*V0JWPGJd8BY=!qWd|hr7^BZU_A(weW*^@+)+OD{8@LeSCtHeq=e| z`B~JT2+Pk#Uz3ajGJ_4WLE|XET7y=vhruX?j; zSOdON2K%oR@8~;LWn>7DR_+?Z3(Woc;Sgt>N{yq%g~>#N^QI23Qc8=SXmh-!2Yvj zQvzz^sRAk(`GSCl^@1Zau@e!y6`jiIt7yi|6j@&u!-5AW@k=oeg!yD0EQyfO#cXz1 z?P0*=Oq&nFSVI4f!cY%%VUcd0@wf%?CN3WL%4`do@1eai>9C(*D}*#c8m8R&2|kd2 zA(^T=-=_hslFB~rUGFb2wSVJY>?d=l!4k{{PbE+o+OZUdpWMLOaKXTu^UT7_@`;5P zit9~AH+hq(5zH`_7BdX?9L$FMsTsoN;LX)M6KW13)ELFW=w|J@LuIirni*er(1;{2 zH4|(Mm67B{X2Oj@qqwypJIo_^Eye|I11+SUW%|Hsz3ZgVXmCWKVkF6FJMJ0f9xp=S z2f!$}B{mdp4xWK=z=lrK6yCo+uT<(^Wxs6_8XB`W^L2kksa2y{OM9*axyU) h`uDR~o!N>{kg3@RVW)p?8CAb8z!T|%XmAh9`9Fn1dSw6r literal 0 HcmV?d00001 diff --git a/ui/imports/utils/Global.qml b/ui/imports/utils/Global.qml index 6d7477396c..81d456c76d 100644 --- a/ui/imports/utils/Global.qml +++ b/ui/imports/utils/Global.qml @@ -107,6 +107,9 @@ QtObject { // Swap signal openSwapModalRequested(var formDataParams) + // BuyCrypto + signal openBuyCryptoModalRequested() + ///////////////////////////////////////////////////// // WalletConnect POC - to remove signal popupWalletConnect()