* Add capability to register an address based on an ENS * update tests * Check for existing addresses using an ENS
This commit is contained in:
parent
7a6714eeb2
commit
3c6923963d
|
@ -0,0 +1,54 @@
|
|||
(ns status-im.contexts.wallet.accounts.add-account.address-to-watch.events
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.constants :as constants]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/ens-not-found
|
||||
(fn [{:keys [db]} _]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :add-address-to-watch :activity-state] :invalid-ens)
|
||||
(assoc-in [:wallet :ui :add-address-to-watch :validated-address] nil))}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/store-address-activity
|
||||
(fn [{:keys [db]} [address {:keys [hasActivity]}]]
|
||||
(let [registered-addresses (-> db :wallet :accounts keys set)
|
||||
address-already-registered? (registered-addresses address)]
|
||||
(if address-already-registered?
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :add-address-to-watch :activity-state]
|
||||
:address-already-registered)
|
||||
(assoc-in [:wallet :ui :add-address-to-watch :validated-address] nil))}
|
||||
(let [state (if hasActivity :has-activity :no-activity)]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :add-address-to-watch :activity-state] state)
|
||||
(assoc-in [:wallet :ui :add-address-to-watch :validated-address] address))})))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/clear-address-activity
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet :ui] dissoc :add-address-to-watch)}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/get-address-details
|
||||
(fn [{:keys [db]} [address-or-ens]]
|
||||
(let [request-params [constants/ethereum-mainnet-chain-id address-or-ens]
|
||||
ens? (string/includes? address-or-ens ".")]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :add-address-to-watch :activity-state] :scanning)
|
||||
(assoc-in [:wallet :ui :add-address-to-watch :validated-address] nil))
|
||||
:fx [(if ens?
|
||||
[:json-rpc/call
|
||||
[{:method "ens_addressOf"
|
||||
:params request-params
|
||||
:on-success [:wallet/get-address-details]
|
||||
:on-error [:wallet/ens-not-found]}]]
|
||||
[:json-rpc/call
|
||||
[{:method "wallet_getAddressDetails"
|
||||
:params request-params
|
||||
:on-success [:wallet/store-address-activity address-or-ens]
|
||||
:on-error #(log/info "failed to get address details"
|
||||
{:error %
|
||||
:event :wallet/get-address-details})}]])]})))
|
|
@ -8,22 +8,22 @@
|
|||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.contexts.wallet.add-address-to-watch.style :as style]
|
||||
[status-im.contexts.wallet.common.validation :as validation]
|
||||
[status-im.subs.wallet.add-account.address-to-watch]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn validate-message
|
||||
[addresses]
|
||||
(fn [s]
|
||||
(cond
|
||||
(or (= s nil) (= s "")) nil
|
||||
(contains? addresses s) (i18n/label :t/address-already-in-use)
|
||||
(not (or (validation/eth-address? s)
|
||||
(validation/ens-name? s))) (i18n/label :t/invalid-address)
|
||||
:else nil)))
|
||||
(defn- validate-address
|
||||
[known-addresses user-input]
|
||||
(cond
|
||||
(or (nil? user-input) (= user-input "")) nil
|
||||
(contains? known-addresses user-input) (i18n/label :t/address-already-in-use)
|
||||
(not
|
||||
(or (validation/eth-address? user-input)
|
||||
(validation/ens-name? user-input))) (i18n/label :t/invalid-address)))
|
||||
|
||||
(defn- address-input
|
||||
[{:keys [input-value validation-msg validate
|
||||
clear-input]}]
|
||||
[{:keys [input-value validation-msg validate clear-input]}]
|
||||
(let [scanned-address (rf/sub [:wallet/scanned-address])
|
||||
empty-input? (and (string/blank? @input-value)
|
||||
(string/blank? scanned-address))
|
||||
|
@ -32,10 +32,11 @@
|
|||
(reset! input-value new-text)
|
||||
(reagent/flush)
|
||||
(if (and (not-empty new-text) (nil? (validate new-text)))
|
||||
(rf/dispatch [:wallet/get-address-details new-text])
|
||||
(rf/dispatch [:wallet/clear-address-activity-check]))
|
||||
(debounce/debounce-and-dispatch [:wallet/get-address-details new-text]
|
||||
500)
|
||||
(rf/dispatch [:wallet/clear-address-activity]))
|
||||
(when (and scanned-address (not= scanned-address new-text))
|
||||
(rf/dispatch [:wallet/clear-address-activity-check])
|
||||
(rf/dispatch [:wallet/clear-address-activity])
|
||||
(rf/dispatch [:wallet/clean-scanned-address])))
|
||||
paste-on-input #(clipboard/get-string
|
||||
(fn [clipboard-text]
|
||||
|
@ -44,8 +45,7 @@
|
|||
(when-not (string/blank? scanned-address)
|
||||
(on-change-text scanned-address)))
|
||||
[scanned-address])
|
||||
[rn/view
|
||||
{:style style/input-container}
|
||||
[rn/view {:style style/input-container}
|
||||
[quo/input
|
||||
{:accessibility-label :add-address-to-watch
|
||||
:placeholder (i18n/label :t/address-placeholder)
|
||||
|
@ -72,84 +72,92 @@
|
|||
:i/scan]]))
|
||||
|
||||
(defn activity-indicator
|
||||
[]
|
||||
(let [activity-state (rf/sub [:wallet/watch-address-activity-state])
|
||||
{:keys [accessibility-label icon type message]}
|
||||
(case activity-state
|
||||
:has-activity {:accessibility-label :account-has-activity
|
||||
:icon :i/done
|
||||
:type :success
|
||||
:message :t/this-address-has-activity}
|
||||
:no-activity {:accessibility-label :account-has-no-activity
|
||||
:icon :i/info
|
||||
:type :warning
|
||||
:message :t/this-address-has-no-activity}
|
||||
{:accessibility-label :searching-for-activity
|
||||
:icon :i/pending-state
|
||||
:type :default
|
||||
:message :t/searching-for-activity})]
|
||||
[activity-state]
|
||||
(let [{:keys [message]
|
||||
:as props} (case activity-state
|
||||
:has-activity {:accessibility-label :account-has-activity
|
||||
:icon :i/done
|
||||
:type :success
|
||||
:message :t/this-address-has-activity}
|
||||
:no-activity {:accessibility-label :account-has-no-activity
|
||||
:icon :i/info
|
||||
:type :warning
|
||||
:message :t/this-address-has-no-activity}
|
||||
:invalid-ens {:accessibility-label :error-message
|
||||
:icon :i/info
|
||||
:type :error
|
||||
:message :t/invalid-address}
|
||||
:address-already-registered {:accessibility-label :error-message
|
||||
:icon :i/info
|
||||
:type :error
|
||||
:message :t/address-already-in-use}
|
||||
{:accessibility-label :searching-for-activity
|
||||
:icon :i/pending-state
|
||||
:type :default
|
||||
:message :t/searching-for-activity})]
|
||||
(when activity-state
|
||||
[quo/info-message
|
||||
{:accessibility-label accessibility-label
|
||||
:size :default
|
||||
:icon icon
|
||||
:type type
|
||||
:style style/info-message}
|
||||
(assoc props
|
||||
:style style/info-message
|
||||
:size :default)
|
||||
(i18n/label message)])))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [addresses (rf/sub [:wallet/addresses])
|
||||
input-value (reagent/atom nil)
|
||||
validate (validate-message (set addresses))
|
||||
validation-msg (reagent/atom (validate
|
||||
@input-value))
|
||||
validate #(validate-address (set addresses) %)
|
||||
validation-msg (reagent/atom nil)
|
||||
clear-input (fn []
|
||||
(reset! input-value nil)
|
||||
(reset! validation-msg nil)
|
||||
(rf/dispatch [:wallet/clear-address-activity-check])
|
||||
(rf/dispatch [:wallet/clear-address-activity])
|
||||
(rf/dispatch [:wallet/clean-scanned-address]))
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
(rf/dispatch [:wallet/clean-scanned-address])
|
||||
(rf/dispatch [:wallet/clear-address-activity-check])
|
||||
(rf/dispatch [:wallet/clear-address-activity])
|
||||
(fn []
|
||||
[rn/view
|
||||
{:style {:flex 1}}
|
||||
[floating-button-page/view
|
||||
{:header [quo/page-nav
|
||||
{:type :no-title
|
||||
:icon-name :i/close
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:wallet/clean-scanned-address])
|
||||
(rf/dispatch [:wallet/clear-address-activity-check])
|
||||
(rf/dispatch [:navigate-back]))}]
|
||||
:footer [quo/button
|
||||
{:customization-color customization-color
|
||||
:disabled? (or (string/blank? @input-value)
|
||||
(some? (validate @input-value)))
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:navigate-to
|
||||
:confirm-address-to-watch
|
||||
{:address @input-value}])
|
||||
(clear-input))
|
||||
:container-style {:z-index 2}}
|
||||
(i18n/label :t/continue)]}
|
||||
[quo/page-top
|
||||
{:container-style style/header-container
|
||||
:title (i18n/label :t/add-address)
|
||||
:description :text
|
||||
:description-text (i18n/label :t/enter-eth)}]
|
||||
[:f> address-input
|
||||
{:input-value input-value
|
||||
:validate validate
|
||||
:validation-msg validation-msg
|
||||
:clear-input clear-input}]
|
||||
(when @validation-msg
|
||||
[quo/info-message
|
||||
{:accessibility-label :error-message
|
||||
:size :default
|
||||
:icon :i/info
|
||||
:type :error
|
||||
:style style/info-message}
|
||||
@validation-msg])
|
||||
[activity-indicator]]])))
|
||||
(let [activity-state (rf/sub [:wallet/watch-address-activity-state])
|
||||
validated-address (rf/sub [:wallet/watch-address-validated-address])]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[floating-button-page/view
|
||||
{:header [quo/page-nav
|
||||
{:type :no-title
|
||||
:icon-name :i/close
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:wallet/clean-scanned-address])
|
||||
(rf/dispatch [:wallet/clear-address-activity])
|
||||
(rf/dispatch [:navigate-back]))}]
|
||||
:footer [quo/button
|
||||
{:customization-color customization-color
|
||||
:disabled? (or (string/blank? @input-value)
|
||||
(some? (validate @input-value))
|
||||
(= activity-state :invalid-ens)
|
||||
(= activity-state :scanning)
|
||||
(not validated-address))
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:navigate-to
|
||||
:confirm-address-to-watch
|
||||
{:address validated-address}])
|
||||
(clear-input))
|
||||
:container-style {:z-index 2}}
|
||||
(i18n/label :t/continue)]}
|
||||
[quo/page-top
|
||||
{:container-style style/header-container
|
||||
:title (i18n/label :t/add-address)
|
||||
:description :text
|
||||
:description-text (i18n/label :t/enter-eth)}]
|
||||
[:f> address-input
|
||||
{:input-value input-value
|
||||
:validate validate
|
||||
:validation-msg validation-msg
|
||||
:clear-input clear-input}]
|
||||
(if @validation-msg
|
||||
[quo/info-message
|
||||
{:accessibility-label :error-message
|
||||
:size :default
|
||||
:icon :i/info
|
||||
:type :error
|
||||
:style style/info-message}
|
||||
@validation-msg]
|
||||
[activity-indicator activity-state])]]))))
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
[react-native.background-timer :as background-timer]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.accounts.add-account.address-to-watch.events]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.data-store :as data-store]
|
||||
[status-im.contexts.wallet.events.collectibles]
|
||||
[status-im.contexts.wallet.item-types :as item-types]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.collection]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.number]
|
||||
|
@ -360,27 +360,6 @@
|
|||
(fn [{:keys [db]}]
|
||||
{:db (assoc db :wallet/valid-ens-or-address? false)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/get-address-details-success
|
||||
(fn [{:keys [db]} [{:keys [hasActivity]}]]
|
||||
{:db (assoc-in db
|
||||
[:wallet :ui :watch-address-activity-state]
|
||||
(if hasActivity :has-activity :no-activity))}))
|
||||
|
||||
(rf/reg-event-fx :wallet/clear-address-activity-check
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet :ui] dissoc :watch-address-activity-state)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/get-address-details
|
||||
(fn [{:keys [db]} [address]]
|
||||
{:db (assoc-in db [:wallet :ui :watch-address-activity-state] :scanning)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wallet_getAddressDetails"
|
||||
:params [(chain/chain-id db) address]
|
||||
:on-success [:wallet/get-address-details-success]
|
||||
:on-error #(log/info "failed to get address details"
|
||||
{:error %
|
||||
:event :wallet/get-address-details})}]]]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/navigate-to-chain-explorer-from-bottom-sheet
|
||||
(fn [_ [explorer-link address]]
|
||||
|
|
|
@ -115,16 +115,15 @@
|
|||
|
||||
(defn- local-suggestions-list
|
||||
[]
|
||||
(fn []
|
||||
(let [local-suggestion (rf/sub [:wallet/local-suggestions])]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[rn/flat-list
|
||||
{:data local-suggestion
|
||||
:content-container-style {:flex-grow 1}
|
||||
:key-fn :id
|
||||
:on-scroll-to-index-failed identity
|
||||
:keyboard-should-persist-taps :handled
|
||||
:render-fn suggestion-component}]])))
|
||||
(let [local-suggestion (rf/sub [:wallet/local-suggestions])]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[rn/flat-list
|
||||
{:data local-suggestion
|
||||
:content-container-style {:flex-grow 1}
|
||||
:key-fn :id
|
||||
:on-scroll-to-index-failed identity
|
||||
:keyboard-should-persist-taps :handled
|
||||
:render-fn suggestion-component}]]))
|
||||
|
||||
(defn- f-view
|
||||
[]
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
(ns status-im.subs.wallet.add-account.address-to-watch
|
||||
(:require [re-frame.core :as rf]))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/add-address-to-watch
|
||||
:<- [:wallet/ui]
|
||||
:-> :add-address-to-watch)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/watch-address-activity-state
|
||||
:<- [:wallet/add-address-to-watch]
|
||||
:-> :activity-state)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/watch-address-validated-address
|
||||
:<- [:wallet/add-address-to-watch]
|
||||
:-> :validated-address)
|
|
@ -2,6 +2,7 @@
|
|||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as rf]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.subs.wallet.add-account.address-to-watch]
|
||||
[utils.number]))
|
||||
|
||||
(defn- filter-networks
|
||||
|
@ -93,11 +94,6 @@
|
|||
:<- [:wallet/wallet-send]
|
||||
:-> :bridge-to-chain-id)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/watch-address-activity-state
|
||||
:<- [:wallet/ui]
|
||||
:-> :watch-address-activity-state)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/keypairs
|
||||
:<- [:wallet]
|
||||
|
|
|
@ -296,12 +296,16 @@
|
|||
(is (nil? (rf/sub [sub-name]))))
|
||||
|
||||
(testing "watch address activity state with no-activity value"
|
||||
(swap! rf-db/app-db #(assoc-in % [:wallet :ui :watch-address-activity-state] :no-activity))
|
||||
(swap! rf-db/app-db #(assoc-in % [:wallet :ui :add-address-to-watch :activity-state] :no-activity))
|
||||
(is (match? :no-activity (rf/sub [sub-name]))))
|
||||
|
||||
(testing "watch address activity state with has-activity value"
|
||||
(swap! rf-db/app-db #(assoc-in % [:wallet :ui :watch-address-activity-state] :has-activity))
|
||||
(is (match? :has-activity (rf/sub [sub-name])))))
|
||||
(swap! rf-db/app-db #(assoc-in % [:wallet :ui :add-address-to-watch :activity-state] :has-activity))
|
||||
(is (match? :has-activity (rf/sub [sub-name]))))
|
||||
|
||||
(testing "watch address activity state with invalid-ens value"
|
||||
(swap! rf-db/app-db #(assoc-in % [:wallet :ui :add-address-to-watch :activity-state] :invalid-ens))
|
||||
(is (match? :invalid-ens (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/accounts-without-current-viewing-account
|
||||
[sub-name]
|
||||
|
|
Loading…
Reference in New Issue