[Fixes #6874] Added transaction-receipt, schedule and balance events

Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
Julien Eluard 2018-11-29 23:05:46 +01:00
parent 6365a0d1e2
commit e3e75e0498
No known key found for this signature in database
GPG Key ID: 6FD7DB5437FCBEF6
7 changed files with 162 additions and 16 deletions

View File

@ -200,6 +200,7 @@
(def ^:const web3-send-transaction "eth_sendTransaction") (def ^:const web3-send-transaction "eth_sendTransaction")
(def ^:const web3-personal-sign "personal_sign") (def ^:const web3-personal-sign "personal_sign")
(def ^:const web3-get-logs "eth_getLogs") (def ^:const web3-get-logs "eth_getLogs")
(def ^:const web3-transaction-receipt "eth_getTransactionReceipt")
(def ^:const event-transfer-hash (def ^:const event-transfer-hash
(ethereum/sha3 "Transfer(address,address,uint256)")) (ethereum/sha3 "Transfer(address,address,uint256)"))

View File

@ -12,6 +12,7 @@
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.wallet.settings.views :as settings] [status-im.ui.screens.wallet.settings.views :as settings]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.utils.money :as money]
[status-im.ui.components.colors :as colors] [status-im.ui.components.colors :as colors]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
@ -21,6 +22,15 @@
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.chat.commands.sending :as commands-sending])) [status-im.chat.commands.sending :as commands-sending]))
(re-frame/reg-fx
::identity-event
(fn [{:keys [cb]}] (re-frame/dispatch (cb {}))))
(re-frame/reg-event-fx
:extensions/identity-event
(fn [_ [_ _ m]]
{::identity-event m}))
(re-frame/reg-fx (re-frame/reg-fx
::alert ::alert
(fn [value] (js/alert value))) (fn [value] (js/alert value)))
@ -39,11 +49,58 @@
(fn [_ [_ _ {:keys [value]}]] (fn [_ [_ _ {:keys [value]}]]
{::log value})) {::log value}))
(re-frame/reg-fx
::schedule-start
(fn [{:keys [interval on-created on-result]}]
(let [id (js/setInterval #(re-frame/dispatch (on-result {})) interval)]
(re-frame/dispatch (on-created {:value id})))))
(handlers/register-handler-fx
:extensions/schedule-start
(fn [_ [_ _ m]]
{::schedule-start m}))
(re-frame/reg-fx
::schedule-cancel
(fn [{:keys [value]}]
(js/clearInterval value)))
(handlers/register-handler-fx
:extensions/schedule-cancel
(fn [_ [_ _ m]]
{::schedule-cancel m}))
(re-frame/reg-sub (re-frame/reg-sub
:extensions/identity :extensions/identity
(fn [_ [_ _ {:keys [value]}]] (fn [_ [_ _ {:keys [value]}]]
value)) value))
(defn get-token-for [network all-tokens token]
(if (= token "ETH")
{:decimals 18
:address "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}
(tokens/token-for (ethereum/network->chain-keyword network) all-tokens token)))
(re-frame/reg-sub
:extensions.wallet/balance
:<- [:wallet/all-tokens]
:<- [:network]
:<- [:balance]
(fn [[all-tokens network balance] [_ _ {token :token}]]
(let [{:keys [decimals]} (get-token-for network all-tokens token)
value (get balance (keyword token))]
{:value (money/token->unit value decimals)
:value-in-wei value})))
(re-frame/reg-sub
:extensions.wallet/token
:<- [:wallet/all-tokens]
:<- [:network]
(fn [[all-tokens network] [_ _ {token :token amount :amount}]]
(let [{:keys [decimals] :as m} (get-token-for network all-tokens token)]
(merge m
(when amount {:amount (money/unit->token amount decimals)})))))
(re-frame/reg-sub (re-frame/reg-sub
:extensions.wallet/tokens :extensions.wallet/tokens
:<- [:wallet/all-tokens] :<- [:wallet/all-tokens]
@ -59,10 +116,25 @@
(fn [db [_ {id :id} {:keys [key]}]] (fn [db [_ {id :id} {:keys [key]}]]
(get-in db [:extensions/store id key]))) (get-in db [:extensions/store id key])))
(defn- empty-value? [o]
(cond
(seqable? o) (empty? o)
:else (nil? o)))
(defn put-or-dissoc [db id key value]
(if (empty-value? value)
(update-in db [:extensions/store id] dissoc key)
(assoc-in db [:extensions/store id key] value)))
(handlers/register-handler-fx (handlers/register-handler-fx
:store/put :store/put
(fn [{:keys [db]} [_ {id :id} {:keys [key value]}]] (fn [{:keys [db]} [_ {id :id} {:keys [key value]}]]
{:db (assoc-in db [:extensions/store id key] value)})) {:db (put-or-dissoc db id key value)}))
(handlers/register-handler-fx
:store/puts
(fn [{:keys [db]} [_ {id :id} {:keys [value]}]]
{:db (reduce #(put-or-dissoc %1 id (:key %2) (:value %2)) db value)}))
(defn- append [acc k v] (defn- append [acc k v]
(let [o (get acc k)] (let [o (get acc k)]
@ -190,13 +262,14 @@
(fn [_ [_ _ m]] (fn [_ [_ _ m]]
{::arithmetic m})) {::arithmetic m}))
(defn button [{:keys [on-click disabled]} label] (defn button [{:keys [on-click enabled disabled] :as m} label]
[button/secondary-button (merge {:disabled? disabled} [button/secondary-button (merge {:disabled? (or (when (contains? m :enabled) (or (nil? enabled) (false? enabled))) disabled)}
(when on-click {:on-press #(re-frame/dispatch (on-click {}))})) label]) (when on-click {:on-press #(re-frame/dispatch (on-click {}))})) label])
(defn input [{:keys [on-change placeholder]}] (defn input [{:keys [keyboard-type style on-change placeholder]}]
[react/text-input (merge {:placeholder placeholder [react/text-input (merge {:placeholder placeholder}
:style {:width "100%"}} (when style {:style style})
(when keyboard-type {:keyboard-type keyboard-type})
(when on-change (when on-change
{:on-change-text #(re-frame/dispatch (on-change {:value %}))}))]) {:on-change-text #(re-frame/dispatch (on-change {:value %}))}))])
@ -256,8 +329,8 @@
'text {:value text} 'text {:value text}
'touchable-opacity {:value touchable-opacity :properties {:on-press :event}} 'touchable-opacity {:value touchable-opacity :properties {:on-press :event}}
'image {:value image :properties {:uri :string}} 'image {:value image :properties {:uri :string}}
'input {:value input :properties {:on-change :event :placeholder :string}} 'input {:value input :properties {:on-change :event :placeholder :string :keyboard-type :keyword}}
'button {:value button :properties {:disabled :boolean :on-click :event}} 'button {:value button :properties {:enabled :boolean :disabled :boolean :on-click :event}}
'link {:value link :properties {:uri :string}} 'link {:value link :properties {:uri :string}}
'list {:value list :properties {:data :vector :item-view :view :key? :keyword}} 'list {:value list :properties {:data :vector :item-view :view :key? :keyword}}
'checkbox {:value checkbox :properties {:on-change :event :checked :boolean}} 'checkbox {:value checkbox :properties {:on-change :event :checked :boolean}}
@ -268,8 +341,14 @@
:queries {'identity {:value :extensions/identity :arguments {:value :map}} :queries {'identity {:value :extensions/identity :arguments {:value :map}}
'store/get {:value :store/get :arguments {:key :string}} 'store/get {:value :store/get :arguments {:key :string}}
'wallet/collectibles {:value :get-collectible-token :arguments {:token :string :symbol :string}} 'wallet/collectibles {:value :get-collectible-token :arguments {:token :string :symbol :string}}
'wallet/balance {:value :extensions.wallet/balance :arguments {:token :string}}
'wallet/token {:value :extensions.wallet/token :arguments {:token :string :amount? :numeric}}
'wallet/tokens {:value :extensions.wallet/tokens :arguments {:filter :vector}}} 'wallet/tokens {:value :extensions.wallet/tokens :arguments {:filter :vector}}}
:events {'alert :events {'identity
{:permissions [:read]
:value :extensions/identity-event
:arguments {:cb :event}}
'alert
{:permissions [:read] {:permissions [:read]
:value :alert :value :alert
:arguments {:value :string}} :arguments {:value :string}}
@ -303,6 +382,16 @@
:arguments {:values #{:plus :minus :times :divide} :arguments {:values #{:plus :minus :times :divide}
:operation :keyword :operation :keyword
:on-result :event}} :on-result :event}}
'schedule/start
{:permissions [:read]
:value :extensions/schedule-start
:arguments {:interval :number
:on-created :event
:on-result :event}}
'schedule/cancel
{:permissions [:read]
:value :extensions/schedule-cancel
:arguments {:value :number}}
'json/parse 'json/parse
{:permissions [:read] {:permissions [:read]
:value :extensions/json-parse :value :extensions/json-parse
@ -316,11 +405,15 @@
'store/put 'store/put
{:permissions [:read] {:permissions [:read]
:value :store/put :value :store/put
:arguments {:key :string :value :map}} :arguments {:key :string :value :any}}
'store/puts
{:permissions [:read]
:value :store/puts
:arguments {:value :vector}}
'store/append 'store/append
{:permissions [:read] {:permissions [:read]
:value :store/append :value :store/append
:arguments {:key :string :value :map}} :arguments {:key :string :value :any}}
'store/clear 'store/clear
{:permissions [:read] {:permissions [:read]
:value :store/clear :value :store/clear
@ -346,6 +439,11 @@
:arguments {:hash :string :arguments {:hash :string
:on-success :event :on-success :event
:on-failure? :event}} :on-failure? :event}}
'ethereum/transaction-receipt
{:permissions [:read]
:value :extensions/ethereum-transaction-receipt
:arguments {:value :string
:on-result :event}}
'ethereum/send-transaction 'ethereum/send-transaction
{:permissions [:read] {:permissions [:read]
:value :extensions/ethereum-send-transaction :value :extensions/ethereum-send-transaction

View File

@ -99,6 +99,44 @@
(fn [{db :db} [_ _ {:keys [to] :as arguments}]] (fn [{db :db} [_ _ {:keys [to] :as arguments}]]
(wrap-with-resolution db arguments :to execute-ethcall))) (wrap-with-resolution db arguments :to execute-ethcall)))
(defn- parse-log [{:keys [address transactionHash blockHash transactionIndex topics blockNumber logIndex removed data]}]
{:address address
:transaction-hash transactionHash
:blockHash blockHash
:transaction-index (abi-spec/hex-to-number transactionIndex)
:topics topics ;; TODO parse topics
:block-number (abi-spec/hex-to-number blockNumber)
:log-index (abi-spec/hex-to-number logIndex)
:removed removed
:data data})
(defn- parse-receipt [m]
(when m
(let [{:keys [status transactionHash transactionIndex blockHash blockNumber from to cumulativeGasUsed gasUsed contractAddress logs logsBloom]} m]
{:status (abi-spec/hex-to-number status)
:transaction-hash transactionHash
:transaction-index (abi-spec/hex-to-number transactionIndex)
:block-hash blockHash
:block-number (abi-spec/hex-to-number blockNumber)
:from from
:to to
:cumulative-gas-used (abi-spec/hex-to-number cumulativeGasUsed)
:gas-used (abi-spec/hex-to-number gasUsed)
:contract-address contractAddress
:logs (map parse-log logs)
:logs-bloom logsBloom})))
(handlers/register-handler-fx
:extensions/ethereum-transaction-receipt
(fn [_ [_ _ {:keys [value on-result]}]]
(let [args {:jsonrpc "2.0"
:method constants/web3-transaction-receipt
:params [value]}
payload (types/clj->json args)]
(status/call-private-rpc payload #(let [{:keys [error result]} (types/json->clj %1)
response (merge {:result (parse-receipt result)} (when error {:error error}))]
(re-frame/dispatch (on-result response)))))))
;; eth_getLogs implementation ;; eth_getLogs implementation
(defn- event-topic-enc [event params] (defn- event-topic-enc [event params]
@ -158,7 +196,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:extensions/ethereum-resolve-ens :extensions/ethereum-resolve-ens
(fn [{db :db} [_ _ {:keys [name on-result] :as arguments}]] (fn [{db :db} [_ _ {:keys [name on-result]}]]
(if (ens/is-valid-eth-name? name) (if (ens/is-valid-eth-name? name)
(let [{:keys [web3 network]} db (let [{:keys [web3 network]} db
network-info (get-in db [:account/account :networks network]) network-info (get-in db [:account/account :networks network])

View File

@ -37,7 +37,8 @@
(.hexToUtf8 utils (str "0x" x))) (.hexToUtf8 utils (str "0x" x)))
(defn hex-to-number [x] (defn hex-to-number [x]
(.toNumber (dependencies/Web3.prototype.toBigNumber (str "0x" x) 16))) (when x
(.toNumber (dependencies/Web3.prototype.toBigNumber (str "0x" x) 16))))
(defn sha3 [s] (defn sha3 [s]
(.sha3 utils (str s))) (.sha3 utils (str s)))

View File

@ -523,6 +523,9 @@
(defn nfts-for [all-tokens chain] (defn nfts-for [all-tokens chain]
(filter :nft? (tokens-for all-tokens chain))) (filter :nft? (tokens-for all-tokens chain)))
(defn token-for [chain all-tokens token]
(some #(when (= token (name (:symbol %))) %) (tokens-for all-tokens chain)))
(defn sorted-tokens-for [all-tokens chain] (defn sorted-tokens-for [all-tokens chain]
(->> (tokens-for all-tokens chain) (->> (tokens-for all-tokens chain)
(filter #(not (:hidden? %))) (filter #(not (:hidden? %)))

View File

@ -94,11 +94,13 @@
(defn token->unit [n decimals] (defn token->unit [n decimals]
(when-let [bn (bignumber n)] (when-let [bn (bignumber n)]
(.dividedBy bn (bignumber (from-decimal decimals))))) (when-let [d (from-decimal decimals)]
(.dividedBy bn (bignumber d)))))
(defn unit->token [n decimals] (defn unit->token [n decimals]
(when-let [bn (bignumber n)] (when-let [bn (bignumber n)]
(.times bn (bignumber (from-decimal decimals))))) (when-let [d (from-decimal decimals)]
(.times bn (bignumber d)))))
;;NOTE(goranjovic) - We have two basic representations of values that refer to cryptocurrency amounts: formatted and ;;NOTE(goranjovic) - We have two basic representations of values that refer to cryptocurrency amounts: formatted and
;; internal. Formatted representation is the one we show on screens and include in reports, whereas internal ;; internal. Formatted representation is the one we show on screens and include in reports, whereas internal

View File

@ -2,6 +2,9 @@
(:require [cljs.test :refer-macros [deftest is testing]] (:require [cljs.test :refer-macros [deftest is testing]]
[status-im.utils.ethereum.abi-spec :as abi-spec])) [status-im.utils.ethereum.abi-spec :as abi-spec]))
(deftest enc
(is (= "000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" (abi-spec/enc {:type :address :value "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}))))
(deftest test-encode (deftest test-encode
(is (= (abi-spec/encode "baz(uint32,bool)" [69 true]) (is (= (abi-spec/encode "baz(uint32,bool)" [69 true])
"0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001")) "0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001"))