diff --git a/resources/images/tokens/mainnet/KUDOS.png b/resources/images/tokens/mainnet/KUDOS.png new file mode 100644 index 0000000000..e3cdccc333 Binary files /dev/null and b/resources/images/tokens/mainnet/KUDOS.png differ diff --git a/resources/images/tokens/mainnet/KUDOS@2x.png b/resources/images/tokens/mainnet/KUDOS@2x.png new file mode 100644 index 0000000000..9c4cfbe0b6 Binary files /dev/null and b/resources/images/tokens/mainnet/KUDOS@2x.png differ diff --git a/resources/images/tokens/mainnet/KUDOS@3x.png b/resources/images/tokens/mainnet/KUDOS@3x.png new file mode 100644 index 0000000000..7307195b64 Binary files /dev/null and b/resources/images/tokens/mainnet/KUDOS@3x.png differ diff --git a/resources/images/tokens/rinkeby/KUDOS.png b/resources/images/tokens/rinkeby/KUDOS.png new file mode 100644 index 0000000000..e3cdccc333 Binary files /dev/null and b/resources/images/tokens/rinkeby/KUDOS.png differ diff --git a/resources/images/tokens/rinkeby/KUDOS@2x.png b/resources/images/tokens/rinkeby/KUDOS@2x.png new file mode 100644 index 0000000000..9c4cfbe0b6 Binary files /dev/null and b/resources/images/tokens/rinkeby/KUDOS@2x.png differ diff --git a/resources/images/tokens/rinkeby/KUDOS@3x.png b/resources/images/tokens/rinkeby/KUDOS@3x.png new file mode 100644 index 0000000000..7307195b64 Binary files /dev/null and b/resources/images/tokens/rinkeby/KUDOS@3x.png differ diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 7fc414730e..bb67abd20c 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -88,7 +88,7 @@ (defn default-account-settings [] {:wallet {:visible-tokens {:testnet #{:STT :HND} :mainnet #{:SNT} - :rinkeby #{:MOKSHA}}}}) + :rinkeby #{:MOKSHA :KUDOS}}}}) (def currencies {:aed {:id :aed :code "AED" :display-name (i18n/label :t/currency-display-name-aed) :symbol "د.إ"} diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index ddc00b3c8d..dd346a8c61 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -21,6 +21,7 @@ status-im.ui.screens.wallet.collectibles.cryptostrikers.events status-im.ui.screens.wallet.collectibles.etheremon.events status-im.ui.screens.wallet.collectibles.superrare.events + status-im.ui.screens.wallet.collectibles.kudos.events status-im.utils.keychain.events [re-frame.core :as re-frame] [status-im.hardwallet.core :as hardwallet] diff --git a/src/status_im/ui/screens/wallet/collectibles/cryptokitties/events.cljs b/src/status_im/ui/screens/wallet/collectibles/cryptokitties/events.cljs index 6325389839..0f62201147 100644 --- a/src/status_im/ui/screens/wallet/collectibles/cryptokitties/events.cljs +++ b/src/status_im/ui/screens/wallet/collectibles/cryptokitties/events.cljs @@ -18,7 +18,7 @@ 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] +(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=" diff --git a/src/status_im/ui/screens/wallet/collectibles/cryptostrikers/events.cljs b/src/status_im/ui/screens/wallet/collectibles/cryptostrikers/events.cljs index 90f910544b..049f246c13 100644 --- a/src/status_im/ui/screens/wallet/collectibles/cryptostrikers/events.cljs +++ b/src/status_im/ui/screens/wallet/collectibles/cryptostrikers/events.cljs @@ -4,7 +4,7 @@ (def strikers :STRK) -(defmethod collectibles/load-collectible-fx strikers [_ id] +(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)}]) diff --git a/src/status_im/ui/screens/wallet/collectibles/etheremon/events.cljs b/src/status_im/ui/screens/wallet/collectibles/etheremon/events.cljs index 396bd56ba9..6d12758850 100644 --- a/src/status_im/ui/screens/wallet/collectibles/etheremon/events.cljs +++ b/src/status_im/ui/screens/wallet/collectibles/etheremon/events.cljs @@ -4,7 +4,7 @@ (def emona :EMONA) -(defmethod collectibles/load-collectible-fx emona [_ id] +(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))]) diff --git a/src/status_im/ui/screens/wallet/collectibles/events.cljs b/src/status_im/ui/screens/wallet/collectibles/events.cljs index cc63c027d2..912b1b8ec2 100644 --- a/src/status_im/ui/screens/wallet/collectibles/events.cljs +++ b/src/status_im/ui/screens/wallet/collectibles/events.cljs @@ -4,43 +4,47 @@ [status-im.utils.ethereum.erc721 :as erc721] [status-im.utils.ethereum.tokens :as tokens] [status-im.utils.money :as money] - [status-im.browser.core :as browser])) + [status-im.browser.core :as browser] + [status-im.utils.ethereum.core :as ethereum] + [status-im.constants :as constants])) -(defmulti load-collectible-fx (fn [symbol _] symbol)) +(defmulti load-collectible-fx (fn [_ symbol _] symbol)) -(defmethod load-collectible-fx :default [_ _] nil) +(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]}) +(defmethod load-collectibles-fx :default [web3 symbol items-number address chain-id] + {:load-collectibles-fx [web3 symbol items-number address chain-id]}) (handlers/register-handler-fx :show-collectibles-list (fn [{:keys [db]} [_ address {:keys [symbol amount] :as collectible}]] - (let [items-number (money/to-number amount) + (let [chain-id (get-in constants/default-networks [(:network db) :config :NetworkId]) + 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)) + (load-collectibles-fx (:web3 db) symbol items-number address chain-id)) {: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 [_ v2] + (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))] + (fn [[web3 symbol items-number address chain-id]] + (let [chain (ethereum/chain-id->chain-keyword chain-id) + contract (:address (tokens/symbol->token chain 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))) + (fn [cofx [_ symbol token-id]] + (load-collectible-fx cofx symbol token-id))) (handlers/register-handler-fx :store-collectibles diff --git a/src/status_im/ui/screens/wallet/collectibles/kudos/events.cljs b/src/status_im/ui/screens/wallet/collectibles/kudos/events.cljs new file mode 100644 index 0000000000..52955c5181 --- /dev/null +++ b/src/status_im/ui/screens/wallet/collectibles/kudos/events.cljs @@ -0,0 +1,36 @@ +(ns status-im.ui.screens.wallet.collectibles.kudos.events + (:require [status-im.ui.screens.wallet.collectibles.events :as collectibles] + [status-im.utils.http :as http] + [status-im.utils.ethereum.erc721 :as erc721] + [status-im.utils.ethereum.tokens :as tokens] + [re-frame.core :as re-frame] + [status-im.utils.handlers :as handlers] + [status-im.constants :as constants] + [status-im.utils.ethereum.core :as ethereum])) + +(def kudos :KUDOS) + +(defmethod collectibles/load-collectible-fx kudos [{db :db} symbol id] + (let [chain-id (get-in constants/default-networks [(:network db) :config :NetworkId])] + {:erc721-token-uri [(:web3 db) symbol id chain-id]})) + +(re-frame/reg-fx + :erc721-token-uri + (fn [[web3 symbol tokenId chain-id]] + (let [chain (ethereum/chain-id->chain-keyword chain-id) + contract (:address (tokens/symbol->token chain symbol))] + (erc721/token-uri web3 contract tokenId + #(re-frame/dispatch [:token-uri-success + tokenId + (when %2 + ;;TODO extra chars in rinkeby + (subs %2 (.indexOf %2 "http")))]))))) + +(handlers/register-handler-fx + :token-uri-success + (fn [_ [_ tokenId token-uri]] + {:http-get {:url token-uri + :success-event-creator (fn [o] + [:load-collectible-success kudos {tokenId (http/parse-payload o)}]) + :failure-event-creator (fn [o] + [:load-collectible-failure kudos {tokenId (http/parse-payload o)}])}})) diff --git a/src/status_im/ui/screens/wallet/collectibles/kudos/views.cljs b/src/status_im/ui/screens/wallet/collectibles/kudos/views.cljs new file mode 100644 index 0000000000..6160cfba5a --- /dev/null +++ b/src/status_im/ui/screens/wallet/collectibles/kudos/views.cljs @@ -0,0 +1,27 @@ +(ns status-im.ui.screens.wallet.collectibles.kudos.views + (:require [status-im.ui.screens.wallet.collectibles.views :as collectibles] + [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.components.action-button.action-button :as action-button] + [status-im.ui.components.colors :as colors] + [re-frame.core :as re-frame] + [status-im.i18n :as i18n])) + +(defmethod collectibles/render-collectible :KUDOS [_ {: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-gitcoin) + :icon :icons/address + :icon-opts {:color colors/blue} + :accessibility-label :open-collectible-button + :on-press #(re-frame/dispatch [:open-collectible-in-browser external_url])}]]) \ No newline at end of file diff --git a/src/status_im/ui/screens/wallet/collectibles/superrare/events.cljs b/src/status_im/ui/screens/wallet/collectibles/superrare/events.cljs index 90499fb4d1..ff1dcdef92 100644 --- a/src/status_im/ui/screens/wallet/collectibles/superrare/events.cljs +++ b/src/status_im/ui/screens/wallet/collectibles/superrare/events.cljs @@ -6,7 +6,7 @@ (def superrare :SUPR) -(defmethod collectibles/load-collectible-fx superrare [_ ids] +(defmethod collectibles/load-collectible-fx superrare [_ _ ids] {:http-get-n (mapv (fn [id] {:url id :success-event-creator (fn [o] @@ -29,7 +29,7 @@ imageUri }}}}")) -(defmethod collectibles/load-collectibles-fx superrare [_ _ _ address] +(defmethod collectibles/load-collectibles-fx superrare [_ _ _ address _] {:http-post {:url graphql-url :data (types/clj->json {:query (graphql-query (ethereum/naked-address address))}) :opts {:headers {"Content-Type" "application/json"}} diff --git a/src/status_im/ui/screens/wallet/main/views.cljs b/src/status_im/ui/screens/wallet/main/views.cljs index 79c897146a..11777b8e98 100644 --- a/src/status_im/ui/screens/wallet/main/views.cljs +++ b/src/status_im/ui/screens/wallet/main/views.cljs @@ -17,6 +17,7 @@ status-im.ui.screens.wallet.collectibles.cryptostrikers.views status-im.ui.screens.wallet.collectibles.cryptokitties.views status-im.ui.screens.wallet.collectibles.superrare.views + status-im.ui.screens.wallet.collectibles.kudos.views [status-im.ui.components.status-bar.view :as status-bar.view] [status-im.ui.screens.wallet.transactions.views :as transactions.views] [status-im.ui.components.colors :as colors])) diff --git a/src/status_im/utils/ethereum/core.cljs b/src/status_im/utils/ethereum/core.cljs index b739d1661a..b51b319571 100644 --- a/src/status_im/utils/ethereum/core.cljs +++ b/src/status_im/utils/ethereum/core.cljs @@ -60,7 +60,15 @@ (defn hex->string [s] (when s - (.toAscii dependencies/Web3.prototype s))) + (let [hex (.toString s)] + (loop [res "" i (if (string/starts-with? hex hex-prefix) 2 0)] + (if (and (< i (.-length hex))) + (recur + (if (= (.substr hex i 2) "00") + res + (str res (.fromCharCode js/String (js/parseInt (.substr hex i 2) 16)))) + (+ i 2)) + res))))) (defn hex->boolean [s] (= s "0x0")) diff --git a/src/status_im/utils/ethereum/erc721.cljs b/src/status_im/utils/ethereum/erc721.cljs index bd8a1ef1e8..54974f3287 100644 --- a/src/status_im/utils/ethereum/erc721.cljs +++ b/src/status_im/utils/ethereum/erc721.cljs @@ -12,3 +12,12 @@ (ethereum/normalized-address address) (ethereum/int->hex index)) #(cb %1 (ethereum/hex->bignumber %2)))) + +(defn token-uri [web3 contract tokenId cb] + (ethereum/call web3 + (ethereum/call-params + contract + "tokenURI(uint256)" + (ethereum/int->hex tokenId)) + (fn [v1 v2] + (cb v1 (ethereum/hex->string v2))))) diff --git a/src/status_im/utils/ethereum/tokens.cljs b/src/status_im/utils/ethereum/tokens.cljs index 1580d79213..59d0168c22 100644 --- a/src/status_im/utils/ethereum/tokens.cljs +++ b/src/status_im/utils/ethereum/tokens.cljs @@ -422,7 +422,11 @@ {:symbol :SUPR :nft? true :name "SuperRare" - :address "0x41a322b28d0ff354040e2cbc676f0320d8c8850d"}]) + :address "0x41a322b28d0ff354040e2cbc676f0320d8c8850d"} + {:symbol :KUDOS + :nft? true + :name "KudosToken" + :address "0x56c72cda0b04fc39a25d0b6a64fa258fad46d664"}]) :testnet (resolve-icons :testnet [{:name "Status Test Token" @@ -456,7 +460,11 @@ [{:name "Moksha Coin" :symbol :MOKSHA :decimals 18 - :address "0x6ba7dc8dd10880ab83041e60c4ede52bb607864b"}]) + :address "0x6ba7dc8dd10880ab83041e60c4ede52bb607864b"} + {:symbol :KUDOS + :nft? true + :name "KudosToken" + :address "0x93bB0AFbd0627Bbd3a6C72Bc318341D3A22e254a"}]) :custom []}) diff --git a/translations/en.json b/translations/en.json index 5bad510429..e71e10436c 100644 --- a/translations/en.json +++ b/translations/en.json @@ -487,6 +487,7 @@ "currency-display-name-isk": "Iceland Krona", "connect-wnode-content": "Connect to {{name}}?", "view-cryptostrikers": "View in CryptoStrikers", + "view-gitcoin": "View in Gitcoin", "view-superrare": "View in SuperRare", "add-network": "Add network", "unknown-status-go-error": "Unknown status-go error",