From f692ae2222034ee15c05b77421fc0d09da4ba5c5 Mon Sep 17 00:00:00 2001 From: Omar Basem Date: Thu, 7 Dec 2023 08:00:56 +0400 Subject: [PATCH] Wallet: ENS (#18000) * wallet: ens --- .../components/inputs/address_input/view.cljs | 12 ++-- src/status_im2/constants.cljs | 3 + src/status_im2/contexts/wallet/events.cljs | 41 +++++++++++++ .../wallet/send/select_address/style.cljs | 6 +- .../wallet/send/select_address/view.cljs | 59 ++++++++++--------- .../wallet/send/select_asset/view.cljs | 11 +--- src/status_im2/navigation/screens.cljs | 3 +- 7 files changed, 84 insertions(+), 51 deletions(-) diff --git a/src/quo/components/inputs/address_input/view.cljs b/src/quo/components/inputs/address_input/view.cljs index e56089c20b..31ea593853 100644 --- a/src/quo/components/inputs/address_input/view.cljs +++ b/src/quo/components/inputs/address_input/view.cljs @@ -61,14 +61,10 @@ value (reagent/atom "") focused? (atom false)] (fn [{:keys [scanned-value theme blur? on-change-text on-blur on-focus on-clear on-scan on-detect-ens - on-detect-address - ens-regex address-regex - valid-ens-or-address?]}] + on-detect-address address-regex valid-ens-or-address?]}] (let [on-change (fn [text] (when (not= @value text) - (let [ens? (when ens-regex - (boolean (re-matches ens-regex text))) - address? (when address-regex + (let [address? (when address-regex (boolean (re-matches address-regex text)))] (if (> (count text) 0) (reset! status :typing) @@ -76,9 +72,9 @@ (reset! value text) (when on-change-text (on-change-text text)) - (when (and ens? on-detect-ens) + (when (and on-detect-ens (> (count text) 0)) (reset! status :loading) - (on-detect-ens text)) + (on-detect-ens text #(reset! status :typing))) (when (and address? on-detect-address) (reset! status :loading) (on-detect-address text))))) diff --git a/src/status_im2/constants.cljs b/src/status_im2/constants.cljs index b0e20c11da..73c730bda6 100644 --- a/src/status_im2/constants.cljs +++ b/src/status_im2/constants.cljs @@ -390,3 +390,6 @@ (def ^:const account-default-customization-color :blue) (def ^:const wallet-account-name-max-length 20) + +(def ^:const status-address-domain ".stateofus.eth") +(def ^:const eth-address-domain ".eth") diff --git a/src/status_im2/contexts/wallet/events.cljs b/src/status_im2/contexts/wallet/events.cljs index c397856d48..8f2a4bbe6d 100644 --- a/src/status_im2/contexts/wallet/events.cljs +++ b/src/status_im2/contexts/wallet/events.cljs @@ -7,9 +7,11 @@ [quo.foundations.colors :as colors] [react-native.background-timer :as background-timer] [status-im2.common.data-store.wallet :as data-store] + [status-im2.contexts.wallet.item-types :as item-types] [status-im2.contexts.wallet.temp :as temp] [taoensso.timbre :as log] [utils.ethereum.chain :as chain] + [utils.ethereum.eip.eip55 :as eip55] [utils.i18n :as i18n] [utils.number] [utils.re-frame :as rf] @@ -327,6 +329,45 @@ {:event :wallet/get-collectible-details-done :response response}))))) +(rf/reg-event-fx :wallet/find-ens + (fn [{:keys [db]} [input contacts chain-id cb]] + (let [result (if (empty? input) + [] + (filter #(string/starts-with? (or (:ens-name %) "") input) contacts))] + (if (and input (empty? result)) + (rf/dispatch [:wallet/search-ens input chain-id cb ".stateofus.eth"]) + {:db (assoc db + :wallet/local-suggestions + (map #(assoc % :type item-types/saved-address) result) + :wallet/valid-ens-or-address? (not-empty result))})))) + +(rf/reg-event-fx :wallet/search-ens + (fn [_ [input chain-id cb domain]] + (let [ens (if (string/includes? input ".") input (str input domain))] + {:fx [[:json-rpc/call + [{:method "ens_addressOf" + :params [chain-id ens] + :on-success #(rf/dispatch [:wallet/set-ens-address % ens]) + :on-error (fn [] + (if (= domain ".stateofus.eth") + (rf/dispatch [:wallet/search-ens input chain-id cb ".eth"]) + (do + (rf/dispatch [:wallet/set-ens-address nil ens]) + (cb))))}]]]}))) + +(rf/reg-event-fx :wallet/set-ens-address + (fn [{:keys [db]} [result ens]] + {:db (assoc db + :wallet/local-suggestions (if result + [{:type item-types/address + :ens ens + :address (eip55/address->checksum result) + :networks [:ethereum :optimism]}] + []) + :wallet/valid-ens-or-address? (boolean result))})) + + + (rf/reg-event-fx :wallet/fetch-address-suggestions (fn [{:keys [db]} [address]] {:db (assoc db diff --git a/src/status_im2/contexts/wallet/send/select_address/style.cljs b/src/status_im2/contexts/wallet/send/select_address/style.cljs index c663fc8f37..05a473c694 100644 --- a/src/status_im2/contexts/wallet/send/select_address/style.cljs +++ b/src/status_im2/contexts/wallet/send/select_address/style.cljs @@ -1,9 +1,7 @@ (ns status-im2.contexts.wallet.send.select-address.style) -(defn container - [margin-top] - {:flex 1 - :margin-top margin-top}) +(def container + {:flex 1}) (def title-container {:margin-horizontal 20 diff --git a/src/status_im2/contexts/wallet/send/select_address/view.cljs b/src/status_im2/contexts/wallet/send/select_address/view.cljs index 20d365c06b..877f6a8ff5 100644 --- a/src/status_im2/contexts/wallet/send/select_address/view.cljs +++ b/src/status_im2/contexts/wallet/send/select_address/view.cljs @@ -4,7 +4,6 @@ [quo.foundations.colors :as colors] [quo.theme :as quo.theme] [react-native.core :as rn] - [react-native.safe-area :as safe-area] [reagent.core :as reagent] [status-im2.constants :as constants] [status-im2.contexts.wallet.common.account-switcher.view :as account-switcher] @@ -49,12 +48,11 @@ (fn [] (let [scanned-address (rf/sub [:wallet/scanned-address]) send-address (rf/sub [:wallet/send-address]) - valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?])] + valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?]) + chain-id (rf/sub [:chain-id]) + contacts (rf/sub [:contacts/active])] [quo/address-input - {:on-focus (fn [] - (when (empty? @input-value) - (rf/dispatch [:wallet/clean-local-suggestions])) - (reset! input-focused? true)) + {:on-focus #(reset! input-focused? true) :on-blur #(reset! input-focused? false) :on-scan (fn [] (rn/dismiss-keyboard!) @@ -62,22 +60,19 @@ :ens-regex constants/regx-ens :address-regex constants/regx-address :scanned-value (or send-address scanned-address) - :on-detect-ens #(debounce/debounce-and-dispatch - [:wallet/validate-ens %] - 300) :on-detect-address #(debounce/debounce-and-dispatch [:wallet/validate-address %] 300) + :on-detect-ens (fn [text cb] + (debounce/debounce-and-dispatch + [:wallet/find-ens text contacts chain-id cb] + 300)) :on-change-text (fn [text] - (let [starts-like-eth-address (re-matches - constants/regx-full-or-partial-address - text)] - (when-not (= scanned-address text) - (rf/dispatch [:wallet/clean-scanned-address])) - (if starts-like-eth-address - (rf/dispatch [:wallet/fetch-address-suggestions text]) - (rf/dispatch [:wallet/clean-local-suggestions])) - (reset! input-value text))) + (when-not (= scanned-address text) + (rf/dispatch [:wallet/clean-scanned-address])) + (when (empty? text) + (rf/dispatch [:wallet/clean-local-suggestions])) + (reset! input-value text)) :valid-ens-or-address? valid-ens-or-address?}]))) (defn- ens-linked-address @@ -90,8 +85,8 @@ ^{:key (str network)} [quo/text {:size :paragraph-2 - :style {:color (colors/resolve-color (:network-name network) theme)}} - (str (:short-name network) ":")]) + :style {:color (colors/resolve-color network theme)}} + (str (subs (name network) 0 3) ":")]) networks) [quo/text {:size :paragraph-2 @@ -101,14 +96,20 @@ (defn- suggestion-component [] - (fn [{:keys [type ens address accounts] :as local-suggestion} _ _ _] + (fn [{:keys [type ens address accounts primary-name public-key ens-name color] :as local-suggestion} _ + _ _] (let [props {:on-press (fn [] (let [address (if accounts (:address (first accounts)) address)] (when-not ens (rf/dispatch [:wallet/select-send-address address])))) :active-state? false}] (cond (= type types/saved-address) - [quo/saved-address (merge props {:user-props local-suggestion})] + [quo/saved-address + (merge props + {:user-props {:name primary-name + :address public-key + :ens ens-name + :customization-color color}})] (= type types/saved-contact-address) [quo/saved-contact-address (merge props local-suggestion)] (and (not ens) (= type types/address)) @@ -132,8 +133,7 @@ (defn- f-view-internal [] - (let [margin-top (safe-area/get-top) - selected-tab (reagent/atom (:id (first tabs-data))) + (let [selected-tab (reagent/atom (:id (first tabs-data))) on-close (fn [] (rf/dispatch [:wallet/clean-scanned-address]) (rf/dispatch [:wallet/clean-local-suggestions]) @@ -143,8 +143,12 @@ input-focused? (reagent/atom false)] (fn [] (let [valid-ens-or-address? (boolean (rf/sub [:wallet/valid-ens-or-address?]))] + (rn/use-effect (fn [] + (fn [] + (rf/dispatch [:wallet/clean-scanned-address]) + (rf/dispatch [:wallet/clean-local-suggestions])))) [rn/scroll-view - {:content-container-style (style/container margin-top) + {:content-container-style style/container :keyboard-should-persist-taps :handled :scroll-enabled false} [account-switcher/view {:on-press on-close}] @@ -168,10 +172,7 @@ :type :primary :disabled? (not valid-ens-or-address?) :container-style style/button - :on-press (fn [] - (rf/dispatch [:wallet/select-send-address @input-value]) - (rf/dispatch [:navigate-to-within-stack - [:wallet-select-asset :wallet-select-address]]))} + :on-press #(js/alert "Not implemented yet")} (i18n/label :t/continue)])] [:<> [quo/tabs diff --git a/src/status_im2/contexts/wallet/send/select_asset/view.cljs b/src/status_im2/contexts/wallet/send/select_asset/view.cljs index 984dda3338..1add54fb44 100644 --- a/src/status_im2/contexts/wallet/send/select_asset/view.cljs +++ b/src/status_im2/contexts/wallet/send/select_asset/view.cljs @@ -7,6 +7,7 @@ [react-native.core :as rn] [react-native.safe-area :as safe-area] [reagent.core :as reagent] + [status-im2.contexts.wallet.common.account-switcher.view :as account-switcher] [status-im2.contexts.wallet.send.select-asset.style :as style] [utils.i18n :as i18n] [utils.re-frame :as rf])) @@ -76,15 +77,7 @@ {:content-container-style {:flex 1} :keyboard-should-persist-taps :handled :scroll-enabled false} - [quo/page-nav - {:icon-name :i/arrow-left - :on-press on-close - :accessibility-label :top-bar - :right-side :account-switcher - :account-switcher {:customization-color :purple - :on-press #(js/alert "Not implemented yet") - :state :default - :emoji "🍑"}}] + [account-switcher/view {:on-press on-close}] [quo/text-combinations {:title (i18n/label :t/select-asset) :container-style style/title-container diff --git a/src/status_im2/navigation/screens.cljs b/src/status_im2/navigation/screens.cljs index b7049751ff..4cea065c2a 100644 --- a/src/status_im2/navigation/screens.cljs +++ b/src/status_im2/navigation/screens.cljs @@ -306,7 +306,8 @@ :component wallet-send-input-amount/view} {:name :wallet-select-address - :options {:modalPresentationStyle :overCurrentContext} + :options {:modalPresentationStyle :overCurrentContext + :insets {:top? true}} :component wallet-select-address/view} {:name :wallet-select-asset