Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[refactoring] remove web3, clean up wallet effects #8232

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/status_im/accounts/login/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@
(fx/defn initialize-wallet [cofx]
(fx/merge cofx
(wallet/initialize-tokens)
(wallet/update-balances)
(wallet/update-prices)
(transactions/initialize)
(ethereum.subscriptions/initialize)
(wallet/update-wallet)))
(ethereum.subscriptions/initialize)))

(fx/defn user-login [{:keys [db] :as cofx} create-database?]
(let [{:keys [address password]} (accounts.db/credentials cofx)]
Expand Down
6 changes: 3 additions & 3 deletions src/status_im/chat/commands/impl/transactions.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,9 @@
;; TODO(janherich) - refactor wallet send events, updating gas price
;; is generic thing which shouldn't be defined in wallet.send, then
;; we can include the utility helper without running into circ-dep problem
:update-gas-price {:web3 (:web3 db)
:success-event :wallet/update-gas-price-success
:edit? false}}
:wallet/update-gas-price
{:success-event :wallet/update-gas-price-success
:edit? false}}
(navigation/navigate-to-cofx next-view-id {}))))
protocol/EnhancedParameters
(enhance-send-parameters [_ parameters cofx]
Expand Down
61 changes: 61 additions & 0 deletions src/status_im/ethereum/contracts.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
(ns status-im.ethereum.contracts
(:require [re-frame.core :as re-frame]
[status-im.utils.ethereum.abi-spec :as abi-spec]
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.fx :as fx]
[status-im.utils.money :as money]
[status-im.wallet.core :as wallet]))

(def contracts
{:status/tribute-to-talk
{:address
{:mainnet nil
:testnet "0x3da3fc53e24707f36c5b4433b442e896c4955f0e"
:rinkeby nil}
:methods
{:get-manifest
{:signature "getManifest(address)"
:outputs ["bytes"]}
:set-manifest
{:signature "setManifest(bytes)"
:write? true}}}})

(re-frame/reg-fx
::call
(fn [{:keys [address data callback]}]
(ethereum/call {:to address
:data data}
callback)))

(defn get-contract-address
[db contract]
(let [chain-keyword (-> (get-in db [:account/account :networks (:network db)])
ethereum/network->chain-keyword)]
(get-in contracts [contract :address chain-keyword])))

(fx/defn call
[{:keys [db] :as cofx}
{:keys [contract contract-address method params
callback on-result on-error details]}]
(when-let [contract-address (or contract-address
(get-contract-address db contract))]
(let [{:keys [signature outputs write?]}
(get-in contracts [contract :methods method])
data (abi-spec/encode signature params)]
(if write?
(wallet/open-sign-transaction-flow
cofx
(merge {:to contract-address
:data data
:id "approve"
:symbol :ETH
:method "eth_sendTransaction"
:amount (money/bignumber 0)
:on-result on-result
:on-error on-error}
details))
{::call {:address contract-address
:data data
:callback #(callback (if (empty? outputs)
%
(abi-spec/decode % outputs)))}}))))
74 changes: 74 additions & 0 deletions src/status_im/ethereum/json_rpc.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
(ns status-im.ethereum.json-rpc
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.ethereum.decode :as decode]
[status-im.native-module.core :as status]
[status-im.utils.ethereum.abi-spec :as abi-spec]
[status-im.utils.money :as money]
[status-im.utils.types :as types]
[taoensso.timbre :as log]))

(def json-rpc-api
{"eth_call" {}
"eth_getBalance"
{:on-result money/bignumber}
"eth_estimateGas"
{:on-result money/bignumber}
"eth_gasPrice"
{:on-result money/bignumber}
"eth_getBlockByHash"
{:on-result #(-> (update % :number decode/uint)
(update :timestamp decode/uint))}
"eth_getTransactionByHash" {}
"eth_getTransactionReceipt" {}
"eth_newBlockFilter" {:subscription? true}
"eth_newFilter" {:subscription? true}})

