chore(wallet): refactor keypairs data in app-db

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
This commit is contained in:
Mohamed Javid 2024-06-14 20:35:59 +05:30
parent 6a3794f380
commit 7a44e2870a
No known key found for this signature in database
GPG Key ID: 9B8D7DD7EF02CF1D
10 changed files with 138 additions and 126 deletions

View File

@ -1,24 +1,5 @@
(ns status-im.contexts.settings.wallet.data-store)
(defn extract-keypair-name
[db key-uids-set]
(when (= (count key-uids-set) 1)
(let [key-uid (first key-uids-set)
keypairs (get-in db [:wallet :keypairs])]
(->> (filter #(= (:key-uid %) key-uid) keypairs)
first
:name))))
(defn update-keypair
[keypairs key-uid update-fn]
(mapcat (fn [keypair]
(if (= (keypair :key-uid) key-uid)
(if-let [updated (update-fn keypair)]
[updated]
[])
[keypair]))
keypairs))
(defn make-accounts-fully-operable
"Updates accounts to be fully operable based on specified key-uids and an optional operable condition.
@ -32,10 +13,10 @@
- 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))
(fn [acc k {:keys [key-uid] :as account}]
(if (and (contains? key-uids-set key-uid)
(or (nil? operable-condition)
(= (keyword (:operable account)) operable-condition)))
(= (:operable account) operable-condition)))
(assoc acc k (assoc account :operable :fully))
(assoc acc k account)))
{}
@ -44,7 +25,7 @@
(defn- make-keypairs-accounts-fully-operable
[accounts operable-condition]
(map (fn [account]
(if (or (nil? operable-condition) (= (keyword (:operable account)) operable-condition))
(if (or (nil? operable-condition) (= (:operable account) operable-condition))
(assoc account :operable :fully)
account))
accounts))
@ -53,27 +34,30 @@
"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.
- :keypairs (map): A map of keypair key-uid to keypair 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 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."
- A new map 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 % operable-condition))
(assoc :lowest-operability :fully))
keypair))
keypairs))
(reduce-kv (fn [acc k keypair]
(if (contains? key-uids-set k)
(assoc acc
k
(-> keypair
(update :accounts make-keypairs-accounts-fully-operable operable-condition)
(assoc :lowest-operability :fully)))
(assoc acc k 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))
(if-let [account-key-uid (get-in db [:wallet :accounts address :key-uid])]
(conj key-uid-set account-key-uid)
key-uid-set))
#{}
addresses))

View File

