add transaction details screen

This commit is contained in:
Eric Dvorsak 2017-09-12 04:03:59 +02:00 committed by Roman Volosovskyi
parent 1b0409fdc9
commit 5e31fcdacc
11 changed files with 329 additions and 85 deletions

View File

@ -2,7 +2,7 @@
(def translations (def translations
{ {
;common ;;common
:members-title "Members" :members-title "Members"
:not-implemented "!not implemented" :not-implemented "!not implemented"
:chat-name "Chat name" :chat-name "Chat name"
@ -20,7 +20,7 @@
:camera-access-error "To grant the required camera permission, please, go to your system settings and make sure that Status > Camera is selected." :camera-access-error "To grant the required camera permission, please, go to your system settings and make sure that Status > Camera is selected."
:photos-access-error "To grant the required photos permission, please, go to your system settings and make sure that Status > Photos is selected." :photos-access-error "To grant the required photos permission, please, go to your system settings and make sure that Status > Photos is selected."
;drawer ;;drawer
:invite-friends "Invite friends" :invite-friends "Invite friends"
:faq "FAQ" :faq "FAQ"
:switch-users "Switch users" :switch-users "Switch users"
@ -28,7 +28,7 @@
:view-all "View all" :view-all "View all"
:current-network "Current network" :current-network "Current network"
;chat ;;chat
:is-typing "is typing" :is-typing "is typing"
:and-you "and you" :and-you "and you"
:search-chat "Search chat" :search-chat "Search chat"
@ -48,11 +48,11 @@
:faucet-success "Faucet request has been received" :faucet-success "Faucet request has been received"
:faucet-error "Faucet request error" :faucet-error "Faucet request error"
;sync ;;sync
:sync-in-progress "Syncing..." :sync-in-progress "Syncing..."
:sync-synced "In sync" :sync-synced "In sync"
;messages ;;messages
:status-sending "Sending" :status-sending "Sending"
:status-pending "Pending" :status-pending "Pending"
:status-sent "Sent" :status-sent "Sent"
@ -61,7 +61,7 @@
:status-delivered "Delivered" :status-delivered "Delivered"
:status-failed "Failed" :status-failed "Failed"
;datetime ;;datetime
:datetime-ago-format "{{number}} {{time-intervals}} {{ago}}" :datetime-ago-format "{{number}} {{time-intervals}} {{ago}}"
:datetime-second {:one "second" :datetime-second {:one "second"
:other "seconds"} :other "seconds"}
@ -76,7 +76,7 @@
:datetime-yesterday "yesterday" :datetime-yesterday "yesterday"
:datetime-today "today" :datetime-today "today"
;profile ;;profile
:profile "Profile" :profile "Profile"
:edit-profile "Edit profile" :edit-profile "Edit profile"
:report-user "REPORT USER" :report-user "REPORT USER"
@ -116,7 +116,7 @@
:browsing-open-in-web-browser "Open in web browser" :browsing-open-in-web-browser "Open in web browser"
:browsing-cancel "Cancel" :browsing-cancel "Cancel"
;sign-up ;;sign-up
:contacts-syncronized "Your contacts have been synchronized" :contacts-syncronized "Your contacts have been synchronized"
:confirmation-code (str "Thanks! We've sent you a text message with a confirmation " :confirmation-code (str "Thanks! We've sent you a text message with a confirmation "
"code. Please provide that code to confirm your phone number") "code. Please provide that code to confirm your phone number")
@ -135,13 +135,13 @@
:move-to-internal-failure-message "We need to move some important files from external to internal storage. To do this, we need your permission. We won't be using external storage in future versions." :move-to-internal-failure-message "We need to move some important files from external to internal storage. To do this, we need your permission. We won't be using external storage in future versions."
:debug-enabled "Debug server has been launched! You can now execute *status-dev-cli scan* to find the server from your computer on the same network." :debug-enabled "Debug server has been launched! You can now execute *status-dev-cli scan* to find the server from your computer on the same network."
;phone types ;;phone types
:phone-e164 "International 1" :phone-e164 "International 1"
:phone-international "International 2" :phone-international "International 2"
:phone-national "National" :phone-national "National"
:phone-significant "Significant" :phone-significant "Significant"
;chats ;;chats
:chats "Chats" :chats "Chats"
:new-chat "New chat" :new-chat "New chat"
:delete-chat "Delete chat" :delete-chat "Delete chat"
@ -153,7 +153,7 @@
:topic-format "Wrong format [a-z0-9\\-]+" :topic-format "Wrong format [a-z0-9\\-]+"
:public-group-topic "Topic" :public-group-topic "Topic"
;discover ;;discover
:discover "Discover" :discover "Discover"
:none "None" :none "None"
:search-tags "Type your search tags here" :search-tags "Type your search tags here"
@ -162,10 +162,10 @@
:no-statuses-discovered "No statuses discovered" :no-statuses-discovered "No statuses discovered"
:no-statuses-found "No statuses found" :no-statuses-found "No statuses found"
;settings ;;settings
:settings "Settings" :settings "Settings"
;contacts ;;contacts
:contacts "Contacts" :contacts "Contacts"
:new-contact "New contact" :new-contact "New contact"
:delete-contact "Delete contact" :delete-contact "Delete contact"
@ -183,7 +183,7 @@
:enter-address "Enter address" :enter-address "Enter address"
:more "more" :more "more"
;group-settings ;;group-settings
:remove "Remove" :remove "Remove"
:save "Save" :save "Save"
:delete "Delete" :delete "Delete"
@ -200,7 +200,7 @@
:green "Green" :green "Green"
:red "Red" :red "Red"
;commands ;;commands
:money-command-description "Send money" :money-command-description "Send money"
:location-command-description "Send location" :location-command-description "Send location"
:phone-command-description "Send phone number" :phone-command-description "Send phone number"
@ -216,7 +216,7 @@
:chat-send-eth-to "{{amount}} ETH to {{chat-name}}" :chat-send-eth-to "{{amount}} ETH to {{chat-name}}"
:chat-send-eth-from "{{amount}} ETH from {{chat-name}}" :chat-send-eth-from "{{amount}} ETH from {{chat-name}}"
;location command ;;location command
:your-current-location "Your current location" :your-current-location "Your current location"
:places-nearby "Places nearby" :places-nearby "Places nearby"
:search-results "Search results" :search-results "Search results"
@ -226,7 +226,7 @@
:sharing-copy-to-clipboard-address "Copy the Address" :sharing-copy-to-clipboard-address "Copy the Address"
:sharing-copy-to-clipboard-coordinates "Copy coordinates" :sharing-copy-to-clipboard-coordinates "Copy coordinates"
;new-group ;;new-group
:group-chat-name "Chat name" :group-chat-name "Chat name"
:empty-group-chat-name "Please enter a name" :empty-group-chat-name "Please enter a name"
:illegal-group-chat-name "Please select another name" :illegal-group-chat-name "Please select another name"
@ -241,11 +241,11 @@
:contact-s {:one "contact" :contact-s {:one "contact"
:other "contacts"} :other "contacts"}
;participants ;;participants
:add-participants "Add Participants" :add-participants "Add Participants"
:remove-participants "Remove Participants" :remove-participants "Remove Participants"
;protocol ;;protocol
:received-invitation "received chat invitation" :received-invitation "received chat invitation"
:removed-from-chat "removed you from group chat" :removed-from-chat "removed you from group chat"
:left "left" :left "left"
@ -253,7 +253,7 @@
:removed "removed" :removed "removed"
:You "You" :You "You"
;new-contact ;;new-contact
:add-new-contact "Add new contact" :add-new-contact "Add new contact"
:import-qr "Import" :import-qr "Import"
:scan-qr "Scan QR" :scan-qr "Scan QR"
@ -267,7 +267,7 @@
:can-not-add-yourself "You can't add yourself" :can-not-add-yourself "You can't add yourself"
:unknown-address "Unknown address" :unknown-address "Unknown address"
;login ;;login
:connect "Connect" :connect "Connect"
:address "Address" :address "Address"
:password "Password" :password "Password"
@ -276,7 +276,7 @@
:sign-in "Sign in" :sign-in "Sign in"
:wrong-password "Wrong password" :wrong-password "Wrong password"
;recover ;;recover
:recover-from-passphrase "Recover from passphrase" :recover-from-passphrase "Recover from passphrase"
:recover-explain "Please enter the passphrase for your password to recover access" :recover-explain "Please enter the passphrase for your password to recover access"
:passphrase "Passphrase" :passphrase "Passphrase"
@ -285,21 +285,21 @@
:enter-valid-password "Please enter a password" :enter-valid-password "Please enter a password"
:twelve-words-in-correct-order "12 words in correct order" :twelve-words-in-correct-order "12 words in correct order"
;accounts ;;accounts
:recover-access "Recover access" :recover-access "Recover access"
:add-account "Add account" :add-account "Add account"
:create-new-account "Create new account" :create-new-account "Create new account"
;wallet-qr-code ;;wallet-qr-code
:done "Done" :done "Done"
;validation ;;validation
:invalid-phone "Invalid phone number" :invalid-phone "Invalid phone number"
:amount "Amount" :amount "Amount"
:not-enough-eth (str "Not enough ETH on balance " :not-enough-eth (str "Not enough ETH on balance "
"({{balance}} ETH)") "({{balance}} ETH)")
;transactions ;;transactions
:confirm "Confirm" :confirm "Confirm"
:confirm-transactions {:one "Confirm transaction" :confirm-transactions {:one "Confirm transaction"
:other "Confirm {{count}} transactions" :other "Confirm {{count}} transactions"
@ -324,8 +324,19 @@
:data "Data" :data "Data"
:got-it "Got it" :got-it "Got it"
:contract-creation "Contract Creation" :contract-creation "Contract Creation"
:block "Block"
:hash "Hash"
:gas-limit "Gas limit"
:gas-price "Gas price"
:gas-used "Gas Used"
:cost-fee "Cost/Fee"
:nonce "Nonce"
:confirmations "confirmations"
:confirmations-helper-text "If you want to be sure your transaction will not be compromise wait until it gets at least 10 blocks confirmations"
:copy-transaction-hash "Copy transaction hash"
:open-on-etherscan "Open on Etherscan"
;:webview ;;webview
:web-view-error "oops, error" :web-view-error "oops, error"
;;testfairy warning ;;testfairy warning
@ -350,6 +361,7 @@
:share "Share" :share "Share"
:currency "Currency" :currency "Currency"
:transactions "Transactions" :transactions "Transactions"
:transaction-details "Transaction details"
:transactions-sign "Sign" :transactions-sign "Sign"
:transactions-sign-all "Sign all" :transactions-sign-all "Sign all"
:transactions-sign-all-text "Sign the transaction by entering your password.\nMake sure that the words above match your secret signing phrase" :transactions-sign-all-text "Sign the transaction by entering your password.\nMake sure that the words above match your secret signing phrase"

View File

@ -42,3 +42,7 @@
(or search-mode? (or search-mode?
(and (= view-id :chat-list) chats-edit-mode?) (and (= view-id :chat-list) chats-edit-mode?)
(and (= view-id :contact-list) contacts-edit-mode?)))) (and (= view-id :contact-list) contacts-edit-mode?))))
(reg-sub :network
(fn [db]
(:network db)))

View File

@ -66,6 +66,8 @@
:wallet-list wallet-list-screen :wallet-list wallet-list-screen
:wallet-send-transaction send-transaction :wallet-send-transaction send-transaction
:wallet-request-transaction request-transaction :wallet-request-transaction request-transaction
:wallet-transactions wallet-transactions/transactions
:wallet-transaction-details wallet-transactions/transaction-details
:discover-search-results discover-search-results :discover-search-results discover-search-results
:new-chat new-chat :new-chat new-chat
:new-group new-group :new-group new-group
@ -106,7 +108,6 @@
:transaction-details transaction-details :transaction-details transaction-details
:confirmation-success confirmation-success :confirmation-success confirmation-success
:contact-list-modal contact-list-modal :contact-list-modal contact-list-modal
:wallet-transactions wallet-transactions/transactions
:wallet-transactions-filter wallet-transactions/filter-history :wallet-transactions-filter wallet-transactions/filter-history
:wallet-transactions-sign-all wallet-transactions/sign-all :wallet-transactions-sign-all wallet-transactions/sign-all
(throw (str "Unknown modal view: " modal-view)))] (throw (str "Unknown modal view: " modal-view)))]

