diff --git a/src/status_im/contexts/settings/wallet/saved_addresses/sheets/address_options/view.cljs b/src/status_im/contexts/settings/wallet/saved_addresses/sheets/address_options/view.cljs index f0dc8e39a0..c1ae3ac6f6 100644 --- a/src/status_im/contexts/settings/wallet/saved_addresses/sheets/address_options/view.cljs +++ b/src/status_im/contexts/settings/wallet/saved_addresses/sheets/address_options/view.cljs @@ -6,15 +6,20 @@ [react-native.platform :as platform] [status-im.constants :as constants] [status-im.contexts.settings.wallet.saved-addresses.sheets.remove-address.view :as remove-address] + [status-im.contexts.wallet.common.utils :as utils] + [status-im.contexts.wallet.common.utils.networks :as network-utils] [utils.i18n :as i18n] [utils.re-frame :as rf])) (defn view [{:keys [name full-address chain-short-names address] :as opts}] - (let [open-send-flow (rn/use-callback + (let [[_ splitted-address] (network-utils/split-network-full-address address) + open-send-flow (rn/use-callback #(rf/dispatch [:wallet/select-send-address {:address full-address - :recipient full-address + :recipient {:label (utils/get-shortened-address + splitted-address) + :recipient-type :saved-address} :stack-id :wallet-select-address :start-flow? true}]) [full-address]) diff --git a/src/status_im/contexts/shell/qr_reader/sheets/scanned_wallet_address.cljs b/src/status_im/contexts/shell/qr_reader/sheets/scanned_wallet_address.cljs index f5d1bf8964..c334f2994e 100644 --- a/src/status_im/contexts/shell/qr_reader/sheets/scanned_wallet_address.cljs +++ b/src/status_im/contexts/shell/qr_reader/sheets/scanned_wallet_address.cljs @@ -1,28 +1,33 @@ (ns status-im.contexts.shell.qr-reader.sheets.scanned-wallet-address (:require [quo.core :as quo] + [status-im.contexts.wallet.common.utils :as utils] + [status-im.contexts.wallet.common.utils.networks :as network-utils] [status-im.feature-flags :as ff] [utils.i18n :as i18n] [utils.re-frame :as rf])) (defn view [address] - [:<> - [quo/drawer-top - {:title address - :type :address}] - [quo/action-drawer - [[{:icon :i/send - :accessibility-label :send-asset - :label (i18n/label :t/send-to-this-address) - :on-press (fn [] - (rf/dispatch [:wallet/select-send-address - {:address address - :recipient address - :stack-id :wallet-select-address - :start-flow? true}]))} - (when (ff/enabled? :ff/wallet.saved-addresses) - {:icon :i/save - :accessibility-label :save-address - :label (i18n/label :t/save-address) - :on-press #(js/alert "feature not implemented")})]]]]) + (let [[_ splitted-address] (network-utils/split-network-full-address address)] + [:<> + [quo/drawer-top + {:title address + :type :address}] + [quo/action-drawer + [[{:icon :i/send + :accessibility-label :send-asset + :label (i18n/label :t/send-to-this-address) + :on-press (fn [] + (rf/dispatch [:wallet/select-send-address + {:address address + :recipient {:recipient-type :address + :label (utils/get-shortened-address + splitted-address)} + :stack-id :wallet-select-address + :start-flow? true}]))} + (when (ff/enabled? :ff/wallet.saved-addresses) + {:icon :i/save + :accessibility-label :save-address + :label (i18n/label :t/save-address) + :on-press #(js/alert "feature not implemented")})]]]])) diff --git a/src/status_im/contexts/wallet/common/utils.cljs b/src/status_im/contexts/wallet/common/utils.cljs index b0f7f6ec7a..3e2e9660e5 100644 --- a/src/status_im/contexts/wallet/common/utils.cljs +++ b/src/status_im/contexts/wallet/common/utils.cljs @@ -272,6 +272,14 @@ %) address-tokens))) +(defn get-shortened-address + "Takes first and last 4 digits from address including leading 0x + and adds unicode ellipsis in between" + [address] + (when address + (let [counter (count address)] + (str (subs address 0 6) "\u2026" (subs address (- counter 3) counter))))) + (defn make-limit-label-crypto [amount currency] (str amount diff --git a/src/status_im/contexts/wallet/common/utils/networks.cljs b/src/status_im/contexts/wallet/common/utils/networks.cljs index 188f4e1e67..ad20445e0b 100644 --- a/src/status_im/contexts/wallet/common/utils/networks.cljs +++ b/src/status_im/contexts/wallet/common/utils/networks.cljs @@ -143,6 +143,12 @@ token-networks-ids-set (set token-networks-ids)] (contains? token-networks-ids-set chain-id))) +(defn split-network-full-address + [address] + (as-> address $ + (string/split $ ":") + [(butlast $) (last $)])) + (def mainnet-network-details {:source (resources/get-network constants/mainnet-network-name) :short-name constants/mainnet-short-name diff --git a/src/status_im/contexts/wallet/send/select_address/tabs/view.cljs b/src/status_im/contexts/wallet/send/select_address/tabs/view.cljs index 43b042e167..02b81fd65d 100644 --- a/src/status_im/contexts/wallet/send/select_address/tabs/view.cljs +++ b/src/status_im/contexts/wallet/send/select_address/tabs/view.cljs @@ -4,6 +4,7 @@ [quo.theme :as quo.theme] [react-native.core :as rn] [status-im.common.resources :as resources] + [status-im.contexts.wallet.common.utils :as utils] [status-im.contexts.wallet.send.select-address.tabs.style :as style] [utils.i18n :as i18n] [utils.re-frame :as rf])) @@ -30,7 +31,10 @@ :full-address? true) :on-press #(rf/dispatch [:wallet/select-send-address {:address address - :recipient account + :recipient {:recipient-type :account + :label (:name account) + :customization-color (:color account) + :emoji (:emoji account)} :stack-id :screen/wallet.select-address}])}])))]))) (defn- recent-transactions @@ -48,7 +52,9 @@ {:address address :on-press #(rf/dispatch [:wallet/select-send-address {:address address - :recipient address + :recipient {:label (utils/get-shortened-address + address) + :recipient-type :address} :stack-id :screen/wallet.select-address}])}])) recent-recipients)))) @@ -59,7 +65,9 @@ #(rf/dispatch [:wallet/select-send-address {:address full-address - :recipient full-address + :recipient {:label name + :customization-color customization-color + :recipient-type :saved-address} :stack-id :screen/wallet.select-address}]) [full-address])] [quo/saved-address diff --git a/src/status_im/contexts/wallet/send/select_address/view.cljs b/src/status_im/contexts/wallet/send/select_address/view.cljs index c1dc144f09..a1e2a3b2d7 100644 --- a/src/status_im/contexts/wallet/send/select_address/view.cljs +++ b/src/status_im/contexts/wallet/send/select_address/view.cljs @@ -1,5 +1,6 @@ (ns status-im.contexts.wallet.send.select-address.view (:require + [clojure.string :as string] [quo.core :as quo] [quo.foundations.colors :as colors] [quo.theme] @@ -9,6 +10,8 @@ [status-im.common.floating-button-page.view :as floating-button-page] [status-im.constants :as constants] [status-im.contexts.wallet.common.account-switcher.view :as account-switcher] + [status-im.contexts.wallet.common.utils :as utils] + [status-im.contexts.wallet.common.utils.networks :as network-utils] [status-im.contexts.wallet.common.validation :as validation] [status-im.contexts.wallet.item-types :as types] [status-im.contexts.wallet.send.select-address.style :as style] @@ -136,6 +139,33 @@ :keyboard-should-persist-taps :handled :render-fn suggestion-component}]])) +(defn- footer + [input-value] + (let [local-suggestion-address (rf/sub [:wallet/local-suggestions->full-address]) + color (rf/sub [:wallet/current-viewing-account-color]) + valid-ens-or-address? (boolean (rf/sub [:wallet/valid-ens-or-address?]))] + [quo/button + {:accessibility-label :continue-button + :type :primary + :disabled? (not valid-ens-or-address?) + :on-press (fn [] + (let [address (or + local-suggestion-address + input-value) + [_ splitted-address] (network-utils/split-network-full-address + address)] + (rf/dispatch + [:wallet/select-send-address + {:address address + :recipient {:label + (utils/get-shortened-address + splitted-address) + :recipient-type :address} + :stack-id + :screen/wallet.select-address}]))) + :customization-color color} + (i18n/label :t/continue)])) + (defn view [] (let [on-close (fn [] @@ -150,10 +180,8 @@ input-value (reagent/atom "") input-focused? (reagent/atom false)] (fn [] - (let [selected-tab (or (rf/sub [:wallet/send-tab]) (:id (first tabs-data))) - valid-ens-or-address? (boolean (rf/sub [:wallet/valid-ens-or-address?])) - local-suggestion-address (rf/sub [:wallet/local-suggestions->full-address]) - color (rf/sub [:wallet/current-viewing-account-color])] + (let [selected-tab (or (rf/sub [:wallet/send-tab]) (:id (first tabs-data))) + valid-ens-or-address? (boolean (rf/sub [:wallet/valid-ens-or-address?]))] [floating-button-page/view {:content-container-style {:flex 1} :footer-container-padding 0 @@ -162,20 +190,8 @@ {:on-press on-close :margin-top (safe-area/get-top) :switcher-type :select-account}] - :footer (when (> (count @input-value) 0) - [quo/button - {:accessibility-label :continue-button - :type :primary - :disabled? (not valid-ens-or-address?) - :on-press #(rf/dispatch - [:wallet/select-send-address - {:address (or - local-suggestion-address - @input-value) - :stack-id - :screen/wallet.select-address}]) - :customization-color color} - (i18n/label :t/continue)])} + :footer (when-not (string/blank? @input-value) + [footer @input-value])} [quo/page-top {:title (i18n/label :t/send-to) :title-accessibility-label :title-label}] diff --git a/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs b/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs index a61896ef69..7f2fd8263f 100644 --- a/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs +++ b/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs @@ -1,22 +1,21 @@ (ns status-im.contexts.wallet.send.transaction-confirmation.view (:require [clojure.string :as string] - [legacy.status-im.utils.utils :as utils] [quo.core :as quo] [quo.theme :as quo.theme] [react-native.core :as rn] [react-native.safe-area :as safe-area] [status-im.common.floating-button-page.view :as floating-button-page] [status-im.common.standard-authentication.core :as standard-auth] - [status-im.contexts.wallet.common.utils.networks :as network-utils] + [status-im.contexts.wallet.common.utils :as utils] [status-im.contexts.wallet.send.transaction-confirmation.style :as style] [utils.i18n :as i18n] [utils.re-frame :as rf] [utils.security.core :as security])) (defn- transaction-title - [{:keys [token-display-name amount account to-address route to-network image-url - transaction-type collectible?]}] + [{:keys [token-display-name amount account route to-network image-url transaction-type + collectible? recipient]}] (let [to-network-name (:network-name to-network) to-network-color (if (= to-network-name :mainnet) :ethereum to-network-name)] [rn/view {:style style/content-container} @@ -107,9 +106,7 @@ :image-source (:source to-network) :label (string/capitalize (name (:network-name to-network))) :customization-color to-network-color}] - [quo/summary-tag - {:type :address - :label (utils/get-shortened-address to-address)}])] + [quo/summary-tag (assoc recipient :type (:recipient-type recipient))])] (when (= transaction-type :tx/bridge) [rn/view {:style {:flex-direction :row @@ -127,20 +124,12 @@ :customization-color (:color account)}]])])) (defn- user-summary - [{:keys [network-values token-display-name account-props theme label accessibility-label - summary-type]}] - (let [network-values (reduce-kv - (fn [acc chain-id amount] - (let [network-name (network-utils/id->network chain-id) - network-keyword (if (= network-name :mainnet) - :ethereum - network-name)] - (assoc acc - network-keyword - {:amount amount - :token-symbol token-display-name}))) - {} - network-values)] + [{:keys [account-props theme label accessibility-label summary-type recipient account-to?]}] + (let [network-values (rf/sub [:wallet/network-values account-to?]) + summary-info-type (case (:recipient-type recipient) + :saved-address :saved-account + :account :status-account + summary-type)] [rn/view {:style {:padding-horizontal 20 :padding-bottom 16}} @@ -151,10 +140,17 @@ :accessibility-label accessibility-label} label] [quo/summary-info - {:type summary-type + {:type summary-info-type :networks? true :values network-values - :account-props account-props}]])) + :account-props (cond-> account-props + account-to? + (assoc + :size 32 + :name (:label recipient) + :full-name (:label recipient) + :emoji (:emoji recipient) + :customization-color (:customization-color recipient)))}]])) (defn- data-item [{:keys [title subtitle]}] @@ -202,39 +198,45 @@ [_] (let [on-close #(rf/dispatch [:navigate-back])] (fn [] - (let [theme (quo.theme/use-theme) - send-transaction-data (rf/sub [:wallet/wallet-send]) - {:keys [token-display-name collectible amount route - to-address bridge-to-chain-id - from-values-by-chain - to-values-by-chain]} send-transaction-data - collectible? (some? collectible) - image-url (when collectible - (get-in collectible [:preview-url :uri])) - transaction-type (:tx-type send-transaction-data) - estimated-time-min (reduce + (map :estimated-time route)) - token-symbol (or token-display-name - (-> send-transaction-data :token :symbol)) - first-route (first route) - native-currency-symbol (get-in first-route [:from :native-currency-symbol]) - native-token (when native-currency-symbol - (rf/sub [:wallet/token-by-symbol native-currency-symbol])) - fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted native-token]) - account (rf/sub [:wallet/current-viewing-account]) - account-color (:color account) - bridge-to-network (when bridge-to-chain-id - (rf/sub [:wallet/network-details-by-chain-id - bridge-to-chain-id])) - loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?]) - from-account-props {:customization-color account-color - :size 32 - :emoji (:emoji account) - :type :default - :name (:name account) - :address (utils/get-shortened-address (:address - account))} - user-props {:full-name to-address - :address (utils/get-shortened-address to-address)}] + (let [theme (quo.theme/use-theme) + send-transaction-data (rf/sub [:wallet/wallet-send]) + {:keys [token-display-name collectible amount + route + to-address bridge-to-chain-id type + recipient]} send-transaction-data + collectible? (some? collectible) + image-url (when collectible + (get-in collectible [:preview-url :uri])) + transaction-type (:tx-type send-transaction-data) + estimated-time-min (reduce + (map :estimated-time route)) + token-symbol (or token-display-name + (-> send-transaction-data :token :symbol)) + first-route (first route) + native-currency-symbol (get-in first-route + [:from :native-currency-symbol]) + native-token (when native-currency-symbol + (rf/sub [:wallet/token-by-symbol + native-currency-symbol])) + fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted + native-token]) + account (rf/sub [:wallet/current-viewing-account]) + account-color (:color account) + bridge-to-network (when bridge-to-chain-id + (rf/sub [:wallet/network-details-by-chain-id + bridge-to-chain-id])) + loading-suggested-routes? (rf/sub + [:wallet/wallet-send-loading-suggested-routes?]) + from-account-props {:customization-color account-color + :size 32 + :emoji (:emoji account) + :type :default + :name (:name account) + :address (utils/get-shortened-address + (:address + account))} + user-props {:full-name to-address + :address (utils/get-shortened-address + to-address)}] [rn/view {:style {:flex 1}} [floating-button-page/view {:footer-container-padding 0 @@ -274,23 +276,21 @@ {:token-display-name token-symbol :amount amount :account account - :to-address to-address + :type type + :recipient recipient :route route :to-network bridge-to-network :image-url image-url :transaction-type transaction-type :collectible? collectible?}] [user-summary - {:token-display-name token-symbol - :summary-type :status-account + {:summary-type :status-account :accessibility-label :summary-from-label :label (i18n/label :t/from-capitalized) - :network-values from-values-by-chain :account-props from-account-props :theme theme}] [user-summary - {:token-display-name token-symbol - :summary-type (if (= transaction-type :tx/bridge) + {:summary-type (if (= transaction-type :tx/bridge) :status-account :account) :accessibility-label :summary-to-label @@ -298,5 +298,6 @@ :account-props (if (= transaction-type :tx/bridge) from-account-props user-props) - :network-values to-values-by-chain + :recipient recipient + :account-to? true :theme theme}]]]])))) diff --git a/src/status_im/subs/wallet/networks.cljs b/src/status_im/subs/wallet/networks.cljs index 1af52c3974..70a3ef47c1 100644 --- a/src/status_im/subs/wallet/networks.cljs +++ b/src/status_im/subs/wallet/networks.cljs @@ -64,3 +64,19 @@ short-names)) transformed-address (str prefix address)] transformed-address))) + +(re-frame/reg-sub + :wallet/network-values + :<- [:wallet/wallet-send] + (fn [{:keys [from-values-by-chain to-values-by-chain token-display-name] :as send-data} [_ to-values?]] + (let [network-values (if to-values? to-values-by-chain from-values-by-chain) + token-symbol (or token-display-name + (-> send-data :token :symbol))] + (reduce-kv + (fn [acc chain-id amount] + (let [network-name (network-utils/id->network chain-id)] + (assoc acc + (if (= network-name :mainnet) :ethereum network-name) + {:amount amount :token-symbol token-symbol}))) + {} + network-values)))) diff --git a/src/status_im/subs/wallet/networks_test.cljs b/src/status_im/subs/wallet/networks_test.cljs index 65fc7fdb4f..e69fac3c87 100644 --- a/src/status_im/subs/wallet/networks_test.cljs +++ b/src/status_im/subs/wallet/networks_test.cljs @@ -100,3 +100,23 @@ "returns the address without the prefixes when an address and equal or more than 3 network preferences are passed" (is (match? "0x01" (rf/sub [sub-name "0x01" [:ethereum :optimism :arbitrum]]))))) + +(h/deftest-sub :wallet/network-values + [sub-name] + (testing "network values for the from account are returned correctly" + (swap! rf-db/app-db assoc-in + [:wallet :ui :send] + {:from-values-by-chain {1 100} + :to-values-by-chain {42161 100} + :token-display-name "ETH"}) + (is + (match? {:ethereum {:amount 100 :token-symbol "ETH"}} (rf/sub [sub-name false])))) + + (testing "network values for the to account are returned correctly" + (swap! rf-db/app-db assoc-in + [:wallet :ui :send] + {:from-values-by-chain {1 100} + :to-values-by-chain {42161 100} + :token-display-name "ARB1"}) + (is + (match? {:arbitrum {:amount 100 :token-symbol "ARB1"}} (rf/sub [sub-name true])))))