(defn call
[{:keys [method params on-success on-error]}]
(when-let [method-options (json-rpc-api method)]
(let [{:keys [id on-result subscription?]
:or {on-result identity
id 1
params []}} method-options
on-error (or on-error
#(log/error :json-rpc/error method :params params :error %))]
(if (nil? method)
(log/error :json-rpc/method-not-found method)
(status/call-private-rpc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be good to have something like (status/call-private-rpc "name" params)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is what I made initially but it turns out you always have different options so I figured it is better to have this generic function taking a map.

(types/clj->json {:jsonrpc "2.0"
:id id
:method (if subscription?
"eth_subscribeSignal"
method)
:params (if subscription?
[method params]
params)})
(fn [response]
(if (string/blank? response)
(on-error {:message "Blank response"})
(let [{:keys [error result] :as response2} (types/json->clj response)]
(if error
(on-error error)
(if subscription?
(re-frame/dispatch
[:ethereum.callback/subscription-success
result on-success])
(on-success (on-result result))))))))))))

(defn eth-call
[{:keys [contract method params outputs on-success on-error block]
:or {block "latest"
params []}}]
(call {:method "eth_call"
:params [{:to contract
:data (abi-spec/encode method params)}
(if (int? block)
(abi-spec/number-to-hex block)
block)]
:on-success
(if outputs
#(on-success (abi-spec/decode % outputs))
on-success)
:on-error
on-error}))
51 changes: 18 additions & 33 deletions src/status_im/ethereum/subscriptions.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
[status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.fx :as fx]
[status-im.utils.types :as types]
[taoensso.timbre :as log]))
[taoensso.timbre :as log]
[status-im.ethereum.json-rpc :as json-rpc]))

(fx/defn handle-signal
[cofx {:keys [subscription_id data] :as event}]
Expand Down Expand Up @@ -56,33 +57,14 @@
;; from etherscan
(transactions/initialize))))))

(defn subscribe-signal
[filter params callback]
(status/call-private-rpc
(types/clj->json {:jsonrpc "2.0"
:id 1
:method "eth_subscribeSignal"
:params [filter params]})
(fn [response]
(if (string/blank? response)
(log/error ::subscription-unknown-error :filter filter :params params)
(let [{:keys [error result]}
(-> (.parse js/JSON response)
(js->clj :keywordize-keys true))]
(if error
(log/error ::subscription-error error :filter filter :params params)
(re-frame/dispatch [:ethereum.callback/subscription-success
result
callback])))))))

(defn new-token-transaction-filter
[{:keys [chain-tokens from to] :as args}]
(subscribe-signal
"eth_newFilter"
[{:fromBlock "latest"
:toBlock "latest"
:topics [constants/event-transfer-hash from to]}]
(transactions/inbound-token-transfer-handler chain-tokens)))
(json-rpc/call
{:method "eth_newFilter"
:params [{:fromBlock "latest"
:toBlock "latest"
:topics [constants/event-transfer-hash from to]}]
:on-success (transactions/inbound-token-transfer-handler chain-tokens)}))

(re-frame/reg-fx
:ethereum.subscriptions/token-transactions
Expand All @@ -95,13 +77,16 @@

(defn new-block-filter
[]
(subscribe-signal
"eth_newBlockFilter" []
(fn [[block-hash]]
(transactions/get-block-by-hash
block-hash
(fn [block]
(re-frame/dispatch [:ethereum.signal/new-block block]))))))
(json-rpc/call
{:method "eth_newBlockFilter"
:on-success
(fn [[block-hash]]
(json-rpc/call
{:method "eth_getBlockByHash"
:params [block-hash true]
:on-success
(fn [block]
(re-frame/dispatch [:ethereum.signal/new-block block]))}))}))

(re-frame/reg-fx
:ethereum.subscriptions/new-block
Expand Down