wallet favourites
This commit is contained in:
parent
6454df4734
commit
ff790d4152
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -115,6 +115,8 @@
|
|||
"wallet_getTransfersByAddress" {}
|
||||
"wallet_getCustomTokens" {}
|
||||
"wallet_addCustomToken" {}
|
||||
"wallet_addFavourite" {}
|
||||
"wallet_getFavourites" {}
|
||||
"wallet_deleteCustomToken" {}
|
||||
"browsers_getBrowsers" {}
|
||||
"browsers_addBrowser" {}
|
||||
|
|
|
@ -55,12 +55,13 @@
|
|||
|
||||
(fx/defn initialize-wallet
|
||||
{:events [::initialize-wallet]}
|
||||
[{:keys [db] :as cofx} accounts custom-tokens]
|
||||
[{:keys [db] :as cofx} accounts custom-tokens favourites]
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (assoc db :multiaccount/accounts
|
||||
(rpc->accounts accounts))}
|
||||
(wallet/initialize-tokens custom-tokens)
|
||||
(wallet/initialize-favourites favourites)
|
||||
(wallet/update-balances nil)
|
||||
(prices/update-prices)))
|
||||
|
||||
|
@ -154,11 +155,17 @@
|
|||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(json-rpc/call {:method "wallet_getCustomTokens"
|
||||
:on-success resolve
|
||||
:on-error reject})))
|
||||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(json-rpc/call {:method "wallet_getFavourites"
|
||||
:on-success resolve
|
||||
:on-error reject})))]))
|
||||
(.then (fn [[accounts custom-tokens]]
|
||||
(.then (fn [[accounts custom-tokens favourites]]
|
||||
(callback accounts
|
||||
(mapv #(update % :symbol keyword) custom-tokens))))
|
||||
(mapv #(update % :symbol keyword) custom-tokens)
|
||||
favourites)))
|
||||
(.catch (fn [_]
|
||||
(log/error "Failed to initialize wallet"))))))
|
||||
|
||||
|
@ -186,9 +193,9 @@
|
|||
:networks/networks networks
|
||||
:multiaccount multiaccount))
|
||||
::initialize-wallet
|
||||
(fn [accounts custom-tokens]
|
||||
(fn [accounts custom-tokens favourites]
|
||||
(re-frame/dispatch [::initialize-wallet
|
||||
accounts custom-tokens]))}
|
||||
accounts custom-tokens favourites]))}
|
||||
notifications-enabled?
|
||||
(assoc ::notifications/enable nil))
|
||||
(acquisition/login)
|
||||
|
@ -269,7 +276,7 @@
|
|||
:default-mailserver true})
|
||||
(multiaccounts/switch-preview-privacy-mode-flag)
|
||||
(logging/set-log-level (:log-level multiaccount))
|
||||
(initialize-wallet accounts nil))))
|
||||
(initialize-wallet accounts nil nil))))
|
||||
|
||||
(defn- keycard-setup? [cofx]
|
||||
(boolean (get-in cofx [:db :keycard :flow])))
|
||||
|
|
|
@ -14,4 +14,9 @@
|
|||
(fx/defn token-filter-changed
|
||||
{:events [:search/token-filter-changed]}
|
||||
[cofx search-filter]
|
||||
{:db (assoc-in (:db cofx) [:ui/search :token-filter] search-filter)})
|
||||
{:db (assoc-in (:db cofx) [:ui/search :token-filter] search-filter)})
|
||||
|
||||
(fx/defn recipient-filter-changed
|
||||
{:events [:search/recipient-filter-changed]}
|
||||
[cofx search-filter]
|
||||
{:db (assoc-in (:db cofx) [:ui/search :recipient-filter] search-filter)})
|
|
@ -163,6 +163,8 @@
|
|||
(reg-root-key-sub :wallet/prepare-transaction :wallet/prepare-transaction)
|
||||
(reg-root-key-sub :wallet-service/manual-setting :wallet-service/manual-setting)
|
||||
(reg-root-key-sub :wallet-service/state :wallet-service/state)
|
||||
(reg-root-key-sub :wallet/recipient :wallet/recipient)
|
||||
(reg-root-key-sub :wallet/favourites :wallet/favourites)
|
||||
|
||||
;;commands
|
||||
(reg-root-key-sub :commands/select-account :commands/select-account)
|
||||
|
@ -367,6 +369,12 @@
|
|||
(fn [search]
|
||||
(get search :home-filter)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:search/recipient-filter
|
||||
:<- [:ui/search]
|
||||
(fn [search]
|
||||
(get search :recipient-filter)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:search/currency-filter
|
||||
:<- [:ui/search]
|
||||
|
@ -531,6 +539,23 @@
|
|||
(fn [accounts]
|
||||
(filter #(not= (:type %) :watch) accounts)))
|
||||
|
||||
(defn filter-recipient-accounts
|
||||
[search-filter {:keys [name]}]
|
||||
(string/includes? (string/lower-case (str name)) search-filter))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:accounts-for-recipient
|
||||
:<- [:multiaccount/accounts]
|
||||
:<- [:wallet/prepare-transaction]
|
||||
:<- [:search/recipient-filter]
|
||||
(fn [[accounts {:keys [from]} search-filter]]
|
||||
(let [accounts (remove #(= (:address %) (:address from)) accounts)]
|
||||
(if (string/blank? search-filter)
|
||||
accounts
|
||||
(filter (partial filter-recipient-accounts
|
||||
(string/lower-case search-filter))
|
||||
accounts)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:add-account-disabled?
|
||||
:<- [:multiaccount/accounts]
|
||||
|
@ -1285,6 +1310,21 @@
|
|||
(fn [currency-id]
|
||||
(get constants/currencies currency-id)))
|
||||
|
||||
(defn filter-recipient-favs
|
||||
[search-filter {:keys [name]}]
|
||||
(string/includes? (string/lower-case (str name)) search-filter))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/favourites-filtered
|
||||
:<- [:wallet/favourites]
|
||||
:<- [:search/recipient-filter]
|
||||
(fn [[favs search-filter]]
|
||||
(let [favs (vals favs)]
|
||||
(if (string/blank? search-filter)
|
||||
favs
|
||||
(filter (partial filter-recipient-favs
|
||||
(string/lower-case search-filter))
|
||||
favs)))))
|
||||
;;WALLET TRANSACTIONS ==================================================================================================
|
||||
|
||||
(re-frame/reg-sub
|
||||
|
@ -1434,6 +1474,17 @@
|
|||
(keep #(enrich-transaction-for-list filters % address))
|
||||
(group-transactions-by-date))}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/recipient-recent-txs
|
||||
(fn [[_ address] _]
|
||||
[(re-frame/subscribe [:wallet.transactions/transactions address])])
|
||||
(fn [[transactions] _]
|
||||
(->> transactions
|
||||
vals
|
||||
(sort-by :timestamp >)
|
||||
(remove #(= (:type %) :pending))
|
||||
(take 3))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.transactions.details/current-transaction
|
||||
(fn [[_ _ address] _]
|
||||
|
@ -1620,6 +1671,28 @@
|
|||
(fn [blocked-contacts]
|
||||
(count blocked-contacts)))
|
||||
|
||||
(defn filter-recipient-contacts
|
||||
[search-filter {:keys [names]}]
|
||||
(let [{:keys [nickname three-words-name ens-name]} names]
|
||||
(or
|
||||
(when ens-name
|
||||
(string/includes? (string/lower-case (str ens-name)) search-filter))
|
||||
(string/includes? (string/lower-case three-words-name) search-filter)
|
||||
(when nickname
|
||||
(string/includes? (string/lower-case nickname) search-filter)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:contacts/active-with-ens-names
|
||||
:<- [:contacts/active]
|
||||
:<- [:search/recipient-filter]
|
||||
(fn [[contacts search-filter]]
|
||||
(let [contacts (filter :ens-verified contacts)]
|
||||
(if (string/blank? search-filter)
|
||||
contacts
|
||||
(filter (partial filter-recipient-contacts
|
||||
(string/lower-case search-filter))
|
||||
contacts)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:contacts/current-contact
|
||||
:<- [:contacts/contacts]
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
is-ens? (and (not is-public-key?)
|
||||
(ens/valid-eth-name-prefix? new-identity))
|
||||
error (db/validate-pub-key db new-identity)]
|
||||
(reset! resolve-last-id nil)
|
||||
(merge {:db (assoc db
|
||||
:contacts/new-identity
|
||||
{:public-key new-identity
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [status-im.ui.screens.profile.tribute-to-talk.views :as tr-to-talk]
|
||||
[status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat]
|
||||
[status-im.ui.screens.wallet.components.views :as wallet.components]
|
||||
[status-im.ui.screens.wallet.recipient.views :as recipient]
|
||||
[status-im.ui.screens.qr-scanner.views :as qr-scanner]
|
||||
[status-im.ui.screens.stickers.views :as stickers]
|
||||
[status-im.ui.screens.home.views :as home]
|
||||
|
@ -24,7 +24,8 @@
|
|||
[status-im.utils.config :as config]
|
||||
[status-im.ui.screens.chat.image.preview.views :as image-preview]
|
||||
[status-im.ui.screens.profile.contact.views :as contact]
|
||||
[status-im.ui.screens.notifications-settings.views :as notifications-settings]))
|
||||
[status-im.ui.screens.notifications-settings.views :as notifications-settings]
|
||||
[status-im.ui.screens.wallet.send.views :as wallet]))
|
||||
|
||||
(defonce main-stack (navigation/create-stack))
|
||||
(defonce bottom-tabs (navigation/create-bottom-tabs))
|
||||
|
@ -103,8 +104,14 @@
|
|||
:transition :presentation-ios
|
||||
:insets {:bottom true}
|
||||
:component group-chat/add-participants-toggle-list}
|
||||
{:name :contact-code
|
||||
:component wallet.components/contact-code}
|
||||
{:name :recipient
|
||||
:transition :presentation-ios
|
||||
:insets {:bottom true}
|
||||
:component recipient/recipient}
|
||||
{:name :new-favourite
|
||||
:transition :presentation-ios
|
||||
:insets {:bottom true}
|
||||
:component recipient/new-favourite}
|
||||
{:name :qr-scanner
|
||||
:insets {:top false :bottom false}
|
||||
:component qr-scanner/qr-scanner}
|
||||
|
@ -122,7 +129,15 @@
|
|||
{:name :notifications-onboarding
|
||||
:back-handler :noop
|
||||
:insets {:bottom true}
|
||||
:component notifications-settings/notifications-onboarding}]
|
||||
:component notifications-settings/notifications-onboarding}
|
||||
{:name :prepare-send-transaction
|
||||
:transition :presentation-ios
|
||||
:insets {:bottom true}
|
||||
:component wallet/prepare-send-transaction}
|
||||
{:name :request-transaction
|
||||
:transition :presentation-ios
|
||||
:insets {:bottom true}
|
||||
:component wallet/request-transaction}]
|
||||
|
||||
(when config/quo-preview-enabled?
|
||||
[{:name :quo-preview
|
||||
|
|
|
@ -104,8 +104,6 @@
|
|||
{:enableURLHandling true
|
||||
:initialState @state}))
|
||||
[main-app-navigator]]
|
||||
[wallet/prepare-transaction]
|
||||
[wallet/request-transaction]
|
||||
[wallet/select-account]
|
||||
[signing/signing]
|
||||
[bottom-sheet]
|
||||
|
|
|
@ -1,43 +1,6 @@
|
|||
(ns status-im.ui.screens.wallet.components.views
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.ui.screens.wallet.components.styles :as styles]
|
||||
[quo.core :as quo]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.utils.debounce :as debounce])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.wallet.components.styles :as styles]))
|
||||
|
||||
(defn separator []
|
||||
[react/view (styles/separator)])
|
||||
|
||||
(defn- recipient-topbar [content]
|
||||
[topbar/topbar {:navigation {:label (i18n/label :t/cancel)
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:set-in [:wallet/prepare-transaction :modal-opened?] false])
|
||||
(re-frame/dispatch [:navigate-back]))}
|
||||
:title (i18n/label :t/recipient)
|
||||
:right-accessories [{:on-press #(debounce/dispatch-and-chill [:wallet.send/set-recipient content] 3000)
|
||||
:label (i18n/label :t/done)
|
||||
:disabled (string/blank? content)}]}])
|
||||
|
||||
(views/defview contact-code []
|
||||
(views/letsubs [content (reagent/atom nil)]
|
||||
[react/view {:flex 1}
|
||||
[recipient-topbar @content]
|
||||
[react/view {:padding-horizontal 16
|
||||
:padding-vertical 24
|
||||
:flex 1}
|
||||
[quo/text-input
|
||||
{:multiline true
|
||||
:height 98
|
||||
:placeholder (i18n/label :t/recipient-code-placeholder)
|
||||
:text-align-vertical :top
|
||||
:on-change-text #(reset! content %)
|
||||
:accessibility-label :recipient-address-input}]
|
||||
[react/text {:style {:color colors/gray
|
||||
:margin-vertical 16}}
|
||||
(i18n/label :t/enter-recipient-address-or-username)]]]))
|
||||
[react/view (styles/separator)])
|
|
@ -0,0 +1,315 @@
|
|||
(ns status-im.ui.screens.wallet.recipient.views
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[quo.core :as quo]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.utils.debounce :as debounce]
|
||||
[status-im.ui.components.search-input.view :as search-input]
|
||||
[status-im.ui.screens.wallet.components.views :as components]
|
||||
[status-im.ui.components.icons.vector-icons :as icons]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
|
||||
[status-im.ui.components.toolbar :as toolbar]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.stateofus :as stateofus])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(defn- recipient-topbar []
|
||||
[topbar/topbar
|
||||
{:navigation {:on-press
|
||||
#(do
|
||||
(re-frame/dispatch [:wallet/recipient-modal-closed])
|
||||
(re-frame/dispatch [:search/recipient-filter-changed nil])
|
||||
(re-frame/dispatch [:navigate-back]))}
|
||||
:modal? true
|
||||
:border-bottom false
|
||||
:title (i18n/label :t/recipient)
|
||||
:right-accessories
|
||||
[{:icon :qr
|
||||
:accessibility-label :scan-contact-code-button
|
||||
:on-press #(re-frame/dispatch [:wallet.send/qr-scanner
|
||||
{:handler :wallet.send/qr-scanner-result}])}]}])
|
||||
|
||||
(defonce search-active? (reagent/atom false))
|
||||
|
||||
(defn search-input-wrapper []
|
||||
(let [search-filter @(re-frame/subscribe [:search/recipient-filter])]
|
||||
[react/view {:padding-horizontal 16
|
||||
:padding-vertical 10}
|
||||
[search-input/search-input
|
||||
{:search-active? search-active?
|
||||
:search-filter search-filter
|
||||
:on-cancel #(re-frame/dispatch [:search/recipient-filter-changed nil])
|
||||
:on-change (fn [text]
|
||||
(re-frame/dispatch [:search/recipient-filter-changed text])
|
||||
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
|
||||
(debounce/debounce-and-dispatch [:new-chat/set-new-identity text] 300))}]]))
|
||||
|
||||
(defn section [_ _ _]
|
||||
(let [opened? (reagent/atom false)]
|
||||
(fn [title cnt content]
|
||||
[react/view {:padding-vertical 8}
|
||||
[quo/list-item
|
||||
{:title title
|
||||
:on-press #(swap! opened? not)
|
||||
:accessory
|
||||
[react/view {:flex-direction :row :align-items :center}
|
||||
(when (pos? cnt)
|
||||
[react/text {:style {:color colors/gray}} cnt])
|
||||
[icons/icon (if @opened? :main-icons/dropdown :main-icons/next)
|
||||
{:container-style {:align-items :center
|
||||
:margin-left 8
|
||||
:justify-content :center}
|
||||
:resize-mode :center
|
||||
:color colors/black}]]}]
|
||||
(when @opened?
|
||||
content)])))
|
||||
|
||||
(defn render-account [account]
|
||||
[quo/list-item
|
||||
{:icon [chat-icon/custom-icon-view-list (:name account) (:color account)]
|
||||
:title (:name account)
|
||||
:on-press #(re-frame/dispatch [:wallet.send/set-recipient (:address account)])
|
||||
:subtitle [quo/text {:monospace true
|
||||
:color :secondary}
|
||||
(utils/get-shortened-checksum-address (:address account))]}])
|
||||
|
||||
(def scroll-view-ref (atom nil))
|
||||
|
||||
(defn contacts-list-item [{:keys [name] :as contact}]
|
||||
(let [[first-name second-name] (multiaccounts/contact-two-names contact true)]
|
||||
[quo/list-item
|
||||
{:title first-name
|
||||
:subtitle second-name
|
||||
:on-press #(do
|
||||
(some-> ^js @scroll-view-ref (.scrollTo #js {:x 0 :animated true}))
|
||||
(re-frame/dispatch [:wallet.recipient/focus-input])
|
||||
(re-frame/dispatch [:wallet.recipient/address-changed name]))
|
||||
:icon [chat-icon/contact-icon-contacts-tab
|
||||
(multiaccounts/displayed-photo contact)]}]))
|
||||
|
||||
(defn empty-items [icon title]
|
||||
[react/view {:height 94 :align-items :center :justify-content :center}
|
||||
[icons/icon icon
|
||||
{:color colors/gray}]
|
||||
[react/text {:style {:color colors/gray :margin-top 8}}
|
||||
title]])
|
||||
|
||||
(views/defview accounts-section []
|
||||
(views/letsubs [accounts [:accounts-for-recipient]]
|
||||
(let [cnt (count accounts)]
|
||||
[section
|
||||
(i18n/label :t/my-accounts)
|
||||
cnt
|
||||
(if (> cnt 0)
|
||||
[react/view
|
||||
(for [account accounts]
|
||||
[render-account account])]
|
||||
[empty-items :main-icons/address (i18n/label :t/my-accounts-empty)])])))
|
||||
|
||||
(defn render-recent [{:keys [from to type amount-text currency-text]}]
|
||||
(let [inbound? (= type :inbound)
|
||||
address (if inbound? from to)]
|
||||
[quo/list-item
|
||||
{:title [quo/text {:monospace true}
|
||||
(utils/get-shortened-checksum-address address)]
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:wallet.recipient/focus-input])
|
||||
(re-frame/dispatch [:wallet.recipient/address-changed address]))
|
||||
:size :small
|
||||
:accessory [react/text {:style {:flex-shrink 1
|
||||
:color colors/gray}}
|
||||
(str (if inbound? "↓ " "↑ ") amount-text " " currency-text)]}]))
|
||||
|
||||
(defn recent-section []
|
||||
(let [{:keys [from]} @(re-frame/subscribe [:wallet/prepare-transaction])
|
||||
txs @(re-frame/subscribe [:wallet/recipient-recent-txs (:address from)])
|
||||
cnt (count txs)]
|
||||
[section
|
||||
(i18n/label :t/recent)
|
||||
cnt
|
||||
(if (> cnt 0)
|
||||
[react/view
|
||||
(for [tx txs]
|
||||
[render-recent tx])]
|
||||
[empty-items :main-icons/history (i18n/label :t/recent-empty)])]))
|
||||
|
||||
(defn render-fav [{:keys [address name]}]
|
||||
(let [noname? (string/blank? name)
|
||||
short-address (utils/get-shortened-checksum-address address)]
|
||||
[quo/list-item
|
||||
{:icon [chat-icon/custom-icon-view-list
|
||||
(if noname? " 2" name)
|
||||
(rand-nth colors/chat-colors)]
|
||||
:title (if noname?
|
||||
[quo/text {:monospace true}
|
||||
short-address]
|
||||
name)
|
||||
:subtitle (when-not noname? [quo/text {:monospace true
|
||||
:color :secondary}
|
||||
short-address])
|
||||
:on-press #(re-frame/dispatch [:wallet.send/set-recipient address])
|
||||
:size (when noname? :small)}]))
|
||||
|
||||
(views/defview fav-section []
|
||||
(views/letsubs [favourites [:wallet/favourites-filtered]]
|
||||
(let [cnt (count favourites)]
|
||||
[section
|
||||
(i18n/label :t/favourites)
|
||||
cnt
|
||||
[react/view
|
||||
;;TODO implement later
|
||||
#_[quo/list-item
|
||||
{:title "Add favourite"
|
||||
:icon :main-icons/add
|
||||
:theme :accent}]
|
||||
(if (> cnt 0)
|
||||
[react/view
|
||||
(for [data favourites]
|
||||
[render-fav data])]
|
||||
[empty-items :main-icons/favourite (i18n/label :t/favourites-empty)])]])))
|
||||
|
||||
(views/defview contacts-section []
|
||||
(views/letsubs [contacts [:contacts/active-with-ens-names]]
|
||||
(let [cnt (count contacts)]
|
||||
[section
|
||||
(i18n/label :t/contacts)
|
||||
cnt
|
||||
(if (> cnt 0)
|
||||
[react/view
|
||||
(for [contact contacts]
|
||||
[contacts-list-item contact])]
|
||||
[empty-items :main-icons/username (i18n/label :t/contacts-empty)])])))
|
||||
|
||||
(views/defview search-results []
|
||||
(views/letsubs [contacts [:contacts/active-with-ens-names]
|
||||
favourites [:wallet/favourites-filtered]
|
||||
accounts [:accounts-for-recipient]]
|
||||
[react/view
|
||||
(for [account accounts]
|
||||
[render-account account])
|
||||
(for [data favourites]
|
||||
[render-fav data])
|
||||
(for [contact contacts]
|
||||
[contacts-list-item contact])]))
|
||||
|
||||
(defn accordion [search-filter]
|
||||
(if (not (string/blank? search-filter))
|
||||
[search-results]
|
||||
[react/view
|
||||
[components/separator]
|
||||
[accounts-section]
|
||||
[components/separator]
|
||||
[recent-section]
|
||||
[components/separator]
|
||||
[fav-section]
|
||||
[components/separator]
|
||||
[contacts-section]
|
||||
[components/separator]]))
|
||||
|
||||
(views/defview new-favourite []
|
||||
(views/letsubs [{:keys [resolved-address]} [:wallet/recipient]
|
||||
fav-name (atom "")]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[react/view {:flex 1}
|
||||
[topbar/topbar
|
||||
{:modal? true
|
||||
:title (i18n/label :t/new-favourite)}]
|
||||
[react/scroll-view {:style {:flex 1}}
|
||||
[react/view {:padding-horizontal 16}
|
||||
[react/view {:flex-direction :row :justify-content :space-between
|
||||
:align-items :center :height 40 :margin-vertical 8}
|
||||
[quo/text (i18n/label :t/address-or-ens-name)]]
|
||||
[quo/text-input
|
||||
{:multiline true
|
||||
:default-value resolved-address
|
||||
:height 70
|
||||
:editable false}]]
|
||||
[react/view {:height 16}]
|
||||
[quo/list-header (i18n/label :t/name-optional)]
|
||||
[react/view {:padding-horizontal 16}
|
||||
[quo/text-input {:show-cancel false
|
||||
:on-change-text #(reset! fav-name %)}]]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:center
|
||||
[quo/button
|
||||
{:accessibility-label :add-fav
|
||||
:type :secondary
|
||||
:on-press #(re-frame/dispatch [:wallet/add-favourite resolved-address @fav-name])}
|
||||
(i18n/label :t/add)]}]]]))
|
||||
|
||||
(views/defview recipient []
|
||||
(views/letsubs [{:keys [address resolved-address searching] :as recip} [:wallet/recipient]
|
||||
search-filter [:search/recipient-filter]
|
||||
input-focused? (reagent/atom false)]
|
||||
(let [disabled? (or searching (not resolved-address))]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[react/view {:flex 1}
|
||||
[recipient-topbar]
|
||||
[search-input-wrapper]
|
||||
[react/scroll-view {:style {:flex 1}
|
||||
:keyboard-should-persist-taps :handled
|
||||
:ref #(reset! scroll-view-ref %)}
|
||||
[react/view
|
||||
[components/separator]
|
||||
[react/view {:padding-horizontal 16 :margin-bottom 16}
|
||||
[react/view {:flex-direction :row :justify-content :space-between
|
||||
:align-items :center :height 40 :margin-vertical 8}
|
||||
[quo/text (i18n/label :t/address-or-ens-name)]
|
||||
[quo/button {:type :secondary
|
||||
:on-press #(re-frame/dispatch [:wallet.recipient/address-paste-pressed])}
|
||||
(i18n/label :t/paste)]]
|
||||
[quo/text-input
|
||||
{:multiline true
|
||||
:get-ref #(when (and recip %)
|
||||
(re-frame/dispatch [:set-in [:wallet/recipient :inp-ref] %]))
|
||||
:on-focus #(reset! input-focused? true)
|
||||
:on-blur #(reset! input-focused? false)
|
||||
:default-value address
|
||||
:height 70
|
||||
:placeholder (i18n/label :t/recipient-code-placeholder)
|
||||
:text-align-vertical :top
|
||||
:on-change-text #(do
|
||||
(re-frame/dispatch [:set-in [:wallet/recipient :searching] :searching])
|
||||
(debounce/debounce-and-dispatch [:wallet.recipient/address-changed %] 600))
|
||||
:accessibility-label :recipient-address-input}]]
|
||||
[react/view {:align-items :center :height 30 :padding-bottom 8}
|
||||
(if searching
|
||||
[react/small-loading-indicator]
|
||||
(when resolved-address
|
||||
[quo/text {:style {:margin-horizontal 16}
|
||||
:size :small
|
||||
:align :center
|
||||
:color :secondary}
|
||||
(when-not (ethereum/address? address)
|
||||
(str (stateofus/username-with-domain address) " • "))
|
||||
[quo/text {:monospace true
|
||||
:size :inherit
|
||||
:color :inherit}
|
||||
(utils/get-shortened-address resolved-address)]]))]
|
||||
[accordion search-filter]]]
|
||||
(when @input-focused?
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:left
|
||||
[quo/button
|
||||
{:accessibility-label :participant-add-to-favs
|
||||
:type :secondary
|
||||
:disabled disabled?
|
||||
:on-press #(re-frame/dispatch [:navigate-to :new-favourite])}
|
||||
(i18n/label :t/add-to-favourites)]
|
||||
:right
|
||||
[quo/button
|
||||
{:accessibility-label :participant-done
|
||||
:type :secondary
|
||||
:after :main-icons/next
|
||||
:disabled disabled?
|
||||
:on-press #(re-frame/dispatch [:wallet.send/set-recipient resolved-address])}
|
||||
(i18n/label :t/done)]}])]])))
|
|
@ -50,9 +50,7 @@
|
|||
:icon :main-icons/qr
|
||||
:theme :accent
|
||||
:accessibility-label :chose-recipient-scan-qr
|
||||
:on-press #(re-frame/dispatch [:wallet.send/qr-scanner {:handler :wallet.send/qr-scanner-result
|
||||
:cancel-handler :wallet.send/qr-scanner-cancel
|
||||
:modal-opened? true}])}
|
||||
:on-press #(re-frame/dispatch [:wallet.send/qr-scanner {:handler :wallet.send/qr-scanner-result}])}
|
||||
{:title (i18n/label :t/recipient-code)
|
||||
:icon :main-icons/address
|
||||
:theme :accent
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
(ns status-im.ui.screens.wallet.send.styles
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defn sheet [small-screen?]
|
||||
(defn sheet []
|
||||
{:flex 1})
|
||||
|
||||
(defn acc-sheet []
|
||||
{:background-color colors/white
|
||||
:border-top-right-radius 16
|
||||
:border-top-left-radius 16
|
||||
:padding-bottom (if small-screen? 40 60)})
|
||||
:padding-bottom 60})
|
||||
|
||||
(defn header [small-screen?]
|
||||
{:flex-direction :row
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.money :as money]
|
||||
[quo.core :as quo]
|
||||
[status-im.ethereum.core :as ethereum]))
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
|
||||
[status-im.ui.components.topbar :as topbar]))
|
||||
|
||||
(defn header [{:keys [label small-screen?]}]
|
||||
[react/view (styles/header small-screen?)
|
||||
|
@ -69,23 +71,26 @@
|
|||
(defn render-contact [contact from-chat?]
|
||||
(if from-chat?
|
||||
[quo/list-item {:title (multiaccounts/displayed-name contact)
|
||||
:subtitle (:address contact)
|
||||
:subtitle [quo/text {:monospace true
|
||||
:color :secondary}
|
||||
(utils/get-shortened-checksum-address (:address contact))]
|
||||
:icon [chat-icon/contact-icon-contacts-tab
|
||||
(multiaccounts/displayed-photo contact)]}]
|
||||
[quo/list-item
|
||||
{:title (if-not contact
|
||||
(i18n/label :t/wallet-choose-recipient)
|
||||
[quo/text {:size :large
|
||||
:monospace true}
|
||||
(utils/get-shortened-checksum-address
|
||||
(if (string? contact) contact (:address contact)))])
|
||||
:accessibility-label :choose-recipient-button
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:dismiss-keyboard])
|
||||
(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||
{:content sheets/choose-recipient
|
||||
:content-height 200}]))
|
||||
:chevron true}]))
|
||||
(merge {:title (if-not contact
|
||||
(i18n/label :t/wallet-choose-recipient)
|
||||
[quo/text {:size :large
|
||||
:monospace true}
|
||||
(utils/get-shortened-checksum-address
|
||||
(if (string? contact) contact (:address contact)))])
|
||||
:accessibility-label :choose-recipient-button
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:dismiss-keyboard])
|
||||
(re-frame/dispatch [:wallet.send/navigate-to-recipient-code]))
|
||||
:chevron true}
|
||||
(when-not contact
|
||||
{:icon :main-icons/add
|
||||
:theme :accent}))]))
|
||||
|
||||
(defn set-max [token]
|
||||
[react/touchable-highlight
|
||||
|
@ -102,140 +107,12 @@
|
|||
[react/text {:style {:color colors/gray :margin-left 16 :margin-bottom 8
|
||||
:font-size 15 :line-height 22}}
|
||||
(str (i18n/format-currency (* amount price) (:code wallet-currency)) " " (:code wallet-currency))])))
|
||||
(views/defview sheet [_]
|
||||
(views/letsubs [{:keys [amount-error amount-text
|
||||
request?
|
||||
from token to sign-enabled? from-chat?]
|
||||
:as tx}
|
||||
[:wallet.send/prepare-transaction-with-balance]
|
||||
prices [:prices]
|
||||
wallet-currency [:wallet/currency]
|
||||
window-height [:dimensions/window-height]
|
||||
window-width [:dimensions/window-width]
|
||||
keyboard-height [:keyboard-height]]
|
||||
(let [small-screen? (< (- window-height keyboard-height) 450)
|
||||
to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))]
|
||||
[react/view {:style (styles/sheet small-screen?)}
|
||||
[react/view {:flex-direction :row :padding-horizontal 16 :align-items :center
|
||||
:margin-top 12 :margin-bottom 4}
|
||||
[react/text-input
|
||||
{:style {:font-size (if small-screen? 24 38)
|
||||
:max-width (- (* (/ window-width 4) 3) 106)
|
||||
:color (if amount-error colors/red colors/black)}
|
||||
:keyboard-type :decimal-pad
|
||||
:auto-capitalize :words
|
||||
:accessibility-label :amount-input
|
||||
:default-value amount-text
|
||||
:editable (not request?)
|
||||
:auto-focus true
|
||||
:on-change-text #(re-frame/dispatch [:wallet.send/set-amount-text %])
|
||||
:placeholder "0.0 "}]
|
||||
[asset-selector tx window-width]
|
||||
(when amount-error
|
||||
[tooltip/tooltip (if from
|
||||
amount-error
|
||||
(i18n/label :t/select-account-first))
|
||||
{:bottom-value 2
|
||||
:font-size 12}])]
|
||||
[fiat-value amount-text token prices wallet-currency]
|
||||
(when-not (or request? from-chat?)
|
||||
[set-max token])
|
||||
[components/separator]
|
||||
(when-not small-screen?
|
||||
[quo/list-header (i18n/label :t/from)])
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
(when small-screen?
|
||||
[react/i18n-text {:style {:width 50 :text-align :right :color colors/gray} :key :t/from}])
|
||||
[react/view {:flex 1}
|
||||
[render-account from token :wallet.send/set-field]]]
|
||||
(when-not small-screen?
|
||||
[quo/list-header
|
||||
(i18n/label :t/to)])
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
(when small-screen?
|
||||
[react/i18n-text {:style {:width 50 :text-align :right :color colors/gray} :key :t/to}])
|
||||
[react/view {:flex 1}
|
||||
[render-contact to from-chat?]]]
|
||||
[toolbar/toolbar
|
||||
{:left
|
||||
[quo/button
|
||||
{:type :secondary
|
||||
:on-press #(re-frame/dispatch [:wallet/cancel-transaction-command])}
|
||||
(i18n/label :t/cancel)]
|
||||
:right
|
||||
[quo/button
|
||||
{:accessibility-label :send-transaction-bottom-sheet
|
||||
:disabled (not sign-enabled?)
|
||||
:on-press #(re-frame/dispatch
|
||||
[(cond
|
||||
request?
|
||||
:wallet.ui/sign-transaction-button-clicked-from-request
|
||||
from-chat?
|
||||
:wallet.ui/sign-transaction-button-clicked-from-chat
|
||||
:else
|
||||
:wallet.ui/sign-transaction-button-clicked) tx])}
|
||||
(if (and (not request?) from-chat? (not to-norm))
|
||||
(i18n/label :t/wallet-send)
|
||||
(i18n/label :t/next))]}]])))
|
||||
(views/defview request-sheet [_]
|
||||
(views/letsubs [{:keys [amount-error amount-text from token sign-enabled?] :as tx}
|
||||
[:wallet.request/prepare-transaction-with-balance]
|
||||
window-height [:dimensions/window-height]
|
||||
window-width [:dimensions/window-width]
|
||||
prices [:prices]
|
||||
wallet-currency [:wallet/currency]
|
||||
keyboard-height [:keyboard-height]]
|
||||
(let [small-screen? (< (- window-height keyboard-height) 450)]
|
||||
[react/view {:style (styles/sheet small-screen?)}
|
||||
[header {:small-screen? small-screen?
|
||||
:label :t/request-transaction}]
|
||||
[react/view {:flex-direction :row :padding-horizontal 24 :align-items :center
|
||||
:margin-vertical (if small-screen? 8 16)}
|
||||
[react/text-input
|
||||
{:style {:font-size (if small-screen? 24 38)
|
||||
:color (when amount-error colors/red)
|
||||
:flex-shrink 1}
|
||||
:keyboard-type :decimal-pad
|
||||
:auto-capitalize :words
|
||||
:accessibility-label :amount-input
|
||||
:default-value amount-text
|
||||
:auto-focus true
|
||||
:on-change-text #(re-frame/dispatch [:wallet.request/set-amount-text %])
|
||||
:placeholder "0.0 "}]
|
||||
[asset-selector tx window-width]
|
||||
(when amount-error
|
||||
[tooltip/tooltip amount-error {:bottom-value 2
|
||||
:font-size 12}])]
|
||||
[fiat-value amount-text token prices wallet-currency]
|
||||
[components/separator]
|
||||
(when-not small-screen?
|
||||
[quo/list-header
|
||||
(i18n/label :t/to)])
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
(when small-screen?
|
||||
[react/i18n-text {:style {:width 50 :text-align :right :color colors/gray} :key :t/to}])
|
||||
[react/view {:flex 1}
|
||||
[render-account from token :wallet.request/set-field]]]
|
||||
[toolbar/toolbar
|
||||
{:left
|
||||
[react/view {:padding-horizontal 8}
|
||||
[quo/button
|
||||
{:type :secondary
|
||||
:on-press #(re-frame/dispatch [:wallet/cancel-transaction-command])}
|
||||
(i18n/label :t/cancel)]]
|
||||
:right
|
||||
[quo/button
|
||||
{:accessibility-label :request-transaction-bottom-sheet
|
||||
:disabled (not sign-enabled?)
|
||||
:on-press #(re-frame/dispatch
|
||||
[:wallet.ui/request-transaction-button-clicked tx])}
|
||||
(i18n/label :t/wallet-request)]}]])))
|
||||
|
||||
(views/defview select-account-sheet [{:keys [from message]}]
|
||||
(views/letsubs [window-height [:dimensions/window-height]
|
||||
keyboard-height [:keyboard-height]]
|
||||
(let [small-screen? (< (- window-height keyboard-height) 450)]
|
||||
[react/view {:style (styles/sheet small-screen?)}
|
||||
[react/view {:style (styles/acc-sheet)}
|
||||
[header {:small-screen? small-screen?
|
||||
:label :t/select-account}]
|
||||
[react/view {:flex-direction :row :padding-horizontal 24 :align-items :center
|
||||
|
@ -265,32 +142,144 @@
|
|||
(:address from)])}
|
||||
(i18n/label :t/share)]}]])))
|
||||
|
||||
(defview prepare-transaction []
|
||||
(letsubs [tx [:wallet/prepare-transaction]]
|
||||
[bottom-panel/animated-bottom-panel
|
||||
;;we use select-keys here because we don't want to update view if other keys in map are changed
|
||||
;; and because modal screen (qr code scanner) can't be opened over bottom sheet we have to use :modal-opened?
|
||||
;; to hide our transaction panel
|
||||
(when (and tx
|
||||
(not (:modal-opened? tx))
|
||||
(not (:request-command? tx)))
|
||||
(select-keys tx [:from-chat?]))
|
||||
sheet]))
|
||||
|
||||
(defview request-transaction []
|
||||
(letsubs [tx [:wallet/prepare-transaction]]
|
||||
[bottom-panel/animated-bottom-panel
|
||||
;;we use select-keys here because we don't want to update view if other keys in map are changed
|
||||
;; and because modal screen (qr code scanner) can't be opened over bottom sheet we have to use :modal-opened?
|
||||
;; to hide our transaction panel
|
||||
(when (and tx
|
||||
(not (:modal-opened? tx))
|
||||
(:request-command? tx))
|
||||
(select-keys tx [:from-chat? :request?]))
|
||||
request-sheet]))
|
||||
|
||||
(defview select-account []
|
||||
(letsubs [data [:commands/select-account]]
|
||||
[bottom-panel/animated-bottom-panel
|
||||
data
|
||||
select-account-sheet]))
|
||||
|
||||
(views/defview request-transaction [_]
|
||||
(views/letsubs [{:keys [amount-error amount-text from token sign-enabled?] :as tx}
|
||||
[:wallet.request/prepare-transaction-with-balance]
|
||||
window-width [:dimensions/window-width]
|
||||
prices [:prices]
|
||||
wallet-currency [:wallet/currency]]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[react/view {:flex 1}
|
||||
[topbar/topbar
|
||||
{:navigation {:on-press
|
||||
#(do
|
||||
(re-frame/dispatch [:wallet/cancel-transaction-command])
|
||||
(re-frame/dispatch [:navigate-back]))}
|
||||
:modal? true
|
||||
:border-bottom true
|
||||
:title (i18n/label :t/request-transaction)}]
|
||||
[react/scroll-view {:style {:flex 1}
|
||||
:keyboard-should-persist-taps :handled}
|
||||
[react/view {:style (styles/sheet)}
|
||||
[react/view {:flex-direction :row :padding-horizontal 24 :align-items :center
|
||||
:margin-vertical 16}
|
||||
[react/text-input
|
||||
{:style {:font-size 38
|
||||
:color (when amount-error colors/red)
|
||||
:flex-shrink 1}
|
||||
:keyboard-type :decimal-pad
|
||||
:auto-capitalize :words
|
||||
:accessibility-label :amount-input
|
||||
:default-value amount-text
|
||||
:auto-focus true
|
||||
:on-change-text #(re-frame/dispatch [:wallet.request/set-amount-text %])
|
||||
:placeholder "0.0 "}]
|
||||
[asset-selector tx window-width]
|
||||
(when amount-error
|
||||
[tooltip/tooltip amount-error {:bottom-value 2
|
||||
:font-size 12}])]
|
||||
[fiat-value amount-text token prices wallet-currency]
|
||||
[components/separator]
|
||||
[quo/list-header
|
||||
(i18n/label :t/to)]
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
[react/view {:flex 1}
|
||||
[render-account from token :wallet.request/set-field]]]]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:right
|
||||
[quo/button
|
||||
{:type :secondary
|
||||
:after :main-icon/next
|
||||
:accessibility-label :request-transaction-bottom-sheet
|
||||
:disabled (not sign-enabled?)
|
||||
:on-press #(do
|
||||
(re-frame/dispatch
|
||||
[:wallet.ui/request-transaction-button-clicked tx])
|
||||
(re-frame/dispatch [:navigate-back]))}
|
||||
(i18n/label :t/wallet-request)]}]]]))
|
||||
|
||||
(views/defview prepare-send-transaction [_]
|
||||
(views/letsubs [{:keys [amount-error amount-text
|
||||
request?
|
||||
from token to sign-enabled? from-chat?]
|
||||
:as tx}
|
||||
[:wallet.send/prepare-transaction-with-balance]
|
||||
prices [:prices]
|
||||
wallet-currency [:wallet/currency]
|
||||
window-width [:dimensions/window-width]]
|
||||
(let [to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[react/view {:flex 1}
|
||||
[topbar/topbar
|
||||
{:navigation {:on-press
|
||||
#(do
|
||||
(re-frame/dispatch [:wallet/cancel-transaction-command])
|
||||
(re-frame/dispatch [:navigate-back]))}
|
||||
:modal? true
|
||||
:border-bottom true
|
||||
:title (i18n/label :t/send-transaction)}]
|
||||
[react/scroll-view {:style {:flex 1}
|
||||
:keyboard-should-persist-taps :handled}
|
||||
[react/view {:style (styles/sheet)}
|
||||
[react/view {:flex-direction :row :padding-horizontal 16 :align-items :center
|
||||
:margin-top 12 :margin-bottom 4}
|
||||
[react/text-input
|
||||
{:style {:font-size 38
|
||||
:max-width (- (* (/ window-width 4) 3) 106)
|
||||
:color (if amount-error colors/red colors/black)}
|
||||
:keyboard-type :decimal-pad
|
||||
:auto-capitalize :words
|
||||
:accessibility-label :amount-input
|
||||
:default-value amount-text
|
||||
:editable (not request?)
|
||||
:auto-focus true
|
||||
:on-change-text #(re-frame/dispatch [:wallet.send/set-amount-text %])
|
||||
:placeholder "0.0 "}]
|
||||
[asset-selector tx window-width]
|
||||
(when amount-error
|
||||
[tooltip/tooltip (if from
|
||||
amount-error
|
||||
(i18n/label :t/select-account-first))
|
||||
{:bottom-value 2
|
||||
:font-size 12}])]
|
||||
[fiat-value amount-text token prices wallet-currency]
|
||||
(when-not (or request? from-chat?)
|
||||
[set-max token])
|
||||
[components/separator]
|
||||
[quo/list-header (i18n/label :t/from)]
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
[react/view {:flex 1}
|
||||
[render-account from token :wallet.send/set-field]]]
|
||||
[quo/list-header
|
||||
(i18n/label :t/to)]
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
[react/view {:flex 1}
|
||||
[render-contact to from-chat?]]]]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:right
|
||||
[quo/button
|
||||
{:accessibility-label :send-transaction-bottom-sheet
|
||||
:type :secondary
|
||||
:after :main-icon/next
|
||||
:disabled (not sign-enabled?)
|
||||
:on-press #(do
|
||||
(re-frame/dispatch
|
||||
[(cond
|
||||
request?
|
||||
:wallet.ui/sign-transaction-button-clicked-from-request
|
||||
from-chat?
|
||||
:wallet.ui/sign-transaction-button-clicked-from-chat
|
||||
:else
|
||||
:wallet.ui/sign-transaction-button-clicked) tx])
|
||||
(re-frame/dispatch [:navigate-back]))}
|
||||
(if (and (not request?) from-chat? (not to-norm))
|
||||
(i18n/label :t/wallet-send)
|
||||
(i18n/label :t/next))]}]]])))
|
|
@ -2,7 +2,6 @@
|
|||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ethereum.eip681 :as eip681]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.i18n :as i18n]
|
||||
|
@ -11,9 +10,7 @@
|
|||
[status-im.router.core :as router]
|
||||
[status-im.qr-scanner.core :as qr-scaner]
|
||||
[status-im.ui.components.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.navigation :as navigation]
|
||||
[clojure.string :as string]
|
||||
[status-im.ethereum.stateofus :as stateofus]))
|
||||
[status-im.navigation :as navigation]))
|
||||
|
||||
;; FIXME(Ferossgp): Should be part of QR scanner not wallet
|
||||
(fx/defn toggle-flashlight
|
||||
|
@ -30,10 +27,14 @@
|
|||
(assoc-in fx [:db :wallet :send-transaction :gas]
|
||||
ethereum/default-transaction-gas))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-address
|
||||
(fn [{:keys [registry ens-name cb]}]
|
||||
(ens/get-addr registry ens-name cb)))
|
||||
(fx/defn set-recipient
|
||||
{:events [:wallet.send/set-recipient]}
|
||||
[{:keys [db]} address]
|
||||
{:db (-> db
|
||||
(dissoc :wallet/recipient)
|
||||
(assoc-in [:ui/search :recipient-filter] nil)
|
||||
(assoc-in [:wallet/prepare-transaction :to] address))
|
||||
:dispatch [:navigate-back]})
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-addresses
|
||||
|
@ -50,29 +51,6 @@
|
|||
(.catch (fn [error]
|
||||
(js/console.log error))))))
|
||||
|
||||
(fx/defn set-recipient
|
||||
{:events [:wallet.send/set-recipient ::recipient-address-resolved]}
|
||||
[{:keys [db]} raw-recipient]
|
||||
(let [chain (ethereum/chain-keyword db)
|
||||
recipient (when raw-recipient (string/trim raw-recipient))]
|
||||
(cond
|
||||
(ethereum/address? recipient)
|
||||
(let [checksum (eip55/address->checksum recipient)]
|
||||
(if (eip55/valid-address-checksum? checksum)
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet/prepare-transaction :to] checksum)
|
||||
(assoc-in [:wallet/prepare-transaction :modal-opened?] false))
|
||||
:dispatch [:navigate-back]}
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address-checksum {:data recipient})}))
|
||||
(not (string/blank? recipient))
|
||||
{::resolve-address {:registry (get ens/ens-registries chain)
|
||||
:ens-name (if (= (.indexOf ^js recipient ".") -1)
|
||||
(stateofus/subdomain recipient)
|
||||
recipient)
|
||||
:cb #(re-frame/dispatch [::recipient-address-resolved %])}}
|
||||
:else
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address {:data recipient})})))
|
||||
|
||||
(defn- fill-prepare-transaction-details
|
||||
[db
|
||||
{:keys [address name value symbol gas gasPrice gasLimit]
|
||||
|
@ -101,30 +79,29 @@
|
|||
(let [{:keys [address] :as details}
|
||||
(eip681/extract-request-details data all-tokens)]
|
||||
(if address
|
||||
(if (:wallet/prepare-transaction db)
|
||||
{:db (update db :wallet/prepare-transaction assoc
|
||||
:to address :to-name (find-address-name db address))}
|
||||
(let [current-chain-id (get-in networks [current-network :config :NetworkId])]
|
||||
(merge {:db (fill-prepare-transaction-details db details all-tokens)}
|
||||
(when (and chain-id (not= current-chain-id chain-id))
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-chain-id
|
||||
{:data uri :chain current-chain-id})}))))
|
||||
(if (:wallet/recipient db)
|
||||
{:db (update db :wallet/recipient assoc :resolved-address address
|
||||
:address address)
|
||||
;;android
|
||||
:dispatch-later [{:ms 1000 :dispatch [:wallet.recipient/focus-input]}]}
|
||||
(if (:wallet/prepare-transaction db)
|
||||
{:db (update db :wallet/prepare-transaction assoc
|
||||
:to address :to-name (find-address-name db address))}
|
||||
(let [current-chain-id (get-in networks [current-network :config :NetworkId])]
|
||||
(merge {:db (fill-prepare-transaction-details db details all-tokens)
|
||||
:dispatch [:navigate-to :prepare-send-transaction]}
|
||||
(when (and chain-id (not= current-chain-id chain-id))
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-chain-id
|
||||
{:data uri :chain current-chain-id})})))))
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})})))
|
||||
|
||||
(fx/defn qr-scanner-allowed
|
||||
{:events [:wallet.send/qr-scanner]}
|
||||
[{:keys [db] :as cofx} options]
|
||||
(fx/merge cofx
|
||||
(when (:modal-opened? options)
|
||||
{:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] true)})
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(qr-scaner/scan-qr-code options)))
|
||||
|
||||
(fx/defn qr-scanner-cancel
|
||||
{:events [:wallet.send/qr-scanner-cancel]}
|
||||
[{db :db} _]
|
||||
{:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] false)})
|
||||
|
||||
(fx/defn parse-eip681-uri-and-resolve-ens
|
||||
{:events [:wallet/parse-eip681-uri-and-resolve-ens]}
|
||||
[{db :db :as cofx} {:keys [message uri paths ens-names error]}]
|
||||
|
@ -154,7 +131,4 @@
|
|||
[cofx data _]
|
||||
(fx/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(parse-eip681-uri-and-resolve-ens (router/match-eip681 data))
|
||||
(fn [{:keys [db]}]
|
||||
(when (get-in db [:wallet/prepare-transaction :modal-opened?])
|
||||
{:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] false)}))))
|
||||
(parse-eip681-uri-and-resolve-ens (router/match-eip681 data))))
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
[status-im.wallet.prices :as prices]
|
||||
[status-im.wallet.utils :as wallet.utils]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.ui.screens.mobile-network-settings.utils :as mobile-network-utils]))
|
||||
[status-im.ui.screens.mobile-network-settings.utils :as mobile-network-utils]
|
||||
status-im.wallet.recipient.core))
|
||||
|
||||
(defn get-balance
|
||||
[{:keys [address on-success on-error]}]
|
||||
|
@ -208,6 +209,13 @@
|
|||
(when config/erc20-contract-warnings-enabled?
|
||||
{:wallet/validate-tokens [default-tokens all-default-tokens]}))))
|
||||
|
||||
(fx/defn initialize-favourites
|
||||
[{:keys [db]} favourites]
|
||||
{:db (assoc db :wallet/favourites (reduce (fn [acc {:keys [address] :as favourit}]
|
||||
(assoc acc address favourit))
|
||||
{}
|
||||
favourites))})
|
||||
|
||||
(fx/defn update-balances
|
||||
[{{:keys [network-status :wallet/all-tokens
|
||||
multiaccount :multiaccount/accounts] :as db} :db
|
||||
|
@ -419,7 +427,8 @@
|
|||
:symbol symbol
|
||||
:amount-text amount-text
|
||||
:request? true
|
||||
:from-chat? true})}))
|
||||
:from-chat? true})
|
||||
:dispatch [:navigate-to :prepare-send-transaction]}))
|
||||
|
||||
(fx/defn sign-transaction-button-clicked-from-request
|
||||
{:events [:wallet.ui/sign-transaction-button-clicked-from-request]}
|
||||
|
@ -513,7 +522,8 @@
|
|||
(:multiaccount/accounts db))
|
||||
:to contact
|
||||
:symbol :ETH
|
||||
:from-chat? true})}
|
||||
:from-chat? true})
|
||||
:dispatch [:navigate-to :prepare-send-transaction]}
|
||||
ens-verified
|
||||
(assoc ::resolve-address
|
||||
{:registry (get ens/ens-registries chain)
|
||||
|
@ -535,7 +545,8 @@
|
|||
contact.db/enrich-contact))
|
||||
:symbol :ETH
|
||||
:from-chat? true
|
||||
:request-command? true})}))
|
||||
:request-command? true})
|
||||
:dispatch [:navigate-to :request-transaction]}))
|
||||
|
||||
(fx/defn prepare-transaction-from-wallet
|
||||
{:events [:wallet/prepare-transaction-from-wallet]}
|
||||
|
@ -545,6 +556,7 @@
|
|||
:to nil
|
||||
:symbol :ETH
|
||||
:from-chat? false})
|
||||
:dispatch [:navigate-to :prepare-send-transaction]
|
||||
:signing/update-gas-price {:success-event :wallet.send/update-gas-price-success}})
|
||||
|
||||
(fx/defn cancel-transaction-command
|
||||
|
@ -595,9 +607,10 @@
|
|||
{:events [:wallet.send/navigate-to-recipient-code]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] true)}
|
||||
{:db (-> db
|
||||
(assoc :wallet/recipient {}))}
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(navigation/navigate-to-cofx :contact-code nil)))
|
||||
(navigation/navigate-to-cofx :recipient nil)))
|
||||
|
||||
(fx/defn show-delete-account-confirmation
|
||||
{:events [:wallet.settings/show-delete-account-confirmation]}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
(ns status-im.wallet.recipient.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.react :as react]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.navigation :as navigation]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]))
|
||||
|
||||
;;NOTE we want to handle only last resolve
|
||||
(def resolve-last-id (atom nil))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-address
|
||||
(fn [{:keys [registry ens-name cb]}]
|
||||
(ens/get-addr registry ens-name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet.recipient/address-paste
|
||||
(fn [inp-ref]
|
||||
(react/get-from-clipboard
|
||||
#(do
|
||||
(when inp-ref (.focus inp-ref))
|
||||
(re-frame/dispatch [:wallet.recipient/address-changed (string/trim %)])))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet.recipient/address-paste
|
||||
(fn [inp-ref]
|
||||
(react/get-from-clipboard
|
||||
#(do
|
||||
(when inp-ref (.focus inp-ref))
|
||||
(re-frame/dispatch [:wallet.recipient/address-changed (string/trim %)])))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::focus-input
|
||||
(fn [inp-ref]
|
||||
(when inp-ref
|
||||
(.focus inp-ref))))
|
||||
|
||||
(fx/defn focus-input
|
||||
{:events [:wallet.recipient/focus-input]}
|
||||
[{:keys [db]}]
|
||||
{::focus-input (get-in db [:wallet/recipient :inp-ref])})
|
||||
|
||||
(fx/defn address-paste-pressed
|
||||
{:events [:wallet.recipient/address-paste-pressed]}
|
||||
[{:keys [db]}]
|
||||
{:wallet.recipient/address-paste (get-in db [:wallet/recipient :inp-ref])})
|
||||
|
||||
(fx/defn set-recipient
|
||||
{:events [::recipient-address-resolved]}
|
||||
[{:keys [db]} raw-recipient id]
|
||||
(when (or (not id) (= id @resolve-last-id))
|
||||
(reset! resolve-last-id nil)
|
||||
(let [chain (ethereum/chain-keyword db)
|
||||
recipient (utils/safe-trim raw-recipient)]
|
||||
(cond
|
||||
(ethereum/address? recipient)
|
||||
(let [checksum (eip55/address->checksum recipient)]
|
||||
(if (eip55/valid-address-checksum? checksum)
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet/recipient :searching] false)
|
||||
(assoc-in [:wallet/recipient :resolved-address] checksum))}
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address-checksum {:data recipient})
|
||||
:db (assoc-in db [:wallet/recipient :searching] false)}))
|
||||
(and (not (string/blank? recipient)) (ens/valid-eth-name-prefix? recipient))
|
||||
(let [ens-name (if (= (.indexOf ^js recipient ".") -1)
|
||||
(stateofus/subdomain recipient)
|
||||
recipient)]
|
||||
(if (ens/is-valid-eth-name? ens-name)
|
||||
(do
|
||||
(reset! resolve-last-id (random/id))
|
||||
{::resolve-address
|
||||
{:registry (get ens/ens-registries chain)
|
||||
:ens-name ens-name
|
||||
:cb #(re-frame/dispatch [::recipient-address-resolved % @resolve-last-id])}})
|
||||
{:db (assoc-in db [:wallet/recipient :searching] false)}))
|
||||
:else
|
||||
{:db (assoc-in db [:wallet/recipient :searching] false)}))))
|
||||
|
||||
(fx/defn address-changed
|
||||
{:events [:wallet.recipient/address-changed]}
|
||||
[{:keys [db] :as cofx} new-identity]
|
||||
(fx/merge cofx
|
||||
{:db (update db :wallet/recipient assoc :address new-identity :resolved-address nil
|
||||
:searching true)}
|
||||
(set-recipient new-identity nil)))
|
||||
|
||||
(fx/defn recipient-modal-closed
|
||||
{:events [:wallet/recipient-modal-closed]}
|
||||
[{:keys [db]}]
|
||||
{:db (dissoc db :wallet/recipient)})
|
||||
|
||||
(fx/defn add-favourite
|
||||
{:events [:wallet/add-favourite]}
|
||||
[{:keys [db] :as cofx} address name]
|
||||
(let [new-favourite {:address address
|
||||
:name (or name "")}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:wallet/favourites address] new-favourite)
|
||||
::focus-input (get-in db [:wallet/recipient :inp-ref])
|
||||
::json-rpc/call [{:method "wallet_addFavourite"
|
||||
:params [new-favourite]
|
||||
:on-success #()}]}
|
||||
(navigation/navigate-back))))
|
|
@ -2,7 +2,7 @@
|
|||
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.62.1",
|
||||
"commit-sha1": "36e742cb70fb7372e0d57ba391523613f6ed87d5",
|
||||
"src-sha256": "06639pfr782zpp7ysaz4ljlsp87pswdnwlq0j15v7z75xfg4yz6p"
|
||||
"version": "v0.62.2",
|
||||
"commit-sha1": "682722b9734cef6f3c6832575d78c6996988a379",
|
||||
"src-sha256": "0ry6l6f154j7d8zp4dw5gs5pwygmjr61hxnpj0yr32h7i6zdna88"
|
||||
}
|
||||
|
|
|
@ -1263,5 +1263,15 @@
|
|||
"membership-description": "Group membership requires you to be accepted by the group admin",
|
||||
"group-membership-request": "Group membership request",
|
||||
"members-limit-reached": "Members limit reached",
|
||||
"favourites": "Favourites",
|
||||
"new-favourite": "New favourite",
|
||||
"add-to-favourites": "Add to favourites",
|
||||
"favourites-empty": "Addresses added to favourites will appear here",
|
||||
"contacts-empty": "Contacts with ENS names will appear here",
|
||||
"my-accounts": "My accounts",
|
||||
"my-accounts-empty": "Your available accounts will appear here",
|
||||
"recent-empty": "Recently used addresses will appear here",
|
||||
"address-or-ens-name": "Address or ENS name",
|
||||
"name-optional": "Name (optional)",
|
||||
"mute": "Mute"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue