* Update wallet events and subs to handle collectibles per account Additionally, - Move collectibles related events to a new events namespace (`status-im.contexts.wallet.events.collectibles`). - Update tests to consider collectibles per account. * Update collectibles tab to handle a current viewing account
This commit is contained in:
parent
fc591f303c
commit
4ff5e4da8b
|
@ -10,7 +10,10 @@
|
|||
|
||||
(defn- view-internal
|
||||
[{:keys [theme]}]
|
||||
(let [collectible-list (rf/sub [:wallet/collectibles])]
|
||||
(let [specific-address (rf/sub [:wallet/current-viewing-account-address])
|
||||
collectible-list (if specific-address
|
||||
(rf/sub [:wallet/collectibles-per-account specific-address])
|
||||
(rf/sub [:wallet/all-collectibles]))]
|
||||
(if (empty? collectible-list)
|
||||
[empty-tab/view
|
||||
{:title (i18n/label :t/no-collectibles)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
[clojure.string :as string]
|
||||
[react-native.background-timer :as background-timer]
|
||||
[status-im.common.data-store.wallet :as data-store]
|
||||
[status-im.contexts.wallet.events.collectibles]
|
||||
[status-im.contexts.wallet.item-types :as item-types]
|
||||
[status-im.contexts.wallet.temp :as temp]
|
||||
[taoensso.timbre :as log]
|
||||
|
@ -13,8 +14,7 @@
|
|||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.number]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.transforms :as types]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :wallet/show-account-created-toast
|
||||
(fn [{:keys [db]} [address]]
|
||||
|
@ -65,10 +65,7 @@
|
|||
db
|
||||
(data-store/rpc->accounts wallet-accounts))
|
||||
:fx [[:dispatch [:wallet/get-wallet-token]]
|
||||
[:dispatch
|
||||
[:wallet/request-collectibles
|
||||
{:start-at-index 0
|
||||
:new-request? true}]]
|
||||
[:dispatch [:wallet/request-collectibles {:start-at-index 0 :new-request? true}]]
|
||||
(when new-account?
|
||||
[:dispatch [:wallet/navigate-to-new-account navigate-to-account]])]})))
|
||||
|
||||
|
@ -224,121 +221,6 @@
|
|||
data)}]
|
||||
{:db (assoc db :wallet/networks network-data)})))
|
||||
|
||||
(def collectibles-request-batch-size 1000)
|
||||
|
||||
(defn displayable-collectible?
|
||||
[collectible]
|
||||
(let [{:keys [image-url animation-url]} (:collectible-data collectible)]
|
||||
(or (not (string/blank? animation-url))
|
||||
(not (string/blank? image-url)))))
|
||||
|
||||
(defn store-collectibles
|
||||
[{:keys [db]} [collectibles]]
|
||||
(let [stored-collectibles (get-in db [:wallet :collectibles])
|
||||
displayable-collectibles (filter displayable-collectible? collectibles)]
|
||||
{:db (assoc-in db
|
||||
[:wallet :collectibles]
|
||||
(reduce conj displayable-collectibles stored-collectibles))}))
|
||||
|
||||
(rf/reg-event-fx :wallet/store-collectibles store-collectibles)
|
||||
|
||||
(defn clear-stored-collectibles
|
||||
[{:keys [db]}]
|
||||
{:db (update db :wallet dissoc :collectibles)})
|
||||
|
||||
(rf/reg-event-fx :wallet/clear-stored-collectibles clear-stored-collectibles)
|
||||
|
||||
(defn store-last-collectible-details
|
||||
[{:keys [db]} [collectible]]
|
||||
{:db (assoc-in db
|
||||
[:wallet :last-collectible-details]
|
||||
collectible)})
|
||||
|
||||
(rf/reg-event-fx :wallet/store-last-collectible-details store-last-collectible-details)
|
||||
|
||||
(def collectible-data-types
|
||||
{:unique-id 0
|
||||
:header 1
|
||||
:details 2
|
||||
:community-header 3})
|
||||
|
||||
(def fetch-type
|
||||
{:never-fetch 0
|
||||
:always-fetch 1
|
||||
:fetch-if-not-cached 2
|
||||
:fetch-if-cache-old 3})
|
||||
|
||||
(def max-cache-age-seconds 3600)
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/request-collectibles
|
||||
(fn [{:keys [db]} [{:keys [start-at-index new-request?]}]]
|
||||
(let [request-id 0
|
||||
collectibles-filter nil
|
||||
data-type (collectible-data-types :header)
|
||||
fetch-criteria {:fetch-type (fetch-type :fetch-if-not-cached)
|
||||
:max-cache-age-seconds max-cache-age-seconds}
|
||||
request-params [request-id
|
||||
[(chain/chain-id db)]
|
||||
(keys (get-in db [:wallet :accounts]))
|
||||
collectibles-filter
|
||||
start-at-index
|
||||
collectibles-request-batch-size
|
||||
data-type
|
||||
fetch-criteria]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getOwnedCollectiblesAsync"
|
||||
:params request-params
|
||||
:on-success #()
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to request collectibles"
|
||||
{:event :wallet/request-collectibles
|
||||
:error error
|
||||
:params request-params}))}]]
|
||||
(when new-request?
|
||||
[:dispatch [:wallet/clear-stored-collectibles]])]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/owned-collectibles-filtering-done
|
||||
(fn [_ [{:keys [message]}]]
|
||||
(let [response (cske/transform-keys csk/->kebab-case-keyword
|
||||
(types/json->clj message))
|
||||
{:keys [collectibles has-more offset]} response
|
||||
start-at-index (+ offset (count collectibles))]
|
||||
{:fx
|
||||
[[:dispatch [:wallet/store-collectibles collectibles]]
|
||||
(when has-more
|
||||
[:dispatch
|
||||
[:wallet/request-collectibles
|
||||
{:start-at-index start-at-index}]])]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/get-collectible-details
|
||||
(fn [_ [collectible-id]]
|
||||
(let [request-id 0
|
||||
collectible-id-converted (cske/transform-keys csk/->PascalCaseKeyword collectible-id)
|
||||
data-type (collectible-data-types :details)
|
||||
request-params [request-id [collectible-id-converted] data-type]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getCollectiblesByUniqueIDAsync"
|
||||
:params request-params
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to request collectible"
|
||||
{:event :wallet/get-collectible-details
|
||||
:error error
|
||||
:params request-params}))}]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/get-collectible-details-done
|
||||
(fn [_ [{:keys [message]}]]
|
||||
(let [response (cske/transform-keys csk/->kebab-case-keyword
|
||||
(types/json->clj message))
|
||||
{:keys [collectibles]} response
|
||||
collectible (first collectibles)]
|
||||
(if collectible
|
||||
{:fx
|
||||
[[:dispatch [:wallet/store-last-collectible-details collectible]]]}
|
||||
(log/error "failed to get collectible details"
|
||||
{:event :wallet/get-collectible-details-done
|
||||
:response response})))))
|
||||
|
||||
(rf/reg-event-fx :wallet/find-ens
|
||||
(fn [{:keys [db]} [input contacts chain-id cb]]
|
||||
(let [result (if (empty? input)
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
(ns status-im.contexts.wallet.events.collectibles
|
||||
(:require [camel-snake-kebab.core :as csk]
|
||||
[camel-snake-kebab.extras :as cske]
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as rf]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.transforms :as types]))
|
||||
|
||||
(def collectible-data-types
|
||||
{:unique-id 0
|
||||
:header 1
|
||||
:details 2
|
||||
:community-header 3})
|
||||
|
||||
(def fetch-type
|
||||
{:never-fetch 0
|
||||
:always-fetch 1
|
||||
:fetch-if-not-cached 2
|
||||
:fetch-if-cache-old 3})
|
||||
|
||||
(def max-cache-age-seconds 3600)
|
||||
(def collectibles-request-batch-size 1000)
|
||||
|
||||
(defn displayable-collectible?
|
||||
[collectible]
|
||||
(let [{:keys [image-url animation-url]} (:collectible-data collectible)]
|
||||
(or (not (string/blank? animation-url))
|
||||
(not (string/blank? image-url)))))
|
||||
|
||||
(defn- add-collectibles-to-accounts
|
||||
[accounts collectibles]
|
||||
(reduce (fn [acc {:keys [ownership] :as collectible}]
|
||||
(->> ownership
|
||||
(map :address) ; In ERC1155 tokens a collectible can be owned by multiple addresses.
|
||||
(reduce (fn add-collectible-to-address [acc address]
|
||||
(update-in acc [address :collectibles] conj collectible))
|
||||
acc)))
|
||||
accounts
|
||||
collectibles))
|
||||
|
||||
(defn store-collectibles
|
||||
[{:keys [db]} [collectibles]]
|
||||
(let [displayable-collectibles (filter displayable-collectible? collectibles)]
|
||||
{:db (update-in db [:wallet :accounts] add-collectibles-to-accounts displayable-collectibles)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/store-collectibles store-collectibles)
|
||||
|
||||
(defn clear-stored-collectibles
|
||||
[{:keys [db]}]
|
||||
{:db (update-in db [:wallet :accounts] update-vals #(dissoc % :collectibles))})
|
||||
|
||||
(rf/reg-event-fx :wallet/clear-stored-collectibles clear-stored-collectibles)
|
||||
|
||||
(defn store-last-collectible-details
|
||||
[{:keys [db]} [collectible]]
|
||||
{:db (assoc-in db [:wallet :last-collectible-details] collectible)})
|
||||
|
||||
(rf/reg-event-fx :wallet/store-last-collectible-details store-last-collectible-details)
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/request-collectibles
|
||||
(fn [{:keys [db]} [{:keys [start-at-index new-request?]}]]
|
||||
(let [request-id 0
|
||||
collectibles-filter nil
|
||||
data-type (collectible-data-types :header)
|
||||
fetch-criteria {:fetch-type (fetch-type :fetch-if-not-cached)
|
||||
:max-cache-age-seconds max-cache-age-seconds}
|
||||
request-params [request-id
|
||||
[(chain/chain-id db)]
|
||||
(keys (get-in db [:wallet :accounts]))
|
||||
collectibles-filter
|
||||
start-at-index
|
||||
collectibles-request-batch-size
|
||||
data-type
|
||||
fetch-criteria]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getOwnedCollectiblesAsync"
|
||||
:params request-params
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to request collectibles"
|
||||
{:event :wallet/request-collectibles
|
||||
:error error
|
||||
:params request-params}))}]]
|
||||
(when new-request?
|
||||
[:dispatch [:wallet/clear-stored-collectibles]])]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/owned-collectibles-filtering-done
|
||||
(fn [_ [{:keys [message]}]]
|
||||
(let [{:keys [has-more offset
|
||||
collectibles]} (cske/transform-keys csk/->kebab-case-keyword (types/json->clj message))
|
||||
start-at-index (+ offset (count collectibles))]
|
||||
{:fx [[:dispatch [:wallet/store-collectibles collectibles]]
|
||||
(when has-more
|
||||
[:dispatch [:wallet/request-collectibles {:start-at-index start-at-index}]])]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/get-collectible-details
|
||||
(fn [_ [collectible-id]]
|
||||
(let [request-id 0
|
||||
collectible-id-converted (cske/transform-keys csk/->PascalCaseKeyword collectible-id)
|
||||
data-type (collectible-data-types :details)
|
||||
request-params [request-id [collectible-id-converted] data-type]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getCollectiblesByUniqueIDAsync"
|
||||
:params request-params
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to request collectible"
|
||||
{:event :wallet/get-collectible-details
|
||||
:error error
|
||||
:params request-params}))}]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/get-collectible-details-done
|
||||
(fn [_ [{:keys [message]}]]
|
||||
(let [response (cske/transform-keys csk/->kebab-case-keyword
|
||||
(types/json->clj message))
|
||||
{:keys [collectibles]} response
|
||||
collectible (first collectibles)]
|
||||
(if collectible
|
||||
{:fx [[:dispatch [:wallet/store-last-collectible-details collectible]]]}
|
||||
(log/error "failed to get collectible details"
|
||||
{:event :wallet/get-collectible-details-done
|
||||
:response response})))))
|
|
@ -2,7 +2,8 @@
|
|||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
matcher-combinators.test
|
||||
[status-im.contexts.wallet.events :as events]))
|
||||
[status-im.contexts.wallet.events :as events]
|
||||
[status-im.contexts.wallet.events.collectibles :as collectibles]))
|
||||
|
||||
(def address "0x2f88d65f3cb52605a54a833ae118fb1363acccd2")
|
||||
|
||||
|
@ -35,27 +36,40 @@
|
|||
[false {:collectible-data {:image-url nil :animation-url ""}}]
|
||||
[false {:collectible-data {:image-url "" :animation-url ""}}]]]
|
||||
(doseq [[result collection] expected-results]
|
||||
(is (match? result (events/displayable-collectible? collection))))))
|
||||
(is (match? result (collectibles/displayable-collectible? collection))))))
|
||||
|
||||
(testing "save-collectibles-request-details"
|
||||
(let [db {:wallet {}}
|
||||
collectibles [{:collectible-data {:image-url "https://..." :animation-url "https://..."}}
|
||||
{:collectible-data {:image-url "" :animation-url "https://..."}}
|
||||
{:collectible-data {:image-url "" :animation-url nil}}]
|
||||
expected-db {:wallet {:collectibles [{:collectible-data
|
||||
{:image-url "https://..." :animation-url "https://..."}}
|
||||
{:collectible-data
|
||||
{:image-url "" :animation-url "https://..."}}]}}
|
||||
effects (events/store-collectibles {:db db} [collectibles])
|
||||
(let [db {:wallet {:accounts {"0x1" {}
|
||||
"0x3" {}}}}
|
||||
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"}]}
|
||||
collectibles [collectible-1 collectible-2 collectible-3]
|
||||
expected-db {:wallet {:accounts {"0x1" {:collectibles (list collectible-2 collectible-1)}
|
||||
"0x2" {:collectibles (list collectible-3)}
|
||||
"0x3" {}}}}
|
||||
effects (collectibles/store-collectibles {:db db} [collectibles])
|
||||
result-db (:db effects)]
|
||||
(is (match? result-db expected-db)))))
|
||||
|
||||
(deftest clear-stored-collectibles
|
||||
(let [db {:wallet {:collectibles [{:id 1} {:id 2}]}}]
|
||||
(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 {}}
|
||||
effects (events/clear-stored-collectibles {:db db})
|
||||
(let [expected-db {:wallet {:accounts {"0x1" {}
|
||||
"0x2" {"some other stuff" "with any value"}
|
||||
"0x3" {}}}}
|
||||
effects (collectibles/clear-stored-collectibles {:db db})
|
||||
result-db (:db effects)]
|
||||
|
||||
(is (match? result-db expected-db))))))
|
||||
|
||||
(deftest store-last-collectible-details
|
||||
|
@ -65,6 +79,6 @@
|
|||
:image-url "https://..."}
|
||||
expected-db {:wallet {:last-collectible-details {:description "Pandaria"
|
||||
:image-url "https://..."}}}
|
||||
effects (events/store-last-collectible-details {:db db} [last-collectible])
|
||||
effects (collectibles/store-last-collectible-details {:db db} [last-collectible])
|
||||
result-db (:db effects)]
|
||||
(is (match? result-db expected-db)))))
|
||||
|
|
|
@ -11,12 +11,24 @@
|
|||
image-url))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/collectibles
|
||||
:wallet/collectibles-per-account
|
||||
:<- [:wallet]
|
||||
(fn [wallet [_ address]]
|
||||
(as-> wallet $
|
||||
(get-in $ [:accounts address :collectibles])
|
||||
(map (fn [{:keys [collectible-data] :as collectible}]
|
||||
(assoc collectible :preview-url (preview-url collectible-data)))
|
||||
$))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/all-collectibles
|
||||
:<- [:wallet]
|
||||
(fn [wallet]
|
||||
(map (fn [collectible]
|
||||
(assoc collectible :preview-url (preview-url (:collectible-data collectible))))
|
||||
(:collectibles wallet))))
|
||||
(->> wallet
|
||||
:accounts
|
||||
(mapcat (comp :collectibles val))
|
||||
(map (fn [{:keys [collectible-data] :as collectible}]
|
||||
(assoc collectible :preview-url (preview-url collectible-data)))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/last-collectible-details
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
:<- [:wallet/ui]
|
||||
:-> :tokens-loading?)
|
||||
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/current-viewing-account-address
|
||||
:<- [:wallet]
|
||||
|
|
Loading…
Reference in New Issue