Wallet - Resolve user types on Transaction Confirmation Page #20267 (#20480)

This commit is contained in:
mmilad75 2024-06-27 18:12:59 +02:00 committed by GitHub
parent 112b69c1d6
commit 1ee44259c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 190 additions and 105 deletions

View File

@ -6,15 +6,20 @@
[react-native.platform :as platform] [react-native.platform :as platform]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.settings.wallet.saved-addresses.sheets.remove-address.view :as remove-address] [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.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn view (defn view
[{:keys [name full-address chain-short-names address] :as opts}] [{: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 #(rf/dispatch [:wallet/select-send-address
{:address full-address {:address full-address
:recipient full-address :recipient {:label (utils/get-shortened-address
splitted-address)
:recipient-type :saved-address}
:stack-id :wallet-select-address :stack-id :wallet-select-address
:start-flow? true}]) :start-flow? true}])
[full-address]) [full-address])

View File

@ -1,28 +1,33 @@
(ns status-im.contexts.shell.qr-reader.sheets.scanned-wallet-address (ns status-im.contexts.shell.qr-reader.sheets.scanned-wallet-address
(:require (:require
[quo.core :as quo] [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] [status-im.feature-flags :as ff]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn view (defn view
[address] [address]
[:<> (let [[_ splitted-address] (network-utils/split-network-full-address address)]
[quo/drawer-top [:<>
{:title address [quo/drawer-top
:type :address}] {:title address
[quo/action-drawer :type :address}]
[[{:icon :i/send [quo/action-drawer
:accessibility-label :send-asset [[{:icon :i/send
:label (i18n/label :t/send-to-this-address) :accessibility-label :send-asset
:on-press (fn [] :label (i18n/label :t/send-to-this-address)
(rf/dispatch [:wallet/select-send-address :on-press (fn []
{:address address (rf/dispatch [:wallet/select-send-address
:recipient address {:address address
:stack-id :wallet-select-address :recipient {:recipient-type :address
:start-flow? true}]))} :label (utils/get-shortened-address
(when (ff/enabled? :ff/wallet.saved-addresses) splitted-address)}
{:icon :i/save :stack-id :wallet-select-address
:accessibility-label :save-address :start-flow? true}]))}
:label (i18n/label :t/save-address) (when (ff/enabled? :ff/wallet.saved-addresses)
:on-press #(js/alert "feature not implemented")})]]]]) {:icon :i/save
:accessibility-label :save-address
:label (i18n/label :t/save-address)
:on-press #(js/alert "feature not implemented")})]]]]))

View File

@ -272,6 +272,14 @@
%) %)
address-tokens))) 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 (defn make-limit-label-crypto
[amount currency] [amount currency]
(str amount (str amount

View File

@ -143,6 +143,12 @@
token-networks-ids-set (set token-networks-ids)] token-networks-ids-set (set token-networks-ids)]
(contains? token-networks-ids-set chain-id))) (contains? token-networks-ids-set chain-id)))
(defn split-network-full-address
[address]
(as-> address $
(string/split $ ":")
[(butlast $) (last $)]))
(def mainnet-network-details (def mainnet-network-details
{:source (resources/get-network constants/mainnet-network-name) {:source (resources/get-network constants/mainnet-network-name)
:short-name constants/mainnet-short-name :short-name constants/mainnet-short-name

View File

@ -4,6 +4,7 @@
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[status-im.common.resources :as resources] [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] [status-im.contexts.wallet.send.select-address.tabs.style :as style]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@ -30,7 +31,10 @@
:full-address? true) :full-address? true)
:on-press #(rf/dispatch [:wallet/select-send-address :on-press #(rf/dispatch [:wallet/select-send-address
{:address 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}])}])))]))) :stack-id :screen/wallet.select-address}])}])))])))
(defn- recent-transactions (defn- recent-transactions
@ -48,7 +52,9 @@
{:address address {:address address
:on-press #(rf/dispatch [:wallet/select-send-address :on-press #(rf/dispatch [:wallet/select-send-address
{:address address {:address address
:recipient address :recipient {:label (utils/get-shortened-address
address)
:recipient-type :address}
:stack-id :screen/wallet.select-address}])}])) :stack-id :screen/wallet.select-address}])}]))
recent-recipients)))) recent-recipients))))
@ -59,7 +65,9 @@
#(rf/dispatch #(rf/dispatch
[:wallet/select-send-address [:wallet/select-send-address
{:address full-address {:address full-address
:recipient full-address :recipient {:label name
:customization-color customization-color
:recipient-type :saved-address}
:stack-id :screen/wallet.select-address}]) :stack-id :screen/wallet.select-address}])
[full-address])] [full-address])]
[quo/saved-address [quo/saved-address

View File

@ -1,5 +1,6 @@
(ns status-im.contexts.wallet.send.select-address.view (ns status-im.contexts.wallet.send.select-address.view
(:require (:require
[clojure.string :as string]
[quo.core :as quo] [quo.core :as quo]
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme] [quo.theme]
@ -9,6 +10,8 @@
[status-im.common.floating-button-page.view :as floating-button-page] [status-im.common.floating-button-page.view :as floating-button-page]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher] [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.common.validation :as validation]
[status-im.contexts.wallet.item-types :as types] [status-im.contexts.wallet.item-types :as types]
[status-im.contexts.wallet.send.select-address.style :as style] [status-im.contexts.wallet.send.select-address.style :as style]
@ -136,6 +139,33 @@
:keyboard-should-persist-taps :handled :keyboard-should-persist-taps :handled
:render-fn suggestion-component}]])) :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 (defn view
[] []
(let [on-close (fn [] (let [on-close (fn []
@ -150,10 +180,8 @@
input-value (reagent/atom "") input-value (reagent/atom "")
input-focused? (reagent/atom false)] input-focused? (reagent/atom false)]
(fn [] (fn []
(let [selected-tab (or (rf/sub [:wallet/send-tab]) (:id (first tabs-data))) (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?])) 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])]
[floating-button-page/view [floating-button-page/view
{:content-container-style {:flex 1} {:content-container-style {:flex 1}
:footer-container-padding 0 :footer-container-padding 0
@ -162,20 +190,8 @@
{:on-press on-close {:on-press on-close
:margin-top (safe-area/get-top) :margin-top (safe-area/get-top)
:switcher-type :select-account}] :switcher-type :select-account}]
:footer (when (> (count @input-value) 0) :footer (when-not (string/blank? @input-value)
[quo/button [footer @input-value])}
{: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)])}
[quo/page-top [quo/page-top
{:title (i18n/label :t/send-to) {:title (i18n/label :t/send-to)
:title-accessibility-label :title-label}] :title-accessibility-label :title-label}]

View File

@ -1,22 +1,21 @@
(ns status-im.contexts.wallet.send.transaction-confirmation.view (ns status-im.contexts.wallet.send.transaction-confirmation.view
(:require (:require
[clojure.string :as string] [clojure.string :as string]
[legacy.status-im.utils.utils :as utils]
[quo.core :as quo] [quo.core :as quo]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.safe-area :as safe-area] [react-native.safe-area :as safe-area]
[status-im.common.floating-button-page.view :as floating-button-page] [status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.standard-authentication.core :as standard-auth] [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] [status-im.contexts.wallet.send.transaction-confirmation.style :as style]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[utils.security.core :as security])) [utils.security.core :as security]))
(defn- transaction-title (defn- transaction-title
[{:keys [token-display-name amount account to-address route to-network image-url [{:keys [token-display-name amount account route to-network image-url transaction-type
transaction-type collectible?]}] collectible? recipient]}]
(let [to-network-name (:network-name to-network) (let [to-network-name (:network-name to-network)
to-network-color (if (= to-network-name :mainnet) :ethereum to-network-name)] to-network-color (if (= to-network-name :mainnet) :ethereum to-network-name)]
[rn/view {:style style/content-container} [rn/view {:style style/content-container}
@ -107,9 +106,7 @@
:image-source (:source to-network) :image-source (:source to-network)
:label (string/capitalize (name (:network-name to-network))) :label (string/capitalize (name (:network-name to-network)))
:customization-color to-network-color}] :customization-color to-network-color}]
[quo/summary-tag [quo/summary-tag (assoc recipient :type (:recipient-type recipient))])]
{:type :address
:label (utils/get-shortened-address to-address)}])]
(when (= transaction-type :tx/bridge) (when (= transaction-type :tx/bridge)
[rn/view [rn/view
{:style {:flex-direction :row {:style {:flex-direction :row
@ -127,20 +124,12 @@
:customization-color (:color account)}]])])) :customization-color (:color account)}]])]))
(defn- user-summary (defn- user-summary
[{:keys [network-values token-display-name account-props theme label accessibility-label [{:keys [account-props theme label accessibility-label summary-type recipient account-to?]}]
summary-type]}] (let [network-values (rf/sub [:wallet/network-values account-to?])
(let [network-values (reduce-kv summary-info-type (case (:recipient-type recipient)
(fn [acc chain-id amount] :saved-address :saved-account
(let [network-name (network-utils/id->network chain-id) :account :status-account
network-keyword (if (= network-name :mainnet) summary-type)]
:ethereum
network-name)]
(assoc acc
network-keyword
{:amount amount
:token-symbol token-display-name})))
{}
network-values)]
[rn/view [rn/view
{:style {:padding-horizontal 20 {:style {:padding-horizontal 20
:padding-bottom 16}} :padding-bottom 16}}
@ -151,10 +140,17 @@
:accessibility-label accessibility-label} :accessibility-label accessibility-label}
label] label]
[quo/summary-info [quo/summary-info
{:type summary-type {:type summary-info-type
:networks? true :networks? true
:values network-values :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 (defn- data-item
[{:keys [title subtitle]}] [{:keys [title subtitle]}]
@ -202,39 +198,45 @@
[_] [_]
(let [on-close #(rf/dispatch [:navigate-back])] (let [on-close #(rf/dispatch [:navigate-back])]
(fn [] (fn []
(let [theme (quo.theme/use-theme) (let [theme (quo.theme/use-theme)
send-transaction-data (rf/sub [:wallet/wallet-send]) send-transaction-data (rf/sub [:wallet/wallet-send])
{:keys [token-display-name collectible amount route {:keys [token-display-name collectible amount
to-address bridge-to-chain-id route
from-values-by-chain to-address bridge-to-chain-id type
to-values-by-chain]} send-transaction-data recipient]} send-transaction-data
collectible? (some? collectible) collectible? (some? collectible)
image-url (when collectible image-url (when collectible
(get-in collectible [:preview-url :uri])) (get-in collectible [:preview-url :uri]))
transaction-type (:tx-type send-transaction-data) transaction-type (:tx-type send-transaction-data)
estimated-time-min (reduce + (map :estimated-time route)) estimated-time-min (reduce + (map :estimated-time route))
token-symbol (or token-display-name token-symbol (or token-display-name
(-> send-transaction-data :token :symbol)) (-> send-transaction-data :token :symbol))
first-route (first route) first-route (first route)
native-currency-symbol (get-in first-route [:from :native-currency-symbol]) native-currency-symbol (get-in first-route
native-token (when native-currency-symbol [:from :native-currency-symbol])
(rf/sub [:wallet/token-by-symbol native-currency-symbol])) native-token (when native-currency-symbol
fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted native-token]) (rf/sub [:wallet/token-by-symbol
account (rf/sub [:wallet/current-viewing-account]) native-currency-symbol]))
account-color (:color account) fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted
bridge-to-network (when bridge-to-chain-id native-token])
(rf/sub [:wallet/network-details-by-chain-id account (rf/sub [:wallet/current-viewing-account])
bridge-to-chain-id])) account-color (:color account)
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?]) bridge-to-network (when bridge-to-chain-id
from-account-props {:customization-color account-color (rf/sub [:wallet/network-details-by-chain-id
:size 32 bridge-to-chain-id]))
:emoji (:emoji account) loading-suggested-routes? (rf/sub
:type :default [:wallet/wallet-send-loading-suggested-routes?])
:name (:name account) from-account-props {:customization-color account-color
:address (utils/get-shortened-address (:address :size 32
account))} :emoji (:emoji account)
user-props {:full-name to-address :type :default
:address (utils/get-shortened-address to-address)}] :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}} [rn/view {:style {:flex 1}}
[floating-button-page/view [floating-button-page/view
{:footer-container-padding 0 {:footer-container-padding 0
@ -274,23 +276,21 @@
{:token-display-name token-symbol {:token-display-name token-symbol
:amount amount :amount amount
:account account :account account
:to-address to-address :type type
:recipient recipient
:route route :route route
:to-network bridge-to-network :to-network bridge-to-network
:image-url image-url :image-url image-url
:transaction-type transaction-type :transaction-type transaction-type
:collectible? collectible?}] :collectible? collectible?}]
[user-summary [user-summary
{:token-display-name token-symbol {:summary-type :status-account
:summary-type :status-account
:accessibility-label :summary-from-label :accessibility-label :summary-from-label
:label (i18n/label :t/from-capitalized) :label (i18n/label :t/from-capitalized)
:network-values from-values-by-chain
:account-props from-account-props :account-props from-account-props
:theme theme}] :theme theme}]
[user-summary [user-summary
{:token-display-name token-symbol {:summary-type (if (= transaction-type :tx/bridge)
:summary-type (if (= transaction-type :tx/bridge)
:status-account :status-account
:account) :account)
:accessibility-label :summary-to-label :accessibility-label :summary-to-label
@ -298,5 +298,6 @@
:account-props (if (= transaction-type :tx/bridge) :account-props (if (= transaction-type :tx/bridge)
from-account-props from-account-props
user-props) user-props)
:network-values to-values-by-chain :recipient recipient
:account-to? true
:theme theme}]]]])))) :theme theme}]]]]))))

View File

@ -64,3 +64,19 @@
short-names)) short-names))
transformed-address (str prefix address)] transformed-address (str prefix address)]
transformed-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))))

View File

@ -100,3 +100,23 @@
"returns the address without the prefixes when an address and equal or more than 3 network preferences are passed" "returns the address without the prefixes when an address and equal or more than 3 network preferences are passed"
(is (is
(match? "0x01" (rf/sub [sub-name "0x01" [:ethereum :optimism :arbitrum]]))))) (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])))))