[#12818] Support tx history (in a way) when on BSC chains

This commit is contained in:
Roman Volosovskyi 2021-11-27 11:02:53 +02:00
parent 89d42b9ef4
commit c7e66fb1aa
No known key found for this signature in database
GPG Key ID: 0238A4B5ECEE70DE
14 changed files with 215 additions and 118 deletions

View File

@ -17,16 +17,21 @@
(.hexToUtf8 utils s)
(catch :default _ nil)))
;; IDs standardized in https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md#list-of-chain-ids
(def BSC-mainnet-chain-id 56)
(def BSC-testnet-chain-id 97)
;; IDs standardized in https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md#list-of-chain-ids
(def chains
{:mainnet {:id 1 :name "Mainnet"}
:testnet {:id 3 :name "Ropsten"}
:rinkeby {:id 4 :name "Rinkeby"}
:xdai {:id 100 :name "xDai"}
:poa {:id 99 :name "POA"}
:goerli {:id 5 :name "Goerli"}
:bsc {:id 56 :name "BSC"}})
{:mainnet {:id 1 :name "Mainnet"}
:testnet {:id 3 :name "Ropsten"}
:rinkeby {:id 4 :name "Rinkeby"}
:xdai {:id 100 :name "xDai"}
:poa {:id 99 :name "POA"}
:goerli {:id 5 :name "Goerli"}
:bsc {:id BSC-mainnet-chain-id
:name "BSC"}
:bsc-testnet {:id BSC-testnet-chain-id
:name "BSC tetnet"}})
(defn chain-id->chain-keyword [i]
(or (some #(when (= i (:id (val %))) (key %)) chains)
@ -47,7 +52,8 @@
(defn testnet? [id]
(contains? #{(chain-keyword->chain-id :testnet)
(chain-keyword->chain-id :rinkeby)
(chain-keyword->chain-id :goerli)} id))
(chain-keyword->chain-id :goerli)
(chain-keyword->chain-id :bsc-testnet)} id))
(defn sidechain? [id]
(contains? #{(chain-keyword->chain-id :xdai)
@ -109,6 +115,16 @@
network-id (get db :networks/current-network)]
(get networks network-id)))
(defn binance-chain-id? [chain-id]
(or (= BSC-mainnet-chain-id chain-id)
(= BSC-testnet-chain-id chain-id)))
(defn binance-chain? [db]
(-> db
current-network
network->chain-id
binance-chain-id?))
(def custom-rpc-node-id-len 45)
(defn custom-rpc-node? [{:keys [id]}]

View File

@ -194,6 +194,7 @@
"wallet_getCryptoOnRamps" {}
"wallet_getOpenseaCollectionsByOwner" {}
"wallet_getOpenseaAssetsByOwnerAndCollection" {}
"wallet_loadTransferByHash" {}
"browsers_getBrowsers" {}
"browsers_addBrowser" {}
"browsers_deleteBrowser" {}

View File

@ -17,30 +17,34 @@
(def all-native-currencies
(ethereum.macros/resolve-native-currency-icons
{:mainnet {:name "Ether"
:symbol :ETH
:decimals 18}
:testnet {:name "Ropsten Ether"
:symbol :ETH
:symbol-display :ETHro
:decimals 18}
:rinkeby {:name "Rinkeby Ether"
:symbol :ETH
:symbol-display :ETHri
:decimals 18}
:poa {:name "POA"
:symbol :ETH
:symbol-display :POA
:decimals 18}
:xdai {:name "xDAI"
:symbol :ETH
:symbol-display :xDAI
:symbol-exchange :DAI
:decimals 18}
:bsc {:name "BSC"
:symbol :ETH
:symbol-display :BNB
:decimals 18}}))
{:mainnet {:name "Ether"
:symbol :ETH
:decimals 18}
:testnet {:name "Ropsten Ether"
:symbol :ETH
:symbol-display :ETHro
:decimals 18}
:rinkeby {:name "Rinkeby Ether"
:symbol :ETH
:symbol-display :ETHri
:decimals 18}
:poa {:name "POA"
:symbol :ETH
:symbol-display :POA
:decimals 18}
:xdai {:name "xDAI"
:symbol :ETH
:symbol-display :xDAI
:symbol-exchange :DAI
:decimals 18}
:bsc {:name "BSC"
:symbol :ETH
:symbol-display :BNB
:decimals 18}
:bsc-testnet {:name "BSC test"
:symbol :ETH
:symbol-display :BNBtest
:decimals 18}}))
(def native-currency-symbols
(set (map #(-> % val :symbol) all-native-currencies)))

View File

@ -2,6 +2,7 @@
(:require [cljs.spec.alpha :as spec]
[re-frame.core :as re-frame]
[status-im.ens.core :as ens]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.decode :as decode]
[status-im.ethereum.eip55 :as eip55]
[status-im.ethereum.encode :as encode]
@ -13,16 +14,31 @@
(def confirmations-count-threshold 12)
(def etherscan-supported? #{:testnet :mainnet :rinkeby})
(def etherscan-supported?
#{(ethereum/chain-keyword->chain-id :mainnet)
(ethereum/chain-keyword->chain-id :testnet)
(ethereum/chain-keyword->chain-id :rinkeby)})
(let [network->subdomain {:testnet "ropsten" :rinkeby "rinkeby"}]
(defn get-transaction-details-url [chain hash]
{:pre [(keyword? chain) (string? hash)]
:post [(or (nil? %) (string? %))]}
(when (etherscan-supported? chain)
(let [network-subdomain (when-let [subdomain (network->subdomain chain)]
(str subdomain "."))]
(str "https://" network-subdomain "etherscan.io/tx/" hash)))))
(def binance-mainnet-chain-id (ethereum/chain-keyword->chain-id :bsc))
(def binance-testnet-chain-id (ethereum/chain-keyword->chain-id :bsc-testnet))
(def network->subdomain {3 "ropsten"
4 "rinkeby"})
(defn get-transaction-details-url [chain-id hash]
{:pre [(number? chain-id) (string? hash)]
:post [(or (nil? %) (string? %))]}
(cond
(etherscan-supported? chain-id)
(let [network-subdomain (when-let [subdomain (network->subdomain chain-id)]
(str subdomain "."))]
(str "https://" network-subdomain "etherscan.io/tx/" hash))
(= chain-id binance-mainnet-chain-id)
(str "https://bscscan.com/tx/" hash)
(= chain-id binance-testnet-chain-id)
(str "https://testnet.bscscan.com/tx/" hash)))
(def default-erc20-token
{:symbol :ERC20
@ -358,6 +374,7 @@
(tx-fetching-in-progress [address]))))
(fx/defn get-fetched-transfers
{:events [:transaction/get-fetched-transfers]}
[{:keys [db]}]
{:transactions/get-transfers
{:chain-tokens (:wallet/all-tokens db)

View File

@ -122,8 +122,11 @@
(wallet/get-cached-balances scan-all-tokens?))
(when-not (get db :wallet/new-account)
(wallet/restart-wallet-service nil))
(when-not (utils.mobile-sync/syncing-allowed? cofx)
(when (or (not (utils.mobile-sync/syncing-allowed? cofx))
(ethereum/binance-chain? db))
(transactions/get-fetched-transfers))
(when (ethereum/binance-chain? db)
(wallet/request-current-block-update))
(prices/update-prices)))
(fx/defn login

View File

@ -304,13 +304,13 @@
(fx/defn transaction-result
[{:keys [db] :as cofx} result tx-obj]
(let [{:keys [on-result symbol amount]} (get db :signing/tx)]
(let [{:keys [on-result symbol amount from]} (get db :signing/tx)]
(fx/merge cofx
{:db (dissoc db :signing/tx :signing/sign)
:signing/show-transaction-result nil}
(prepare-unconfirmed-transaction result tx-obj symbol amount)
(check-queue)
(wallet/watch-tx result)
(wallet/watch-tx (get from :address) result)
#(when on-result
{:dispatch (conj on-result result)}))))
@ -323,7 +323,7 @@
(fx/merge
cofx
{:db (dissoc db :signing/tx :signing/sign)}
(wallet/watch-tx transaction-hash)
(wallet/watch-tx (get from :address) transaction-hash)
(if (keycard.common/keycard-multiaccount? db)
(signing.keycard/hash-message
{:data data

View File

@ -1776,11 +1776,11 @@
(get-in wallet [:fetching address :all-fetched?])))
(re-frame/reg-sub
:wallet/etherscan-link
:wallet/chain-explorer-link
(fn [db [_ address]]
(let [network (:networks/current-network db)
link (get-in config/default-networks-by-id
[network :etherscan-link])]
[network :chain-explorer-link])]
(when link
(str link address)))))
@ -2108,8 +2108,8 @@
(fn [[_ _ address] _]
[(re-frame/subscribe [:wallet.transactions/transactions address])
(re-frame/subscribe [:ethereum/native-currency])
(re-frame/subscribe [:ethereum/chain-keyword])])
(fn [[transactions native-currency chain-keyword] [_ hash _]]
(re-frame/subscribe [:chain-id])])
(fn [[transactions native-currency chain-id] [_ hash _]]
(let [{:keys [gas-used gas-price fee-cap tip-cap hash timestamp type]
:as transaction}
(get transactions hash)
@ -2147,7 +2147,7 @@
(money/fee-value gas-used gas-price)
native-currency-text))
:url (transactions/get-transaction-details-url
chain-keyword
chain-id
hash)}))))))
(re-frame/reg-sub
@ -2196,6 +2196,12 @@
:<- [:wallet]
:request-transaction)
(re-frame/reg-sub
:wallet/binance-chain?
:<- [:current-network]
(fn [network]
(ethereum/binance-chain-id? (get-in network [:config :NetworkId]))))
;;UI ==============================================================================================================
(re-frame/reg-sub

View File

@ -216,7 +216,7 @@
[{:ms 100 :dispatch [:process-statuses statuses]}])
(when (seq transactions)
(for [transaction-hash transactions]
{:ms 100 :dispatch [:watch-tx transaction-hash]})))}
{:ms 100 :dispatch [:watch-tx nil transaction-hash]})))}
(process-response response-js process-async)))))
(fx/defn remove-hash

View File

@ -110,8 +110,7 @@
[tabs/tab-title state :assets (i18n/label :t/wallet-assets) (= tab :assets)]
(when ethereum-network?
[tabs/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)])
(when ethereum-network?
[tabs/tab-title state :history (i18n/label :t/history) (= tab :history)])]
[tabs/tab-title state :history (i18n/label :t/history) (= tab :history)]]
(cond
(= tab :assets)
[:<>

View File

@ -73,8 +73,8 @@
{:on-press #(re-frame/dispatch [:signing.ui/cancel-transaction-pressed hash])}
(i18n/label :t/cancel)]])])
(defn etherscan-link [address]
(let [link @(re-frame/subscribe [:wallet/etherscan-link address])]
(defn chain-explorer-link [address]
(let [link @(re-frame/subscribe [:wallet/chain-explorer-link address])]
[react/touchable-highlight
{:on-press #(when link
(.openURL ^js react/linking link))}
@ -124,11 +124,12 @@
keycard-account? @(re-frame/subscribe [:multiaccounts/keycard-account?])
custom-rpc-node? @(re-frame/subscribe [:custom-rpc-node])
non-archival-rpc-node? @(re-frame/subscribe [:wallet/non-archival-node])
binance-chain? @(re-frame/subscribe [:wallet/binance-chain?])
all-fetched? @(re-frame/subscribe [:wallet/tx-history-fetched? address])
syncing-allowed? @(re-frame/subscribe [:mobile-network/syncing-allowed?])]
[react/view {:flex 1}
[etherscan-link address]
(cond non-archival-rpc-node?
[chain-explorer-link address]
(cond (or non-archival-rpc-node? binance-chain?)
[non-archival-node]
custom-rpc-node?
[custom-node])

View File

@ -1,8 +1,8 @@
(ns status-im.utils.config
(:require [clojure.string :as string]
(:require ["react-native-config" :default react-native-config]
[clojure.string :as string]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.ens :as ens]
["react-native-config" :default react-native-config]))
[status-im.ethereum.ens :as ens]))
(def config
(memoize
@ -94,56 +94,65 @@
(get-in default-multiaccount [:wallet/visible-tokens chain]))
(def mainnet-networks
[{:id "mainnet_rpc",
:etherscan-link "https://etherscan.io/address/",
:name "Mainnet with upstream RPC",
:config {:NetworkId (ethereum/chain-keyword->chain-id :mainnet)
:DataDir "/ethereum/mainnet_rpc"
:UpstreamConfig {:Enabled true
:URL mainnet-rpc-url}}}])
[{:id "mainnet_rpc",
:chain-explorer-link "https://etherscan.io/address/",
:name "Mainnet with upstream RPC",
:config {:NetworkId (ethereum/chain-keyword->chain-id :mainnet)
:DataDir "/ethereum/mainnet_rpc"
:UpstreamConfig {:Enabled true
:URL mainnet-rpc-url}}}])
(def sidechain-networks
[{:id "xdai_rpc",
:name "xDai Chain",
:config {:NetworkId (ethereum/chain-keyword->chain-id :xdai)
:DataDir "/ethereum/xdai_rpc"
:UpstreamConfig {:Enabled true
:URL "https://dai.poa.network"}}}
[{:id "xdai_rpc",
:name "xDai Chain",
:chain-explorer-link "https://blockscout.com/xdai/mainnet/address/",
:config {:NetworkId (ethereum/chain-keyword->chain-id :xdai)
:DataDir "/ethereum/xdai_rpc"
:UpstreamConfig {:Enabled true
:URL "https://dai.poa.network"}}}
{:id "poa_rpc",
:name "POA Network",
:config {:NetworkId (ethereum/chain-keyword->chain-id :poa)
:DataDir "/ethereum/poa_rpc"
:UpstreamConfig {:Enabled true
:URL "https://core.poa.network"}}}
{:id "bsc_rpc",
:name "BSC Network",
:config {:NetworkId (ethereum/chain-keyword->chain-id :bsc)
:DataDir "/ethereum/bsc_rpc"
:UpstreamConfig {:Enabled true
:URL "https://bsc-dataseed.binance.org"}}}])
{:id "bsc_rpc",
:chain-explorer-link "https://bscscan.com/address/",
:name "BSC Network",
:config {:NetworkId (ethereum/chain-keyword->chain-id :bsc)
:DataDir "/ethereum/bsc_rpc"
:UpstreamConfig {:Enabled true
:URL "https://bsc-dataseed.binance.org"}}}])
(def testnet-networks
[{:id "testnet_rpc",
:etherscan-link "https://ropsten.etherscan.io/address/",
:name "Ropsten with upstream RPC",
:config {:NetworkId (ethereum/chain-keyword->chain-id :testnet)
:DataDir "/ethereum/testnet_rpc"
:UpstreamConfig {:Enabled true
:URL testnet-rpc-url}}}
{:id "rinkeby_rpc",
:etherscan-link "https://rinkeby.etherscan.io/address/",
:name "Rinkeby with upstream RPC",
:config {:NetworkId (ethereum/chain-keyword->chain-id :rinkeby)
:DataDir "/ethereum/rinkeby_rpc"
:UpstreamConfig {:Enabled true
:URL (str "https://rinkeby.infura.io/v3/" INFURA_TOKEN)}}}
{:id "goerli_rpc",
:etherscan-link "https://goerli.etherscan.io/address/",
:name "Goerli with upstream RPC",
:config {:NetworkId (ethereum/chain-keyword->chain-id :goerli)
:DataDir "/ethereum/goerli_rpc"
:UpstreamConfig {:Enabled true
:URL (str "https://goerli.infura.io/v3/" INFURA_TOKEN)}}}])
[{:id "testnet_rpc",
:chain-explorer-link "https://ropsten.etherscan.io/address/",
:name "Ropsten with upstream RPC",
:config {:NetworkId (ethereum/chain-keyword->chain-id :testnet)
:DataDir "/ethereum/testnet_rpc"
:UpstreamConfig {:Enabled true
:URL testnet-rpc-url}}}
{:id "rinkeby_rpc",
:chain-explorer-link "https://rinkeby.etherscan.io/address/",
:name "Rinkeby with upstream RPC",
:config {:NetworkId (ethereum/chain-keyword->chain-id :rinkeby)
:DataDir "/ethereum/rinkeby_rpc"
:UpstreamConfig {:Enabled true
:URL (str "https://rinkeby.infura.io/v3/" INFURA_TOKEN)}}}
{:id "goerli_rpc",
:chain-explorer-link "https://goerli.etherscan.io/address/",
:name "Goerli with upstream RPC",
:config {:NetworkId (ethereum/chain-keyword->chain-id :goerli)
:DataDir "/ethereum/goerli_rpc"
:UpstreamConfig {:Enabled true
:URL (str "https://goerli.infura.io/v3/" INFURA_TOKEN)}}}
{:id "bsc_testnet_rpc",
:chain-explorer-link "https://testnet.bscscan.com/address/",
:name "BSC testnet",
:config {:NetworkId (ethereum/chain-keyword->chain-id :bsc-testnet)
:DataDir "/ethereum/bsc_testnet_rpc"
:UpstreamConfig {:Enabled true
:URL "https://data-seed-prebsc-1-s1.binance.org:8545/"}}}])
(def default-networks
(concat testnet-networks mainnet-networks sidechain-networks))

View File

@ -767,12 +767,15 @@
{:keys [force-restart? on-recent-history-fetching]
:as params}]
(when (:multiaccount db)
(let [syncing-allowed? (mobile-network-utils/syncing-allowed? cofx)]
(let [syncing-allowed? (mobile-network-utils/syncing-allowed? cofx)
binance-chain? (ethereum/binance-chain? db)]
(log/info "restart-wallet-service"
"force-restart?" force-restart?
"syncing-allowed?" syncing-allowed?)
(if (or syncing-allowed?
force-restart?)
"syncing-allowed?" syncing-allowed?
"binance-chain?" binance-chain?)
(if (and (or syncing-allowed?
force-restart?)
(not binance-chain?))
(check-recent-history cofx params)
(after-checking-history cofx)))))
@ -792,6 +795,27 @@
cofx
{:force-restart? force-restart?}))
(re-frame/reg-fx
:load-transaction-by-hash
(fn [[address hash]]
(log/info "calling wallet_loadTransferByHash" address hash)
(json-rpc/call
{:method "wallet_loadTransferByHash"
:params [address hash]
:on-success #(re-frame/dispatch [:transaction/get-fetched-transfers])
:on-error #(log/warn "Transfer loading failed" %)})))
(fx/defn load-transaction-by-hash
[_ address hash]
{:load-transaction-by-hash [address hash]})
(fx/defn transaction-included
{:events [::transaction-included]}
[{:keys [db] :as cofx} address hash]
(if (ethereum/binance-chain? db)
(load-transaction-by-hash cofx address hash)
(restart cofx true)))
(def pull-to-refresh-cooldown-period (* 1 60 1000))
(fx/defn restart-on-pull
@ -813,17 +837,17 @@
::start-watching
(fn [hashes]
(log/info "[wallet] watch transactions" hashes)
(doseq [hash hashes]
(doseq [[address hash] hashes]
(json-rpc/call
{:method "wallet_watchTransaction"
:params [hash]
:on-success #(re-frame.core/dispatch [::restart true])
:on-success #(re-frame.core/dispatch [::transaction-included address hash])
:on-error #(log/info "[wallet] watch transaction error" % "hash" hash)}))))
(fx/defn watch-tx
{:events [:watch-tx]}
[{:keys [db] :as cofx} tx-id]
{::start-watching [tx-id]})
[{:keys [db] :as cofx} address tx-id]
{::start-watching [[address tx-id]]})
(fx/defn watch-transsactions
[_ hashes]
@ -1020,7 +1044,7 @@
db)))
db
(map (partial normalize-transaction db) raw-transactions))
::start-watching (map :hash raw-transactions)})
::start-watching (map (juxt :from :hash) raw-transactions)})
(re-frame/reg-fx
:wallet/delete-pending-transactions
@ -1037,3 +1061,20 @@
[{:keys [db]} enabled?]
{::async-storage/set! {:transactions-management-enabled? enabled?}
:db (assoc db :wallet/transactions-management-enabled? enabled?)})
(fx/defn update-curent-block
{:events [::update-current-block]}
[{:keys [db]} block]
{:db (assoc db :ethereum/current-block block)})
(re-frame/reg-fx
::request-current-block-update
(fn []
(json-rpc/call
{:method "eth_getBlockByNumber"
:params ["latest" false]
:on-success #(re-frame/dispatch [::update-current-block (get % :number)])})))
(fx/defn request-current-block-update
[_]
{::request-current-block-update nil})

View File

@ -4,11 +4,11 @@
(deftest get-transaction-details-url
(is (= "https://etherscan.io/tx/asdfasdf"
(transactions/get-transaction-details-url :mainnet "asdfasdf")))
(transactions/get-transaction-details-url 1 "asdfasdf")))
(is (= "https://rinkeby.etherscan.io/tx/asdfasdfg"
(transactions/get-transaction-details-url :rinkeby "asdfasdfg")))
(transactions/get-transaction-details-url 4 "asdfasdfg")))
(is (= "https://ropsten.etherscan.io/tx/asdfasdfgg"
(transactions/get-transaction-details-url :testnet "asdfasdfgg")))
(is (nil? (transactions/get-transaction-details-url :not-a-net "asdfasdfg")))
(transactions/get-transaction-details-url 3 "asdfasdfgg")))
(is (nil? (transactions/get-transaction-details-url 7787878 "asdfasdfg")))
(is (thrown? js/Error (transactions/get-transaction-details-url nil "asdfasdfg")))
(is (thrown? js/Error (transactions/get-transaction-details-url :asdf 1))))
(is (thrown? js/Error (transactions/get-transaction-details-url 676868 1))))

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.91.8",
"commit-sha1": "a65c873b8f2633c05a0f108a84ccbc3b8456378a",
"src-sha256": "16c8nphz7jkfsgcp2gcv91lhky2ykkz0mrazg03pqdrcnjb2y774"
"version": "v0.91.10",
"commit-sha1": "7ef2efaabd643a476699d545d22faf36ba066b08",
"src-sha256": "0rwpbkqwzk772advqs6g98bqrbcvhs25xwwnfci04pqycklh11zb"
}