[#6703] Stickers UI and contract wedding
Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
parent
2fa27d4ef9
commit
a1aeff70e5
|
@ -83,13 +83,10 @@
|
||||||
(let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))]
|
(let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))]
|
||||||
(cond-> browser history-host (assoc :unsafe? (dependencies/phishing-detect history-host)))))
|
(cond-> browser history-host (assoc :unsafe? (dependencies/phishing-detect history-host)))))
|
||||||
|
|
||||||
(def ipfs-proto-code "e3")
|
|
||||||
(def swarm-proto-code "e4")
|
|
||||||
|
|
||||||
(defn resolve-ens-content-callback [hex]
|
(defn resolve-ens-content-callback [hex]
|
||||||
(let [hash (when hex (multihash/base58 (multihash/create :sha2-256 (subs hex 2))))]
|
(let [hash (when hex (multihash/base58 (multihash/create :sha2-256 (subs hex 2))))]
|
||||||
(if (and hash (not= hash resolver/default-hash))
|
(if (and hash (not= hash resolver/default-hash))
|
||||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success ipfs-proto-code hash])
|
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success constants/ipfs-proto-code hash])
|
||||||
(re-frame/dispatch [:browser.callback/resolve-ens-contenthash]))))
|
(re-frame/dispatch [:browser.callback/resolve-ens-contenthash]))))
|
||||||
|
|
||||||
(defn resolve-ens-contenthash-callback [hex]
|
(defn resolve-ens-contenthash-callback [hex]
|
||||||
|
@ -97,7 +94,7 @@
|
||||||
hash (when hex (multihash/base58 (multihash/create :sha2-256 (subs hex 12))))]
|
hash (when hex (multihash/base58 (multihash/create :sha2-256 (subs hex 12))))]
|
||||||
;; We only support IPFS and SWARM
|
;; We only support IPFS and SWARM
|
||||||
;; TODO Once more implementations / providers are published this will have to be improved
|
;; TODO Once more implementations / providers are published this will have to be improved
|
||||||
(if (and ((#{swarm-proto-code ipfs-proto-code} proto-code) hash (not= hash resolver/default-hash)))
|
(if (and ((#{constants/swarm-proto-code constants/ipfs-proto-code} proto-code) hash (not= hash resolver/default-hash)))
|
||||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success proto-code hash])
|
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success proto-code hash])
|
||||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-error]))))
|
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-error]))))
|
||||||
|
|
||||||
|
@ -179,7 +176,7 @@
|
||||||
(let [current-url (get-current-url (get-current-browser db))
|
(let [current-url (get-current-url (get-current-browser db))
|
||||||
host (http/url-host current-url)
|
host (http/url-host current-url)
|
||||||
path (subs current-url (+ (.indexOf current-url host) (count host)))
|
path (subs current-url (+ (.indexOf current-url host) (count host)))
|
||||||
gateway (if (= ipfs-proto-code proto-code)
|
gateway (if (= constants/ipfs-proto-code proto-code)
|
||||||
(let [base32hash (-> (.encode js-dependencies/hi-base32 (alphabase.base58/decode hash))
|
(let [base32hash (-> (.encode js-dependencies/hi-base32 (alphabase.base58/decode hash))
|
||||||
(string/replace #"=" "")
|
(string/replace #"=" "")
|
||||||
(string/lower-case))]
|
(string/lower-case))]
|
||||||
|
|
|
@ -261,3 +261,6 @@
|
||||||
(def ^:const ipfs-add-url "https://ipfs.infura.io:5001/api/v0/add")
|
(def ^:const ipfs-add-url "https://ipfs.infura.io:5001/api/v0/add")
|
||||||
(def ^:const ipfs-add-param-name "extension.event.edn")
|
(def ^:const ipfs-add-param-name "extension.event.edn")
|
||||||
(def ^:const ipfs-cat-url "https://ipfs.infura.io/ipfs/")
|
(def ^:const ipfs-cat-url "https://ipfs.infura.io/ipfs/")
|
||||||
|
|
||||||
|
(def ^:const ipfs-proto-code "e3")
|
||||||
|
(def ^:const swarm-proto-code "e4")
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
[status-im.chat.models.message :as chat.message]
|
[status-im.chat.models.message :as chat.message]
|
||||||
[status-im.contact.core :as contact]
|
[status-im.contact.core :as contact]
|
||||||
[status-im.contact-recovery.core :as contact-recovery]
|
[status-im.contact-recovery.core :as contact-recovery]
|
||||||
[status-im.data-store.core :as data-store]
|
|
||||||
[status-im.extensions.core :as extensions]
|
[status-im.extensions.core :as extensions]
|
||||||
[status-im.extensions.registry :as extensions.registry]
|
[status-im.extensions.registry :as extensions.registry]
|
||||||
[status-im.fleet.core :as fleet]
|
[status-im.fleet.core :as fleet]
|
||||||
|
@ -39,7 +38,6 @@
|
||||||
[status-im.signals.core :as signals]
|
[status-im.signals.core :as signals]
|
||||||
[status-im.transport.message.core :as transport.message]
|
[status-im.transport.message.core :as transport.message]
|
||||||
[status-im.ui.screens.currency-settings.models :as currency-settings.models]
|
[status-im.ui.screens.currency-settings.models :as currency-settings.models]
|
||||||
[status-im.chat.models.message :as models.message]
|
|
||||||
[status-im.node.core :as node]
|
[status-im.node.core :as node]
|
||||||
[status-im.web3.core :as web3]
|
[status-im.web3.core :as web3]
|
||||||
[status-im.ui.screens.navigation :as navigation]
|
[status-im.ui.screens.navigation :as navigation]
|
||||||
|
@ -47,13 +45,13 @@
|
||||||
[status-im.utils.handlers :as handlers]
|
[status-im.utils.handlers :as handlers]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[status-im.utils.datetime :as time]
|
|
||||||
[status-im.chat.commands.core :as commands]
|
[status-im.chat.commands.core :as commands]
|
||||||
[status-im.chat.models.loading :as chat-loading]
|
[status-im.chat.models.loading :as chat-loading]
|
||||||
[status-im.node.core :as node]
|
[status-im.node.core :as node]
|
||||||
[cljs.reader :as edn]
|
|
||||||
[status-im.stickers.core :as stickers]
|
[status-im.stickers.core :as stickers]
|
||||||
[status-im.utils.config :as config]))
|
[status-im.utils.config :as config]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[status-im.utils.ethereum.core :as ethereum]))
|
||||||
|
|
||||||
;; init module
|
;; init module
|
||||||
|
|
||||||
|
@ -1670,8 +1668,8 @@
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:stickers/load-sticker-pack-success
|
:stickers/load-sticker-pack-success
|
||||||
(fn [cofx [_ edn-string uri open?]]
|
(fn [cofx [_ edn-string id price open?]]
|
||||||
(stickers/load-sticker-pack-success cofx edn-string uri open?)))
|
(stickers/load-sticker-pack-success cofx edn-string id price open?)))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:stickers/install-pack
|
:stickers/install-pack
|
||||||
|
@ -1680,14 +1678,13 @@
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:stickers/load-packs
|
:stickers/load-packs
|
||||||
(fn [_ _]
|
(fn [cofx _]
|
||||||
{;;TODO request list of packs from contract
|
(stickers/load-packs cofx)))
|
||||||
:http-get-n (mapv (fn [uri] {:url uri
|
|
||||||
:success-event-creator (fn [o]
|
(handlers/register-handler-fx
|
||||||
[:stickers/load-sticker-pack-success o uri])
|
:stickers/load-pack
|
||||||
:failure-event-creator (fn [o] nil)})
|
(fn [cofx [_ proto-code hash id price open?]]
|
||||||
;;TODO for testing ONLY
|
(stickers/load-pack cofx proto-code hash id price open?)))
|
||||||
["https://ipfs.infura.io/ipfs/QmRKmQjXyqpfznQ9Y9dTnKePJnQxoJATivPbGcCAKRsZJq/"])}))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:stickers/select-pack
|
:stickers/select-pack
|
||||||
|
@ -1696,5 +1693,35 @@
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:stickers/open-sticker-pack
|
:stickers/open-sticker-pack
|
||||||
(fn [cofx [_ uri]]
|
(fn [cofx [_ id]]
|
||||||
(stickers/open-sticker-pack cofx uri)))
|
(stickers/open-sticker-pack cofx id)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:stickers/buy-pack
|
||||||
|
(fn [cofx [_ id price]]
|
||||||
|
(stickers/approve-pack cofx id price)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:stickers/buy-token
|
||||||
|
(fn [cofx [_ id]]
|
||||||
|
(stickers/buy-token cofx id)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:stickers/get-owned-packs
|
||||||
|
(fn [cofx _]
|
||||||
|
(stickers/get-owned-pack cofx)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:stickers/pack-owned
|
||||||
|
(fn [cofx [_ id]]
|
||||||
|
(stickers/pack-owned cofx id)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:stickers/pending-pack
|
||||||
|
(fn [cofx [_ id]]
|
||||||
|
(stickers/pending-pack cofx id)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:stickers/pending-timout
|
||||||
|
(fn [cofx _]
|
||||||
|
(stickers/pending-timeout cofx)))
|
||||||
|
|
|
@ -2,11 +2,22 @@
|
||||||
(:require [status-im.utils.fx :as fx]
|
(:require [status-im.utils.fx :as fx]
|
||||||
[cljs.reader :as edn]
|
[cljs.reader :as edn]
|
||||||
[status-im.accounts.core :as accounts]
|
[status-im.accounts.core :as accounts]
|
||||||
[status-im.ui.screens.navigation :as navigation]))
|
[status-im.ui.screens.navigation :as navigation]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[status-im.utils.multihash :as multihash]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
|
[status-im.utils.ethereum.stickers :as ethereum.stickers]
|
||||||
|
[status-im.models.wallet :as models.wallet]
|
||||||
|
[status-im.utils.money :as money]
|
||||||
|
[status-im.utils.ethereum.abi-spec :as abi-spec]
|
||||||
|
[status-im.utils.ethereum.erc20 :as erc20]))
|
||||||
|
|
||||||
(fx/defn init-stickers-packs [{:keys [db]}]
|
(fx/defn init-stickers-packs [{:keys [db]}]
|
||||||
(let [sticker-packs (map edn/read-string (get-in db [:account/account :stickers]))]
|
(let [sticker-packs (into {} (map #(let [pack (edn/read-string %)]
|
||||||
{:db (assoc db :stickers/packs-installed (into {} (map #(vector (:id %) %) sticker-packs)))}))
|
(vector (:id pack) pack))
|
||||||
|
(get-in db [:account/account :stickers])))]
|
||||||
|
{:db (assoc db :stickers/packs-installed sticker-packs :stickers/packs sticker-packs)}))
|
||||||
|
|
||||||
(fx/defn install-stickers-pack [{{:account/keys [account] :as db} :db :as cofx} id]
|
(fx/defn install-stickers-pack [{{:account/keys [account] :as db} :db :as cofx} id]
|
||||||
(let [pack (get-in db [:stickers/packs id])]
|
(let [pack (get-in db [:stickers/packs id])]
|
||||||
|
@ -17,24 +28,124 @@
|
||||||
(assoc :stickers/selected-pack id))}
|
(assoc :stickers/selected-pack id))}
|
||||||
(accounts/update-stickers (conj (:stickers account) (pr-str pack))))))
|
(accounts/update-stickers (conj (:stickers account) (pr-str pack))))))
|
||||||
|
|
||||||
(fx/defn load-sticker-pack-success [{:keys [db] :as cofx} edn-string uri open?]
|
(fx/defn load-sticker-pack-success [{:keys [db] :as cofx} edn-string id price open?]
|
||||||
(let [{{:keys [id] :as pack} 'meta} (edn/read-string edn-string)
|
(let [pack (assoc (get (edn/read-string edn-string) 'meta)
|
||||||
pack' (assoc pack :uri uri)]
|
:id id :price price)]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (-> db (assoc-in [:stickers/packs id] pack'))}
|
{:db (-> db (assoc-in [:stickers/packs id] pack))}
|
||||||
#(when open? (navigation/navigate-to-cofx % :stickers-pack-modal pack')))))
|
#(when open? (navigation/navigate-to-cofx % :stickers-pack-modal pack)))))
|
||||||
|
|
||||||
(defn find-pack [pack-uri]
|
(defn pack-data-callback [id open?]
|
||||||
(fn [{:keys [uri] :as pack}]
|
(fn [[category owner mintable timestamp price contenthash]]
|
||||||
(when (= pack-uri uri)
|
(let [proto-code (subs contenthash 2 4)
|
||||||
pack)))
|
hash (when contenthash (multihash/base58 (multihash/create :sha2-256 (subs contenthash 12))))]
|
||||||
|
(when (and (#{constants/swarm-proto-code constants/ipfs-proto-code} proto-code) hash)
|
||||||
|
(re-frame/dispatch [:stickers/load-pack proto-code hash id price open?])))))
|
||||||
|
|
||||||
(fx/defn open-sticker-pack [{{:stickers/keys [packs packs-installed]} :db :as cofx} uri]
|
(fx/defn open-sticker-pack [{{:keys [web3 network] :stickers/keys [packs packs-installed] :as db} :db :as cofx} id]
|
||||||
(when uri
|
(when id
|
||||||
(let [pack (some (find-pack uri) (concat (vals packs-installed) (vals packs)))]
|
(let [pack (or (get packs-installed id) (get packs id))
|
||||||
|
network (get-in db [:account/account :networks network])]
|
||||||
(if pack
|
(if pack
|
||||||
(navigation/navigate-to-cofx cofx :stickers-pack-modal pack)
|
(navigation/navigate-to-cofx cofx :stickers-pack-modal pack)
|
||||||
{:http-get {:url uri
|
{:stickers/pack-data-fx [web3 network id true]}))))
|
||||||
:success-event-creator (fn [o]
|
|
||||||
[:stickers/load-sticker-pack-success o uri true])
|
(fx/defn load-pack [cofx proto-code hash id price open?]
|
||||||
:failure-event-creator (fn [o] nil)}}))))
|
{:http-get {:url (str (if (= constants/swarm-proto-code proto-code)
|
||||||
|
"https://swarm-gateways.net/bzz:/"
|
||||||
|
"https://ipfs.infura.io/ipfs/")
|
||||||
|
hash)
|
||||||
|
:success-event-creator (fn [o]
|
||||||
|
[:stickers/load-sticker-pack-success o id price open?])
|
||||||
|
:failure-event-creator (constantly nil)}})
|
||||||
|
|
||||||
|
(fx/defn load-packs [{{:keys [web3 network] :as db} :db}]
|
||||||
|
(let [network (get-in db [:account/account :networks network])
|
||||||
|
address (ethereum/normalized-address (get-in db [:account/account :address]))]
|
||||||
|
{:stickers/owned-packs-fx [web3 network address]
|
||||||
|
:stickers/load-packs-fx [web3 network]}))
|
||||||
|
|
||||||
|
(defn prepare-transaction [id tx on-result]
|
||||||
|
(merge {:id id
|
||||||
|
:symbol :ETH
|
||||||
|
:method constants/web3-send-transaction
|
||||||
|
:amount (money/bignumber 0)}
|
||||||
|
(when on-result {:on-result on-result})
|
||||||
|
tx))
|
||||||
|
|
||||||
|
(fx/defn buy-token [{{:keys [network] :as db} :db} pack-id]
|
||||||
|
(let [network (get-in db [:account/account :networks network])
|
||||||
|
address (ethereum/normalized-address (get-in db [:account/account :address]))
|
||||||
|
tx-object {:to (get ethereum.stickers/contracts (ethereum/network->chain-keyword network))
|
||||||
|
:data (abi-spec/encode "buyToken(uint256,address)" [pack-id address])}]
|
||||||
|
(models.wallet/open-modal-wallet-for-transaction
|
||||||
|
db
|
||||||
|
(prepare-transaction "buy" tx-object [:stickers/pending-pack pack-id])
|
||||||
|
tx-object)))
|
||||||
|
|
||||||
|
(fx/defn approve-pack [{db :db} pack-id price]
|
||||||
|
(let [network (get-in db [:account/account :networks (:network db)])
|
||||||
|
chain (ethereum/network->chain-keyword network)
|
||||||
|
stickers-contract (get ethereum.stickers/contracts chain)
|
||||||
|
tx-object {:to (get erc20/snt-contracts chain)
|
||||||
|
:data (abi-spec/encode "approve(address,uint256)" [stickers-contract price])}]
|
||||||
|
(models.wallet/open-modal-wallet-for-transaction
|
||||||
|
db
|
||||||
|
(prepare-transaction "approve" tx-object [:stickers/buy-token pack-id])
|
||||||
|
tx-object)))
|
||||||
|
|
||||||
|
(fx/defn pending-pack [{{:keys [web3 network] :as db} :db :as cofx} id]
|
||||||
|
(let [network (get-in db [:account/account :networks network])
|
||||||
|
address (ethereum/normalized-address (get-in db [:account/account :address]))]
|
||||||
|
(fx/merge cofx
|
||||||
|
{:db (update db :stickers/packs-pendning conj id)
|
||||||
|
:stickers/owned-packs-fx [web3 network address]}
|
||||||
|
(navigation/navigate-to-clean :wallet-transaction-sent-modal {})
|
||||||
|
#(when (zero? (count (:stickers/packs-pendning db)))
|
||||||
|
{:stickers/set-pending-timout-fx nil}))))
|
||||||
|
|
||||||
|
(fx/defn pending-timeout [{{:keys [web3 network] :stickers/keys [packs-pendning packs-owned] :as db} :db}]
|
||||||
|
(let [packs-diff (clojure.set/difference packs-pendning packs-owned)
|
||||||
|
network (get-in db [:account/account :networks network])
|
||||||
|
address (ethereum/normalized-address (get-in db [:account/account :address]))]
|
||||||
|
(merge {:db (assoc db :stickers/packs-pendning packs-diff)}
|
||||||
|
(when-not (zero? (count packs-diff))
|
||||||
|
{:stickers/owned-packs-fx [web3 network address]
|
||||||
|
:stickers/set-pending-timout-fx nil}))))
|
||||||
|
|
||||||
|
(fx/defn pack-owned [{db :db} id]
|
||||||
|
{:db (update db :stickers/packs-owned conj id)})
|
||||||
|
|
||||||
|
(fx/defn get-owned-pack [{{:keys [web3 network] :as db} :db}]
|
||||||
|
(let [address (ethereum/normalized-address (get-in db [:account/account :address]))]
|
||||||
|
{:stickers/owned-packs-fx [web3 network address]}))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:stickers/pack-data-fx
|
||||||
|
(fn [[web3 network id open?]]
|
||||||
|
(when-let [contract (get ethereum.stickers/contracts (ethereum/network->chain-keyword network))]
|
||||||
|
(ethereum.stickers/pack-data web3 contract id (pack-data-callback id open?)))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:stickers/set-pending-timout-fx
|
||||||
|
(fn []
|
||||||
|
(js/setTimeout #(re-frame/dispatch [:stickers/pending-timout]) 10000)))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:stickers/load-packs-fx
|
||||||
|
(fn [[web3 network]]
|
||||||
|
(when-let [contract (get ethereum.stickers/contracts (ethereum/network->chain-keyword network))]
|
||||||
|
(ethereum.stickers/pack-count web3 contract
|
||||||
|
(fn [count]
|
||||||
|
(dotimes [n count]
|
||||||
|
(ethereum.stickers/pack-data web3 contract n (pack-data-callback n false))))))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:stickers/owned-packs-fx
|
||||||
|
(fn [[web3 network address]]
|
||||||
|
(when-let [contract (get ethereum.stickers/contracts (ethereum/network->chain-keyword network))]
|
||||||
|
(ethereum.stickers/owned-tokens web3 contract address
|
||||||
|
(fn [tokens]
|
||||||
|
(doseq [n tokens]
|
||||||
|
(ethereum.stickers/token-pack-id web3 contract n
|
||||||
|
#(re-frame/dispatch [:stickers/pack-owned %]))))))))
|
|
@ -55,9 +55,9 @@
|
||||||
[react/view {:style {:margin-bottom 5 :height 2 :width 16 :border-radius 1
|
[react/view {:style {:margin-bottom 5 :height 2 :width 16 :border-radius 1
|
||||||
:background-color (if selected? colors/blue colors/white)}}]]])
|
:background-color (if selected? colors/blue colors/white)}}]]])
|
||||||
|
|
||||||
(defn pack-stickers [packs id]
|
(defn pack-stickers [packs pack-id]
|
||||||
(let [{:keys [stickers uri]} (some #(when (= id (:id %)) %) packs)]
|
(let [{:keys [stickers id]} (some #(when (= pack-id (:id %)) %) packs)]
|
||||||
(map #(assoc % :pack uri) stickers)))
|
(map #(assoc % :pack id) stickers)))
|
||||||
|
|
||||||
(defn show-panel-anim
|
(defn show-panel-anim
|
||||||
[bottom-anim-value alpha-value]
|
[bottom-anim-value alpha-value]
|
||||||
|
|
|
@ -63,6 +63,8 @@
|
||||||
:dimensions/window (dimensions/window)
|
:dimensions/window (dimensions/window)
|
||||||
:push-notifications/stored {}
|
:push-notifications/stored {}
|
||||||
:registry {}
|
:registry {}
|
||||||
|
:stickers/packs-owned #{}
|
||||||
|
:stickers/packs-pendning #{}
|
||||||
:hardwallet {:nfc-supported? false
|
:hardwallet {:nfc-supported? false
|
||||||
:nfc-enabled? false
|
:nfc-enabled? false
|
||||||
:pin {:original []
|
:pin {:original []
|
||||||
|
@ -195,6 +197,8 @@
|
||||||
(spec/def ::hardwallet (spec/nilable map?))
|
(spec/def ::hardwallet (spec/nilable map?))
|
||||||
|
|
||||||
(spec/def :stickers/packs (spec/nilable map?))
|
(spec/def :stickers/packs (spec/nilable map?))
|
||||||
|
(spec/def :stickers/packs-owned (spec/nilable set?))
|
||||||
|
(spec/def :stickers/packs-pendning (spec/nilable set?))
|
||||||
(spec/def :stickers/packs-installed (spec/nilable map?))
|
(spec/def :stickers/packs-installed (spec/nilable map?))
|
||||||
(spec/def :stickers/selected-pack (spec/nilable any?))
|
(spec/def :stickers/selected-pack (spec/nilable any?))
|
||||||
(spec/def :stickers/recent (spec/nilable vector?))
|
(spec/def :stickers/recent (spec/nilable vector?))
|
||||||
|
@ -270,6 +274,8 @@
|
||||||
:stickers/packs-installed
|
:stickers/packs-installed
|
||||||
:stickers/selected-pack
|
:stickers/selected-pack
|
||||||
:stickers/recent
|
:stickers/recent
|
||||||
|
:stickers/packs-owned
|
||||||
|
:stickers/packs-pendning
|
||||||
:bottom-sheet/show?
|
:bottom-sheet/show?
|
||||||
:bottom-sheet/view]
|
:bottom-sheet/view]
|
||||||
:opt-un [::modal
|
:opt-un [::modal
|
||||||
|
|
|
@ -21,8 +21,15 @@
|
||||||
:stickers/all-packs
|
:stickers/all-packs
|
||||||
:<- [:stickers/packs]
|
:<- [:stickers/packs]
|
||||||
:<- [:stickers/installed-packs]
|
:<- [:stickers/installed-packs]
|
||||||
(fn [[packs installed]]
|
:<- [:get :stickers/packs-owned]
|
||||||
(map #(if (get installed (:id %)) (assoc % :installed true) %) (vals packs))))
|
:<- [:get :stickers/packs-pendning]
|
||||||
|
(fn [[packs installed owned pending]]
|
||||||
|
(map (fn [{:keys [id] :as pack}]
|
||||||
|
(cond-> pack
|
||||||
|
(get installed id) (assoc :installed true)
|
||||||
|
(get owned id) (assoc :owned true)
|
||||||
|
(get pending id) (assoc :pending true)))
|
||||||
|
(vals packs))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:stickers/get-current-pack
|
:stickers/get-current-pack
|
||||||
|
@ -32,9 +39,9 @@
|
||||||
(first (filter #(= (:id %) id) packs))))
|
(first (filter #(= (:id %) id) packs))))
|
||||||
|
|
||||||
(defn find-pack-id-for-uri [sticker-uri packs]
|
(defn find-pack-id-for-uri [sticker-uri packs]
|
||||||
(some (fn [{:keys [stickers uri]}]
|
(some (fn [{:keys [stickers id]}]
|
||||||
(when (some #(= sticker-uri (:uri %)) stickers)
|
(when (some #(= sticker-uri (:uri %)) stickers)
|
||||||
uri))
|
id))
|
||||||
packs))
|
packs))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
[status-im.ui.components.toolbar.view :as toolbar]
|
[status-im.ui.components.toolbar.view :as toolbar]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.ui.components.icons.vector-icons :as icons]
|
[status-im.ui.components.icons.vector-icons :as icons]
|
||||||
[status-im.utils.money :as money]))
|
[status-im.utils.money :as money]
|
||||||
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
|
[status-im.ui.components.react :as components]))
|
||||||
|
|
||||||
(defn- thumbnail-icon [uri size]
|
(defn- thumbnail-icon [uri size]
|
||||||
[react/image {:style {:width size :height size :border-radius (/ size 2)}
|
[react/image {:style {:width size :height size :border-radius (/ size 2)}
|
||||||
|
@ -19,24 +21,32 @@
|
||||||
[react/view styles/installed-icon
|
[react/view styles/installed-icon
|
||||||
[icons/icon :main-icons/check {:color colors/white :height 20 :width 20}]])
|
[icons/icon :main-icons/check {:color colors/white :height 20 :width 20}]])
|
||||||
|
|
||||||
(defview price-badge [price id]
|
(defview price-badge [price id owned pending]
|
||||||
(letsubs [balance [:balance]]
|
(letsubs [network [:network]
|
||||||
(let [snt (money/wei-> :eth (:SNT balance))
|
balance [:balance]]
|
||||||
|
(let [chain (ethereum/network->chain-keyword network)
|
||||||
|
snt (money/to-number (if (= :mainnet chain) (:SNT balance) (:STT balance)))
|
||||||
not-enough-snt? (> price snt)
|
not-enough-snt? (> price snt)
|
||||||
no-snt? (nil? snt)]
|
no-snt? (or (nil? snt) (zero? snt))]
|
||||||
[react/touchable-highlight {:on-press #(when (zero? price) (re-frame/dispatch [:stickers/install-pack id]))}
|
[react/touchable-highlight {:on-press #(cond pending nil
|
||||||
[react/view (styles/price-badge not-enough-snt?)
|
(or owned (zero? price))
|
||||||
(when (and (not (zero? price)) (not no-snt?))
|
(re-frame/dispatch [:stickers/install-pack id])
|
||||||
|
(or no-snt? not-enough-snt?) nil
|
||||||
|
:else (re-frame/dispatch [:stickers/buy-pack id price]))}
|
||||||
|
[react/view (styles/price-badge (and (not (or owned (zero? price))) (or no-snt? not-enough-snt?)))
|
||||||
|
(when (and (not (zero? price))) ;(not no-snt?))
|
||||||
[icons/icon :icons/logo {:color colors/white :width 12 :height 12 :container-style {:margin-right 8}}])
|
[icons/icon :icons/logo {:color colors/white :width 12 :height 12 :container-style {:margin-right 8}}])
|
||||||
[react/text {:style {:font-size 15 :color colors/white}}
|
(if pending
|
||||||
(cond (zero? price)
|
[components/activity-indicator {:animating true}]
|
||||||
(i18n/label :t/install)
|
[react/text {:style {:font-size 15 :color colors/white}}
|
||||||
no-snt?
|
(cond (or owned (zero? price))
|
||||||
(i18n/label :t/buy-with-snt)
|
(i18n/label :t/install)
|
||||||
:else
|
;no-snt?
|
||||||
(str price))]]])))
|
;(i18n/label :t/buy-with-snt)
|
||||||
|
:else
|
||||||
|
(str (money/wei-> :eth price)))])]])))
|
||||||
|
|
||||||
(defn pack-badge [{:keys [name author price thumbnail preview id installed] :as pack}]
|
(defn pack-badge [{:keys [name author price thumbnail preview id installed owned pending] :as pack}]
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :stickers-pack pack])}
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :stickers-pack pack])}
|
||||||
[react/view {:margin-bottom 27}
|
[react/view {:margin-bottom 27}
|
||||||
[react/image {:style {:height 200 :border-radius 20} :source {:uri preview}}]
|
[react/image {:style {:height 200 :border-radius 20} :source {:uri preview}}]
|
||||||
|
@ -47,7 +57,7 @@
|
||||||
[react/text {:style {:font-size 15 :color colors/gray :margin-top 6}} author]]
|
[react/text {:style {:font-size 15 :color colors/gray :margin-top 6}} author]]
|
||||||
(if installed
|
(if installed
|
||||||
[installed-icon]
|
[installed-icon]
|
||||||
[price-badge price id])]]])
|
[price-badge price id owned pending])]]])
|
||||||
|
|
||||||
(defview packs []
|
(defview packs []
|
||||||
(letsubs [packs [:stickers/all-packs]]
|
(letsubs [packs [:stickers/all-packs]]
|
||||||
|
@ -64,7 +74,7 @@
|
||||||
(def sticker-icon-size 60)
|
(def sticker-icon-size 60)
|
||||||
|
|
||||||
(defview pack-main [modal?]
|
(defview pack-main [modal?]
|
||||||
(letsubs [{:keys [id name author price thumbnail stickers installed]} [:stickers/get-current-pack]]
|
(letsubs [{:keys [id name author price thumbnail stickers installed owned pending]} [:stickers/get-current-pack]]
|
||||||
[react/view styles/screen
|
[react/view styles/screen
|
||||||
[status-bar/status-bar]
|
[status-bar/status-bar]
|
||||||
[react/keyboard-avoiding-view components.styles/flex
|
[react/keyboard-avoiding-view components.styles/flex
|
||||||
|
@ -76,7 +86,7 @@
|
||||||
[react/text {:style {:font-size 15 :color colors/gray :margin-top 6}} author]]
|
[react/text {:style {:font-size 15 :color colors/gray :margin-top 6}} author]]
|
||||||
(if installed
|
(if installed
|
||||||
[installed-icon]
|
[installed-icon]
|
||||||
[price-badge price id])]
|
[price-badge price id owned pending])]
|
||||||
[react/view {:style {:padding-top 8 :flex 1}}
|
[react/view {:style {:padding-top 8 :flex 1}}
|
||||||
[react/scroll-view {:keyboard-should-persist-taps :handled :style {:flex 1}}
|
[react/scroll-view {:keyboard-should-persist-taps :handled :style {:flex 1}}
|
||||||
[react/view {:flex-direction :row :flex-wrap :wrap}
|
[react/view {:flex-direction :row :flex-wrap :wrap}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
(:require [cljs.spec.alpha :as spec]
|
(:require [cljs.spec.alpha :as spec]
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[status-im.js-dependencies :as dependencies]))
|
[status-im.js-dependencies :as dependencies]))
|
||||||
|
|
||||||
;; Utility functions for encoding
|
;; Utility functions for encoding
|
||||||
|
|
||||||
(def utils dependencies/web3-utils)
|
(def utils dependencies/web3-utils)
|
||||||
|
@ -330,7 +329,7 @@
|
||||||
(conj (butlast (:coll (reduce offset-reducer {:cnt 0 :coll []} lengths))) 0)))
|
(conj (butlast (:coll (reduce offset-reducer {:cnt 0 :coll []} lengths))) 0)))
|
||||||
|
|
||||||
(defn hex-to-bytes [hex]
|
(defn hex-to-bytes [hex]
|
||||||
(let [len (* (.toNumber (.toBN utils (subs hex 0 64))) 2)]
|
(let [len (* (hex-to-number (subs hex 0 64)) 2)]
|
||||||
(substr hex 64 len)))
|
(substr hex 64 len)))
|
||||||
|
|
||||||
(defn dyn-hex-to-value [hex type]
|
(defn dyn-hex-to-value [hex type]
|
||||||
|
|
|
@ -24,6 +24,11 @@
|
||||||
|
|
||||||
(def utils dependencies/web3-utils)
|
(def utils dependencies/web3-utils)
|
||||||
|
|
||||||
|
(def snt-contracts
|
||||||
|
{:mainnet "0x744d70fdbe2ba4cf95131626614a1763df805b9e"
|
||||||
|
:testnet "0xc55cF4B03948D7EBc8b9E8BAD92643703811d162"
|
||||||
|
:rinkeby nil})
|
||||||
|
|
||||||
(def abi
|
(def abi
|
||||||
(clj->js
|
(clj->js
|
||||||
[{:constant true
|
[{:constant true
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
(ns status-im.utils.ethereum.stickers
|
||||||
|
(:require [status-im.utils.ethereum.core :as ethereum]
|
||||||
|
[status-im.utils.ethereum.abi-spec :as abi-spec]))
|
||||||
|
|
||||||
|
(def contracts
|
||||||
|
{:mainnet nil
|
||||||
|
:testnet "0x82694E3DeabE4D6f4e6C180Fe6ad646aB8EF53ae"
|
||||||
|
:rinkeby nil})
|
||||||
|
|
||||||
|
(defn pack-count [web3 contract cb]
|
||||||
|
"Returns number of packs rigestered in the contract"
|
||||||
|
(ethereum/call web3
|
||||||
|
(ethereum/call-params contract "packCount()")
|
||||||
|
(fn [_ count] (cb (ethereum/hex->int count)))))
|
||||||
|
|
||||||
|
(defn pack-data [web3 contract pack-id cb]
|
||||||
|
"Returns vector of pack data parameters by pack id: [category owner mintable timestamp price contenthash]"
|
||||||
|
(ethereum/call web3
|
||||||
|
(ethereum/call-params contract "getPackData(uint256)" (ethereum/int->hex pack-id))
|
||||||
|
(fn [_ data]
|
||||||
|
(cb (abi-spec/decode (subs data 2) ["bytes4[]" "address" "bool" "uint256" "uint256" "bytes"])))))
|
||||||
|
|
||||||
|
(defn owned-tokens [web3 contract address cb]
|
||||||
|
"Returns vector of owned tokens ids in the contract by address"
|
||||||
|
(ethereum/call web3
|
||||||
|
(ethereum/call-params contract "tokensOwnedBy(address)" (ethereum/normalized-address address))
|
||||||
|
(fn [_ data]
|
||||||
|
(cb (first (abi-spec/decode (subs data 2) ["uint256[]"]))))))
|
||||||
|
|
||||||
|
(defn token-pack-id [web3 contract token cb]
|
||||||
|
"Returns pack id in the contract by token id"
|
||||||
|
(ethereum/call web3
|
||||||
|
(ethereum/call-params contract "tokenPackId(uint256)" (ethereum/int->hex token))
|
||||||
|
(fn [_ data] (cb (ethereum/hex->int data)))))
|
Loading…
Reference in New Issue