[Fixes #6874] Added transaction-receipt, schedule and balance events
Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
parent
6365a0d1e2
commit
e3e75e0498
|
@ -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)"))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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])
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
|
@ -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? %)))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"))
|
||||||
|
|
Loading…
Reference in New Issue