diff --git a/src/quo/components/list_items/network_list/view.cljs b/src/quo/components/list_items/network_list/view.cljs index 16628e16f04..8a879f0e63e 100644 --- a/src/quo/components/list_items/network_list/view.cljs +++ b/src/quo/components/list_items/network_list/view.cljs @@ -1,6 +1,7 @@ (ns quo.components.list-items.network-list.view (:require [clojure.string :as string] + [quo.components.icon :as icon] [quo.components.list-items.network-list.style :as style] [quo.components.markdown.text :as text] [quo.theme :as quo.theme] @@ -42,8 +43,8 @@ [:map {:closed true} [:network-image :int] [:label :string] - [:fiat-value :string] - [:token-value :string] + [:fiat-value {:optional true} [:maybe :string]] + [:token-value {:optional true} [:maybe :string]] [:container-style {:optional true} [:maybe :map]] [:customization-color {:optional true} [:maybe :schema.common/customization-color]] [:state {:optional true} [:enum :pressed :active :disabled :default]] @@ -51,7 +52,7 @@ :any]) (defn- view-internal - [{:keys [on-press container-style state customization-color] + [{:keys [fiat-value token-value on-press container-style state customization-color] :as props :or {customization-color :blue}}] (let [theme (quo.theme/use-theme) @@ -67,6 +68,8 @@ :on-press (when-not (= state :disabled) on-press) :accessibility-label :network-list} [info props] - [values props]])) + (if (or token-value fiat-value) + [values props] + [icon/icon :i/chevron-right])])) (def view (schema/instrument #'view-internal ?schema)) diff --git a/src/status_im/contexts/wallet/buy_crypto/events.cljs b/src/status_im/contexts/wallet/buy_crypto/events.cljs new file mode 100644 index 00000000000..f9584a4f72b --- /dev/null +++ b/src/status_im/contexts/wallet/buy_crypto/events.cljs @@ -0,0 +1,72 @@ +(ns status-im.contexts.wallet.buy-crypto.events + (:require [re-frame.core :as rf] + [react-native.core :as rn] + [status-im.contexts.wallet.sheets.buy-network-selection.view :as buy-network-selection] + [status-im.contexts.wallet.sheets.select-asset.view :as select-asset] + [utils.i18n :as i18n])) + +(rf/reg-event-fx :wallet.buy-crypto/select-provider + (fn [{:keys [db]} [{:keys [account provider recurrent?]}]] + (let [swap-network (get-in db [:wallet :ui :swap :network])] + {:db (-> db + (assoc-in [:wallet :ui :buy-crypto :account] account) + (assoc-in [:wallet :ui :buy-crypto :provider] provider) + (assoc-in [:wallet :ui :buy-crypto :recurrent?] recurrent?)) + :fx [(if swap-network + [:dispatch [:wallet.buy-crypto/select-network swap-network]] + [:dispatch + [:show-bottom-sheet + {:content + (fn [] + [buy-network-selection/view + {:provider provider + :account account}])}]])]}))) + +(rf/reg-event-fx :wallet.buy-crypto/select-network + (fn [{:keys [db]} [network]] + (let [provider (get-in db [:wallet :ui :buy-crypto :provider]) + network-chain-id (:chain-id network) + supported-tokens (:supported-tokens provider) + supported-tokens-on-network (set (map :symbol + (filter (fn [token] + (= (:chain-id token) network-chain-id)) + supported-tokens)))] + {:db (assoc-in db [:wallet :ui :buy-crypto :network] network) + :fx [[:dispatch + [:show-bottom-sheet + {:content + (fn [] + [select-asset/view + {:title (i18n/label :t/select-asset-to-buy) + :network network + :provider provider + :on-select (fn [token] + (rf/dispatch [:wallet/get-crypto-on-ramp-url {:token token}])) + :hide-token-fn (fn [_ token] + (not (contains? supported-tokens-on-network + (:symbol token))))}])}]]]}))) + +(rf/reg-event-fx + :wallet/get-crypto-on-ramp-url + (fn [{:keys [db]} [{:keys [token]}]] + (let [account (get-in db [:wallet :ui :buy-crypto :account]) + provider (get-in db [:wallet :ui :buy-crypto :provider]) + network (get-in db [:wallet :ui :buy-crypto :network]) + recurrent? (get-in db [:wallet :ui :buy-crypto :recurrent?]) + provider-id (:id provider) + parameters {:symbol (:symbol token) + :destAddress (:address account) + :chainID (:chain-id network) + :isRecurrent recurrent?}] + {:fx [[:json-rpc/call + [{:method "wallet_getCryptoOnRampURL" + :params [provider-id parameters] + :on-success (fn [url] + (rf/dispatch [:navigate-back]) + (rf/dispatch [:wallet.buy-crypto/clean-all]) + (rn/open-url url)) + :on-error [:wallet/log-rpc-error {:event :wallet/get-crypto-on-ramps}]}]]]}))) + +(rf/reg-event-fx :wallet.buy-crypto/clean-all + (fn [{:keys [db]}] + {:db (update-in db [:wallet :ui] dissoc :buy-crypto)})) diff --git a/src/status_im/contexts/wallet/common/asset_list/view.cljs b/src/status_im/contexts/wallet/common/asset_list/view.cljs index 1ecab1b8811..69a779a0be0 100644 --- a/src/status_im/contexts/wallet/common/asset_list/view.cljs +++ b/src/status_im/contexts/wallet/common/asset_list/view.cljs @@ -32,9 +32,11 @@ :selected)}])) (defn view - [{:keys [content-container-style search-text on-token-press preselected-token-symbol] + [{:keys [content-container-style search-text on-token-press preselected-token-symbol chain-ids] :or {content-container-style {:padding-horizontal 8}}}] - (let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered {:query search-text}]) + (let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered + {:query search-text + :chain-ids chain-ids}]) currency (rf/sub [:profile/currency]) currency-symbol (rf/sub [:profile/currency-symbol])] [gesture/flat-list diff --git a/src/status_im/contexts/wallet/common/utils.cljs b/src/status_im/contexts/wallet/common/utils.cljs index 9d5764858ef..411ed6a14ab 100644 --- a/src/status_im/contexts/wallet/common/utils.cljs +++ b/src/status_im/contexts/wallet/common/utils.cljs @@ -155,6 +155,10 @@ [accounts address] (some #(when (= (:address %) address) %) accounts)) +(defn get-default-account + [accounts] + (some #(when (:default-account? %) %) accounts)) + (defn calculate-token-fiat-value "Returns the token fiat value for provided raw balance" [{:keys [currency balance token]}] diff --git a/src/status_im/contexts/wallet/sheets/buy_network_selection/style.cljs b/src/status_im/contexts/wallet/sheets/buy_network_selection/style.cljs new file mode 100644 index 00000000000..df40dc502d0 --- /dev/null +++ b/src/status_im/contexts/wallet/sheets/buy_network_selection/style.cljs @@ -0,0 +1,28 @@ +(ns status-im.contexts.wallet.sheets.buy-network-selection.style) + +(defn network-list-container + [mainnet?] + {:margin-horizontal 8 + :padding-vertical (when mainnet? 8)}) + +(def header-container + {:height 62 + :padding-horizontal 20}) + +(def context-tag + {:margin-top 0}) + +(def divider-label + {:padding-top 0 + :padding-bottom 0}) + +(def subheader-container + {:flex-direction :row + :align-items :center + :margin-top 4}) + +(def on + {:margin-right 4}) + +(def to + {:margin-horizontal 4}) diff --git a/src/status_im/contexts/wallet/sheets/buy_network_selection/view.cljs b/src/status_im/contexts/wallet/sheets/buy_network_selection/view.cljs new file mode 100644 index 00000000000..427f709a77c --- /dev/null +++ b/src/status_im/contexts/wallet/sheets/buy_network_selection/view.cljs @@ -0,0 +1,78 @@ +(ns status-im.contexts.wallet.sheets.buy-network-selection.view + (:require [quo.core :as quo] + [quo.foundations.resources :as quo.resources] + [react-native.core :as rn] + [status-im.constants :as constants] + [status-im.contexts.wallet.sheets.buy-network-selection.style :as style] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(defn- network-item + [{:keys [network on-select-network]}] + (let [{:keys [network-name]} network + mainnet? (= network-name constants/mainnet-network-name)] + [quo/network-list + {:label (name network-name) + :network-image (quo.resources/get-network network-name) + :on-press #(on-select-network network) + :container-style (style/network-list-container mainnet?)}])) + +(defn- subheader + [{:keys [provider account]}] + [rn/view {:style style/subheader-container} + [quo/text + {:size :paragraph-2 + :weight :medium + :style style/on} + (i18n/label :t/on-uppercase)] + [quo/context-tag + {:type :network + :network-logo (:logo-url provider) + :network-name (:name provider) + :size 24 + :container-style style/context-tag}] + [quo/text + {:size :paragraph-2 + :weight :medium + :style style/to} + (i18n/label :t/to)] + [quo/context-tag + {:type :account + :account-name (:name account) + :emoji (:emoji account) + :size 24 + :container-style style/context-tag}]]) + +(defn view + [] + (let [provider (rf/sub [:wallet/wallet-buy-crypto-provider]) + account (rf/sub [:wallet/wallet-buy-crypto-account]) + network-details (rf/sub [:wallet/network-details]) + mainnet-network (first network-details) + layer-2-networks (rest network-details) + render-fn (rn/use-callback (fn [network] + [network-item + {:network network + :on-select-network + (fn [network] + (rf/dispatch [:wallet.buy-crypto/select-network + network]))}]))] + [:<> + [rn/view {:style style/header-container} + [quo/text + {:size :heading-2 + :weight :semi-bold} + (i18n/label :t/select-network-for-buying)] + [subheader + {:provider provider + :account account}]] + (when mainnet-network + [network-item + {:network mainnet-network + :on-select-network #(rf/dispatch [:wallet.buy-crypto/select-network mainnet-network])}]) + [quo/divider-label {:container-style style/divider-label} + (i18n/label :t/layer-2)] + [rn/flat-list + {:data (vec layer-2-networks) + :render-fn render-fn + :scroll-enabled false}]])) diff --git a/src/status_im/contexts/wallet/sheets/buy_token/view.cljs b/src/status_im/contexts/wallet/sheets/buy_token/view.cljs index af17d797d8d..960fe154b91 100644 --- a/src/status_im/contexts/wallet/sheets/buy_token/view.cljs +++ b/src/status_im/contexts/wallet/sheets/buy_token/view.cljs @@ -7,11 +7,20 @@ [utils.re-frame :as rf])) (defn- crypto-on-ramp-item - [{:keys [name description fees logo-url site-url recurrent-site-url]} _ _ {:keys [tab]}] - (let [open-url (rn/use-callback (fn [] - (rf/dispatch [:open-url - (if (= tab :recurrent) recurrent-site-url site-url)])) - [site-url recurrent-site-url tab])] + [{:keys [name description fees logo-url site-url recurrent-site-url urls-need-parameters] + :as provider} + _ + _ + {:keys [account tab]}] + (let [open-url (rn/use-callback + (fn [] + (if urls-need-parameters + (rf/dispatch [:wallet.buy-crypto/select-provider + {:account account + :provider provider + :recurrent? (= tab :recurrent)}]) + (rn/open-url (if (= tab :recurrent) recurrent-site-url site-url)))) + [site-url recurrent-site-url tab])] [quo/settings-item {:title name :description :text @@ -39,6 +48,7 @@ (rn/use-mount (fn [] (rf/dispatch [:wallet/get-crypto-on-ramps]))) (let [crypto-on-ramps (rf/sub [:wallet/crypto-on-ramps]) + account (rf/sub [:wallet/current-viewing-account-or-default]) [selected-tab set-selected-tab] (rn/use-state initial-tab) [min-height set-min-height] (rn/use-state 0) on-layout (rn/use-callback @@ -58,5 +68,6 @@ (:one-time crypto-on-ramps)) :on-layout on-layout :style (style/list-container min-height) - :render-data {:tab selected-tab} + :render-data {:tab selected-tab + :account account} :render-fn crypto-on-ramp-item}]])) diff --git a/src/status_im/contexts/wallet/sheets/select_asset/view.cljs b/src/status_im/contexts/wallet/sheets/select_asset/view.cljs index ad23fb2939e..863e9523871 100644 --- a/src/status_im/contexts/wallet/sheets/select_asset/view.cljs +++ b/src/status_im/contexts/wallet/sheets/select_asset/view.cljs @@ -51,14 +51,31 @@ :network-name full-name :type :network}]) +(defn- provider-view + [{:keys [name logo-url]}] + [quo/context-tag + {:size 24 + :network-logo logo-url + :network-name name + :type :network}]) + (defn- subheader-view - [{:keys [account network]}] + [{:keys [provider account network]}] [rn/view {:style style/subheader-container} [quo/text {:size :paragraph-2 :weight :medium} (i18n/label :t/select-asset-on)] - [account-view account] + (if provider + [provider-view provider] + [account-view account]) + (when provider + [:<> + [quo/text + {:size :paragraph-2 + :weight :medium} + (i18n/label :t/to)] + [account-view account]]) [quo/text {:size :paragraph-2 :weight :medium} @@ -66,9 +83,8 @@ [network-view network]]) (defn view - [{:keys [title on-select hide-token-fn disable-token-fn]}] - (let [account (rf/sub [:wallet/current-viewing-account]) - {:keys [network]} (rf/sub [:wallet/swap]) + [{:keys [title network provider on-select hide-token-fn disable-token-fn]}] + (let [account (rf/sub [:wallet/current-viewing-account-or-default]) [search-text set-search-text] (rn/use-state "") window-height (:height (rn/get-window))] [rn/safe-area-view {:style (style/container window-height)} @@ -81,8 +97,9 @@ {:title title :title-accessibility-label :title-label}] [subheader-view - {:account account - :network network}] + {:account account + :network network + :provider provider}] [assets-view {:search-text search-text :on-change-text #(set-search-text %) diff --git a/src/status_im/contexts/wallet/swap/events.cljs b/src/status_im/contexts/wallet/swap/events.cljs index 57ced08ace9..027e02169d4 100644 --- a/src/status_im/contexts/wallet/swap/events.cljs +++ b/src/status_im/contexts/wallet/swap/events.cljs @@ -76,11 +76,7 @@ (rf/reg-event-fx :wallet.swap/select-asset-to-receive (fn [{:keys [db]} [{:keys [token]}]] - {:db (update-in db - [:wallet :ui :swap] - #(-> % - (assoc :asset-to-receive token) - (assoc :loading-swap-proposal? true)))})) + {:db (assoc-in db [:wallet :ui :swap :asset-to-receive] token)})) (rf/reg-event-fx :wallet.swap/set-default-slippage (fn [{:keys [db]}] diff --git a/src/status_im/contexts/wallet/swap/setup_swap/view.cljs b/src/status_im/contexts/wallet/swap/setup_swap/view.cljs index 27557dd5209..489f6bbd053 100644 --- a/src/status_im/contexts/wallet/swap/setup_swap/view.cljs +++ b/src/status_im/contexts/wallet/swap/setup_swap/view.cljs @@ -274,23 +274,28 @@ (defn- pay-token-bottom-sheet [] - (let [asset-to-receive (rf/sub [:wallet/swap-asset-to-receive])] + (let [asset-to-receive (rf/sub [:wallet/swap-asset-to-receive]) + network (rf/sub [:wallet/swap-network])] [select-asset/view {:title (i18n/label :t/select-asset-to-pay) + :network network :on-select (fn [token] (rf/dispatch [:wallet.swap/select-asset-to-pay {:token token}])) - :hide-token-fn (fn [type {:keys [available-balance]}] - (and (= type constants/swap-tokens-my) - (= available-balance 0))) + :hide-token-fn (fn [type {:keys [balances-per-chain]}] + (let [balance (get-in balances-per-chain [(:chain-id network) :balance] "0")] + (and (= type constants/swap-tokens-my) + (= balance "0")))) :disable-token-fn (fn [_ token] (= (:symbol token) (:symbol asset-to-receive)))}])) (defn- receive-token-bottom-sheet [] - (let [asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])] + (let [asset-to-pay (rf/sub [:wallet/swap-asset-to-pay]) + network (rf/sub [:wallet/swap-network])] [select-asset/view {:title (i18n/label :t/select-asset-to-receive) + :network network :on-select (fn [token] (rf/dispatch [:wallet.swap/select-asset-to-receive {:token token}])) :disable-token-fn (fn [_ token] diff --git a/src/status_im/contexts/wallet/tokens/data.cljs b/src/status_im/contexts/wallet/tokens/data.cljs index 8d347be4e92..d1146677263 100644 --- a/src/status_im/contexts/wallet/tokens/data.cljs +++ b/src/status_im/contexts/wallet/tokens/data.cljs @@ -34,9 +34,8 @@ (defn tokens-by-symbol [props] - (tokens-by-key (assoc props - :key-fn - (fn [{:keys [address] :as token}] - (if (get-in token [:communityData :id]) - address - (:symbol token)))))) + (tokens-by-key + (assoc props + :key-fn + (fn [{:keys [chainId address] :as token}] + (str chainId "-" (if (get-in token [:communityData :id]) address (:symbol token))))))) diff --git a/src/status_im/contexts/wallet/tokens/events_test.cljs b/src/status_im/contexts/wallet/tokens/events_test.cljs index ecf316f34d1..cc6000e6d79 100644 --- a/src/status_im/contexts/wallet/tokens/events_test.cljs +++ b/src/status_im/contexts/wallet/tokens/events_test.cljs @@ -75,7 +75,7 @@ :image nil}) :by-symbol '({:address "0x0000000000000000000000000000000000000000" :decimals 18 - :key "ETH" + :key "1-ETH" :community-id nil :symbol "ETH" :sources ["native"] @@ -86,7 +86,7 @@ :image nil} {:address "0x0000000000000000000000000000000000000001" :decimals 18 - :key "SNT" + :key "1-SNT" :community-id nil :symbol "SNT" :sources ["native"] @@ -174,7 +174,7 @@ :image nil}) :by-symbol '({:address "0x0000000000000000000000000000000000000000" :decimals 18 - :key "ETH" + :key "1-ETH" :community-id nil :symbol "ETH" :sources ["native"] @@ -185,7 +185,7 @@ :image nil} {:address "0x0000000000000000000000000000000000000001" :decimals 18 - :key "SNT" + :key "1-SNT" :community-id nil :symbol "SNT" :sources ["native" "second"] @@ -196,7 +196,7 @@ :image nil} {:address "0x0000000000000000000000000000000000000002" :decimals 18 - :key "ANOTHER1" + :key "1-ANOTHER1" :community-id nil :symbol "ANOTHER1" :sources ["second"] @@ -253,7 +253,7 @@ :image nil}) :by-symbol '({:address "0x0000000000000000000000000000000000000000" :decimals 18 - :key "ETH" + :key "1-ETH" :community-id nil :symbol "ETH" :sources ["native"] @@ -264,7 +264,7 @@ :image nil} {:address "0x0000000000000000000000000000000000000000" :decimals 18 - :key "ANOTHER1" + :key "1-ANOTHER1" :community-id nil :symbol "ANOTHER1" :sources ["native" "second"] diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 9489186e919..c9b3094f2f3 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -41,6 +41,7 @@ status-im.contexts.syncing.events status-im.contexts.wallet.add-account.add-address-to-watch.events status-im.contexts.wallet.add-account.create-account.events + status-im.contexts.wallet.buy-crypto.events status-im.contexts.wallet.collectible.events status-im.contexts.wallet.common.wizard.events status-im.contexts.wallet.effects diff --git a/src/status_im/subs/wallet/buy.cljs b/src/status_im/subs/wallet/buy.cljs index d85cab56495..5adf82ba003 100644 --- a/src/status_im/subs/wallet/buy.cljs +++ b/src/status_im/subs/wallet/buy.cljs @@ -5,3 +5,28 @@ :wallet/crypto-on-ramps :<- [:wallet] :-> :crypto-on-ramps) + +(rf/reg-sub + :wallet/wallet-buy-crypto + :<- [:wallet/ui] + :-> :buy-crypto) + +(rf/reg-sub + :wallet/wallet-buy-crypto-account + :<- [:wallet/wallet-buy-crypto] + :-> :account) + +(rf/reg-sub + :wallet/wallet-buy-crypto-provider + :<- [:wallet/wallet-buy-crypto] + :-> :provider) + +(rf/reg-sub + :wallet/wallet-buy-crypto-recurrent? + :<- [:wallet/wallet-buy-crypto] + :-> :recurrent?) + +(rf/reg-sub + :wallet/wallet-buy-crypto-network + :<- [:wallet/wallet-buy-crypto] + :-> :network) diff --git a/src/status_im/subs/wallet/wallet.cljs b/src/status_im/subs/wallet/wallet.cljs index b06a76c2ef6..7ac91558fe1 100644 --- a/src/status_im/subs/wallet/wallet.cljs +++ b/src/status_im/subs/wallet/wallet.cljs @@ -399,6 +399,22 @@ (assoc :balance balance :formatted-balance formatted-balance))))) +(rf/reg-sub + :wallet/current-viewing-account-or-default + :<- [:wallet/accounts] + :<- [:wallet/current-viewing-account-address] + :<- [:wallet/balances-in-selected-networks] + :<- [:profile/currency-symbol] + (fn [[accounts current-viewing-account-address balances currency-symbol]] + (let [account (or (utils/get-account-by-address accounts current-viewing-account-address) + (utils/get-default-account accounts)) + address (:address account) + balance (get balances address) + formatted-balance (utils/prettify-balance currency-symbol balance)] + (assoc account + :balance balance + :formatted-balance formatted-balance)))) + (rf/reg-sub :wallet/current-viewing-account-color :<- [:wallet/current-viewing-account] @@ -420,7 +436,7 @@ (rf/reg-sub :wallet/current-viewing-account-tokens-filtered - :<- [:wallet/current-viewing-account] + :<- [:wallet/current-viewing-account-or-default] :<- [:wallet/network-details] :<- [:wallet/wallet-send] (fn [[account networks send-data] [_ {:keys [query chain-ids hide-token-fn]}]] diff --git a/translations/en.json b/translations/en.json index ac22377f411..8ea1f62657c 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1794,6 +1794,7 @@ "on-keycard": "On Keycard", "on-status-tree": "On Status tree", "on-the-web": "On the web", + "on-uppercase": "On", "once-enabled-share-metadata": "Once enabled, links posted in the chat may share your metadata with the site", "one-day": "One day", "one-month": "One month", @@ -2212,11 +2213,13 @@ "select-another-account": "Select another account", "select-asset": "Select asset", "select-asset-on": "On", + "select-asset-to-buy": "Select asset to buy", "select-asset-to-pay": "Select asset to pay", "select-asset-to-receive": "Select asset to receive", "select-asset-via": "via", "select-chat": "Select chat to start messaging", "select-network": "Select network", + "select-network-for-buying": "Select network for buying", "select-networks": "Select networks", "select-new-location-for-keys": "Select a new location to save your private key(s)", "select-token-to-receive": "Select token to receive",