use wallet_getTokensBalances to reduce number of rpc calls

This commit is contained in:
yenda 2019-08-24 02:26:48 +02:00
parent b45e7ccafb
commit ddefae11b1
No known key found for this signature in database
GPG Key ID: 0095623C0069DCE6
6 changed files with 138 additions and 143 deletions

View File

@ -59,6 +59,7 @@
"status_startOneOnOneChat" {}
"status_removeChat" {}
"wallet_getTransfers" {}
"wallet_getTokensBalances" {}
"browsers_getBrowsers" {}
"browsers_addBrowser" {}
"browsers_deleteBrowser" {}

View File

@ -2,6 +2,7 @@
(:require [re-frame.core :as re-frame]
[status-im.constants :as constants]
[status-im.ethereum.decode :as decode]
[status-im.ethereum.eip55 :as eip55]
[status-im.ethereum.encode :as encode]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.ethereum.core :as ethereum]

View File

@ -1628,11 +1628,6 @@
(fn [cofx [_ symbol checked?]]
(wallet/toggle-visible-token cofx symbol checked?)))
(handlers/register-handler-fx
:wallet/token-found
(fn [cofx [_ address symbol balance]]
(wallet/configure-token-balance-and-visibility cofx address symbol balance)))
(handlers/register-handler-fx
:wallet.settings.ui/navigate-back-pressed
(fn [cofx [_ on-close]]
@ -1641,36 +1636,6 @@
{:dispatch on-close})
(navigation/navigate-back))))
(handlers/register-handler-fx
:wallet.callback/update-balance-success
(fn [cofx [_ address balance]]
(wallet/update-balance cofx address balance)))
(handlers/register-handler-fx
:wallet.callback/update-balance-fail
(fn [cofx [_ err]]
(wallet/on-update-balance-fail cofx err)))
(handlers/register-handler-fx
:wallet.callback/update-token-balance-success
(fn [cofx [_ address symbol balance]]
(wallet/update-token-balance cofx address symbol balance)))
(handlers/register-handler-fx
:wallet.callback/update-token-balance-fail
(fn [cofx [_ symbol err]]
(wallet/on-update-token-balance-fail cofx symbol err)))
(handlers/register-handler-fx
:wallet.callback/update-prices-success
(fn [cofx [_ prices]]
(wallet/on-update-prices-success cofx prices)))
(handlers/register-handler-fx
:wallet.callback/update-prices-fail
(fn [cofx [_ err]]
(wallet/on-update-prices-fail cofx err)))
(handlers/register-handler-fx
:wallet.ui/show-transaction-details
(fn [cofx [_ hash address]]

View File

@ -354,12 +354,6 @@
(fn [{:keys [public-key]}]
public-key))
(re-frame/reg-sub
:multiaccount/default-address
:<- [:multiaccount]
(fn [{:keys [accounts]}]
(:address (ethereum/get-default-account accounts))))
(re-frame/reg-sub
:sign-in-enabled?
:<- [:multiaccounts/login]
@ -1012,7 +1006,7 @@
(re-frame/reg-sub
:account-portfolio-value
(fn [[_ address] _]
[(re-frame/subscribe [:balance (string/lower-case address)])
[(re-frame/subscribe [:balance address])
(re-frame/subscribe [:prices])
(re-frame/subscribe [:wallet/currency])
(re-frame/subscribe [:ethereum/chain-keyword])
@ -1073,7 +1067,7 @@
(re-frame/reg-sub
:wallet/visible-assets-with-amount
(fn [[_ address] _]
[(re-frame/subscribe [:balance (string/lower-case address)])
[(re-frame/subscribe [:balance address])
(re-frame/subscribe [:wallet/visible-assets])])
(fn [[balance visible-assets]]
(map #(assoc % :amount (get balance (:symbol %))) visible-assets)))
@ -1093,7 +1087,7 @@
(re-frame/reg-sub
:wallet/visible-assets-with-values
(fn [[_ address] _]
[(re-frame/subscribe [:wallet/visible-assets-with-amount (string/lower-case address)])
[(re-frame/subscribe [:wallet/visible-assets-with-amount address])
(re-frame/subscribe [:prices])
(re-frame/subscribe [:wallet/currency])])
(fn [[assets prices currency]]
@ -1130,7 +1124,7 @@
(re-frame/reg-sub
:wallet/transferrable-assets-with-amount
(fn [[_ address]]
(re-frame/subscribe [:wallet/visible-assets-with-amount (string/lower-case address)]))
(re-frame/subscribe [:wallet/visible-assets-with-amount address]))
(fn [all-assets]
(filter #(not (:nft? %)) all-assets)))
@ -1146,7 +1140,7 @@
:wallet/transactions
:<- [:wallet]
(fn [wallet [_ address]]
(get-in wallet [:accounts (string/lower-case address) :transactions])))
(get-in wallet [:accounts address :transactions])))
(re-frame/reg-sub
:wallet/filters
@ -1348,38 +1342,6 @@
(fn [send-transaction]
(:camera-flashlight send-transaction)))
(defn check-sufficient-funds
[{:keys [sufficient-funds?] :as transaction} balance symbol amount]
(cond-> transaction
(nil? sufficient-funds?)
(assoc :sufficient-funds?
(or (nil? amount)
(money/sufficient-funds? amount (get balance symbol))))))
(defn check-sufficient-gas
[transaction balance symbol amount]
(assoc transaction :sufficient-gas?
(or (nil? amount)
(let [available-ether (money/bignumber (get balance :ETH 0))
available-for-gas (if (= :ETH symbol)
(.minus available-ether (money/bignumber amount))
available-ether)]
(money/sufficient-funds? (-> transaction
:max-fee
money/bignumber
(money/formatted->internal :ETH 18))
(money/bignumber available-for-gas))))))
(re-frame/reg-sub
:wallet.send/transaction
:<- [::send-transaction]
:<- [:wallet]
(fn [[{:keys [amount symbol from] :as transaction} wallet]]
(let [balance (get-in wallet [:accounts from :balance])]
(-> transaction
(check-sufficient-funds balance symbol amount)
(check-sufficient-gas balance symbol amount)))))
(re-frame/reg-sub
:wallet/settings
:<- [:wallet]
@ -1903,6 +1865,27 @@
(or amount-error (get-sufficient-gas-error balance (:symbol token) amount-bn gas gasPrice)))
(get-sufficient-gas-error balance nil nil gas gasPrice))))
(re-frame/reg-sub
:wallet.send/transaction
:<- [::send-transaction]
:<- [:wallet]
:<- [:network-status]
:<- [:wallet/all-tokens]
:<- [:ethereum/chain-keyword]
(fn [[{:keys [amount symbol from to amount-error] :as transaction}
wallet network-status all-tokens chain]]
(let [balance (get-in wallet [:accounts from :balance])
token (tokens/asset-for all-tokens chain symbol)]
(assoc (merge transaction
(when amount
(get-sufficient-funds-error balance symbol amount)))
:balance balance
:token token
:sign-enabled? (and to
(nil? amount-error)
(not (nil? amount))
(= :online network-status))))))
;; NETWORK SETTINGS
(defn- filter-networks [network-type]

View File

@ -35,10 +35,10 @@
colors/white
colors/white-transparent-10)}]]])
(defn- render-send-transaction-view [{:keys [chain transaction scroll all-tokens amount-input network-status]}]
(let [{:keys [from amount amount-text amount-error asset-error to to-name sufficient-funds? symbol]} transaction
{:keys [decimals] :as token} (tokens/asset-for all-tokens chain symbol)
online? (= :online network-status)]
(defn- render-send-transaction-view
[{:keys [transaction scroll amount-input]}]
(let [{:keys [from amount amount-text amount-error token sign-enabled?
asset-error to to-name symbol]} transaction]
[wallet.components/simple-screen {:avoid-keyboard? true
:status-bar-type :wallet}
[toolbar (i18n/label :t/send-transaction)]
@ -58,16 +58,12 @@
:type :send
:symbol symbol}]
[wallet.components/amount-selector
{:error (or amount-error (when-not sufficient-funds? (i18n/label :t/wallet-insufficient-funds)))
{:error amount-error
:amount amount
:amount-text amount-text
:input-options {:on-change-text #(re-frame/dispatch [:wallet.send/set-and-validate-amount % symbol decimals])
:input-options {:on-change-text #(re-frame/dispatch [:wallet.send/set-and-validate-amount %])
:ref (partial reset! amount-input)}} token]]]
[sign-transaction-button (and to
(nil? amount-error)
(not (nil? amount))
sufficient-funds?
online?)]]]))
[sign-transaction-button sign-enabled?]]]))
(defn- send-transaction-view [{:keys [scroll]}]
(let [amount-input (atom nil)
@ -82,12 +78,6 @@
(defview send-transaction []
(letsubs [transaction [:wallet.send/transaction]
chain [:ethereum/chain-keyword]
scroll (atom nil)
network-status [:network-status]
all-tokens [:wallet/all-tokens]]
scroll (atom nil)]
[send-transaction-view {:transaction transaction
:scroll scroll
:chain chain
:all-tokens all-tokens
:network-status network-status}]))
:scroll scroll}]))

