diff --git a/src/status_im/contexts/wallet/collectible/events.cljs b/src/status_im/contexts/wallet/collectible/events.cljs index 39f1f1df5c18..4c641e02a769 100644 --- a/src/status_im/contexts/wallet/collectible/events.cljs +++ b/src/status_im/contexts/wallet/collectible/events.cljs @@ -346,17 +346,10 @@ {:event :wallet/get-collectible-details-done :response response}))))) -(defn group-collectibles-by-ownership-address - [collectible] - (->> (:ownership collectible) - (map (fn [{:keys [address]}] - [address collectible])) - (into {}))) - (rf/reg-event-fx :wallet/update-collectibles-data (fn [{:keys [db]} [collectible]] - (let [collectibles-by-address (group-collectibles-by-ownership-address collectible)] + (let [collectibles-by-address (collectible-utils/group-collectibles-by-ownership-address collectible)] {:db (update-in db [:wallet :accounts] #(reduce-kv diff --git a/src/status_im/contexts/wallet/collectible/utils.cljs b/src/status_im/contexts/wallet/collectible/utils.cljs index 22af847cffb3..bbe76c7fe979 100644 --- a/src/status_im/contexts/wallet/collectible/utils.cljs +++ b/src/status_im/contexts/wallet/collectible/utils.cljs @@ -5,7 +5,7 @@ [taoensso.timbre :as log] [utils.number :as utils.number])) -(defn total-collectible-balance +(defn- total-collectible-balance ([ownership] (reduce (fn [total {:keys [balance]}] (+ total (or (js/parseInt balance) 0))) @@ -88,3 +88,10 @@ acc))) {}) vals)) + +(defn group-collectibles-by-ownership-address + [collectible] + (->> (:ownership collectible) + (map (fn [{:keys [address]}] + [address collectible])) + (into {}))) diff --git a/src/status_im/contexts/wallet/collectible/utils_test.cljs b/src/status_im/contexts/wallet/collectible/utils_test.cljs index 2fad8fb3ab06..7d10eb4d8f55 100644 --- a/src/status_im/contexts/wallet/collectible/utils_test.cljs +++ b/src/status_im/contexts/wallet/collectible/utils_test.cljs @@ -44,3 +44,60 @@ :token-id token-id :test-networks-enabled? true}) "https://testnets.opensea.io/assets/optimism-sepolia/0xC/0xT")))) + +(deftest collectible-balance-test + (testing "Returns balance for a specific address" + (let [collectible {:ownership [{:address "0x123" :balance "10"} + {:address "0x456" :balance "20"}]}] + (is (= 10 (utils/collectible-balance collectible "0x123"))) + (is (= 20 (utils/collectible-balance collectible "0x456"))) + (is (nil? (utils/collectible-balance collectible "0x789"))))) + + (testing "Returns total balance when no address is provided" + (let [collectible {:ownership [{:address "0x123" :balance "10"} + {:address "0x456" :balance "20"} + {:address "0x789" :balance nil}]}] + (is (= 30 (utils/collectible-balance collectible nil))))) + + (testing "Returns 0 when ownership is empty" + (let [collectible {:ownership []}] + (is (= 0 (utils/collectible-balance collectible nil))))) + + (testing "Handles nil balance values correctly" + (let [collectible {:ownership [{:address "0x123" :balance nil} + {:address "0x456" :balance nil}]}] + (is (= 0 (utils/collectible-balance collectible nil)))))) + +(deftest group-collectibles-by-ownership-address-test + (testing "Groups collectibles by ownership address correctly" + (let [collectible {:id {:contract-id {:chain-id 10 :address "0xContract"} :token-id "1"} + :ownership [{:address "0x123" :balance 10} + {:address "0x456" :balance 20}]} + expected {"0x123" collectible + "0x456" collectible}] + (is (= expected (utils/group-collectibles-by-ownership-address collectible))))) + + (testing "Returns an empty map when there is no ownership data" + (let [collectible {:id {:contract-id {:chain-id 10 :address "0xContract"} :token-id "1"} + :ownership []}] + (is (= {} (utils/group-collectibles-by-ownership-address collectible))))) + + (testing "Handles ownership with nil address values" + (let [collectible {:id {:contract-id {:chain-id 10 :address "0xContract"} :token-id "1"} + :ownership [{:address nil :balance 10} + {:address "0x456" :balance 20}]} + expected {"0x456" collectible}] + (is (= expected (utils/group-collectibles-by-ownership-address collectible))))) + + (testing "Handles duplicate ownership addresses" + (let [collectible {:id {:contract-id {:chain-id 10 :address "0xContract"} :token-id "1"} + :ownership [{:address "0x123" :balance 10} + {:address "0x123" :balance 5}]} + expected {"0x123" collectible}] + (is (= expected (utils/group-collectibles-by-ownership-address collectible))))) + + (testing "Handles collectibles with no address in ownership" + (let [collectible {:id {:contract-id {:chain-id 10 :address "0xContract"} :token-id "1"} + :ownership [{:balance 10}]} + expected {}] + (is (= expected (utils/group-collectibles-by-ownership-address collectible)))))) diff --git a/src/status_im/contexts/wallet/data_store.cljs b/src/status_im/contexts/wallet/data_store.cljs index cdf1e7203d43..3922b27e3a92 100644 --- a/src/status_im/contexts/wallet/data_store.cljs +++ b/src/status_im/contexts/wallet/data_store.cljs @@ -300,7 +300,7 @@ keypair (get keypairs selected-keypair-uid)] (boolean (seq (:keycards keypair))))) -(defn transform-collectible +(defn- transform-collectible [{:keys [added updated removed]}] (let [entry (first (remove nil? (concat added updated removed)))] (when entry diff --git a/src/status_im/contexts/wallet/data_store_test.cljs b/src/status_im/contexts/wallet/data_store_test.cljs index 6b30f1574836..d0f71143c5c4 100644 --- a/src/status_im/contexts/wallet/data_store_test.cljs +++ b/src/status_im/contexts/wallet/data_store_test.cljs @@ -265,3 +265,34 @@ (testing "returns false when db does not contain wallet data" (let [db {}] (is (false? (sut/selected-keypair-keycard? db)))))) + +(deftest rpc->collectible-id-test + (testing "Transforms JSON and returns collectible ID when valid data is provided" + (let [json {:added nil + :updated [{:contractID {:chainID 11155111 + :address "0x5ac615dc2507bc382d4714a74a707bc4d385c3e7"} + :tokenID 1}] + :removed nil}] + (is (= {:contract-id {:chain-id 11155111 + :address "0x5ac615dc2507bc382d4714a74a707bc4d385c3e7"} + :token-id "1"} + (sut/rpc->collectible-id json))))) + + (testing "Returns nil for empty JSON input" + (let [json {}] + (is (nil? (sut/rpc->collectible-id json))))) + + (testing "Handles malformed data gracefully" + (let [json {:unexpected-key [{:id 1}]}] + (is (nil? (sut/rpc->collectible-id json))))) + + (testing "Returns transformed collectible ID when JSON contains only `added` key" + (let [json {:added [{:contractID {:chainID 222 + :address "0x123456"} + :tokenID 77}] + :updated nil + :removed nil}] + (is (= {:contract-id {:chain-id 222 + :address "0x123456"} + :token-id "77"} + (sut/rpc->collectible-id json))))))