feat(wallet)!: process wallet accounts from backup on account recovery (#20160)

This commit:

- adds a feature to process backed-up wallet data on account recovery (without the necessity to re-login)
- refactors keypair data store functions
- refactors wallet event to support calling for single account/address

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
This commit is contained in:
Mohamed Javid 2024-06-07 20:28:49 +05:30 committed by GitHub
parent a3e713bbf0
commit 9c7cb0fe93
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 402 additions and 210 deletions

View File

@ -105,6 +105,12 @@
"waku.backedup.settings"
{:fx [[:dispatch [:profile/update-setting-from-backup (transforms/js->clj event-js)]]]}
"waku.backedup.keypair"
{:fx [[:dispatch [:wallet/process-keypair-from-backup (transforms/js->clj event-js)]]]}
"waku.backedup.watch-only-account"
{:fx [[:dispatch [:wallet/process-watch-only-account-from-backup (transforms/js->clj event-js)]]]}
"mediaserver.started"
{:db (assoc db :mediaserver/port (oops/oget event-js :port))}

View File

@ -8,7 +8,7 @@
(defn view
[]
(let [tokens-loading? (rf/sub [:wallet/tokens-loading?])
(let [tokens-loading? (rf/sub [:wallet/current-viewing-account-tokens-loading?])
tokens (rf/sub [:wallet/current-viewing-account-token-values])
{:keys [watch-only?]} (rf/sub [:wallet/current-viewing-account])]
(if tokens-loading?

View File

@ -11,8 +11,8 @@
(defn get-keypairs-success
[{:keys [db]} [keypairs]]
(let [parsed-keypairs (data-store/parse-keypairs keypairs)
default-key-uid (:key-uid (first parsed-keypairs))]
(let [parsed-keypairs (data-store/rpc->keypairs keypairs)
default-key-uid (:key-uid (some #(when (= (:type %) :profile) %) parsed-keypairs))]
{:db (-> db
(assoc-in [:wallet :keypairs] parsed-keypairs)
(assoc-in [:wallet :ui :create-account :selected-keypair-uid] default-key-uid))}))

View File

@ -34,8 +34,8 @@
(->> given-accounts
(filter (fn [{:keys [path]}]
(not (string/starts-with? path constants/path-eip1581))))
(map (fn [{:keys [customization-color emoji name address]}]
{:account-props {:customization-color customization-color
(map (fn [{:keys [color emoji name address]}]
{:account-props {:customization-color color
:size 32
:emoji emoji
:type :default
@ -48,20 +48,21 @@
:action :none}))))
(defn- keypair
[item index _
[item _ _
{:keys [profile-picture compressed-key selected-key-uid set-selected-key-uid customization-color]}]
(let [accounts (parse-accounts (:accounts item))]
(let [profile-keypair? (= (:type item) :profile)
accounts (parse-accounts (:accounts item))]
[quo/keypair
{:customization-color customization-color
:profile-picture (when (zero? index) profile-picture)
:profile-picture (when profile-keypair? profile-picture)
:status-indicator false
:type (if (zero? index) :default-keypair :other)
:type (if profile-keypair? :default-keypair :other)
:stored :on-device
:on-options-press #(js/alert "Options pressed")
:action :selector
:blur? false
:details {:full-name (:name item)
:address (when (zero? index)
:address (when profile-keypair?
(utils/get-shortened-compressed-key compressed-key))}
:on-press #(set-selected-key-uid (:key-uid item))
:accounts accounts

View File

@ -110,6 +110,20 @@
new-request? (update-in [:wallet :accounts] update-vals #(dissoc % :collectibles)))
:fx collectible-requests})))
(defn request-new-collectibles-for-account-from-signal
[{:keys [db]} [address]]
(let [pending-requests (get-in db [:wallet :ui :collectibles :pending-requests] 0)
[request-id] (get-unique-collectible-request-id 1)]
{:db (assoc-in db [:wallet :ui :collectibles :pending-requests] (inc pending-requests))
:fx [[:dispatch
[:wallet/request-new-collectibles-for-account
{:request-id request-id
:account address
:amount collectibles-request-batch-size}]]]}))
(rf/reg-event-fx :wallet/request-new-collectibles-for-account-from-signal
request-new-collectibles-for-account-from-signal)
(rf/reg-event-fx
:wallet/request-collectibles-for-current-viewing-account
(fn [{:keys [db]} _]

View File

@ -0,0 +1,70 @@
(ns status-im.contexts.wallet.collectible.events-test
(:require
[cljs.test :refer-macros [deftest is testing]]
matcher-combinators.test
[status-im.contexts.wallet.collectible.events :as events]))
(deftest store-collectibles-test
(testing "flush-collectibles"
(let [collectible-1 {:collectible-data {:image-url "https://..." :animation-url "https://..."}
:ownership [{:address "0x1"
:balance "1"}]}
collectible-2 {:collectible-data {:image-url "" :animation-url "https://..."}
:ownership [{:address "0x1"
:balance "1"}]}
collectible-3 {:collectible-data {:image-url "" :animation-url nil}
:ownership [{:address "0x2"
:balance "1"}]}
db {:wallet {:ui {:collectibles {:pending-requests 0
:fetched {"0x1" [collectible-1
collectible-2]
"0x2" [collectible-3]}}}
:accounts {"0x1" {}
"0x3" {}}}}
expected-db {:wallet {:ui {:collectibles {}}
:accounts {"0x1" {:collectibles (list collectible-1 collectible-2)}
"0x2" {:collectibles (list collectible-3)}
"0x3" {}}}}
result-db (:db (events/flush-collectibles {:db db}))]
(is (match? result-db expected-db)))))
(deftest clear-stored-collectibles-test
(let [db {:wallet {:accounts {"0x1" {:collectibles [{:id 1} {:id 2}]}
"0x2" {"some other stuff" "with any value"
:collectibles [{:id 3}]}
"0x3" {}}}}]
(testing "clear-stored-collectibles"
(let [expected-db {:wallet {:accounts {"0x1" {}
"0x2" {"some other stuff" "with any value"}
"0x3" {}}}}
effects (events/clear-stored-collectibles {:db db})
result-db (:db effects)]
(is (match? result-db expected-db))))))
(deftest store-last-collectible-details-test
(testing "store-last-collectible-details"
(let [db {:wallet {}}
last-collectible {:description "Pandaria"
:image-url "https://..."}
expected-db {:wallet {:last-collectible-details {:description "Pandaria"
:image-url "https://..."}}}
effects (events/store-last-collectible-details {:db db}
[last-collectible])
result-db (:db effects)]
(is (match? result-db expected-db)))))
(deftest request-new-collectibles-for-account-from-signal-test
(testing "request new collectibles for account from signal"
(let [db {:wallet {}}
address "0x1"
expected {:db {:wallet {:ui {:collectibles {:pending-requests 1}}}}
:fx [[:dispatch
[:wallet/request-new-collectibles-for-account
{:request-id 0
:account address
:amount events/collectibles-request-batch-size}]]]}
effects (events/request-new-collectibles-for-account-from-signal {:db db}
[address])]
(is (match? expected effects)))))

View File

@ -1,6 +1,5 @@
(ns status-im.contexts.wallet.data-store
(:require
[camel-snake-kebab.core :as csk]
[camel-snake-kebab.extras :as cske]
[clojure.set :as set]
[clojure.string :as string]
@ -22,7 +21,9 @@
(defn add-keys-to-account
[account]
(assoc account :watch-only? (= (:type account) :watch)))
(-> account
(assoc :watch-only? (= (:type account) :watch))
(assoc :default-account? (:wallet account))))
(defn- sanitize-emoji
"As Desktop uses Twemoji, the emoji received can be an img tag
@ -44,9 +45,11 @@
(update :test-preferred-chain-ids chain-ids-string->set)
(update :type keyword)
(update :operable keyword)
(update :color #(if (seq %) (keyword %) constants/account-default-customization-color))
(update :color
#(if (and (not (keyword? %)) (string/blank? %))
constants/account-default-customization-color
(keyword %)))
(update :emoji sanitize-emoji)
(assoc :default-account? (:wallet account))
add-keys-to-account))
(defn rpc->accounts
@ -107,36 +110,33 @@
:nativeCurrencySymbol :native-currency-symbol
:nativeCurrencyName :native-currency-symbol})))
(defn sort-keypairs
[keypairs]
(sort-by #(if (some (fn [account]
(string/starts-with? (:path account) constants/path-eip1581))
(:accounts %))
0
1)
keypairs))
(defn get-keypair-lowest-operability
[{:keys [accounts]}]
(cond
(some #(= (:operable %) :no) accounts)
:no
(defn sort-and-rename-keypairs
[keypairs]
(let [sorted-keypairs (sort-keypairs keypairs)]
(map (fn [item]
(update item
:accounts
(fn [accounts]
(map
(fn [{:keys [colorId] :as account}]
(assoc account
:customization-color
(if (seq colorId)
(keyword colorId)
:blue)))
accounts))))
sorted-keypairs)))
(some #(= (:operable %) :partially) accounts)
:partially
(defn parse-keypairs
:else
:fully))
(defn- add-keys-to-keypair
[keypair]
(assoc keypair :lowest-operability (get-keypair-lowest-operability keypair)))
(defn rpc->keypair
[keypair]
(-> keypair
(update :type keyword)
(update :accounts #(map rpc->account %))
add-keys-to-keypair))
(defn rpc->keypairs
[keypairs]
(let [renamed-data (sort-and-rename-keypairs keypairs)]
(cske/transform-keys csk/->kebab-case-keyword renamed-data)))
(->> (map rpc->keypair keypairs)
(sort-by #(if (= (:type %) :profile) 0 1))))
(defn- add-keys-to-saved-address
[saved-address]

View File

@ -6,5 +6,4 @@
:selected-networks (set constants/default-network-names)})
(def defaults
{:ui {:network-filter network-filter-defaults
:tokens-loading? true}})
{:ui {:network-filter network-filter-defaults}})

View File

@ -57,19 +57,27 @@
{:fx [[:dispatch [:wallet/clean-current-viewing-account]]
[:dispatch [:pop-to-root :shell-stack]]]}))
(defn log-rpc-error
[_ [{:keys [event params]} error]]
(log/warn (str "[wallet] Failed to " event)
{:params params
:error error}))
(rf/reg-event-fx :wallet/log-rpc-error log-rpc-error)
(rf/reg-event-fx
:wallet/get-accounts-success
(fn [{:keys [db]} [accounts]]
(let [wallet-accounts (filter #(not (:chat %)) accounts)
(let [wallet-accounts (data-store/rpc->accounts accounts)
wallet-db (get db :wallet)
new-account? (:new-account? wallet-db)
navigate-to-account (:navigate-to-account wallet-db)]
{:db (assoc-in db
[:wallet :accounts]
(utils.collection/index-by :address (data-store/rpc->accounts wallet-accounts)))
:fx [[:dispatch [:wallet/get-wallet-token]]
(utils.collection/index-by :address wallet-accounts))
:fx [[:dispatch [:wallet/get-wallet-token-for-all-accounts]]
[:dispatch [:wallet/request-collectibles-for-all-accounts {:new-request? true}]]
[:dispatch [:wallet/check-recent-history]]
[:dispatch [:wallet/check-recent-history-for-all-accounts]]
(when new-account?
[:dispatch [:wallet/navigate-to-new-account navigate-to-account]])]})))
@ -79,9 +87,16 @@
{:fx [[:json-rpc/call
[{:method "accounts_getAccounts"
:on-success [:wallet/get-accounts-success]
:on-error #(log/info "failed to get accounts "
{:error %
:event :wallet/get-accounts})}]]]}))
:on-error [:wallet/log-rpc-error {:event :wallet/get-accounts}]}]]]}))
(defn process-account-from-signal
[{:keys [db]} [{:keys [address] :as account}]]
{:db (assoc-in db [:wallet :accounts address] (data-store/rpc->account account))
:fx [[:dispatch [:wallet/get-wallet-token-for-account address]]
[:dispatch [:wallet/request-new-collectibles-for-account-from-signal address]]
[:dispatch [:wallet/check-recent-history-for-account address]]]})
(rf/reg-event-fx :wallet/process-account-from-signal process-account-from-signal)
(rf/reg-event-fx
:wallet/save-account
@ -93,9 +108,7 @@
(rf/dispatch [:wallet/get-accounts])
(when (fn? on-success)
(on-success)))
:on-error #(log/info "failed to save account "
{:error %
:event :wallet/save-account})}]]]}))
:on-error [:wallet/log-rpc-error {:event :wallet/save-account}]}]]]}))
(rf/reg-event-fx
:wallet/show-account-deleted-toast
@ -125,35 +138,41 @@
[{: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})}]]]}))
:on-error [:wallet/log-rpc-error {:event :wallet/remove-account}]}]]]}))
(defn get-wallet-token-for-all-accounts
[{:keys [db]}]
{:fx (->> (get-in db [:wallet :accounts])
vals
(mapv
(fn [{:keys [address]}]
[:dispatch [:wallet/get-wallet-token-for-account address]])))})
(rf/reg-event-fx :wallet/get-wallet-token-for-all-accounts get-wallet-token-for-all-accounts)
(defn get-wallet-token-for-account
[{:keys [db]} [address]]
{:db (assoc-in db [:wallet :ui :tokens-loading address] true)
:fx [[:json-rpc/call
[{:method "wallet_getWalletToken"
:params [[address]]
:on-success [:wallet/store-wallet-token address]
:on-error [:wallet/get-wallet-token-for-account-failed address]}]]]})
(rf/reg-event-fx :wallet/get-wallet-token-for-account get-wallet-token-for-account)
(rf/reg-event-fx
:wallet/get-wallet-token
(fn [{:keys [db]}]
(let [addresses (->> (get-in db [:wallet :accounts])
vals
(map :address))]
{:db (assoc-in db [:wallet :ui :tokens-loading?] true)
:fx [[:json-rpc/call
[{:method "wallet_getWalletToken"
:params [addresses]
:on-success [:wallet/store-wallet-token]
:on-error [:wallet/get-wallet-token-failed addresses]}]]]})))
(rf/reg-event-fx
:wallet/get-wallet-token-failed
(fn [{:keys [db]} [params error]]
:wallet/get-wallet-token-for-account-failed
(fn [{:keys [db]} [address error]]
(log/info "failed to get wallet token "
{:error error
:event :wallet/get-wallet-token
:params params})
{:db (assoc-in db [:wallet :ui :tokens-loading?] false)}))
:event :wallet/get-wallet-token-for-account
:params address})
{:db (assoc-in db [:wallet :ui :tokens-loading address] false)}))
(rf/reg-event-fx
:wallet/store-wallet-token
(fn [{:keys [db]} [raw-tokens-data]]
(fn [{:keys [db]} [address raw-tokens-data]]
(let [tokens (data-store/rpc->tokens raw-tokens-data)
add-tokens (fn [stored-accounts tokens-per-account]
(reduce-kv (fn [accounts address tokens-data]
@ -164,7 +183,7 @@
tokens-per-account))]
{:db (-> db
(update-in [:wallet :accounts] add-tokens tokens)
(assoc-in [:wallet :ui :tokens-loading?] false))})))
(assoc-in [:wallet :ui :tokens-loading address] false))})))
(rf/defn scan-address-success
{:events [:wallet/scan-address-success]}
@ -209,7 +228,9 @@
(security/safe-unmask-data password))
account-config]
:on-success [:wallet/add-account-success lowercase-address]
:on-error #(log/info "failed to create account " % account-config)}]]]})))
:on-error [:wallet/log-rpc-error
{:event :wallet/add-account
:params account-config}]}]]]})))
(defn get-keypairs
[_]
@ -217,7 +238,7 @@
[{:method "accounts_getKeypairs"
:params []
:on-success [:wallet/get-keypairs-success]
:on-error #(log/info "failed to get keypairs " %)}]]]})
:on-error [:wallet/log-rpc-error {:event :wallet/get-keypairs}]}]]]})
(rf/reg-event-fx :wallet/get-keypairs get-keypairs)
@ -254,7 +275,7 @@
[{:method "wallet_getEthereumChains"
:params []
:on-success [:wallet/get-ethereum-chains-success]
:on-error #(log/info "failed to get networks " %)}]}))
:on-error [:wallet/log-rpc-error {:event :wallet/get-ethereum-chains}]}]}))
(rf/reg-event-fx
:wallet/get-ethereum-chains-success
@ -354,29 +375,34 @@
(rf/reg-event-fx :wallet/reload
(fn [_]
{:fx [[:dispatch-n [[:wallet/get-wallet-token]]]]}))
{:fx [[:dispatch [:wallet/get-wallet-token-for-all-accounts]]]}))
(rf/reg-event-fx :wallet/start-wallet
(fn [_]
{:fx [[:json-rpc/call
[{:method "wallet_startWallet"
:on-error #(log/info "failed to start wallet"
{:error %
:event :wallet/start-wallet})}]]]}))
:on-error [:wallet/log-rpc-error {:event :wallet/start-wallet}]}]]]}))
(defn check-recent-history-for-all-accounts
[{:keys [db]}]
{:fx (->> (get-in db [:wallet :accounts])
vals
(mapv (fn [{:keys [address]}]
[:dispatch [:wallet/check-recent-history-for-account address]])))})
(rf/reg-event-fx :wallet/check-recent-history-for-all-accounts check-recent-history-for-all-accounts)
(rf/reg-event-fx
:wallet/check-recent-history
(fn [{:keys [db]}]
(let [addresses (->> (get-in db [:wallet :accounts])
vals
(map :address))
chain-ids (chain/chain-ids db)]
:wallet/check-recent-history-for-account
(fn [{:keys [db]} [address]]
(let [chain-ids (chain/chain-ids db)
params [chain-ids [address]]]
{:fx [[:json-rpc/call
[{:method "wallet_checkRecentHistoryForChainIDs"
:params [chain-ids addresses]
:on-error #(log/info "failed to check recent history"
{:error %
:event :wallet/check-recent-history})}]]]})))
:params params
:on-error [:wallet/log-rpc-error
{:event :wallet/check-recent-history-for-account
:params params}]}]]]})))
(rf/reg-event-fx :wallet/initialize
(fn []
@ -496,9 +522,9 @@
;; https://github.com/status-im/status-mobile/issues/19864
:method "wallet_filterActivityAsync"
:params request-params
:on-error #(log/info "failed to fetch activities"
{:error %
:event :wallet/fetch-activities})}]]]})))
:on-error [:wallet/log-rpc-error
{:event :wallet/fetch-activities
:params request-params}]}]]]})))
(rf/reg-event-fx
:wallet/activity-filtering-done
@ -523,9 +549,7 @@
{:fx [[:json-rpc/call
[{:method "wallet_getCryptoOnRamps"
:on-success [:wallet/get-crypto-on-ramps-success]
:on-error #(log/info "failed to fetch crypto on ramps"
{:error %
:event :wallet/get-crypto-on-ramps})}]]]}))
:on-error [:wallet/log-rpc-error {:event :wallet/get-crypto-on-ramps}]}]]]}))
(rf/reg-event-fx
:wallet/resolve-ens
@ -536,3 +560,27 @@
:params [chain-id ens]
:on-success on-success
:on-error on-error}]]]})))
(rf/reg-event-fx
: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)
accounts-fx (mapv (fn [{:keys [chat] :as account}]
;; We exclude the chat account from the profile keypair
;; for fetching the assets
(when-not chat
[:dispatch
[:wallet/process-account-from-signal
account]]))
accounts)]
{:db (assoc-in db [:wallet :keypairs] updated-keypairs)
:fx accounts-fx})))
(rf/reg-event-fx
:wallet/process-watch-only-account-from-backup
(fn [_ [{:keys [backedUpWatchOnlyAccount]}]]
{:fx [[:dispatch [:wallet/process-account-from-signal backedUpWatchOnlyAccount]]]}))