View File

@ -4,6 +4,7 @@
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.constants :as constants]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.eip55 :as eip55]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.ethereum.tokens :as tokens]
[status-im.i18n :as i18n]
@ -37,8 +38,8 @@
(json-rpc/call
{:method "eth_getBalance"
:params [address "latest"]
:on-success #(re-frame/dispatch [:wallet.callback/update-balance-success address %])
:on-error #(re-frame/dispatch [:wallet.callback/update-balance-fail %])}))))
:on-success #(re-frame/dispatch [::update-balance-success address %])
:on-error #(re-frame/dispatch [::update-balance-fail %])}))))
;; TODO(oskarth): At some point we want to get list of relevant
;; assets to get prices for
@ -56,6 +57,7 @@
(assoc-in db [:wallet :errors error-type] (or err :unknown-error)))
(fx/defn on-update-prices-fail
{::events [::update-prices-fail]}
[{:keys [db]} err]
(log/debug "Unable to get prices: " err)
{:db (-> db
@ -63,14 +65,16 @@
(assoc :prices-loading? false))})
(fx/defn on-update-balance-fail
{:events [::update-balance-fail]}
[{:keys [db]} err]
(log/debug "Unable to get balance: " err)
{:db (-> db
(assoc-error-message :balance-update :error-unable-to-get-balance))})
(fx/defn on-update-token-balance-fail
[{:keys [db]} symbol err]
(log/debug "Unable to get token " symbol "balance: " err)
{:events [::update-token-balance-fail]}
[{:keys [db]} err]
(log/debug "Unable to get tokens balances: " err)
{:db (-> db
(assoc-error-message :balance-update :error-unable-to-get-token-balance))})
@ -142,24 +146,48 @@
(validate-token-symbol! token)
(validate-token-name! token))))
(defn- clean-up-results
"remove empty balances
if there is no visible assets, returns all positive balances
otherwise return only the visible assets balances"
[results tokens assets]
(let [balances
(reduce (fn [acc [address balances]]
(let [pos-balances
(reduce (fn [acc [token-address token-balance]]
(if (pos? token-balance)
(let [token-symbol (get tokens (name token-address))]
(if (or (empty? assets)
(assets token-symbol))
(assoc acc token-symbol token-balance)
acc))
acc))
{}
balances)]
(if (not-empty pos-balances)
(assoc acc (eip55/address->checksum (name address)) pos-balances)
acc)))
{}
results)]
(when (not-empty balances)
balances)))
(re-frame/reg-fx
:wallet/get-tokens-balances
(fn [{:keys [addresses tokens assets]}]
;;TODO not great to have so many calls , should be optimized, there is wallet_getTokensBalances why wouldn't use it?
(doseq [{:keys [address symbol]} tokens]
(doseq [account-address addresses]
(json-rpc/eth-call
{:contract address
:method "balanceOf(address)"
:params [account-address]
:outputs ["uint256"]
:on-success (fn [[balance]]
(if (and assets (assets symbol))
(re-frame/dispatch [:wallet.callback/update-token-balance-success account-address symbol balance])
;; NOTE: when there it is not a visible assets we make an initialization round
(when (pos? balance)
(re-frame/dispatch [:wallet/token-found account-address symbol balance]))))
:on-error #(re-frame/dispatch [:wallet.callback/update-token-balance-fail symbol %])})))))
(let [tokens-addresses (keys tokens)]
(json-rpc/call
{:method "wallet_getTokensBalances"
:params [addresses tokens-addresses]
:on-success
(fn [results]
(when-let [balances (clean-up-results results tokens assets)]
(re-frame/dispatch (if (empty? assets)
;; NOTE: when there it is not a visible
;; assets we make an initialization round
[::tokens-found balances]
[::update-tokens-balances-success balances]))))
:on-error #(re-frame/dispatch [::update-token-balance-fail %])}))))
(defn clear-error-message [db error-type]
(update-in db [:wallet :errors] dissoc error-type))
@ -193,7 +221,10 @@
chain (ethereum/chain-keyword db)
assets (get-in settings [:wallet :visible-tokens chain])
tokens (->> (tokens/tokens-for all-tokens chain)
(remove #(or (:hidden? %))))]
(remove #(or (:hidden? %)))
(reduce (fn [acc {:keys [address symbol]}]
(assoc acc address symbol))
{}))]
(when (not= network-status :offline)
(fx/merge
cofx
@ -215,7 +246,7 @@
{:keys [address chaos-mode? settings]} :multiaccount :as db} :db}]
(let [chain (ethereum/chain-keyword db)
mainnet? (= :mainnet chain)
assets (get-in settings [:wallet :visible-tokens chain])
assets (get-in settings [:wallet :visible-tokens chain] #{})
tokens (tokens-symbols assets all-tokens chain)
currency-id (or (get-in settings [:wallet :currency]) :usd)
currency (get constants/currencies currency-id)]
@ -227,8 +258,8 @@
(wallet.utils/exchange-symbol))])
:to [(:code currency)]
:mainnet? mainnet?
:success-event :wallet.callback/update-prices-success
:error-event :wallet.callback/update-prices-fail
:success-event ::update-prices-success
:error-event ::update-prices-fail
:chaos-mode? chaos-mode?}
:db
@ -242,20 +273,18 @@
(disj ids id)))
(fx/defn on-update-prices-success
{:events [::update-prices-success]}
[{:keys [db]} prices]
{:db (assoc db
:prices prices
:prices-loading? false)})
(fx/defn update-balance
{:events [::update-balance-success]}
[{:keys [db]} address balance]
{:db (-> db
(assoc-in [:wallet :accounts address :balance :ETH] (money/bignumber balance)))})
(fx/defn update-token-balance
[{:keys [db]} address symbol balance]
{:db (-> db
(assoc-in [:wallet :accounts address :balance symbol] (money/bignumber balance)))})
{:db (assoc-in db
[:wallet :accounts (eip55/address->checksum address) :balance :ETH]
(money/bignumber balance))})
(defn update-toggle-in-settings
[{{:keys [multiaccount] :as db} :db} symbol checked?]
@ -268,6 +297,38 @@
(let [new-settings (update-toggle-in-settings cofx symbol checked?)]
(multiaccounts.update/update-settings cofx new-settings {})))
(fx/defn update-tokens-balances
{:events [::update-tokens-balances-success]}
[{:keys [db]} balances]
(let [accounts (get-in db [:wallet :accounts])]
{:db (assoc-in db
[:wallet :accounts]
(reduce (fn [acc [address balances]]
(assoc-in acc
[address :balance]
(reduce (fn [acc [token-symbol balance]]
(assoc acc
token-symbol
(money/bignumber balance)))
(get-in accounts [address :balance])
balances)))
accounts
balances))}))
(fx/defn configure-token-balance-and-visibility
{:events [::tokens-found]}
[{:keys [db] :as cofx} balances]
(let [chain (ethereum/chain-keyword db)
settings (get-in db [:multiaccount :settings])
visible-tokens (into #{} (flatten (map keys (vals balances))))
new-settings (assoc-in settings
[:wallet :visible-tokens chain]
visible-tokens)]
(fx/merge cofx
(multiaccounts.update/update-settings cofx new-settings {})
(update-tokens-balances balances)
(update-prices))))
(fx/defn add-custom-token
[{:keys [db] :as cofx} {:keys [symbol address] :as token}]
(let [chain (ethereum/chain-keyword db)
@ -282,24 +343,18 @@
new-settings (update-in settings [:wallet :custom-tokens chain] dissoc address)]
(multiaccounts.update/update-settings cofx new-settings {})))
(fx/defn configure-token-balance-and-visibility
[cofx address symbol balance]
(fx/merge cofx
(toggle-visible-token symbol true)
;;TODO(goranjovic): move `update-token-balance-success` function to wallet models
(update-token-balance address symbol balance)))
(defn set-and-validate-amount-db [db amount symbol decimals]
(let [{:keys [value error]} (wallet.db/parse-amount amount decimals)]
(-> db
(assoc-in [:wallet :send-transaction :amount] (money/formatted->internal value symbol decimals))
(assoc-in [:wallet :send-transaction :amount-text] amount)
(assoc-in [:wallet :send-transaction :amount-error] error))))
(fx/defn set-and-validate-amount
{:events [:wallet.send/set-and-validate-amount]}
[{:keys [db]} amount symbol decimals]
{:db (set-and-validate-amount-db db amount symbol decimals)})
[{:keys [db]} amount]
(let [chain (ethereum/chain-keyword db)
all-tokens (:wallet/all-tokens db)
symbol (get-in db [:wallet :send-transaction :symbol])
{:keys [decimals]} (tokens/asset-for all-tokens chain symbol)
{:keys [value error]} (wallet.db/parse-amount amount decimals)]
{:db (-> db
(assoc-in [:wallet :send-transaction :amount] (money/formatted->internal value symbol decimals))
(assoc-in [:wallet :send-transaction :amount-text] amount)
(assoc-in [:wallet :send-transaction :amount-error] error))}))
(fx/defn set-symbol
{:events [:wallet.send/set-symbol]}