diff --git a/src/quo/components/gradient/gradient_cover/view.cljs b/src/quo/components/gradient/gradient_cover/view.cljs index d038cf1475..2fd86951fd 100644 --- a/src/quo/components/gradient/gradient_cover/view.cljs +++ b/src/quo/components/gradient/gradient_cover/view.cljs @@ -6,14 +6,21 @@ [react-native.linear-gradient :as linear-gradient])) (defn- view-internal - [{:keys [customization-color opacity container-style height] :or {customization-color :blue}}] - (let [color-top (colors/custom-color customization-color 50 20) - color-bottom (colors/custom-color customization-color 50 0)] - [linear-gradient/linear-gradient - {:accessibility-label :gradient-cover - :colors [color-top color-bottom] - :start {:x 0 :y 0} - :end {:x 0 :y 1} - :style (merge (style/root-container opacity height) container-style)}])) + [{:keys [customization-color opacity container-style height] + :or {customization-color :blue}}] + ;; `when` added for safety, `linear-gradient` will break if `nil` is passed, + ;; the `:or` destructuring won't work because it's only applied when the + ;; `:customization-color` key is non-existent. While deleting an account the key exists + ;; and has a `nil` value. + (when customization-color + (let [color-top (colors/resolve-color customization-color 50 20) + color-bottom (colors/resolve-color customization-color 50 0)] + [linear-gradient/linear-gradient + {:accessibility-label :gradient-cover + :colors [color-top color-bottom] + :start {:x 0 :y 0} + :end {:x 0 :y 1} + :style (merge (style/root-container opacity height) + container-style)}]))) (def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im/config.cljs b/src/status_im/config.cljs index 71a3458ce0..2043934a52 100644 --- a/src/status_im/config.cljs +++ b/src/status_im/config.cljs @@ -172,4 +172,5 @@ (def wallet-feature-flags {:edit-default-keypair false - :bridge-token false}) + :bridge-token false + :remove-account false}) diff --git a/src/status_im/contexts/wallet/common/sheets/account_options/view.cljs b/src/status_im/contexts/wallet/common/sheets/account_options/view.cljs index 320b2aa30b..9de634a3bc 100644 --- a/src/status_im/contexts/wallet/common/sheets/account_options/view.cljs +++ b/src/status_im/contexts/wallet/common/sheets/account_options/view.cljs @@ -9,6 +9,7 @@ [react-native.gesture :as gesture] [react-native.platform :as platform] [reagent.core :as reagent] + [status-im.config :as config] [status-im.contexts.wallet.common.sheets.account-options.style :as style] [status-im.contexts.wallet.common.sheets.remove-account.view :as remove-account] [status-im.contexts.wallet.common.utils :as utils] @@ -32,12 +33,13 @@ (defn- options [{:keys [theme show-account-selector? options-height]}] - (let [{:keys [name color emoji address watch-only?]} (rf/sub [:wallet/current-viewing-account]) - network-preference-details (rf/sub [:wallet/network-preference-details]) - multichain-address (utils/get-multichain-address - network-preference-details - address) - share-title (str name " " (i18n/label :t/address))] + (let [{:keys [name color emoji address watch-only? + default-account?]} (rf/sub [:wallet/current-viewing-account]) + network-preference-details (rf/sub [:wallet/network-preference-details]) + multichain-address (utils/get-multichain-address + network-preference-details + address) + share-title (i18n/label :t/share-address-title {:address name})] [rn/view {:on-layout #(reset! options-height (oops/oget % "nativeEvent.layout.height")) :style (when show-account-selector? style/options-container)} @@ -92,15 +94,19 @@ #(rf/dispatch [:wallet/share-account {:title share-title :content multichain-address}]) 600))} - {:add-divider? (not show-account-selector?) - :icon :i/delete - :accessibility-label :remove-account - :label (i18n/label :t/remove-account) - :danger? true - :on-press #(rf/dispatch [:show-bottom-sheet - {:content - (fn [] - [remove-account/view])}])}]]] + (when-not default-account? + {:add-divider? (not show-account-selector?) + :icon :i/delete + :accessibility-label :remove-account + :label (i18n/label :t/remove-account) + :danger? true + :on-press (fn [] + (if (:remove-account config/wallet-feature-flags) + (rf/dispatch [:show-bottom-sheet + {:content + (fn [] + [remove-account/view])}]) + (js/alert "Feature disabled in config file")))})]]] (when show-account-selector? [:<> [quo/divider-line {:container-style style/divider-label}] diff --git a/src/status_im/contexts/wallet/common/sheets/remove_account/view.cljs b/src/status_im/contexts/wallet/common/sheets/remove_account/view.cljs index 761ce0f6e2..a9d086ce13 100644 --- a/src/status_im/contexts/wallet/common/sheets/remove_account/view.cljs +++ b/src/status_im/contexts/wallet/common/sheets/remove_account/view.cljs @@ -11,13 +11,17 @@ [utils.re-frame :as rf])) (defn- footer - [{:keys [submit-disabled?]}] + [{:keys [address submit-disabled? toast-message]}] [quo/bottom-actions {:actions :2-actions :customization-color :danger :button-one-label (i18n/label :t/remove) - :button-one-props {:on-press #(js/alert "Will be implemented") - :type :danger + :button-one-props {:on-press + (fn [] + (rf/dispatch [:wallet/remove-account + {:address address + :toast-message toast-message}])) + :type :danger :disabled? submit-disabled?} :button-two-label (i18n/label :t/cancel) :button-two-props {:on-press #(rf/dispatch [:hide-bottom-sheet]) @@ -26,7 +30,7 @@ (defn- recovery-phase-flow [] (let [confirmed? (reagent/atom false)] - (fn [{:keys [name emoji path color] :as _account}] + (fn [{:keys [address name emoji path color] :as _account}] (let [formatted-path (utils/format-derivation-path path)] [:<> [quo/drawer-top @@ -64,10 +68,13 @@ :checked? @confirmed? :on-change #(swap! confirmed? not)}] [quo/text (i18n/label :t/remove-account-confirmation)]] - [footer {:submit-disabled? (not @confirmed?)}]])))) + [footer + {:submit-disabled? (not @confirmed?) + :address address + :toast-message (i18n/label :t/account-removed)}]])))) (defn- watched-address-flow - [{:keys [name emoji color] :as _account}] + [{:keys [address name emoji color] :as _account}] [:<> [quo/drawer-top {:title (i18n/label :t/remove-watched-address-title) @@ -79,13 +86,17 @@ [rn/view {:style style/desc-container} [quo/text {:weight :medium} (i18n/label :t/remove-watched-address-desc)]] - [footer {:submit-disabled? false}]]) + [footer + {:submit-disabled? false + :address address + :toast-message (i18n/label :t/watched-account-removed)}]]) (defn- view-internal [] (let [{:keys [type] :as account} (rf/sub [:wallet/current-viewing-account])] (case type :generated [recovery-phase-flow account] - :watch [watched-address-flow account]))) + :watch [watched-address-flow account] + nil))) (def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im/contexts/wallet/data_store.cljs b/src/status_im/contexts/wallet/data_store.cljs index fe582d0c07..3e8b721705 100644 --- a/src/status_im/contexts/wallet/data_store.cljs +++ b/src/status_im/contexts/wallet/data_store.cljs @@ -33,6 +33,7 @@ (update :test-preferred-chain-ids chain-ids-string->set) (update :type keyword) (update :color #(if (seq %) (keyword %) constants/account-default-customization-color)) + (assoc :default-account? (:wallet account)) add-keys-to-account)) (defn rpc->accounts @@ -49,7 +50,8 @@ :color :colorId}) (update :prodPreferredChainIds chain-ids-set->string) (update :testPreferredChainIds chain-ids-set->string) - (dissoc :watch-only?))) + (dissoc :watch-only?) + (dissoc :default-account?))) (defn- rpc->balances-per-chain [token] diff --git a/src/status_im/contexts/wallet/edit_account/view.cljs b/src/status_im/contexts/wallet/edit_account/view.cljs index dafcf1764f..48bc343fa0 100644 --- a/src/status_im/contexts/wallet/edit_account/view.cljs +++ b/src/status_im/contexts/wallet/edit_account/view.cljs @@ -2,6 +2,7 @@ (:require [quo.core :as quo] [react-native.core :as rn] [reagent.core :as reagent] + [status-im.config :as config] [status-im.contexts.wallet.common.screen-base.create-or-edit-account.view :as create-or-edit-account] [status-im.contexts.wallet.common.sheets.network-preferences.view @@ -51,7 +52,7 @@ :updated-key :name :new-value @edited-account-name}))] (fn [] - (let [{:keys [name emoji address color watch-only?] + (let [{:keys [name emoji address color watch-only? default-account?] :as account} (rf/sub [:wallet/current-viewing-account]) network-details (rf/sub [:wallet/network-preference-details]) test-networks-enabled? (rf/sub [:profile/test-networks-enabled?]) @@ -62,13 +63,16 @@ button-disabled? (or (nil? @edited-account-name) (= name @edited-account-name))] [create-or-edit-account/view - {:page-nav-right-side [{:icon-name :i/delete - :on-press - (fn [] - (rf/dispatch [:show-bottom-sheet - {:content - (fn [] - [remove-account/view])}]))}] + {:page-nav-right-side [(when-not default-account? + {:icon-name :i/delete + :on-press + (fn [] + (if (:remove-account config/wallet-feature-flags) + (rf/dispatch [:show-bottom-sheet + {:content + (fn [] + [remove-account/view])}]) + (js/alert "Feature disabled in config file")))})] :account-name account-name :account-emoji emoji :account-color color diff --git a/src/status_im/contexts/wallet/events.cljs b/src/status_im/contexts/wallet/events.cljs index 4afae116a2..5c856ff7da 100644 --- a/src/status_im/contexts/wallet/events.cljs +++ b/src/status_im/contexts/wallet/events.cljs @@ -7,6 +7,7 @@ [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] @@ -51,10 +52,9 @@ wallet-db (get db :wallet) new-account? (:new-account? wallet-db) navigate-to-account (:navigate-to-account wallet-db)] - {:db (reduce (fn [db {:keys [address] :as account}] - (assoc-in db [:wallet :accounts address] account)) - db - (data-store/rpc->accounts wallet-accounts)) + {:db (assoc-in db + [:wallet :accounts] + (utils.collection/index-by :address (data-store/rpc->accounts wallet-accounts))) :fx [[:dispatch [:wallet/get-wallet-token]] [:dispatch [:wallet/request-collectibles {:start-at-index 0 :new-request? true}]] (when new-account? @@ -84,6 +84,30 @@ {:error % :event :wallet/save-account})}]]]})) +(rf/reg-event-fx + :wallet/show-account-deleted-toast + (fn [_ [toast-message]] + {:fx [[:dispatch [:toasts/upsert {:type :positive :text toast-message}]]]})) + +(rf/reg-event-fx + :wallet/remove-account-success + (fn [_ [toast-message _]] + {:fx [[:dispatch [:hide-bottom-sheet]] + [:dispatch [:pop-to-root :shell-stack]] + [:dispatch [:wallet/get-accounts]] + [:dispatch [:wallet/show-account-deleted-toast toast-message]]]})) + +(rf/reg-event-fx + :wallet/remove-account + (fn [_ [{:keys [address toast-message]}]] + {:fx [[:json-rpc/call + [{:method "accounts_deleteAccount" + :params [address] + :on-success [:wallet/remove-account-success toast-message] + :on-error #(log/info "failed to remove account " + {:error % + :event :wallet/remove-account})}]]]})) + (rf/reg-event-fx :wallet/get-wallet-token (fn [{:keys [db]}] @@ -133,10 +157,10 @@ (rf/reg-event-fx :wallet/create-derived-addresses (fn [{:keys [db]} [{:keys [sha3-pwd path]} on-success]] - (let [{:keys [wallet-root-address]} (:profile/profile db)] + (let [{:keys [address]} (:profile/profile db)] {:fx [[:json-rpc/call [{:method "wallet_getDerivedAddresses" - :params [sha3-pwd wallet-root-address [path]] + :params [sha3-pwd address [path]] :on-success on-success :on-error #(log/info "failed to derive address " %)}]]]}))) diff --git a/test/jest/jest.config.js b/test/jest/jest.config.js index 21d54e1b15..ac7bcc0d96 100644 --- a/test/jest/jest.config.js +++ b/test/jest/jest.config.js @@ -4,6 +4,7 @@ const transformIgnorePatterns = () => { '@react-native-community', '@react-native-community/blur', 'react-native', + 'react-native-config', 'react-native-background-timer', 'react-native-gifted-charts', 'react-native-haptic-feedback', diff --git a/translations/en.json b/translations/en.json index 7f54db4d0b..b14dce16f3 100644 --- a/translations/en.json +++ b/translations/en.json @@ -2483,5 +2483,8 @@ "not-preferred-by-receiver": "Not preferred by receiver", "apply-changes": "Apply changes", "receiver-networks-warning": "Changing these settings may result in sending tokens to networks the recipient doesn't use", - "no-routes-found-confirmation": "No routes found. Token type may not be supported or you may don't have enough ETH to cover gas." + "no-routes-found-confirmation": "No routes found. Token type may not be supported or you may don't have enough ETH to cover gas.", + "watched-account-removed": "Watched address has been removed", + "account-removed": "Account has been removed", + "share-address-title": "{{address}} address" }