From 0581fc2f9db32a8424aa70a2693aa80a07913eb2 Mon Sep 17 00:00:00 2001 From: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:33:54 +0530 Subject: [PATCH] feat(wallet): sync saved addresses (#20546) This commit adds syncing saved addresses across paired devices whenever a new saved address is added or an existing one is edited or removed. Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com> --- .../messenger/messages/transport/events.cljs | 9 ++ .../wallet/saved_addresses/events.cljs | 55 ++++--- .../wallet/saved_addresses/events_test.cljs | 134 ++++++++++++++---- .../sheets/address_options/view.cljs | 2 +- src/status_im/contexts/wallet/data_store.cljs | 2 +- translations/en.json | 1 + 6 files changed, 152 insertions(+), 51 deletions(-) diff --git a/src/status_im/contexts/chat/messenger/messages/transport/events.cljs b/src/status_im/contexts/chat/messenger/messages/transport/events.cljs index 5eb56e4788..9416ae3769 100644 --- a/src/status_im/contexts/chat/messenger/messages/transport/events.cljs +++ b/src/status_im/contexts/chat/messenger/messages/transport/events.cljs @@ -21,6 +21,7 @@ [status-im.contexts.chat.messenger.messages.pin.events :as messages.pin] [status-im.contexts.communities.events :as communities] [status-im.contexts.shell.activity-center.events :as activity-center] + [status-im.contexts.wallet.data-store :as wallet.data-store] [taoensso.timbre :as log] [utils.re-frame :as rf])) @@ -56,6 +57,7 @@ ^js accounts (.-accounts response-js) ^js ens-username-details-js (.-ensUsernameDetails response-js) ^js customization-color-js (.-customizationColor response-js) + ^js saved-addresses-js (.-savedAddresses response-js) sync-handler (when-not process-async process-response)] (cond @@ -199,6 +201,13 @@ (models.visibility-status-updates/sync-visibility-status-update current-visibility-status-clj))) + (seq saved-addresses-js) + (let [saved-addresses (-> saved-addresses-js types/js->clj wallet.data-store/rpc->saved-addresses)] + (js-delete response-js "savedAddresses") + (rf/merge cofx + {:fx [[:dispatch [:wallet/reconcile-saved-addresses saved-addresses]]]} + (process-next response-js sync-handler))) + (seq ens-username-details-js) (let [ens-username-details-clj (types/js->clj ens-username-details-js)] (js-delete response-js "ensUsernameDetails") diff --git a/src/status_im/contexts/settings/wallet/saved_addresses/events.cljs b/src/status_im/contexts/settings/wallet/saved_addresses/events.cljs index 493e69d0aa..23e957fa92 100644 --- a/src/status_im/contexts/settings/wallet/saved_addresses/events.cljs +++ b/src/status_im/contexts/settings/wallet/saved_addresses/events.cljs @@ -23,15 +23,29 @@ (rf/reg-event-fx :wallet/save-address save-address) +(defn- update-saved-addresses + [saved-addresses-db new-saved-addresses] + (reduce + (fn [acc {:keys [address removed? test?] :as saved-address}] + (let [db-key (if test? :test :prod)] + (if removed? + (update acc db-key dissoc address) + (assoc-in acc [db-key address] saved-address)))) + (or saved-addresses-db + {:test {} + :prod {}}) + new-saved-addresses)) + +(defn reconcile-saved-addresses + [{:keys [db]} [saved-addresses]] + {:db (update-in db [:wallet :saved-addresses] update-saved-addresses saved-addresses)}) + +(rf/reg-event-fx :wallet/reconcile-saved-addresses reconcile-saved-addresses) + (defn get-saved-addresses-success - [{:keys [db]} [raw-saved-addresses]] - (let [saved-addresses (reduce - (fn [result {:keys [address test?] :as saved-address}] - (assoc-in result [(if test? :test :prod) address] saved-address)) - {:test {} - :prod {}} - (data-store/rpc->saved-addresses raw-saved-addresses))] - {:db (assoc-in db [:wallet :saved-addresses] saved-addresses)})) + [_ [raw-saved-addresses]] + (let [saved-addresses (data-store/rpc->saved-addresses raw-saved-addresses)] + {:fx [[:dispatch [:wallet/reconcile-saved-addresses saved-addresses]]]})) (rf/reg-event-fx :wallet/get-saved-addresses-success get-saved-addresses-success) @@ -52,15 +66,17 @@ (rf/reg-event-fx :wallet/get-saved-addresses get-saved-addresses) (defn delete-saved-address-success - [_ [toast-message]] - {:fx [[:dispatch [:wallet/get-saved-addresses]] - [:dispatch [:hide-bottom-sheet]] - [:dispatch-later - {:ms 100 - :dispatch [:toasts/upsert - {:type :positive - :theme :dark - :text toast-message}]}]]}) + [{:keys [db]} [{:keys [address test-networks-enabled? toast-message]}]] + (let [db-key (if test-networks-enabled? :test :prod) + saved-address (get-in db [:wallet :saved-addresses db-key address])] + {:fx [[:dispatch [:wallet/reconcile-saved-addresses [(assoc saved-address :removed? true)]]] + [:dispatch [:hide-bottom-sheet]] + [:dispatch-later + {:ms 100 + :dispatch [:toasts/upsert + {:type :positive + :theme :dark + :text toast-message}]}]]})) (rf/reg-event-fx :wallet/delete-saved-address-success delete-saved-address-success) @@ -82,7 +98,10 @@ {:fx [[:json-rpc/call [{:method "wakuext_deleteSavedAddress" :params [address test-networks-enabled?] - :on-success [:wallet/delete-saved-address-success toast-message] + :on-success [:wallet/delete-saved-address-success + {:address address + :test-networks-enabled? test-networks-enabled? + :toast-message toast-message}] :on-error [:wallet/delete-saved-address-failed]}]]]})) (rf/reg-event-fx :wallet/delete-saved-address delete-saved-address) diff --git a/src/status_im/contexts/settings/wallet/saved_addresses/events_test.cljs b/src/status_im/contexts/settings/wallet/saved_addresses/events_test.cljs index 1fc9a500b6..d6eff59260 100644 --- a/src/status_im/contexts/settings/wallet/saved_addresses/events_test.cljs +++ b/src/status_im/contexts/settings/wallet/saved_addresses/events_test.cljs @@ -2,7 +2,8 @@ (:require [cljs.test :refer-macros [deftest is testing]] matcher-combinators.test - [status-im.contexts.settings.wallet.saved-addresses.events :as events])) + [status-im.contexts.settings.wallet.saved-addresses.events :as events] + [status-im.contexts.wallet.data-store :as data-store])) (deftest get-saved-addresses-test (testing "get saved addresses - dispatches RPC call" @@ -15,7 +16,7 @@ :on-error [:wallet/saved-addresses-rpc-error :get-saved-addresses]}]]]] (is (match? expected-fx result-fx))))) -(def saved-address-1 +(def saved-address-rpc-1 {:isTest false :address "0x1" :mixedcaseAddress "0x1" @@ -26,21 +27,45 @@ :colorId "purple" :removed false}) +(def saved-address-1 + {:test? true + :address "0x1" + :mixedcase-address "0x1" + :chain-short-names "eth:oeth:" + :network-preferences-names `(:mainnet :optimism) + :name "Bob" + :created-at 1716826714 + :ens "" + :ens? false + :customization-color :blue + :removed? false}) + (def saved-address-2 - {:isTest true - :address "0x2" - :mixedcaseAddress "0x2" - :chainShortNames "eth:arb1:oeth:" - :name "Bob" - :createdAt 1716826714 - :ens "" - :colorId "blue" - :removed false}) + {:test? false + :address "0x2" + :mixedcase-address "0x2" + :chain-short-names "eth:arb1:oeth:" + :network-preferences-names `(:mainnet :arbitrum :optimism) + :name "Alicia Keys" + :created-at 1716826806 + :ens "alicia.eth" + :ens? true + :customization-color :purple + :removed? false}) (deftest get-saved-addresses-success-test + (let [cofx {:db {}} + raw-saved-addresses [saved-address-rpc-1] + effects (events/get-saved-addresses-success cofx [raw-saved-addresses]) + saved-addresses (data-store/rpc->saved-addresses raw-saved-addresses) + result-fx (:fx effects) + expected-fx [[:dispatch [:wallet/reconcile-saved-addresses saved-addresses]]]] + (is (match? expected-fx result-fx)))) + +(deftest reconcile-saved-addresses-test (testing "no saved addresses" (let [cofx {:db {}} - effects (events/get-saved-addresses-success cofx nil) + effects (events/reconcile-saved-addresses cofx nil) result-db (:db effects) expected-db {:wallet {:saved-addresses {:test {} :prod {}}}}] @@ -48,15 +73,15 @@ (testing "one test saved address" (let [cofx {:db {}} - effects (events/get-saved-addresses-success cofx [[saved-address-2]]) + effects (events/reconcile-saved-addresses cofx [[saved-address-1]]) result-db (:db effects) expected-db {:wallet {:saved-addresses - {:test {"0x2" {:test? true - :address "0x2" - :mixedcase-address "0x2" - :chain-short-names "eth:arb1:oeth:" + {:test {"0x1" {:test? true + :address "0x1" + :mixedcase-address "0x1" + :chain-short-names "eth:oeth:" :ens? false - :network-preferences-names `(:mainnet :arbitrum :optimism) + :network-preferences-names `(:mainnet :optimism) :name "Bob" :created-at 1716826714 :ens "" @@ -67,29 +92,73 @@ (testing "two saved addresses (test and prod)" (let [cofx {:db {}} - effects (events/get-saved-addresses-success cofx [[saved-address-1 saved-address-2]]) + effects (events/reconcile-saved-addresses cofx [[saved-address-1 saved-address-2]]) result-db (:db effects) expected-db {:wallet {:saved-addresses - {:test {"0x2" {:test? true - :address "0x2" - :mixedcase-address "0x2" - :chain-short-names "eth:arb1:oeth:" - :network-preferences-names `(:mainnet :arbitrum :optimism) + {:test {"0x1" {:test? true + :address "0x1" + :mixedcase-address "0x1" + :chain-short-names "eth:oeth:" :ens? false + :network-preferences-names `(:mainnet :optimism) :name "Bob" :created-at 1716826714 :ens "" :customization-color :blue :removed? false}} - :prod {"0x1" {:test? false - :address "0x1" - :mixedcase-address "0x1" + :prod {"0x2" {:test? false + :address "0x2" + :mixedcase-address "0x2" :chain-short-names "eth:arb1:oeth:" :network-preferences-names `(:mainnet :arbitrum :optimism) - :ens? false - :name "Amy" + :ens? true + :name "Alicia Keys" :created-at 1716826806 - :ens "" + :ens "alicia.eth" + :customization-color :purple + :removed? false}}}}}] + (is (match? expected-db result-db)))) + + (testing "remove a test saved addresses" + (let [cofx {:db {:wallet {:saved-addresses + {:test {"0x1" {:test? true + :address "0x1" + :mixedcase-address "0x1" + :chain-short-names "eth:oeth:" + :ens? false + :network-preferences-names `(:mainnet :optimism) + :name "Bob" + :created-at 1716826714 + :ens "" + :customization-color :blue + :removed? false}} + :prod {"0x2" {:test? false + :address "0x2" + :mixedcase-address "0x2" + :chain-short-names "eth:arb1:oeth:" + :network-preferences-names `(:mainnet :arbitrum + :optimism) + :ens? true + :name "Alicia Keys" + :created-at 1716826806 + :ens "alicia.eth" + :customization-color :purple + :removed? false}}}}}} + effects (events/reconcile-saved-addresses cofx + [[(assoc saved-address-1 :removed? true) + saved-address-2]]) + result-db (:db effects) + expected-db {:wallet {:saved-addresses + {:test {} + :prod {"0x2" {:test? false + :address "0x2" + :mixedcase-address "0x2" + :chain-short-names "eth:arb1:oeth:" + :network-preferences-names `(:mainnet :arbitrum :optimism) + :ens? true + :name "Alicia Keys" + :created-at 1716826806 + :ens "alicia.eth" :customization-color :purple :removed? false}}}}}] (is (match? expected-db result-db))))) @@ -141,7 +210,10 @@ expected-fx [[:json-rpc/call [{:method "wakuext_deleteSavedAddress" :params [address test-networks-enabled?] - :on-success [:wallet/delete-saved-address-success toast-message] + :on-success [:wallet/delete-saved-address-success + {:address address + :test-networks-enabled? test-networks-enabled? + :toast-message toast-message}] :on-error [:wallet/delete-saved-address-failed]}]]]] (is (match? expected-fx result-fx))))) diff --git a/src/status_im/contexts/settings/wallet/saved_addresses/sheets/address_options/view.cljs b/src/status_im/contexts/settings/wallet/saved_addresses/sheets/address_options/view.cljs index c1ae3ac6f6..c760394f68 100644 --- a/src/status_im/contexts/settings/wallet/saved_addresses/sheets/address_options/view.cljs +++ b/src/status_im/contexts/settings/wallet/saved_addresses/sheets/address_options/view.cljs @@ -109,7 +109,7 @@ :on-press open-show-address-qr :accessibility-label :show-address-qr-code} {:icon :i/edit - :label (i18n/label :t/edit-account) + :label (i18n/label :t/edit-details) :blur? true :on-press open-edit-saved-address :accessibility-label :edit-saved-address} diff --git a/src/status_im/contexts/wallet/data_store.cljs b/src/status_im/contexts/wallet/data_store.cljs index c84ba7feb9..4ad71b6281 100644 --- a/src/status_im/contexts/wallet/data_store.cljs +++ b/src/status_im/contexts/wallet/data_store.cljs @@ -154,7 +154,7 @@ :colorId :customization-color :mixedcaseAddress :mixedcase-address :removed :removed?}) - (update :customization-color keyword) + (update :customization-color (comp keyword string/lower-case)) add-keys-to-saved-address)) (defn rpc->saved-addresses diff --git a/translations/en.json b/translations/en.json index 5d96e3ebd6..44f570b184 100644 --- a/translations/en.json +++ b/translations/en.json @@ -2507,6 +2507,7 @@ "disconnect-dapp-success": "{{dapp}} disconnected from {{account}}", "disconnect-dapp-fail": "Failed to disconnect {{dapp}} from {{account}}", "edit-account": "Edit account", + "edit-details": "Edit details", "share-account": "Share account", "remove-account": "Remove account", "select-another-account": "Select another account",