View File

@ -3,10 +3,55 @@
[cljs.test :refer-macros [deftest is testing]]
matcher-combinators.test
[status-im.constants :as constants]
[status-im.contexts.wallet.collectible.events :as collectible-events]
[status-im.contexts.wallet.events :as events]))
(def address "0x2f88d65f3cb52605a54a833ae118fb1363acccd2")
(def address "0x2ee6138eb9344a8b76eca3cf7554a06c82a1e2d8")
(def raw-account
{:path "m/44'/60'/0'/0/0"
:emoji "🛃"
:key-uid "0xf9b4dc40911638052ef9cbed6e8ac689198d8f11d2235c5d62e2457c1503dc4f"
:address address
:wallet true
:name "Ethereum account"
:createdAt 1716548742000
:type "generated"
:chat false
:prodPreferredChainIds "1:42161"
:hidden false
:position 0
:clock 1712315009484
:testPreferredChainIds "11155111:421614"
:colorId "purple"
:operable "fully"
:mixedcase-address "0x2Ee6138eb9344a8b76Eca3cf7554A06C82A1e2D8"
:public-key
"0x04ee7c47e4b68cc05dcd3377cbd5cde6be3c89fcf20a981e55e0285ed63a50f51f8b423465eee134c51bb0255e6041e9e5b006054b0fa72a7c76942a5a1a3f4e7e"
:removed false})
(def account
{:path "m/44'/60'/0'/0/0"
:emoji "🛃"
:key-uid "0xf9b4dc40911638052ef9cbed6e8ac689198d8f11d2235c5d62e2457c1503dc4f"
:address address
:color :purple
:wallet true
:default-account? true
:name "Ethereum account"
:type :generated
:chat false
:test-preferred-chain-ids #{11155111 421614}
:watch-only? false
:hidden false
:prod-preferred-chain-ids #{1 42161}
:position 0
:clock 1712315009484
:created-at 1716548742000
:operable :fully
:mixedcase-address "0x2Ee6138eb9344a8b76Eca3cf7554A06C82A1e2D8"
:public-key
"0x04ee7c47e4b68cc05dcd3377cbd5cde6be3c89fcf20a981e55e0285ed63a50f51f8b423465eee134c51bb0255e6041e9e5b006054b0fa72a7c76942a5a1a3f4e7e"
:removed false})
(deftest scan-address-success-test
(let [db {}]
@ -25,57 +70,6 @@
result-db (:db effects)]
(is (match? result-db expected-db))))))
(deftest store-collectibles-test
(testing "flush-collectibles"
(let [collectible-1 {:collectible-data {:image-url "https://..." :animation-url "https://..."}
:ownership [{:address "0x1"
:balance "1"}]}
collectible-2 {:collectible-data {:image-url "" :animation-url "https://..."}
:ownership [{:address "0x1"
:balance "1"}]}
collectible-3 {:collectible-data {:image-url "" :animation-url nil}
:ownership [{:address "0x2"
:balance "1"}]}
db {:wallet {:ui {:collectibles {:pending-requests 0
:fetched {"0x1" [collectible-1
collectible-2]
"0x2" [collectible-3]}}}
:accounts {"0x1" {}
"0x3" {}}}}
expected-db {:wallet {:ui {:collectibles {}}
:accounts {"0x1" {:collectibles (list collectible-1 collectible-2)}
"0x2" {:collectibles (list collectible-3)}
"0x3" {}}}}
result-db (:db (collectible-events/flush-collectibles {:db db}))]
(is (match? result-db expected-db)))))
(deftest clear-stored-collectibles-test
(let [db {:wallet {:accounts {"0x1" {:collectibles [{:id 1} {:id 2}]}
"0x2" {"some other stuff" "with any value"
:collectibles [{:id 3}]}
"0x3" {}}}}]
(testing "clear-stored-collectibles"
(let [expected-db {:wallet {:accounts {"0x1" {}
"0x2" {"some other stuff" "with any value"}
"0x3" {}}}}
effects (collectible-events/clear-stored-collectibles {:db db})
result-db (:db effects)]
(is (match? result-db expected-db))))))
(deftest store-last-collectible-details-test
(testing "store-last-collectible-details"
(let [db {:wallet {}}
last-collectible {:description "Pandaria"
:image-url "https://..."}
expected-db {:wallet {:last-collectible-details {:description "Pandaria"
:image-url "https://..."}}}
effects (collectible-events/store-last-collectible-details {:db db}
[last-collectible])
result-db (:db effects)]
(is (match? result-db expected-db)))))
(deftest reset-selected-networks-test
(testing "reset-selected-networks"
(let [db {:wallet {}}
@ -122,3 +116,51 @@
effects (events/update-selected-networks {:db db} props)
result-fx (:fx effects)]
(is (match? result-fx expected-fx)))))
(deftest get-wallet-token-for-all-accounts-test
(testing "get wallet token for all accounts"
(let [address-1 "0x1"
address-2 "0x2"
cofx {:db {:wallet {:accounts {address-1 {:address address-1}
address-2 {:address address-2}}}}}
effects (events/get-wallet-token-for-all-accounts cofx)
result-fx (:fx effects)
expected-fx [[:dispatch [:wallet/get-wallet-token-for-account address-1]]
[:dispatch [:wallet/get-wallet-token-for-account address-2]]]]
(is (match? expected-fx result-fx)))))
(deftest get-wallet-token-for-account-test
(testing "get wallet token for account"
(let [cofx {:db {}}
effects (events/get-wallet-token-for-account cofx [address])
expected-effects {:db {:wallet {:ui {:tokens-loading {address true}}}}
:fx [[:json-rpc/call
[{:method "wallet_getWalletToken"
:params [[address]]
:on-success [:wallet/store-wallet-token address]
:on-error [:wallet/get-wallet-token-for-account-failed
address]}]]]}]
(is (match? expected-effects effects)))))
(deftest check-recent-history-for-all-accounts-test
(testing "check recent history for all accounts"
(let [address-1 "0x1"
address-2 "0x2"
cofx {:db {:wallet {:accounts {address-1 {:address address-1}
address-2 {:address address-2}}}}}
effects (events/check-recent-history-for-all-accounts cofx)
result-fx (:fx effects)
expected-fx [[:dispatch [:wallet/check-recent-history-for-account address-1]]
[:dispatch [:wallet/check-recent-history-for-account address-2]]]]
(is (match? expected-fx result-fx)))))
(deftest process-account-from-signal-test
(testing "process account from signal"
(let [cofx {:db {:wallet {:accounts {}}}}
effects (events/process-account-from-signal cofx [raw-account])
expected-effects {:db {:wallet {:accounts {address account}}}
:fx [[:dispatch [:wallet/get-wallet-token-for-account address]]
[:dispatch
[:wallet/request-new-collectibles-for-account-from-signal address]]
[:dispatch [:wallet/check-recent-history-for-account address]]]}]
(is (match? expected-effects effects)))))

