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
{
;common
;;common
:members-title "Members"
:not-implemented "!not implemented"
: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."
: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"
:faq "FAQ"
:switch-users "Switch users"
@ -28,7 +28,7 @@
:view-all "View all"
:current-network "Current network"
;chat
;;chat
:is-typing "is typing"
:and-you "and you"
:search-chat "Search chat"
@ -48,11 +48,11 @@
:faucet-success "Faucet request has been received"
:faucet-error "Faucet request error"
;sync
;;sync
:sync-in-progress "Syncing..."
:sync-synced "In sync"
;messages
;;messages
:status-sending "Sending"
:status-pending "Pending"
:status-sent "Sent"
@ -61,7 +61,7 @@
:status-delivered "Delivered"
:status-failed "Failed"
;datetime
;;datetime
:datetime-ago-format "{{number}} {{time-intervals}} {{ago}}"
:datetime-second {:one "second"
:other "seconds"}
@ -76,7 +76,7 @@
:datetime-yesterday "yesterday"
:datetime-today "today"
;profile
;;profile
:profile "Profile"
:edit-profile "Edit profile"
:report-user "REPORT USER"
@ -116,7 +116,7 @@
:browsing-open-in-web-browser "Open in web browser"
:browsing-cancel "Cancel"
;sign-up
;;sign-up
:contacts-syncronized "Your contacts have been synchronized"
:confirmation-code (str "Thanks! We've sent you a text message with a confirmation "
"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."
: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-international "International 2"
:phone-national "National"
:phone-significant "Significant"
;chats
;;chats
:chats "Chats"
:new-chat "New chat"
:delete-chat "Delete chat"
@ -153,7 +153,7 @@
:topic-format "Wrong format [a-z0-9\\-]+"
:public-group-topic "Topic"
;discover
;;discover
:discover "Discover"
:none "None"
:search-tags "Type your search tags here"
@ -162,10 +162,10 @@
:no-statuses-discovered "No statuses discovered"
:no-statuses-found "No statuses found"
;settings
;;settings
:settings "Settings"
;contacts
;;contacts
:contacts "Contacts"
:new-contact "New contact"
:delete-contact "Delete contact"
@ -183,7 +183,7 @@
:enter-address "Enter address"
:more "more"
;group-settings
;;group-settings
:remove "Remove"
:save "Save"
:delete "Delete"
@ -200,7 +200,7 @@
:green "Green"
:red "Red"
;commands
;;commands
:money-command-description "Send money"
:location-command-description "Send location"
:phone-command-description "Send phone number"
@ -216,7 +216,7 @@
:chat-send-eth-to "{{amount}} ETH to {{chat-name}}"
:chat-send-eth-from "{{amount}} ETH from {{chat-name}}"
;location command
;;location command
:your-current-location "Your current location"
:places-nearby "Places nearby"
:search-results "Search results"
@ -226,7 +226,7 @@
:sharing-copy-to-clipboard-address "Copy the Address"
:sharing-copy-to-clipboard-coordinates "Copy coordinates"
;new-group
;;new-group
:group-chat-name "Chat name"
:empty-group-chat-name "Please enter a name"
:illegal-group-chat-name "Please select another name"
@ -241,11 +241,11 @@
:contact-s {:one "contact"
:other "contacts"}
;participants
;;participants
:add-participants "Add Participants"
:remove-participants "Remove Participants"
;protocol
;;protocol
:received-invitation "received chat invitation"
:removed-from-chat "removed you from group chat"
:left "left"
@ -253,7 +253,7 @@
:removed "removed"
:You "You"
;new-contact
;;new-contact
:add-new-contact "Add new contact"
:import-qr "Import"
:scan-qr "Scan QR"
@ -267,7 +267,7 @@
:can-not-add-yourself "You can't add yourself"
:unknown-address "Unknown address"
;login
;;login
:connect "Connect"
:address "Address"
:password "Password"
@ -276,7 +276,7 @@
:sign-in "Sign in"
:wrong-password "Wrong password"
;recover
;;recover
:recover-from-passphrase "Recover from passphrase"
:recover-explain "Please enter the passphrase for your password to recover access"
:passphrase "Passphrase"
@ -285,21 +285,21 @@
:enter-valid-password "Please enter a password"
:twelve-words-in-correct-order "12 words in correct order"
;accounts
;;accounts
:recover-access "Recover access"
:add-account "Add account"
:create-new-account "Create new account"
;wallet-qr-code
;;wallet-qr-code
:done "Done"
;validation
;;validation
:invalid-phone "Invalid phone number"
:amount "Amount"
:not-enough-eth (str "Not enough ETH on balance "
"({{balance}} ETH)")
;transactions
;;transactions
:confirm "Confirm"
:confirm-transactions {:one "Confirm transaction"
:other "Confirm {{count}} transactions"
@ -324,8 +324,19 @@
:data "Data"
:got-it "Got it"
: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"
;;testfairy warning
@ -350,6 +361,7 @@
:share "Share"
:currency "Currency"
:transactions "Transactions"
:transaction-details "Transaction details"
:transactions-sign "Sign"
: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"

View File

@ -42,3 +42,7 @@
(or search-mode?
(and (= view-id :chat-list) chats-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-send-transaction send-transaction
:wallet-request-transaction request-transaction
:wallet-transactions wallet-transactions/transactions
:wallet-transaction-details wallet-transactions/transaction-details
:discover-search-results discover-search-results
:new-chat new-chat
:new-group new-group
@ -106,7 +108,6 @@
:transaction-details transaction-details
:confirmation-success confirmation-success
:contact-list-modal contact-list-modal
:wallet-transactions wallet-transactions/transactions
:wallet-transactions-filter wallet-transactions/filter-history
:wallet-transactions-sign-all wallet-transactions/sign-all
(throw (str "Unknown modal view: " modal-view)))]

View File

@ -129,4 +129,10 @@
(log/debug "Unable to get prices: " err)
(-> db
(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
{:icon :icons/transaction-history
: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 []
[toolbar/toolbar2 {:style wallet.styles/toolbar}

View File

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

View File

@ -15,7 +15,9 @@
:padding-right 10
:font-size 13})
(def main-section styles/flex)
(def main-section
{:flex 1
:background-color styles/color-white})
(def tabs
{:border-bottom-width 1
@ -29,7 +31,7 @@
{:color styles/color-gray7})
(def empty-text
{:text-align :center
{:text-align :center
:margin-top 22
:margin-horizontal 92})
@ -88,3 +90,80 @@
:height 40
:border-radius 32
: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
(: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?
(fn [db]
(get-in db [:wallet :transactions-loading?])))
:<- [:wallet]
(fn [wallet]
(:transactions-loading? wallet)))
(reg-sub :wallet.transactions/error-message?
(fn [db]
(get-in db [:wallet :errors :transactions-update])))
:<- [:wallet]
(fn [wallet]
(get-in wallet [:errors :transactions-update])))
(reg-sub :wallet.transactions/transactions
(fn [db]
(group-by :type (get-in db [:wallet :transactions]))))
:<- [:wallet]
(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
:<- [:wallet.transactions/transactions]
:<- [:wallet.transactions/grouped-transactions]
(fn [transactions]
(:unsigned transactions)))
(reg-sub :wallet.transactions/postponed-transactions-list
:<- [:wallet.transactions/transactions]
:<- [:wallet.transactions/grouped-transactions]
(fn [{:keys [postponed]}]
(when postponed
{:title "Postponed"
@ -28,7 +38,7 @@
:data postponed})))
(reg-sub :wallet.transactions/pending-transactions-list
:<- [:wallet.transactions/transactions]
:<- [:wallet.transactions/grouped-transactions]
(fn [{:keys [pending]}]
(when pending
{:title "Pending"
@ -36,7 +46,7 @@
:data pending})))
(reg-sub :wallet.transactions/completed-transactions-list
:<- [:wallet.transactions/transactions]
:<- [:wallet.transactions/grouped-transactions]
(fn [{:keys [inbound outbound]}]
(->> (into inbound outbound)
(group-by #(datetime/timestamp->date-key (:timestamp %)))
@ -57,3 +67,38 @@
postponed (into postponed)
pending (into pending)
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.styles :as styles]
[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.i18n :as i18n]
[status-im.ui.screens.wallet.transactions.styles :as transactions.styles]
@ -15,6 +16,9 @@
[status-im.utils.utils :as utils])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn- show-not-implemented! []
(utils/show-popup "TODO" "Not implemented yet!"))
(defn on-sign-transaction
[m]
;; TODO(yenda) implement
@ -50,6 +54,7 @@
[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)}]])
(defn- inbound? [type] (= "inbound" type))
(defn- unsigned? [type] (= "unsigned" type))
(defn- transaction-icon [k background-color color]
@ -57,25 +62,28 @@
:icon-opts {:color color}
:style (transactions.styles/transaction-icon-background background-color)})
(defn- transaction-type->icon [s]
(case s
"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)
"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)
(throw (str "Unknown transaction type: " s))))
(defn- transaction-type->icon [k]
(case k
: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)
: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)
(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-icon (transaction-type->icon type)]
[list/item-icon (transaction-type->icon (keyword type))]
[list/item-content
(str value " " symbol)
(if to
(str (i18n/label :t/to) " " to)
(str (i18n/label :t/from) " " from))
(if (inbound? type)
(str (i18n/label :t/from) " " from)
(str (i18n/label :t/to) " " to))
(when (unsigned? type)
[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
(defn- empty-text [s] [react/text {:style transactions.styles/empty-text} s])
@ -135,13 +143,13 @@
(defn- item-tokens [{:keys [symbol label checked?]}]
[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]
[checkbox/checkbox {:checked? true #_checked?}]])
(defn- item-type [{:keys [id label checked?]}]
[list/item
[list/item-icon (transaction-type->icon id)]
[list/item-icon (transaction-type->icon (keyword id))]
[list/item-content label]
[checkbox/checkbox checked?]])
@ -189,6 +197,70 @@
default-view (get-in tabs [0 :view-id])
view-id (reagent/atom default-view)]
[react/view {:style styles/flex}
[status-bar/status-bar {:type :modal-white}]
[status-bar/status-bar]
[toolbar-view view-id unsigned-transactions]
[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
(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]
(when (pos? ms)
(to-short-str ms #(label :t/datetime-today))))

View File

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