View File

@ -130,3 +130,9 @@
(-> db (-> db
(assoc-error-message :prices-update err) (assoc-error-message :prices-update err)
(assoc :prices-loading? false)))) (assoc :prices-loading? false))))
(handlers/register-handler-fx
:show-transaction-details
(fn [{:keys [db]} [_ hash]]
{:db (assoc-in db [:wallet :current-transaction] hash)
:dispatch [:navigate-to :wallet-transaction-details]}))

View File

@ -33,7 +33,7 @@
(def transaction-history-action (def transaction-history-action
{:icon :icons/transaction-history {:icon :icons/transaction-history
:icon-opts (merge {:color :white :style {:viewBox "-108 65.9 24 24"}} wallet.styles/toolbar-icon) :icon-opts (merge {:color :white :style {:viewBox "-108 65.9 24 24"}} wallet.styles/toolbar-icon)
:handler #(rf/dispatch [:navigate-to-modal :wallet-transactions])}) :handler #(rf/dispatch [:navigate-to :wallet-transactions])})
(defn toolbar-view [] (defn toolbar-view []
[toolbar/toolbar2 {:style wallet.styles/toolbar} [toolbar/toolbar2 {:style wallet.styles/toolbar}

View File

@ -2,9 +2,14 @@
(:require [re-frame.core :refer [reg-sub subscribe]] (:require [re-frame.core :refer [reg-sub subscribe]]
[status-im.utils.money :as money])) [status-im.utils.money :as money]))
(reg-sub :balance (reg-sub :wallet
(fn [db] (fn [db]
(get-in db [:wallet :balance]))) (:wallet db)))
(reg-sub :balance
:<- [:wallet]
(fn [wallet]
(:balance wallet)))
(reg-sub :price (reg-sub :price
(fn [db] (fn [db]
@ -15,9 +20,10 @@
(get-in db [:prices :last-day]))) (get-in db [:prices :last-day])))
(reg-sub :wallet/error-message? (reg-sub :wallet/error-message?
(fn [db] :<- [:wallet]
(or (get-in db [:wallet :errors :balance-update]) (fn [wallet]
(get-in db [:wallet :errors :prices-update])))) (or (get-in wallet [:errors :balance-update])
(get-in wallet [:errors :prices-update]))))
(reg-sub :eth-balance (reg-sub :eth-balance
:<- [:balance] :<- [:balance]
@ -51,5 +57,6 @@
(:prices-loading? db))) (:prices-loading? db)))
(reg-sub :wallet/balance-loading? (reg-sub :wallet/balance-loading?
(fn [db] :<- [:wallet]
(get-in db [:wallet :balance-loading?]))) (fn [wallet]
(:balance-loading? wallet)))

View File

@ -15,7 +15,9 @@
:padding-right 10 :padding-right 10
:font-size 13}) :font-size 13})
(def main-section styles/flex) (def main-section
{:flex 1
:background-color styles/color-white})
(def tabs (def tabs
{:border-bottom-width 1 {:border-bottom-width 1
@ -88,3 +90,80 @@
:height 40 :height 40
:border-radius 32 :border-radius 32
:background-color color}) :background-color color})
;; transaction details
(def transaction-details-row
{:flex-direction :row
:margin-vertical 5})
(def transaction-details-item-label
{:flex 1
:margin-right 10
:color styles/color-gray4
:font-size 14})
(def transaction-details-item-value-wrapper
{:flex 5})
(def transaction-details-item-value
{:font-size 14
:color styles/color-black})
(def transaction-details-item-extra-value
{:font-size 14
:color styles/color-gray4})
(def transaction-details-header
{:margin-horizontal 16
:margin-top 10
:flex-direction :row})
(def transaction-details-header-icon
{:margin-vertical 7})
(def transaction-details-header-infos
{:flex 1
:flex-direction :column
:margin-left 12
:margin-vertical 7})
(def transaction-details-header-value
{:font-size 16
:color styles/color-black})
(def transaction-details-header-date
{:font-size 14
:color styles/color-gray4})
(def transaction-details-block
{:margin-horizontal 16})
(def progress-bar
{:flex-direction :row
:margin-vertical 10
:height 2})
(defn progress-bar-done [done]
{:flex done
:background-color styles/color-blue2})
(defn progress-bar-todo [todo]
{:flex todo
:background-color styles/color-blue2
:opacity 0.30})
(def transaction-details-confirmations-count
{:color styles/color-black
:font-size 15
:margin-vertical 2})
(def transaction-details-confirmations-helper-text
{:color styles/color-gray4
:font-size 14
:margin-vertical 2})
(def transaction-details-separator
{:background-color styles/color-light-gray3
:height 1
:margin-vertical 10})

