send transaction layer 1
This commit is contained in:
parent
62affda881
commit
9246d7df21
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16px" height="8px" viewBox="0 0 16 8">
|
||||||
|
<path fill="none" d="M0,0 L15.969209,0.0223819541 L9.39011025,6.60148066 C8.60906167,7.38252924 7.34273171,7.38252924 6.56168312,6.60148066 L6.55741249,6.59719708 L0,0 Z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 234 B |
|
@ -55,3 +55,5 @@
|
||||||
|
|
||||||
(defn create-value-xy [x y]
|
(defn create-value-xy [x y]
|
||||||
(js/ReactNative.Animated.ValueXY. (clj->js {:x x, :y y})))
|
(js/ReactNative.Animated.ValueXY. (clj->js {:x x, :y y})))
|
||||||
|
|
||||||
|
(def easing js/ReactNative.Easing)
|
|
@ -67,6 +67,7 @@
|
||||||
:icons/dropdown (slurp-svg "./resources/icons/dropdown.svg")
|
:icons/dropdown (slurp-svg "./resources/icons/dropdown.svg")
|
||||||
:icons/grab (slurp-svg "./resources/icons/grab.svg")
|
:icons/grab (slurp-svg "./resources/icons/grab.svg")
|
||||||
:icons/share (slurp-svg "./resources/icons/share.svg")
|
:icons/share (slurp-svg "./resources/icons/share.svg")
|
||||||
|
:icons/tooltip-triangle (slurp-svg "./resources/icons/tooltip-triangle.svg")
|
||||||
:icons/network (slurp-svg "./resources/icons/network.svg")})
|
:icons/network (slurp-svg "./resources/icons/network.svg")})
|
||||||
|
|
||||||
(defn normalize-property-name [n]
|
(defn normalize-property-name [n]
|
||||||
|
|
|
@ -106,3 +106,5 @@
|
||||||
(def toolbar-text-action-disabled {:color styles/color-gray7})
|
(def toolbar-text-action-disabled {:color styles/color-gray7})
|
||||||
|
|
||||||
(def item-text-white-background {:color styles/color-blue4})
|
(def item-text-white-background {:color styles/color-blue4})
|
||||||
|
|
||||||
|
(def ios-content-item {:position :absolute :right 90 :left 90})
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
[status-im.components.context-menu :as context-menu]
|
[status-im.components.context-menu :as context-menu]
|
||||||
[status-im.components.toolbar-new.actions :as act]
|
[status-im.components.toolbar-new.actions :as act]
|
||||||
[status-im.components.toolbar-new.styles :as tst]
|
[status-im.components.toolbar-new.styles :as tst]
|
||||||
[status-im.components.icons.vector-icons :as vi]))
|
[status-im.components.icons.vector-icons :as vi]
|
||||||
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
;; Navigation item
|
;; Navigation item
|
||||||
|
|
||||||
|
@ -103,10 +104,15 @@
|
||||||
action-items]
|
action-items]
|
||||||
[rn/view {:style (merge (tst/toolbar-wrapper background-color flat?) style)}
|
[rn/view {:style (merge (tst/toolbar-wrapper background-color flat?) style)}
|
||||||
[rn/view {:style tst/toolbar}
|
[rn/view {:style tst/toolbar}
|
||||||
|
(when platform/ios?
|
||||||
|
[rn/view tst/ios-content-item
|
||||||
|
content-item])
|
||||||
(when nav-item
|
(when nav-item
|
||||||
[rn/view {:style (tst/toolbar-nav-actions-container 0)}
|
[rn/view {:style (tst/toolbar-nav-actions-container 0)}
|
||||||
nav-item])
|
nav-item])
|
||||||
content-item
|
(if platform/ios?
|
||||||
|
[rn/view st/flex]
|
||||||
|
content-item)
|
||||||
action-items]
|
action-items]
|
||||||
(when-not no-sync-bar? [sync-state-gradient-view/sync-state-gradient-view])]))
|
(when-not no-sync-bar? [sync-state-gradient-view/sync-state-gradient-view])]))
|
||||||
|
|
||||||
|
|
|
@ -127,8 +127,7 @@
|
||||||
(status/discard-transaction id)))))
|
(status/discard-transaction id)))))
|
||||||
|
|
||||||
(register-handler ::transaction-queued
|
(register-handler ::transaction-queued
|
||||||
(after #(dispatch [:navigate-to-modal :unsigned-transactions]))
|
(fn [{:wallet/keys [send-transaction] :as db} [_ {:keys [id message_id args] :as transaction}]]
|
||||||
(fn [db [_ {:keys [id message_id args] :as transaction}]]
|
|
||||||
(let [{:keys [from to value data gas gasPrice]} args]
|
(let [{:keys [from to value data gas gasPrice]} args]
|
||||||
(if (transaction-valid? transaction)
|
(if (transaction-valid? transaction)
|
||||||
(let [transaction {:id id
|
(let [transaction {:id id
|
||||||
|
@ -140,6 +139,9 @@
|
||||||
:gas-price (.toDecimal js/Web3.prototype gasPrice)
|
:gas-price (.toDecimal js/Web3.prototype gasPrice)
|
||||||
:timestamp (time/now-ms)
|
:timestamp (time/now-ms)
|
||||||
:message-id message_id}]
|
:message-id message_id}]
|
||||||
|
(if (:waiting-signal? send-transaction)
|
||||||
|
(dispatch [:wallet/transaction-queued id])
|
||||||
|
(dispatch [:navigate-to-modal :unsigned-transactions]))
|
||||||
(assoc-in db [:transactions-queue id] transaction))
|
(assoc-in db [:transactions-queue id] transaction))
|
||||||
db))))
|
db))))
|
||||||
|
|
||||||
|
@ -147,7 +149,7 @@
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
(fn [{:keys [transactions modal]} [_ {:keys [id response]}]]
|
(fn [{:keys [transactions modal]} [_ {:keys [id response]}]]
|
||||||
(let [{:keys [hash error]} response
|
(let [{:keys [hash error]} response
|
||||||
{:keys [message-id]} (transactions id)]
|
{:keys [message-id]} (get transactions id)]
|
||||||
(log/debug :parsed-response response)
|
(log/debug :parsed-response response)
|
||||||
(when-not (and error (string? error) (not (s/blank? error)))
|
(when-not (and error (string? error) (not (s/blank? error)))
|
||||||
(if (and message-id (not (s/blank? message-id)))
|
(if (and message-id (not (s/blank? message-id)))
|
||||||
|
|
|
@ -3,50 +3,52 @@
|
||||||
(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"
|
||||||
:notifications-title "Notifications and sounds"
|
:notifications-title "Notifications and sounds"
|
||||||
:offline "Offline"
|
:offline "Offline"
|
||||||
:search-for "Search for..."
|
:search-for "Search for..."
|
||||||
:cancel "Cancel"
|
:cancel "Cancel"
|
||||||
:next "Next"
|
:next "Next"
|
||||||
:type-a-message "Type a message..."
|
:type-a-message "Type a message..."
|
||||||
:type-a-command "Start typing a command..."
|
:type-a-command "Start typing a command..."
|
||||||
:error "Error"
|
:error "Error"
|
||||||
:unknown-status-go-error "Unknown status-go error"
|
:unknown-status-go-error "Unknown status-go error"
|
||||||
:node-unavailable "No ethereum node running"
|
:node-unavailable "No ethereum node running"
|
||||||
|
:yes "Yes"
|
||||||
|
:no "No"
|
||||||
|
|
||||||
: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"
|
||||||
:feedback "Got feedback?\nShake your phone!"
|
:feedback "Got feedback?\nShake your phone!"
|
||||||
: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"
|
||||||
:members {:one "1 member"
|
:members {:one "1 member"
|
||||||
:other "{{count}} members"
|
:other "{{count}} members"
|
||||||
:zero "no members"}
|
:zero "no members"}
|
||||||
:members-active {:one "1 member"
|
:members-active {:one "1 member"
|
||||||
:other "{{count}} members"
|
:other "{{count}} members"
|
||||||
:zero "no members"}
|
:zero "no members"}
|
||||||
:public-group-status "Public"
|
:public-group-status "Public"
|
||||||
:active-online "Online"
|
:active-online "Online"
|
||||||
:active-unknown "Unknown"
|
:active-unknown "Unknown"
|
||||||
:available "Available"
|
:available "Available"
|
||||||
:no-messages "No messages"
|
:no-messages "No messages"
|
||||||
:suggestions-requests "Requests"
|
:suggestions-requests "Requests"
|
||||||
:suggestions-commands "Commands"
|
:suggestions-commands "Commands"
|
||||||
: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..."
|
||||||
|
@ -275,6 +277,7 @@
|
||||||
:sign-in-to-status "Sign in to Status"
|
:sign-in-to-status "Sign in to Status"
|
||||||
:sign-in "Sign in"
|
:sign-in "Sign in"
|
||||||
:wrong-password "Wrong password"
|
:wrong-password "Wrong password"
|
||||||
|
:enter-password "Enter password"
|
||||||
|
|
||||||
;;recover
|
;;recover
|
||||||
:recover-from-passphrase "Recover from passphrase"
|
:recover-from-passphrase "Recover from passphrase"
|
||||||
|
@ -356,6 +359,7 @@
|
||||||
:wallet-add-asset "Add asset"
|
:wallet-add-asset "Add asset"
|
||||||
:wallet-total-value "Total value"
|
:wallet-total-value "Total value"
|
||||||
:wallet-settings "Wallet Settings"
|
:wallet-settings "Wallet Settings"
|
||||||
|
:signing-phrase-description "Sign the transaction by entering your password. Make sure that the words above match your secret signing phrase"
|
||||||
:request-transaction "Request Transaction"
|
:request-transaction "Request Transaction"
|
||||||
:send-request "Send request"
|
:send-request "Send request"
|
||||||
:share "Share"
|
:share "Share"
|
||||||
|
@ -364,6 +368,8 @@
|
||||||
:transaction-details "Transaction details"
|
:transaction-details "Transaction details"
|
||||||
:transactions-sign "Sign"
|
:transactions-sign "Sign"
|
||||||
:transactions-sign-all "Sign all"
|
:transactions-sign-all "Sign all"
|
||||||
|
:transactions-sign-transaction "Sign Transaction"
|
||||||
|
:transactions-sign-later "Sign Later"
|
||||||
: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"
|
||||||
:transactions-sign-input-placeholder "Enter your password"
|
:transactions-sign-input-placeholder "Enter your password"
|
||||||
:transactions-history "History"
|
:transactions-history "History"
|
||||||
|
@ -374,15 +380,26 @@
|
||||||
:transactions-filter-tokens "Tokens"
|
:transactions-filter-tokens "Tokens"
|
||||||
:transactions-filter-type "Type"
|
:transactions-filter-type "Type"
|
||||||
:transactions-filter-select-all "Select all"
|
:transactions-filter-select-all "Select all"
|
||||||
|
:view-transaction-details "View Transaction Details"
|
||||||
|
:transaction-description "If you want to be sure you transaction will not be compromised wait until it gets at least 10 block confirmations"
|
||||||
|
:transaction-sent "Transaction Sent"
|
||||||
|
:transaction-moved-text "The transaction has ben successfully moved to “Unsigned”"
|
||||||
|
:transaction-moved-title "Transaction Moved"
|
||||||
|
:sign-later-title "Sign Transaction Later?"
|
||||||
|
:sign-later-text "You will be able to sign in in the transaction history"
|
||||||
:not-applicable "Not applicable for unsigned transactions"
|
:not-applicable "Not applicable for unsigned transactions"
|
||||||
|
|
||||||
;; Wallet Send
|
;; Wallet Send
|
||||||
:wallet-send-transaction "Send a Transaction"
|
:wallet-send-transaction "Send Transaction"
|
||||||
:wallet-send-step-one "Step 1 of 3"
|
:wallet-send-step "Step {{step}} of {{number}}"
|
||||||
:wallet-choose-recipient "Choose Recipient"
|
:wallet-choose-recipient "Choose Recipient"
|
||||||
:wallet-choose-from-contacts "Choose From Contacts"
|
:wallet-choose-from-contacts "Choose From Contacts"
|
||||||
:wallet-address-from-clipboard "Use Address From Clipboard"
|
:wallet-address-from-clipboard "Use Address From Clipboard"
|
||||||
:wallet-browse-photos "Browse Photos"
|
:wallet-browse-photos "Browse Photos"
|
||||||
|
:validation-amount-invalid-number "Amount is not valid number"
|
||||||
|
:validation-amount-is-too-precise "Amount is too precise. The smallest unit you can send is 1 Wei (1x10^-18 ETH)"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;network settings
|
;network settings
|
||||||
:new-network "New network"
|
:new-network "New network"
|
||||||
|
|
|
@ -112,6 +112,7 @@
|
||||||
:my-profile/profile
|
:my-profile/profile
|
||||||
:my-profile/default-name
|
:my-profile/default-name
|
||||||
:wallet/request-transaction
|
:wallet/request-transaction
|
||||||
|
:wallet/send-transaction
|
||||||
:networks/selected-network
|
:networks/selected-network
|
||||||
:networks/networks
|
:networks/networks
|
||||||
:node/after-start
|
:node/after-start
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
status-im.ui.screens.wallet.subs
|
status-im.ui.screens.wallet.subs
|
||||||
status-im.ui.screens.wallet.transactions.subs
|
status-im.ui.screens.wallet.transactions.subs
|
||||||
status-im.ui.screens.wallet.send.subs
|
status-im.ui.screens.wallet.send.subs
|
||||||
|
status-im.ui.screens.wallet.request.subs
|
||||||
status-im.ui.screens.network-settings.subs
|
status-im.ui.screens.network-settings.subs
|
||||||
status-im.transactions.subs
|
status-im.transactions.subs
|
||||||
status-im.bots.subs))
|
status-im.bots.subs))
|
||||||
|
|
|
@ -43,9 +43,12 @@
|
||||||
[status-im.ui.screens.profile.qr-code.views :refer [qr-code-view]]
|
[status-im.ui.screens.profile.qr-code.views :refer [qr-code-view]]
|
||||||
|
|
||||||
[status-im.ui.screens.wallet.send.views :refer [send-transaction]]
|
[status-im.ui.screens.wallet.send.views :refer [send-transaction]]
|
||||||
|
[status-im.ui.screens.wallet.choose-recipient.views :refer [choose-recipient]]
|
||||||
[status-im.ui.screens.wallet.request.views :refer [request-transaction]]
|
[status-im.ui.screens.wallet.request.views :refer [request-transaction]]
|
||||||
[status-im.ui.screens.wallet.wallet-list.views :refer [wallet-list-screen]]
|
[status-im.ui.screens.wallet.wallet-list.views :refer [wallet-list-screen]]
|
||||||
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions]
|
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions]
|
||||||
|
[status-im.ui.screens.wallet.send.transaction-sent.views :refer [transaction-sent]]
|
||||||
|
|
||||||
[status-im.components.status-bar :as status-bar]
|
[status-im.components.status-bar :as status-bar]
|
||||||
[status-im.ui.screens.network-settings.views :refer [network-settings]]
|
[status-im.ui.screens.network-settings.views :refer [network-settings]]
|
||||||
[status-im.ui.screens.network-settings.add-rpc.views :refer [add-rpc-url]]
|
[status-im.ui.screens.network-settings.add-rpc.views :refer [add-rpc-url]]
|
||||||
|
@ -69,6 +72,8 @@
|
||||||
(:wallet :chat-list :discover :contact-list) main-tabs
|
(:wallet :chat-list :discover :contact-list) main-tabs
|
||||||
:wallet-list wallet-list-screen
|
:wallet-list wallet-list-screen
|
||||||
:wallet-send-transaction send-transaction
|
:wallet-send-transaction send-transaction
|
||||||
|
:wallet-transaction-sent transaction-sent
|
||||||
|
:choose-recipient choose-recipient
|
||||||
:wallet-request-transaction request-transaction
|
:wallet-request-transaction request-transaction
|
||||||
:wallet-transactions wallet-transactions/transactions
|
:wallet-transactions wallet-transactions/transactions
|
||||||
:wallet-transaction-details wallet-transactions/transaction-details
|
:wallet-transaction-details wallet-transactions/transaction-details
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
(ns status-im.ui.screens.wallet.choose-recipient.styles
|
||||||
|
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
|
||||||
|
(:require [status-im.components.styles :as styles]))
|
||||||
|
|
||||||
|
(def wallet-container
|
||||||
|
{:flex 1
|
||||||
|
:background-color styles/color-blue4})
|
||||||
|
|
||||||
|
(def toolbar-buttons-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:flex-shrink 1
|
||||||
|
:justify-content :space-between
|
||||||
|
:width 68
|
||||||
|
:margin-right 12})
|
||||||
|
|
||||||
|
(def choose-recipient-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:padding-top 20
|
||||||
|
:padding-bottom 20
|
||||||
|
:justify-content :center})
|
||||||
|
|
||||||
|
(def choose-recipient-label
|
||||||
|
{:color :white})
|
||||||
|
|
||||||
|
(defstyle recipient-buttons
|
||||||
|
{:flex-direction :column
|
||||||
|
:margin-horizontal 28
|
||||||
|
:margin-vertical 20
|
||||||
|
:border-radius 8
|
||||||
|
:ios {:background-color styles/color-blue6}})
|
||||||
|
|
||||||
|
(def recipient-icon {:margin-right 20})
|
||||||
|
|
||||||
|
(def recipient-icon-disabled {:margin-right 20
|
||||||
|
:opacity 0.3})
|
||||||
|
|
||||||
|
(def recipient-button
|
||||||
|
{:flex-direction :row
|
||||||
|
:justify-content :space-between
|
||||||
|
:margin-vertical 10
|
||||||
|
:margin-left 20})
|
||||||
|
|
||||||
|
(def recipient-button-text
|
||||||
|
{:color :white
|
||||||
|
:align-self :center
|
||||||
|
:font-size 14})
|
||||||
|
|
||||||
|
(def recipient-button-text-disabled
|
||||||
|
(merge recipient-button-text {:color "rgba(255, 255, 255, 0.3)"}))
|
||||||
|
|
||||||
|
(defnstyle recipient-touchable [divider?]
|
||||||
|
(cond-> {:border-color styles/color-gray-transparent-light}
|
||||||
|
divider? (assoc :ios {:border-bottom-width 1})))
|
||||||
|
|
||||||
|
(def recipient-touchable-disabled
|
||||||
|
{:background-color styles/color-blue4
|
||||||
|
:border-bottom-left-radius 8
|
||||||
|
:border-bottom-right-radius 8
|
||||||
|
:border-left-width 1
|
||||||
|
:border-bottom-width 1
|
||||||
|
:border-right-width 1
|
||||||
|
:border-color "rgba(255, 255, 255, 0.3)"})
|
||||||
|
|
||||||
|
(def qr-container
|
||||||
|
{:flex 1})
|
||||||
|
|
||||||
|
(def preview
|
||||||
|
{:flex 1
|
||||||
|
:justify-content :flex-end
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(def corner-dimensions
|
||||||
|
{:position :absolute
|
||||||
|
:width 40
|
||||||
|
:height 40})
|
||||||
|
|
||||||
|
(defn corner-left-bottom [dimension]
|
||||||
|
(let [viewport-offset 0.1666]
|
||||||
|
(merge corner-dimensions {:bottom (* viewport-offset dimension)
|
||||||
|
:left (* viewport-offset dimension)})))
|
||||||
|
|
||||||
|
(defn corner-right-bottom [dimension]
|
||||||
|
(let [viewport-offset 0.1666]
|
||||||
|
(merge corner-dimensions {:right (* viewport-offset dimension)
|
||||||
|
:bottom (* viewport-offset dimension)})))
|
||||||
|
|
||||||
|
(defn corner-left-top [dimension]
|
||||||
|
(let [viewport-offset 0.1666]
|
||||||
|
(merge corner-dimensions {:top (* viewport-offset dimension)
|
||||||
|
:left (* viewport-offset dimension)})))
|
||||||
|
|
||||||
|
(defn corner-right-top [dimension]
|
||||||
|
(let [viewport-offset 0.1666]
|
||||||
|
(merge corner-dimensions {:top (* viewport-offset dimension)
|
||||||
|
:right (* viewport-offset dimension)})))
|
||||||
|
|
||||||
|
(def viewfinder-port {:position :absolute
|
||||||
|
:left 0
|
||||||
|
:top 0
|
||||||
|
:bottom 0
|
||||||
|
:right 0
|
||||||
|
:flex 1})
|
||||||
|
|
||||||
|
(defn viewfinder-translucent [height width side]
|
||||||
|
(let [viewport-offset 0.1666
|
||||||
|
height-offset (* viewport-offset height)
|
||||||
|
width-offset (* viewport-offset width)]
|
||||||
|
(cond-> {:position :absolute
|
||||||
|
:background-color :black
|
||||||
|
:opacity 0.7}
|
||||||
|
(= :top side) (assoc :height height-offset
|
||||||
|
:width width)
|
||||||
|
(= :right side) (assoc :height (- height height-offset)
|
||||||
|
:width width-offset
|
||||||
|
:bottom 0
|
||||||
|
:right 0)
|
||||||
|
(= :bottom side) (assoc :height height-offset
|
||||||
|
:width (- width width-offset)
|
||||||
|
:bottom 0
|
||||||
|
:left 0)
|
||||||
|
(= :left side) (assoc :height (- height (* 2 height-offset))
|
||||||
|
:width width-offset
|
||||||
|
:top height-offset
|
||||||
|
:left 0))))
|
|
@ -0,0 +1,95 @@
|
||||||
|
(ns status-im.ui.screens.wallet.choose-recipient.views
|
||||||
|
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||||
|
(:require [re-frame.core :as re-frame]
|
||||||
|
[status-im.utils.utils :as utils]
|
||||||
|
[status-im.components.toolbar-new.view :as toolbar]
|
||||||
|
[status-im.components.toolbar-new.actions :as act]
|
||||||
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||||
|
[status-im.components.react :as react]
|
||||||
|
[status-im.components.icons.vector-icons :as vector-icons]
|
||||||
|
[status-im.ui.screens.wallet.choose-recipient.styles :as styles]
|
||||||
|
[status-im.components.status-bar :as status-bar]
|
||||||
|
[status-im.components.camera :as camera]
|
||||||
|
[clojure.string :as string]))
|
||||||
|
|
||||||
|
(defn- show-not-implemented! []
|
||||||
|
(utils/show-popup "TODO" "Not implemented yet!"))
|
||||||
|
|
||||||
|
(defn choose-from-contacts []
|
||||||
|
(re-frame/dispatch [:navigate-to-modal
|
||||||
|
:contact-list-modal
|
||||||
|
{:handler #(re-frame/dispatch [:wallet-open-send-transaction (:address %1) (:name %1)])
|
||||||
|
:action :send
|
||||||
|
:params {:hide-actions? true}}]))
|
||||||
|
|
||||||
|
(defn toolbar-view []
|
||||||
|
[toolbar/toolbar2 {:style wallet.styles/toolbar
|
||||||
|
:no-sync-bar? true}
|
||||||
|
[toolbar/nav-button (act/back-white act/default-handler)]
|
||||||
|
[toolbar/content-title {:color :white} (i18n/label :t/wallet-choose-recipient)]
|
||||||
|
[toolbar/actions [{:icon :icons/flash-active
|
||||||
|
:icon-opts {:color :white}
|
||||||
|
:handler show-not-implemented!}]]])
|
||||||
|
|
||||||
|
(defn recipient-buttons []
|
||||||
|
[react/view {:style styles/recipient-buttons}
|
||||||
|
[react/touchable-highlight {:style (styles/recipient-touchable true)
|
||||||
|
:on-press choose-from-contacts}
|
||||||
|
[react/view {:style styles/recipient-button}
|
||||||
|
[react/text {:style styles/recipient-button-text}
|
||||||
|
(i18n/label :t/wallet-choose-from-contacts)]
|
||||||
|
[vector-icons/icon :icons/qr {:color :white
|
||||||
|
:container-style styles/recipient-icon}]]]
|
||||||
|
[react/touchable-highlight {:style (styles/recipient-touchable true)
|
||||||
|
:on-press #(react/get-from-clipboard
|
||||||
|
(fn [clipboard]
|
||||||
|
(re-frame/dispatch [:choose-recipient clipboard])))}
|
||||||
|
[react/view {:style styles/recipient-button}
|
||||||
|
[react/text {:style styles/recipient-button-text}
|
||||||
|
(i18n/label :t/wallet-address-from-clipboard)]
|
||||||
|
[vector-icons/icon :icons/copy-from {:color :white
|
||||||
|
:container-style styles/recipient-icon}]]]
|
||||||
|
[react/touchable-highlight {:style styles/recipient-touchable-disabled}
|
||||||
|
[react/view {:style styles/recipient-button}
|
||||||
|
[react/text {:style styles/recipient-button-text-disabled}
|
||||||
|
(i18n/label :t/wallet-browse-photos)]
|
||||||
|
[vector-icons/icon :icons/browse {:color :white
|
||||||
|
:container-style styles/recipient-icon-disabled}]]]])
|
||||||
|
|
||||||
|
(defn viewfinder [{:keys [height width]}]
|
||||||
|
(let [min-dimension (min height width)]
|
||||||
|
[react/view {:style styles/viewfinder-port}
|
||||||
|
[react/view {:style (styles/viewfinder-translucent height width :top)}]
|
||||||
|
[react/view {:style (styles/viewfinder-translucent height width :right)}]
|
||||||
|
[react/view {:style (styles/viewfinder-translucent height width :bottom)}]
|
||||||
|
[react/view {:style (styles/viewfinder-translucent height width :left)}]
|
||||||
|
[react/image {:source {:uri :corner_left_top}
|
||||||
|
:style (styles/corner-left-top min-dimension)}]
|
||||||
|
[react/image {:source {:uri :corner_right_top}
|
||||||
|
:style (styles/corner-right-top min-dimension)}]
|
||||||
|
[react/image {:source {:uri :corner_left_bottom}
|
||||||
|
:style (styles/corner-left-bottom min-dimension)}]
|
||||||
|
[react/image {:source {:uri :corner_right_bottom}
|
||||||
|
:style (styles/corner-right-bottom min-dimension)}]]))
|
||||||
|
|
||||||
|
(defview choose-recipient []
|
||||||
|
(letsubs [camera-dimensions [:camera-dimensions]]
|
||||||
|
[react/view {:style styles/wallet-container}
|
||||||
|
[status-bar/status-bar {:type :wallet}]
|
||||||
|
[toolbar-view]
|
||||||
|
[react/view {:style styles/qr-container
|
||||||
|
:on-layout #(let [layout (.. % -nativeEvent -layout)]
|
||||||
|
(re-frame/dispatch [:set-in [:wallet :camera-dimensions]
|
||||||
|
{:width (.-width layout)
|
||||||
|
:height (.-height layout)}]))}
|
||||||
|
[camera/camera {:style styles/preview
|
||||||
|
:aspect :fill
|
||||||
|
:captureAudio false
|
||||||
|
:onBarCodeRead (fn [code]
|
||||||
|
(let [data (-> code
|
||||||
|
.-data
|
||||||
|
(string/replace #"ethereum:" ""))]
|
||||||
|
(re-frame/dispatch [:choose-recipient data])))}]
|
||||||
|
[viewfinder camera-dimensions]]
|
||||||
|
[recipient-buttons]]))
|
|
@ -0,0 +1,12 @@
|
||||||
|
(ns status-im.ui.screens.wallet.components.animations
|
||||||
|
(:require [status-im.components.animation :as animation]))
|
||||||
|
|
||||||
|
(defn animate-tooltip [bottom-value opacity-value]
|
||||||
|
(fn []
|
||||||
|
(animation/start
|
||||||
|
(animation/parallel
|
||||||
|
[(animation/timing opacity-value {:toValue 1
|
||||||
|
:duration 500})
|
||||||
|
(animation/timing bottom-value {:toValue 8.5
|
||||||
|
:easing (.bezier animation/easing 0.685, 0.000, 0.025, 1.185)
|
||||||
|
:duration 500})]))))
|
|
@ -12,15 +12,23 @@
|
||||||
:height 52
|
:height 52
|
||||||
:letter-spacing -0.2})
|
:letter-spacing -0.2})
|
||||||
|
|
||||||
(def label
|
(defstyle label
|
||||||
{:color :white
|
{:color :white
|
||||||
:font-size 14
|
:ios {:font-size 14
|
||||||
:line-height 16
|
:line-height 16
|
||||||
:letter-spacing -0.2})
|
:letter-spacing -0.2}
|
||||||
|
:android {:font-size 12
|
||||||
|
:line-height 12}})
|
||||||
|
|
||||||
|
(def amount-text-input-container
|
||||||
|
{:margin-top 8})
|
||||||
|
|
||||||
|
(def label-transparent
|
||||||
|
(merge label
|
||||||
|
{:color styles/color-white-transparent}))
|
||||||
|
|
||||||
(defnstyle amount-container [active?]
|
(defnstyle amount-container [active?]
|
||||||
{:margin-top 8
|
{:height 52
|
||||||
:height 52
|
|
||||||
:background-color (if active?
|
:background-color (if active?
|
||||||
styles/color-white-transparent-4
|
styles/color-white-transparent-4
|
||||||
styles/color-white-transparent-3)
|
styles/color-white-transparent-3)
|
||||||
|
@ -42,31 +50,100 @@
|
||||||
:justify-content :center})
|
:justify-content :center})
|
||||||
|
|
||||||
(defstyle currency-container
|
(defstyle currency-container
|
||||||
{:margin-top 8
|
{:margin-top 8
|
||||||
|
:height 52
|
||||||
|
;;TODO disabled
|
||||||
|
:border-width 1
|
||||||
|
:border-color styles/color-white-transparent-4
|
||||||
|
;:background-color styles/color-white-transparent-3
|
||||||
|
:justify-content :center
|
||||||
|
:padding 14
|
||||||
|
:ios {:border-radius 8}
|
||||||
|
:android {:border-radius 4}})
|
||||||
|
|
||||||
|
(defstyle recipient-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:flex 1
|
||||||
|
:margin-top 8
|
||||||
:height 52
|
:height 52
|
||||||
|
:align-items :center
|
||||||
:background-color styles/color-white-transparent-3
|
:background-color styles/color-white-transparent-3
|
||||||
:justify-content :center
|
:padding-vertical 14
|
||||||
:padding 14
|
:padding-left 14
|
||||||
|
:padding-right 8
|
||||||
:ios {:border-radius 8}
|
:ios {:border-radius 8}
|
||||||
:android {:border-radius 4}})
|
:android {:border-radius 4}})
|
||||||
|
|
||||||
(defstyle wallet-container
|
(defstyle wallet-container
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
:margin-top 8
|
:margin-top 8
|
||||||
:height 52
|
:height 52
|
||||||
:background-color styles/color-white-transparent-3
|
;;TODO disabled
|
||||||
:align-items :center
|
:border-width 1
|
||||||
:padding 14
|
:border-color styles/color-white-transparent-4
|
||||||
:ios {:border-radius 8}
|
;:background-color styles/color-white-transparent-3
|
||||||
:android {:border-radius 4}})
|
:align-items :center
|
||||||
|
:padding 14
|
||||||
|
:ios {:border-radius 8}
|
||||||
|
:android {:border-radius 4}})
|
||||||
|
|
||||||
(def wallet-name
|
(def wallet-name
|
||||||
{:color :white
|
{:color :white
|
||||||
:font-size 15
|
:font-size 15
|
||||||
:letter-spacing -0.2})
|
:letter-spacing -0.2})
|
||||||
|
|
||||||
|
(defn participant [address?]
|
||||||
|
{:color (if address? :white styles/color-white-transparent)
|
||||||
|
:flex-shrink 1
|
||||||
|
:font-size 15
|
||||||
|
:letter-spacing -0.2})
|
||||||
|
|
||||||
(def wallet-value
|
(def wallet-value
|
||||||
{:padding-left 6
|
{:padding-left 6
|
||||||
:color styles/color-white-transparent-5
|
:color styles/color-white-transparent-5
|
||||||
:font-size 15
|
:font-size 15
|
||||||
:letter-spacing -0.2})
|
:letter-spacing -0.2})
|
||||||
|
|
||||||
|
(def separator
|
||||||
|
{:height 1
|
||||||
|
:margin-horizontal 15
|
||||||
|
:background-color styles/color-white-transparent-1
|
||||||
|
:margin-top 16})
|
||||||
|
|
||||||
|
(def button-text
|
||||||
|
{:color :white
|
||||||
|
:font-size 15
|
||||||
|
:letter-spacing -0.2})
|
||||||
|
|
||||||
|
(def tooltip-container
|
||||||
|
{:position :absolute
|
||||||
|
:align-items :center
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:top 0})
|
||||||
|
|
||||||
|
(defn tooltip-animated [bottom-value opacity-value]
|
||||||
|
{:position :absolute
|
||||||
|
:align-items :center
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:bottom bottom-value
|
||||||
|
:opacity opacity-value})
|
||||||
|
|
||||||
|
(def tooltip-text-container
|
||||||
|
{:padding-horizontal 16
|
||||||
|
:padding-vertical 9
|
||||||
|
:background-color :white
|
||||||
|
:border-radius 8})
|
||||||
|
|
||||||
|
(def tooltip-text
|
||||||
|
{:color styles/color-red-2
|
||||||
|
:font-size 15})
|
||||||
|
|
||||||
|
(def tooltip-triangle
|
||||||
|
{:width 16
|
||||||
|
:height 8
|
||||||
|
:viewBox "0 0 16 8"})
|
||||||
|
|
||||||
|
(def recipient-name-container
|
||||||
|
{:padding-right 6})
|
|
@ -1,29 +1,48 @@
|
||||||
(ns status-im.ui.screens.wallet.components.views
|
(ns status-im.ui.screens.wallet.components.views
|
||||||
(:require-macros [status-im.utils.views :as views])
|
(:require-macros [status-im.utils.views :as views])
|
||||||
(:require [status-im.components.react :as react]
|
(:require [status-im.components.react :as react]
|
||||||
|
[status-im.components.styles :as components.styles]
|
||||||
[status-im.ui.screens.wallet.components.styles :as styles]
|
[status-im.ui.screens.wallet.components.styles :as styles]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[reagent.core :as reagent]))
|
[reagent.core :as reagent]
|
||||||
|
[status-im.components.icons.vector-icons :as vector-icons]
|
||||||
|
[status-im.components.animation :as animation]
|
||||||
|
[status-im.utils.platform :as platform]
|
||||||
|
[status-im.ui.screens.wallet.components.animations :as animations]))
|
||||||
|
|
||||||
|
(views/defview tooltip [label & [style]]
|
||||||
|
(views/letsubs [bottom-value (animation/create-value 16)
|
||||||
|
opacity-value (animation/create-value 0)]
|
||||||
|
{:component-did-mount (animations/animate-tooltip bottom-value opacity-value)}
|
||||||
|
[react/view styles/tooltip-container
|
||||||
|
[react/animated-view {:style (merge (styles/tooltip-animated bottom-value opacity-value) style)}
|
||||||
|
[react/view styles/tooltip-text-container
|
||||||
|
[react/text {:style styles/tooltip-text} label]]
|
||||||
|
[vector-icons/icon :icons/tooltip-triangle {:color :white :style styles/tooltip-triangle}]]]))
|
||||||
|
|
||||||
|
(defn amount-input []
|
||||||
|
(let [active? (reagent/atom false)]
|
||||||
|
(fn [& [{:keys [input-options style error]}]]
|
||||||
|
(let [{:keys [on-focus on-blur]} input-options]
|
||||||
|
[react/view components.styles/flex
|
||||||
|
[react/text {:style styles/label} (i18n/label :t/amount)]
|
||||||
|
[react/view styles/amount-text-input-container
|
||||||
|
[react/view (merge (styles/amount-container @active?) style)
|
||||||
|
[react/text-input
|
||||||
|
(merge
|
||||||
|
{:keyboard-type :numeric
|
||||||
|
:placeholder "0.000"
|
||||||
|
:placeholder-text-color "#ffffff66"
|
||||||
|
:selection-color :white
|
||||||
|
:style styles/text-input
|
||||||
|
:on-focus #(do (reset! active? true)
|
||||||
|
(when on-focus (on-focus)))
|
||||||
|
:on-blur #(do (reset! active? false)
|
||||||
|
(when on-blur (on-blur)))}
|
||||||
|
(dissoc input-options :on-focus :on-blur))]]
|
||||||
|
(when-not (nil? error)
|
||||||
|
[tooltip error])]]))))
|
||||||
|
|
||||||
(defn amount-input [& [{:keys [input-options style]}]]
|
|
||||||
(let [active? (reagent/atom false)
|
|
||||||
{:keys [on-focus on-blur]} input-options]
|
|
||||||
(fn []
|
|
||||||
[react/view {:flex 1}
|
|
||||||
[react/text {:style styles/label} (i18n/label :t/amount)]
|
|
||||||
[react/view (merge (styles/amount-container @active?) style)
|
|
||||||
[react/text-input
|
|
||||||
(merge
|
|
||||||
{:keyboard-type :numeric
|
|
||||||
:placeholder "0.000"
|
|
||||||
:placeholder-text-color "#ffffff66"
|
|
||||||
:selection-color :white
|
|
||||||
:style styles/text-input
|
|
||||||
:on-focus #(do (reset! active? true)
|
|
||||||
(when on-focus (on-focus)))
|
|
||||||
:on-blur #(do (reset! active? false)
|
|
||||||
(when on-blur (on-blur)))}
|
|
||||||
(dissoc input-options :on-focus :on-blur))]]])))
|
|
||||||
|
|
||||||
;;TODO (andrey) this should be choose component with the list of currencies
|
;;TODO (andrey) this should be choose component with the list of currencies
|
||||||
(defn choose-currency [& [style]]
|
(defn choose-currency [& [style]]
|
||||||
|
@ -33,6 +52,25 @@
|
||||||
style)
|
style)
|
||||||
[react/text {:style styles/wallet-name} "ETH"]]])
|
[react/text {:style styles/wallet-name} "ETH"]]])
|
||||||
|
|
||||||
|
(defn choose-recipient [{:keys [address name on-press style]}]
|
||||||
|
(let [address? (and (not (nil? address)) (not= address ""))]
|
||||||
|
[react/touchable-highlight {:on-press on-press}
|
||||||
|
[react/view
|
||||||
|
[react/text {:style styles/label} (i18n/label :t/recipient)]
|
||||||
|
[react/view (merge styles/recipient-container
|
||||||
|
style)
|
||||||
|
(when name
|
||||||
|
[react/view styles/recipient-name-container
|
||||||
|
[react/text {:style (styles/participant true)
|
||||||
|
:number-of-lines 1}
|
||||||
|
name]])
|
||||||
|
[react/view components.styles/flex
|
||||||
|
[react/text {:style (styles/participant (and (not name) address?))
|
||||||
|
:number-of-lines 1
|
||||||
|
:ellipsizeMode :middle}
|
||||||
|
(if address? address "Choose recipient...")]]
|
||||||
|
[vector-icons/icon :icons/forward {:color :white}]]]]))
|
||||||
|
|
||||||
;;TODO (andrey) this should be choose component with the list of wallets
|
;;TODO (andrey) this should be choose component with the list of wallets
|
||||||
(views/defview choose-wallet [& [style]]
|
(views/defview choose-wallet [& [style]]
|
||||||
(views/letsubs [eth-balance [:eth-balance]]
|
(views/letsubs [eth-balance [:eth-balance]]
|
||||||
|
@ -41,10 +79,21 @@
|
||||||
[react/view (merge styles/wallet-container
|
[react/view (merge styles/wallet-container
|
||||||
style)
|
style)
|
||||||
[react/text {:style styles/wallet-name} "Main wallet"]
|
[react/text {:style styles/wallet-name} "Main wallet"]
|
||||||
[react/text {:style styles/wallet-value} (str eth-balance " ETH")]]]))
|
[react/text {:style styles/wallet-value
|
||||||
|
:number-of-lines 1
|
||||||
|
:ellipsizeMode :middle}
|
||||||
|
(str eth-balance " ETH")]]]))
|
||||||
|
|
||||||
(defn network-label
|
(defn network-label
|
||||||
([n] (network-label [{} n]))
|
([n] (network-label [{} n]))
|
||||||
([style n] [react/view (merge styles/network-container
|
([style n] [react/view (merge styles/network-container
|
||||||
style)
|
style)
|
||||||
[react/text {:style styles/network} n]]))
|
[react/text {:style styles/network} n]]))
|
||||||
|
|
||||||
|
(defn separator []
|
||||||
|
[react/view styles/separator])
|
||||||
|
|
||||||
|
(defn button-text [label]
|
||||||
|
[react/text {:style styles/button-text
|
||||||
|
:font (if platform/android? :medium :default)
|
||||||
|
:uppercase? (get-in platform/platform-specific [:uppercase?])} label])
|
|
@ -1,6 +1,10 @@
|
||||||
(ns status-im.ui.screens.wallet.db
|
(ns status-im.ui.screens.wallet.db
|
||||||
(:require [cljs.spec.alpha :as spec]
|
(:require [cljs.spec.alpha :as spec]
|
||||||
status-im.ui.screens.wallet.request.db))
|
status-im.ui.screens.wallet.request.db
|
||||||
|
status-im.ui.screens.wallet.send.db
|
||||||
|
[status-im.i18n :as i18n]
|
||||||
|
[clojure.string :as string]))
|
||||||
|
|
||||||
;; (angusiguess) If we add more error types we can treat them as 'one-of' the following
|
;; (angusiguess) If we add more error types we can treat them as 'one-of' the following
|
||||||
(spec/def :wallet/error #{:error})
|
(spec/def :wallet/error #{:error})
|
||||||
|
|
||||||
|
@ -15,3 +19,20 @@
|
||||||
|
|
||||||
;; TODO(oskarth): spec for balance as BigNumber
|
;; TODO(oskarth): spec for balance as BigNumber
|
||||||
;; TODO(oskarth): Spec for prices as as: {:from ETH, :to USD, :price 290.11, :last-day 304.17}
|
;; TODO(oskarth): Spec for prices as as: {:from ETH, :to USD, :price 290.11, :last-day 304.17}
|
||||||
|
|
||||||
|
(defn get-amount-validation-error [amount web3]
|
||||||
|
(let [amount' (string/replace amount #"," ".")
|
||||||
|
amount-splited (string/split amount' #"[.]")]
|
||||||
|
(cond
|
||||||
|
(or (nil? amount) (= amount "") (= amount "0") (re-matches #"0[,.]0*$" amount))
|
||||||
|
nil
|
||||||
|
|
||||||
|
(or (js/isNaN (js/parseFloat amount'))
|
||||||
|
(try (when (<= (.toWei web3 amount' "ether") 0) true)
|
||||||
|
(catch :default err true)))
|
||||||
|
(i18n/label :t/validation-amount-invalid-number)
|
||||||
|
|
||||||
|
(and (= (count amount-splited) 2) (> (count (last amount-splited)) 18))
|
||||||
|
(i18n/label :t/validation-amount-is-too-precise)
|
||||||
|
|
||||||
|
:else nil)))
|
|
@ -3,9 +3,6 @@
|
||||||
(:require [status-im.components.styles :as styles]
|
(:require [status-im.components.styles :as styles]
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
(def wallet-container
|
|
||||||
{:flex 1})
|
|
||||||
|
|
||||||
(def error-container
|
(def error-container
|
||||||
{:align-self :center
|
{:align-self :center
|
||||||
:justify-content :center
|
:justify-content :center
|
||||||
|
@ -19,12 +16,9 @@
|
||||||
:padding-right 10
|
:padding-right 10
|
||||||
:font-size 13})
|
:font-size 13})
|
||||||
|
|
||||||
(def toolbar
|
|
||||||
{:background-color (if platform/ios? styles/color-blue4 styles/color-blue5)
|
|
||||||
:elevation 0})
|
|
||||||
|
|
||||||
(def toolbar-title-container
|
(def toolbar-title-container
|
||||||
{:flex-direction :row})
|
{:flex-direction :row
|
||||||
|
:padding-left 24})
|
||||||
|
|
||||||
(def toolbar-title-text
|
(def toolbar-title-text
|
||||||
{:color styles/color-white
|
{:color styles/color-white
|
||||||
|
@ -59,21 +53,21 @@
|
||||||
:color styles/color-white})
|
:color styles/color-white})
|
||||||
|
|
||||||
(defstyle total-balance-currency
|
(defstyle total-balance-currency
|
||||||
{:font-size 37
|
{:font-size 37
|
||||||
:margin-left 9
|
:margin-left 9
|
||||||
:color styles/color-white-transparent-5
|
:color styles/color-white-transparent-5
|
||||||
:android {:letter-spacing 1.5}
|
:android {:letter-spacing 1.5}
|
||||||
:ios {:letter-spacing 1.16}})
|
:ios {:letter-spacing 1.16}})
|
||||||
|
|
||||||
(def value-variation
|
(def value-variation
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
:align-items :center})
|
:align-items :center})
|
||||||
|
|
||||||
(defstyle value-variation-title
|
(defstyle value-variation-title
|
||||||
{:font-size 14
|
{:font-size 14
|
||||||
:color styles/color-white-transparent-6
|
:color styles/color-white-transparent-6
|
||||||
:android {:letter-spacing -0.18}
|
:android {:letter-spacing -0.18}
|
||||||
:ios {:letter-spacing -0.2}})
|
:ios {:letter-spacing -0.2}})
|
||||||
|
|
||||||
(def today-variation-container
|
(def today-variation-container
|
||||||
{:border-radius 100
|
{:border-radius 100
|
||||||
|
@ -101,9 +95,9 @@
|
||||||
{:color styles/color-red-4}))
|
{:color styles/color-red-4}))
|
||||||
|
|
||||||
(defstyle buttons
|
(defstyle buttons
|
||||||
{:margin-top 34
|
{:margin-top 34
|
||||||
:android {:margin-horizontal 21}
|
:android {:margin-horizontal 21}
|
||||||
:ios {:margin-horizontal 29}})
|
:ios {:margin-horizontal 29}})
|
||||||
|
|
||||||
(defstyle main-button-text
|
(defstyle main-button-text
|
||||||
{:padding-vertical 13
|
{:padding-vertical 13
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
[status-im.components.drawer.view :as drawer]
|
[status-im.components.drawer.view :as drawer]
|
||||||
[status-im.components.list.views :as list]
|
[status-im.components.list.views :as list]
|
||||||
[status-im.components.react :as react]
|
[status-im.components.react :as react]
|
||||||
[status-im.components.styles :as styles]
|
|
||||||
[status-im.components.icons.vector-icons :as vi]
|
[status-im.components.icons.vector-icons :as vi]
|
||||||
[status-im.components.toolbar-new.view :as toolbar]
|
[status-im.components.toolbar-new.view :as toolbar]
|
||||||
[status-im.components.toolbar-new.actions :as act]
|
[status-im.components.toolbar-new.actions :as act]
|
||||||
|
@ -15,7 +14,9 @@
|
||||||
[status-im.utils.config :as config]
|
[status-im.utils.config :as config]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
[status-im.ui.screens.wallet.main.styles :as wallet.styles]
|
[status-im.ui.screens.wallet.main.styles :as styles]
|
||||||
|
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||||
|
[status-im.components.styles :as components.styles]
|
||||||
[status-im.ui.screens.wallet.views :as wallet.views]))
|
[status-im.ui.screens.wallet.views :as wallet.views]))
|
||||||
|
|
||||||
(defn- show-not-implemented! []
|
(defn- show-not-implemented! []
|
||||||
|
@ -23,18 +24,18 @@
|
||||||
|
|
||||||
(defn toolbar-title []
|
(defn toolbar-title []
|
||||||
[react/touchable-highlight {:on-press #(rf/dispatch [:navigate-to :wallet-list])}
|
[react/touchable-highlight {:on-press #(rf/dispatch [:navigate-to :wallet-list])}
|
||||||
[react/view {:style wallet.styles/toolbar-title-container}
|
[react/view {:style styles/toolbar-title-container}
|
||||||
[react/text {:style wallet.styles/toolbar-title-text
|
[react/text {:style styles/toolbar-title-text
|
||||||
:font :toolbar-title}
|
:font :toolbar-title}
|
||||||
(i18n/label :t/main-wallet)]
|
(i18n/label :t/main-wallet)]
|
||||||
[vi/icon
|
[vi/icon
|
||||||
:icons/dropdown
|
:icons/dropdown
|
||||||
{:container-style wallet.styles/toolbar-title-icon
|
{:container-style styles/toolbar-title-icon
|
||||||
:color :white}]]])
|
:color :white}]]])
|
||||||
|
|
||||||
(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"}} styles/toolbar-icon)
|
||||||
:handler #(rf/dispatch [:navigate-to :wallet-transactions])})
|
:handler #(rf/dispatch [:navigate-to :wallet-transactions])})
|
||||||
|
|
||||||
(defn toolbar-view []
|
(defn toolbar-view []
|
||||||
|
@ -49,27 +50,27 @@
|
||||||
(defn- change-display [change]
|
(defn- change-display [change]
|
||||||
(let [pos-change? (or (pos? change) (zero? change))]
|
(let [pos-change? (or (pos? change) (zero? change))]
|
||||||
[react/view {:style (if pos-change?
|
[react/view {:style (if pos-change?
|
||||||
wallet.styles/today-variation-container-positive
|
styles/today-variation-container-positive
|
||||||
wallet.styles/today-variation-container-negative)}
|
styles/today-variation-container-negative)}
|
||||||
[react/text {:style (if pos-change?
|
[react/text {:style (if pos-change?
|
||||||
wallet.styles/today-variation-positive
|
styles/today-variation-positive
|
||||||
wallet.styles/today-variation-negative)}
|
styles/today-variation-negative)}
|
||||||
(if change
|
(if change
|
||||||
(str (when pos-change? "+") change "%")
|
(str (when pos-change? "+") change "%")
|
||||||
"-%")]]))
|
"-%")]]))
|
||||||
|
|
||||||
(defn main-section [usd-value change error-message]
|
(defn main-section [usd-value change error-message]
|
||||||
[react/view {:style wallet.styles/main-section}
|
[react/view {:style styles/main-section}
|
||||||
(when error-message [wallet.views/error-message-view wallet.styles/error-container wallet.styles/error-message])
|
(when error-message [wallet.views/error-message-view styles/error-container styles/error-message])
|
||||||
[react/view {:style wallet.styles/total-balance-container}
|
[react/view {:style styles/total-balance-container}
|
||||||
[react/view {:style wallet.styles/total-balance}
|
[react/view {:style styles/total-balance}
|
||||||
[react/text {:style wallet.styles/total-balance-value} usd-value]
|
[react/text {:style styles/total-balance-value} usd-value]
|
||||||
[react/text {:style wallet.styles/total-balance-currency} "USD"]]
|
[react/text {:style styles/total-balance-currency} "USD"]]
|
||||||
[react/view {:style wallet.styles/value-variation}
|
[react/view {:style styles/value-variation}
|
||||||
[react/text {:style wallet.styles/value-variation-title}
|
[react/text {:style styles/value-variation-title}
|
||||||
(i18n/label :t/wallet-total-value)]
|
(i18n/label :t/wallet-total-value)]
|
||||||
[change-display change]]
|
[change-display change]]
|
||||||
[btn/buttons {:style wallet.styles/buttons :button-text-style wallet.styles/main-button-text}
|
[btn/buttons {:style styles/buttons :button-text-style styles/main-button-text}
|
||||||
[{:text (i18n/label :t/wallet-send)
|
[{:text (i18n/label :t/wallet-send)
|
||||||
:on-press #(do (rf/dispatch [:navigate-to :wallet-send-transaction])
|
:on-press #(do (rf/dispatch [:navigate-to :wallet-send-transaction])
|
||||||
(when platform/android?
|
(when platform/android?
|
||||||
|
@ -83,15 +84,15 @@
|
||||||
|
|
||||||
(defn- token->image [id]
|
(defn- token->image [id]
|
||||||
(case id
|
(case id
|
||||||
"eth" {:source (:ethereum resources/assets) :style (wallet.styles/asset-border styles/color-gray-transparent-light)}))
|
"eth" {:source (:ethereum resources/assets) :style (styles/asset-border components.styles/color-gray-transparent-light)}))
|
||||||
|
|
||||||
(defn add-asset []
|
(defn add-asset []
|
||||||
[list/touchable-item show-not-implemented!
|
[list/touchable-item show-not-implemented!
|
||||||
[react/view
|
[react/view
|
||||||
[list/item
|
[list/item
|
||||||
[list/item-icon {:icon :icons/add :style wallet.styles/add-asset-icon :icon-opts {:color :blue}}]
|
[list/item-icon {:icon :icons/add :style styles/add-asset-icon :icon-opts {:color :blue}}]
|
||||||
[react/view {:style wallet.styles/asset-item-value-container}
|
[react/view {:style styles/asset-item-value-container}
|
||||||
[react/text {:style wallet.styles/add-asset-text}
|
[react/text {:style styles/add-asset-text}
|
||||||
(i18n/label :t/wallet-add-asset)]]]]])
|
(i18n/label :t/wallet-add-asset)]]]]])
|
||||||
|
|
||||||
(defn render-asset [{:keys [id currency amount]}]
|
(defn render-asset [{:keys [id currency amount]}]
|
||||||
|
@ -101,9 +102,9 @@
|
||||||
[react/view
|
[react/view
|
||||||
[list/item
|
[list/item
|
||||||
[list/item-image {:uri :launch_logo}]
|
[list/item-image {:uri :launch_logo}]
|
||||||
[react/view {:style wallet.styles/asset-item-value-container}
|
[react/view {:style styles/asset-item-value-container}
|
||||||
[react/text {:style wallet.styles/asset-item-value} (str amount)]
|
[react/text {:style styles/asset-item-value} (str amount)]
|
||||||
[react/text {:style wallet.styles/asset-item-currency
|
[react/text {:style styles/asset-item-currency
|
||||||
:uppercase? true}
|
:uppercase? true}
|
||||||
id]]
|
id]]
|
||||||
[list/item-icon {:icon :icons/forward}]]]]
|
[list/item-icon {:icon :icons/forward}]]]]
|
||||||
|
@ -112,17 +113,17 @@
|
||||||
[list/item
|
[list/item
|
||||||
(let [{:keys [source style]} (token->image id)]
|
(let [{:keys [source style]} (token->image id)]
|
||||||
[list/item-image source style])
|
[list/item-image source style])
|
||||||
[react/view {:style wallet.styles/asset-item-value-container}
|
[react/view {:style styles/asset-item-value-container}
|
||||||
[react/text {:style wallet.styles/asset-item-value} (str amount)]
|
[react/text {:style styles/asset-item-value} (str amount)]
|
||||||
[react/text {:style wallet.styles/asset-item-currency
|
[react/text {:style styles/asset-item-currency
|
||||||
:uppercase? true}
|
:uppercase? true}
|
||||||
id]]]]
|
id]]]]
|
||||||
[add-asset]))
|
[add-asset]))
|
||||||
|
|
||||||
(defn asset-section [eth prices-loading? balance-loading?]
|
(defn asset-section [eth prices-loading? balance-loading?]
|
||||||
(let [assets [{:id "eth" :currency :eth :amount eth}]]
|
(let [assets [{:id "eth" :currency :eth :amount eth}]]
|
||||||
[react/view {:style wallet.styles/asset-section}
|
[react/view {:style styles/asset-section}
|
||||||
[react/text {:style wallet.styles/asset-section-title} (i18n/label :t/wallet-assets)]
|
[react/text {:style styles/asset-section-title} (i18n/label :t/wallet-assets)]
|
||||||
[list/flat-list
|
[list/flat-list
|
||||||
{:data (conj assets {}) ;; Extra map triggers rendering for add-asset
|
{:data (conj assets {}) ;; Extra map triggers rendering for add-asset
|
||||||
:render-fn render-asset
|
:render-fn render-asset
|
||||||
|
@ -138,6 +139,6 @@
|
||||||
error-message [:wallet/error-message?]]
|
error-message [:wallet/error-message?]]
|
||||||
[react/view {:style wallet.styles/wallet-container}
|
[react/view {:style wallet.styles/wallet-container}
|
||||||
[toolbar-view]
|
[toolbar-view]
|
||||||
[react/view {:style styles/flex}
|
[react/view components.styles/flex
|
||||||
[main-section portfolio-value portfolio-change error-message]
|
[main-section portfolio-value portfolio-change error-message]
|
||||||
[asset-section eth-balance prices-loading? balance-loading?]]]))
|
[asset-section eth-balance prices-loading? balance-loading?]]]))
|
||||||
|
|
|
@ -15,3 +15,9 @@
|
||||||
(defmethod navigation/preload-data! :wallet-request-transaction
|
(defmethod navigation/preload-data! :wallet-request-transaction
|
||||||
[db _]
|
[db _]
|
||||||
(dissoc db :wallet/request-transaction))
|
(dissoc db :wallet/request-transaction))
|
||||||
|
|
||||||
|
(defmethod navigation/preload-data! :wallet-send-transaction
|
||||||
|
[db [event]]
|
||||||
|
(if (= event :navigate-back)
|
||||||
|
db
|
||||||
|
(dissoc db :wallet/send-transaction)))
|
|
@ -3,6 +3,7 @@
|
||||||
(:require [cljs.spec.alpha :as spec]))
|
(:require [cljs.spec.alpha :as spec]))
|
||||||
|
|
||||||
(spec/def ::amount (spec/nilable string?))
|
(spec/def ::amount (spec/nilable string?))
|
||||||
|
(spec/def ::amount-error (spec/nilable string?))
|
||||||
|
|
||||||
(spec/def :wallet/request-transaction (allowed-keys
|
(spec/def :wallet/request-transaction (allowed-keys
|
||||||
:opt-un [::amount]))
|
:opt-un [::amount ::amount-error]))
|
|
@ -1,7 +1,7 @@
|
||||||
(ns status-im.ui.screens.wallet.request.events
|
(ns status-im.ui.screens.wallet.request.events
|
||||||
(:require
|
(:require
|
||||||
[re-frame.core :as re-frame :refer [dispatch reg-fx]]
|
[status-im.utils.handlers :as handlers]
|
||||||
[status-im.utils.handlers :as handlers]))
|
[status-im.ui.screens.wallet.db :as wallet.db]))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:wallet-send-request
|
:wallet-send-request
|
||||||
|
@ -10,4 +10,11 @@
|
||||||
[:navigate-to-clean :chat-list]
|
[:navigate-to-clean :chat-list]
|
||||||
[:chat-with-command whisper-identity :request
|
[:chat-with-command whisper-identity :request
|
||||||
{:contact contact
|
{:contact contact
|
||||||
:amount (:amount request-transaction)}]]}))
|
:amount (:amount request-transaction)}]]}))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:wallet-validate-request-amount
|
||||||
|
(fn [{{:keys [web3] :wallet/keys [request-transaction] :as db} :db} _]
|
||||||
|
(let [amount (:amount request-transaction)
|
||||||
|
error (wallet.db/get-amount-validation-error amount web3)]
|
||||||
|
{:db (assoc-in db [:wallet/request-transaction :amount-error] error)})))
|
|
@ -1,9 +1,6 @@
|
||||||
(ns status-im.ui.screens.wallet.request.styles
|
(ns status-im.ui.screens.wallet.request.styles
|
||||||
(:require [status-im.components.styles :as styles]))
|
(:require [status-im.components.styles :as styles]))
|
||||||
|
|
||||||
(def main-container
|
|
||||||
{:flex 1})
|
|
||||||
|
|
||||||
(def network-label
|
(def network-label
|
||||||
{:margin-top 27})
|
{:margin-top 27})
|
||||||
|
|
||||||
|
@ -14,44 +11,5 @@
|
||||||
(def qr-container
|
(def qr-container
|
||||||
{:margin-top 16})
|
{:margin-top 16})
|
||||||
|
|
||||||
(def choose-wallet-container
|
|
||||||
{:margin-top 27
|
|
||||||
:margin-horizontal 15})
|
|
||||||
|
|
||||||
(def amount-container
|
|
||||||
{:margin-top 16
|
|
||||||
:margin-horizontal 15
|
|
||||||
:flex-direction :row})
|
|
||||||
|
|
||||||
(def choose-currency-container
|
|
||||||
{:margin-left 8})
|
|
||||||
|
|
||||||
(def choose-currency
|
|
||||||
{:width 116})
|
|
||||||
|
|
||||||
(def separator
|
|
||||||
{:height 1
|
|
||||||
:margin-horizontal 15
|
|
||||||
:background-color styles/color-white-transparent-1
|
|
||||||
:margin-top 16})
|
|
||||||
|
|
||||||
(def buttons-container
|
|
||||||
{:margin-vertical 15
|
|
||||||
:padding-horizontal 12
|
|
||||||
:flex-direction :row
|
|
||||||
:align-items :center})
|
|
||||||
|
|
||||||
(def share-icon-container
|
(def share-icon-container
|
||||||
{:margin-right 8})
|
{:margin-right 8})
|
||||||
|
|
||||||
(def forward-icon-container
|
|
||||||
{:margin-left 8})
|
|
||||||
|
|
||||||
(def button-text
|
|
||||||
{:color :white
|
|
||||||
:font-size 15
|
|
||||||
:letter-spacing -0.2})
|
|
||||||
|
|
||||||
(def button-container
|
|
||||||
{:flex-direction :row
|
|
||||||
:align-items :center})
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
(ns status-im.ui.screens.wallet.request.subs
|
||||||
|
(:require [re-frame.core :as re-frame]))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:wallet.request/request-enabled?
|
||||||
|
:<- [:get-in [:wallet/request-transaction :amount]]
|
||||||
|
:<- [:get-in [:wallet/request-transaction :amount-error]]
|
||||||
|
(fn [[amount amount-error]]
|
||||||
|
(and
|
||||||
|
(nil? amount-error)
|
||||||
|
(not (nil? amount)) (not= amount ""))))
|
|
@ -7,7 +7,7 @@
|
||||||
[status-im.components.toolbar-new.actions :as actions]
|
[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.components.status-bar :as status-bar]
|
[status-im.components.status-bar :as status-bar]
|
||||||
[status-im.ui.screens.wallet.send.styles :as wallet-styles]
|
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||||
[status-im.components.icons.vector-icons :as vi]
|
[status-im.components.icons.vector-icons :as vi]
|
||||||
[status-im.ui.screens.wallet.components.views :as components]
|
[status-im.ui.screens.wallet.components.views :as components]
|
||||||
[status-im.ui.screens.wallet.request.styles :as styles]
|
[status-im.ui.screens.wallet.request.styles :as styles]
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
(defn toolbar-view []
|
(defn toolbar-view []
|
||||||
[toolbar/toolbar2 {:style wallet-styles/toolbar :hide-border? true}
|
[toolbar/toolbar2 {:style wallet.styles/toolbar :hide-border? true}
|
||||||
[toolbar/nav-button (actions/back-white actions/default-handler)]
|
[toolbar/nav-button (actions/back-white actions/default-handler)]
|
||||||
[toolbar/content-title {:color :white} (i18n/label :t/request-transaction)]])
|
[toolbar/content-title {:color :white} (i18n/label :t/request-transaction)]])
|
||||||
|
|
||||||
|
@ -36,41 +36,40 @@
|
||||||
:fgColor "#4360df"
|
:fgColor "#4360df"
|
||||||
:size 256}]))
|
:size 256}]))
|
||||||
|
|
||||||
(defn button-text [label]
|
|
||||||
[react/text {:style styles/button-text
|
|
||||||
:font (if platform/android? :medium :default)
|
|
||||||
:uppercase? (get-in platform/platform-specific [:uppercase?])} label])
|
|
||||||
|
|
||||||
(views/defview request-transaction []
|
(views/defview request-transaction []
|
||||||
;;Because input field is in the end of view we will scroll to the end on input focus event
|
;;Because input field is in the end of view we will scroll to the end on input focus event
|
||||||
(views/letsubs [scroll (atom nil)]
|
(views/letsubs [amount-error [:get-in [:wallet/request-transaction :amount-error]]
|
||||||
[react/keyboard-avoiding-view wallet-styles/wallet-modal-container
|
request-enabled? [:wallet.request/request-enabled?]
|
||||||
|
scroll (atom nil)]
|
||||||
|
[react/keyboard-avoiding-view wallet.styles/wallet-modal-container
|
||||||
[status-bar/status-bar {:type :wallet}]
|
[status-bar/status-bar {:type :wallet}]
|
||||||
[toolbar-view]
|
[toolbar-view]
|
||||||
[react/scroll-view {:ref #(reset! scroll %)}
|
[react/scroll-view {:ref #(reset! scroll %)}
|
||||||
[react/view styles/main-container
|
[react/view components.styles/flex
|
||||||
[react/view styles/network-container
|
[react/view styles/network-container
|
||||||
;;TODO (andrey) name of active network should be used
|
;;TODO (andrey) name of active network should be used
|
||||||
[components/network-label styles/network-label "Testnet"]
|
[components/network-label styles/network-label "Testnet"]
|
||||||
[react/view styles/qr-container
|
[react/view styles/qr-container
|
||||||
[qr-code]]]
|
[qr-code]]]
|
||||||
[react/view styles/choose-wallet-container
|
[react/view wallet.styles/choose-wallet-container
|
||||||
[components/choose-wallet]]
|
[components/choose-wallet]]
|
||||||
[react/view styles/amount-container
|
[react/view wallet.styles/amount-container
|
||||||
[components/amount-input
|
[components/amount-input
|
||||||
{:input-options {:on-focus (fn [] (when @scroll (js/setTimeout #(.scrollToEnd @scroll) 100)))
|
{:error amount-error
|
||||||
|
:input-options {:on-focus (fn [] (when @scroll (js/setTimeout #(.scrollToEnd @scroll) 100)))
|
||||||
:on-change-text
|
:on-change-text
|
||||||
#(re-frame/dispatch [:set-in [:wallet/request-transaction :amount] %])}}]
|
#(do (re-frame/dispatch [:set-in [:wallet/request-transaction :amount] %])
|
||||||
[react/view styles/choose-currency-container
|
(re-frame/dispatch [:wallet-validate-request-amount]))}}]
|
||||||
[components/choose-currency styles/choose-currency]]]]]
|
[react/view wallet.styles/choose-currency-container
|
||||||
[react/view styles/separator]
|
[components/choose-currency wallet.styles/choose-currency]]]]]
|
||||||
[react/view styles/buttons-container
|
[components/separator]
|
||||||
|
[react/view wallet.styles/buttons-container
|
||||||
[react/touchable-highlight {:on-press #()}
|
[react/touchable-highlight {:on-press #()}
|
||||||
[react/view styles/button-container
|
[react/view (wallet.styles/button-container false)
|
||||||
[vi/icon :icons/share {:color :white :container-style styles/share-icon-container}]
|
[vi/icon :icons/share {:color :white :container-style styles/share-icon-container}]
|
||||||
[button-text (i18n/label :t/share)]]]
|
[components/button-text (i18n/label :t/share)]]]
|
||||||
[react/view components.styles/flex]
|
[react/view components.styles/flex]
|
||||||
[react/touchable-highlight {:on-press send-request}
|
[react/touchable-highlight {:on-press (when request-enabled? send-request)}
|
||||||
[react/view styles/button-container
|
[react/view (wallet.styles/button-container request-enabled?)
|
||||||
[button-text (i18n/label :t/send-request)]
|
[components/button-text (i18n/label :t/send-request)]
|
||||||
[vi/icon :icons/forward {:color :white :container-style styles/forward-icon-container}]]]]]))
|
[vi/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]]))
|
|
@ -0,0 +1,11 @@
|
||||||
|
(ns status-im.ui.screens.wallet.send.animations
|
||||||
|
(:require [status-im.components.animation :as animation]))
|
||||||
|
|
||||||
|
(defn animate-sign-panel [opacity-value bottom-value]
|
||||||
|
(animation/start
|
||||||
|
(animation/parallel
|
||||||
|
[(animation/timing opacity-value {:toValue 1
|
||||||
|
:duration 500})
|
||||||
|
(animation/timing bottom-value {:toValue 53
|
||||||
|
:easing (.bezier animation/easing 0.685, 0.000, 0.025, 1.185)
|
||||||
|
:duration 500})])))
|
|
@ -0,0 +1,17 @@
|
||||||
|
(ns status-im.ui.screens.wallet.send.db
|
||||||
|
(:require-macros [status-im.utils.db :refer [allowed-keys]])
|
||||||
|
(:require [cljs.spec.alpha :as spec]))
|
||||||
|
|
||||||
|
(spec/def ::amount (spec/nilable string?))
|
||||||
|
(spec/def ::to-address (spec/nilable string?))
|
||||||
|
(spec/def ::to-name (spec/nilable string?))
|
||||||
|
(spec/def ::amount-error (spec/nilable string?))
|
||||||
|
(spec/def ::password (spec/nilable string?))
|
||||||
|
(spec/def ::transaction-id (spec/nilable string?))
|
||||||
|
(spec/def ::waiting-signal? (spec/nilable boolean?))
|
||||||
|
(spec/def ::signing? (spec/nilable boolean?))
|
||||||
|
(spec/def ::later? (spec/nilable boolean?))
|
||||||
|
|
||||||
|
(spec/def :wallet/send-transaction (allowed-keys
|
||||||
|
:opt-un [::amount ::to-address ::to-name ::amount-error ::password
|
||||||
|
::waiting-signal? ::signing? ::transaction-id ::later?]))
|
|
@ -1,8 +1,123 @@
|
||||||
(ns status-im.ui.screens.wallet.send.events
|
(ns status-im.ui.screens.wallet.send.events
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[status-im.ui.screens.wallet.db :as wallet.db]))
|
[status-im.utils.handlers :as handlers]
|
||||||
|
[status-im.ui.screens.wallet.db :as wallet.db]
|
||||||
|
[status-im.native-module.core :as status]
|
||||||
|
[status-im.utils.types :as types]
|
||||||
|
[clojure.string :as string]
|
||||||
|
[status-im.utils.money :as money]
|
||||||
|
[status-im.utils.utils :as utils]
|
||||||
|
[status-im.i18n :as i18n]))
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
;;;; FX
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
::accept-transaction
|
||||||
|
(fn [{:keys [password id on-completed]}]
|
||||||
|
(status/complete-transactions (list id) password on-completed)))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
::send-transaction
|
||||||
|
(fn [{:keys [web3] :as params}]
|
||||||
|
(when web3
|
||||||
|
(.sendTransaction
|
||||||
|
(.-eth web3)
|
||||||
|
(clj->js (select-keys params [:from :to :value]))
|
||||||
|
#()))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
::show-transaction-moved
|
||||||
|
(fn []
|
||||||
|
(utils/show-popup (i18n/label :t/transaction-moved-title) (i18n/label :t/transaction-moved-text))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
::discard-transaction
|
||||||
|
(fn [id]
|
||||||
|
(status/discard-transaction id)))
|
||||||
|
|
||||||
|
;;;; Handlers
|
||||||
|
|
||||||
|
(handlers/register-handler-db
|
||||||
:choose-recipient
|
:choose-recipient
|
||||||
(fn [db [_ recipient]]
|
(fn [db [_ recipient]]
|
||||||
(assoc-in db [:wallet :send :recipient] recipient)))
|
(assoc-in db [:wallet :send :recipient] recipient)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:wallet-open-send-transaction
|
||||||
|
(fn [{db :db} [_ address name]]
|
||||||
|
{:db (update db :wallet/send-transaction
|
||||||
|
#(assoc % :to-address address
|
||||||
|
:to-name name))
|
||||||
|
:dispatch-n [[:navigate-back]
|
||||||
|
[:navigate-back]]}))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:wallet-validate-amount
|
||||||
|
(fn [{{:keys [web3] :wallet/keys [send-transaction] :as db} :db} _]
|
||||||
|
(let [amount (:amount send-transaction)
|
||||||
|
error (wallet.db/get-amount-validation-error amount web3)]
|
||||||
|
{:db (assoc-in db [:wallet/send-transaction :amount-error] error)})))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
::transaction-completed
|
||||||
|
(fn [{db :db} [_ {:keys [id response]}]]
|
||||||
|
(let [{:keys [hash error]} response]
|
||||||
|
(when-not (and error (string? error) (not (string/blank? error)))
|
||||||
|
{:db (-> db
|
||||||
|
(assoc-in [:wallet/send-transaction :transaction-id] nil)
|
||||||
|
(assoc :wrong-password? false))
|
||||||
|
:dispatch [:navigate-to :wallet-transaction-sent]}))))
|
||||||
|
|
||||||
|
(defn on-transactions-completed [raw-results]
|
||||||
|
(let [results (:results (types/json->clj raw-results))]
|
||||||
|
(doseq [result results]
|
||||||
|
;;TODO (andrey) legacy, should be removed with old transactions screens
|
||||||
|
(re-frame/dispatch [:transaction-completed {:id (name (key result)) :response (second result)}])
|
||||||
|
(re-frame/dispatch [::transaction-completed {:id (name (key result)) :response (second result)}]))))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:wallet/transaction-queued
|
||||||
|
(fn [{{:wallet/keys [send-transaction] :as db} :db} [_ transaction-id]]
|
||||||
|
(let [{:keys [later? password]} send-transaction]
|
||||||
|
(if later?
|
||||||
|
{:db (-> db
|
||||||
|
(assoc-in [:wallet/send-transaction :waiting-signal?] false)
|
||||||
|
(assoc :transactions (:transactions-queue db)))
|
||||||
|
:dispatch [:navigate-back]
|
||||||
|
::show-transaction-moved nil}
|
||||||
|
{:db (assoc-in db [:wallet/send-transaction :transaction-id] transaction-id)
|
||||||
|
::accept-transaction {:id transaction-id
|
||||||
|
:password password
|
||||||
|
:on-completed on-transactions-completed}}))))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:wallet/sign-transaction
|
||||||
|
(fn [{{:keys [web3]
|
||||||
|
:wallet/keys [send-transaction]
|
||||||
|
:accounts/keys [accounts current-account-id] :as db} :db} [_ later?]]
|
||||||
|
(let [{:keys [amount transaction-id password]} send-transaction
|
||||||
|
amount' (money/to-wei (string/replace amount #"," "."))]
|
||||||
|
(if transaction-id
|
||||||
|
{::accept-transaction {:id transaction-id
|
||||||
|
:password password
|
||||||
|
:on-completed on-transactions-completed}}
|
||||||
|
{:db (update-in db [:wallet/send-transaction]
|
||||||
|
#(assoc % :waiting-signal? true
|
||||||
|
:later? later?))
|
||||||
|
::send-transaction {:web3 web3
|
||||||
|
:from (get-in accounts [current-account-id :address])
|
||||||
|
:to (:to-address send-transaction)
|
||||||
|
:value amount'}}))))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:wallet/discard-transaction
|
||||||
|
(fn [{{:wallet/keys [send-transaction] :as db} :db} _]
|
||||||
|
(let [{:keys [transaction-id]} send-transaction]
|
||||||
|
(merge {:db (-> db
|
||||||
|
(update-in [:wallet/send-transaction]
|
||||||
|
#(assoc % :signing? false :transaction-id nil))
|
||||||
|
(assoc :wrong-password? false))}
|
||||||
|
(when transaction-id
|
||||||
|
;;TODO (andrey) use ::discard-transaction fx instead
|
||||||
|
{:dispatch-n [[:deny-transaction transaction-id]
|
||||||
|
[:status-im.transactions.handlers/remove-transaction transaction-id]]})))))
|
|
@ -1,18 +1,9 @@
|
||||||
(ns status-im.ui.screens.wallet.send.styles
|
(ns status-im.ui.screens.wallet.send.styles
|
||||||
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
|
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
|
||||||
(:require [status-im.components.styles :as styles]
|
(:require [status-im.components.styles :as styles]))
|
||||||
[status-im.utils.platform :as platform]))
|
|
||||||
|
|
||||||
(def wallet-container
|
|
||||||
{:flex 1
|
|
||||||
:background-color styles/color-blue4})
|
|
||||||
|
|
||||||
(def wallet-modal-container
|
|
||||||
{:flex 1
|
|
||||||
:background-color styles/color-blue3})
|
|
||||||
|
|
||||||
(def toolbar
|
(def toolbar
|
||||||
{:background-color styles/color-blue4
|
{:background-color styles/color-blue5
|
||||||
:elevation 0
|
:elevation 0
|
||||||
:padding-bottom 10})
|
:padding-bottom 10})
|
||||||
|
|
||||||
|
@ -33,119 +24,40 @@
|
||||||
(def toolbar-title-icon
|
(def toolbar-title-icon
|
||||||
(merge toolbar-icon {:opacity 0.4}))
|
(merge toolbar-icon {:opacity 0.4}))
|
||||||
|
|
||||||
(def toolbar-buttons-container
|
(defn animated-sign-panel [bottom-value]
|
||||||
{:flex-direction :row
|
{:position :absolute
|
||||||
:flex-shrink 1
|
:left 12
|
||||||
:justify-content :space-between
|
:right 12
|
||||||
:width 68
|
:bottom bottom-value})
|
||||||
:margin-right 12})
|
|
||||||
|
|
||||||
(def choose-recipient-container
|
(defn sign-panel [opacity-value]
|
||||||
{:flex-direction :row
|
{:opacity opacity-value
|
||||||
:padding-top 20
|
:border-radius 8
|
||||||
:padding-bottom 20
|
:background-color :white
|
||||||
:justify-content :center})
|
:padding-top 12
|
||||||
|
:padding-horizontal 12})
|
||||||
|
|
||||||
(def choose-recipient-label
|
(def signing-phrase-container
|
||||||
{:color :white})
|
{:border-radius 8
|
||||||
|
:height 36
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center
|
||||||
|
:background-color styles/color-light-gray})
|
||||||
|
|
||||||
(defstyle recipient-buttons
|
(def signing-phrase
|
||||||
{:flex-direction :column
|
{:font-size 15
|
||||||
:margin-horizontal 28
|
:letter-spacing -0.2
|
||||||
:margin-vertical 20
|
:color :black})
|
||||||
:border-radius 8
|
|
||||||
:ios {:background-color styles/color-blue6}})
|
|
||||||
|
|
||||||
(def recipient-icon {:margin-right 20})
|
(def signing-phrase-description
|
||||||
|
{:padding-top 8})
|
||||||
|
|
||||||
(def recipient-icon-disabled {:margin-right 20
|
(def password-container
|
||||||
:opacity 0.3})
|
{:flex 1
|
||||||
|
:padding-vertical 20})
|
||||||
|
|
||||||
(def recipient-button
|
(def password
|
||||||
{:flex-direction :row
|
{:padding 0
|
||||||
:justify-content :space-between
|
:font-size 15
|
||||||
:margin-vertical 10
|
:letter-spacing -0.2
|
||||||
:margin-left 20})
|
:height 20})
|
||||||
|
|
||||||
(def recipient-button-text
|
|
||||||
{:color :white
|
|
||||||
:align-self :center
|
|
||||||
:font-size 14})
|
|
||||||
|
|
||||||
(def recipient-button-text-disabled
|
|
||||||
(merge recipient-button-text {:color "rgba(255, 255, 255, 0.3)"}))
|
|
||||||
|
|
||||||
(defnstyle recipient-touchable [divider?]
|
|
||||||
(cond-> {:border-color styles/color-gray-transparent-light}
|
|
||||||
divider? (assoc :ios {:border-bottom-width 1})))
|
|
||||||
|
|
||||||
(def recipient-touchable-disabled
|
|
||||||
{:background-color styles/color-blue4
|
|
||||||
:border-bottom-left-radius 8
|
|
||||||
:border-bottom-right-radius 8
|
|
||||||
:border-left-width 1
|
|
||||||
:border-bottom-width 1
|
|
||||||
:border-right-width 1
|
|
||||||
:border-color "rgba(255, 255, 255, 0.3)"})
|
|
||||||
|
|
||||||
(def qr-container
|
|
||||||
{:flex 1})
|
|
||||||
|
|
||||||
(def preview
|
|
||||||
{:flex 1
|
|
||||||
:justify-content :flex-end
|
|
||||||
:align-items :center})
|
|
||||||
|
|
||||||
(def corner-dimensions
|
|
||||||
{:position :absolute
|
|
||||||
:width 40
|
|
||||||
:height 40})
|
|
||||||
|
|
||||||
(defn corner-left-bottom [dimension]
|
|
||||||
(let [viewport-offset 0.1666]
|
|
||||||
(merge corner-dimensions {:bottom (* viewport-offset dimension)
|
|
||||||
:left (* viewport-offset dimension)})))
|
|
||||||
|
|
||||||
(defn corner-right-bottom [dimension]
|
|
||||||
(let [viewport-offset 0.1666]
|
|
||||||
(merge corner-dimensions {:right (* viewport-offset dimension)
|
|
||||||
:bottom (* viewport-offset dimension)})))
|
|
||||||
|
|
||||||
(defn corner-left-top [dimension]
|
|
||||||
(let [viewport-offset 0.1666]
|
|
||||||
(merge corner-dimensions {:top (* viewport-offset dimension)
|
|
||||||
:left (* viewport-offset dimension)})))
|
|
||||||
|
|
||||||
(defn corner-right-top [dimension]
|
|
||||||
(let [viewport-offset 0.1666]
|
|
||||||
(merge corner-dimensions {:top (* viewport-offset dimension)
|
|
||||||
:right (* viewport-offset dimension)})))
|
|
||||||
|
|
||||||
(def viewfinder-port {:position :absolute
|
|
||||||
:left 0
|
|
||||||
:top 0
|
|
||||||
:bottom 0
|
|
||||||
:right 0
|
|
||||||
:flex 1})
|
|
||||||
|
|
||||||
(defn viewfinder-translucent [height width side]
|
|
||||||
(let [viewport-offset 0.1666
|
|
||||||
height-offset (* viewport-offset height)
|
|
||||||
width-offset (* viewport-offset width)]
|
|
||||||
(cond-> {:position :absolute
|
|
||||||
:background-color :black
|
|
||||||
:opacity 0.7}
|
|
||||||
(= :top side) (assoc :height height-offset
|
|
||||||
:width width)
|
|
||||||
(= :right side) (assoc :height (- height height-offset)
|
|
||||||
:width width-offset
|
|
||||||
:bottom 0
|
|
||||||
:right 0)
|
|
||||||
(= :bottom side) (assoc :height height-offset
|
|
||||||
:width (- width width-offset)
|
|
||||||
:bottom 0
|
|
||||||
:left 0)
|
|
||||||
(= :left side) (assoc :height (- height (* 2 height-offset))
|
|
||||||
:width width-offset
|
|
||||||
:top height-offset
|
|
||||||
:left 0))))
|
|
|
@ -4,3 +4,20 @@
|
||||||
(re-frame/reg-sub :camera-dimensions
|
(re-frame/reg-sub :camera-dimensions
|
||||||
(fn [db]
|
(fn [db]
|
||||||
(get-in db [:wallet :camera-dimensions])))
|
(get-in db [:wallet :camera-dimensions])))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:wallet.send/sign-enabled?
|
||||||
|
:<- [:get-in [:wallet/send-transaction :amount]]
|
||||||
|
:<- [:get-in [:wallet/send-transaction :to-address]]
|
||||||
|
:<- [:get-in [:wallet/send-transaction :amount-error]]
|
||||||
|
(fn [[amount to-address amount-error]]
|
||||||
|
(and
|
||||||
|
(nil? amount-error)
|
||||||
|
(not (nil? to-address)) (not= to-address "")
|
||||||
|
(not (nil? amount)) (not= amount ""))))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:wallet.send/sign-password-enabled?
|
||||||
|
:<- [:get-in [:wallet/send-transaction :password]]
|
||||||
|
(fn [password]
|
||||||
|
(and (not (nil? password)) (not= password ""))))
|
|
@ -0,0 +1,50 @@
|
||||||
|
(ns status-im.ui.screens.wallet.send.transaction-sent.styles
|
||||||
|
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]]))
|
||||||
|
|
||||||
|
(def transaction-sent-container
|
||||||
|
{:align-items :center})
|
||||||
|
|
||||||
|
(def ok-icon-container
|
||||||
|
{:width 56
|
||||||
|
:height 56
|
||||||
|
:border-radius 28
|
||||||
|
:background-color :white
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center
|
||||||
|
:margin-top 57
|
||||||
|
:margin-bottom 16})
|
||||||
|
|
||||||
|
(def transaction-sent
|
||||||
|
{:color :white
|
||||||
|
:font-size 17})
|
||||||
|
|
||||||
|
(def gap
|
||||||
|
{:height 8})
|
||||||
|
|
||||||
|
(def transaction-sent-description
|
||||||
|
{:color :white
|
||||||
|
:opacity 0.6
|
||||||
|
:font-size 14
|
||||||
|
:text-align :center
|
||||||
|
:padding-horizontal 16})
|
||||||
|
|
||||||
|
(def transaction-details-container
|
||||||
|
{:height 42
|
||||||
|
:background-color "#00000033"
|
||||||
|
:margin-horizontal 16
|
||||||
|
:opacity 0.2
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center
|
||||||
|
:border-radius 8})
|
||||||
|
|
||||||
|
(def transaction-details
|
||||||
|
{:color :white
|
||||||
|
:font-size 15})
|
||||||
|
|
||||||
|
(def got-it-container
|
||||||
|
{:align-items :center
|
||||||
|
:padding-vertical 18})
|
||||||
|
|
||||||
|
(def got-it
|
||||||
|
{:color :white
|
||||||
|
:font-size 15})
|
|
@ -0,0 +1,38 @@
|
||||||
|
(ns status-im.ui.screens.wallet.send.transaction-sent.views
|
||||||
|
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||||
|
(:require [status-im.components.react :as react]
|
||||||
|
[status-im.components.status-bar :as status-bar]
|
||||||
|
[status-im.components.icons.vector-icons :as vi]
|
||||||
|
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||||
|
[status-im.ui.screens.wallet.send.transaction-sent.styles :as styles]
|
||||||
|
[status-im.components.styles :as components.styles]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[status-im.ui.screens.wallet.components.views :as components]
|
||||||
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
|
(defview transaction-sent []
|
||||||
|
[react/view wallet.styles/wallet-modal-container
|
||||||
|
[status-bar/status-bar {:type :transparent}]
|
||||||
|
[react/view styles/transaction-sent-container
|
||||||
|
[react/view styles/ok-icon-container
|
||||||
|
[vi/icon :icons/ok {:color components.styles/color-blue4}]]
|
||||||
|
[react/text {:style styles/transaction-sent
|
||||||
|
:font (if platform/android? :medium :default)}
|
||||||
|
(i18n/label :t/transaction-sent)]
|
||||||
|
[react/view styles/gap]
|
||||||
|
[react/text {:style styles/transaction-sent-description} (i18n/label :t/transaction-description)]]
|
||||||
|
[react/view components.styles/flex]
|
||||||
|
[react/touchable-highlight {:on-press #()}; TODO (andrey) #(re-frame/dispatch [:navigate-to-clean :wallet-transaction-details])}
|
||||||
|
[react/view styles/transaction-details-container
|
||||||
|
[react/text {:style styles/transaction-details
|
||||||
|
:font (if platform/android? :medium :default)
|
||||||
|
:uppercase? (get-in platform/platform-specific [:uppercase?])}
|
||||||
|
(i18n/label :t/view-transaction-details)]]]
|
||||||
|
[components/separator]
|
||||||
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to-clean :wallet])}
|
||||||
|
[react/view styles/got-it-container
|
||||||
|
[react/text {:style styles/got-it
|
||||||
|
:font (if platform/android? :medium :default)
|
||||||
|
:uppercase? (get-in platform/platform-specific [:uppercase?])}
|
||||||
|
(i18n/label :t/got-it)]]]])
|
|
@ -4,7 +4,6 @@
|
||||||
[status-im.components.react :as react]
|
[status-im.components.react :as react]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.components.button.view :as button]
|
[status-im.components.button.view :as button]
|
||||||
[status-im.components.styles :as styles]
|
|
||||||
[status-im.components.status-bar :as status-bar]
|
[status-im.components.status-bar :as status-bar]
|
||||||
[status-im.components.toolbar-new.actions :as act]
|
[status-im.components.toolbar-new.actions :as act]
|
||||||
[status-im.components.toolbar-new.view :as toolbar]
|
[status-im.components.toolbar-new.view :as toolbar]
|
||||||
|
@ -13,77 +12,113 @@
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.screens.wallet.send.styles :as send.styles]
|
[status-im.ui.screens.wallet.send.styles :as send.styles]
|
||||||
[status-im.components.icons.vector-icons :as vector-icons]
|
[status-im.components.icons.vector-icons :as vector-icons]
|
||||||
[reagent.core :as r]))
|
[reagent.core :as r]
|
||||||
|
[status-im.utils.platform :as platform]
|
||||||
|
[status-im.ui.screens.wallet.request.styles :as request.styles]
|
||||||
|
[status-im.ui.screens.wallet.send.styles :as styles]
|
||||||
|
[status-im.ui.screens.wallet.components.views :as components]
|
||||||
|
[status-im.components.styles :as components.styles]
|
||||||
|
[status-im.components.icons.vector-icons :as vi]
|
||||||
|
[status-im.components.animation :as animation]
|
||||||
|
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||||
|
[status-im.ui.screens.wallet.send.animations :as send.animations]))
|
||||||
|
|
||||||
(defn- show-not-implemented! []
|
(defn toolbar-view [signing?]
|
||||||
(utils/show-popup "TODO" "Not implemented yet!"))
|
[toolbar/toolbar2 {:style wallet.styles/toolbar}
|
||||||
|
[toolbar/nav-button (act/back-white (if signing?
|
||||||
|
#(do (re-frame/dispatch [:wallet/discard-transaction])
|
||||||
|
(act/default-handler))
|
||||||
|
act/default-handler))]
|
||||||
|
[toolbar/content-title {:color :white} (i18n/label :t/send-transaction)]])
|
||||||
|
|
||||||
(defn toolbar-view []
|
(defn sign-later []
|
||||||
[toolbar/toolbar2 {:style send.styles/toolbar
|
(utils/show-question
|
||||||
:no-sync-bar? true}
|
(i18n/label :t/sign-later-title)
|
||||||
[toolbar/nav-button (act/close-white act/default-handler)]
|
(i18n/label :t/sign-later-text)
|
||||||
[toolbar/content-title {:color :white} (i18n/label :t/wallet-choose-recipient)]
|
#(re-frame/dispatch [:wallet/sign-transaction true])))
|
||||||
[toolbar/actions [{:icon :icons/flash-active
|
|
||||||
:icon-opts {:color :white}
|
|
||||||
:handler show-not-implemented!}]]])
|
|
||||||
|
|
||||||
(defn recipient-buttons []
|
(defview sign-panel []
|
||||||
[react/view {:style send.styles/recipient-buttons}
|
(letsubs [account [:get-current-account]
|
||||||
[react/touchable-highlight {:style (send.styles/recipient-touchable true)}
|
;;TODO (andrey) use send-transaction map after we remove old transactions ui
|
||||||
[react/view {:style send.styles/recipient-button}
|
wrong-password? [:get :wrong-password?];[:get-in [:wallet/send-transaction :wrong-password?]]
|
||||||
[react/text {:style send.styles/recipient-button-text}
|
signing-phrase (:signing-phrase @account)
|
||||||
(i18n/label :t/wallet-choose-from-contacts)]
|
bottom-value (animation/create-value -250)
|
||||||
[vector-icons/icon :icons/qr {:color :white
|
opacity-value (animation/create-value 0)]
|
||||||
:container-style send.styles/recipient-icon}]]]
|
{:component-did-mount #(send.animations/animate-sign-panel opacity-value bottom-value)}
|
||||||
[react/touchable-highlight {:style (send.styles/recipient-touchable true)
|
[react/animated-view {:style (styles/animated-sign-panel bottom-value)}
|
||||||
:on-press #(react/get-from-clipboard
|
[react/animated-view {:style (styles/sign-panel opacity-value)}
|
||||||
(fn [clipboard]
|
[react/view styles/signing-phrase-container
|
||||||
(re-frame/dispatch [:choose-recipient clipboard])))}
|
[react/text {:style styles/signing-phrase} signing-phrase]]
|
||||||
[react/view {:style send.styles/recipient-button}
|
[react/text {:style styles/signing-phrase-description} (i18n/label :t/signing-phrase-description)]
|
||||||
[react/text {:style send.styles/recipient-button-text}
|
[react/view styles/password-container
|
||||||
(i18n/label :t/wallet-address-from-clipboard)]
|
[react/text-input
|
||||||
[vector-icons/icon :icons/copy-from {:color :white
|
{:auto-focus true
|
||||||
:container-style send.styles/recipient-icon}]]]
|
:secure-text-entry true
|
||||||
[react/touchable-highlight {:style send.styles/recipient-touchable-disabled}
|
:placeholder (i18n/label :t/enter-password)
|
||||||
[react/view {:style send.styles/recipient-button}
|
:placeholder-text-color "#939ba1"
|
||||||
[react/text {:style send.styles/recipient-button-text-disabled}
|
:on-change-text #(do
|
||||||
(i18n/label :t/wallet-browse-photos)]
|
(re-frame/dispatch [:set-in [:wallet/send-transaction :password] %]))
|
||||||
[vector-icons/icon :icons/browse {:color :white
|
:style styles/password}]]]
|
||||||
:container-style send.styles/recipient-icon-disabled}]]]])
|
(when wrong-password?
|
||||||
|
[components/tooltip (i18n/label :t/wrong-password)])]))
|
||||||
|
|
||||||
(defn viewfinder [{:keys [height width]}]
|
|
||||||
(let [min-dimension (min height width)]
|
(defview signing-buttons []
|
||||||
[react/view {:style send.styles/viewfinder-port}
|
(letsubs [sign-enabled? [:wallet.send/sign-password-enabled?]]
|
||||||
[react/view {:style (send.styles/viewfinder-translucent height width :top)}]
|
[react/view wallet.styles/buttons-container
|
||||||
[react/view {:style (send.styles/viewfinder-translucent height width :right)}]
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet/discard-transaction])}
|
||||||
[react/view {:style (send.styles/viewfinder-translucent height width :bottom)}]
|
[react/view (wallet.styles/button-container true)
|
||||||
[react/view {:style (send.styles/viewfinder-translucent height width :left)}]
|
[components/button-text (i18n/label :t/cancel)]]]
|
||||||
[react/image {:source {:uri :corner_left_top}
|
[react/view components.styles/flex]
|
||||||
:style (send.styles/corner-left-top min-dimension)}]
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet/sign-transaction])}
|
||||||
[react/image {:source {:uri :corner_right_top}
|
[react/view (wallet.styles/button-container sign-enabled?)
|
||||||
:style (send.styles/corner-right-top min-dimension)}]
|
[components/button-text (i18n/label :t/transactions-sign-transaction)]
|
||||||
[react/image {:source {:uri :corner_left_bottom}
|
[vi/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]))
|
||||||
:style (send.styles/corner-left-bottom min-dimension)}]
|
|
||||||
[react/image {:source {:uri :corner_right_bottom}
|
(defview sign-buttons []
|
||||||
:style (send.styles/corner-right-bottom min-dimension)}]]))
|
(letsubs [sign-enabled? [:wallet.send/sign-enabled?]]
|
||||||
|
[react/view wallet.styles/buttons-container
|
||||||
|
(when sign-enabled?
|
||||||
|
[react/touchable-highlight {:on-press sign-later}
|
||||||
|
[react/view (wallet.styles/button-container sign-enabled?)
|
||||||
|
[components/button-text (i18n/label :t/transactions-sign-later)]]])
|
||||||
|
[react/view components.styles/flex]
|
||||||
|
[react/touchable-highlight {:on-press (when sign-enabled? #(re-frame/dispatch [:set-in [:wallet/send-transaction :signing?] true]))}
|
||||||
|
[react/view (wallet.styles/button-container sign-enabled?)
|
||||||
|
[components/button-text (i18n/label :t/transactions-sign-transaction)]
|
||||||
|
[vi/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]))
|
||||||
|
|
||||||
(defview send-transaction []
|
(defview send-transaction []
|
||||||
(letsubs [camera-dimensions [:camera-dimensions]]
|
(letsubs [amount [:get-in [:wallet/send-transaction :amount]]
|
||||||
[react/view {:style send.styles/wallet-container}
|
amount-error [:get-in [:wallet/send-transaction :amount-error]]
|
||||||
[status-bar/status-bar {:type :wallet}]
|
signing? [:get-in [:wallet/send-transaction :signing?]]
|
||||||
[toolbar-view]
|
to-address [:get-in [:wallet/send-transaction :to-address]]
|
||||||
[react/view {:style send.styles/qr-container
|
to-name [:get-in [:wallet/send-transaction :to-name]]]
|
||||||
:on-layout #(let [layout (.. % -nativeEvent -layout)]
|
[react/keyboard-avoiding-view wallet.styles/wallet-modal-container
|
||||||
(re-frame/dispatch [:set-in [:wallet :camera-dimensions]
|
[react/view components.styles/flex
|
||||||
{:width (.-width layout)
|
[status-bar/status-bar {:type :wallet}]
|
||||||
:height (.-height layout)}]))}
|
[toolbar-view signing?]
|
||||||
[camera/camera {:style send.styles/preview
|
[react/scroll-view {:keyboardShouldPersistTaps :always}
|
||||||
:aspect :fill
|
[react/view components.styles/flex
|
||||||
:captureAudio false
|
[react/view wallet.styles/choose-participant-container
|
||||||
:onBarCodeRead (fn [code]
|
[components/choose-recipient {:address to-address
|
||||||
(let [data (-> code
|
:name to-name
|
||||||
.-data
|
:on-press #(re-frame/dispatch [:navigate-to :choose-recipient])}]]
|
||||||
(str/replace #"ethereum:" ""))]
|
[react/view wallet.styles/choose-wallet-container
|
||||||
(re-frame/dispatch [:choose-recipient data])))}]
|
[components/choose-wallet]]
|
||||||
[viewfinder camera-dimensions]]
|
[react/view wallet.styles/amount-container
|
||||||
[recipient-buttons]]))
|
[components/amount-input
|
||||||
|
{:error amount-error
|
||||||
|
:input-options {:auto-focus true
|
||||||
|
:default-value amount
|
||||||
|
:on-change-text #(do
|
||||||
|
(re-frame/dispatch [:set-in [:wallet/send-transaction :amount] %])
|
||||||
|
(re-frame/dispatch [:wallet-validate-amount]))}}]
|
||||||
|
[react/view wallet.styles/choose-currency-container
|
||||||
|
[components/choose-currency wallet.styles/choose-currency]]]]]
|
||||||
|
[components/separator]
|
||||||
|
(if signing?
|
||||||
|
[signing-buttons]
|
||||||
|
[sign-buttons])
|
||||||
|
(when signing?
|
||||||
|
[sign-panel])]]))
|
|
@ -1,5 +1,15 @@
|
||||||
(ns status-im.ui.screens.wallet.styles
|
(ns status-im.ui.screens.wallet.styles
|
||||||
(:require [status-im.components.styles :as st]))
|
(:require-macros [status-im.utils.styles :refer [defstyle]])
|
||||||
|
(:require [status-im.components.styles :as st]
|
||||||
|
[status-im.components.styles :as styles]))
|
||||||
|
|
||||||
|
(def wallet-container
|
||||||
|
{:flex 1})
|
||||||
|
|
||||||
|
(defstyle toolbar
|
||||||
|
{:ios {:background-color styles/color-blue4}
|
||||||
|
:android {:background-color styles/color-blue5
|
||||||
|
:elevation 0}})
|
||||||
|
|
||||||
(def wallet-exclamation-container
|
(def wallet-exclamation-container
|
||||||
{:background-color st/color-red-2
|
{:background-color st/color-red-2
|
||||||
|
@ -13,3 +23,42 @@
|
||||||
(def wallet-error-exclamation
|
(def wallet-error-exclamation
|
||||||
{:width 16
|
{:width 16
|
||||||
:height 16})
|
:height 16})
|
||||||
|
|
||||||
|
(def buttons-container
|
||||||
|
{:margin-vertical 15
|
||||||
|
:padding-horizontal 12
|
||||||
|
:flex-direction :row
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(def forward-icon-container
|
||||||
|
{:margin-left 8})
|
||||||
|
|
||||||
|
(defn button-container [enabled?]
|
||||||
|
(merge
|
||||||
|
{:flex-direction :row
|
||||||
|
:align-items :center}
|
||||||
|
(when-not enabled?
|
||||||
|
{:opacity 0.4})))
|
||||||
|
|
||||||
|
(def wallet-modal-container
|
||||||
|
{:flex 1
|
||||||
|
:background-color styles/color-blue4})
|
||||||
|
|
||||||
|
(def choose-participant-container
|
||||||
|
{:margin-top 16
|
||||||
|
:margin-horizontal 15})
|
||||||
|
|
||||||
|
(def choose-wallet-container
|
||||||
|
{:margin-top 16
|
||||||
|
:margin-horizontal 15})
|
||||||
|
|
||||||
|
(def amount-container
|
||||||
|
{:margin-top 16
|
||||||
|
:margin-horizontal 15
|
||||||
|
:flex-direction :row})
|
||||||
|
|
||||||
|
(def choose-currency-container
|
||||||
|
{:margin-left 8})
|
||||||
|
|
||||||
|
(def choose-currency
|
||||||
|
{:width 116})
|
|
@ -23,6 +23,9 @@
|
||||||
(defn bignumber [n]
|
(defn bignumber [n]
|
||||||
(dependencies/Web3.prototype.toBigNumber (str n)))
|
(dependencies/Web3.prototype.toBigNumber (str n)))
|
||||||
|
|
||||||
|
(defn to-wei [str]
|
||||||
|
(dependencies/Web3.prototype.toWei str "ether"))
|
||||||
|
|
||||||
(def eth-units
|
(def eth-units
|
||||||
{:wei (bignumber "1")
|
{:wei (bignumber "1")
|
||||||
:kwei (bignumber "1000")
|
:kwei (bignumber "1000")
|
||||||
|
|
|
@ -24,6 +24,18 @@
|
||||||
(when on-cancel {:onPress on-cancel}))
|
(when on-cancel {:onPress on-cancel}))
|
||||||
{:text (or s "OK") :onPress on-accept :style "destructive"})))))
|
{:text (or s "OK") :onPress on-accept :style "destructive"})))))
|
||||||
|
|
||||||
|
(defn show-question
|
||||||
|
([title content on-accept]
|
||||||
|
(show-question title content on-accept nil))
|
||||||
|
([title content on-accept on-cancel]
|
||||||
|
(.alert (.-Alert rn-dependencies/react-native)
|
||||||
|
title
|
||||||
|
content
|
||||||
|
(clj->js
|
||||||
|
(vector (merge {:text (i18n/label :t/no)}
|
||||||
|
(when on-cancel {:onPress on-cancel}))
|
||||||
|
{:text (i18n/label :t/yes) :onPress on-accept})))))
|
||||||
|
|
||||||
(defn http-post
|
(defn http-post
|
||||||
([action data on-success]
|
([action data on-success]
|
||||||
(http-post action data on-success nil))
|
(http-post action data on-success nil))
|
||||||
|
|
Loading…
Reference in New Issue