mirror of
https://github.com/status-im/status-mobile.git
synced 2025-02-04 12:55:03 +00:00
[wallet] use status-go wallet service
- remove use of etherscan and subscriptions - replace by status-go
This commit is contained in:
parent
c3c4a5170a
commit
562773fa1b
8
src/status_im/ethereum/encode.cljs
Normal file
8
src/status_im/ethereum/encode.cljs
Normal file
@ -0,0 +1,8 @@
|
||||
(ns status-im.ethereum.encode
|
||||
(:require [status-im.js-dependencies :as dependencies]))
|
||||
|
||||
(defn utils [] (dependencies/web3-utils))
|
||||
|
||||
(defn uint
|
||||
[x]
|
||||
(.numberToHex (utils) x))
|
@ -35,7 +35,8 @@
|
||||
"status_joinPublicChat" {}
|
||||
"status_chats" {}
|
||||
"status_startOneOnOneChat" {}
|
||||
"status_removeChat" {}})
|
||||
"status_removeChat" {}
|
||||
"wallet_getTransfers" {}})
|
||||
|
||||
(defn call
|
||||
[{:keys [method params on-success on-error]}]
|
||||
|
@ -4,6 +4,7 @@
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.wallet.db :as wallet]
|
||||
[status-im.ethereum.transactions.core :as transactions]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]))
|
||||
@ -22,82 +23,37 @@
|
||||
[{:keys [db]} id handler]
|
||||
{:db (assoc-in db [:ethereum/subscriptions id] handler)})
|
||||
|
||||
(defn keep-user-transactions
|
||||
[wallet-address transactions]
|
||||
(keep (fn [{:keys [to from] :as transaction}]
|
||||
(when-let [direction (cond
|
||||
(= wallet-address to) :inbound
|
||||
(= wallet-address from) :outbound)]
|
||||
(assoc transaction :direction direction)))
|
||||
transactions))
|
||||
|
||||
(fx/defn new-block
|
||||
[{:keys [db] :as cofx} {:keys [number transactions] :as block}]
|
||||
(when number
|
||||
(let [{:keys [:wallet/all-tokens :ethereum/current-block]} db
|
||||
chain (ethereum/chain-keyword db)
|
||||
chain-tokens (into {} (map (juxt :address identity)
|
||||
(tokens/tokens-for all-tokens chain)))
|
||||
wallet-address (ethereum/current-address db)
|
||||
token-contracts-addresses (into #{} (keys chain-tokens))]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:ethereum/current-block] number)
|
||||
:ethereum.transactions/enrich-transactions-from-new-blocks
|
||||
{:chain-tokens chain-tokens
|
||||
:block block
|
||||
:transactions (keep-user-transactions wallet-address
|
||||
transactions)}}
|
||||
(transactions/check-watched-transactions)
|
||||
(when (or (not current-block)
|
||||
(not= number (inc current-block)))
|
||||
;; in case we skipped some blocks or got an uncle, re-fetch history
|
||||
;; from etherscan
|
||||
(transactions/initialize))))))
|
||||
|
||||
(defn new-token-transaction-filter
|
||||
[{:keys [chain-tokens from to] :as args}]
|
||||
(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
|
||||
(fn [{:keys [address] :as args}]
|
||||
;; start inbound token transaction subscriptions
|
||||
;; outbound token transactions are already caught in new blocks filter
|
||||
(new-token-transaction-filter (merge args
|
||||
{:direction :inbound
|
||||
:to address}))))
|
||||
|
||||
(defn new-block-filter
|
||||
[]
|
||||
(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
|
||||
new-block-filter)
|
||||
|
||||
(fx/defn initialize
|
||||
[{:keys [db] :as cofx}]
|
||||
[{:keys [db] :as cofx} historical? block-number accounts]
|
||||
(let [{:keys [:wallet/all-tokens]} db
|
||||
chain (ethereum/chain-keyword db)
|
||||
chain-tokens (into {} (map (juxt :address identity)
|
||||
(tokens/tokens-for all-tokens chain)))
|
||||
normalized-address (ethereum/current-address db)
|
||||
padded-address (transactions/add-padding normalized-address)]
|
||||
{:ethereum.subscriptions/new-block nil
|
||||
:ethereum.subscriptions/token-transactions
|
||||
{:chain-tokens chain-tokens
|
||||
:address padded-address}}))
|
||||
(tokens/tokens-for all-tokens chain)))]
|
||||
(fx/merge cofx
|
||||
(cond-> {}
|
||||
(not historical?)
|
||||
(assoc :db (assoc db [:ethereum/current-block] block-number))
|
||||
|
||||
(not-empty accounts)
|
||||
(assoc ::transactions/get-transfers {:chain-tokens chain-tokens
|
||||
:from-block block-number}))
|
||||
(transactions/check-watched-transactions))))
|
||||
|
||||
(fx/defn reorg
|
||||
[{:keys [db] :as cofx} block-number accounts]
|
||||
(let [{:keys [:wallet/all-tokens]} db
|
||||
chain (ethereum/chain-keyword db)
|
||||
chain-tokens (into {} (map (juxt :address identity)
|
||||
(tokens/tokens-for all-tokens chain)))]
|
||||
{:db (update-in db [:wallet :transactions]
|
||||
wallet/remove-transactions-since-block block-number)
|
||||
::transactions/get-transfers {:chain-tokens chain-tokens
|
||||
:from-block block-number}}))
|
||||
|
||||
(fx/defn new-wallet-event
|
||||
[{:keys [db] :as cofx} {:keys [type blockNumber accounts] :as event}]
|
||||
(case type
|
||||
"newblock" (new-block cofx false blockNumber accounts)
|
||||
"history" (new-block cofx true blockNumber accounts)
|
||||
"reorg" (reorg cofx blockNumber accounts)
|
||||
(log/warn ::unknown-wallet-event :type type :event event)))
|
||||
|
@ -2,14 +2,27 @@
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.decode :as decode]
|
||||
[status-im.ethereum.encode :as encode]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.ethereum.transactions.etherscan :as transactions.etherscan]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.wallet.core :as wallet]))
|
||||
|
||||
(def confirmations-count-threshold 12)
|
||||
|
||||
(def etherscan-supported? #{:testnet :mainnet :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)))))
|
||||
|
||||
(defn add-padding [address]
|
||||
{:pre [(string? address)]}
|
||||
(str "0x000000000000000000000000" (subs address 2)))
|
||||
@ -23,120 +36,61 @@
|
||||
:decimals 18
|
||||
:name "ERC20"})
|
||||
|
||||
(defn direction
|
||||
[address to]
|
||||
(if (= address to)
|
||||
:inbound
|
||||
:outbound))
|
||||
|
||||
(defn- parse-token-transfer
|
||||
[chain-tokens direction transfer]
|
||||
[chain-tokens transfer]
|
||||
(let [{:keys [blockHash transactionHash topics data address]} transfer
|
||||
[_ from to] topics
|
||||
{:keys [nft? symbol] :as token} (get chain-tokens address
|
||||
default-erc20-token)]
|
||||
(when-not nft?
|
||||
(cond-> {:hash transactionHash
|
||||
:symbol symbol
|
||||
:from (remove-padding from)
|
||||
:to (remove-padding to)
|
||||
:value (money/bignumber data)
|
||||
:type direction
|
||||
:token token
|
||||
:error? false
|
||||
;; NOTE(goranjovic) - just a flag we need when we merge this entry
|
||||
;; with the existing entry in the app, e.g. transaction info with
|
||||
;; gas details, or a previous transfer entry with old confirmations
|
||||
;; count.
|
||||
:transfer true}
|
||||
(= :inbound direction)
|
||||
(assoc :block-hash blockHash)))))
|
||||
{:hash transactionHash
|
||||
:symbol symbol
|
||||
:from (remove-padding from)
|
||||
:to (remove-padding to)
|
||||
:value (money/bignumber data)
|
||||
:type (direction address to)
|
||||
:token token
|
||||
:error? false
|
||||
;; NOTE(goranjovic) - just a flag we need when we merge this entry
|
||||
;; with the existing entry in the app, e.g. transaction info with
|
||||
;; gas details, or a previous transfer entry with old confirmations
|
||||
;; count.
|
||||
:transfer true})))
|
||||
|
||||
(defn enrich-transaction-from-new-block
|
||||
[chain-tokens
|
||||
{:keys [number timestamp]}
|
||||
{:keys [transfer direction hash gasPrice value gas from input nonce to] :as transaction}]
|
||||
(json-rpc/call
|
||||
{:method "eth_getTransactionReceipt"
|
||||
:params [hash]
|
||||
:on-success
|
||||
(fn [{:keys [gasUsed logs] :as receipt}]
|
||||
(let [[event _ _] (:topics (first logs))
|
||||
transfer (= constants/event-transfer-hash event)]
|
||||
(re-frame/dispatch
|
||||
[:ethereum.transactions/new
|
||||
(merge {:block (str number)
|
||||
:timestamp (str (* timestamp 1000))
|
||||
:gas-used (str (decode/uint gasUsed))
|
||||
:gas-price (str (decode/uint gasPrice))
|
||||
:gas-limit (str (decode/uint gas))
|
||||
:nonce (str (decode/uint nonce))
|
||||
:data input}
|
||||
(if transfer
|
||||
(parse-token-transfer chain-tokens
|
||||
:outbound
|
||||
(first logs))
|
||||
;; this is not a ERC20 token transaction
|
||||
{:hash hash
|
||||
:symbol :ETH
|
||||
:from from
|
||||
:to to
|
||||
:type direction
|
||||
:value (str (decode/uint value))}))])))}))
|
||||
(defn enrich-transfer
|
||||
[chain-tokens transfer]
|
||||
(let [{:keys [address blockNumber timestamp type transaction receipt from]} transfer
|
||||
{:keys [hash gasPrice value gas input nonce to]} transaction
|
||||
{:keys [gasUsed logs]} receipt
|
||||
erc20? (= type "erc20")]
|
||||
(merge {:block (str (decode/uint blockNumber))
|
||||
:timestamp (* (decode/uint timestamp) 1000)
|
||||
:gas-used (str (decode/uint gasUsed))
|
||||
:gas-price (str (decode/uint gasPrice))
|
||||
:gas-limit (str (decode/uint gas))
|
||||
:nonce (str (decode/uint nonce))
|
||||
:data input}
|
||||
(if erc20?
|
||||
(parse-token-transfer chain-tokens (first logs))
|
||||
;; this is not a ERC20 token transaction
|
||||
{:hash hash
|
||||
:symbol :ETH
|
||||
:from from
|
||||
:to to
|
||||
:type (direction address to)
|
||||
:value (str (decode/uint value))}))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:ethereum.transactions/enrich-transactions-from-new-blocks
|
||||
(fn [{:keys [chain-tokens block transactions]}]
|
||||
(doseq [transaction transactions]
|
||||
(enrich-transaction-from-new-block chain-tokens
|
||||
block
|
||||
transaction))))
|
||||
|
||||
(defn inbound-token-transfer-handler
|
||||
"The handler gets a list of inbound token transfer events and parses each
|
||||
transfer. Transfers are grouped by block the following chain of callbacks
|
||||
follows:
|
||||
- get block by hash is called to get the `timestamp` of each block
|
||||
- get transaction by hash is called on each transaction to get the `gasPrice`
|
||||
`gas` used, `input` data and `nonce` of each transaction
|
||||
- get transaction receipt is used to get the `gasUsed`
|
||||
- finally everything is merged into one map that is dispatched in a
|
||||
`ethereum.signal/new-transaction` event for each transfer"
|
||||
[chain-tokens]
|
||||
(fn [transfers]
|
||||
(let [transfers-by-block
|
||||
(group-by :block-hash
|
||||
(keep #(parse-token-transfer
|
||||
chain-tokens
|
||||
:inbound
|
||||
%)
|
||||
transfers))]
|
||||
;; TODO: remove this callback chain by implementing a better status-go api
|
||||
;; This function takes the map of supported tokens as params and returns a
|
||||
;; handler for token transfer events
|
||||
(doseq [[block-hash block-transfers] transfers-by-block]
|
||||
(json-rpc/call
|
||||
{:method "eth_getBlockByHash"
|
||||
:params [block-hash false]
|
||||
:on-success
|
||||
(fn [{:keys [timestamp number]}]
|
||||
(let [timestamp (str (* timestamp 1000))]
|
||||
(doseq [{:keys [hash] :as transfer} block-transfers]
|
||||
(json-rpc/call
|
||||
{:method "eth_getTransactionByHash"
|
||||
:params [hash]
|
||||
:on-success
|
||||
(fn [{:keys [gasPrice gas input nonce]}]
|
||||
(json-rpc/call
|
||||
{:method "eth_getTransactionReceipt"
|
||||
:params [hash]
|
||||
:on-success
|
||||
(fn [{:keys [gasUsed]}]
|
||||
(re-frame/dispatch
|
||||
[:ethereum.transactions/new
|
||||
(-> transfer
|
||||
(dissoc :block-hash)
|
||||
(assoc :timestamp timestamp
|
||||
:block (str number)
|
||||
:gas-used (str (decode/uint gasUsed))
|
||||
:gas-price (str (decode/uint gasPrice))
|
||||
:gas-limit (str (decode/uint gas))
|
||||
:data input
|
||||
:nonce (str (decode/uint nonce))))]))}))}))))})))))
|
||||
(defn enrich-transfers
|
||||
[chain-tokens transfers]
|
||||
(mapv (fn [transfer]
|
||||
(enrich-transfer chain-tokens transfer))
|
||||
transfers))
|
||||
|
||||
;; -----------------------------------------------
|
||||
;; transactions api
|
||||
@ -172,17 +126,24 @@
|
||||
(let [watched-transactions
|
||||
(select-keys (get-in db [:wallet :transactions])
|
||||
(keys (get db :ethereum/watched-transactions)))]
|
||||
(apply fx/merge cofx
|
||||
(apply fx/merge
|
||||
cofx
|
||||
(map (fn [[_ transaction]]
|
||||
(check-transaction transaction))
|
||||
watched-transactions))))
|
||||
|
||||
(fx/defn new
|
||||
[{:keys [db] :as cofx} {:keys [hash] :as transaction}]
|
||||
(fx/defn add-transfer
|
||||
[{:keys [db] :as cofx} {:keys [hash] :as transfer}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:wallet :transactions hash] transaction)}
|
||||
(check-transaction transaction)
|
||||
wallet/update-balances))
|
||||
{:db (assoc-in db [:wallet :transactions hash] transfer)}
|
||||
(check-transaction transfer)))
|
||||
|
||||
(fx/defn new-transfers
|
||||
{:events [::new-transfers]}
|
||||
[{:keys [db] :as cofx} transfers]
|
||||
(let [add-transfers-fx (map add-transfer transfers)]
|
||||
(apply fx/merge cofx (conj add-transfers-fx
|
||||
wallet/update-balances))))
|
||||
|
||||
(fx/defn handle-history
|
||||
[{:keys [db] :as cofx} transactions]
|
||||
@ -198,6 +159,23 @@
|
||||
[:wallet :transactions]
|
||||
merge transactions)})
|
||||
|
||||
(re-frame/reg-fx
|
||||
::get-transfers
|
||||
(fn [{:keys [chain-tokens from-block to-block]
|
||||
:or {from-block "0"
|
||||
to-block nil}}]
|
||||
;; start inbound token transaction subscriptions
|
||||
;; outbound token transactions are already caught in new blocks filter
|
||||
(json-rpc/call
|
||||
{:method "wallet_getTransfers"
|
||||
:params [(encode/uint from-block) (encode/uint to-block)]
|
||||
:on-success #(re-frame/dispatch
|
||||
[::new-transfers (enrich-transfers chain-tokens %)])})))
|
||||
|
||||
(fx/defn initialize
|
||||
[cofx]
|
||||
(transactions.etherscan/fetch-history cofx))
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [:wallet/all-tokens]} db
|
||||
chain (ethereum/chain-keyword db)
|
||||
chain-tokens (into {} (map (juxt :address identity)
|
||||
(tokens/tokens-for all-tokens chain)))]
|
||||
{::get-transfers {:chain-tokens chain-tokens}}))
|
||||
|
@ -1,191 +0,0 @@
|
||||
(ns status-im.ethereum.transactions.etherscan
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; etherscan transactions
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(def etherscan-supported? #{:testnet :mainnet :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 etherscan-api-key "DMSI4UAAKUBVGCDMVP3H2STAMSAUV7BYFI")
|
||||
|
||||
(defn- get-api-network-subdomain [chain]
|
||||
(case chain
|
||||
(:testnet) "api-ropsten"
|
||||
(:mainnet) "api"
|
||||
(:rinkeby) "api-rinkeby"))
|
||||
|
||||
(defn- get-transaction-url
|
||||
([chain address] (get-transaction-url chain address false))
|
||||
([chain address chaos-mode?]
|
||||
{:pre [(keyword? chain) (string? address)]
|
||||
:post [(string? %)]}
|
||||
(let [network-subdomain (get-api-network-subdomain chain)]
|
||||
(if chaos-mode?
|
||||
"http://httpstat.us/500"
|
||||
(str "https://" network-subdomain
|
||||
".etherscan.io/api?module=account&action=txlist&address=" address
|
||||
"&startblock=0&endblock=99999999&sort=desc&apikey=" etherscan-api-key
|
||||
"&q=json")))))
|
||||
|
||||
(defn- get-token-transaction-url
|
||||
([chain address] (get-token-transaction-url chain address false))
|
||||
([chain address chaos-mode?]
|
||||
{:pre [(keyword? chain) (string? address)]
|
||||
:post [(string? %)]}
|
||||
(let [network-subdomain (get-api-network-subdomain chain)]
|
||||
(if chaos-mode?
|
||||
"http://httpstat.us/500"
|
||||
(str "https://" network-subdomain
|
||||
".etherscan.io/api?module=account&action=tokentx&address=" address
|
||||
"&startblock=0&endblock=999999999&sort=asc&apikey=" etherscan-api-key
|
||||
"&q=json")))))
|
||||
|
||||
(defn- format-transaction
|
||||
[address
|
||||
{:keys [value timeStamp blockNumber hash from to
|
||||
gas gasPrice gasUsed nonce input isError]}]
|
||||
(let [inbound? (= address to)
|
||||
error? (= "1" isError)]
|
||||
{:value value
|
||||
;; timestamp is in seconds, we convert it in ms
|
||||
:timestamp (str timeStamp "000")
|
||||
:symbol :ETH
|
||||
:type (cond error? :failed
|
||||
inbound? :inbound
|
||||
:else :outbound)
|
||||
:block blockNumber
|
||||
:hash hash
|
||||
:from from
|
||||
:to to
|
||||
:gas-limit gas
|
||||
:gas-price gasPrice
|
||||
:gas-used gasUsed
|
||||
:nonce nonce
|
||||
:data input}))
|
||||
|
||||
(defn- format-token-transaction
|
||||
[address
|
||||
chain-tokens
|
||||
{:keys [contractAddress blockHash hash tokenDecimal gasPrice value
|
||||
gas tokenName timeStamp transactionIndex tokenSymbol
|
||||
confirmations blockNumber from gasUsed input nonce
|
||||
cumulativeGasUsed to]}]
|
||||
(let [inbound? (= address to)
|
||||
token (get chain-tokens contractAddress
|
||||
{:name tokenName
|
||||
:symbol tokenSymbol
|
||||
:decimals tokenDecimal
|
||||
:address contractAddress})]
|
||||
{:value value
|
||||
;; timestamp is in seconds, we convert it in ms
|
||||
:timestamp (str timeStamp "000")
|
||||
:symbol (keyword tokenSymbol)
|
||||
:type (if inbound?
|
||||
:inbound
|
||||
:outbound)
|
||||
:block blockNumber
|
||||
:hash hash
|
||||
:from from
|
||||
:to to
|
||||
:gas-limit gas
|
||||
:gas-price gasPrice
|
||||
:gas-used gasUsed
|
||||
:nonce nonce
|
||||
:data input
|
||||
:error? false
|
||||
:transfer true
|
||||
:token token}))
|
||||
|
||||
(defn- format-transactions-response [response format-fn]
|
||||
(let [{:keys [result]} (types/json->clj response)]
|
||||
(cond-> {}
|
||||
(vector? result)
|
||||
(into (comp
|
||||
(map format-fn)
|
||||
(map (juxt :hash identity)))
|
||||
result))))
|
||||
|
||||
(defn- etherscan-history
|
||||
[chain address on-success on-error chaos-mode?]
|
||||
(if (etherscan-supported? chain)
|
||||
(let [url (get-transaction-url chain address chaos-mode?)]
|
||||
(log/debug :etherscan-transactions :url url)
|
||||
(http/get url
|
||||
#(on-success (format-transactions-response
|
||||
%
|
||||
(partial format-transaction address)))
|
||||
on-error))
|
||||
(log/info "Etherscan not supported for " chain)))
|
||||
|
||||
(defn- etherscan-token-history
|
||||
[chain address chain-tokens on-success on-error chaos-mode?]
|
||||
(if (etherscan-supported? chain)
|
||||
(let [token-url (get-token-transaction-url chain address chaos-mode?)]
|
||||
(log/debug :etherscan-token-transactions :token-url token-url)
|
||||
(http/get token-url
|
||||
#(on-success (format-transactions-response
|
||||
%
|
||||
(partial format-token-transaction address chain-tokens)))
|
||||
on-error))
|
||||
(log/info "Etherscan not supported for " chain)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:ethereum.transactions.etherscan/fetch-history
|
||||
(fn [{:keys [chain address on-success on-error chaos-mode?]}]
|
||||
(etherscan-history chain address on-success on-error chaos-mode?)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:ethereum.transactions.etherscan/fetch-token-history
|
||||
(fn [{:keys [chain chain-tokens address on-success on-error chaos-mode?]}]
|
||||
(etherscan-token-history chain address chain-tokens on-success on-error chaos-mode?)))
|
||||
|
||||
;; -----------------------------------------------
|
||||
;; chain transactions
|
||||
;; -----------------------------------------------
|
||||
|
||||
(fx/defn fetch-history
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [:multiaccount :wallet/all-tokens]} db
|
||||
chain (ethereum/chain-keyword db)
|
||||
chain-tokens (into {} (map (juxt :address identity)
|
||||
(tokens/tokens-for all-tokens chain)))
|
||||
chaos-mode? (get-in multiaccount [:settings :chaos-mode?])
|
||||
normalized-address (ethereum/current-address db)]
|
||||
#:ethereum.transactions.etherscan
|
||||
{:fetch-history
|
||||
{:chain chain
|
||||
:address normalized-address
|
||||
:on-success
|
||||
#(re-frame/dispatch
|
||||
[:ethereum.transactions.callback/fetch-history-success %])
|
||||
:on-error
|
||||
#(re-frame/dispatch
|
||||
[:ethereum.transactions.callback/etherscan-error %])
|
||||
:chaos-mode? chaos-mode?}
|
||||
:fetch-token-history
|
||||
{:chain chain
|
||||
:chain-tokens chain-tokens
|
||||
:address normalized-address
|
||||
:on-success
|
||||
#(re-frame/dispatch
|
||||
[:ethereum.transactions.callback/fetch-token-history-success %])
|
||||
:on-error
|
||||
#(re-frame/dispatch
|
||||
[:ethereum.transactions.callback/etherscan-error %])
|
||||
:chaos-mode? chaos-mode?}}))
|
@ -1835,11 +1835,6 @@
|
||||
(fn [cofx [_ id handler]]
|
||||
(ethereum.subscriptions/register-subscription cofx id handler)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:ethereum.signal/new-block
|
||||
(fn [cofx [_ block]]
|
||||
(ethereum.subscriptions/new-block cofx block)))
|
||||
|
||||
;; ethereum transactions events
|
||||
(handlers/register-handler-fx
|
||||
:ethereum.transactions.callback/fetch-history-success
|
||||
@ -1856,11 +1851,6 @@
|
||||
(fn [cofx [_ transactions]]
|
||||
(ethereum.transactions/handle-token-history cofx transactions)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:ethereum.transactions/new
|
||||
(fn [cofx [_ transaction]]
|
||||
(ethereum.transactions/new cofx transaction)))
|
||||
|
||||
;; wallet events
|
||||
|
||||
(handlers/register-handler-fx
|
||||
|
@ -88,8 +88,7 @@
|
||||
(wallet/initialize-tokens)
|
||||
(wallet/update-balances)
|
||||
(wallet/update-prices)
|
||||
(transactions/initialize)
|
||||
(ethereum.subscriptions/initialize)))
|
||||
(transactions/initialize)))
|
||||
|
||||
(fx/defn user-login-without-creating-db
|
||||
{:events [:multiaccounts.login.ui/password-input-submitted]}
|
||||
|
@ -120,6 +120,7 @@
|
||||
:LightClient true
|
||||
:MinimumPoW 0.001
|
||||
:EnableNTPSync true}
|
||||
:WalletConfig {:Enabled true}
|
||||
:ShhextConfig {:BackupDisabledDataDir (utils.platform/no-backup-directory)
|
||||
:InstallationID installation-id
|
||||
:MaxMessageDeliveryAttempts config/max-message-delivery-attempts
|
||||
|
@ -83,4 +83,5 @@
|
||||
"status.chats.did-change" (chat.loading/load-chats-from-rpc cofx)
|
||||
"whisper.filter.added" (transport.filters/handle-negotiated-filter cofx event)
|
||||
"messages.new" (transport.message/receive-messages cofx event)
|
||||
"wallet" (ethereum.subscriptions/new-wallet-event cofx event)
|
||||
(log/debug "Event " type " not handled" event))))
|
||||
|
@ -14,7 +14,6 @@
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.ethereum.transactions.core :as transactions]
|
||||
[status-im.ethereum.transactions.etherscan :as transactions.etherscan]
|
||||
[status-im.fleet.core :as fleet]
|
||||
[status-im.group-chats.db :as group-chats.db]
|
||||
[status-im.i18n :as i18n]
|
||||
@ -1166,12 +1165,12 @@
|
||||
:<- [:contacts/contacts-by-address]
|
||||
:<- [:ethereum/native-currency]
|
||||
(fn [[transactions contacts native-currency]]
|
||||
(reduce-kv (fn [acc hash transaction]
|
||||
(assoc acc
|
||||
hash
|
||||
(enrich-transaction transaction contacts native-currency)))
|
||||
{}
|
||||
transactions)))
|
||||
(reduce (fn [acc [hash transaction]]
|
||||
(assoc acc
|
||||
hash
|
||||
(enrich-transaction transaction contacts native-currency)))
|
||||
{}
|
||||
transactions)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/all-filters?
|
||||
@ -1296,7 +1295,7 @@
|
||||
(money/wei->str :eth
|
||||
(money/fee-value gas-used gas-price)
|
||||
native-currency-text))
|
||||
:url (transactions.etherscan/get-transaction-details-url
|
||||
:url (transactions/get-transaction-details-url
|
||||
chain-keyword
|
||||
hash)}))))))
|
||||
|
||||
|
@ -230,3 +230,6 @@
|
||||
|
||||
(def empty-message-map
|
||||
(priority-map-keyfn-by :clock-value >))
|
||||
|
||||
(def empty-transaction-map
|
||||
(priority-map-keyfn-by :block #(< (int %1) (int %2))))
|
||||
|
@ -3,7 +3,8 @@
|
||||
[status-im.i18n :as i18n]
|
||||
status-im.ui.screens.wallet.request.db
|
||||
status-im.ui.screens.wallet.send.db
|
||||
[status-im.utils.money :as money]))
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.priority-map :refer [empty-transaction-map]]))
|
||||
|
||||
(spec/def :wallet.send/recipient string?)
|
||||
|
||||
@ -65,10 +66,18 @@
|
||||
#{:inbound :outbound :pending :failed})
|
||||
|
||||
(def default-wallet
|
||||
{:filters default-wallet-filters})
|
||||
{:filters default-wallet-filters
|
||||
:transactions empty-transaction-map})
|
||||
|
||||
(defn get-confirmations
|
||||
[{:keys [block]} current-block]
|
||||
(if (and current-block block)
|
||||
(inc (- current-block block))
|
||||
0))
|
||||
|
||||
(defn remove-transactions-since-block
|
||||
[transactions block]
|
||||
(into empty-transaction-map
|
||||
(drop-while (fn [[k v]]
|
||||
(>= (int (:block v)) block))
|
||||
transactions)))
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user