@ -10,9 +10,7 @@
(rf/reg-event-fx
:wallet/rename-keypair-success
(fn [{:keys [db]} [key-uid name]]
{:db (update-in db
[:wallet :keypairs]
#(data-store/update-keypair % key-uid (fn [keypair] (assoc keypair :name name))))
{:db (update-in db [:wallet :keypairs key-uid] assoc :name name)
:fx [[:dispatch [:navigate-back]]
[:dispatch
[:toasts/upsert
@ -49,9 +47,7 @@
(rf/reg-event-fx :wallet/remove-keypair-success
(fn [{:keys [db]} [key-uid]]
{:db (update-in db
[:wallet :keypairs]
#(data-store/update-keypair % key-uid (fn [_] nil)))
{:db (update-in db [:wallet :keypairs] dissoc key-uid)
:fx [[:dispatch [:hide-bottom-sheet]]
[:dispatch
[:toasts/upsert
@ -71,8 +67,11 @@
(defn make-keypairs-accounts-fully-operable
[{: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)]
(let [key-uids-set (set key-uids-to-update)
single-keypair-to-update? (= (count key-uids-to-update) 1)
keypair-name (when single-keypair-to-update?
(let [key-uid (first key-uids-set)]
(get-in db [:wallet :keypairs key-uid :name])))]
{:db (->
db
(update-in [:wallet :accounts]
@ -85,7 +84,7 @@
[:toasts/upsert
{:type :positive
:theme :dark
:text (if (= (count key-uids-to-update) 1)
:text (if single-keypair-to-update?
(i18n/label :t/key-pair-imported-successfully {:name keypair-name})
(i18n/label :t/key-pairs-successfully-imported
{:count (count key-uids-to-update)}))}]]]}))

View File

@ -29,7 +29,7 @@
:keypair-name new-keypair-name}])))))))
(deftest get-keypair-export-connection-test
(let [cofx {:db (mock-db [] {})}
(let [cofx {:db (mock-db {} {})}
sha3-pwd "test-password"
user-key-uid "test-key-uid"
callback (fn [connect-string] (println "callback" connect-string))]
@ -57,23 +57,23 @@
(sut/remove-keypair cofx [mock-key-uid])))))))
(deftest make-keypairs-accounts-fully-operable-test
(let [db (mock-db [{:key-uid mock-key-uid
:lowest-operability :no
:accounts [{:key-uid mock-key-uid :operable "no"}]}]
{"0x1" {:key-uid mock-key-uid :operable "no"}})
(let [db (mock-db {mock-key-uid {:key-uid mock-key-uid
:lowest-operability :no
:accounts [{:key-uid mock-key-uid
:operable :no}]}}
{"0x1" {:key-uid mock-key-uid :operable :no}})
key-uids-to-update [mock-key-uid]]
(testing "make-keypairs-accounts-fully-operable"
(let [effects (sut/make-keypairs-accounts-fully-operable {:db db} [key-uids-to-update])
result-db (:db effects)
updated-keypair (some #(when (= (:key-uid %) mock-key-uid) %)
(get-in result-db [:wallet :keypairs]))
updated-keypair (get-in result-db [:wallet :keypairs mock-key-uid])
updated-account (get-in result-db [:wallet :accounts "0x1"])]
(is (= (keyword (-> updated-keypair :accounts first :operable)) :fully))
(is (= (keyword (:operable updated-account)) :fully))
(is (= (-> updated-keypair :accounts first :operable) :fully))
(is (= (:operable updated-account) :fully))
(is (= (:lowest-operability updated-keypair) :fully))))))
(deftest connection-string-for-import-keypair-test
(let [cofx {:db (mock-db [] {})}
(let [cofx {:db (mock-db {} {})}
sha3-pwd "test-password"
user-key-uid "test-key-uid"
connection-string "test-connection-string"]

View File

@ -70,7 +70,17 @@
{:keys [address path watch-only?]} (rf/sub [:wallet/current-viewing-account])
{keypair-name :name
keypair-type :type} (rf/sub [:wallet/current-viewing-account-keypair])
networks (rf/sub [:wallet/network-preference-details])]
networks (rf/sub [:wallet/network-preference-details])
origin-type (rn/use-memo
#(case keypair-type
:seed
:recovery-phrase
:key
:private-key
:default-keypair)
[keypair-type])]
[rn/scroll-view
{:style style/about-tab
:content-container-style {:padding-bottom (+ constants/floating-shell-button-height 8)}}
@ -91,7 +101,7 @@
:on-press #(rf/dispatch [:show-bottom-sheet {:content about-options}])}]
(when (not watch-only?)
[quo/account-origin
{:type (if (= keypair-type "seed") :recovery-phrase :default-keypair)
{:type origin-type
:stored :on-device
:profile-picture (profile.utils/photo profile)
:customization-color customization-color

View File

@ -5,6 +5,7 @@
[status-im.contexts.wallet.add-account.create-account.utils :as create-account.utils]
[status-im.contexts.wallet.data-store :as data-store]
[taoensso.timbre :as log]
[utils.collection]
[utils.re-frame :as rf]
[utils.security.core :as security]
[utils.transforms :as transforms]))
@ -12,9 +13,11 @@
(defn get-keypairs-success
[{:keys [db]} [keypairs]]
(let [parsed-keypairs (data-store/rpc->keypairs keypairs)
default-key-uid (:key-uid (some #(when (= (:type %) :profile) %) parsed-keypairs))]
default-key-uid (->> parsed-keypairs
(some #(when (= (:type %) :profile) %))
:key-uid)]
{:db (-> db
(assoc-in [:wallet :keypairs] parsed-keypairs)
(assoc-in [:wallet :keypairs] (utils.collection/index-by :key-uid parsed-keypairs))
(assoc-in [:wallet :ui :create-account :selected-keypair-uid] default-key-uid))}))
(rf/reg-event-fx :wallet/get-keypairs-success get-keypairs-success)
@ -41,10 +44,10 @@
(defn seed-phrase-validated
[{:keys [db]} [seed-phrase key-uid on-error]]
(let [keypair-already-added? (->> db
:wallet
:keypairs
(some #(= key-uid (:key-uid %))))]
(let [keypair-already-added? (-> db
:wallet
:keypairs
(contains? key-uid))]
(if keypair-already-added?
(do
(on-error)

View File

@ -73,7 +73,7 @@
[]
(let [compressed-key (rf/sub [:profile/compressed-key])
customization-color (rf/sub [:profile/customization-color])
keypairs (rf/sub [:wallet/keypairs])
keypairs (rf/sub [:wallet/keypairs-list])
selected-keypair (rf/sub [:wallet/selected-keypair-uid])
profile-picture (rf/sub [:profile/image])
[selected-key-uid set-selected-key-uid] (rn/use-state selected-keypair)]

View File

@ -529,10 +529,9 @@
:wallet/process-keypair-from-backup
(fn [{:keys [db]} [{:keys [backedUpKeypair]}]]
(let [{:keys [key-uid accounts]} backedUpKeypair
keypairs-db (get-in db [:wallet :keypairs])
updated-keypairs (-> (filter #(not= (:key-uid %) key-uid) keypairs-db)
(conj backedUpKeypair)
data-store/rpc->keypairs)
updated-keypairs (assoc-in db
[:wallet :keypairs key-uid]
(data-store/rpc->keypair backedUpKeypair))
accounts-fx (mapv (fn [{:keys [chat] :as account}]
;; We exclude the chat account from the profile keypair
;; for fetching the assets

View File

@ -194,6 +194,12 @@
:<- [:wallet]
:-> :keypairs)
(rf/reg-sub
:wallet/keypairs-list
:<- [:wallet]
(fn [{:keys [keypairs]}]
(vals keypairs)))
(rf/reg-sub
:wallet/selected-keypair-uid
:<- [:wallet/create-account]
@ -204,19 +210,15 @@
:<- [:wallet/keypairs]
:<- [:wallet/selected-keypair-uid]
(fn [[keypairs selected-keypair-uid]]
(some #(when (= (:key-uid %) selected-keypair-uid)
%)
keypairs)))
(get keypairs selected-keypair-uid)))
(rf/reg-sub
:wallet/selected-primary-keypair?
:<- [:wallet/keypairs]
:<- [:wallet/selected-keypair-uid]
(fn [[keypairs selected-keypair-uid]]
(let [primary-keypair-uid (->> keypairs
(some #(when (= (:type %) "profile") %))
(:key-uid))]
(= selected-keypair-uid primary-keypair-uid))))
(= (get-in keypairs [selected-keypair-uid :type])
:profile)))
(rf/reg-sub
:wallet/selected-networks->chain-ids
@ -261,22 +263,22 @@
:wallet/settings-keypairs-accounts
:<- [:wallet/keypairs]
(fn [keypairs [_ format-options]]
(let [grouped-keypairs (group-by :lowest-operability keypairs)
(let [grouped-keypairs (->> keypairs
vals
(group-by :lowest-operability))
operable-keypair-ids (->> (concat (:fully grouped-keypairs)
(:partially grouped-keypairs))
(map :key-uid)
(into #{}))
missing-keypair-ids (->> (map :key-uid (:no grouped-keypairs))
(into #{}))]
{:operable (->> keypairs
(filter #(contains? operable-keypair-ids (:key-uid %)))
(mapv :key-uid))
missing-keypair-ids (mapv :key-uid (:no grouped-keypairs))]
{:operable (->> (select-keys keypairs operable-keypair-ids)
vals
(map (fn [{:keys [accounts name type key-uid]}]
{:type (keyword type)
:name name
:key-uid key-uid
:accounts (format-settings-keypair-accounts accounts format-options)})))
:missing (->> keypairs
(filter #(contains? missing-keypair-ids (:key-uid %)))
:missing (->> (select-keys keypairs missing-keypair-ids)
vals
(map (fn [{:keys [accounts name type key-uid]}]
{:type (keyword type)
:name name
@ -366,7 +368,7 @@
:<- [:wallet/current-viewing-account]
:<- [:wallet/keypairs]
(fn [[{:keys [key-uid]} keypairs]]
(first (filter #(= key-uid (:key-uid %)) keypairs))))
(get keypairs key-uid)))
(rf/reg-sub
:wallet/current-viewing-account-tokens-in-selected-networks

View File

@ -596,18 +596,6 @@
(assoc :network-preferences-names #{}))]
(rf/sub [sub-name])))))
(def keypairs
[{:key-uid "abc"}])
(h/deftest-sub :wallet/keypairs
[sub-name]
(testing "returns all keypairs"
(swap! rf-db/app-db
#(assoc-in % [:wallet :keypairs] keypairs))
(is
(= keypairs
(rf/sub [sub-name])))))
(def chat-account
{:path "m/43'/60'/1581'/0'/0"
:emoji ""
@ -650,20 +638,43 @@
:operable :no
:removed false})
(def default-keypair-accounts
{:key-uid "abc"
(def profile-key-pair-key-uid "abc")
(def seed-phrase-key-pair-key-uid "def")
(def profile-keypair
{:key-uid profile-key-pair-key-uid
:name "My Profile"
:type "profile"
:type :profile
:lowest-operability :fully
:accounts []})
(def seed-phrase-keypair-accounts
{:key-uid "def"
(def seed-phrase-keypair
{:key-uid seed-phrase-key-pair-key-uid
:name "My Key Pair"
:type "seed"
:type :seed
:lowest-operability :no
:accounts []})
(h/deftest-sub :wallet/keypairs
[sub-name]
(testing "returns keypairs map"
(swap! rf-db/app-db #(assoc-in %
[:wallet :keypairs]
{profile-key-pair-key-uid profile-keypair}))
(is (match? {profile-key-pair-key-uid profile-keypair} (rf/sub [sub-name])))))
(h/deftest-sub :wallet/keypairs-list
[sub-name]
(testing "returns all keypairs"
(swap! rf-db/app-db #(assoc-in %
[:wallet :keypairs]
{profile-key-pair-key-uid profile-keypair
seed-phrase-key-pair-key-uid seed-phrase-keypair}))
(let [result (rf/sub [sub-name])
expected (list profile-keypair seed-phrase-keypair)]
(is (match? 2 (count result)))
(is (match? expected result)))))
(h/deftest-sub :wallet/settings-keypairs-accounts
[sub-name]
(testing "returns formatted key-pairs and accounts"
@ -672,12 +683,14 @@
(-> db
(assoc-in
[:wallet :keypairs]
[(assoc default-keypair-accounts
:accounts
[operable-wallet-account])
(assoc seed-phrase-keypair-accounts
:accounts
[inoperable-wallet-account])])
{profile-key-pair-key-uid (update profile-keypair
:accounts
conj
operable-wallet-account)
seed-phrase-key-pair-key-uid (update seed-phrase-keypair
:accounts
conj
inoperable-wallet-account)})
(assoc-in
[:wallet :accounts]
{(:address operable-wallet-account) operable-wallet-account
@ -685,15 +698,15 @@
(is
(match?
{:missing [{:name (:name seed-phrase-keypair-accounts)
:key-uid (:key-uid seed-phrase-keypair-accounts)
:type (keyword (:type seed-phrase-keypair-accounts))
{:missing [{:name (:name seed-phrase-keypair)
:key-uid (:key-uid seed-phrase-keypair)
:type (:type seed-phrase-keypair)
:accounts [{:customization-color (:color inoperable-wallet-account)
:emoji (:emoji inoperable-wallet-account)
:type :default}]}]
:operable [{:name (:name default-keypair-accounts)
:key-uid (:key-uid default-keypair-accounts)
:type (keyword (:type default-keypair-accounts))
:operable [{:name (:name profile-keypair)
:key-uid (:key-uid profile-keypair)
:type (:type profile-keypair)
:accounts [{:account-props {:customization-color (:color operable-wallet-account)
:size 32
:emoji (:emoji operable-wallet-account)
@ -711,9 +724,10 @@
(-> db
(assoc-in
[:wallet :keypairs]
[(assoc default-keypair-accounts
:accounts
[operable-wallet-account])])
{profile-key-pair-key-uid (update profile-keypair
:accounts
conj
operable-wallet-account)})
(assoc-in
[:wallet :accounts]
{(:address operable-wallet-account) operable-wallet-account}))))
@ -728,9 +742,9 @@
size-option 20]
(is
(match? {:missing []
:operable [{:name (:name default-keypair-accounts)
:key-uid (:key-uid default-keypair-accounts)
:type (keyword (:type default-keypair-accounts))
:operable [{:name (:name profile-keypair)
:key-uid (:key-uid profile-keypair)
:type (:type profile-keypair)
:accounts [{:account-props {:customization-color color
:size size-option
:emoji emoji
@ -750,10 +764,11 @@
(-> db
(assoc-in
[:wallet :keypairs]
[(assoc default-keypair-accounts
:accounts
[operable-wallet-account
chat-account])])
{profile-key-pair-key-uid (update profile-keypair
:accounts
conj
operable-wallet-account
chat-account)})
(assoc-in
[:wallet :accounts]
{(:address operable-wallet-account) operable-wallet-account
@ -761,9 +776,9 @@
(is
(match?
{:missing []
:operable [{:name (:name default-keypair-accounts)
:key-uid (:key-uid default-keypair-accounts)
:type (keyword (:type default-keypair-accounts))
:operable [{:name (:name profile-keypair)
:key-uid (:key-uid profile-keypair)
:type (:type profile-keypair)
:accounts [{:account-props {:customization-color (:color operable-wallet-account)
:size 32
:emoji (:emoji operable-wallet-account)