[refactor] transaction history and filters
This commit is contained in:
parent
f1b8ba8764
commit
2cd26c585d
|
@ -1,30 +1,34 @@
|
|||
(ns status-im.chat.commands.impl.transactions
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [clojure.string :as string]
|
||||
[reagent.core :as reagent]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.chat.commands.impl.transactions.styles
|
||||
:as
|
||||
transactions-styles]
|
||||
[status-im.chat.commands.protocol :as protocol]
|
||||
[status-im.chat.commands.impl.transactions.styles :as transactions-styles]
|
||||
[status-im.data-store.messages :as messages-store]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.svgimage :as svgimage]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.contact.db :as db.contact]
|
||||
[status-im.data-store.messages :as messages-store]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.svgimage :as svgimage]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.ui.screens.wallet.choose-recipient.events
|
||||
:as
|
||||
choose-recipient.events]
|
||||
[status-im.ui.screens.wallet.utils :as wallet.utils]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.utils.ethereum.core :as ethereum]
|
||||
[status-im.utils.ethereum.tokens :as tokens]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.screens.wallet.db :as wallet.db]
|
||||
[status-im.ui.screens.wallet.choose-recipient.events :as choose-recipient.events]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.ui.screens.wallet.utils :as wallet.utils]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon]))
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[status-im.wallet.db :as wallet.db])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
;; common `send/request` functionality
|
||||
|
||||
|
@ -179,19 +183,22 @@
|
|||
;; `/send` command
|
||||
|
||||
(defview send-status [tx-hash outgoing]
|
||||
(letsubs [confirmed? [:chats/transaction-confirmed? tx-hash]
|
||||
tx-exists? [:chats/wallet-transaction-exists? tx-hash]]
|
||||
[react/touchable-highlight {:on-press #(when tx-exists?
|
||||
(letsubs [{:keys [exists? confirmed?]} [:chats/transaction-status tx-hash]]
|
||||
[react/touchable-highlight {:on-press #(when exists?
|
||||
(re-frame/dispatch [:show-transaction-details tx-hash]))}
|
||||
[react/view transactions-styles/command-send-status-container
|
||||
[vector-icons/icon (if confirmed? :tiny-icons/tiny-check :tiny-icons/tiny-pending)
|
||||
{:color (if outgoing colors/blue-light colors/blue)
|
||||
[vector-icons/icon (if confirmed?
|
||||
:tiny-icons/tiny-check
|
||||
:tiny-icons/tiny-pending)
|
||||
{:color (if outgoing
|
||||
colors/blue-light
|
||||
colors/blue)
|
||||
:container-style (transactions-styles/command-send-status-icon outgoing)}]
|
||||
[react/view
|
||||
[react/text {:style (transactions-styles/command-send-status-text outgoing)}
|
||||
(i18n/label (cond
|
||||
confirmed? :status-confirmed
|
||||
tx-exists? :status-pending
|
||||
exists? :status-pending
|
||||
:else :status-tx-not-found))]]]]))
|
||||
|
||||
(defn transaction-status [{:keys [tx-hash outgoing]}]
|
||||
|
|
|
@ -30,13 +30,6 @@
|
|||
|
||||
(def system "system")
|
||||
|
||||
(def default-wallet-transactions
|
||||
{:filters
|
||||
{:type [{:id :inbound :label (i18n/label :t/incoming) :checked? true}
|
||||
{:id :outbound :label (i18n/label :t/outgoing) :checked? true}
|
||||
{:id :pending :label (i18n/label :t/pending) :checked? true}
|
||||
{:id :failed :label (i18n/label :t/failed) :checked? true}]}})
|
||||
|
||||
(def mainnet-networks
|
||||
{"mainnet" {:id "mainnet",
|
||||
:name "Mainnet",
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.logging.core :as logging]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[status-im.web3.core :as web3]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.wallet.custom-tokens.core :as custom-tokens]))
|
||||
|
@ -2144,3 +2145,20 @@
|
|||
:ethereum.transactions/new
|
||||
(fn [cofx [_ transaction]]
|
||||
(ethereum.transactions/new cofx transaction)))
|
||||
|
||||
;; wallet events
|
||||
(handlers/register-handler-fx
|
||||
:wallet.transactions/add-filter
|
||||
(fn [{:keys [db]} [_ id]]
|
||||
{:db (update-in db [:wallet :filters] conj id)}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.transactions/remove-filter
|
||||
(fn [{:keys [db]} [_ id]]
|
||||
{:db (update-in db [:wallet :filters] disj id)}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.transactions/add-all-filters
|
||||
(fn [{:keys [db]} _]
|
||||
{:db (assoc-in db [:wallet :filters]
|
||||
wallet.db/default-wallet-filters)}))
|
||||
|
|
|
@ -39,7 +39,8 @@
|
|||
status-im.ui.screens.hardwallet.connect.subs
|
||||
status-im.ui.screens.hardwallet.settings.subs
|
||||
status-im.ui.screens.hardwallet.pin.subs
|
||||
status-im.ui.screens.hardwallet.setup.subs))
|
||||
status-im.ui.screens.hardwallet.setup.subs
|
||||
[status-im.wallet.db :as wallet.db]))
|
||||
|
||||
;; TOP LEVEL ===========================================================================================================
|
||||
|
||||
|
@ -690,18 +691,16 @@
|
|||
(filter-contacts selected-contacts active-contacts)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/transaction-confirmed?
|
||||
:<- [:wallet-transactions]
|
||||
(fn [txs [_ tx-hash]]
|
||||
(-> (get-in txs [tx-hash :confirmations] "0")
|
||||
(js/parseInt)
|
||||
(>= transactions/confirmations-count-threshold))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/wallet-transaction-exists?
|
||||
:<- [:wallet-transactions]
|
||||
(fn [txs [_ tx-hash]]
|
||||
(not (nil? (get txs tx-hash)))))
|
||||
:chats/transaction-status
|
||||
:<- [:wallet/transactions]
|
||||
:<- [:ethereum/current-block]
|
||||
(fn [[transactions current-block] [_ hash]]
|
||||
(when-let [transaction (get transactions hash)]
|
||||
{:exists? true
|
||||
:confirmed?
|
||||
(-> transaction
|
||||
(wallet.db/get-confirmations current-block)
|
||||
(>= transactions/confirmations-count-threshold))})))
|
||||
|
||||
;;BOOTNODES ============================================================================================================
|
||||
|
||||
|
@ -1026,87 +1025,133 @@
|
|||
;;WALLET TRANSACTIONS ==================================================================================================
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet-transactions
|
||||
:wallet/transactions
|
||||
:<- [:wallet]
|
||||
(fn [wallet]
|
||||
(get wallet :transactions)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/filters
|
||||
:<- [:wallet.transactions]
|
||||
(fn [txs]
|
||||
(get txs :filters)))
|
||||
:wallet/filters
|
||||
:<- [:wallet]
|
||||
(fn [wallet]
|
||||
(get wallet :filters)))
|
||||
|
||||
(defn enrich-transaction
|
||||
[{:keys [type to from timestamp] :as transaction} contacts]
|
||||
(let [[contact-address key-contact key-wallet] (if (= type :inbound)
|
||||
[from :from-contact :to-wallet]
|
||||
[to :to-contact :from-wallet])
|
||||
[{:keys [type to from value token] :as transaction}
|
||||
contacts native-currency]
|
||||
(let [[contact-address key-contact key-wallet]
|
||||
(if (= type :inbound)
|
||||
[from :from-contact :to-wallet]
|
||||
[to :to-contact :from-wallet])
|
||||
wallet (i18n/label :main-wallet)
|
||||
contact (get contacts (utils.hex/normalize-hex contact-address))]
|
||||
contact (get contacts contact-address)
|
||||
{:keys [symbol-display symbol decimals] :as asset}
|
||||
(or token native-currency)
|
||||
amount-text (if value
|
||||
(wallet.utils/format-amount value decimals)
|
||||
"...")
|
||||
currency-text (when asset
|
||||
(clojure.core/name (or symbol-display symbol)))]
|
||||
(cond-> transaction
|
||||
contact (assoc key-contact (:name contact))
|
||||
:always (assoc key-wallet wallet
|
||||
:time-formatted (datetime/timestamp->time timestamp)))))
|
||||
:amount-text amount-text
|
||||
:currency-text currency-text))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/transactions
|
||||
:<- [:wallet]
|
||||
:<- [:wallet/transactions]
|
||||
:<- [:contacts/contacts-by-address]
|
||||
(fn [[wallet contacts]]
|
||||
(reduce (fn [acc [hash transaction]]
|
||||
(assoc acc hash (enrich-transaction transaction contacts)))
|
||||
{}
|
||||
(:transactions wallet))))
|
||||
:<- [:ethereum/native-currency]
|
||||
(fn [[transactions contacts native-currency]]
|
||||
(reduce-kv (fn [acc hash transaction]
|
||||
(assoc acc
|
||||
hash
|
||||
(enrich-transaction transaction contacts native-currency)))
|
||||
{}
|
||||
transactions)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/grouped-transactions
|
||||
:<- [:wallet.transactions/transactions]
|
||||
(fn [transactions]
|
||||
(group-by :type (vals transactions))))
|
||||
:wallet.transactions/all-filters?
|
||||
:<- [:wallet/filters]
|
||||
(fn [filters]
|
||||
(= wallet.db/default-wallet-filters
|
||||
filters)))
|
||||
|
||||
(def filters-labels
|
||||
{:inbound (i18n/label :t/incoming)
|
||||
:outbound (i18n/label :t/outgoing)
|
||||
:pending (i18n/label :t/pending)
|
||||
:failed (i18n/label :t/failed)})
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/pending-transactions-list
|
||||
:<- [:wallet.transactions/grouped-transactions]
|
||||
(fn [{:keys [pending]}]
|
||||
(when pending
|
||||
{:title "Pending"
|
||||
:key :pending
|
||||
:data pending})))
|
||||
:wallet.transactions/filters
|
||||
:<- [:wallet/filters]
|
||||
(fn [filters]
|
||||
(map (fn [id]
|
||||
(let [checked? (filters id)]
|
||||
{:id id
|
||||
:label (filters-labels id)
|
||||
:checked? checked?
|
||||
:on-touch #(if checked?
|
||||
(re-frame/dispatch [:wallet.transactions/remove-filter id])
|
||||
(re-frame/dispatch [:wallet.transactions/add-filter id]))}))
|
||||
wallet.db/default-wallet-filters)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/failed-transactions-list
|
||||
:<- [:wallet.transactions/grouped-transactions]
|
||||
(fn [{:keys [failed]}]
|
||||
(when failed
|
||||
{:title "Failed"
|
||||
:key :failed
|
||||
:data failed})))
|
||||
:wallet.transactions.filters/screen
|
||||
:<- [:wallet.transactions/filters]
|
||||
:<- [:wallet.transactions/all-filters?]
|
||||
(fn [[filters all-filters?]]
|
||||
{:all-filters? all-filters?
|
||||
:filters filters
|
||||
:on-touch-select-all (when-not all-filters?
|
||||
#(re-frame/dispatch
|
||||
[:wallet.transactions/add-all-filters]))}))
|
||||
|
||||
(defn group-transactions-by-date [transactions]
|
||||
(defn- enrich-transaction-for-list
|
||||
[filters
|
||||
{:keys [type from-contact from to-contact to hash timestamp] :as transaction}]
|
||||
(when (filters type)
|
||||
(assoc (case type
|
||||
:inbound
|
||||
(assoc transaction
|
||||
:label (i18n/label :t/from)
|
||||
:contact-accessibility-label :sender-text
|
||||
:address-accessibility-label :sender-address-text
|
||||
:contact from-contact
|
||||
:address from)
|
||||
(assoc transaction
|
||||
:label (i18n/label :t/to)
|
||||
:contact-accessibility-label :recipient-name-text
|
||||
:address-accessibility-label :recipient-address-text
|
||||
:contact to-contact
|
||||
:address to))
|
||||
:time-formatted (datetime/timestamp->time timestamp)
|
||||
:on-touch-fn #(re-frame/dispatch [:show-transaction-details hash]))))
|
||||
|
||||
(defn- group-transactions-by-date
|
||||
[transactions]
|
||||
(->> transactions
|
||||
(group-by #(datetime/timestamp->date-key (:timestamp %)))
|
||||
(sort-by key)
|
||||
reverse
|
||||
(sort-by key >)
|
||||
(map (fn [[date-key transactions]]
|
||||
{:title (datetime/timestamp->mini-date (:timestamp (first transactions)))
|
||||
:key date-key
|
||||
:data (sort-by :timestamp > transactions)}))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/completed-transactions-list
|
||||
:<- [:wallet.transactions/grouped-transactions]
|
||||
(fn [{:keys [inbound outbound failed]}]
|
||||
(group-transactions-by-date (concat inbound outbound failed))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/transactions-history-list
|
||||
:<- [:wallet.transactions/pending-transactions-list]
|
||||
:<- [:wallet.transactions/completed-transactions-list]
|
||||
(fn [[pending completed]]
|
||||
(cond-> []
|
||||
pending (into pending)
|
||||
completed (into completed))))
|
||||
:wallet.transactions.history/screen
|
||||
:<- [:wallet.transactions/transactions]
|
||||
:<- [:wallet/filters]
|
||||
:<- [:wallet.transactions/all-filters?]
|
||||
(fn [[transactions filters all-filters?]]
|
||||
{:all-filters? all-filters?
|
||||
:transaction-history-sections
|
||||
(->> transactions
|
||||
vals
|
||||
(keep #(enrich-transaction-for-list filters %))
|
||||
(group-transactions-by-date))}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions/current-transaction
|
||||
|
@ -1123,55 +1168,45 @@
|
|||
(fn [[transactions current-transaction native-currency chain-keyword]]
|
||||
(let [{:keys [gas-used gas-price hash timestamp type token value]
|
||||
:as transaction}
|
||||
(get transactions current-transaction)]
|
||||
(get transactions current-transaction)
|
||||
native-currency-text (-> native-currency
|
||||
:symbol-display
|
||||
name)]
|
||||
(when transaction
|
||||
(let [{:keys [symbol-display symbol decimals] :as asset}
|
||||
(or token native-currency)
|
||||
amount-text (if value
|
||||
(wallet.utils/format-amount value decimals)
|
||||
"...")
|
||||
currency-text (when asset
|
||||
(clojure.core/name (or symbol-display symbol)))
|
||||
native-currency-text (-> native-currency
|
||||
:symbol-display
|
||||
name)]
|
||||
(merge transaction
|
||||
{:amount-text amount-text
|
||||
:currency-text currency-text
|
||||
:gas-price-eth (if gas-price
|
||||
(money/wei->str :eth
|
||||
gas-price
|
||||
native-currency-text)
|
||||
"-")
|
||||
:gas-price-gwei (if gas-price
|
||||
(money/wei->str :gwei
|
||||
gas-price)
|
||||
"-")
|
||||
:date (datetime/timestamp->long-date timestamp)}
|
||||
(if (= type :unsigned)
|
||||
{:block (i18n/label :not-applicable)
|
||||
:cost (i18n/label :not-applicable)
|
||||
:gas-limit (i18n/label :not-applicable)
|
||||
:gas-used (i18n/label :not-applicable)
|
||||
:nonce (i18n/label :not-applicable)
|
||||
:hash (i18n/label :not-applicable)}
|
||||
{:cost (when gas-used
|
||||
(money/wei->str :eth
|
||||
(money/fee-value gas-used gas-price)
|
||||
native-currency-text))
|
||||
:url (transactions.etherscan/get-transaction-details-url
|
||||
chain-keyword
|
||||
hash)})))))))
|
||||
(merge transaction
|
||||
{:gas-price-eth (if gas-price
|
||||
(money/wei->str :eth
|
||||
gas-price
|
||||
native-currency-text)
|
||||
"-")
|
||||
:gas-price-gwei (if gas-price
|
||||
(money/wei->str :gwei
|
||||
gas-price)
|
||||
"-")
|
||||
:date (datetime/timestamp->long-date timestamp)}
|
||||
(if (= type :unsigned)
|
||||
{:block (i18n/label :not-applicable)
|
||||
:cost (i18n/label :not-applicable)
|
||||
:gas-limit (i18n/label :not-applicable)
|
||||
:gas-used (i18n/label :not-applicable)
|
||||
:nonce (i18n/label :not-applicable)
|
||||
:hash (i18n/label :not-applicable)}
|
||||
{:cost (when gas-used
|
||||
(money/wei->str :eth
|
||||
(money/fee-value gas-used gas-price)
|
||||
native-currency-text))
|
||||
:url (transactions.etherscan/get-transaction-details-url
|
||||
chain-keyword
|
||||
hash)}))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions.details/screen
|
||||
:<- [:wallet.transactions.details/current-transaction]
|
||||
:<- [:ethereum/current-block]
|
||||
(fn [[{:keys [block] :as transaction} current-block]]
|
||||
(fn [[transaction current-block]]
|
||||
:wallet.transactions.details/current-transaction
|
||||
(let [confirmations (if (and current-block block)
|
||||
(inc (- current-block block))
|
||||
0)]
|
||||
(let [confirmations (wallet.db/get-confirmations transaction
|
||||
current-block)]
|
||||
(assoc transaction
|
||||
:confirmations confirmations
|
||||
:confirmations-progress
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
status-im.browser.db
|
||||
status-im.ui.screens.add-new.db
|
||||
status-im.ui.screens.add-new.new-public-chat.db
|
||||
status-im.ui.components.bottom-sheet.core))
|
||||
status-im.ui.components.bottom-sheet.core
|
||||
[status-im.wallet.db :as wallet.db]))
|
||||
|
||||
;; initial state of app-db
|
||||
(def app-db {:keyboard-height 0
|
||||
|
@ -32,7 +33,7 @@
|
|||
:selected-participants #{}
|
||||
:sync-state :done
|
||||
:app-state "active"
|
||||
:wallet.transactions constants/default-wallet-transactions
|
||||
:wallet wallet.db/default-wallet
|
||||
:wallet/all-tokens {}
|
||||
:prices {}
|
||||
:peers-count 0
|
||||
|
@ -329,7 +330,6 @@
|
|||
:chat/id->command
|
||||
:chat/access-scope->command-id
|
||||
:wallet/wallet
|
||||
:wallet/wallet.transactions
|
||||
:prices/prices
|
||||
:prices/prices-loading?
|
||||
:notifications/notifications
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
status-im.ui.screens.wallet.send.events
|
||||
status-im.ui.screens.wallet.request.events
|
||||
status-im.ui.screens.wallet.settings.events
|
||||
status-im.ui.screens.wallet.transactions.events
|
||||
status-im.ui.screens.wallet.choose-recipient.events
|
||||
status-im.ui.screens.wallet.collectibles.cryptokitties.events
|
||||
status-im.ui.screens.wallet.collectibles.cryptostrikers.events
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
(ns status-im.ui.screens.wallet.request.events
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.screens.wallet.db :as wallet-db]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
(:require [status-im.chat.commands.sending :as commands-sending]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.chat.commands.sending :as commands-sending]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.money :as money]))
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.wallet.db :as wallet.db]))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet-send-request
|
||||
|
@ -23,7 +21,7 @@
|
|||
(handlers/register-handler-fx
|
||||
:wallet.request/set-and-validate-amount
|
||||
(fn [{:keys [db]} [_ amount symbol decimals]]
|
||||
(let [{:keys [value error]} (wallet-db/parse-amount amount decimals)]
|
||||
(let [{:keys [value error]} (wallet.db/parse-amount amount decimals)]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :request-transaction :amount] (money/formatted->internal value symbol decimals))
|
||||
(assoc-in [:wallet :request-transaction :amount-text] amount)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
[status-im.native-module.core :as status]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.ui.screens.wallet.db :as wallet.db]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[status-im.utils.ethereum.core :as ethereum]
|
||||
[status-im.utils.ethereum.erc20 :as erc20]
|
||||
[status-im.utils.ethereum.tokens :as tokens]
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
(ns status-im.ui.screens.wallet.transactions.events
|
||||
(:require [status-im.utils.handlers :as handlers]))
|
||||
|
||||
(defn- mark-all-checked [filters]
|
||||
(update filters
|
||||
:type
|
||||
#(map (fn [m]
|
||||
(assoc m :checked? true))
|
||||
%)))
|
||||
|
||||
(defn- mark-checked [filters {:keys [type]} checked?]
|
||||
(update filters
|
||||
:type
|
||||
#(map (fn [{:keys [id] :as m}]
|
||||
(if (= type id)
|
||||
(assoc m :checked? checked?)
|
||||
m))
|
||||
%)))
|
||||
|
||||
(defn- update-filters [db f]
|
||||
(update-in db [:wallet.transactions :filters] f))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.transactions/filter
|
||||
(fn [{:keys [db]} [_ path checked?]]
|
||||
{:db (update-filters db #(mark-checked % path checked?))}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.transactions/filter-all
|
||||
(fn [{:keys [db]} _]
|
||||
{:db (update-filters db mark-all-checked)}))
|
|
@ -15,154 +15,149 @@
|
|||
[status-im.utils.money :as money])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn history-action [filter?]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TRANSACTION HISTORY
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn history-action
|
||||
[all-filters?]
|
||||
(cond->
|
||||
{:icon :main-icons/filter
|
||||
:icon-opts {:accessibility-label :filters-button}
|
||||
:handler #(re-frame/dispatch [:navigate-to :wallet-transactions-filter])}
|
||||
filter? (assoc-in [:icon-opts :overlay-style] styles/corner-dot)))
|
||||
(not all-filters?) (assoc-in [:icon-opts :overlay-style] styles/corner-dot)))
|
||||
|
||||
(defn- all-checked? [filter-data]
|
||||
(and (every? :checked? (:type filter-data))
|
||||
(every? :checked? (:tokens filter-data))))
|
||||
|
||||
(defn- toolbar-view [filter-data]
|
||||
(defn- toolbar-view
|
||||
[all-filters?]
|
||||
[toolbar/toolbar nil
|
||||
toolbar/default-nav-back
|
||||
[toolbar/content-title (i18n/label :t/transactions-history)]
|
||||
[toolbar/actions
|
||||
[(history-action (not (all-checked? filter-data)))]]])
|
||||
[(history-action all-filters?)]]])
|
||||
|
||||
(defn- inbound? [type] (= :inbound type))
|
||||
(defn- failed? [type] (= :failed type))
|
||||
|
||||
(defn- transaction-icon [k background-color color]
|
||||
{:icon k
|
||||
(defn- transaction-icon
|
||||
[icon-key background-color color]
|
||||
{:icon icon-key
|
||||
:icon-opts {:color color}
|
||||
:style (styles/transaction-icon-background background-color)})
|
||||
|
||||
(defn- transaction-type->icon [k]
|
||||
(defn- transaction-type->icon
|
||||
[k]
|
||||
(case k
|
||||
:inbound (transaction-icon :main-icons/arrow-left (colors/alpha colors/green 0.2) colors/green)
|
||||
:outbound (transaction-icon :main-icons/arrow-right (colors/alpha colors/blue 0.1) colors/blue)
|
||||
:failed (transaction-icon :main-icons/warning colors/gray-light colors/red)
|
||||
(:postponed :pending) (transaction-icon :main-icons/arrow-right colors/gray-light colors/gray)
|
||||
:inbound (transaction-icon :main-icons/arrow-left
|
||||
(colors/alpha colors/green 0.2)
|
||||
colors/green)
|
||||
:outbound (transaction-icon :main-icons/arrow-right
|
||||
(colors/alpha colors/blue 0.1)
|
||||
colors/blue)
|
||||
:failed (transaction-icon :main-icons/warning
|
||||
colors/gray-light
|
||||
colors/red)
|
||||
:pending (transaction-icon :main-icons/arrow-right
|
||||
colors/gray-light colors/gray)
|
||||
(throw (str "Unknown transaction type: " k))))
|
||||
|
||||
(defn render-transaction
|
||||
[{:keys [hash from-contact to-contact to from type value time-formatted symbol]}
|
||||
network all-tokens hide-details?]
|
||||
(let [[label contact address contact-accessibility-label
|
||||
address-accessibility-label]
|
||||
(if (inbound? type)
|
||||
[(i18n/label :t/from) from-contact from :sender-text :sender-address-text]
|
||||
[(i18n/label :t/to) to-contact to :recipient-name-text :recipient-address-text])
|
||||
{:keys [decimals] :as token}
|
||||
(tokens/asset-for all-tokens
|
||||
(ethereum/network->chain-keyword network)
|
||||
symbol)]
|
||||
[list/touchable-item #(when-not hide-details? (re-frame/dispatch [:show-transaction-details hash]))
|
||||
[react/view {:accessibility-label :transaction-item}
|
||||
[list/item
|
||||
(when type
|
||||
[list/item-icon (transaction-type->icon (keyword type))])
|
||||
[list/item-content
|
||||
[react/view {:style styles/amount-time}
|
||||
[react/nested-text {:style styles/tx-amount
|
||||
:ellipsize-mode "tail"
|
||||
:number-of-lines 1}
|
||||
[{:accessibility-label :amount-text}
|
||||
(-> value (money/internal->formatted symbol decimals) money/to-fixed str)]
|
||||
" "
|
||||
[{:accessibility-label :currency-text}
|
||||
(wallet.utils/display-symbol token)]]
|
||||
[react/text {:style styles/tx-time}
|
||||
time-formatted]]
|
||||
[react/view {:style styles/address-row}
|
||||
[react/text {:style styles/address-label}
|
||||
label]
|
||||
(when contact
|
||||
[react/text {:style styles/address-contact
|
||||
:accessibility-label contact-accessibility-label}
|
||||
contact])
|
||||
[react/text {:style styles/address-hash
|
||||
:ellipsize-mode "middle"
|
||||
:number-of-lines 1
|
||||
:accessibility-label address-accessibility-label}
|
||||
address]]]
|
||||
(when-not hide-details?
|
||||
[list/item-icon {:icon :main-icons/next
|
||||
:style {:margin-top 10}
|
||||
:icon-opts (merge styles/forward
|
||||
{:accessibility-label :show-transaction-button})}])]]]))
|
||||
[{:keys [label contact address contact-accessibility-label
|
||||
address-accessibility-label currency-text amount-text
|
||||
time-formatted on-touch-fn type]}]
|
||||
[list/touchable-item on-touch-fn
|
||||
[react/view {:accessibility-label :transaction-item}
|
||||
[list/item
|
||||
(when type
|
||||
[list/item-icon (transaction-type->icon (keyword type))])
|
||||
[list/item-content
|
||||
[react/view {:style styles/amount-time}
|
||||
[react/nested-text {:style styles/tx-amount
|
||||
:ellipsize-mode "tail"
|
||||
:number-of-lines 1}
|
||||
[{:accessibility-label :amount-text}
|
||||
amount-text]
|
||||
" "
|
||||
[{:accessibility-label :currency-text}
|
||||
currency-text]]
|
||||
[react/text {:style styles/tx-time}
|
||||
time-formatted]]
|
||||
[react/view {:style styles/address-row}
|
||||
[react/text {:style styles/address-label}
|
||||
label]
|
||||
(when contact
|
||||
[react/text {:style styles/address-contact
|
||||
:accessibility-label contact-accessibility-label}
|
||||
contact])
|
||||
[react/text {:style styles/address-hash
|
||||
:ellipsize-mode "middle"
|
||||
:number-of-lines 1
|
||||
:accessibility-label address-accessibility-label}
|
||||
address]]]
|
||||
[list/item-icon {:icon :main-icons/next
|
||||
:style {:margin-top 10}
|
||||
:icon-opts (merge styles/forward
|
||||
{:accessibility-label :show-transaction-button})}]]]])
|
||||
|
||||
(defn filtered-transaction? [transaction filter-data]
|
||||
(:checked? (some #(when (= (:type transaction) (:id %)) %) (:type filter-data))))
|
||||
(defn history-list
|
||||
[transactions-history-sections]
|
||||
[react/view components.styles/flex
|
||||
[list/section-list {:sections transactions-history-sections
|
||||
:key-fn :hash
|
||||
:render-fn #(render-transaction %)
|
||||
:empty-component
|
||||
[react/i18n-text {:style styles/empty-text
|
||||
:key :transactions-history-empty}]
|
||||
:refreshing false}]])
|
||||
|
||||
(defn update-transactions [m filter-data]
|
||||
(update m
|
||||
:data
|
||||
(fn [v]
|
||||
(filter #(filtered-transaction? % filter-data) v))))
|
||||
(defview transactions
|
||||
[]
|
||||
(letsubs [{:keys [transaction-history-sections all-filters?]}
|
||||
[:wallet.transactions.history/screen]]
|
||||
[react/view styles/transactions-view
|
||||
[status-bar/status-bar]
|
||||
[toolbar-view all-filters?]
|
||||
[history-list transaction-history-sections]]))
|
||||
|
||||
(defview history-list [& [hide-details?]]
|
||||
(letsubs [transactions-history-list [:wallet.transactions/transactions-history-list]
|
||||
filter-data [:wallet.transactions/filters]
|
||||
network [:account/network]
|
||||
all-tokens [:wallet/all-tokens]]
|
||||
[react/view components.styles/flex
|
||||
[list/section-list {:sections (map #(update-transactions % filter-data) transactions-history-list)
|
||||
:key-fn :hash
|
||||
:render-fn #(render-transaction % network all-tokens hide-details?)
|
||||
:empty-component [react/i18n-text {:style styles/empty-text
|
||||
:key :transactions-history-empty}]
|
||||
:refreshing false}]]))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TRANSACTION FILTERS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Filter history
|
||||
|
||||
(defn- item-filter [{:keys [icon checked? path]} content]
|
||||
(defn- render-item-filter [{:keys [id label checked? on-touch]}]
|
||||
[react/view {:accessibility-label :filter-item}
|
||||
[list/list-item-with-checkbox
|
||||
{:checked? checked?
|
||||
:on-value-change #(re-frame/dispatch [:wallet.transactions/filter path %])}
|
||||
:on-value-change on-touch}
|
||||
[list/item
|
||||
[list/item-icon icon]
|
||||
content]]])
|
||||
|
||||
(defn- render-item-filter [{:keys [id label checked?]}]
|
||||
(when id
|
||||
[item-filter {:icon (transaction-type->icon id) :checked? checked? :path {:type id}}
|
||||
[list/item-icon (transaction-type->icon id)]
|
||||
[list/item-content
|
||||
[list/item-primary-only {:accessibility-label :filter-name-text}
|
||||
label]]]))
|
||||
|
||||
(defn- wrap-filter-data [m]
|
||||
[{:title (i18n/label :t/transactions-filter-type)
|
||||
:key :type
|
||||
:render-fn render-item-filter
|
||||
:data (:type m)}])
|
||||
label]]]]])
|
||||
|
||||
(defview filter-history []
|
||||
(letsubs [filter-data [:wallet.transactions/filters]]
|
||||
(letsubs [{:keys [filters all-filters? on-touch-select-all]}
|
||||
[:wallet.transactions.filters/screen]]
|
||||
[react/view styles/filter-container
|
||||
[status-bar/status-bar {:type :modal-main}]
|
||||
[toolbar/toolbar {}
|
||||
[toolbar/nav-clear-text {:accessibility-label :done-button} (i18n/label :t/done)]
|
||||
[toolbar/content-title (i18n/label :t/transactions-filter-title)]
|
||||
[toolbar/text-action {:handler #(re-frame/dispatch [:wallet.transactions/filter-all])
|
||||
:disabled? (all-checked? filter-data)
|
||||
:accessibility-label :select-all-button}
|
||||
[toolbar/nav-clear-text
|
||||
{:accessibility-label :done-button}
|
||||
(i18n/label :t/done)]
|
||||
[toolbar/content-title
|
||||
(i18n/label :t/transactions-filter-title)]
|
||||
[toolbar/text-action
|
||||
{:handler on-touch-select-all
|
||||
:disabled? all-filters?
|
||||
:accessibility-label :select-all-button}
|
||||
(i18n/label :t/transactions-filter-select-all)]]
|
||||
[react/view {:style (merge {:background-color :white} components.styles/flex)}
|
||||
[list/section-list {:sections (wrap-filter-data filter-data)
|
||||
:key-fn (comp str :id)}]]]))
|
||||
[react/view
|
||||
{:style (merge {:background-color :white} components.styles/flex)}
|
||||
[list/section-list {:sections [{:title
|
||||
(i18n/label :t/transactions-filter-type)
|
||||
:key :type
|
||||
:render-fn render-item-filter
|
||||
:data filters}]
|
||||
:key-fn :id}]]]))
|
||||
|
||||
(defview transactions []
|
||||
(letsubs [filter-data [:wallet.transactions/filters]]
|
||||
[react/view styles/transactions-view
|
||||
[status-bar/status-bar]
|
||||
[toolbar-view filter-data]
|
||||
[history-list]]))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TRANSACTION DETAILS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn details-header
|
||||
[date type amount-text currency-text]
|
||||
|
@ -183,10 +178,10 @@
|
|||
[react/view {:style (styles/progress-bar-todo (- 100 progress) failed?)}]])
|
||||
|
||||
(defn details-confirmations
|
||||
[confirmations confirmations-progress type]
|
||||
[confirmations confirmations-progress failed?]
|
||||
[react/view {:style styles/details-block}
|
||||
[progress-bar confirmations-progress (failed? type)]
|
||||
(if (failed? type)
|
||||
[progress-bar confirmations-progress failed?]
|
||||
(if failed?
|
||||
[react/i18n-text {:style styles/details-failed
|
||||
:key :failed}]
|
||||
[react/text {:style styles/details-confirmations-count}
|
||||
|
@ -259,6 +254,6 @@
|
|||
(when transaction [toolbar/actions (details-action hash url)])]
|
||||
[react/scroll-view {:style components.styles/main-container}
|
||||
[details-header date type amount-text currency-text]
|
||||
[details-confirmations confirmations confirmations-progress type]
|
||||
[details-confirmations confirmations confirmations-progress (= :failed type)]
|
||||
[react/view {:style styles/details-separator}]
|
||||
[details-list transaction]]]))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.ui.screens.wallet.db
|
||||
(ns status-im.wallet.db
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[status-im.i18n :as i18n]
|
||||
status-im.ui.screens.wallet.request.db
|
||||
|
@ -22,6 +22,7 @@
|
|||
(spec/def :wallet/visible-tokens any?)
|
||||
(spec/def :wallet/currency any?)
|
||||
(spec/def :wallet/balance any?)
|
||||
(spec/def :wallet/filters set?)
|
||||
|
||||
(spec/def :wallet/wallet (spec/keys :opt-un [:wallet/send-transaction
|
||||
:wallet/request-transaction
|
||||
|
@ -30,6 +31,7 @@
|
|||
:wallet/errors
|
||||
:wallet/transactions
|
||||
:wallet/edit
|
||||
:wallet/filters
|
||||
:wallet/current-tab
|
||||
:wallet/current-transaction
|
||||
:wallet/modal-history?
|
||||
|
@ -58,3 +60,15 @@
|
|||
|
||||
:else
|
||||
{:value value}))))
|
||||
|
||||
(def default-wallet-filters
|
||||
#{:inbound :outbound :pending :failed})
|
||||
|
||||
(def default-wallet
|
||||
{:filters default-wallet-filters})
|
||||
|
||||
(defn get-confirmations
|
||||
[{:keys [block]} current-block]
|
||||
(if (and current-block block)
|
||||
(inc (- current-block block))
|
||||
0))
|
|
@ -12,7 +12,6 @@
|
|||
[status-im.test.wallet.subs]
|
||||
[status-im.test.wallet.transactions]
|
||||
[status-im.test.wallet.transactions.subs]
|
||||
[status-im.test.wallet.transactions.views]
|
||||
[status-im.test.mailserver.core]
|
||||
[status-im.test.fleet.core]
|
||||
[status-im.test.group-chats.core]
|
||||
|
@ -99,7 +98,6 @@
|
|||
'status-im.test.wallet.subs
|
||||
'status-im.test.wallet.transactions
|
||||
'status-im.test.wallet.transactions.subs
|
||||
'status-im.test.wallet.transactions.views
|
||||
'status-im.test.chat.models.loading
|
||||
'status-im.test.chat.models.input
|
||||
'status-im.test.chat.models.message
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(ns status-im.test.ui.screens.wallet.db
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.ui.screens.wallet.db :as wallet.db]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.i18n :as i18n]))
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
(ns status-im.test.wallet.transactions.views
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[status-im.ui.screens.wallet.transactions.views :as views]))
|
||||
|
||||
(deftest filtered-transaction?
|
||||
(is (not (true? (views/filtered-transaction? {:type :inbound} {:type [{:id :outbound :checked? true}]}))))
|
||||
(is (not (true? (views/filtered-transaction? {:type :inbound} {:type [{:id :inbound :checked? false}]}))))
|
||||
(is (true? (views/filtered-transaction? {:type :inbound} {:type [{:id :inbound :checked? true}]})))
|
||||
(is (true? (views/filtered-transaction? {:type :inbound} {:type [{:id :outbound :checked? true} {:id :inbound :checked? true}]}))))
|
||||
|
||||
(deftest update-transactions
|
||||
(is (= {:data '()} (views/update-transactions {:data {:type :inbound}} {:type [{:id :outbound :checked? true}]}))))
|
Loading…
Reference in New Issue