View File

@ -1,26 +1,36 @@
(ns status-im.ui.screens.wallet.transactions.subs (ns status-im.ui.screens.wallet.transactions.subs
(:require [re-frame.core :refer [reg-sub subscribe]] (:require [re-frame.core :refer [reg-sub subscribe]]
[status-im.utils.datetime :as datetime])) [status-im.utils.datetime :as datetime]
[status-im.utils.money :as money]
[status-im.utils.transactions :as transactions]))
(reg-sub :wallet.transactions/transactions-loading? (reg-sub :wallet.transactions/transactions-loading?
(fn [db] :<- [:wallet]
(get-in db [:wallet :transactions-loading?]))) (fn [wallet]
(:transactions-loading? wallet)))
(reg-sub :wallet.transactions/error-message? (reg-sub :wallet.transactions/error-message?
(fn [db] :<- [:wallet]
(get-in db [:wallet :errors :transactions-update]))) (fn [wallet]
(get-in wallet [:errors :transactions-update])))
(reg-sub :wallet.transactions/transactions (reg-sub :wallet.transactions/transactions
(fn [db] :<- [:wallet]
(group-by :type (get-in db [:wallet :transactions])))) (fn [wallet]
(:transactions wallet)))
(reg-sub :wallet.transactions/grouped-transactions
:<- [:wallet.transactions/transactions]
(fn [transactions]
(group-by :type (vals transactions))))
(reg-sub :wallet.transactions/unsigned-transactions (reg-sub :wallet.transactions/unsigned-transactions
:<- [:wallet.transactions/transactions] :<- [:wallet.transactions/grouped-transactions]
(fn [transactions] (fn [transactions]
(:unsigned transactions))) (:unsigned transactions)))
(reg-sub :wallet.transactions/postponed-transactions-list (reg-sub :wallet.transactions/postponed-transactions-list
:<- [:wallet.transactions/transactions] :<- [:wallet.transactions/grouped-transactions]
(fn [{:keys [postponed]}] (fn [{:keys [postponed]}]
(when postponed (when postponed
{:title "Postponed" {:title "Postponed"
@ -28,7 +38,7 @@
:data postponed}))) :data postponed})))
(reg-sub :wallet.transactions/pending-transactions-list (reg-sub :wallet.transactions/pending-transactions-list
:<- [:wallet.transactions/transactions] :<- [:wallet.transactions/grouped-transactions]
(fn [{:keys [pending]}] (fn [{:keys [pending]}]
(when pending (when pending
{:title "Pending" {:title "Pending"
@ -36,7 +46,7 @@
:data pending}))) :data pending})))
(reg-sub :wallet.transactions/completed-transactions-list (reg-sub :wallet.transactions/completed-transactions-list
:<- [:wallet.transactions/transactions] :<- [:wallet.transactions/grouped-transactions]
(fn [{:keys [inbound outbound]}] (fn [{:keys [inbound outbound]}]
(->> (into inbound outbound) (->> (into inbound outbound)
(group-by #(datetime/timestamp->date-key (:timestamp %))) (group-by #(datetime/timestamp->date-key (:timestamp %)))
@ -57,3 +67,38 @@
postponed (into postponed) postponed (into postponed)
pending (into pending) pending (into pending)
completed (into completed)))) completed (into completed))))
(reg-sub :wallet.transactions/current-transaction
:<- [:wallet]
(fn [wallet]
(:current-transaction wallet)))
(reg-sub :wallet.transactions/transaction-details
:<- [:wallet.transactions/transactions]
:<- [:wallet.transactions/current-transaction]
:<- [:network]
(fn [[transactions current-transaction network]]
(let [{:keys [gas-used gas-price hash timestamp type] :as transaction} (get transactions current-transaction)]
(merge transaction
{:cost (money/wei->ether (money/fee-value gas-used gas-price))
:gas-price-eth (str (.toFixed (money/wei->ether gas-price)) " ETH")
:date (datetime/timestamp->long-date timestamp)
:url (transactions/get-transaction-details-url network hash)}
;; TODO (yenda) proper wallet logic when wallet switching is impletmented
(if (= type :inbound)
{:to-wallet "Main wallet"}
{:from-wallet "Main wallet"})))))
(reg-sub :wallet.transactions.details/confirmations
:<- [:wallet.transactions/transaction-details]
(fn [transaction-details]
;;TODO (yenda) this field should be calculated based on the current-block and the block of the transaction
(:confirmations transaction-details)))
(reg-sub :wallet.transactions.details/confirmations-progress
:<- [:wallet.transactions.details/confirmations]
(fn [confirmations]
(let [max-confirmations 10]
(if (>= confirmations max-confirmations)
100
(* 100 (/ confirmations max-confirmations))))))

View File

@ -8,6 +8,7 @@
[status-im.components.status-bar :as status-bar] [status-im.components.status-bar :as status-bar]
[status-im.components.styles :as styles] [status-im.components.styles :as styles]
[status-im.components.tabs.views :as tabs] [status-im.components.tabs.views :as tabs]
[status-im.components.toolbar-new.actions :as actions]
[status-im.components.toolbar-new.view :as toolbar] [status-im.components.toolbar-new.view :as toolbar]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.screens.wallet.transactions.styles :as transactions.styles] [status-im.ui.screens.wallet.transactions.styles :as transactions.styles]
@ -15,6 +16,9 @@
[status-im.utils.utils :as utils]) [status-im.utils.utils :as utils])
(:require-macros [status-im.utils.views :refer [defview letsubs]])) (:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn- show-not-implemented! []
(utils/show-popup "TODO" "Not implemented yet!"))
(defn on-sign-transaction (defn on-sign-transaction
[m] [m]
;; TODO(yenda) implement ;; TODO(yenda) implement
@ -50,6 +54,7 @@
[button/primary-button {:text (i18n/label :t/transactions-sign) :on-press #(on-sign-transaction m)}] [button/primary-button {:text (i18n/label :t/transactions-sign) :on-press #(on-sign-transaction m)}]
[button/secondary-button {:text (i18n/label :t/delete) :on-press #(on-delete-transaction m)}]]) [button/secondary-button {:text (i18n/label :t/delete) :on-press #(on-delete-transaction m)}]])
(defn- inbound? [type] (= "inbound" type))
(defn- unsigned? [type] (= "unsigned" type)) (defn- unsigned? [type] (= "unsigned" type))
(defn- transaction-icon [k background-color color] (defn- transaction-icon [k background-color color]
@ -57,25 +62,28 @@
:icon-opts {:color color} :icon-opts {:color color}
:style (transactions.styles/transaction-icon-background background-color)}) :style (transactions.styles/transaction-icon-background background-color)})
(defn- transaction-type->icon [s] (defn- transaction-type->icon [k]
(case s (case k
"unsigned" (transaction-icon :icons/dots-horizontal styles/color-gray4-transparent styles/color-gray7) :unsigned (transaction-icon :icons/dots-horizontal styles/color-gray4-transparent styles/color-gray7)
"inbound" (transaction-icon :icons/arrow-left styles/color-green-3-light styles/color-green-3) :inbound (transaction-icon :icons/arrow-left styles/color-green-3-light styles/color-green-3)
"outbound" (transaction-icon :icons/arrow-right styles/color-blue4-transparent styles/color-blue4) :outbound (transaction-icon :icons/arrow-right styles/color-blue4-transparent styles/color-blue4)
("postponed" "pending") (transaction-icon :icons/arrow-right styles/color-gray4-transparent styles/color-gray7) (:postponed :pending) (transaction-icon :icons/arrow-right styles/color-gray4-transparent styles/color-gray7)
(throw (str "Unknown transaction type: " s)))) (throw (str "Unknown transaction type: " k))))
(defn render-transaction [{:keys [to from type value symbol] :as m}] (defn render-transaction [{:keys [hash to from type value symbol] :as m}]
[list/item [list/item
[list/item-icon (transaction-type->icon type)] [list/item-icon (transaction-type->icon (keyword type))]
[list/item-content [list/item-content
(str value " " symbol) (str value " " symbol)
(if to (if (inbound? type)
(str (i18n/label :t/to) " " to) (str (i18n/label :t/from) " " from)
(str (i18n/label :t/from) " " from)) (str (i18n/label :t/to) " " to))
(when (unsigned? type) (when (unsigned? type)
[action-buttons m])] [action-buttons m])]
[list/item-icon {:icon :icons/forward :icon-opts transactions.styles/forward}]]) [react/touchable-highlight {:on-press #(re-frame/dispatch [:show-transaction-details hash])}
[react/view
[list/item-icon {:icon :icons/forward
:icon-opts transactions.styles/forward}]]]])
;; TODO(yenda) hook with re-frame ;; TODO(yenda) hook with re-frame
(defn- empty-text [s] [react/text {:style transactions.styles/empty-text} s]) (defn- empty-text [s] [react/text {:style transactions.styles/empty-text} s])
@ -135,13 +143,13 @@
(defn- item-tokens [{:keys [symbol label checked?]}] (defn- item-tokens [{:keys [symbol label checked?]}]
[list/item [list/item
[list/item-icon (transaction-type->icon "pending")] ;; TODO(jeluard) add proper token data [list/item-icon (transaction-type->icon :pending)] ;; TODO(jeluard) add proper token data
[list/item-content label symbol] [list/item-content label symbol]
[checkbox/checkbox {:checked? true #_checked?}]]) [checkbox/checkbox {:checked? true #_checked?}]])
(defn- item-type [{:keys [id label checked?]}] (defn- item-type [{:keys [id label checked?]}]
[list/item [list/item
[list/item-icon (transaction-type->icon id)] [list/item-icon (transaction-type->icon (keyword id))]
[list/item-content label] [list/item-content label]
[checkbox/checkbox checked?]]) [checkbox/checkbox checked?]])
@ -189,6 +197,70 @@
default-view (get-in tabs [0 :view-id]) default-view (get-in tabs [0 :view-id])
view-id (reagent/atom default-view)] view-id (reagent/atom default-view)]
[react/view {:style styles/flex} [react/view {:style styles/flex}
[status-bar/status-bar {:type :modal-white}] [status-bar/status-bar]
[toolbar-view view-id unsigned-transactions] [toolbar-view view-id unsigned-transactions]
[main-section view-id tabs]])) [main-section view-id tabs]]))
(defn transaction-details-header [{:keys [value date type]}]
[react/view {:style transactions.styles/transaction-details-header}
[react/view {:style transactions.styles/transaction-details-header-icon}
[list/item-icon (transaction-type->icon type)]]
[react/view {:style transactions.styles/transaction-details-header-infos}
[react/text {:style transactions.styles/transaction-details-header-value} (str value " ETH")]
[react/text {:style transactions.styles/transaction-details-header-date} date]]])
(defn progress-bar [progress]
[react/view {:style transactions.styles/progress-bar}
[react/view {:style (transactions.styles/progress-bar-done progress)}]
[react/view {:style (transactions.styles/progress-bar-todo (- 100 progress))}]])
(defn transaction-details-confirmations [confirmations confirmations-progress]
[react/view {:style transactions.styles/transaction-details-block}
[progress-bar confirmations-progress]
[react/text {:style transactions.styles/transaction-details-confirmations-count}
(str confirmations " " (i18n/label :t/confirmations))]
[react/text {:style transactions.styles/transaction-details-confirmations-helper-text}
(i18n/label :t/confirmations-helper-text)]])
(defn transaction-details-list-row
([label value]
(transaction-details-list-row label value nil))
([label value extra-value]
[react/view {:style transactions.styles/transaction-details-row}
[react/text {:style transactions.styles/transaction-details-item-label} (i18n/label label)]
[react/view {:style transactions.styles/transaction-details-item-value-wrapper}
[react/text {:style transactions.styles/transaction-details-item-value} (str value)]
[react/text {:style transactions.styles/transaction-details-item-extra-value} (str extra-value)]]]))
(defn transaction-details-list [{:keys [block hash from from-wallet to to-wallet gas-limit gas-price-eth gas-used cost nonce data]}]
[react/view {:style transactions.styles/transaction-details-block}
[transaction-details-list-row :t/block block]
[transaction-details-list-row :t/hash hash]
[transaction-details-list-row :t/from (or from-wallet from) (when from-wallet from)]
[transaction-details-list-row :t/to (or to-wallet to) (when to-wallet to)]
[transaction-details-list-row :t/gas-limit gas-limit]
[transaction-details-list-row :t/gas-price gas-price-eth]
[transaction-details-list-row :t/gas-used gas-used]
[transaction-details-list-row :t/cost-fee (str cost " ETH")]
[transaction-details-list-row :t/nonce nonce]
[transaction-details-list-row :t/data data]])
(defn details-action [hash url]
[(actions/opts [{:text (i18n/label :t/copy-transaction-hash) :value #(react/copy-to-clipboard hash)}
{:text (i18n/label :t/open-on-etherscan) :value #(.openURL react/linking url)}])])
(defview transaction-details []
(letsubs [{:keys [hash url] :as transaction-details} [:wallet.transactions/transaction-details]
confirmations [:wallet.transactions.details/confirmations]
confirmations-progress [:wallet.transactions.details/confirmations-progress]]
[react/view {:style styles/flex}
[status-bar/status-bar]
[toolbar/toolbar2 {}
toolbar/default-nav-back
[toolbar/content-title (i18n/label :t/transaction-details)]
[toolbar/actions (details-action hash url)]]
[react/scroll-view
[transaction-details-header transaction-details]
[transaction-details-confirmations confirmations confirmations-progress]
[react/view {:style transactions.styles/transaction-details-separator}]
[transaction-details-list transaction-details]]]))

View File

@ -44,6 +44,12 @@
from-long from-long
(plus time-zone-offset))))) (plus time-zone-offset)))))
(defn timestamp->long-date [ms]
(keyword (unparse (formatter "MMM DD YYYY HH:mm:ss")
(-> ms
from-long
(plus time-zone-offset)))))
(defn day-relative [ms] (defn day-relative [ms]
(when (pos? ms) (when (pos? ms)
(to-short-str ms #(label :t/datetime-today)))) (to-short-str ms #(label :t/datetime-today))))

View File

@ -3,33 +3,45 @@
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im.utils.money :as money])) [status-im.utils.money :as money]))
(defn get-transaction-url [network account] (defn get-network-subdomain [network]
(let [network (case network (case network
"testnet" "ropsten" "testnet" "ropsten"
"mainnet" "api")] "mainnet" "api"))
(str "https://" network ".etherscan.io/api?module=account&action=txlist&address=0x"
(defn get-transaction-details-url [network hash]
(let [network-subdomain (get-network-subdomain network)]
(str "https://" network-subdomain ".etherscan.io/tx/" hash)))
(defn get-transaction-url [network account]
(let [network-subdomain (get-network-subdomain network)]
(str "https://" network-subdomain ".etherscan.io/api?module=account&action=txlist&address=0x"
account "&startblock=0&endblock=99999999&sort=desc&apikey=YourApiKeyToken?q=json"))) account "&startblock=0&endblock=99999999&sort=desc&apikey=YourApiKeyToken?q=json")))
(defn format-transaction [account {:keys [value to from timeStamp]}] (defn format-transaction [account {:keys [value timeStamp blockNumber hash from to gas gasPrice gasUsed nonce confirmations input]}]
(let [transaction {:value (money/wei->ether value) (let [inbound? (= (str "0x" account) to)]
{:value (money/wei->ether value)
;; timestamp is in seconds, we convert it in ms ;; timestamp is in seconds, we convert it in ms
:timestamp (str timeStamp "000") :timestamp (str timeStamp "000")
:symbol "ETH"} :symbol "ETH"
inbound? (= (str "0x" account) to)] :type (if inbound? :inbound :outbound)
(if inbound? :block blockNumber
(assoc transaction :hash hash
:from from :from from
:type :inbound)
(assoc transaction
:to to :to to
:type :outbound)))) :gas-limit gas
:gas-price gasPrice
:gas-used gasUsed
:nonce nonce
:confirmations confirmations
:data input}))
(defn format-transactions-response [response account] (defn format-transactions-response [response account]
(->> response (->> response
types/json->clj types/json->clj
:result :result
(map (partial format-transaction account)) (reduce (fn [transactions {:keys [hash] :as transaction}]
(sort-by :timestamp))) (assoc transactions hash (format-transaction account transaction)))
{})))
(defn get-transactions [network account on-success on-error] (defn get-transactions [network account on-success on-error]
(utils/http-get (get-transaction-url network account) (utils/http-get (get-transaction-url network account)