From 24068dad5c188c5de1d20de9eaf6d61d90644183 Mon Sep 17 00:00:00 2001 From: Mohsen Date: Fri, 14 Jun 2024 12:25:44 +0300 Subject: [PATCH] [#20405] feat: make partially operable key pair to be fully operable (#20433) --- .../standard_authentication/events.cljs | 15 +++++-- .../contexts/settings/wallet/data_store.cljs | 44 ++++++++++++++++--- .../contexts/settings/wallet/events.cljs | 44 +++++++++++++++++-- .../contexts/settings/wallet/events_test.cljs | 17 +++++++ src/status_im/subs/wallet/wallet.cljs | 8 ++++ src/status_im/subs/wallet/wallet_test.cljs | 14 ++++++ 6 files changed, 130 insertions(+), 12 deletions(-) diff --git a/src/status_im/common/standard_authentication/events.cljs b/src/status_im/common/standard_authentication/events.cljs index a6b826de6d..5a22fdc662 100644 --- a/src/status_im/common/standard_authentication/events.cljs +++ b/src/status_im/common/standard_authentication/events.cljs @@ -66,9 +66,18 @@ (defn- bottom-sheet-password-view [{:keys [on-press-biometric on-auth-success auth-button-icon-left auth-button-label]}] (fn [] - (let [handle-password-success (fn [password] - (rf/dispatch [:standard-auth/reset-login-password]) - (-> password security/hash-masked-password on-auth-success))] + (let [has-partially-operable-accounts? (rf/sub [:wallet/has-partially-operable-accounts?]) + handle-password-success + (fn [password] + (let [sha3-pwd (security/hash-masked-password password) + on-auth-success-callback #(on-auth-success sha3-pwd)] + (rf/dispatch [:standard-auth/reset-login-password]) + (if has-partially-operable-accounts? + (rf/dispatch [:wallet/make-partially-operable-accounts-fully-operable + {:password sha3-pwd + :on-success on-auth-success-callback + :on-error on-auth-success-callback}]) + (on-auth-success-callback))))] [enter-password/view {:on-enter-password handle-password-success :on-press-biometrics on-press-biometric diff --git a/src/status_im/contexts/settings/wallet/data_store.cljs b/src/status_im/contexts/settings/wallet/data_store.cljs index a9c9b47aba..3c57eec708 100644 --- a/src/status_im/contexts/settings/wallet/data_store.cljs +++ b/src/status_im/contexts/settings/wallet/data_store.cljs @@ -20,28 +20,60 @@ keypairs)) (defn make-accounts-fully-operable - [accounts key-uids-set] + "Updates accounts to be fully operable based on specified key-uids and an optional operable condition. + + Parameters: + - :accounts (map): A map of account addresses to account details. + - :key-uids-set (set): A set of key-uids that need to be checked and updated. + - :operable-condition (keyword, optional): The condition that the account's operability must meet to be updated. + If nil or not provided, the function will update all accounts. + + Returns: + - A new map with accounts updated to be fully operable where the conditions are met." + [{:keys [accounts key-uids-set operable-condition]}] (reduce-kv (fn [acc k account] (if (and (contains? key-uids-set (:key-uid account)) - (= (keyword (:operable account)) :no)) + (or (nil? operable-condition) + (= (keyword (:operable account)) operable-condition))) (assoc acc k (assoc account :operable :fully)) (assoc acc k account))) {} accounts)) (defn- make-keypairs-accounts-fully-operable - [accounts] + [accounts operable-condition] (map (fn [account] - (assoc account :operable :fully)) + (if (or (nil? operable-condition) (= (keyword (:operable account)) operable-condition)) + (assoc account :operable :fully) + account)) accounts)) (defn make-keypairs-fully-operable - [keypairs key-uids-set] + "Updates keypairs' accounts to be fully operable based on specified key-uids and an optional operable condition. + + Parameters: + - :keypairs (seq): A sequence of keypair maps. + - :key-uids-set (set): A set of key-uids that need to be checked and updated. + - :operable-condition (keyword, optional): The condition that the keypair's accounts' operability must meet to be updated. + If nil or not provided, the function will update all keypairs' accounts. + + Returns: + - A new sequence with keypairs updated to be fully operable where the conditions are met." + [{:keys [keypairs key-uids-set operable-condition]}] (map (fn [keypair] (if (contains? key-uids-set (:key-uid keypair)) (-> keypair - (update :accounts make-keypairs-accounts-fully-operable) + (update :accounts #(make-keypairs-accounts-fully-operable % operable-condition)) (assoc :lowest-operability :fully)) keypair)) keypairs)) + +(defn map-addresses-to-key-uids + [db addresses] + (reduce (fn [key-uid-set address] + (if-let [account (get-in db [:wallet :accounts address])] + (conj key-uid-set (:key-uid account)) + key-uid-set)) + #{} + addresses)) diff --git a/src/status_im/contexts/settings/wallet/events.cljs b/src/status_im/contexts/settings/wallet/events.cljs index 9796dc5d69..8771da3383 100644 --- a/src/status_im/contexts/settings/wallet/events.cljs +++ b/src/status_im/contexts/settings/wallet/events.cljs @@ -73,9 +73,14 @@ [{:keys [db]} [key-uids-to-update]] (let [key-uids-set (set key-uids-to-update) keypair-name (data-store/extract-keypair-name db key-uids-set)] - {:db (-> db - (update-in [:wallet :accounts] #(data-store/make-accounts-fully-operable % key-uids-set)) - (update-in [:wallet :keypairs] #(data-store/make-keypairs-fully-operable % key-uids-set))) + {:db (-> + db + (update-in [:wallet :accounts] + #(data-store/make-accounts-fully-operable {:accounts % + :key-uids-set key-uids-set})) + (update-in [:wallet :keypairs] + #(data-store/make-keypairs-fully-operable {:keypairs % + :key-uids-set key-uids-set}))) :fx [[:dispatch [:toasts/upsert {:type :positive @@ -223,3 +228,36 @@ (rf/reg-event-fx :wallet/import-missing-keypair-by-private-key-failed import-missing-keypair-by-private-key-failed) + +(defn make-partially-operable-accounts-fully-operable-success + [{:keys [db]} [addresses]] + (let [key-uids-to-update (data-store/map-addresses-to-key-uids db addresses)] + {:db (-> db + (update-in [:wallet :accounts] + #(data-store/make-accounts-fully-operable {:accounts % + :key-uids-set key-uids-to-update + :operable-condition :partially})) + (update-in [:wallet :keypairs] + #(data-store/make-keypairs-fully-operable {:keypairs % + :key-uids-set key-uids-to-update + :operable-condition :partially})))})) + +(rf/reg-event-fx :wallet/make-partially-operable-accounts-fully-operable-success + make-partially-operable-accounts-fully-operable-success) + +(defn make-partially-operable-accounts-fully-operable + [_ [{:keys [password on-success on-error]}]] + {:fx [[:json-rpc/call + [{:method "accounts_makePartiallyOperableAccoutsFullyOperable" + :params [(security/safe-unmask-data password)] + :on-success (fn [addresses] + (when addresses + (rf/dispatch [:wallet/make-partially-operable-accounts-fully-operable-success + addresses])) + (on-success)) + :on-error (fn [error] + (log/error "failed to make partially accounts fully operable" {:error error}) + (on-error error))}]]]}) + +(rf/reg-event-fx :wallet/make-partially-operable-accounts-fully-operable + make-partially-operable-accounts-fully-operable) diff --git a/src/status_im/contexts/settings/wallet/events_test.cljs b/src/status_im/contexts/settings/wallet/events_test.cljs index f1690b25bc..5ee28749f2 100644 --- a/src/status_im/contexts/settings/wallet/events_test.cljs +++ b/src/status_im/contexts/settings/wallet/events_test.cljs @@ -129,3 +129,20 @@ (sut/make-seed-phrase-keypair-fully-operable cofx [mnemonic-masked password-masked on-success on-error]))))) + +(deftest make-partly-operable-accounts-fully-operable-test + (let [cofx {:db {}} + password-masked (security/mask-data "password") + on-success #(prn "success") + on-error #(prn "error") + expected {:fx [[:json-rpc/call + [{:method "accounts_makePartiallyOperableAccoutsFullyOperable" + :params [(security/safe-unmask-data password-masked)] + :on-success fn? + :on-error fn?}]]]}] + (is (match? expected + (sut/make-partially-operable-accounts-fully-operable + cofx + [{:password password-masked + :on-success on-success + :on-error on-error}]))))) diff --git a/src/status_im/subs/wallet/wallet.cljs b/src/status_im/subs/wallet/wallet.cljs index 69561b9992..56f647834b 100644 --- a/src/status_im/subs/wallet/wallet.cljs +++ b/src/status_im/subs/wallet/wallet.cljs @@ -617,3 +617,11 @@ currency-symbol fee-in-fiat)] fee-formatted))) + +(rf/reg-sub + :wallet/has-partially-operable-accounts? + :<- [:wallet/accounts] + (fn [accounts] + (->> accounts + (some #(= :partially (:operable %))) + boolean))) diff --git a/src/status_im/subs/wallet/wallet_test.cljs b/src/status_im/subs/wallet/wallet_test.cljs index dbe2c58b7b..6b258af24f 100644 --- a/src/status_im/subs/wallet/wallet_test.cljs +++ b/src/status_im/subs/wallet/wallet_test.cljs @@ -912,3 +912,17 @@ :market-values-per-currency {:usd {:price 10000}}} result (rf/sub [sub-name token-for-fees])] (is (match? result "$1.00"))))) + +(h/deftest-sub :wallet/has-partially-operable-accounts? + [sub-name] + (testing "returns false if there are no partially operable accounts" + (swap! rf-db/app-db + #(assoc-in % [:wallet :accounts] accounts)) + (is (false? (rf/sub [sub-name])))) + + (testing "returns true if there are partially operable accounts" + (swap! rf-db/app-db + #(assoc-in % + [:wallet :accounts] + (update accounts "0x2" assoc :operable :partially))) + (is (true? (rf/sub [sub-name])))))