Wrong number of collectibles in the list and they are mixed up [#4904]
Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
parent
4c3b9e1555
commit
ee317c4aeb
|
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
### Added
|
||||
- Added Farsi public #status channel
|
||||
- Spam moderation
|
||||
- Collectibles support (CryptoKitties, CryptoStrikers and Etheremon)
|
||||
|
||||
## [0.9.21] - 2018-06-25
|
||||
### Added
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
(ns status-im.ui.components.svgimage
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.utils.platform :as platform]))
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.http :as http]))
|
||||
|
||||
(defn html [uri width height]
|
||||
(str
|
||||
|
@ -38,7 +39,7 @@
|
|||
(defn svgimage [{:keys [style source]}]
|
||||
(let [width (reagent/atom nil)
|
||||
{:keys [uri k] :or {k 1}} source]
|
||||
(when (re-find #"^(https:)([/|.|\w|\s|-])*\.(?:jpg|svg|png)$" uri)
|
||||
(when (http/url-sanitized? uri)
|
||||
(fn []
|
||||
[react/view {:style style
|
||||
:on-layout #(reset! width (-> % .-nativeEvent .-layout .-width))}
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
|
||||
(spec/def :navigation.screen-params/usage-data vector?)
|
||||
|
||||
(spec/def :navigation.screen-params/display-collectible map?)
|
||||
(spec/def :navigation.screen-params/collectibles-list map?)
|
||||
|
||||
(spec/def :navigation/screen-params (spec/nilable (allowed-keys :opt-un [:navigation.screen-params/network-details
|
||||
:navigation.screen-params/browser
|
||||
|
@ -124,7 +124,7 @@
|
|||
:navigation.screen-params/edit-contact-group
|
||||
:navigation.screen-params/dapp-description
|
||||
:navigation.screen-params/usage-data
|
||||
:navigation.screen-params/display-collectible])))
|
||||
:navigation.screen-params/collectibles-list])))
|
||||
|
||||
(spec/def :desktop/desktop (spec/nilable any?))
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
status-im.ui.screens.wallet.settings.events
|
||||
status-im.ui.screens.wallet.transactions.events
|
||||
status-im.ui.screens.wallet.choose-recipient.events
|
||||
status-im.ui.screens.wallet.collectibles.cryptokitties.events
|
||||
status-im.ui.screens.wallet.collectibles.cryptostrikers.events
|
||||
status-im.ui.screens.wallet.collectibles.etheremon.events
|
||||
status-im.ui.screens.browser.events
|
||||
status-im.ui.screens.offline-messaging-settings.events
|
||||
status-im.ui.screens.bootnodes-settings.events
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
[status-im.ui.screens.profile.contact.views :as profile.contact]
|
||||
[status-im.ui.screens.profile.group-chat.views :as profile.group-chat]
|
||||
[status-im.ui.screens.profile.photo-capture.views :refer [profile-photo-capture]]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles]
|
||||
[status-im.ui.screens.wallet.collectibles.views :refer [collectibles-list]]
|
||||
[status-im.ui.screens.wallet.send.views :refer [send-transaction send-transaction-modal sign-message-modal]]
|
||||
[status-im.ui.screens.wallet.choose-recipient.views :refer [choose-recipient]]
|
||||
[status-im.ui.screens.wallet.request.views :refer [request-transaction send-transaction-request]]
|
||||
|
@ -54,7 +54,7 @@
|
|||
|
||||
(defn get-main-component [view-id]
|
||||
(case view-id
|
||||
:display-collectible collectibles/display-collectible
|
||||
:collectibles-list collectibles-list
|
||||
:intro intro
|
||||
:create-account create-account
|
||||
:usage-data usage-data
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.cryptokitties
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.action-button.action-button :as action-button]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles]
|
||||
[status-im.ui.screens.wallet.collectibles.styles :as styles]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.ui.components.svgimage :as svgimage]))
|
||||
|
||||
(def ck :CK)
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:load-kitties
|
||||
(fn [{db :db} [_ ids]]
|
||||
{:db db
|
||||
:http-get-n (mapv (fn [id]
|
||||
{:url (str "https://api.cryptokitties.co/kitties/" id)
|
||||
:success-event-creator (fn [o]
|
||||
[:load-collectible-success ck {id (http/parse-payload o)}])
|
||||
:failure-event-creator (fn [o]
|
||||
[:load-collectible-failure ck {id (http/parse-payload o)}])})
|
||||
ids)}))
|
||||
|
||||
(defn kitties-url [address]
|
||||
(str "https://api.cryptokitties.co/kitties?offset=0&limit=20&owner_wallet_address=" address "&parents=false"))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:load-kitties-success
|
||||
(fn [{db :db} [_ ids]]
|
||||
{:db db
|
||||
:dispatch [:load-kitties ids]}))
|
||||
|
||||
;; TODO(julien) Each HTTP call will return up to 20 kitties. Make sure all extra kitties are fetched
|
||||
(defmethod collectibles/load-collectibles-fx ck [_ _ _ address]
|
||||
{:http-get {:url (kitties-url address)
|
||||
:success-event-creator (fn [o]
|
||||
[:load-kitties-success (map :id (:kitties (http/parse-payload o)))])
|
||||
:failure-event-creator (fn [o]
|
||||
[:load-collectibles-failure (http/parse-payload o)])
|
||||
:timeout-ms 10000}})
|
||||
|
||||
(def base-url "https://www.cryptokitties.co/kitty/")
|
||||
|
||||
(defmethod collectibles/render-collectible ck [_ {:keys [id name bio image_url]}]
|
||||
[react/view {:style styles/details}
|
||||
[react/view {:style styles/details-text}
|
||||
[svgimage/svgimage {:style styles/details-image
|
||||
:source {:uri image_url}}]
|
||||
[react/view {:flex 1}
|
||||
[react/text {:style styles/details-name}
|
||||
(or name (i18n/label :t/cryptokitty-name {:id id}))]
|
||||
[react/text {:number-of-lines 3
|
||||
:ellipsize-mode :tail}
|
||||
bio]]]
|
||||
[action-button/action-button {:label (i18n/label :t/view-cryptokitties)
|
||||
:icon :icons/address
|
||||
:icon-opts {:color colors/blue}
|
||||
:accessibility-label :open-collectible-button
|
||||
:on-press #(re-frame/dispatch [:open-browser {:url (str base-url id)}])}]])
|
|
@ -0,0 +1,31 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.cryptokitties.events
|
||||
(:require [status-im.utils.handlers :as handlers]
|
||||
[status-im.ui.screens.wallet.collectibles.events :as collectibles]
|
||||
[status-im.utils.http :as http]))
|
||||
|
||||
(def ck :CK)
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:load-kitties
|
||||
(fn [{db :db} [_ ids]]
|
||||
{:db db
|
||||
:http-get-n (mapv (fn [id]
|
||||
{:url (str "https://api.cryptokitties.co/kitties/" id)
|
||||
:success-event-creator (fn [o]
|
||||
[:load-collectible-success ck {id (http/parse-payload o)}])
|
||||
:failure-event-creator (fn [o]
|
||||
[:load-collectible-failure ck {id (http/parse-payload o)}])})
|
||||
ids)}))
|
||||
|
||||
;; TODO(andrey) Each HTTP call will return up to 100 kitties. Maybe we need to implement some kind of paging later
|
||||
(defmethod collectibles/load-collectibles-fx ck [_ _ items-number address]
|
||||
{:http-get {:url (str "https://api.cryptokitties.co/kitties?offset=0&limit="
|
||||
items-number
|
||||
"&owner_wallet_address="
|
||||
address
|
||||
"&parents=false")
|
||||
:success-event-creator (fn [o]
|
||||
[:load-kitties (map :id (:kitties (http/parse-payload o)))])
|
||||
:failure-event-creator (fn [o]
|
||||
[:load-collectibles-failure (http/parse-payload o)])
|
||||
:timeout-ms 10000}})
|
|
@ -0,0 +1,28 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.cryptokitties.views
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.action-button.action-button :as action-button]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.wallet.collectibles.styles :as styles]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles]
|
||||
[status-im.ui.components.svgimage :as svgimage]))
|
||||
|
||||
(defmethod collectibles/render-collectible :CK [_ {:keys [id name bio image_url]}]
|
||||
[react/view {:style styles/details}
|
||||
[react/view {:style styles/details-text}
|
||||
[svgimage/svgimage {:style styles/details-image
|
||||
:source {:uri image_url}}]
|
||||
[react/view {:flex 1}
|
||||
[react/text {:style styles/details-name}
|
||||
(or name (i18n/label :t/cryptokitty-name {:id id}))]
|
||||
[react/text {:number-of-lines 3
|
||||
:ellipsize-mode :tail}
|
||||
bio]]]
|
||||
[action-button/action-button
|
||||
{:label (i18n/label :t/view-cryptokitties)
|
||||
:icon :icons/address
|
||||
:icon-opts {:color colors/blue}
|
||||
:accessibility-label :open-collectible-button
|
||||
:on-press #(re-frame/dispatch [:open-browser
|
||||
{:url (str "https://www.cryptokitties.co/kitty/" id)}])}]])
|
|
@ -1,36 +0,0 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.cryptostrikers
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.action-button.action-button :as action-button]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.wallet.collectibles.styles :as styles]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.ui.components.svgimage :as svgimage]))
|
||||
|
||||
(def strikers :STRK)
|
||||
|
||||
(defmethod collectibles/load-collectible-fx strikers [_ id]
|
||||
{:http-get {:url (str "https://us-central1-cryptostrikers-prod.cloudfunctions.net/cards/" id)
|
||||
:success-event-creator (fn [o]
|
||||
[:load-collectible-success strikers {id (http/parse-payload o)}])
|
||||
:failure-event-creator (fn [o]
|
||||
[:load-collectible-failure strikers {id (http/parse-payload o)}])}})
|
||||
|
||||
(defmethod collectibles/render-collectible strikers [_ {:keys [external_url description name image]}]
|
||||
[react/view {:style styles/details}
|
||||
[react/view {:style styles/details-text}
|
||||
[svgimage/svgimage {:style styles/details-image
|
||||
:source {:uri image
|
||||
:k 1.4}}]
|
||||
[react/view {:flex 1 :justify-content :center}
|
||||
[react/text {:style styles/details-name}
|
||||
name]
|
||||
[react/text
|
||||
description]]]
|
||||
[action-button/action-button {:label (i18n/label :t/view-cryptostrikers)
|
||||
:icon :icons/address
|
||||
:icon-opts {:color colors/blue}
|
||||
:accessibility-label :open-collectible-button
|
||||
:on-press #(re-frame/dispatch [:open-browser {:url external_url}])}]])
|
|
@ -0,0 +1,12 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.cryptostrikers.events
|
||||
(:require [status-im.ui.screens.wallet.collectibles.events :as collectibles]
|
||||
[status-im.utils.http :as http]))
|
||||
|
||||
(def strikers :STRK)
|
||||
|
||||
(defmethod collectibles/load-collectible-fx strikers [_ id]
|
||||
{:http-get {:url (str "https://us-central1-cryptostrikers-prod.cloudfunctions.net/cards/" id)
|
||||
:success-event-creator (fn [o]
|
||||
[:load-collectible-success strikers {id (http/parse-payload o)}])
|
||||
:failure-event-creator (fn [o]
|
||||
[:load-collectible-failure strikers {id (http/parse-payload o)}])}})
|
|
@ -0,0 +1,27 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.cryptostrikers.views
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.action-button.action-button :as action-button]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.wallet.collectibles.styles :as styles]
|
||||
[status-im.ui.components.svgimage :as svgimage]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles]))
|
||||
|
||||
(defmethod collectibles/render-collectible :STRK [_ {:keys [external_url description name image]}]
|
||||
[react/view {:style styles/details}
|
||||
[react/view {:style styles/details-text}
|
||||
[svgimage/svgimage {:style styles/details-image
|
||||
:source {:uri image
|
||||
:k 1.4}}]
|
||||
[react/view {:flex 1 :justify-content :center}
|
||||
[react/text {:style styles/details-name}
|
||||
name]
|
||||
[react/text
|
||||
description]]]
|
||||
[action-button/action-button
|
||||
{:label (i18n/label :t/view-cryptostrikers)
|
||||
:icon :icons/address
|
||||
:icon-opts {:color colors/blue}
|
||||
:accessibility-label :open-collectible-button
|
||||
:on-press #(re-frame/dispatch [:open-browser {:url external_url}])}]])
|
|
@ -1,37 +0,0 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.etheremon
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.action-button.action-button :as action-button]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.wallet.collectibles.styles :as styles]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.ui.components.svgimage :as svgimage]))
|
||||
|
||||
(def emona :EMONA)
|
||||
|
||||
(defmethod collectibles/load-collectible-fx emona [_ id]
|
||||
{:http-get {:url (str "https://www.etheremon.com/api/monster/get_data?monster_ids=" id)
|
||||
:success-event-creator (fn [o]
|
||||
[:load-collectible-success emona (:data (http/parse-payload o))])
|
||||
:failure-event-creator (fn [o]
|
||||
[:load-collectible-failure emona {id (http/parse-payload o)}])}})
|
||||
|
||||
(def base-url "https://www.etheremon.com/#/mons/")
|
||||
|
||||
(defmethod collectibles/render-collectible emona [_ {:keys [monster_id user_defined_name image]}]
|
||||
[react/view {:style styles/details}
|
||||
[react/view {:style styles/details-text}
|
||||
[react/view {:flex 1}
|
||||
[svgimage/svgimage {:style styles/details-image
|
||||
:source {:uri image
|
||||
:k 2}}]]
|
||||
[react/view {:flex 1 :justify-content :center}
|
||||
[react/text {:style styles/details-name}
|
||||
user_defined_name]]]
|
||||
[action-button/action-button {:label (i18n/label :t/view-etheremon)
|
||||
:icon :icons/address
|
||||
:icon-opts {:color colors/blue}
|
||||
:accessibility-label :open-collectible-button
|
||||
:on-press #(re-frame/dispatch [:open-browser {:url (str base-url monster_id)}])}]])
|
|
@ -0,0 +1,12 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.etheremon.events
|
||||
(:require [status-im.ui.screens.wallet.collectibles.events :as collectibles]
|
||||
[status-im.utils.http :as http]))
|
||||
|
||||
(def emona :EMONA)
|
||||
|
||||
(defmethod collectibles/load-collectible-fx emona [_ id]
|
||||
{:http-get {:url (str "https://www.etheremon.com/api/monster/get_data?monster_ids=" id)
|
||||
:success-event-creator (fn [o]
|
||||
[:load-collectible-success emona (:data (http/parse-payload o))])
|
||||
:failure-event-creator (fn [o]
|
||||
[:load-collectible-failure emona {id (http/parse-payload o)}])}})
|
|
@ -0,0 +1,27 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.etheremon.views
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.action-button.action-button :as action-button]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.wallet.collectibles.styles :as styles]
|
||||
[status-im.ui.components.svgimage :as svgimage]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles]))
|
||||
|
||||
(defmethod collectibles/render-collectible :EMONA [_ {:keys [user_defined_name image class_id]}]
|
||||
[react/view {:style styles/details}
|
||||
[react/view {:style styles/details-text}
|
||||
[react/view {:flex 1}
|
||||
[svgimage/svgimage {:style styles/details-image
|
||||
:source {:uri image
|
||||
:k 2}}]]
|
||||
[react/view {:flex 1 :justify-content :center}
|
||||
[react/text {:style styles/details-name}
|
||||
user_defined_name]]]
|
||||
[action-button/action-button
|
||||
{:label (i18n/label :t/view-etheremon)
|
||||
:icon :icons/address
|
||||
:icon-opts {:color colors/blue}
|
||||
:accessibility-label :open-collectible-button
|
||||
:on-press #(re-frame/dispatch [:open-browser
|
||||
{:url (str "https://www.etheremon.com/#/mons/" class_id)}])}]])
|
|
@ -1,6 +1,45 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.events
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.handlers :as handlers]))
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.ethereum.erc721 :as erc721]
|
||||
[status-im.utils.ethereum.tokens :as tokens]
|
||||
[status-im.utils.money :as money]))
|
||||
|
||||
(defmulti load-collectible-fx (fn [symbol _] symbol))
|
||||
|
||||
(defmethod load-collectible-fx :default [_ _] nil)
|
||||
|
||||
(defmulti load-collectibles-fx (fn [_ symbol _ _] symbol))
|
||||
|
||||
(defmethod load-collectibles-fx :default [web3 symbol items-number address]
|
||||
{:load-collectibles-fx [web3 symbol items-number address]})
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:show-collectibles-list
|
||||
(fn [{:keys [db]} [_ address {:keys [symbol amount] :as collectible}]]
|
||||
(let [items-number (money/to-number amount)
|
||||
loaded-items-number (count (get-in db [:collectibles symbol]))]
|
||||
(merge (when (not= items-number loaded-items-number)
|
||||
(load-collectibles-fx (:web3 db) symbol items-number address))
|
||||
{:dispatch [:navigate-to :collectibles-list collectible]}))))
|
||||
|
||||
(defn load-token [web3 i items-number contract address symbol]
|
||||
(when (< i items-number)
|
||||
(erc721/token-of-owner-by-index web3 contract address i
|
||||
(fn [v1 v2]
|
||||
(load-token web3 (inc i) items-number contract address symbol)
|
||||
(re-frame/dispatch [:load-collectible symbol (.toNumber v2)])))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:load-collectibles-fx
|
||||
(fn [[web3 symbol items-number address]]
|
||||
(let [contract (:address (tokens/symbol->token :mainnet symbol))]
|
||||
(load-token web3 0 items-number contract address symbol))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:load-collectible
|
||||
(fn [_ [_ symbol token-id]]
|
||||
(load-collectible-fx symbol token-id)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:load-collectible-success
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.subs
|
||||
(:require [re-frame.core :as re-frame]))
|
||||
|
||||
(re-frame/reg-sub :collectibles
|
||||
(fn [db [_ s]]
|
||||
(vals (get-in db [:collectibles s]))))
|
||||
(re-frame/reg-sub :collectibles :collectibles)
|
||||
|
||||
(re-frame/reg-sub
|
||||
:screen-collectibles
|
||||
:<- [:collectibles]
|
||||
:<- [:get-screen-params]
|
||||
(fn [[collectibles {:keys [symbol]}]]
|
||||
(mapv #(assoc (second %) :id (first %)) (get collectibles symbol))))
|
|
@ -1,7 +1,6 @@
|
|||
(ns status-im.ui.screens.wallet.collectibles.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
(:require [status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]
|
||||
|
@ -9,33 +8,24 @@
|
|||
[status-im.ui.components.toolbar.view :as toolbar]
|
||||
[status-im.ui.screens.wallet.collectibles.styles :as styles]))
|
||||
|
||||
(defmulti load-collectible-fx (fn [symbol _] symbol))
|
||||
|
||||
(defmethod load-collectible-fx :default [_ _] nil)
|
||||
|
||||
(defmulti load-collectibles-fx (fn [_ symbol _ _] symbol))
|
||||
|
||||
(defmethod load-collectibles-fx :default [web3 symbol i address]
|
||||
{:load-collectibles [web3 symbol i address]})
|
||||
|
||||
(defmulti render-collectible (fn [symbol _] symbol))
|
||||
|
||||
(defmethod render-collectible :default [symbol {:keys [id name]}]
|
||||
[react/view {:style styles/default-collectible}
|
||||
[react/text (str (clojure.core/name symbol) " #" (or id name))]])
|
||||
|
||||
(defview display-collectible []
|
||||
(letsubs [{:keys [name symbol]} [:get-screen-params]]
|
||||
(let [collectibles @(re-frame/subscribe [:collectibles symbol])]
|
||||
[react/view {:style component.styles/flex}
|
||||
(if (seq collectibles)
|
||||
[react/view {:style component.styles/flex}
|
||||
[status-bar/status-bar]
|
||||
[toolbar/toolbar {}
|
||||
toolbar/default-nav-back
|
||||
[toolbar/content-title name]]
|
||||
[list/flat-list {:data collectibles
|
||||
:key-fn (comp str :id)
|
||||
:render-fn #(render-collectible symbol %)}]]
|
||||
[react/view {:style styles/loading-indicator}
|
||||
[react/activity-indicator {:animating true :size :large :color colors/blue}]])])))
|
||||
(defview collectibles-list []
|
||||
(letsubs [{:keys [name symbol]} [:get-screen-params]
|
||||
collectibles [:screen-collectibles]]
|
||||
[react/view {:style component.styles/flex}
|
||||
[react/view {:style component.styles/flex}
|
||||
[status-bar/status-bar]
|
||||
[toolbar/toolbar {}
|
||||
toolbar/default-nav-back
|
||||
[toolbar/content-title name]]
|
||||
(if (seq collectibles)
|
||||
[list/flat-list {:data collectibles
|
||||
:key-fn (comp str :id)
|
||||
:render-fn #(render-collectible symbol %)}]
|
||||
[react/view {:style styles/loading-indicator}
|
||||
[react/activity-indicator {:animating true :size :large :color colors/blue}]])]]))
|
|
@ -14,8 +14,6 @@
|
|||
status-im.ui.screens.wallet.request.events
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles]
|
||||
[status-im.utils.ethereum.erc721 :as erc721]
|
||||
[status-im.utils.money :as money]))
|
||||
|
||||
(defn get-balance [{:keys [web3 account-id on-success on-error]}]
|
||||
|
@ -282,22 +280,3 @@
|
|||
{:db (-> db
|
||||
(assoc-in [:wallet :send-transaction] {})
|
||||
(navigation/navigate-back))}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet/show-collectibles
|
||||
(fn [{:keys [db]} [_ i address {:keys [symbol] :as m}]]
|
||||
(assoc (collectibles/load-collectibles-fx (:web3 db) symbol i address)
|
||||
:dispatch [:navigate-to :display-collectible m])))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:load-collectibles
|
||||
(fn [[web3 symbol i address]]
|
||||
(dotimes [n i]
|
||||
(erc721/token-of-owner-by-index web3 (:address (tokens/symbol->token :mainnet symbol)) address n
|
||||
#(re-frame/dispatch [:load-collectible symbol (.toNumber %2)])))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:load-collectible
|
||||
(fn [{db :db} [_ symbol id]]
|
||||
(assoc (collectibles/load-collectible-fx symbol id)
|
||||
:db db)))
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
[status-im.ui.screens.wallet.styles :as styles]
|
||||
[status-im.ui.screens.wallet.utils :as wallet.utils]
|
||||
[status-im.utils.money :as money]
|
||||
status-im.ui.screens.wallet.collectibles.cryptokitties
|
||||
status-im.ui.screens.wallet.collectibles.cryptostrikers
|
||||
status-im.ui.screens.wallet.collectibles.etheremon))
|
||||
status-im.ui.screens.wallet.collectibles.etheremon.views
|
||||
status-im.ui.screens.wallet.collectibles.cryptostrikers.views
|
||||
status-im.ui.screens.wallet.collectibles.cryptokitties.views))
|
||||
|
||||
(defn toolbar-view []
|
||||
[toolbar/toolbar {:style styles/toolbar :flat? true}
|
||||
|
@ -88,11 +88,12 @@
|
|||
[list/item-icon {:icon :icons/forward
|
||||
:icon-opts {:color :gray}}])
|
||||
|
||||
(defn- render-collectible [address-hex {:keys [symbol name icon amount] :as m}]
|
||||
(let [i (money/to-fixed amount)
|
||||
details? (pos? i)]
|
||||
[react/touchable-highlight (when details?
|
||||
{:on-press #(re-frame/dispatch [:wallet/show-collectibles i address-hex m])})
|
||||
(defn- render-collectible [address-hex {:keys [symbol name icon amount] :as collectible}]
|
||||
(let [items-number (money/to-fixed amount)
|
||||
details? (pos? items-number)]
|
||||
[react/touchable-highlight
|
||||
(when details?
|
||||
{:on-press #(re-frame/dispatch [:show-collectibles-list address-hex collectible])})
|
||||
[react/view {:style styles/asset-item-container}
|
||||
[list/item
|
||||
[list/item-image icon]
|
||||
|
@ -100,8 +101,9 @@
|
|||
[react/text {:style styles/asset-item-value
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail
|
||||
:accessibility-label (str (-> symbol clojure.core/name clojure.string/lower-case) "-collectible-value-text")}
|
||||
(or i 0)]
|
||||
:accessibility-label (str (-> symbol clojure.core/name clojure.string/lower-case)
|
||||
"-collectible-value-text")}
|
||||
(or items-number "...")]
|
||||
[react/text {:style styles/asset-item-currency
|
||||
:number-of-lines 1}
|
||||
name]]
|
||||
|
|
|
@ -6,5 +6,9 @@
|
|||
|
||||
(defn token-of-owner-by-index [web3 contract address index cb]
|
||||
(ethereum/call web3
|
||||
(ethereum/call-params contract "tokenOfOwnerByIndex(address,uint256)" (ethereum/normalized-address address) index)
|
||||
(ethereum/call-params
|
||||
contract
|
||||
"tokenOfOwnerByIndex(address,uint256)"
|
||||
(ethereum/normalized-address address)
|
||||
(ethereum/int->hex index))
|
||||
#(cb %1 (ethereum/hex->bignumber %2))))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.utils.ethereum.tokens
|
||||
(:require-macros [status-im.utils.ethereum.macros :refer [resolve-icons]])
|
||||
(:require [clojure.string :as string]))
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.utils.config :as config]))
|
||||
|
||||
(defn- asset-border [color]
|
||||
{:border-color color :border-width 1 :border-radius 32})
|
||||
|
@ -386,21 +387,18 @@
|
|||
:address "0x9B11EFcAAA1890f6eE52C6bB7CF8153aC5d74139"
|
||||
:decimals 8
|
||||
:hidden? true}
|
||||
{:symbol :CK
|
||||
:nft? true
|
||||
:name "CryptoKitties"
|
||||
:address "0x06012c8cf97bead5deae237070f9587f8e7a266d"
|
||||
:hidden? true}
|
||||
{:symbol :EMONA
|
||||
:nft? true
|
||||
:name "Etheremon"
|
||||
:address "0xB2c0782ae4A299f7358758B2D15dA9bF29E1DD99"
|
||||
:hidden? true}
|
||||
{:symbol :STRK
|
||||
:nft? true
|
||||
:name "CryptoStrikers"
|
||||
:address "0xdcaad9fd9a74144d226dbf94ce6162ca9f09ed7e"
|
||||
:hidden? true}])
|
||||
{:symbol :CK
|
||||
:nft? true
|
||||
:name "CryptoKitties"
|
||||
:address "0x06012c8cf97bead5deae237070f9587f8e7a266d"}
|
||||
{:symbol :EMONA
|
||||
:nft? true
|
||||
:name "Etheremon"
|
||||
:address "0xB2c0782ae4A299f7358758B2D15dA9bF29E1DD99"}
|
||||
{:symbol :STRK
|
||||
:nft? true
|
||||
:name "CryptoStrikers"
|
||||
:address "0xdcaad9fd9a74144d226dbf94ce6162ca9f09ed7e"}])
|
||||
:testnet
|
||||
(resolve-icons :testnet
|
||||
[{:name "Status Test Token"
|
||||
|
|
|
@ -70,3 +70,6 @@
|
|||
:keywordize-keys true)
|
||||
(catch :default _
|
||||
(log/debug (str "Failed to parse " o))))))
|
||||
|
||||
(defn url-sanitized? [uri]
|
||||
(not (nil? (re-find #"^(https:)([/|.|\w|\s|-])*\.(?:jpg|svg|png)$" uri))))
|
|
@ -76,6 +76,10 @@
|
|||
(when bn
|
||||
(.toFixed bn)))
|
||||
|
||||
(defn to-number [bn]
|
||||
(when bn
|
||||
(.toNumber bn)))
|
||||
|
||||
(defn wei->str [unit n]
|
||||
(str (to-fixed (wei-> unit n)) " " (string/upper-case (name unit))))
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
[status-im.test.utils.prices]
|
||||
[status-im.test.utils.keychain.core]
|
||||
[status-im.test.utils.universal-links.core]
|
||||
[status-im.test.utils.http]
|
||||
[status-im.test.ui.screens.events]
|
||||
[status-im.test.ui.screens.accounts.login.events]))
|
||||
|
||||
|
@ -98,5 +99,6 @@
|
|||
'status-im.test.utils.prices
|
||||
'status-im.test.utils.keychain.core
|
||||
'status-im.test.utils.universal-links.core
|
||||
'status-im.test.utils.http
|
||||
'status-im.test.ui.screens.events
|
||||
'status-im.test.ui.screens.accounts.login.events)
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
(ns status-im.test.utils.http
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.utils.http :as http]))
|
||||
|
||||
(deftest url-sanitize-check
|
||||
(testing "https://storage.googleapis.com/ck-kitty-image/0x06012c8cf97bead5deae237070f9587f8e7a266d/818934.svg"
|
||||
(testing "it returns true"
|
||||
(is (http/url-sanitized? "https://storage.googleapis.com/ck-kitty-image/0x06012c8cf97bead5deae237070f9587f8e7a266d/818934.svg"))))
|
||||
|
||||
(testing "https://www.cryptostrikers.com/assets/images/cards/017.svg"
|
||||
(testing "it returns true"
|
||||
(is (http/url-sanitized? "https://www.cryptostrikers.com/assets/images/cards/017.svg"))))
|
||||
|
||||
(testing "https://www.etheremon.com/assets/images/mons_origin/025.png"
|
||||
(testing "it returns true"
|
||||
(is (http/url-sanitized? "https://www.etheremon.com/assets/images/mons_origin/025.png"))))
|
||||
|
||||
(testing "http://www.etheremon.com/assets/images/mons_origin/025.png"
|
||||
(testing "it returns false"
|
||||
(is (not (http/url-sanitized? "http://www.etheremon.com/assets/images/mons_origin/025.png")))))
|
||||
|
||||
(testing "xxx:x \\\\x0Aonerror=javascript:alert(1)"
|
||||
(testing "it returns false"
|
||||
(is (not (http/url-sanitized? "xxx:x \\\\x0Aonerror=javascript:alert(1)")))))
|
||||
|
||||
(testing "https://www.etheremon.com/assets/images/mons_origin/025.png'<script>alert('123');</script>"
|
||||
(testing "it returns false"
|
||||
(is (not (http/url-sanitized? "https://www.etheremon.com/assets/images/mons_origin/025.png'<script>alert('123');</script>")))))
|
||||
|
||||
(testing "https://www.etheremon.com/assets/images/mons'<script>alert('123');</script>origin/025.png"
|
||||
(testing "it returns false"
|
||||
(is (not (http/url-sanitized? "https://www.etheremon.com/assets/images/mons'<script>alert('123');</script>origin/025.png")))))
|
||||
|
||||
(testing "https://www.etheremon.com/assets/images/mons_origin/025.png'><script>\\\\x3Bjavascript:alert(1)</script>"
|
||||
(testing "it returns false"
|
||||
(is (not (http/url-sanitized? "https://www.etheremon.com/assets/images/mons_origin/025.png'><script>\\\\x3Bjavascript:alert(1)</script>")))))
|
||||
|
||||
(testing "https://www.etheremon.com/assets/images/mons'><script>\\\\x3Bjavascript:alert(1)</script>origin/025.png"
|
||||
(testing "it returns false"
|
||||
(is (not (http/url-sanitized? "https://www.etheremon.com/assets/images/mons'><script>\\\\x3Bjavascript:alert(1)</script>origin/025.png"))))))
|
Loading…
Reference in New Issue