diff --git a/src/status_im/chat/commands/impl/transactions.cljs b/src/status_im/chat/commands/impl/transactions.cljs index 22e2906b40f..b512f3dc72e 100644 --- a/src/status_im/chat/commands/impl/transactions.cljs +++ b/src/status_im/chat/commands/impl/transactions.cljs @@ -22,7 +22,6 @@ [status-im.utils.money :as money] [status-im.utils.platform :as platform] [status-im.ui.screens.wallet.db :as wallet.db] - [status-im.ui.screens.wallet.choose-recipient.events :as choose-recipient.events] [status-im.ui.screens.currency-settings.subs :as currency-settings.subs] [status-im.models.transactions :as wallet.transactions] [status-im.ui.screens.navigation :as navigation] @@ -313,8 +312,8 @@ :amount (money/formatted->internal value symbol decimals) :amount-text amount :amount-error error) - (choose-recipient.events/fill-request-details - (transaction-details recipient-contact symbol)) + #_(choose-recipient.events/fill-request-details + (transaction-details recipient-contact symbol)) (update-in [:wallet :send-transaction] dissoc :id :password :wrong-password?)) ;; TODO(janherich) - refactor wallet send events, updating gas price diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index 861b043a753..c1f68103596 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -16,7 +16,6 @@ status-im.ui.screens.wallet.request.events status-im.ui.screens.wallet.settings.events status-im.ui.screens.wallet.transactions.events - status-im.ui.screens.wallet.choose-recipient.events status-im.ui.screens.wallet.collectibles.cryptokitties.events status-im.ui.screens.wallet.collectibles.cryptostrikers.events status-im.ui.screens.wallet.collectibles.etheremon.events diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs index 5704edd9b57..0b2f9e3671a 100644 --- a/src/status_im/ui/screens/views.cljs +++ b/src/status_im/ui/screens/views.cljs @@ -32,14 +32,14 @@ [status-im.ui.screens.wallet.send.views :as send.views :refer [send-transaction send-transaction-modal sign-message-modal]] [status-im.ui.screens.wallet.choose-recipient.views :refer [choose-recipient]] - [status-im.ui.screens.wallet.request.views :refer [request-transaction send-transaction-request]] + [status-im.ui.screens.wallet.request.views :refer [wallet-request-contacts-list request-transaction send-transaction-request]] [status-im.ui.screens.wallet.components.views :as wallet.components] [status-im.ui.screens.wallet.onboarding.views :as wallet.onboarding] [status-im.ui.screens.wallet.transaction-fee.views :as wallet.transaction-fee] [status-im.ui.screens.wallet.settings.views :as wallet-settings] [status-im.ui.screens.wallet.transactions.views :as wallet-transactions] [status-im.ui.screens.wallet.transaction-sent.views :refer [transaction-sent transaction-sent-modal]] - [status-im.ui.screens.wallet.components.views :refer [contact-code recent-recipients recipient-qr-code]] + [status-im.ui.screens.wallet.components.views :refer [recipient-qr-code]] [status-im.ui.screens.network-settings.views :refer [network-settings]] [status-im.ui.screens.network-settings.network-details.views :refer [network-details]] [status-im.ui.screens.network-settings.edit-network.views :refer [edit-network]] @@ -228,9 +228,8 @@ :collectibles-list collectibles-list :wallet-onboarding-setup wallet.onboarding/screen :wallet-send-transaction-chat send-transaction - :contact-code contact-code :send-transaction-stack {:screens {:wallet-send-transaction send-transaction - :recent-recipients recent-recipients + :recent-recipients wallet-request-contacts-list :wallet-transaction-sent transaction-sent :recipient-qr-code recipient-qr-code :wallet-choose-amount send.views/choose-amount-token @@ -241,7 +240,7 @@ :request-transaction-stack {:screens {:wallet-request-transaction request-transaction :wallet-send-transaction-request send-transaction-request :wallet-request-assets wallet.components/request-assets - :recent-recipients recent-recipients} + :recent-recipients wallet-request-contacts-list} :config {:headerMode "none"}} :unsigned-transactions wallet-transactions/transactions :transactions-history wallet-transactions/transactions @@ -324,7 +323,6 @@ :add-participants-toggle-list add-participants-toggle-list :contact-toggle-list contact-toggle-list :group-chat-profile profile.group-chat/group-chat-profile - :contact-code contact-code [react/view [react/text (str "Unknown view: " view-id)]])) (defonce rand-label (rand/id)) diff --git a/src/status_im/ui/screens/wallet/choose_recipient/events.cljs b/src/status_im/ui/screens/wallet/choose_recipient/events.cljs deleted file mode 100644 index d90a7d72d39..00000000000 --- a/src/status_im/ui/screens/wallet/choose_recipient/events.cljs +++ /dev/null @@ -1,119 +0,0 @@ -(ns status-im.ui.screens.wallet.choose-recipient.events - (:require [re-frame.core :as re-frame] - [status-im.constants :as constants] - [status-im.contact.db :as contact.db] - [status-im.i18n :as i18n] - [status-im.utils.ethereum.core :as ethereum] - [status-im.utils.ethereum.eip681 :as eip681] - [status-im.utils.ethereum.ens :as ens] - [status-im.utils.handlers :as handlers] - [status-im.utils.money :as money])) - -(handlers/register-handler-fx - :wallet/toggle-flashlight - (fn [{:keys [db]}] - (let [flashlight-state (get-in db [:wallet :send-transaction :camera-flashlight]) - toggled-state (if (= :on flashlight-state) :off :on)] - {:db (assoc-in db [:wallet :send-transaction :camera-flashlight] toggled-state)}))) - -(defn- find-address-name [db address] - (:name (contact.db/find-contact-by-address (:contacts/contacts db) address))) - -(defn- fill-request-details [db {:keys [address name value symbol gas gasPrice public-key from-chat?]}] - {:pre [(not (nil? address))]} - (let [name (or name (find-address-name db address))] - (update-in - db [:wallet :send-transaction] - (fn [{old-symbol :symbol :as old-transaction}] - (let [symbol-changed? (not= old-symbol symbol)] - (cond-> (assoc old-transaction :to address :to-name name :public-key public-key) - value (assoc :amount value) - symbol (assoc :symbol symbol) - (and gas symbol-changed?) (assoc :gas (money/bignumber gas)) - from-chat? (assoc :from-chat? from-chat?) - (and gasPrice symbol-changed?) - (assoc :gas-price (money/bignumber gasPrice)) - (and symbol (not gasPrice) symbol-changed?) - (assoc :gas-price (ethereum/estimate-gas symbol)))))))) - -(defn- extract-details - "First try to parse as EIP681 URI, if not assume this is an address directly. - Returns a map containing at least the `address` and `chain-id` keys" - [s chain-id all-tokens] - (or (let [m (eip681/parse-uri s)] - (merge m (eip681/extract-request-details m all-tokens))) - (when (ethereum/address? s) - {:address s :chain-id chain-id}))) - -;; NOTE(janherich) - whenever changing assets, we want to clear the previusly set amount/amount-text -(defn changed-asset [{:keys [db] :as fx} old-symbol new-symbol] - (-> fx - (merge {:update-gas-price {:web3 (:web3 db) - :success-event :wallet/update-gas-price-success - :edit? false}}) - (assoc-in [:db :wallet :send-transaction :amount] nil) - (assoc-in [:db :wallet :send-transaction :amount-text] nil) - (assoc-in [:db :wallet :send-transaction :asset-error] - (i18n/label :t/changed-asset-warning {:old old-symbol :new new-symbol})))) - -(defn changed-amount-warning [fx old-amount new-amount] - (assoc-in fx [:db :wallet :send-transaction :amount-error] - (i18n/label :t/changed-amount-warning {:old old-amount :new new-amount}))) - -(defn use-default-eth-gas [fx] - (assoc-in fx [:db :wallet :send-transaction :gas] - ethereum/default-transaction-gas)) - -(re-frame/reg-fx - :resolve-address - (fn [{:keys [web3 registry ens-name cb]}] - (ens/get-addr web3 registry ens-name cb))) - -(handlers/register-handler-fx - :wallet.send/set-recipient - (fn [{:keys [db]} [_ recipient]] - (let [{:keys [web3 network]} db - network-info (get-in db [:account/account :networks network]) - chain (ethereum/network->chain-keyword network-info)] - (if (ens/is-valid-eth-name? recipient) - {:resolve-address {:web3 web3 - :registry (get ens/ens-registries chain) - :ens-name recipient - :cb #(re-frame/dispatch [:wallet.send/set-recipient %])}} - (if (ethereum/address? recipient) - {:db (assoc-in db [:wallet :send-transaction :to] recipient) - :dispatch [:navigate-back]} - {:ui/show-error (i18n/label :t/wallet-invalid-address {:data recipient})}))))) - -(handlers/register-handler-fx - :wallet/fill-request-from-url - (fn [{{:keys [network] :wallet/keys [all-tokens] :as db} :db} [_ data origin]] - (let [current-chain-id (get-in constants/default-networks [network :config :NetworkId]) - {:keys [address chain-id] :as details} (extract-details data current-chain-id all-tokens) - valid-network? (boolean (= current-chain-id chain-id)) - previous-state (get-in db [:wallet :send-transaction]) - old-symbol (:symbol previous-state) - new-symbol (:symbol details) - old-amount (:amount previous-state) - new-amount (:value details) - new-gas (:gas details) - symbol-changed? (and old-symbol new-symbol (not= old-symbol new-symbol))] - (cond-> {:db db - :dispatch [:navigate-back]} - (and address valid-network?) (update :db #(fill-request-details % details)) - symbol-changed? (changed-asset old-symbol new-symbol) - (and old-amount new-amount (not= old-amount new-amount)) (changed-amount-warning old-amount new-amount) - ;; NOTE(goranjovic) - the next line is there is because QR code scanning switches the amount to ETH - ;; automatically, so we need to update the gas limit accordingly. The check for origin screen is there - ;; so that we wouldn't also switch gas limit to ETH specific if the user pastes address as text. - ;; We need to check if address is defined so that we wouldn't trigger this behavior when invalid QR is scanned - ;; (e.g. public-key) - (and address (= origin :qr) (not new-gas) symbol-changed?) (use-default-eth-gas) - (not address) (assoc :ui/show-error (i18n/label :t/wallet-invalid-address {:data data})) - (and address (not valid-network?)) (assoc :ui/show-error (i18n/label :t/wallet-invalid-chain-id {:data data :chain current-chain-id})))))) - -(handlers/register-handler-fx - :wallet/fill-request-from-contact - (fn [{db :db} [_ {:keys [address name public-key]}]] - {:db (fill-request-details db {:address address :name name :public-key public-key}) - :dispatch [:navigate-back]})) diff --git a/src/status_im/ui/screens/wallet/choose_recipient/views.cljs b/src/status_im/ui/screens/wallet/choose_recipient/views.cljs index 5c21aef3eda..67e3a2f474f 100644 --- a/src/status_im/ui/screens/wallet/choose_recipient/views.cljs +++ b/src/status_im/ui/screens/wallet/choose_recipient/views.cljs @@ -10,18 +10,25 @@ [status-im.ui.components.toolbar.actions :as actions] [status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.screens.wallet.choose-recipient.styles :as styles] - [status-im.utils.platform :as platform])) + [status-im.utils.platform :as platform] + [status-im.utils.dimensions :as dimensions] + [reagent.core :as reagent])) + +(defn toggle-flashlight [old-value] + (if (= :off old-value) + :on + :off)) (defn- toolbar-view [camera-flashlight] [toolbar/toolbar styles/toolbar [toolbar/nav-button (actions/back-white actions/default-handler)] [toolbar/content-title {:color :white} (i18n/label :t/wallet-choose-recipient)] - [toolbar/actions [{:icon (if (= :on camera-flashlight) + [toolbar/actions [{:icon (if (= :on @camera-flashlight) :icons/flash-active :icons/flash-inactive) :icon-opts {:color :white} - :handler #(re-frame/dispatch [:wallet/toggle-flashlight])}]]]) + :handler #(swap! camera-flashlight toggle-flashlight)}]]]) (defn- viewfinder [{:keys [height width]} size] (let [height (cond-> height @@ -44,9 +51,10 @@ (int (* 2 (/ (min height width) 3)))) (defview choose-recipient [] - (letsubs [read-once? (atom false) - dimensions [:dimensions/window] - camera-flashlight [:wallet.send/camera-flashlight]] + (letsubs [{:keys [on-recipient]} [:get-screen-params :recipient-qr-code] + camera-flashlight (reagent/atom :off) ;; values are :off and :on + read-once? (atom false) + dimensions (dimensions/window)] [react/view {:style styles/qr-code} [status-bar/status-bar {:type :transparent}] [toolbar-view camera-flashlight] @@ -60,10 +68,11 @@ [camera/camera {:style styles/preview :aspect :fill :captureAudio false - :torchMode (camera/set-torch camera-flashlight) + :torchMode (camera/set-torch @camera-flashlight) :onBarCodeRead #(when-not @read-once? (reset! read-once? true) - (re-frame/dispatch [:wallet/fill-request-from-url (camera/get-qr-code-data %) :qr]))}]] + (on-recipient (camera/get-qr-code-data %)) + (re-frame/dispatch [:navigate-back]))}]] [viewfinder dimensions (size dimensions)]] [bottom-buttons/bottom-button [button/button {:disabled? false diff --git a/src/status_im/ui/screens/wallet/components/styles.cljs b/src/status_im/ui/screens/wallet/components/styles.cljs index 22c8ada94d5..f9a8742f481 100644 --- a/src/status_im/ui/screens/wallet/components/styles.cljs +++ b/src/status_im/ui/screens/wallet/components/styles.cljs @@ -188,10 +188,6 @@ (def recipient-no-address {:color colors/white-transparent}) -(def recent-recipients - {:flex 1 - :background-color colors/white}) - (def wallet-value-container {:flex 1 :flex-direction :row}) diff --git a/src/status_im/ui/screens/wallet/components/views.cljs b/src/status_im/ui/screens/wallet/components/views.cljs index 5febb416f40..f0f57d66e62 100644 --- a/src/status_im/ui/screens/wallet/components/views.cljs +++ b/src/status_im/ui/screens/wallet/components/views.cljs @@ -199,47 +199,6 @@ :accessibility-label (if request? :contact-address-text :recipient-address-text)} (ethereum/normalized-address address)]]]))) -(defn render-contact [contact] - [list/touchable-item #(re-frame/dispatch [:wallet/fill-request-from-contact contact]) - [list/item - [photos/photo (:photo-path contact) {:size list.styles/image-size}] - [list/item-content - [list/item-primary {:accessibility-label :contact-name-text} - (:name contact)] - [react/text {:style list.styles/secondary-text - :accessibility-label :contact-address-text} - (ethereum/normalized-address (:address contact))]]]]) - -(views/defview recent-recipients [] - (views/letsubs [contacts [:contacts/all-added-people-contacts]] - [simple-screen - [toolbar (i18n/label :t/recipient)] - [react/view styles/recent-recipients - [list/flat-list {:data contacts - :key-fn :address - :render-fn render-contact}]]])) - -(defn contact-code [] - (let [content (reagent/atom nil)] - (fn [] - [simple-screen {:avoid-keyboard? true} - [toolbar {:style wallet.styles/toolbar-bottom-line} - default-action - (i18n/label :t/recipient)] - [react/view components.styles/flex - [cartouche {} - (i18n/label :t/recipient) - [text-input {:multiline true - :style styles/contact-code-text-input - :placeholder (i18n/label :t/recipient-code) - :on-change-text #(reset! content %) - :accessibility-label :recipient-address-input}]] - [bottom-buttons/bottom-button - [button/button {:disabled? (string/blank? @content) - :on-press #(re-frame/dispatch [:wallet.send/set-recipient @content]) - :fit-to-text? false} - (i18n/label :t/done)]]]]))) - (defn recipient-qr-code [] [choose-recipient/choose-recipient]) diff --git a/src/status_im/ui/screens/wallet/request/events.cljs b/src/status_im/ui/screens/wallet/request/events.cljs index a8329d176e1..b4bc19b65ac 100644 --- a/src/status_im/ui/screens/wallet/request/events.cljs +++ b/src/status_im/ui/screens/wallet/request/events.cljs @@ -6,7 +6,35 @@ [status-im.chat.models :as chat-model] [status-im.chat.commands.sending :as commands-sending] [status-im.utils.fx :as fx] - [status-im.utils.money :as money])) + [status-im.utils.money :as money] + [status-im.contact.db :as contact.db] + [status-im.utils.ethereum.core :as ethereum])) + +(defn- find-address-name [db address] + (:name (contact.db/find-contact-by-address (:contacts/contacts db) address))) + +(defn- fill-request-details [db {:keys [address name value symbol gas gasPrice public-key from-chat?]}] + {:pre [(not (nil? address))]} + (let [name (or name (find-address-name db address))] + (update-in + db [:wallet :request-transaction] + (fn [{old-symbol :symbol :as old-transaction}] + (let [symbol-changed? (not= old-symbol symbol)] + (cond-> (assoc old-transaction :to address :to-name name :public-key public-key) + value (assoc :amount value) + symbol (assoc :symbol symbol) + (and gas symbol-changed?) (assoc :gas (money/bignumber gas)) + from-chat? (assoc :from-chat? from-chat?) + (and gasPrice symbol-changed?) + (assoc :gas-price (money/bignumber gasPrice)) + (and symbol (not gasPrice) symbol-changed?) + (assoc :gas-price (ethereum/estimate-gas symbol)))))))) + +(handlers/register-handler-fx + :wallet/fill-request-from-contact + (fn [{db :db} [_ {:keys [address name public-key]}]] + {:db (fill-request-details db {:address address :name name :public-key public-key}) + :dispatch [:navigate-back]})) (handlers/register-handler-fx :wallet-send-request diff --git a/src/status_im/ui/screens/wallet/request/views.cljs b/src/status_im/ui/screens/wallet/request/views.cljs index 3a1e5c727d9..4d6c6fbbbb5 100644 --- a/src/status_im/ui/screens/wallet/request/views.cljs +++ b/src/status_im/ui/screens/wallet/request/views.cljs @@ -21,15 +21,37 @@ [status-im.utils.ethereum.eip681 :as eip681] [status-im.utils.utils :as utils] [status-im.utils.ethereum.tokens :as tokens] - [status-im.ui.screens.wallet.utils :as wallet.utils])) + [status-im.ui.screens.wallet.utils :as wallet.utils] + [status-im.ui.components.list.views :as list] + [status-im.ui.screens.chat.photos :as photos] + [status-im.ui.components.list.styles :as list.styles] + [status-im.ui.components.colors :as colors])) -;; Request screen +(defn render-contact [contact] + [list/touchable-item #(re-frame/dispatch [:wallet/fill-request-from-contact contact]) + [list/item + [photos/photo (:photo-path contact) {:size list.styles/image-size}] + [list/item-content + [list/item-primary {:accessibility-label :contact-name-text} + (:name contact)] + [react/text {:style list.styles/secondary-text + :accessibility-label :contact-address-text} + (ethereum/normalized-address (:address contact))]]]]) + +(views/defview wallet-request-contacts-list [] + (views/letsubs [contacts [:contacts/all-added-people-contacts]] + [wallet.components/simple-screen + [wallet.components/toolbar (i18n/label :t/recipient)] + [react/view {:flex 1 + :background-color colors/white} + [list/flat-list {:data contacts + :key-fn :address + :render-fn render-contact}]]])) (views/defview send-transaction-request [] - ;; TODO(jeluard) both send and request flows should be merged (views/letsubs [network [:account/network] - {:keys [to to-name public-key]} [:wallet.send/transaction] - {:keys [amount amount-error amount-text symbol]} [:wallet.request/transaction] + {:keys [to to-name public-key amount amount-error + amount-text symbol]} [:wallet.request/transaction] network-status [:network-status] all-tokens [:wallet/all-tokens] scroll (atom nil)] diff --git a/src/status_im/ui/screens/wallet/send/events.cljs b/src/status_im/ui/screens/wallet/send/events.cljs index 11cd2fe6145..067d1ca9036 100644 --- a/src/status_im/ui/screens/wallet/send/events.cljs +++ b/src/status_im/ui/screens/wallet/send/events.cljs @@ -57,35 +57,34 @@ ;;;; Handlers ;; HANDLE QR CODE -#_(defn- qr-data->send-tx-data [{:keys [address name value symbol gas gasPrice public-key from-chat?]}] - {:pre [(not (nil? address))]} - (cond-> {:to address :public-key public-key} - value (assoc :amount value) - symbol (assoc :symbol symbol) - gas (assoc :gas (money/bignumber gas)) - from-chat? (assoc :from-chat? from-chat?) - gasPrice (assoc :gas-price (money/bignumber gasPrice)))) - -#_(defn extract-qr-code-details [chain-id qr-uri] - {:pre [(integer? chain-id) (string? qr-uri)]} +(defn qr-data->send-tx-data [{:keys [address value symbol gas gasPrice public-key from-chat?]}] + {:pre [(not (nil? address))]} + (cond-> {:to address :public-key public-key} + value (assoc :amount value) + symbol (assoc :symbol symbol) + gas (assoc :gas (money/bignumber gas)) + from-chat? (assoc :from-chat? from-chat?) + gasPrice (assoc :gas-price (money/bignumber gasPrice)))) + +(defn extract-qr-code-details [chain qr-uri] + {:pre [(keyword? chain) (string? qr-uri)]} ;; i don't like fetching all tokens here - (let [{:keys [:wallet/all-tokens]} @re-frame.db/app-db - qr-uri (string/trim qr-uri) - ;chain-id (ethereum/chain-keyword->chain-id chain) -] - (or (let [m (eip681/parse-uri qr-uri)] - (merge m (eip681/extract-request-details m all-tokens))) - (when (ethereum/address? qr-uri) - {:address qr-uri :chain-id chain-id})))) - -#_(defn qr-data->transaction-data [qr-data] - {:pre [(map? qr-data)]} + (let [{:keys [:wallet/all-tokens]} @re-frame.db/app-db + qr-uri (string/trim qr-uri) + chain-id (ethereum/chain-keyword->chain-id chain)] + (or (let [m (eip681/parse-uri qr-uri)] + (merge m (eip681/extract-request-details m all-tokens))) + (when (ethereum/address? qr-uri) + {:address qr-uri :chain-id chain-id})))) + +(defn qr-data->transaction-data [qr-data] + {:pre [(map? qr-data)]} ;; i don't like fetching all tokens here - (let [{:keys [:contacts/contacts]} @re-frame.db/app-db - {:keys [to] :as tx-details} (qr-data->send-tx-data qr-data) - contact-name (:name (contact.db/find-contact-by-address contacts to))] - (cond-> tx-details - contact-name (assoc :to-name name)))) + (let [{:keys [:contacts/contacts]} @re-frame.db/app-db + {:keys [to name] :as tx-details} (qr-data->send-tx-data qr-data) + contact-name (:name (contact.db/find-contact-by-address contacts to))] + (cond-> tx-details + contact-name (assoc :to-name name)))) ;; CHOOSEN RECIPIENT (defn eth-name->address [chain recipient callback] diff --git a/src/status_im/ui/screens/wallet/send/styles.cljs b/src/status_im/ui/screens/wallet/send/styles.cljs index 434218d8e03..cf042b49007 100644 --- a/src/status_im/ui/screens/wallet/send/styles.cljs +++ b/src/status_im/ui/screens/wallet/send/styles.cljs @@ -165,5 +165,5 @@ :font-size 30 :font-weight :bold :line-height 39 - :min-width 236 + :width 236 :margin-horizontal 24}) diff --git a/src/status_im/ui/screens/wallet/send/views.cljs b/src/status_im/ui/screens/wallet/send/views.cljs index 29723e6c0ef..73b7ad77747 100644 --- a/src/status_im/ui/screens/wallet/send/views.cljs +++ b/src/status_im/ui/screens/wallet/send/views.cljs @@ -33,6 +33,7 @@ [status-im.utils.ethereum.tokens :as tokens] [status-im.utils.ethereum.core :as ethereum] [status-im.transport.utils :as transport.utils] + [status-im.utils.ethereum.ens :as ens] [taoensso.timbre :as log] [reagent.core :as reagent] [status-im.ui.components.colors :as colors] @@ -252,13 +253,44 @@ ;; event code +(defn open-qr-scanner [chain text-input transaction] + (.blur @text-input) + (re-frame/dispatch [:navigate-to :recipient-qr-code + {:on-recipient + (fn [qr-data] + (if-let [parsed-qr-data (events/extract-qr-code-details chain qr-data)] + (let [{:keys [chain-id]} parsed-qr-data + tx-data (events/qr-data->transaction-data parsed-qr-data)] + (if (= chain-id (ethereum/chain-keyword->chain-id chain)) + (swap! transaction merge tx-data) + (utils/show-popup (i18n/label :t/error) + (i18n/label :t/wallet-invalid-chain-id {:data qr-data + :chain chain-id})))) + (utils/show-confirmation + {:title (i18n/label :t/error) + :content (i18n/label :t/wallet-invalid-address {:data qr-data}) + :cancel-button-text (i18n/label :t/see-it-again) + :confirm-button-text (i18n/label :t/got-it) + :on-cancel (partial open-qr-scanner chain text-input transaction)})))}])) + +(defn update-recipient [chain transaction error-message value] + (if (ens/is-valid-eth-name? value) + (do (ens/get-addr (get @re-frame.db/app-db :web3) + (get ens/ens-registries chain) + value + #(if (ethereum/address? %) + (swap! transaction assoc :to-ens value :to %) + (reset! error-message "Unknown ENS name")))) + (do (swap! transaction assoc :to value) + (reset! error-message nil)))) + (defn choose-address-view "A view that allows you to choose an address" - [{:keys [chain on-address]}] + [{:keys [chain transaction on-address]}] {:pre [(keyword? chain) (fn? on-address)]} (fn [] - (let [address (reagent/atom "") - error-message (reagent/atom nil)] + (let [error-message (reagent/atom nil) + text-input (atom nil)] (fn [] [react/view {:flex 1} [react/view {:flex 1}] @@ -268,16 +300,17 @@ :font-size 12 :bottom-value 15}]) [react/text-input - {:on-change-text #(do (reset! address %) - (reset! error-message nil)) + {:on-change-text (partial update-recipient chain transaction error-message) :auto-focus true :auto-capitalize :none :auto-correct false :placeholder "0x... or name.eth" :placeholder-text-color "rgb(143,162,234)" :multiline true - :max-length 42 - :value @address + :max-length 84 + :ref #(reset! text-input %) + ;;NOTE(goranjovic)- :default-value instead of :value to prevent the flickering due to two way binding + :default-value (or (:to-ens @transaction) (:to @transaction)) :selection-color colors/green :accessibility-label :recipient-address-input :style styles/choose-recipient-text-input}]] @@ -288,7 +321,7 @@ :on-press #(react/get-from-clipboard (fn [addr] (when (and addr (not (string/blank? addr))) - (reset! address (string/trim addr)))))} + (swap! transaction assoc :to (string/trim addr)))))} [react/view {:flex-direction :row :padding-horizontal 18} [vector-icons/icon :icons/paste {:color colors/white-transparent}] @@ -303,11 +336,7 @@ (fn [] (re-frame/dispatch [:request-permissions {:permissions [:camera] - :on-allowed - #(re-frame/dispatch [:navigate-to - :recipient-qr-code - {:on-recipient - (fn [])}]) + :on-allowed (partial open-qr-scanner chain text-input transaction) :on-denied #(utils/set-timeout (fn [] @@ -322,16 +351,14 @@ :font-size 15 :line-height 22}} (i18n/label :t/scan)]]]] - (let [disabled? (string/blank? @address)] + (let [disabled? (string/blank? (:to @transaction))] [address-button {:disabled? disabled? :underlay-color colors/black-transparent :background-color (if disabled? colors/blue colors/white) :on-press - #(events/chosen-recipient - chain @address - on-address - (fn on-error [_] - (reset! error-message (i18n/label :t/invalid-address))))} + #(events/chosen-recipient chain (:to @transaction) on-address + (fn on-error [_] + (reset! error-message (i18n/label :t/invalid-address))))} [react/text {:style {:color (if disabled? colors/white colors/blue) :font-size 15 :line-height 22}} @@ -392,10 +419,9 @@ ;; TODO clean up all dependencies here, leaving these in place until all behavior is verified on ;; all platforms -(defn- choose-address-contact [{:keys [modal? contacts transaction scroll advanced? network all-tokens amount-input network-status] :as opts}] +(defn- choose-address-contact [{:keys [modal? contacts scroll advanced? transaction network all-tokens amount-input network-status] :as opts}] - (let [{:keys [amount amount-text amount-error asset-error show-password-input? to to-name sufficient-funds? - sufficient-gas? in-progress? from-chat? symbol]} transaction + (let [transaction (reagent/atom transaction) chain (ethereum/network->chain-keyword network) native-currency (tokens/native-currency chain) {:keys [decimals] :as token} (tokens/asset-for all-tokens chain symbol) @@ -406,9 +432,10 @@ [simple-tab-navigator {:address {:name "Address" :component (choose-address-view {:chain chain + :transaction transaction :on-address #(re-frame/dispatch [:navigate-to :wallet-choose-amount - {:transaction (assoc transaction :to %) + {:transaction (swap! transaction assoc :to %) :native-currency native-currency :modal? modal?}])})} :contacts {:name "Contacts" @@ -420,7 +447,7 @@ (re-frame/dispatch [:navigate-to :wallet-choose-amount {:modal? modal? :native-currency native-currency - :transaction (assoc transaction :to address)}]))})}} + :transaction (swap! transaction assoc :to address)}]))})}} :address]])) ;; ----------------------------------------------------------------------