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