View File

@ -8,7 +8,7 @@
(defn view
[]
(let [tokens-loading? (rf/sub [:wallet/tokens-loading?])
(let [tokens-loading? (rf/sub [:wallet/home-tokens-loading?])
{:keys [tokens]} (rf/sub [:wallet/aggregated-token-values-and-balance])]
(if tokens-loading?
[quo/skeleton-list

View File

@ -65,7 +65,7 @@
[]
(let [[selected-tab set-selected-tab] (rn/use-state (:id (first tabs-data)))
account-list-ref (rn/use-ref-atom nil)
tokens-loading? (rf/sub [:wallet/tokens-loading?])
tokens-loading? (rf/sub [:wallet/home-tokens-loading?])
networks (rf/sub [:wallet/selected-network-details])
account-cards-data (rf/sub [:wallet/account-cards-data])
cards (conj account-cards-data (new-account-card-data))

View File

@ -40,6 +40,4 @@
"wallet-activity-filtering-done" {:fx [[:dispatch
[:wallet/activity-filtering-done
(transforms/js->clj event-js)]]]}
(log/debug ::unknown-wallet-event
:type event-type
:event (transforms/js->clj event-js))))))
(log/debug ::unknown-wallet-event :type event-type)))))

View File

@ -39,9 +39,25 @@
:-> :scanned-address)
(rf/reg-sub
:wallet/tokens-loading?
:wallet/tokens-loading
:<- [:wallet/ui]
:-> :tokens-loading?)
:-> :tokens-loading)
(rf/reg-sub
:wallet/home-tokens-loading?
:<- [:wallet/tokens-loading]
(fn [tokens-loading]
(->> tokens-loading
vals
(some true?)
boolean)))
(rf/reg-sub
:wallet/current-viewing-account-tokens-loading?
:<- [:wallet/tokens-loading]
:<- [:wallet/current-viewing-account-address]
(fn [[tokens-loading current-viewing-account-address]]
(get tokens-loading current-viewing-account-address)))
(rf/reg-sub
:wallet/create-account
@ -218,9 +234,9 @@
:or {networks []
size 32}}]
(->> accounts
(keep (fn [{:keys [path customization-color emoji name address]}]
(keep (fn [{:keys [path color emoji name address]}]
(when-not (string/starts-with? path constants/path-eip1581)
{:account-props {:customization-color customization-color
{:account-props {:customization-color color
:size size
:emoji emoji
:type :default
@ -233,8 +249,8 @@
(defn- format-settings-missing-keypair-accounts
[accounts]
(->> accounts
(map (fn [{:keys [customization-color emoji]}]
{:customization-color customization-color
(map (fn [{:keys [color emoji]}]
{:customization-color color
:emoji emoji
:type :default}))))
@ -311,15 +327,15 @@
:wallet/account-cards-data
:<- [:wallet/accounts]
:<- [:wallet/balances-in-selected-networks]
:<- [:wallet/tokens-loading?]
:<- [:wallet/tokens-loading]
:<- [:profile/currency-symbol]
(fn [[accounts balances tokens-loading? currency-symbol]]
(fn [[accounts balances tokens-loading currency-symbol]]
(mapv (fn [{:keys [color address watch-only?] :as account}]
(assoc account
:customization-color color
:type (if watch-only? :watch-only :empty)
:on-press #(rf/dispatch [:wallet/navigate-to-account address])
:loading? tokens-loading?
:loading? (get tokens-loading address)
:balance (utils/prettify-balance currency-symbol (get balances address))))
accounts)))

View File

@ -609,46 +609,46 @@
(rf/sub [sub-name])))))
(def chat-account
{:path "m/43'/60'/1581'/0'/0"
:emoji ""
:key-uid "abc"
:address "address-1"
:color-id ""
:wallet false
:name "My Profile"
:type "generated"
:chat true
:customization-color :blue
:hidden false
:removed false})
{:path "m/43'/60'/1581'/0'/0"
:emoji ""
:key-uid "abc"
:address "address-1"
:color-id ""
:wallet false
:name "My Profile"
:type "generated"
:chat true
:color :blue
:hidden false
:removed false})
(def operable-wallet-account
{:path "m/44'/60'/0'/0/0"
:emoji "🤡"
:key-uid "abc"
:address "address-2"
:wallet true
:name "My Account"
:type "generated"
:chat false
:customization-color :primary
:hidden false
:operable :fully
:removed false})
{:path "m/44'/60'/0'/0/0"
:emoji "🤡"
:key-uid "abc"
:address "address-2"
:wallet true
:name "My Account"
:type "generated"
:chat false
:color :primary
:hidden false
:operable :fully
:removed false})
(def inoperable-wallet-account
{:path "m/44'/60'/0'/0/0"
:emoji "🧠"
:key-uid "def"
:address "address-3"
:wallet true
:name "My Other Account"
:type "generated"
:chat false
:customization-color :primary
:hidden false
:operable :no
:removed false})
{:path "m/44'/60'/0'/0/0"
:emoji "🧠"
:key-uid "def"
:address "address-3"
:wallet true
:name "My Other Account"
:type "generated"
:chat false
:color :primary
:hidden false
:operable :no
:removed false})
(def default-keypair-accounts
{:key-uid "abc"
@ -686,14 +686,13 @@
{:missing [{:name (:name seed-phrase-keypair-accounts)
:key-uid (:key-uid seed-phrase-keypair-accounts)
:type (keyword (:type seed-phrase-keypair-accounts))
:accounts [{:customization-color (:customization-color inoperable-wallet-account)
: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))
:accounts [{:account-props {:customization-color (:customization-color
operable-wallet-account)
:accounts [{:account-props {:customization-color (:color operable-wallet-account)
:size 32
:emoji (:emoji operable-wallet-account)
:type :default
@ -717,7 +716,7 @@
[:wallet :accounts]
{(:address operable-wallet-account) operable-wallet-account}))))
(let [{:keys [customization-color
(let [{:keys [color
name
address
emoji]} operable-wallet-account
@ -730,7 +729,7 @@
:operable [{:name (:name default-keypair-accounts)
:key-uid (:key-uid default-keypair-accounts)
:type (keyword (:type default-keypair-accounts))
:accounts [{:account-props {:customization-color customization-color
:accounts [{:account-props {:customization-color color
:size size-option
:emoji emoji
:type :default
@ -763,8 +762,7 @@
:operable [{:name (:name default-keypair-accounts)
:key-uid (:key-uid default-keypair-accounts)
:type (keyword (:type default-keypair-accounts))
:accounts [{:account-props {:customization-color (:customization-color
operable-wallet-account)
:accounts [{:account-props {:customization-color (:color operable-wallet-account)
:size 32
:emoji (:emoji operable-wallet-account)
:type :default

View File

@ -68,7 +68,7 @@
(defn wallet-loaded?
[]
(not @(rf/subscribe [:wallet/tokens-loading?])))
(not @(rf/subscribe [:wallet/home-tokens-loading?])))
(defn assert-messenger-started
[]