feat(wallet): Add a new saved address with ENS (#20384)
This commit adds a feature to add new saved addresses with ENS Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
This commit is contained in:
parent
cedd4900d5
commit
a3e713bbf0
|
@ -8,6 +8,7 @@
|
|||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.contexts.settings.wallet.saved-addresses.add-address-to-save.style :as style]
|
||||
[status-im.contexts.wallet.common.validation :as validation]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -18,7 +19,7 @@
|
|||
(defn- validate-input
|
||||
[account-addresses saved-addresses user-input]
|
||||
(cond
|
||||
(or (nil? user-input) (= user-input ""))
|
||||
(string/blank? user-input)
|
||||
nil
|
||||
|
||||
(contains? saved-addresses user-input)
|
||||
|
@ -89,7 +90,7 @@
|
|||
|
||||
(defn- existing-saved-address
|
||||
[{:keys [address]}]
|
||||
(let [{:keys [name customization-color chain-short-names ens has-ens?]}
|
||||
(let [{:keys [name customization-color chain-short-names ens ens?]}
|
||||
(rf/sub [:wallet/saved-address-by-address
|
||||
address])]
|
||||
[rn/view {:style style/existing-saved-address-container}
|
||||
|
@ -103,43 +104,65 @@
|
|||
:active-state? true
|
||||
:user-props {:name name
|
||||
:address (str chain-short-names address)
|
||||
:ens (when has-ens? ens)
|
||||
:ens (when ens? ens)
|
||||
:customization-color customization-color
|
||||
:blur? true}
|
||||
:container-style style/saved-address-item}]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [profile-color (rf/sub [:profile/customization-color])
|
||||
accounts-addresses (rf/sub [:wallet/addresses])
|
||||
saved-addresses-addresses (rf/sub [:wallet/saved-addresses-addresses])
|
||||
[input-value set-input-value] (rn/use-state nil)
|
||||
[error set-error] (rn/use-state nil)
|
||||
error? (some? error)
|
||||
validate #(validate-input accounts-addresses
|
||||
saved-addresses-addresses
|
||||
%)
|
||||
clear-input (rn/use-callback
|
||||
(fn []
|
||||
(set-input-value nil)
|
||||
(set-error nil)))
|
||||
on-change-text (rn/use-callback
|
||||
(fn [new-value]
|
||||
(let [lowercase-value (string/lower-case new-value)]
|
||||
(set-error (validate lowercase-value))
|
||||
(set-input-value lowercase-value))))
|
||||
paste-into-input (rn/use-callback #(clipboard/get-string
|
||||
(fn [clipboard-text]
|
||||
(on-change-text clipboard-text))))
|
||||
on-press-continue (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:wallet/set-address-to-save
|
||||
{:address input-value}])
|
||||
(rf/dispatch
|
||||
[:navigate-to-within-stack
|
||||
[:screen/settings.save-address
|
||||
:screen/settings.add-address-to-save]]))
|
||||
[input-value])]
|
||||
(let [profile-color (rf/sub [:profile/customization-color])
|
||||
accounts-addresses (rf/sub [:wallet/addresses])
|
||||
saved-addresses-addresses (rf/sub [:wallet/saved-addresses-addresses])
|
||||
[address-or-ens set-address-or-ens] (rn/use-state "")
|
||||
[ens-address set-ens-address] (rn/use-state "")
|
||||
[error set-error] (rn/use-state nil)
|
||||
error? (some? error)
|
||||
ens-name? (validation/ens-name? address-or-ens)
|
||||
address (if ens-name? ens-address address-or-ens)
|
||||
button-disabled? (or (string/blank? address-or-ens)
|
||||
(and ens-name? (string/blank? ens-address))
|
||||
error?)
|
||||
validate #(validate-input accounts-addresses
|
||||
saved-addresses-addresses
|
||||
%)
|
||||
clear-input (rn/use-callback
|
||||
(fn []
|
||||
(set-address-or-ens "")
|
||||
(set-ens-address "")
|
||||
(set-error nil)))
|
||||
on-ens-resolve (rn/use-callback
|
||||
(fn [resolved-address]
|
||||
(set-error (validate resolved-address))
|
||||
(set-ens-address resolved-address)))
|
||||
on-change-text (rn/use-callback
|
||||
(fn [new-value]
|
||||
(let [trimmed-value (string/trim new-value)]
|
||||
(set-error (validate (string/lower-case trimmed-value)))
|
||||
(set-address-or-ens trimmed-value)
|
||||
(set-ens-address "")
|
||||
(when (validation/ens-name? trimmed-value)
|
||||
(debounce/debounce-and-dispatch
|
||||
[:wallet/resolve-ens
|
||||
{:ens new-value
|
||||
:on-success on-ens-resolve
|
||||
:on-error #(set-error :ens-not-registered)}]
|
||||
300)))))
|
||||
paste-into-input (rn/use-callback #(clipboard/get-string
|
||||
(fn [clipboard-text]
|
||||
(on-change-text clipboard-text))))
|
||||
on-press-continue (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch
|
||||
[:wallet/set-address-to-save
|
||||
{:address address
|
||||
:ens address-or-ens
|
||||
:ens? ens-name?}])
|
||||
(rf/dispatch
|
||||
[:navigate-to-within-stack
|
||||
[:screen/settings.save-address
|
||||
:screen/settings.add-address-to-save]]))
|
||||
[address ens-name? address-or-ens])]
|
||||
(rn/use-unmount #(rf/dispatch [:wallet/clear-address-to-save]))
|
||||
[quo/overlay {:type :shell}
|
||||
[floating-button-page/view
|
||||
|
@ -153,8 +176,7 @@
|
|||
:accessibility-label :add-address-to-save-page-nav}]
|
||||
:footer [quo/button
|
||||
{:customization-color profile-color
|
||||
:disabled? (or (string/blank? input-value)
|
||||
error?)
|
||||
:disabled? button-disabled?
|
||||
:on-press on-press-continue}
|
||||
(i18n/label :t/continue)]}
|
||||
[quo/page-top
|
||||
|
@ -164,7 +186,7 @@
|
|||
:description :text
|
||||
:description-text (i18n/label :t/add-address-to-save-description)}]
|
||||
[address-input
|
||||
{:input-value input-value
|
||||
{:input-value address-or-ens
|
||||
:on-change-text on-change-text
|
||||
:paste-into-input paste-into-input
|
||||
:clear-input clear-input}]
|
||||
|
@ -172,4 +194,4 @@
|
|||
[:<>
|
||||
[error-view {:error error}]
|
||||
(when (= error :existing-saved-address)
|
||||
[existing-saved-address {:address input-value}])])]]))
|
||||
[existing-saved-address {:address address}])])]]))
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
:address "0x2"
|
||||
:mixedcase-address "0x2"
|
||||
:chain-short-names "eth:arb1:oeth:"
|
||||
:has-ens? false
|
||||
:ens? false
|
||||
:network-preferences-names `(:mainnet :arbitrum :optimism)
|
||||
:name "Bob"
|
||||
:created-at 1716826714
|
||||
|
@ -75,7 +75,7 @@
|
|||
:mixedcase-address "0x2"
|
||||
:chain-short-names "eth:arb1:oeth:"
|
||||
:network-preferences-names `(:mainnet :arbitrum :optimism)
|
||||
:has-ens? false
|
||||
:ens? false
|
||||
:name "Bob"
|
||||
:created-at 1716826714
|
||||
:ens ""
|
||||
|
@ -86,7 +86,7 @@
|
|||
:mixedcase-address "0x1"
|
||||
:chain-short-names "eth:arb1:oeth:"
|
||||
:network-preferences-names `(:mainnet :arbitrum :optimism)
|
||||
:has-ens? false
|
||||
:ens? false
|
||||
:name "Amy"
|
||||
:created-at 1716826806
|
||||
:ens ""
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
(defn view
|
||||
[]
|
||||
(let [{:keys [address]} (rf/sub [:wallet/saved-address])
|
||||
(let [{:keys [address ens ens?]} (rf/sub [:wallet/saved-address])
|
||||
[network-prefixes address-without-prefix] (utils/split-prefix-and-address address)
|
||||
[address-label set-address-label] (rn/use-state "")
|
||||
[address-color set-address-color] (rn/use-state (rand-nth colors/account-colors))
|
||||
|
@ -46,6 +46,13 @@
|
|||
selected-networks)
|
||||
[selected-networks])
|
||||
placeholder (i18n/label :t/address-name)
|
||||
address-text (rn/use-callback
|
||||
(fn []
|
||||
[quo/address-text
|
||||
{:full-address? true
|
||||
:address (str chain-short-names address-without-prefix)
|
||||
:format :long}])
|
||||
[address-without-prefix chain-short-names])
|
||||
open-network-preferences (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch
|
||||
|
@ -68,11 +75,29 @@
|
|||
:on-error
|
||||
[:wallet/add-saved-address-failed]
|
||||
:name address-label
|
||||
:ens ens
|
||||
:address address-without-prefix
|
||||
:customization-color address-color
|
||||
:chain-short-names chain-short-names}]))
|
||||
[address-without-prefix chain-short-names address-label
|
||||
address-color])]
|
||||
address-color])
|
||||
data-item-props (rn/use-memo
|
||||
#(cond-> {:status :default
|
||||
:size :default
|
||||
:subtitle-type :default
|
||||
:label :none
|
||||
:blur? true
|
||||
:icon-right? true
|
||||
:right-icon :i/advanced
|
||||
:card? true
|
||||
:title (i18n/label :t/address)
|
||||
:subtitle ens
|
||||
:custom-subtitle address-text
|
||||
:on-press open-network-preferences
|
||||
:container-style style/data-item}
|
||||
ens?
|
||||
(dissoc :custom-subtitle))
|
||||
[ens ens? open-network-preferences address-text])]
|
||||
[quo/overlay {:type :shell}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
|
@ -125,22 +150,4 @@
|
|||
[quo/divider-line
|
||||
{:blur? true
|
||||
:container-style style/color-picker-bottom-divider}]
|
||||
[quo/data-item
|
||||
{:status :default
|
||||
:size :default
|
||||
:subtitle-type :default
|
||||
:label :none
|
||||
:blur? true
|
||||
:icon-right? true
|
||||
:right-icon :i/advanced
|
||||
:card? true
|
||||
:title (i18n/label :t/address)
|
||||
:custom-subtitle (rn/use-callback
|
||||
(fn []
|
||||
[quo/address-text
|
||||
{:full-address? true
|
||||
:address (str chain-short-names address-without-prefix)
|
||||
:format :long}])
|
||||
[selected-networks address])
|
||||
:on-press open-network-preferences
|
||||
:container-style style/data-item}]]]))
|
||||
[quo/data-item data-item-props]]]))
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
|
@ -52,10 +53,11 @@
|
|||
open-remove-confirmation-sheet (rn/use-callback
|
||||
#(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:content (fn []
|
||||
[remove-address/view opts])}])
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:blur-background colors/bottom-sheet-background-blur
|
||||
:content (fn []
|
||||
[remove-address/view opts])}])
|
||||
[opts])
|
||||
open-show-address-qr (rn/use-callback
|
||||
#(rf/dispatch [:open-modal
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.contexts.settings.wallet.saved-addresses.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
|
@ -20,27 +21,29 @@
|
|||
:container-style style/empty-container-style}]))
|
||||
|
||||
(defn- saved-address
|
||||
[{:keys [name address chain-short-names customization-color has-ens? ens network-preferences-names]}]
|
||||
[{:keys [name address chain-short-names customization-color ens? ens network-preferences-names]}]
|
||||
(let [full-address (str chain-short-names address)
|
||||
on-press-saved-address (rn/use-callback
|
||||
#(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:content (fn []
|
||||
[address-options/view
|
||||
{:address address
|
||||
:chain-short-names chain-short-names
|
||||
:full-address full-address
|
||||
:name name
|
||||
:network-preferences-names network-preferences-names
|
||||
:customization-color customization-color}])}])
|
||||
{:theme :dark
|
||||
:shell? true
|
||||
:blur-background colors/bottom-sheet-background-blur
|
||||
:content (fn []
|
||||
[address-options/view
|
||||
{:address address
|
||||
:chain-short-names chain-short-names
|
||||
:full-address full-address
|
||||
:name name
|
||||
:network-preferences-names
|
||||
network-preferences-names
|
||||
:customization-color customization-color}])}])
|
||||
[address chain-short-names full-address name customization-color])]
|
||||
[quo/saved-address
|
||||
{:blur? true
|
||||
:user-props {:name name
|
||||
:address full-address
|
||||
:ens (when has-ens? ens)
|
||||
:ens (when ens? ens)
|
||||
:customization-color customization-color
|
||||
:blur? true}
|
||||
:container-style {:margin-horizontal 8}
|
||||
|
@ -88,12 +91,13 @@
|
|||
:icon :i/add
|
||||
:container-style style/title-container}]
|
||||
[rn/section-list
|
||||
{:key-fn :title
|
||||
:sticky-section-headers-enabled false
|
||||
:render-section-header-fn header
|
||||
:render-section-footer-fn footer
|
||||
:sections saved-addresses
|
||||
:render-fn saved-address
|
||||
:separator [rn/view {:style {:height 4}}]
|
||||
:content-container-style {:flex-grow 1}
|
||||
:empty-component [empty-state]}]]))
|
||||
{:key-fn :title
|
||||
:shows-vertical-scroll-indicator false
|
||||
:sticky-section-headers-enabled false
|
||||
:render-section-header-fn header
|
||||
:render-section-footer-fn footer
|
||||
:sections saved-addresses
|
||||
:render-fn saved-address
|
||||
:separator [rn/view {:style {:height 4}}]
|
||||
:content-container-style {:flex-grow 1}
|
||||
:empty-component [empty-state]}]]))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(ns status-im.contexts.wallet.common.validation
|
||||
(:require [status-im.constants :as constants]))
|
||||
|
||||
(defn ens-name? [s] (re-find constants/regx-ens s))
|
||||
(defn ens-name? [s] (boolean (re-find constants/regx-ens s)))
|
||||
(defn eth-address? [s] (re-find constants/regx-multichain-address s))
|
||||
(defn private-key? [s] (re-find constants/regx-private-key s))
|
||||
|
|
|
@ -143,7 +143,7 @@
|
|||
(-> saved-address
|
||||
(assoc :network-preferences-names
|
||||
(network-utils/network-preference-prefix->network-names (:chain-short-names saved-address)))
|
||||
(assoc :has-ens? (not (string/blank? (:ens saved-address))))))
|
||||
(assoc :ens? (not (string/blank? (:ens saved-address))))))
|
||||
|
||||
(defn rpc->saved-address
|
||||
[saved-address]
|
||||
|
|
|
@ -526,3 +526,13 @@
|
|||
:on-error #(log/info "failed to fetch crypto on ramps"
|
||||
{:error %
|
||||
:event :wallet/get-crypto-on-ramps})}]]]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/resolve-ens
|
||||
(fn [{db :db} [{:keys [ens on-success on-error]}]]
|
||||
(let [chain-id (network-utils/network->chain-id db constants/mainnet-network-name)]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "ens_addressOf"
|
||||
:params [chain-id ens]
|
||||
:on-success on-success
|
||||
:on-error on-error}]]]})))
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
:address "0x1"
|
||||
:mixedcase-address "0x1"
|
||||
:chain-short-names "eth:arb1:oeth:"
|
||||
:has-ens? false
|
||||
:ens? false
|
||||
:network-preferences-names #{:arbitrum
|
||||
:optimism
|
||||
:mainnet}
|
||||
|
@ -22,7 +22,7 @@
|
|||
:address "0x2"
|
||||
:mixedcase-address "0x2"
|
||||
:chain-short-names "eth:"
|
||||
:has-ens? false
|
||||
:ens? false
|
||||
:network-preferences-names #{:mainnet}
|
||||
:name "Bob"
|
||||
:created-at 1716828825
|
||||
|
@ -33,7 +33,7 @@
|
|||
:address "0x1"
|
||||
:mixedcase-address "0x1"
|
||||
:chain-short-names "eth:"
|
||||
:has-ens? false
|
||||
:ens? false
|
||||
:network-preferences-names #{:mainnet}
|
||||
:name "Alice"
|
||||
:created-at 1716826745
|
||||
|
@ -44,7 +44,7 @@
|
|||
:address "0x2"
|
||||
:mixedcase-address "0x2"
|
||||
:chain-short-names "eth:arb1:oeth:"
|
||||
:has-ens? false
|
||||
:ens? false
|
||||
:network-preferences-names #{:arbitrum
|
||||
:optimism
|
||||
:mainnet}
|
||||
|
@ -61,7 +61,7 @@
|
|||
:address "0x1"
|
||||
:mixedcase-address "0x1"
|
||||
:chain-short-names "eth:"
|
||||
:has-ens? false
|
||||
:ens? false
|
||||
:network-preferences-names #{:mainnet}
|
||||
:name "Alice"
|
||||
:created-at 1716826745
|
||||
|
@ -74,7 +74,7 @@
|
|||
:address "0x2"
|
||||
:mixedcase-address "0x2"
|
||||
:chain-short-names "eth:arb1:oeth:"
|
||||
:has-ens? false
|
||||
:ens? false
|
||||
:network-preferences-names #{:arbitrum
|
||||
:optimism
|
||||
:mainnet}
|
||||
|
|
Loading…
Reference in New Issue